<?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>flagrantdisregard &#187; programming</title>
	<atom:link href="http://flagrantdisregard.com/tag/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://flagrantdisregard.com</link>
	<description></description>
	<lastBuildDate>Sat, 24 Mar 2012 19:09:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Lifestreaming</title>
		<link>http://flagrantdisregard.com/lifestreaming/</link>
		<comments>http://flagrantdisregard.com/lifestreaming/#comments</comments>
		<pubDate>Tue, 20 Jul 2010 16:18:43 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[blogging]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[lifestreaming]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://flagrantdisregard.com/?p=2148</guid>
		<description><![CDATA[The word &#8220;lifestreaming&#8221; feels overly broad and I do a mental eye roll every time I say it, but I&#8217;ll use it for now for the sake of expediency. So I&#8217;ve been using Flickr and Delicious forever and Twitter for a while and Google Reader and all of these services are great and let me [...]]]></description>
			<content:encoded><![CDATA[<div class="wp-caption alignright" style="width: 250px"><a href="http://www.flickr.com/photos/asphericlens/3318353265/"><img title="stream by aspheric.lens, on Flickr" src="http://farm4.static.flickr.com/3645/3318353265_85eee11506_m.jpg" alt="stream by aspheric.lens, on Flickr" width="240" height="161" /></a><p class="wp-caption-text">stream by aspheric.lens, on Flickr</p></div>
<p>The word &#8220;lifestreaming&#8221; feels overly broad and I do a mental eye roll every time I say it, but I&#8217;ll use it for now for the sake of expediency.</p>
<p>So I&#8217;ve been using Flickr and Delicious forever and Twitter for a while and Google Reader and all of these services are great and let me share things in different ways. But what&#8217;s always bothered me is that these Shared Things were not only siloed off from each other, they were on sites I didn&#8217;t control. Yes, they all make it very easy to republish your stuff. I was doing that for a while with sidebar widgets for each of those services (I still have them on my <a href="http://flagrantdisregard.com/asides/">Asides</a> page, actually). But it still all felt very unconnected.</p>
<p>What I really wanted was to hook into the sharing functionality on those sites so that when I pushed the Share button in Google Reader, say, it would also send the item to my personal blog. That would allow me to aggregate my photos and bookmarks and tweets in one place and keep a permanent record of all of those things that is in my control.</p>
<p>I looked into several services (thinking I might let someone do the aggregating for me and then download the result), standalone software and plugins for WordPress. One of the better and easy to use solutions in the WordPress plugin category is <a href="http://wordpress.org/extend/plugins/lifestream/">Lifestream by David Cramer.</a> It does almost everything I need except that I didn&#8217;t like the way the resulting lifestream ended up being something separate from the actual blog. I wanted my blog itself to become the lifestream.</p>
<p>In the standalone software category, <a href="http://pubwich.org/">PubWich</a> looks very promising. But, again, I wanted something with seamless integration with WordPress.</p>
<p>So I ended up writing a plugin over the weekend. What it does:</p>
<ul>
<li>Periodically scans and downloads feeds from sources you define</li>
<li>Makes a new blog post for every new item in each feed</li>
<li>Blog posts can be created as new WordPress 3.0 Post Types or posted to specific categories</li>
<li>Defines filters so that you can hook into each individual feed as it is being imported to tweak the content</li>
<li>Saves a history of every feed</li>
</ul>
<p>Then based on that, I created a WordPress theme that styles posts depending on the source. That&#8217;s how I display the post icons and the &#8220;View original&#8221; link with the domain of the source website, for example. Because every item becomes a blog post they inherit everything WordPress provides: they go into the feed, comments, permalinks, etc. That&#8217;s cool! (In a very nerdy way.)</p>
<p>So far, after one day of use, I&#8217;m very happy with it. I intend to release the plugin after I do some more work on it. Let me know if you&#8217;re interested in helping me test it.</p>
]]></content:encoded>
			<wfw:commentRss>http://flagrantdisregard.com/lifestreaming/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Footnotes plugin for WordPress released</title>
		<link>http://flagrantdisregard.com/footnotes-plugin-for-wordpress-released/</link>
		<comments>http://flagrantdisregard.com/footnotes-plugin-for-wordpress-released/#comments</comments>
		<pubDate>Tue, 01 Apr 2008 19:31:33 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[blogging]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://flagrantdisregard.com/?p=949</guid>
		<description><![CDATA[I just released a new plugin for WordPress for adding footnotes (well, endnotes really) to posts. You can check it out and download it from here: Footnotes Plugin. Also, I&#8217;ve written a couple of other plugins you may be interested in.]]></description>
			<content:encoded><![CDATA[<p>I just released a new plugin for WordPress for adding footnotes (well, endnotes really) to posts. You can check it out and download it from here: <a href="http://flagrantdisregard.com/footnotes-plugin/">Footnotes Plugin</a>. Also, I&#8217;ve written a couple of <a href="http://flagrantdisregard.com/wordpress-plugins/">other plugins</a> you may be interested in.</p>
]]></content:encoded>
			<wfw:commentRss>http://flagrantdisregard.com/footnotes-plugin-for-wordpress-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>About the Technical Reviewer</title>
		<link>http://flagrantdisregard.com/about-the-technical-reviewer/</link>
		<comments>http://flagrantdisregard.com/about-the-technical-reviewer/#comments</comments>
		<pubDate>Fri, 29 Feb 2008 02:01:01 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[technology]]></category>
		<category><![CDATA[books]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://flagrantdisregard.com/about-the-technical-reviewer/</guid>
		<description><![CDATA[Received my copy today of the Pro Web 2.0 Mashups book I did the technical review for. Always neat to see something you&#8217;ve worked on become real. Also, I hate writing bios like this.]]></description>
			<content:encoded><![CDATA[<p><img src="http://flagrantdisregard.com/wp-content/uploads/2008/02/technical_reviewer.jpg" alt="About the Technical Reviewer" /></p>
<p>Received my copy today of the <a href="http://flagrantdisregard.com/pro-web-20-mashups/">Pro Web 2.0 Mashups book</a> I did the technical review for. Always neat to see something you&#8217;ve worked on become <em>real.</em> Also, I hate writing bios like this.</p>
]]></content:encoded>
			<wfw:commentRss>http://flagrantdisregard.com/about-the-technical-reviewer/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Pro Web 2.0 Mashups</title>
		<link>http://flagrantdisregard.com/pro-web-20-mashups/</link>
		<comments>http://flagrantdisregard.com/pro-web-20-mashups/#comments</comments>
		<pubDate>Tue, 22 Jan 2008 01:16:59 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[technology]]></category>
		<category><![CDATA[books]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://flagrantdisregard.com/index.php/2008/01/21/pro-web-20-mashups/</guid>
		<description><![CDATA[I just finished technical review on a new book due out next month from Apress called Pro Web 2.0 Mashups: Remixing Data and Web Services. (A technical reviewer basically just makes sure all of the examples work and that the technical stuff the author writes is correct and provides evaluations of the text from a [...]]]></description>
			<content:encoded><![CDATA[<p><img src='http://flagrantdisregard.com/wp-content/uploads/2008/01/promashupcover.jpg' alt='Pro Web 2.0 Mashups' class="alignright" />I just finished technical review on a new book due out next month from Apress called <i>Pro Web 2.0 Mashups: Remixing Data and Web Services.</i> (A technical reviewer basically just makes sure all of the examples work and that the technical stuff the author writes is correct and provides evaluations of the text from a technical viewpoint as the book is written.)</p>
<p>Anyway, it&#8217;s an interesting book about remixing and mashing up data from multiple online services via APIs. But one of the coolest things about the book&#8212;are you ready for this?&#8212;the author, Raymond Yee, and publisher have agreed to release it under a Creative Commons Non-commercial Share-Alike license! In addition, <a href="http://blog.mashupguide.net/">the draft of every chapter is available online</a> right now and the published version will be available shortly. It&#8217;s practically an open-source book.</p>
<p>I&#8217;ve already been paid for my work on the book but I still feel too close to it to be able to give an unbiased review. But who needs a review? Go check out the book yourself and if you like it please show your support for openness and buy a copy when it hits Amazon.</p>
]]></content:encoded>
			<wfw:commentRss>http://flagrantdisregard.com/pro-web-20-mashups/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Bye bye Script.aculo.us, hello MooTools</title>
		<link>http://flagrantdisregard.com/bye-bye-scriptaculous-hello-mootools/</link>
		<comments>http://flagrantdisregard.com/bye-bye-scriptaculous-hello-mootools/#comments</comments>
		<pubDate>Wed, 19 Dec 2007 04:25:17 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[technology]]></category>
		<category><![CDATA[computers]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://flagrantdisregard.com/index.php/2007/12/18/bye-bye-scriptaculous-hello-mootools/</guid>
		<description><![CDATA[I&#8217;ve just finished swapping out the Javascript library used on BigHugeLabs.com from Prototype/Script.aculo.us (P+S) to MooTools and I thought I&#8217;d share my reasons as well as my impressions for the benefit of any other developers thinking of following a similar path. A little background&#8230; BigHugeLabs.com allows visitors to use dozens of &#8220;toys&#8221; to make fun [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just finished swapping out the Javascript library used on <a href="http://bighugelabs.com/">BigHugeLabs.com</a> from <a href="http://www.prototypejs.org/">Prototype</a>/<a href="http://script.aculo.us/">Script.aculo.us</a> (P+S) to <a href="http://mootools.net/">MooTools</a> and I thought I&#8217;d share my reasons as well as my impressions for the benefit of any other developers thinking of following a similar path.</p>
<p><span id="more-849"></span></p>
<h3>A little background&#8230;</h3>
<p>BigHugeLabs.com allows visitors to use dozens of &#8220;toys&#8221; to make fun projects out of their digital photos. On any given day it is visited by around 40,000 people and approximately 40% of those are first-time visitors.</p>
<h3>Why switch?</h3>
<p>I really like Prototype and Script.aculo.us but my main problem with both of them is their bulk. They just do way more than I need. The entire P+S stack (I was using version 1.6.5) comes in at over 250k. It&#8217;s monstrous and those 16,400 new users every day had to download the whole thing. I don&#8217;t even want to think about what the site was like for dial-up or mobile users.</p>
<p>I also have a strong dislike for the Script.aculo.us documentation wiki. &#8220;Clear&#8221; and &#8220;organized&#8221; are two adjectives I can&#8217;t imagine anyone using to describe it.</p>
<p>But a bigger problem with Script.aculo.us than the documentation is that the visual effects sometimes stutter and skip. Even the Script.aculo.us home page staggers and stutters into view as the page loads. In one case recently I was trying to simply slide a small DIV about 100 pixels down a full page. No matter what I tried, I just couldn&#8217;t get the effect to run smoothly. With MooTools, it just worked. Granted, it could have been pilot error, but the bottom line is that MooTools gave me exactly the result I wanted.</p>
<p>A final swaying factor were some of the built-in effects. In particular, I think the Bounce easing transition, Accordion, and Fx.Elements are awesome.</p>
<h3>Implementation</h3>
<p>Switching out the libraries was straightforward. MooTools uses similar syntax and has a 1:1 replacement for everything I was already doing with P+S (except one). Swapping libraries was a simple matter of searching for P+S code and swapping it with equivalent MooTools code. The one exception is that MooTools doesn&#8217;t implement Element.hide() or .show() out of the box. Fortunately, it&#8217;s a simple workaround (by extending the Element class, for example).</p>
<p>The entire conversion took about 12 hours spread over four days. That includes some extra time I took to rewrite the few XML proxies I had as JSON and refactoring where it presented itself. I thought about abstracting all of the MooTools Javascript into my own classes so that if I ever decided to switch frameworks again all of the code that would need to change would be in one location. But I was already finished with the entire conversion before that thought got any traction. Anyway, it would have probably tripled the amount of work for a dubious payoff (I may never switch from MooTools).</p>
<h3>Final thoughts&#8230;</h3>
<p>All combined, the switch has allowed me to shave <b>190k</b> off of BigHugeLabs.com&#8217;s Javascript, shrinking it down to a much more reasonable 56k. That&#8217;s a savings of almost <b>3 gigabytes of transfer per day.</b> And the experience of first-time visitors should be improved as the site loads more quickly for them.</p>
<p>MooTools&#8217; superior <a href="http://docs.mootools.net/">documentation</a> and <a href="http://demos.mootools.net/">demos</a> made it a breeze to pick up. It&#8217;s not perfect, but most everything works as advertised.</p>
<p>From a construction perspective, working with it <em>just feels better</em> to me than P+S. It&#8217;s a subtle point but MooTools just seems to be a better fit for my style.</p>
]]></content:encoded>
			<wfw:commentRss>http://flagrantdisregard.com/bye-bye-scriptaculous-hello-mootools/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Dear Rookie Web Developer</title>
		<link>http://flagrantdisregard.com/dear-rookie-web-developer/</link>
		<comments>http://flagrantdisregard.com/dear-rookie-web-developer/#comments</comments>
		<pubDate>Fri, 18 May 2007 16:31:54 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[technology]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://flagrantdisregard.com/index.php/2007/05/18/dear-rookie-web-developer/</guid>
		<description><![CDATA[Dear Rookie Web Developer, I had the task recently of taking over a project from a group of developers (who shall remain nameless) who were unable to finish it. When I saw what they had written, I could see why. The project had clearly been assigned to inexperienced, junior-level developers who did not have the [...]]]></description>
			<content:encoded><![CDATA[<p>Dear Rookie Web Developer,</p>
<p>I had the task recently of taking over a project from a group of developers (who shall remain nameless) who were unable to finish it. When I saw what they had written, I could see why. The project had clearly been assigned to inexperienced, junior-level developers who did not have the guidance of an experienced mentor. For the benefit of other rookies, I offer this advice, based on problems I found in that project:</p>
<ul>
<li>Your professional reputation among your peers will be based on the quality of the code you write.</li>
<li>Don&#8217;t litter code with comments telling me what you changed. That&#8217;s what diff is for.</li>
<li>     Don&#8217;t comment out sections of code and tell me you deleted them. If you want to delete something, please delete it.</li>
<li>     Poor spelling and grammar are signs of a programmer who doesn&#8217;t care about details. Care.</li>
<li>     Never make a change to something just because it <span style="font-style: italic">looks</span> wrong&#8212;especially to mature code that has been in production for years. It looks wrong for a very good reason and you will break something if you change it.</li>
<li>     I really don&#8217;t care how you indent or use braces but please be consistent.</li>
<li>     Don&#8217;t leave comments explaining the obvious. I can read code.</li>
<li>Please learn how to use an image editor. You don&#8217;t need to take a Photoshop class. Just learn how to slice, choose the right image format and compression, and how to get anti-aliasing right for graphics that will appear on a given background.</li>
<li>     If you are duplicating a snippet of code throughout your project, you are doing it wrong.</li>
<li> Doing something the &#8220;easy&#8221; way today will cost you 10x what it would have cost to do it right in the first place. And I&#8217;m being optimistic. Be lazy for the long-term.</li>
<li> Learn CSS and the correct way to name your classes and IDs. And I don&#8217;t mean learn just enough to get by. It&#8217;s as important as any other code in your project whether it&#8217;s Ruby or PHP or C.</li>
<li>     Learn SQL. Inefficient SQL queries will kill your project.</li>
<li>     More hardware may not be the best solution. Your app is slow because of inefficient code.</li>
<li>     Cross-browser compatibility is no longer a holy grail. It is a minimum requirement and it is not difficult.</li>
</ul>
<p>Sincerely,</p>
<p>John</p>
]]></content:encoded>
			<wfw:commentRss>http://flagrantdisregard.com/dear-rookie-web-developer/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Hypnotized by blue flashy lights at the Microsoft conference</title>
		<link>http://flagrantdisregard.com/hypnotized-by-blue-flashy-lights-at-the-microsoft-conference/</link>
		<comments>http://flagrantdisregard.com/hypnotized-by-blue-flashy-lights-at-the-microsoft-conference/#comments</comments>
		<pubDate>Thu, 15 Dec 2005 01:44:09 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[technology]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://flagrantdisregard.com/?p=494</guid>
		<description><![CDATA[I went to the Microsoft Visual Studio 2005 &#8220;Launch Event&#8221; at the local convention center last week. It was pretty typical for these types of events. Lots of marketing in the guise of technical product demonstrations and the promise of a free lunch. The theme was &#8220;rock and roll.&#8221; The keynote ended with two 30 [...]]]></description>
			<content:encoded><![CDATA[<p>I went to the Microsoft Visual Studio 2005 &#8220;Launch Event&#8221; at the local convention center last week.  It was pretty typical for these types of events.  Lots of marketing in the guise of technical product demonstrations and the promise of a free lunch.  The theme was &#8220;rock and roll.&#8221;  The keynote ended with two 30 foot screens, one on each side of the stage, showing &#8220;READY to ROCK the LAUNCH&#8221; while <a href="http://www.rush.com/">Rush</a> (Tom Sawyer, naturally) blasted through the theater.  Rush.</p>
<p>As if grungy graphics and loud music was going to turn 4,000 nerds into rock stars.</p>
<p>Lots of people had visited the smallish vendor area and got some kind of neon blue flashy light thing.  Some of them were wearing it around their necks and some of them just had it in their transparent conference bags.  It&#8217;s good marketing.  It instantly got attention from everyone who saw it.  But it&#8217;s kind of sad, isn&#8217;t it?  That all these allegedly smart people can be lured to a vendor booth by a couple of blinky lights like some kind of prize bass.  The sales droids at the booth should have been sporting fishing poles and hip waders and kept the flashy things in a tackle box.</p>
]]></content:encoded>
			<wfw:commentRss>http://flagrantdisregard.com/hypnotized-by-blue-flashy-lights-at-the-microsoft-conference/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Gaim Message Blocker plugin</title>
		<link>http://flagrantdisregard.com/gaim-message-blocker-plugin/</link>
		<comments>http://flagrantdisregard.com/gaim-message-blocker-plugin/#comments</comments>
		<pubDate>Fri, 29 Oct 2004 07:00:33 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[technology]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://flagrantdisregard.com/index.php?p=276</guid>
		<description><![CDATA[I just released a plugin for Gaim 1.0.2 that blocks arbitrary instant messages based on a set of filters that you can define. I created it to block the extremely annoying &#8220;AOL System Msg: Your screen name (x) is now signed into AOL(R) Instant Messenger(TM) in 2 locations.&#8221; You can download it from the Gaim [...]]]></description>
			<content:encoded><![CDATA[<p>I just released a plugin for <a href="http://gaim.sourceforge.net/">Gaim 1.0.2</a> that blocks arbitrary instant messages based on a set of filters that you can define.  I created it to block the extremely annoying &#8220;AOL System Msg: Your screen name (x) is now signed into AOL(R) Instant Messenger(TM) in 2 locations.&#8221;  You can download it from the <a href="http://sourceforge.net/tracker/index.php?func=detail&#038;aid=1056585&#038;group_id=235&#038;atid=390395">Gaim Sourceforge plugin tracker</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://flagrantdisregard.com/gaim-message-blocker-plugin/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Dealing with comment spam</title>
		<link>http://flagrantdisregard.com/dealing-with-comment-spam/</link>
		<comments>http://flagrantdisregard.com/dealing-with-comment-spam/#comments</comments>
		<pubDate>Thu, 21 Oct 2004 20:19:52 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[blogging]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://flagrantdisregard.com/index.php?p=267</guid>
		<description><![CDATA[This is a message I sent to the WordPress hackers mailing list today: Subject: New(?) anti-spam technique I&#8217;ve seen an increase in comment spam the last couple of days. This particular species looks a lot like legitimate comments in that it isn&#8217;t riddled with links, the comment text is not advertising, and it isn&#8217;t anonymous. [...]]]></description>
			<content:encoded><![CDATA[<p>This is a message I sent to the <a href="http://wordpress.org/mailman/listinfo/hackers_wordpress.org">WordPress hackers</a> mailing list today:</p>
<p>Subject: New(?) anti-spam technique</p>
<p>I&#8217;ve seen an increase in comment spam the last couple of days. This particular species looks a lot like legitimate comments in that it isn&#8217;t riddled with links, the comment text is not advertising, and it isn&#8217;t anonymous. Of course, the email address is fake and the spam comes from dozens, probably hundreds, of different IP addresses. Flood control was the only thing keeping it in check. The blacklist worked for a little while but then the spam would change and I&#8217;d have to update the blacklist again. So.<br />
<span id="more-267"></span><br />
The first thing I did was check my logs and noticed that the bot was posting directly to wp-comments-post.php with no referrer. So, this took care of the problem immediately (in wp-comments-post.php):</p>
<p><code>// Anti-spam<br />
// Prevent posting directly to this page without having come from another page<br />
// on this site.<br />
$siteurl = strtolower(get_settings('siteurl'));<br />
$referer = strtolower($_SERVER['HTTP_REFERER']);<br />
if ( strpos($referer, $siteurl) === false ) {<br />
&nbsp;&nbsp;// I chose this action because I don't want to give a spammer any clues.<br />
&nbsp;&nbsp;die();<br />
}</code></p>
<p>This works <strong>for now</strong> but since HTTP_REFERER is ridiculously easy to spoof it probably won&#8217;t work for long. I&#8217;m a little surprised that spam bots aren&#8217;t sophisticated enough to do this already.</p>
<p>So, that took care of the immediate problem but I wanted a more long term solution. Captchas came to mind immediately but I dislike captchas because they require legitimate commenters to jump through hoops. I remembered the discussion <a href="http://wordpress.org/pipermail/hackers_wordpress.org/2004-September/002006.html">Kitty</a> started last month about putting a unique hash in the page that must be posted back when the form is submitted. This is a good idea, and I implemented it, but it is also easy for a bot programmer to circumvent since all of the information you need to circumvent it is right there in the form. I made it a little more complicated by requiring the client to compute an md5 hash of the comment + post title and post that back as well (Javascript can do this nicely). But, while that makes a spammer jump through more hoops, once they&#8217;ve done that we&#8217;re back where we started again.</p>
<p>Unsatisfied, I tried <a href="http://www.hashcash.org/">&#8220;hashcash&#8221;</a>. Hashcash is a clever technique that requires the client to expend a certain amount of work computing a &#8220;stamp&#8221;. It requires 2-3 seconds to compute a hashcash stamp, it can&#8217;t be faked, and it takes a trivial amount of time to verify. This delay is no problem for a reader submitting a single comment but is a huge drain on a spammer who wants to post hundreds of comments a second. And if you use date, post_id, server address, and remote address as the stamp seed then the spammer has to compute a new stamp for every post on every server every day. I implemented this as well, in Javascript, but unfortunately Javascript is too slow to compute stamps in a reasonable amount of time. I found that a 16-bit collision takes much too long to compute in Javascript but it only takes a fraction of a second in C which is probably more like what spammers would use (even 12-bit collisions are barely possible with Javascript). I chose Javascript because I wanted the requirements burden on the client to be as low as possible (Java, Flash, ActiveX are all unnacceptable requirements for posting comments). Here&#8217;s something like the algorithm I implemented:</p>
<p>The form onsubmit action would call something like this:</p>
<p><code>function hashcash() {<br />
&nbsp;&nbsp;stampseed1 = 'some combination of date + post id + server address + remote address';<br />
&nbsp;&nbsp;stampseed2 = 0;<br />
&nbsp;&nbsp;while(true) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;hash = hex_md5(stampseed1 + stampseed2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (hash.substr(0,4) == "0000") { // Look for a 16-bit collision<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.getElementById('commentform').stamp.value = stampseed2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;stampseed2++;<br />
&nbsp;&nbsp;}<br />
}<br />
</code></p>
<p>And then wp-comments-post.php would just need to substr(md5(some combination of date + post id + server address + remote address + $_POST['stamp']), 0, 4) == &#8220;0000&#8243; to verify the stamp.</p>
<p>I still like this idea the best, even though I abandonded it. If Javascript could compute these faster then it would be a viable solution.</p>
<p>Then it occurred to me that one way to tell humans from bots is that humans are much slower. This is what I came up with:</p>
<ul>
<li>When a client hits the comment form, start a timer. Start a unique timer for each client (by IP address or some other method).</li>
<li>When the client posts the form, check the timer. If the time elapsed is less than 3 seconds or more than 5 minutes (the &#8220;window&#8221;), moderate the comment.</li>
<li>Delete the timer.</li>
</ul>
<p>Here&#8217;s how I implemented it:</p>
<p><code>[1] At the top of wp-comments.php:<br />
&nbsp;&nbsp;$_SESSION['CommentTimer_'.$_SERVER['REMOTE_ADDR']] = time();<br />
</code><br />
<code>[2] In wp-comments-post.php after check_comment():<br />
&nbsp;&nbsp;if (!isset($_SESSION['CommentTimer_'.$_SERVER['REMOTE_ADDR']])<br />
&nbsp;&nbsp;|| time()-$_SESSION['CommentTimer_'.$_SERVER['REMOTE_ADDR']] &lt; 3<br />
&nbsp;&nbsp;|| time()-$_SESSION['CommentTimer_'.$_SERVER['REMOTE_ADDR']] &gt; 300) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;$approved = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;$comment = "** COMMENT TIMER SPAM **\n".$comment;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;unset($_SESSION['CommentTimer_'.$_SERVER['REMOTE_ADDR']]);<br />
</code><br />
<code>[3] In wp-config.php:<br />
&nbsp;&nbsp;session_start();<br />
</code></p>
<p>This is simple, completely server-side, and transparent to readers. It has zero client-side requirements other than you take a couple of seconds to enter your comment. It busts spambots that spoof IPs on every request, that don&#8217;t use the form, and that don&#8217;t wait. I used $_SESSION for this quick implementation but there is no reason why you couldn&#8217;t store the timers in a database table. You&#8217;d just need to clean out old timers occassionally (perhaps automatically each time the admin went to comment moderation). Also, these could probably be wrapped in existing function calls so templates wouldn&#8217;t have to be modified (for example, embedding [2] in check_comment()).</p>
<p>So far it has stopped my spam completely. The main drawback that comes to mind is that it requires the client to have a stable IP address during a session, so it might be a problem for people with certain ISPs (AOL?).  This can be gotten around by using cookie based identification but then it doesn&#8217;t work for people who won&#8217;t accept cookies.  This method is partially defeatable too. Defeating this method requires a bot to: </p>
<p>Hit/Wait/Post cycle:</p>
<ul>
<li>Hit hundreds of comment forms on different sites.</li>
<li>Hit them all again within the window to post the comment.</li>
<li>Repeat.</li>
</ul>
<p>I say partially because, while the above spamming technique will post the spam, it should drastically slow down the spammer and thus reduce the number of sites he can cover thus reducing the spread of spam. If this is widely implemented, you will be less likely to even encounter spam because fewer spammers will even be able to get to your site in their lists.</p>
<p>Assume:</p>
<ul>
<li>The spambot has 100,000 wp-comment-post.php entries in its index</li>
<li>Each of those blogs implements a 10-second flood control</li>
<li>The spammer can currently post to them all in 10 seconds</li>
</ul>
<p>A naive spam bot would Hit/Wait/Post each post reducing its output from 100,000 posts/10 seconds to 1 post/3 seconds. Even if he has a network of zombie machines doing his bidding, each zombie doing naive Hit/Wait/Post would be reduced to 1 post/3 seconds. 100 zombies in aggregate would be able to do 100 posts/3 seconds.</p>
<p>A more sophisticated circumvention would be to hit them all once (10 seconds), then hit them all again (10 seconds), reducing the output to 100,000 spams every 20 seconds.  But using this technique, if a spambot has millions of posts in his index, then by the time it got around to do the second hit it might have fallen outside of the window.</p>
<p>Another technique would be to start multiple threads on the same spamming machine that do Hit/Wait/Post. A machine that could start 100,000 threads in 10 seconds would be reduced to 100,000 posts/13 seconds. But I don&#8217;t think 100,000 threads on a single machine in 10 seconds is feasible (is it?). If he could start 100 threads then he would be reduced to 100 posts/3 seconds. If a zombie network using this technique split up the 100,000 posts among 100 machines and each machine could do 100,000 posts/10 seconds then they could do all 100,000 posts in just over 3 seconds (vs. 0.1 seconds without the comment timer).</p>
<p>Someone check my math?  :-)</p>
<p>But is this the general case? This spammer appeared to be coming from hundreds of different IP addresses, but I wonder if he really had access to a zombie network or if he was just using IP spoofing from a single machine.</p>
]]></content:encoded>
			<wfw:commentRss>http://flagrantdisregard.com/dealing-with-comment-spam/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Word Statistics plugin for WordPress</title>
		<link>http://flagrantdisregard.com/wordstats-plugin-for-wordpress/</link>
		<comments>http://flagrantdisregard.com/wordstats-plugin-for-wordpress/#comments</comments>
		<pubDate>Wed, 01 Sep 2004 09:20:16 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[blogging]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://flagrantdisregard.com/index.php?p=200</guid>
		<description><![CDATA[I&#8217;ve created a plugin called Word Statistics for WordPress 1.2 2.0 that displays readability statistics on the post editing screen whenever a post is edited or saved (and you continue editing). The plugin also provides similar functionality to the MovableType plugin MTWordStats. I&#8217;ve never used MT or tried the MTWordStats plugin so I can&#8217;t really [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve created a plugin called <a href="http://flagrantdisregard.com/wordstats/">Word Statistics</a> for WordPress <strike>1.2</strike> 2.0 that displays readability statistics on the post editing screen whenever a post is edited or saved (and you continue editing).  The plugin also provides similar functionality to the MovableType plugin <a href="http://mt-plugins.org/local/wordstats.php">MTWordStats</a>.  I&#8217;ve never used MT or tried the MTWordStats plugin so I can&#8217;t really say how the two compare.</p>
<p><strong>Update 12/30/2005:</strong> A new version has just been released that is compatible with WordPress 2.0. The older version is still available and works with versions prior to 2.0.</p>
]]></content:encoded>
			<wfw:commentRss>http://flagrantdisregard.com/wordstats-plugin-for-wordpress/feed/</wfw:commentRss>
		<slash:comments>40</slash:comments>
		</item>
	</channel>
</rss>

