<?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</title>
	<atom:link href="http://nfriedly.com/techblog/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>Mon, 22 Apr 2013 22:39:42 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Automatically removing spamers from the WordPress Coment Notifier Plugin&#8217;s Database</title>
		<link>http://nfriedly.com/techblog/2013/03/automatically-removing-spamers-from-the-wordpress-coment-notifier-plugins-database/</link>
		<comments>http://nfriedly.com/techblog/2013/03/automatically-removing-spamers-from-the-wordpress-coment-notifier-plugins-database/#comments</comments>
		<pubDate>Fri, 22 Mar 2013 18:07:06 +0000</pubDate>
		<dc:creator>nFriedly</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[antispam]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://nfriedly.com/techblog/?p=512</guid>
		<description><![CDATA[Photo by anda (: There&#8217;s an awesome WordPress plugin called Comment Notifier &#8211; what it does is add that check box at the bottom of the comments section. If you leave it checked when you add a comment, then it will automatically email you with anyone ease&#8217;s comments in the future. However, it has a [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://nfriedly.com/techblog/2013/03/automatically-removing-spamers-from-the-wordpress-coment-notifier-plugins-database/"><img src="https://farm1.staticflickr.com/216/512562593_33dcb600f2_m.jpg" width="240" height="180" alt="Beach" class="right" title="Spam? Not anymore! Now all I do is relax and enjoy :)" /></a> <small class="right" style="clear:right"><a href="https://secure.flickr.com/photos/8438819@N03/512562593/">Photo by  anda (:</a></small> There&#8217;s an awesome <a href="http://wordpress.org/">WordPress</a> plugin called <a href="http://www.satollo.net/plugins/comment-notifier">Comment Notifier</a> &#8211; what it does is add that check box at the bottom of the comments section. If you leave it checked when you add a comment, then it will automatically email you with anyone ease&#8217;s comments in the future.</p>
<p>However, it has a slight problem with spam. When spammers leave comments, my combination of <a href="http://akismet.com/">Akismet</a> and <a href="http://wordpress.org/extend/plugins/nospamnx/">NoSpamNX</a> do a pretty good job of keeping spam comments of of the site, but not before their (usually fake) email gets added to the Comment Notifier database. </p>
<p>Recently, I realized that my server was trying to send out several hundred failing emails any time someone left a comment. I shot a short feature request (and a small donation) to the Comment Notifier plugin&#8217;s author, but then decided that this was one I could take on myself. Here&#8217;s how I did it:</p>
<p><span id="more-512"></span></p>
<h2>Step 1: BACK UP YOUR DATABASE</h2>
<p>I&#8217;m using the <a href="http://hmn.md/backupwordpress/">BackUpWordPress</a> so this happens automatically, but I went and ran an extra backup and downloaded the files to my laptop just to be safe.</p>
<h2>Stem 2: Clean up the old data</h2>
<p>This SQL query deletes every email in the <code>comment_notifier</code> table that doesn&#8217;t have a corresponding comment. (Most likely because the comment was already deleted as spam.)</p>
<pre class="brush: sql; title: ; notranslate">
DELETE FROM `wp_YOUR_PREFIX_comment_notifier`
WHERE email NOT IN (
  SELECT comment_author_email FROM `wp_YOUR_PREFIX_comments`
);
</pre>
<p>Obviously, you&#8217;ll need to change the table name prefix (<code>wp_YOUR_PREFIX_</code>) to whatever your install of WP uses.</p>
<h2>Step 3: Add an <a href="http://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_index">index</a> on the <code>comments.comment_author_email</code> column</h2>
<p>This is required in order to add the Foreign Key constraint in next step. It makes MySQL keep a sorted list of emails in the comments table and automatically update it any time a comment is added or deleted.</p>
<pre class="brush: sql; title: ; notranslate">
ALTER TABLE `wp_YOUR_PREFIX_comments` ADD INDEX ( `comment_author_email` );
</pre>
<h2>Step 4: Add a <a href="http://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_foreign_key">Foreign Key</a> constraint that automatically deletes spammers from the <code>comment_notifier</code> table</h2>
<p>This instructs MySQL to enforce a link between the <code>comment_notifier</code> table and the <code>comments</code> table so that any email address in the <code>comment_notifier</code> table must also be in the comments table, and if it gets deleted from the <code>comments</code> table, then automatically delete it from the <code>comment_notifier</code> table also.</p>
<pre class="brush: sql; title: ; notranslate">
ALTER TABLE `wp_YOUR_PREFIX_comment_notifier` 
  ADD CONSTRAINT `auto_delete_spammers` 
    FOREIGN KEY (`email`) 
    REFERENCES `wp_YOUR_PREFIX_comments` (`comment_author_email`) 
    ON DELETE CASCADE;
</pre>
<h2>Step 5: Relax and enjoy</h2>
<p>Any time a comment is deleted as spam (or for any other reason), your Comment Notifier will no longer try to send emails to that comment&#8217;s author. Your email server will thank you.</p>
]]></content:encoded>
			<wfw:commentRss>http://nfriedly.com/techblog/2013/03/automatically-removing-spamers-from-the-wordpress-coment-notifier-plugins-database/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatically unit testing client-side JavaScript with Jasmine and Node.js</title>
		<link>http://nfriedly.com/techblog/2013/02/automatically-unit-testing-client-side-javascript-with-jasmine-and-node-js/</link>
		<comments>http://nfriedly.com/techblog/2013/02/automatically-unit-testing-client-side-javascript-with-jasmine-and-node-js/#comments</comments>
		<pubDate>Mon, 04 Feb 2013 21:14:49 +0000</pubDate>
		<dc:creator>nFriedly</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[jasmine]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://nfriedly.com/techblog/?p=460</guid>
		<description><![CDATA[At Sociable Labs, we have hundreds JavaScript unit tests that run on every checkin. They output a JUnit-compatible report that Bamboo can use to track stats and email us if anything failed. Here&#8217;s how we do it. Our JavaScript &#8220;build&#8221; process is basically a script that concatenated all of our JS files into a single [...]]]></description>
				<content:encoded><![CDATA[<p><a href="automatically-unit-testing-client-side-javascript-with-jasmine-and-node-js"><img src="http://nfriedly.com/techblog/wp-content/uploads/2013/02/jasmine_flower.png" alt="jasmine_logo" width="91" height="90" class="alignleft left size-full wp-image-478" /></a> At <a href="http://sociablelabs.com">Sociable Labs</a>, we have hundreds JavaScript unit tests that run on every checkin. They output a <a href="http://www.junit.org/">JUnit</a>-compatible report that <a href="https://www.atlassian.com/software/bamboo/overview">Bamboo</a> can use to track stats and email us if anything failed. Here&#8217;s how we do it.</p>
<p><span id="more-460"></span></p>
<p>Our JavaScript &#8220;build&#8221; process is basically a script that concatenated all of our JS files into a single big file.<sup><a href="#note-1">[1]</a></sup> We added a flag to that process that would skip the <code>init.js</code> file and instead add a <code>module.exports</code> statement for easy inclusion in <a href="http://nodejs.org/">node.js</a>.</p>
<p>With this setup, we can quickly run hundreds of <a href="http://pivotal.github.com/jasmine/">jasmine</a> specs from the command line in any environment we need &#8211; no browser necessary. Our full suite currently takes about 5 seconds to run.</p>
<p>To start off, we installed the <a href="https://npmjs.org/package/jasmine-node">jasmine-node</a> and <a href="https://npmjs.org/package/jsdom">jsdom</a> NPM modules:</p>
<p><code>npm install jasmine-node<br />
npm install jsdom</code></p>
<p>This is the relevant part of our directory structure, the node_modules folder is top-level:</p>
<p><code>
<pre>
build/
node_modules/
 - ...
test/js/
 - environment/
   - jasmine_helper.js
 - util/
   - install_jsdom.sh
 - gallery_spec.js
 - ajax_spec.js
 - etc.
</pre>
<p></code></p>
<p><code>environment/jasmine_helper.js</code> is where most of the magic is:</p>
<pre class="brush: jscript; title: ; notranslate">
var jsdom = require(&quot;jsdom&quot;);
window = jsdom.jsdom('&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;div id=&quot;rondavu_container&quot;&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;').createWindow();

if(Object.keys(window).length === 0) {
    // this hapens if contextify, one of jsdom's dependencies doesn't install correctly
    // (it installs different code depending on the OS, so it cannot get checked in.);
    throw &quot;jsdom failed to create a usable environment, try uninstalling and reinstalling it&quot;;
}

global.window = window;
global.document = window.document;

var R = global.R = require('../../build/rondavu_test_mode.js');
</pre>
<p>First we create a jsdom environment and verify that it works. (We&#8217;ll come back to that in a minute). Next we make the <code>window</code> and <code>document</code> variables global. Finally we include the slightly modified version of our compiled JS and set it in a global variable so that tests can hit it&#8217;s internal methods. Jasmine always runs all helper files before the spec files, so the global variables are guaranteed to exist by the time our tests run.</p>
<p><code>util/install_jsdom.sh</code> is necessary because one of jsdom&#8217;s dependencies, contextify, installs differently on different operating systems. Because of that, we added node_modules/jsdom to the <code>.gitignore</code> file and run this script before running the js unit tests:</p>
<p><code>
<pre>
#!/bin/bash

# One of JSDOM's dependencies, contextify, cannot be checked in because it installs differently depending on the OS.
# This script checks for the presence of JSDOM and installs it if it's missing

# this line searches npm's local repository for jsdom
# 2> /dev/null is becuse NPM likes to complain about missing readme files in third-party packages
# tr removes the blank line that npm puts out if jsdom isn't found
LS_RESULTS=$(npm --parseable ls jsdom 2>/dev/null | tr -d '\n\')

if [[ -n $LS_RESULTS ]]; then 	# -n tests to see if the argument is non empty
	echo "jsdom is already installed, skipping"
else
    npm install jsdom
fi
</pre>
<p></code></p>
<p>Next up, the <code>*_spec.js</code> files. Basically, any file that ends in &#8220;_spec.js&#8221; will be run automatically by jasmine-node. These are just basic <a href="http://pivotal.github.com/jasmine/">jasmine</a> test suites. </p>
<p>If you already have some jasmine specs written, theres&#8217;s a good chance they&#8217;ll just work. If not, now&#8217;s a great time to start <img src='http://nfriedly.com/techblog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Here&#8217;s a quick example from one of ours:</p>
<pre class="brush: jscript; title: ; notranslate">
describe(&quot;Gallery&quot;, function() {

    var instance;

    beforeEach(function(){
        instance = new R.Module.Gallery(getConfig());
    });

    afterEach(function(){
        instance.destroy();
        instance = null;
    });

    describe(&quot;getTemplateData&quot;, function(){

        var data;
        beforeEach(function(){
           data = {mos: []};
        });

        it(&quot;should include the current FB user ID&quot;, function(){
            var USER_ID = &quot;1234&quot;;
            spyOn(R.FB,&quot;getCurrentUserId&quot;).andReturn(USER_ID);

            instance.getTemplateData(data);

            expect(R.FB.getCurrentUserId).toHaveBeenCalled();
            expect(data.current_user_id).toBe(USER_ID);
        });

        it(&quot;should shuffle the mos when Gallery.ShuffleMos is true&quot;, function(){
            var config = getConfig();
            setParam(config, &quot;Gallery.ShuffleMos&quot;, true);
            spyOn(R.Util, &quot;shuffle&quot;);

            instance = new R.Module.Gallery(config);
            instance.getTemplateData(data);

            expect(R.Util.shuffle).not.toHaveBeenCalled();
        });
    });

    // etc.
});
</pre>
<p>Running the tests is easy: </p>
<ol>
<li>Compile your JS file &#8211; <code>build/rondavu_test_mode.js</code> in our case.</li>
<li>Ensure jsdom is installed locally by running <code>util/install_jsdom.sh</code>.</li>
<li>Run the tests: <code>node_modules/jasmine-node/bin/jasmine-node test/js --forceexit</code></li>
</ol>
<p>The <code>--forceexit</code> option cuts a few seconds of idling off the end of the tests. If you want the JUnit-compatible XML report, add <code>--junitreport --output build/js-test-results.xml</code>. (You will likely need to change the path of the output file to wherever your build system is expecting it to be.)</p>
<p>Finally, the process exit code will tell you if the tests passed or not, making it extremely easy to integrate into build systems. Here is our <a href="https://ant.apache.org/">ant</a> task:</p>
<pre class="brush: xml; title: ; notranslate">
    &lt;target name=&quot;js.test&quot; description=&quot;builds a slightly modified version of our rondavu.js (skipping the init.js
        file and adding a 'module.exports=R;') and then runs all test/js/*_spec.js unit tests.&quot;&gt;

        &lt;exec executable=&quot;scripts/js_builder/build_js.js&quot; dir=&quot;${basedir}&quot; failonerror=&quot;true&quot;&gt;
            &lt;arg value=&quot;--test_mode&quot;/&gt;
            &lt;arg value=&quot;--outfile&quot;/&gt;
            &lt;arg value=&quot;build/rondavu_test_mode.js&quot;/&gt;
            &lt;arg value=&quot;--verbose&quot;/&gt;
        &lt;/exec&gt;

        &lt;!-- some of jsdom's dependencies are environment-specific, so we'll install it here if it's not already present --&gt;
        &lt;chmod file=&quot;test/js/util/install_jsdom.sh&quot; perm=&quot;ugo+rx&quot;/&gt;
        &lt;exec executable=&quot;test/js/util/install_jsdom.sh&quot; failonerror=&quot;true&quot;/&gt;

        &lt;mkdir dir=&quot;${build.test.unit.output}&quot;/&gt;

        &lt;exec executable=&quot;node_modules/jasmine-node/bin/jasmine-node&quot; failonerror=&quot;true&quot;&gt;
            &lt;arg value=&quot;--forceexit&quot;/&gt;
            &lt;arg value=&quot;test/js/&quot;/&gt;
            &lt;arg value=&quot;--junitreport&quot;/&gt;
            &lt;arg value=&quot;--output&quot;/&gt;&lt;arg value=&quot;${build.test.unit.output}/TEST-javascript-results.xml&quot;/&gt;
        &lt;/exec&gt;

    &lt;/target&gt;
</pre>
<p>And there you have it. Happy testing!</p>
<hr style="margin: 30px 0;">
<p><i><a name="note-1">[1]:</a> It&#8217;s actually a bit more complex that that &#8211; we generate a separate file for each customer with their configuration and whatever features they use. </p>
<p>Also, we&#8217;ve recently switched from our custom js build script to <a href="http://requirejs.org/">require.js</a> and <a href="http://jamjs.org/">jam.js</a>, but we&#8217;re still working out the final kinks. Expect a followup post once we&#8217;re fully confident with the new setup <img src='http://nfriedly.com/techblog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </i></p>
]]></content:encoded>
			<wfw:commentRss>http://nfriedly.com/techblog/2013/02/automatically-unit-testing-client-side-javascript-with-jasmine-and-node-js/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<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, 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 that [...]]]></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, and often as not I forget to <code>cd</code> 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>Calling all (available) Web Designers &amp; Developers</title>
		<link>http://nfriedly.com/techblog/2010/12/calling-all-available-web-designers-developers/</link>
		<comments>http://nfriedly.com/techblog/2010/12/calling-all-available-web-designers-developers/#comments</comments>
		<pubDate>Fri, 17 Dec 2010 17:29:24 +0000</pubDate>
		<dc:creator>nFriedly</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[seo]]></category>

		<guid isPermaLink="false">http://nfriedly.com/techblog/?p=329</guid>
		<description><![CDATA[Even though I&#8217;ve been happily employed with Sociable Labs for a while now, I still get fairly frequent calls and emails from people who want to know if I&#8217;m available or I &#8220;know someone.&#8221; The list of people I know is starting to run short, so this post is intended to remedy that. If you [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://nfriedly.com/techblog/2010/12/calling-all-avaliable-web-designers-developers"><img class="alignright size-full wp-image-358" title="Ring Ring!" alt="" src="http://nfriedly.com/techblog/wp-content/uploads/2010/12/1171473_phone_home-min.jpg" width="200" height="245" /></a>Even though I&#8217;ve been happily employed with <a href="http://sociablelabs.com/">Sociable Labs</a> for a while now, I still get fairly frequent calls and emails from people who want to know if I&#8217;m available or I &#8220;know someone.&#8221; The list of people I know is starting to run short, so this post is intended to remedy that.</p>
<p><strong>If you are an individual Web Designer or Web Developer interested in work, please post a comment below.</strong></p>
<p><strong><span id="more-329"></span></strong>What to post:</p>
<ul>
<li>Your name and website in the appropriate fields. I disabled WordPress&#8217;s <code>rel="nofollow"</code> just for you.
<ul>
<li>If you don&#8217;t have a website, get one! Sign up for a <a href="http://www.dreamhost.com/r.cgi?225072">Dreamhost account</a> and buy a template from <a href="http://themeforest.net/?ref=nfriedly">Theme Forest</a> and you&#8217;ll have a solid website in no time.</li>
</ul>
</li>
<li>Your basic skillset. For me, it might be &#8220;Strong Javascript / Ajax, PHP, HTML, and CSS; basic Photoshop, ActionScript and Java&#8221;</li>
<li>A short bit about yourself and your experience.</li>
<li>Where you&#8217;re located, and if you would consider relocating for work.</li>
<li>What type of work you&#8217;re interested in: freelance / short-term contract (3-6 months or less), long-term contract, employment, startup, etc.</li>
</ul>
<p>Tips:</p>
<ul>
<li>This is your first impression to potential clients: Copy-paste it into Word and read it out loud once or twice. Get it right the first time because you can&#8217;t edit comments after you&#8217;ve posted them.</li>
<li>Contact information: any phone number or email address posted here will be picked up by spammers.
<ul>
<li>A basic solution is to just post a .jpg on your website with your phone number and email.</li>
<li>A better solution could be a contact form like this one: <a href="http://nfriedly.com/techblog/2009/06/how-to-build-a-spam-free-contact-forms-without-captchas/">How to build a spam-free contact form without captchas</a></li>
</ul>
</li>
<li>One or two links to your GitHub, LinkedIn, or recent work is fine, but be warned that my WordPress marks<strong> </strong>anything with <strong>more than 3 links as spam</strong>, and it&#8217;s hidden until I get around to checking the spam filter.</li>
<li>Lastly, this is my website, and I may choose to edit or delete comments. For example, if you claim 10+ years experience with jQuery, your comment will be deleted. (JQuery was released in 2006)</li>
</ul>
<p>Thanks and best wishes with your future work!</p>
]]></content:encoded>
			<wfw:commentRss>http://nfriedly.com/techblog/2010/12/calling-all-available-web-designers-developers/feed/</wfw:commentRss>
		<slash:comments>17</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" alt="" src="http://nfriedly.com/img/portfolio/facebook.png" />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>Cross-domain communication</h3>
<p>If you need to communicate between domains, <a href="http://caniuse.com/#feat=x-doc-messaging">modern browsers</a> allow you to use <a href="https://developer.mozilla.org/en-US/docs/DOM/window.postMessage">postMessage</a> to send data between web pages (although it <a href="http://blogs.msdn.com/b/ieinternals/archive/2009/09/16/bugs-in-ie8-support-for-html5-postmessage-sessionstorage-and-localstorage.aspx">doesn&#8217;t work with popups in Internet Explorer</a>).</p>
<p>If you need to support older browsers, you can include the excellent <a href="http://easyxdm.net/">easyXDM</a> library for iframe-parent communication. You might need to combine a popup + one or more iframes in some situations.</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>4</slash:comments>
		</item>
		<item>
		<title>JavaScript library and .swf for cross-domain flash cookies</title>
		<link>http://nfriedly.com/techblog/2010/07/swf-for-javascript-cross-domain-flash-cookies/</link>
		<comments>http://nfriedly.com/techblog/2010/07/swf-for-javascript-cross-domain-flash-cookies/#comments</comments>
		<pubDate>Tue, 13 Jul 2010 18:25:11 +0000</pubDate>
		<dc:creator>nFriedly</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[actionscript 3.0]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[cross-domain]]></category>
		<category><![CDATA[externalinterface]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[flashcookie]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[sharedobject]]></category>
		<category><![CDATA[swf]]></category>

		<guid isPermaLink="false">http://nfriedly.com/techblog/?p=272</guid>
		<description><![CDATA[I&#8217;m working on a project that has a legitimate (non-spammy) reason to need cross-domain cookies, and we settled on flash as a good way to accomplish this. However, I was surprisingly unable to find any complete library or how-to guide for connecting flash cookies to javascript. So I dusted off my flash skills and built [...]]]></description>
				<content:encoded><![CDATA[<div style="position:relative;">
<img class="alignright size-full wp-image-295" title="325990_chocolate_chip_cookies_2" src="http://nfriedly.com/techblog/wp-content/uploads/2010/07/325990_chocolate_chip_cookies_2.jpg" alt="" width="300" height="224" />I&#8217;m working on a project that has a legitimate (non-spammy) reason to need cross-domain cookies, and we settled on flash as a good way to accomplish this.</p>
<p>However, I was surprisingly unable to find any complete library or how-to guide for connecting flash cookies to javascript. So I dusted off my flash skills and built one, and and now you get to enjoy the fruit of my labor:</p>
<p><a href="http://github.com/nfriedly/Javascript-Flash-Cookies"><img style="position: absolute; top: 0pt; right: 0pt; border: 0pt none;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
</div>
<p><span id="more-272"></span></p>
<p><a href="http://github.com/nfriedly/Javascript-Flash-Cookies/zipball/master"><img class="alignleft" src="/img/application_put.png" alt="" /> Download the .swf, .js, and source code from github</a></p>
<p>This is an .swf file  that communicates with JavaScript via flash&#8217;s <a href="http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/external/ExternalInterface.html">ExternalInerface</a> to read and write to a Local <a href="http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/net/SharedObject.html">SharedObject</a> (LSO). Essentially, it&#8217;s cross-domain cookies for javascript.</p>
<p>It also includes an (optional) javascript library that handles embedding, communication, error checking, and logging.</p>
<p>The project is hosted at github: <a href="http://github.com/nfriedly/Javascript-Flash-Cookies">http://github.com/nfriedly/Javascript-Flash-Cookies</a></p>
<hr style="margin-top: 20px;" />
<p><em>You might also be interested in <a href="http://nfriedly.com/techblog/2010/08/how-facebook-sets-and-uses-cross-domain-cookies/">How Facebook Sets and uses cross-Domain cookies</a></em></p>
<hr />
<h3>Working Example</h3>
<p>See <a href="http://nfriedly.com/stuff/swfstore-example/">https://nfriedly.com/stuff/swfstore-example/</a> and <a href="http://nfriedly.github.com/Javascript-Flash-Cookies/">http://nfriedly.github.com/Javascript-Flash-Cookies/</a> for a working example. </p>
<h3>Quick start guide</h3>
<p>To use the library, upload the storage.swf &amp; swfstore.js files to your web server and put this HTML and JavaScript into your web page(s):</p>
<h4>The HTML</h4>
<pre class="brush: xml; title: ; notranslate">
&lt;!-- This example uses jquery, but SwfStore does not require jquery to work. --&gt;
&lt;script src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;/PATH/TO/swfstore.js&quot;&gt;&lt;/script&gt;

&lt;input id=&quot;dataInput&quot; /&gt; &lt;input id=&quot;saveBtn&quot; type=&quot;submit&quot; value=&quot;Save&quot; /&gt;

&lt;div id=&quot;status&quot;&gt;&lt;/div&gt;
</pre>
<h4>And The JavaScript</h4>
<pre class="brush: jscript; title: ; notranslate">

// wait until the page has finished loading before starting
$(function(){

	// first disable things while the swfStore is initializing
	$('input').attr(&quot;disabled&quot;,&quot;disabled&quot;);
	$('#status').text('Loading...');

	var mySwfStore = new SwfStore({

		// Optional but recommended. Try to choose something unique.
		namespace: 'myExample', 

		// To work cross-domain, only one of your sites should have the
		// .swf, all other sites should load it from the first one
		swf_url: 'http://site.com/PATH/TO/storage.swf', 

		// Logs messages to the console if available, a div at the
		// bottom of the page otherwise. 
		debug: true,

		onready: function(){
			// Now that the swfStore was loaded successfully, re-enable
			$('input').removeAttr(&quot;disabled&quot;);

			// Read the existing value (if any)
			$('#dataInput').val(mySwfStore.get('myKey'));

			// Set up an onclick handler to save the text to the 
			// swfStore whenever the Save button is clicked
			$('#saveBtn').click(function(){
				mySwfStore.set('myKey', $('#dataInput').val() );
				$('#status').text('Saved!')
			});

			$('#status').text('Loaded');
		},

		onerror: function(){
			// In case we had an error. (The most common cause is that 
			// the user disabled flash cookies.)
			$('#status').text('Error');
		}
	});
});
</pre>
<h3>Cross-domain usage</h3>
<p>A copy of storage.swf located on one domain may be embedded on pages from one or more other domains, allowing cross-domain cookie access.</p>
<style>
.highlight { background-color: #D1FCA9; }
</style>
<h3>Troubleshooting</h3>
<ul>
<li>Be sure the <span class="highlight">urls</span> to the .swf file and .js file are both correct.</li>
<li>If the .swf file is unable to communicate with the JavaScript, it will <span  class="highlight">display log messages on the flash object</span>. If debug is enabled, this this should be visible on the page.</li>
<li>To <span class="highlight">hide the flash object</span> and disable the <span class="highlight">log messages appending to the bottom of the page</span>, set debug to false</span>. (Log messages are added to a div if no console is found).</li>
<li>If the user does not have flash installed, the onerror function will be called after a (configurable) 10 second timeout. You may want to use a library such as <a href="http://www.featureblend.com/javascript-flash-detection-library.html">Flash Detect</a> to check for this more quickly. <span  class="highlight">Flash Player 9.0.31.0</span> or newer is required.</li>
<li>If you pass a <span class="highlight">non-string data</span> as the key or value, things may break. Your best bet is to use strings and/or use <a href="http://json.org">JSON</a> to encode objects as strings.</li>
<li>If you see the error <span class="highlight">&#8220;uncaught exception: Error in Actionscript. Use a try/catch block to find error.&#8221;</span>, try using &#8220;//&#8221; in the .swf URL rather than &#8220;https://&#8221;. See <a href="https://github.com/nfriedly/Javascript-Flash-Cookies/issues/14">https://github.com/nfriedly/Javascript-Flash-Cookies/issues/14</a> for more information.</li>
<li>Do not set <code class="highlight">display:none</code> on the swf or any of it&#8217;s parent elements, this will cause the file to not render and the timeout will be fired. Disable debug and it will be rendered off screen.</li>
<li>The error <code class="highlight">this.swf.set is not a function</code> has been known to occur when the FlashFirebug plugin is enabled in Firefox / Firebug..
</ul>
<h3>Patches</h3>
<p>Although my JS is solid, my Flash / ActionScript skills leave something to be desired. Patches to either are more than welcome at <a href="http://github.com/nfriedly/Javascript-Flash-Cookies">github</a> (preferred), or just leave a comment here if you&#8217;re not sure how to use github. (This comment has a <a href="http://nfriedly.com/techblog/2010/07/swf-for-javascript-cross-domain-flash-cookies/comment-page-1/#comment-2531">short walk through to using github</a>.)</p>
<h3>Production Use</h3>
<p>If you&#8217;re using SwfStore in a production site, feel free to leave a comment here with a link to the site. I turned off WP&#8217;s default rel=&#8221;nofollow&#8221;, so enjoy the link juice <img src='http://nfriedly.com/techblog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  Reciprocal links are not required, but are always appreciated.</p>
]]></content:encoded>
			<wfw:commentRss>http://nfriedly.com/techblog/2010/07/swf-for-javascript-cross-domain-flash-cookies/feed/</wfw:commentRss>
		<slash:comments>45</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>95</slash:comments>
		</item>
		<item>
		<title>Advanced Javascript: Logical Operators and truthy / falsy</title>
		<link>http://nfriedly.com/techblog/2009/07/advanced-javascript-operators-and-truthy-falsy/</link>
		<comments>http://nfriedly.com/techblog/2009/07/advanced-javascript-operators-and-truthy-falsy/#comments</comments>
		<pubDate>Tue, 07 Jul 2009 16:54:49 +0000</pubDate>
		<dc:creator>nFriedly</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[optimization]]></category>

		<guid isPermaLink="false">http://nfriedly.com/techblog/?p=46</guid>
		<description><![CDATA[Nearly every website on the internet uses javascript in some form or fashion. Yet very few people, even those who write it and teach it, have a clear understanding of how javascript works! Logical Operators are a core part of the language. We&#8217;re going to look at what logical operators are, what &#8220;truthy&#8221; and &#8220;falsy&#8221; [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/fleur-design/308974073/"><img class="alignleft" title="speed machine" src="http://farm1.static.flickr.com/104/308974073_9057064747_m.jpg" alt="" width="240" height="160" /></a> Nearly every website on the internet uses javascript in some form or fashion. Yet very few people, even those who write it and teach it, have a clear understanding of how javascript works!</p>
<p>Logical Operators are a core part of the language. We&#8217;re going to look at what logical operators are, what &#8220;truthy&#8221; and &#8220;falsy&#8221; mean, and <strong>how to use this to write cleaner, faster and more optimized javascript</strong>.</p>
<p><span id="more-46"></span></p>
<h2>Javascript Logical Operators</h2>
<p>In traditional programming, operators such as <code>&amp;&amp;</code> and <code>|| </code> returned a boolean value (<code>true</code> or <code>false</code>). This is not the case in javascript. Here it returns the actual <code>object</code>, not a <code>true</code> / <code>false</code>.  To really explain this, I first have to explain what is truthy and what is falsy.</p>
<h3>Truthy or Falsy</h3>
<p>When javascript is expecting a <code>boolean</code> and it&#8217;s given something else, it decides whether the something else is &#8220;truthy&#8221; or &#8220;falsy&#8221;.</p>
<p>An empty string (<code>''</code>), the number <code>0</code>, <code>null</code>, <code>NaN</code>, a boolean <code>FALSE</code>, and <code>undefined</code> variables are all &#8220;falsy&#8221;. Everything else is &#8220;truthy&#8221;.</p>
<pre class="brush: jscript; title: ; notranslate">
var emptyString = &quot;&quot;; // falsy

var nonEmptyString = &quot;this is text&quot;; // truthy

var numberZero = 0; // falsy

var numberOne = 1; // truthy

var emptyArray = []; // truthy, BUT []==false is true. More below.

var emptyObject = {}; // truthy

var notANumber = 5 / &quot;tree&quot;; // falsy
// NaN is a special javascript object for &quot;Not a Number&quot;.

function exampleFunction(){
	alert(&quot;Test&quot;);
}
// examleFunction is truthy
// BUT exampleFunction() is falsy because it has no return (undefined)
</pre>
<p>Gotchas to watch out for: the strings &#8220;0&#8243; and &#8220;false&#8221; are both considered truthy.  You can convert a string to a number with the <code>parseInt()</code> and <code>parseFloat()</code> functions, or by just multiplying it by 1.</p>
<pre class="brush: jscript; title: ; notranslate">
var test = &quot;0&quot;; // this is a string, not a number

(test == false); // returns false, meaning that test is truthy

(test * 1 == false); // returns true, meaning that `test * 1` is falsy
</pre>
<p>As one commenter <a href="#comment-2100">mentioned</a>, arrays are particularly weird. If you just test it for truthyness, an empty array is truthy. HOWEVER, if you compare an empty array to a boolean, it becomes falsy:</p>
<pre class="brush: jscript; title: ; notranslate">
  if([] == false){
    // this code runs
  }

  if( [] ) {
    // this code also runs
  }

  if([] == true){
    // this code doesn't run
  }

  if( ![] ) {
    // this code also doesn't run
  }

</pre>
<p>Another commenter <a href="http://www.nicollet.net/2009/06/the-truth-of-javascript/">pointed out</a> an additional gotcha to watch out for: while javascript evaluates empty arrays as true, PHP evaluates them as false.</p>
<p>PHP also evaluates &#8220;0&#8243; as falsy. (However the string &#8220;false&#8221; is evaluated as truthy by both PHP and javascript.)</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php

$emptyArray = array(); // falsy in PHP

$stringZero = &quot;0&quot;; // falsy in PHP

?&gt;
</pre>
<h3>How Logical Operators Work</h3>
<h4>Logical OR, <code>||</code></h4>
<p>The logical OR operator, <code>||</code>,  is very simple after you understand what it is doing. If the first object is truthy, that gets returned. Otherwise, the second object gets returned.</p>
<pre class="brush: jscript; title: ; notranslate">
(&quot;test one&quot; || &quot;test two&quot;); // returns &quot;test one&quot;

(&quot;test one&quot; || &quot;&quot;); // returns &quot;test one&quot;

(0 || &quot;test two&quot;); // returns &quot;Test two&quot;

(0 || false); // returns false
</pre>
<p>Where would you ever use this? The OR operator allows you to easily specify default variables in a function.</p>
<pre class="brush: jscript; title: ; notranslate">
function sayHi(name){

	var name = name || &quot;Dave&quot;;

	alert(&quot;Hi &quot; + name);

}

sayHi(&quot;Nathan&quot;); // alerts &quot;Hi Nathan&quot;;

sayHi(); // alerts &quot;Hi Dave&quot;,
// name is set to null when the function is started
</pre>
<h4>Logical AND, <code>&amp;&amp;</code></h4>
<p>The logical AND operator, <code>&amp;&amp;</code>,  works similarly.  If the first object is falsy, it returns that object. If it is truthy, it returns the second object.</p>
<pre class="brush: jscript; title: ; notranslate">
(&quot;test one&quot; &amp;&amp; &quot;test two&quot;); // returns &quot;test two&quot;

(&quot;test one&quot; &amp;&amp; &quot;&quot;); // returns &quot;&quot;

(0 &amp;&amp; &quot;test two&quot;) // returns 0
</pre>
<p>The logical AND allows you to make one variable dependent on another.</p>
<pre class="brush: jscript; title: ; notranslate">
var checkbox = document.getElementById(&quot;agreeToTerms&quot;);

var name = checkbox.checked &amp;&amp; prompt(&quot;What is your name&quot;);

// name is either their name, or false if they haven't checked the AgreeToTerms checkbox

// IMPORTANT NOTE: Internet Explorer 8 breaks the prompt function.
</pre>
<h4>Logical NOT, <code>!</code></h4>
<p>Unlike <code>&#038;&#038;</code> and <code>||</code>, the <code>!</code> operator DOES turn the value it receives into a boolean. If it receives a truthy value, it returns <code>false</code>, and if it receives a falsy value, it returns <code>true</code>.</p>
<pre class="brush: jscript; title: ; notranslate">
(!&quot;test one&quot; || &quot;test two&quot;); // returns &quot;test two&quot;
// (&quot;test one&quot; gets converted to false and skipped)

(!&quot;test one&quot; &amp;&amp; &quot;test two&quot;); // returns false
// (&quot;test one&quot; gets converted to false and returned)

(!0 || !&quot;test two&quot;); // returns true
// (0 gets converted to true and returned)
</pre>
<p>Another useful way to use the <code>!</code> operator is to use two of them &#8211; this way you always get a <code>true</code> or a <code>false</code> no matter what was given to it.</p>
<pre class="brush: jscript; title: ; notranslate">
(!!&quot;test&quot;); // returns true
//  &quot;test&quot; is converted to false, then that is converted to true

(!!&quot;&quot;); // returns false
// &quot;&quot; is converted to true, and then that true is converted to false

(!!variableThatDoesntExist); // returns false even though you're checking an undefined variable.
</pre>
<h2><a href="http://nfriedly.com/webdev">Javascript Optimization</a></h2>
<p>Need any help <a href="/webdev/javascript">optimizing the Javascript and AJAX on your website</a>? Get in touch with your friendly neighborhood <a href="http://nfriedly.com/webdev">javascript expert</a> for ideas on how to optimize your site and a free quote.</p>
]]></content:encoded>
			<wfw:commentRss>http://nfriedly.com/techblog/2009/07/advanced-javascript-operators-and-truthy-falsy/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>How to use XSLT to style an RSS feed</title>
		<link>http://nfriedly.com/techblog/2009/06/how-to-use-xslt-to-style-an-rss-feed/</link>
		<comments>http://nfriedly.com/techblog/2009/06/how-to-use-xslt-to-style-an-rss-feed/#comments</comments>
		<pubDate>Wed, 17 Jun 2009 19:18:39 +0000</pubDate>
		<dc:creator>nFriedly</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[xslt]]></category>

		<guid isPermaLink="false">http://nfriedly.com/techblog/?p=191</guid>
		<description><![CDATA[XSLT is a fairly well-supported technology. It allows you to take any XML file &#8211; including RSS &#8211; and transform it into a styled HTML document. It&#8217;s kind of like CSS on steroids. Unfortunately, most browsers think they know better and go off and do their own thing on RSS feeds. We&#8217;re going to look [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/gogdog/2240855570/"><img class="alignright" src="http://farm3.static.flickr.com/2097/2240855570_4529cf9f6d_m.jpg" alt="Take this!" /></a><abbr title="Extensible Stylesheet Language Transformations">XSLT</abbr> is a fairly well-supported technology. It allows you to take any XML file &#8211; including RSS &#8211; and <em>transform</em> it into a styled HTML document. It&#8217;s kind of like CSS on steroids.</p>
<p>Unfortunately, most browsers think they know better and go off and do their own thing on RSS feeds.</p>
<p>We&#8217;re going to look at how and which browsers can be brought into line, and how to use XSLT to improve the look of your RSS feed in those browsers.</p>
<p><span id="more-191"></span></p>
<h2>The RSS problem</h2>
<p>In most browsers, XML and XSLT are supported in every single case *except* RSS. By default, Internet Explorer, Firefox, Safari, and Opera all ignore XSLT files and do their own thing with RSS. In fact, Google Chrome is the *only* browser I tested that got it right without tinkering.</p>
<p>To their credit, Microsoft at least gave their users the option to turn off the &#8220;feature&#8221;. No other browser even gives this option.</p>
<p>During my tests, I have found a way to &#8220;trick&#8221; Firefox into rendering RSS with XSLT correctly. Currently there seems to be no solution for other browsers except to try and detect them on the server and send the user an HTML file if they&#8217;re in a browser that doesn&#8217;t work properly.</p>
<h3>Internet Explorer</h3>
<p>IE requires that the user specifically choose to disable their take-liberties-with-rss &#8220;feature&#8221;. I would point out that this really isn&#8217;t good enough because 99% of users will never get that far, but sadly, it&#8217;s the closest thing to getting it right out of any browser on the market! (Aside from Google Chrome.)</p>
<p>Here&#8217;s how:</p>
<ol>
<li>Click on the <strong>Tools</strong> menu,</li>
<li>Click on the <strong>Internet Options</strong> sub-menu,</li>
<li>Click on the <strong>Content</strong> tab,</li>
<li>Click on the <strong>Settings</strong> button of the <strong>Feed</strong> section to bring up Feed Settings dialog box,</li>
<li>Un-check the <strong>Turn On Feed Reading View</strong> option.</li>
<li>Click OK all the way to close all opened dialog boxes.</li>
<li>Restart Internet Explorer</li>
</ol>
<h3><a href="http://www.flickr.com/photos/gogdog/2240065731/"><img class="alignright" src="http://farm3.static.flickr.com/2172/2240065731_86c22f48c1_m.jpg" alt="Transform!" /></a>Firefox</h3>
<p>Firefox can be tricked into working because it decides fairly early on in the rendering process whether to treat the page in a standard way or to fly off the handle with it. In fact, it makes this decision before even completely downloading the RSS file.</p>
<p>Because of the early decision process, we can insert 512 characters of white space in between the <code>&lt;?xml ?&gt;</code> declaration and the opening <code>&lt;rss&gt;</code> tag. Firefox is then &#8220;tricked&#8221; into doing the right thing and rendering the feed correctly.</p>
<h2>Working around it</h2>
<p>Although not practical in most cases currently, I&#8217;ve included an example of a script that will take any RSS feed and add a style sheet to it.  It includes the hack to work in firefox and instructions for enabling it in Internet Explorer.</p>
<p><a href="http://nfriedly.com/stuff/rss/?url=http://nfriedly.com/techblog/feed/">http://nfriedly.com/stuff/rss/?url=http://nfriedly.com/techblog/feed/</a></p>
<p>Code for index.php:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php

// grab the url
if(isset($_REQUEST['url'])) $url = $_REQUEST['url'];
else $url = false;

// make sure the url is good (no local files)
if($url &amp;&amp; substr($url,0,7) != &quot;http://&quot;) exit(&quot;Please start urls with 'http://'&quot;);

// make the stylesheet link
$xsl_file = 'xsl.php';
if($url) $xsl_file .= '?url='.urlencode($url);
define('XSL_LINK','&lt;?xml-stylesheet href=&quot;'.$xsl_file.'&quot; type=&quot;text/xsl&quot; ?&gt;');

// if we don't have a url, use the home page
if(!$url) $url = &quot;home.xml&quot;;

// download the rss feed
$rss = file_get_contents($url);

// xml header so firefox doesn't decide it's text
header('content-type: text/xml');

//echo out the header right away, if there is one
if(substr($rss,0,6) == '&lt;?xml '){
	$header_end = strpos($rss,'?&gt;') +2;
	echo substr($rss,0,$header_end);
	$rss = substr($rss,$header_end);
}
//otherwise echo a default header:
else echo '&lt;?xml version=&quot;1.0&quot; ?'.'&gt;';

// remove any existing stylesheet
$rss = preg_replace('/&lt;\?xml-stylesheet([^?]|\?(?!&gt;))*\?'.'&gt;/','',$rss);  // uses lookahead

// add in our stylesheet
echo &quot;\r\n&quot; . XSL_LINK . &quot;\r\n&quot;;

// toss in 512 bytes of nothing to throw off firefox
echo &quot;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 &quot;;

//finally, pass along the content
echo $rss;

?&gt;

</pre>
<p>The xsl.php file is only php to allow for setting the current url in the feed url input box. Ignoring that, you can view it&#8217;s source by looking at <a href="http://nfriedly.com/stuff/rss/xsl.php">http://nfriedly.com/stuff/rss/xsl.php</a>. You could simply save that as an .xml file and have a working copy.</p>
<p>You can also view the <a href="http://nfriedly.com/stuff/rss/theme/style.css">CSS</a> and <a href="http://nfriedly.com/stuff/rss/scripts.js">Javascript</a> used to make everything look nice.</p>
<h2>Hire me for web development</h2>
<p>Need an <a href="http://nfriedly.com/webdev">expert web programmer</a> to research and solve some off-the-wall problem like this? I&#8217;m available. I&#8217;m good solving run-of-the-mill problems too &#8211; <a href="http://nfriedly.com/webdev/javascript">Javascript and AJAX development</a> is my specialty.  <a href="http://nfriedly.com/contact">Get in touch with me</a> for more information and a free quote.</p>
]]></content:encoded>
			<wfw:commentRss>http://nfriedly.com/techblog/2009/06/how-to-use-xslt-to-style-an-rss-feed/feed/</wfw:commentRss>
		<slash:comments>37</slash:comments>
		</item>
	</channel>
</rss>
