<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>nFriedly Web Dev Tech Blog &#187; howto</title>
	<atom:link href="http://nfriedly.com/techblog/tag/howto/feed/" rel="self" type="application/rss+xml" />
	<link>http://nfriedly.com/techblog</link>
	<description>Expert Advice on Website Development, Javascript, Ajax, and Security</description>
	<lastBuildDate>Wed, 16 May 2012 23:48:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>How to make Apache Ant tasks run in a default directory</title>
		<link>http://nfriedly.com/techblog/2012/02/how-to-make-ant-tasks-run-in-a-default-directory/</link>
		<comments>http://nfriedly.com/techblog/2012/02/how-to-make-ant-tasks-run-in-a-default-directory/#comments</comments>
		<pubDate>Wed, 29 Feb 2012 20:14:31 +0000</pubDate>
		<dc:creator>nFriedly</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[ant]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[productivity]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://nfriedly.com/techblog/?p=422</guid>
		<description><![CDATA[I often open a new tab in my Terminal to run an Ant task in, and often as not I forget to CD into the correct directory first and so I am greeted with this error: Nathan-Mac:~ nathan$ ant database.start Buildfile: build.xml does not exist! Build failed On my system, there&#8217;s only one main project [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/soldiersmediacenter/6668518895/" title="The other Apache, image courtesy of The U.S. Army"><img src="http://farm8.staticflickr.com/7020/6668518895_0700a12958_m.jpg" width="240" height="160" alt="Apache takeoff" class="right"></a>I often open a new tab in my Terminal to run an <a href="http://ant.apache.org/">Ant</a> task in, and often as not I forget to CD into the correct directory first and so I am greeted with this error:</p>
<p><code>Nathan-Mac:~ nathan$ ant database.start<br />
Buildfile: build.xml does not exist!<br />
Build failed</code></p>
<p>On my system, there&#8217;s only one main project that uses ant, so I almost always intend for ant tasks to be run against that project&#8217;s build.xml. So, I created a function that makes ant tasks &#8220;just work&#8221; no matter what directory I am in.</p>
<p><span id="more-422"></span></p>
<h3>The code</h3>
<p>First you&#8217;ll need to edit your <code>.profile</code> file. To do so, run the following command:</p>
<p><code>nano ~/.profile</code></p>
<p>Then copy-paste in this code, changing the <code>DEFAULT_ANT_DIR</code> to the path to your project (whatever folder has the build.xml file in it):</p>
<pre><code># make ant commands run in the default directory if
# there is no build.xml in the current directory

export DEFAULT_ANT_DIR = /path/to/your/projects/folder/

function magic-ant() {
  if [ -e ./build.xml ]
    then
      ant $@
    else
      pushd DEFAULT_ANT_DIR
      ant $@
      popd
  fi
}

# reset ant to avoid loops if you ever run `source ~/.profile` again
alias ant=`which ant`

alias ant="magic-ant"</code></pre>
<p>Press <code>[Control]-O</code> then <code>[Enter]</code> to save and <code>[Control]-X</code> to exit nano.</p>
<p>Lastly, run this command to import your changes (or just close and reopen your terminal):</p>
<p><code>source ~/.profile</code></p>
<h3>How it works</h3>
<p>First, we define the path in a shell variable with the path to the default ant project. This isn&#8217;t absolutely required, but it keeps things tidy and simple.</p>
<p><a href="http://www.flickr.com/photos/dasqfamily/235488979/" title="Ant by Qfamily, on Flickr"><img src="http://farm1.staticflickr.com/95/235488979_24ead7f4dc_m.jpg" width="240" height="159" alt="Ant" class="left"></a>Next, we create the <code>magic-ant</code> function which checks if there is a build.xml file in the current directory. If so, it uses that one, otherwise it calls <code>pushd</code> to temporarily change directories to our default one, runs the ant command, and then calls <code>popd</code> to get back to whatever directory you started in. <code>$@</code> is an automatic variable that includes whatever parameters this function was called with.</p>
<p>After that we use alias to reset the ant command in order to avoid endless loops where our magic-ant function calls itself instead of the real ant if you source. The command <code>which</code> returns the path to the program with the given name. Putting it in backticks (`) makes bash execute the command and return the result.</p>
<p>Finally we alias <code>ant</code> to point to our new <code>magic-ant</code> function when run from the command line.</p>
<p>The only downside is that I haven&#8217;t yet figured out how to make <a href="http://matthew.mceachen.us/blog/ant-bash-completion-on-mac-os-x-43.html">Ant task tab completion</a> work with this when you&#8217;re not in the project directory.</p>
]]></content:encoded>
			<wfw:commentRss>http://nfriedly.com/techblog/2012/02/how-to-make-ant-tasks-run-in-a-default-directory/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to get your apps ready for Facebook&#8217;s OAuth 2.0 upgrade</title>
		<link>http://nfriedly.com/techblog/2011/09/javascript-changes-for-facebooks-oauth-2-0-upgrade/</link>
		<comments>http://nfriedly.com/techblog/2011/09/javascript-changes-for-facebooks-oauth-2-0-upgrade/#comments</comments>
		<pubDate>Fri, 16 Sep 2011 20:44:35 +0000</pubDate>
		<dc:creator>nFriedly</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[oauth2.0]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://nfriedly.com/techblog/?p=394</guid>
		<description><![CDATA[I just finished a writeup on the necessary JS changes to support Facebook&#8217;s OAuth 2.0 upgrade, and then Hilary did a followup post on the server-side. The upgrade enabled right now, but it gets forced out on October 1st. These two posts should give you all you need to know to get your site ready [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" src="http://oauth.net/images/oauth-2-sm.png" alt="" width="124" height="123" style="margin-bottom: 0;"/>I just finished a writeup on the necessary JS changes to support Facebook&#8217;s OAuth 2.0 upgrade, and then Hilary did a followup post on the server-side. </p>
<p>The upgrade enabled right now, but it gets forced out on October 1st. These two posts should give you all you need to know to get your site ready for Facebook&#8217;s upgrade:</p>
<p>Part 1: JavaScript - <a href="http://blog.sociablelabs.com/2011/09/16/javascript-changes-facebook-pauth-2-0-upgrade/">JavaScript changes for Facebook’s OAuth 2.0 upgrade</a></p>
<p>Part 2: PHP / Backend &#8211; <a href="http://blog.sociablelabs.com/2011/09/19/server-side-changes-facebook-oauth-2-0-upgrade/">Server Side changes for Facebook’s OAuth 2.0 upgrade</a></p>
<p>Also worth noting, there&#8217;s a lot of good information on <a href="https://developers.facebook.com/blog/">Facebook&#8217;s Developer Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nfriedly.com/techblog/2011/09/javascript-changes-for-facebooks-oauth-2-0-upgrade/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>How Facebook sets and uses cross-domain cookies</title>
		<link>http://nfriedly.com/techblog/2010/08/how-facebook-sets-and-uses-cross-domain-cookies/</link>
		<comments>http://nfriedly.com/techblog/2010/08/how-facebook-sets-and-uses-cross-domain-cookies/#comments</comments>
		<pubDate>Thu, 26 Aug 2010 16:08:06 +0000</pubDate>
		<dc:creator>nFriedly</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[cross-domain]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://nfriedly.com/techblog/?p=310</guid>
		<description><![CDATA[I&#8217;ve seen a lot of confusion about this lately, so I thought I&#8217;d make a quick writeup to explain how facebook does it. (I&#8217;ll also give a quick tip on how you can do it yourself.) What Facebook Does Facebook is in a unique position compared to many developers looking to set cross domain cookies: [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://nfriedly.com/img/portfolio/facebook.png" alt="" />I&#8217;ve seen a lot of confusion about this lately, so I thought I&#8217;d make a quick writeup to explain how facebook does it. (I&#8217;ll also give a quick tip on how you can do it yourself.)</p>
<h3>What Facebook Does</h3>
<p>Facebook is in a unique position compared to many developers looking to set cross domain cookies: The user visits both facebook.com and the other website. <span id="more-310"></span></p>
<p>Facebook never actually sets cookies cross-domain, they only read cookies cross-domain. They set cookies on facebook.com when the user visits facebook.com and they set cookies on the other  example.com (or any other website) when the user visits example.com.<sup><a href="#note-1">1</a></sup></p>
<p>Doing things this way avoids all of the browser security issues because cookies that were already set when the user visited facebook.com can still be read when example.com loads facebook.com in an iframe. This is worth repeating: <strong>Cookies can be read in an iframe if they were set outside of the iframe</strong>.<sup><a href="#note-2">2</a></sup></p>
<h3>What about when the user is not logged into Facebook?</h3>
<p><strong>(This is how you can do it!)</strong></p>
<p>If the user is not logged into Facebook when trying to use Facebook on example.com, then Facebook opens a popup window &#8211; not an iframe &#8211; to let the user log in.</p>
<p>A popup window has none of the cookie restrictions that iframes get; it can read and set cookies normally.</p>
<h3>What about popup blockers?</h3>
<p>Most popup blockers make a special exception for &#8220;intentional&#8221; popups &#8211; ones that occur as a direct result of a user&#8217;s click. When the user clicks the login button, the blocker allows the popup because the click indicates that the user wanted that popup.</p>
<h3>An alternate method for of cross-domain cookies: flash</h3>
<p>If you&#8217;re looking for a flash-based method of setting cross-domain cookies, or would otherwise like to avoid popups, you may want to check out my previous article, which includes source code: <a href="http://nfriedly.com/techblog/2010/07/swf-for-javascript-cross-domain-flash-cookies/">.swf for JavaScript cross-domain flash cookies</a></p>
<h3>Notes</h3>
<ol>
<li><a name="note-1"></a>Cookies are only set on example.com when using the using <a href="http://developers.facebook.com/docs/reference/javascript/">Facebook&#8217;s JavaScript SDK</a>. When embedding Social plugins directly as an iframe, only facebook.com cookies are used.</li>
<li><a name="note-2"></a>Safari sometimes prevents JavaScript from reading cookies in an iframe even if GET and POST requests to the server have full access to the cookies. Safari has several quirks like this, but generally <a href="http://anantgarg.com/2010/02/18/cross-domain-cookies-in-safari/">behaves better with iframes if the user <em>interacts</em> with it</a>.</li>
</ol>
<h2>Need a more advanced integration than what Facebook Social Plugins provide?</h2>
<p>At <a href="http://sociablelabs.com">Sociable Labs</a>, our Intelligent Social Plugins<sup>TM</sup> increase social sharing by 15x and have shown a ~1% increase in sales. And the best part is that <a href="http://www.sociablelabs.com/product.html">we do all of the hard work for you!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://nfriedly.com/techblog/2010/08/how-facebook-sets-and-uses-cross-domain-cookies/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>How to build a spam-free contact form without captchas</title>
		<link>http://nfriedly.com/techblog/2009/11/how-to-build-a-spam-free-contact-forms-without-captchas/</link>
		<comments>http://nfriedly.com/techblog/2009/11/how-to-build-a-spam-free-contact-forms-without-captchas/#comments</comments>
		<pubDate>Sat, 07 Nov 2009 05:12:53 +0000</pubDate>
		<dc:creator>nFriedly</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[antispam]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[ux]]></category>

		<guid isPermaLink="false">http://nfriedly.com/techblog/?p=23</guid>
		<description><![CDATA[Most anti-spam methods used by websites today are annoying at best. They use impossible-to-read captcha images, or they make users jump through some kind of hoop to get the email address instead of just clicking on it. This can mean lost sales and opportunities for you, because each hurdle turns away more users. This article [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-thumbnail wp-image-39" title="data_security_3" src="http://nfriedly.com/techblog/wp-content/uploads/2009/06/data_security_3-150x150.jpg" alt="data_security_3" width="150" height="150" />Most anti-spam methods used by websites today are annoying at best. They use impossible-to-read captcha images, or they make users jump through some kind of hoop to get the email address instead of just clicking on it. <strong>This can mean lost sales and opportunities for you, because each hurdle turns away more users. </strong></p>
<p>This article looks at how to use some simple HTML, CSS, &amp; Javascript to protect your private information without making your guests jump through hoops.</p>
<p><span id="more-23"></span><br />
<a href="http://nfriedly.com/stuff/spam-free-contact.zip"><img class="alignleft" src="/img/application_put.png" alt="" /> Download a working copy of the contact form discussed here.</a></p>
<h2>The Goal</h2>
<p>I want users to be able to contact me simple and easy, no captchas, no math problems, just a regular contact form, clickable email address, and everything copy-paste-able.</p>
<h2>The Problem</h2>
<p>Spammers love captcha-free forms and clickable email addresses. (And lately, copy-paste-able phone numbers.) I do not want to receive a ton of spam!</p>
<h2>The Solution</h2>
<p>With a little bit of CSS and JavaScript wizardry, we can make a simple, easy-to-use contact page that will block almost all automated contact form spam.</p>
<h3>Part 1: The Contact Form</h3>
<p>We are going to make a standard contact form with one extra feature: an input named &#8220;url&#8221; and a note beside it that says &#8220;Don&#8217;t type anything here!&#8221;</p>
<p>The HTML:</p>
<pre class="brush: xml; title: ; notranslate">&lt;form method=&quot;post&quot; action=&quot;/submit.php&quot;&gt;
&lt;p&gt;Your name:
&lt;br /&gt;&lt;input name=&quot;name&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Your email:
&lt;br /&gt;&lt;input name=&quot;email&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;antispam&quot;&gt;Leave this empty:
&lt;br /&gt;&lt;input name=&quot;url&quot; /&gt;&lt;/p&gt;

&lt;textarea name=&quot;message&quot;&gt;&lt;/textarea&gt;

&lt;input type=&quot;submit&quot; value=&quot;Send&quot; /&gt;
&lt;/form&gt;</pre>
<p>Then we use CSS to hide the input and the note.</p>
<p>The CSS:</p>
<pre class="brush: css; title: ; notranslate">.antispam { display:none;} </pre>
<p>Then we make a rule in the server that says &#8216;if the user typed anything in the &#8220;url&#8221; box, then throw it out.&#8217;</p>
<p>The PHP:</p>
<pre class="brush: php; title: ; notranslate">&lt;?php

// if the url field is empty
if(isset($_POST['url']) &amp;&amp; $_POST['url'] == ''){

	// then send the form to your email
	mail( 'you@yoursite.com', 'Contact Form', print_r($_POST,true) );
}

// otherwise, let the spammer think that they got their message through

?&gt;

&lt;h1&gt;Thanks&lt;/h1&gt;
&lt;p&gt;We'll get back to you as soon as possible&lt;/p&gt;</pre>
<p>A regular person won&#8217;t even see the box normally, and will therefore leave it blank without even thinking about it. If the CSS fails to load, they get a note explaining what to do.</p>
<p>However, when a spam bot looks at this, it sees a good spot to stick whatever spammy url they&#8217;re trying to advertise.</p>
<p>Now the php script on the server can tell who is a spammer and who isn&#8217;t. The regular people get sent to your email, the spammers get ignored!</p>
<h3>Part 2:  Click-able Email Address</h3>
<p>Spammers steal your email address by scanning through the source code of the site and grabbing anything that looks like an email address. So we&#8217;re going to make sure that there is no email address in the source code and instead generate it by JavaScript.</p>
<p>The Javascript:</p>
<pre class="brush: jscript; title: ; notranslate">var first = &quot;yourname&quot;;
var last = &quot;yoursite.com&quot;;</pre>
<p>The HTML:</p>
<pre class="brush: xml; title: ; notranslate">&lt;p&gt;My e-mail address:
&lt;script type=&quot;text/javascript&quot;&gt;
document.write('&lt;a href=&quot;mailto:'+first + '@' + last+'&quot;&gt;'+first + '@' + last+'&lt;\/a&gt;');
&lt;/script&gt;
&lt;noscript&gt;
Please enable javascript or use my &lt;a href=&quot;/contact.php&quot;&gt;contact form&lt;/a&gt;
&lt;/noscript&gt;
&lt;/p&gt;</pre>
<p>A regular user will see a regular email address and things just work. A user who happens to have javascript disabled will see an explanation and an alternative solution. And a spammer won&#8217;t see a thing!</p>
<p>This method can easily be extended to phone numbers and other personal information.</p>
<h2>Advanced version: Prettier message body and a proper <code>From:</code> field</h2>
<p>These were the most commonly requested features, so I added an advanced version that changes the <code>From:</code> field of the email to whatever the user typed in the box, and removes all of the <code>Array</code> brackets from the body of the message:</p>
<pre class="brush: php; title: ; notranslate">&lt;?php

// if the url field is empty
if(isset($_POST['url']) &amp;&amp; $_POST['url'] == ''){

	// put your email address here
	$youremail = 'you@yoursite.com';

	// prepare a &quot;pretty&quot; version of the message
	$body = &quot;This is the form that was just submitted:
	Name:  $_POST[name]
	E-Mail: $_POST[email]
	Message: $_POST[message]&quot;;

	// Use the submitters email if they supplied one
	// (and it isn't trying to hack your form).
	// Otherwise send from your email address.
	if( $_POST['email'] &amp;&amp; !preg_match( &quot;/[\r\n]/&quot;, $_POST['email']) ) {
	  $headers = &quot;From: $_POST[email]&quot;;
	} else {
	  $headers = &quot;From: $youremail&quot;;
	}

	// finally, send the message
	mail($youremail, 'Contact Form', $body, $headers );

}

// otherwise, let the spammer think that they got their message through

?&gt;</pre>
<p>The <code>preg_match()</code> is there to make sure spammers can&#8217;t abuse your server by injecting extra fields (such as CC and BCC) into the header. Take a look at <a href="http://www.thesitewizard.com/php/protect-script-from-email-injection.shtml">http://www.thesitewizard.com/php/protect-script-from-email-injection.shtml</a> for more info.</p>
<p>Be sure to check the comments below for several other variations.</p>
<h2>Complete Examples</h2>
<p><img class="alignleft" src="/img/application_put.png" alt="" /> A complete working copy of everything mentioned in this article, including both the simple and advanced versions, is available for download here: <a href="http://nfriedly.com/stuff/spam-free-contact.zip">http://nfriedly.com/stuff/spam-free-contact.zip</a></p>
<p>For a live demo of all of this and more, see my <a href="http://nfriedly.com/contact">contact page</a>.</p>
<h3>WordPress version</h3>
<p>I found that there is an anti-spam plugin for WordPress that uses similar methods to the ones I describe here: <a href="http://wordpress.org/extend/plugins/nospamnx/">http://wordpress.org/extend/plugins/nospamnx/</a> &#8211; I installed it on this blog and it&#8217;s stopped nearly 30,000 spam comments so far.</p>
<h2>Does your website need help?</h2>
<p>I am an <a href="/webdev">Experienced Web Developer with a sharp eye for security</a>. I can make your site easier to use while at the same time cutting down on level of spam you receive through it.  <a href="/contact">Contact me</a> for more information and a free quote.</p>
]]></content:encoded>
			<wfw:commentRss>http://nfriedly.com/techblog/2009/11/how-to-build-a-spam-free-contact-forms-without-captchas/feed/</wfw:commentRss>
		<slash:comments>50</slash:comments>
		</item>
	</channel>
</rss>

