<?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>Ardamis &#187; WordPress</title>
	<atom:link href="http://www.ardamis.com/category/wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ardamis.com</link>
	<description>Ardamis is a blog about web development and technology in general.</description>
	<lastBuildDate>Thu, 02 Feb 2012 07:07:02 +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>Ardamis in 2012 &#8211; new look, more microdata, faster code</title>
		<link>http://www.ardamis.com/2012/01/22/ardamis-2012/</link>
		<comments>http://www.ardamis.com/2012/01/22/ardamis-2012/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 05:50:02 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Google]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[comment spam]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[themes]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=1863</guid>
		<description><![CDATA[Ardamis.com is starting out 2012 with a new look, better structured data markup, and a revamped anti-spam system.]]></description>
			<content:encoded><![CDATA[<p>Just a few weeks behind schedule, but a long time in the works, I&#8217;ve finally pushed the new WordPress theme for Ardamis live.  Basic and elegant (I&#8217;m trying to establish a trend here), the theme also should outperform its predecessors in both page load times and SEO-potential.  The index and archive pages should appear more consistent, and all pages should provide more complete structured data markup (<a href="http://schema.org/">schema.org</a> as well as <a href="http://microformats.org/wiki/existing-classes">microformats.org</a>).  The comment form has been outfitted with <a href="http://www.ardamis.com/2011/08/27/a-cache-proof-method-for-reducing-comment-spam/">an improved approach to reducing comment spam</a>.</p>
<p>The new theme is pretty light on the graphics, due to increased browser support for and subsequently greater use of CSS3 goodness for box shadows and gradients.  I&#8217;ve reduced the number of image files to two: a background and a sprites file.</p>
<p>Only half-implemented in the previous theme, the new look, &#8220;Joy&#8221;, makes much better use of structured data markup, or <a href="http://en.wikipedia.org/wiki/Microdata_(HTML)">microdata</a>.  Google is absolutely looking for ways to display your pages&#8217; semantic markup in its results, so you may as well get on board.</p>
<p>The frequency of spam comments increased dramatically over the past two months, according to my Akismet stats, so I&#8217;ve gone back to the drawing board and developed a better front-line defense against them.  The new method should be more opaque to bots that parse JavaScript while still being invisible to human visitors leaving legitimate comments.</p>
<p>In sum, I think Ardamis should be leaner, faster, and smarter (and maybe prettier) in 2012 than ever before.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2012/01/22/ardamis-2012/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A cache-friendly method for reducing WordPress comment spam</title>
		<link>http://www.ardamis.com/2011/08/27/a-cache-proof-method-for-reducing-comment-spam/</link>
		<comments>http://www.ardamis.com/2011/08/27/a-cache-proof-method-for-reducing-comment-spam/#comments</comments>
		<pubDate>Sat, 27 Aug 2011 08:34:53 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Nonsense]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[comment spam]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[spam]]></category>
		<category><![CDATA[templates]]></category>
		<category><![CDATA[themes]]></category>
		<category><![CDATA[web app]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=1673</guid>
		<description><![CDATA[A safe-for-cached-pages method of filtering out spam comments by requiring at least some time to have passed between the time the page is loaded and the form is submitted.]]></description>
			<content:encoded><![CDATA[<p>In the endless battle against WordPress comment spam, I&#8217;ve developed and then refined a few different methods for preventing spam from getting to the database to begin with.  My philosophy has always been that a human visitor and a spam bot behave differently (after all, we&#8217;re not dealing with <a href="http://en.wikipedia.org/wiki/Do_Androids_Dream_of_Electric_Sheep%3F#Androids">Nexus-6 model androids</a> here), and an effective spam-prevention method should be able to recognize the differences.  I also have a dislike for CAPTCHA methods that require a human visitor to <em>prove</em>, via an intentionally difficult test, that they aren&#8217;t a bot.  The ideal method, I feel, would be invisible to a human visitor, but still accurately identify comments submitted by bots.</p>
<h2>A history of spam fighting</h2>
<p>The most successful and simple method I found was a server-side system for <a href="http://www.ardamis.com/2007/12/15/using-timestamps-to-reduce-wordpress-comment-spam/">reducing comment spam by using a handshake method involving timestamps</a> on hidden form fields.  The general idea was that a bot would submit a comment more quickly than a human visitor, so if the comment was submitted too soon after the page was loaded, it was rejected.  A human caught in this trap would be able to click the Back button on the browser to resubmit.  This had proven to be very effective on ardamis.com, cutting the number of <a href="http://www.ardamis.com/2010/08/09/reducing-wordpress-spam-comments/">spam comments intercepted by Akismet per day to nearly zero</a>.  For a long time, the only problem was that it required modifying a core WordPress file, <strong>wp-comments-post.php</strong>.  Each time WordPress was updated, the core file was replaced.  If I didn&#8217;t then go back and make my modifications again, <a href="http://www.ardamis.com/2011/01/18/a-chart-illustrating-the-reduction-in-comment-spam-at-ardamis-com/">I would lose the spam protection</a> until I made the changes.  As it became easier to update WordPress (via the admin panel) and I updated it more frequently, editing the core file became more of a nuisance.</p>
<h2>A huge facepalm</h2>
<p>When Google began weighting page load times as part of its ranking algorithm, I implemented the <a href="http://wordpress.org/extend/plugins/wp-super-cache/" title="WP Super Cache">WP Super Cache</a> caching plugin on ardamis.com and configured it to use .htaccess and mod_rewrite to serve cache files.  Page load times certainly decreased, but the amount of spam detected by Akismet increased.  After a while, I realized that this was because the spam bots were submitting comments from static, cached pages, and the timestamps on those pages, which had been generated server-side with PHP, were already minutes old when the page was requested.  The form processing script, which normally rejects comments that are submitted too quickly to be written by a human visitor, happily accepted the timestamps.  Even worse, a second function of my anti-spam method also rejected comments that were submitted 10 minutes or more after the page was loaded.  Of course, most of the visitors were being served cached pages that were already more than 10 minutes old, so even legitimate comments were being rejected.  Using PHP to generate my timestamps obviously was not going to work if I wanted to keep serving cached pages.</p>
<h2>JavaScript to the rescue</h2>
<p>Generating real-time timestamps on cached pages requires JavaScript.  But instead of a reliable server clock setting the timestamp, the time is coming from the visitor&#8217;s system, which can&#8217;t be trusted to be accurate.  Merely changing the comment form to use JavaScript to generate the first timestamp wouldn&#8217;t work, because verifying a timestamp generated on the client-side against one generated with a server-side language would be disastrous.</p>
<p>Replacing the PHP-generated timestamps with JavaScript-generated timestamps would require substantial changes to the system.</p>
<p>Traditional client-side form validation using JavaScript happens when the form is submitted.  If the validation fails, the form is not submitted, and the visitor typically gets an alert with suggestions on how to make the form acceptable.  If the validation passes, the form submission continues without bothering the visitor.  To get our two timestamps, we can generate a first timestamp when the page loads and compare it to a second timestamp generated when the form is submitted.  If the visitor submits the form too quickly, we can display an alert showing the number of seconds remaining until the form can be successfully submitted.  This should hopefully be invisible to most visitors who choose to leave comments, but at the very least, far less irritating than a CAPTCHA system.</p>
<p>It took me two tries to get it right, but I&#8217;m going to discuss the less successful method first to point out its flaws.</p>
<h3>Method One (not good enough)</h3>
<p>Here&#8217;s how the original system flowed.</p>
<ol>
<li>Generate a first JS timestamp when the page is loaded.</li>
<li>Generate a second JS timestamp when the form is submitted.</li>
<li>Before the form is submitted, compare the two, and if enough time has passed, write a pre-determined passcode to a hidden INPUT element, then submit the form.</li>
<li>On the form processing page, use server-side logic to verify that the passcode is present and valid.</li>
</ol>
<p>The problem was that it seemed that certain bots could parse JavaScript enough to drop the pre-determined passcode into the hidden form field before submitting the form, circumventing the timestamps completely and defeating the system.  </p>
<p>It also failed to adhere to one of the basic tenants of form validation &#8211; that the input must be checked on both the client-side and the server-side.</p>
<h3>Method Two (better)</h3>
<p>Rather than having the server-side validation be merely a check to confirm that the passcode is present, method two goes back to comparing the timestamps a second time on the server side. Instead of a single hidden input, we now have two &#8211; one for each timestamp.  This is intended to prevent a bot from figuring out the ultimate validation mechanism by simply parsing the JavaScript.  Finally, the hidden fields are added to the form via jQuery, which makes it easier to implement and may act as another layer of obfuscation. </p>
<ol>
<li>Generate a first JS timestamp when the page is loaded and write it to a hidden form field.</li>
<li>Generate a second JS timestamp when the form is submitted and write it to a hidden form field.</li>
<li>Before the form is submitted, compare the two, and if enough time has passed, submit the form (client-side validation).</li>
<li>On the form processing page, use server-side logic to compare the timestamps a second time (server-side validation).</li>
</ol>
<p>The timestamp handshake works more like it did in the server-side-only method.  We still have to pass something from the comment form to the processing script, but it&#8217;s not too obvious from the HTML what is being done with it.</p>
<h2>The same downside plagues me</h2>
<p>Unfortunately, if we want to have any server-side validation at all, and we do, the core file <strong>wp-comments-post.php</strong> will still have to be modified.  In my experience, the system is not sufficiently effective using just client-side validation.  </p>
<h2>The code</h2>
<p>Two files must be modified to implement the validation.</p>
<p><strong>File 1: The theme&#8217;s comments.php file (older themes) or wp-includes\comment-template.php (newer themes)</strong></p>
<p>Your comment form lives somewhere.  My theme is based on Kubrick, the old default WordPress theme, and my comment form is in my theme folder, in a file named <strong>comments.php</strong>.  If your theme is newer and based on the current default theme, twentyeleven, the form is in <strong>wp-includes\comment-template.php</strong>.  If your theme isn&#8217;t based on either of these, all bets are off.  I know it&#8217;s confusing.  Sorry.</p>
<p>Add the JavaScript that creates and populates the timestamp fields.  Be sure to confirm that your comment form has an ID of <strong>commentform</strong>.  I&#8217;m using jQuery to help fire functions when the page loads.</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
$(document).ready(function(){
	ardGenTS1();
});

function ardGenTS1() {
	// prepare the form
	$('#commentform').append('&lt;input type=&quot;hidden&quot; name=&quot;ardTS1&quot; id=&quot;ardTS1&quot; value=&quot;1&quot; /&gt;');
	$('#commentform').append('&lt;input type=&quot;hidden&quot; name=&quot;ardTS2&quot; id=&quot;ardTS2&quot; value=&quot;1&quot; /&gt;');
	$('#commentform').attr('onsubmit', 'return validate()');
	// set a first timestamp when the page loads
	var ardTS1 = (new Date).getTime();
	document.getElementById(&quot;ardTS1&quot;).value = ardTS1;
}

function validate() {
	// read the first timestamp
	var ardTS1 = document.getElementById(&quot;ardTS1&quot;).value;
//	alert ('ardTS1: ' + ardTS1);
	// generate the second timestamp
	var ardTS2 = (new Date).getTime();
	document.getElementById(&quot;ardTS2&quot;).value = ardTS2;
//	alert ('ardTS2: ' + document.getElementById(&quot;ardTS2&quot;).value);
	// find the difference
	var diff = ardTS2 - ardTS1;
	var elapsed = Math.round(diff / 1000);
	var remaining = 10 - elapsed;
//	alert ('diff: ' + diff + '\n\nelapsed:' + elapsed);
	// check whether enough time has elapsed
	if (diff &gt; 10000) {
		// submit the form
		return true;
	}else{
		// display an alert if the form is submitted within 10 seconds
		alert(&quot;This site is protected by an anti-spam feature that requires 10 seconds to have elapsed between the page load and the form submission.\n\nPlease close this alert window.  The form may be resubmitted successfully in &quot; + remaining + &quot; seconds.&quot;);
		// prevent the form from being submitted
		return false;
	}
}
&lt;/script&gt;
</pre>
<p><strong>File 2: The wp-comments-post.php file</strong></p>
<p>The wp-comments-post.php file lives in the root of WordPress and handles the form processing.  We need to add a few lines that check the contents of our new validation input field.</p>
<p>Somewhere after line 53 or so (where <em>$comment_content</em> is defined), insert the following code.</p>
<pre class="brush: php; title: ; notranslate">
$ardTS1 = ( isset($_POST['ardTS1']) ) ? trim($_POST['ardTS1']) : 1;
$ardTS2 = ( isset($_POST['ardTS2']) ) ? trim($_POST['ardTS2']) : 2;
$ardTS = $ardTS2 - $ardTS1;

if ( $ardTS &lt; 10000 ) {
// If the difference of the timestamps is not more than 10 seconds, exit
    wp_die( __('&lt;strong&gt;ERROR&lt;/strong&gt;:  This site uses JavaScript validation to reduce comment spam.  Either your browser has JavaScript disabled, or the comment was not legitimately submitted.') );
}
</pre>
<p>That&#8217;s it.  Not so bad, right?</p>
<h2>Final thoughts</h2>
<p>One advantage to this method over the old PHP-only method is that even if the core file is replaced and the server-side validation is lost, the client-side validation continues to work, perhaps providing some measure of protection.</p>
<p>The method is safe for use with caching systems that create purely static, HTML pages.  I&#8217;ll follow up later and report on how effective it seems to be at stopping spam comments before they get to Akismet (and into the WordPress database).</p>
<p>Now, for a little extra protection, you can rename the <strong>wp-comments-post.php</strong> file and change the path in the comment form&#8217;s action attribute.  I&#8217;ve <a href="http://www.ardamis.com/2010/08/09/reducing-wordpress-spam-comments/">posted logs</a> showing that some bots just try to post spam directly to the <strong>wp-comments-post.php</strong> file, so renaming that file is an easy way to cut down on spam.  Just remember to come back and delete the <strong>wp-comments-post.php</strong> file each time you update WordPress.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2011/08/27/a-cache-proof-method-for-reducing-comment-spam/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to fix the &#8220;PHP Fatal error:  Call to undefined function  get_header()&#8221; error in WordPress</title>
		<link>http://www.ardamis.com/2011/06/02/fix-for-php-fatal-error-get_header-in-wordpress/</link>
		<comments>http://www.ardamis.com/2011/06/02/fix-for-php-fatal-error-get_header-in-wordpress/#comments</comments>
		<pubDate>Thu, 02 Jun 2011 17:07:13 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[500 error]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[themes]]></category>
		<category><![CDATA[troubleshooting]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=1430</guid>
		<description><![CDATA[Fix the "PHP Fatal error: Call to undefined function get_header()" error in WordPress.]]></description>
			<content:encoded><![CDATA[<p>While making changes to my WordPress theme, I noticed that the error_log file in my theme folder contained dozens of PHP Fatal error lines:</p>
<pre class="brush: plain; title: ; notranslate">
...
[01-Jun-2011 14:25:15] PHP Fatal error:  Call to undefined function  get_header() in /home/accountname/public_html/ardamis.com/wp-content/themes/ars/index.php on line 7
[01-Jun-2011 20:58:23] PHP Fatal error:  Call to undefined function  get_header() in /home/accountname/public_html/ardamis.com/wp-content/themes/ars/index.php on line 7
...
</pre>
<p>The first seven lines of my theme&#8217;s index.php file:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php ini_set('display_errors', 0); ?&gt;
&lt;?php
/**
 * @package WordPress
 * @subpackage Ars_Theme
*/
get_header(); ?&gt;
</pre>
<p>I realized that the error was being generated each time that my theme&#8217;s index.php file was called directly, and that the error was caused by the theme&#8217;s inability to locate the WordPress <strong>get_header</strong> function (which is completely normal).  Thankfully, the descriptive error wasn&#8217;t being output to the browser, but was only being logged to the error_log file, due to the inclusion of the <strong>ini_set(&#8216;display_errors&#8217;, 0);</strong> line.  I had learned this the hard way a few months ago when I found that calling the theme&#8217;s index.php file directly would generate an error message, output to the browser, that would reveal my hosting account username as part of the absolute path to the file throwing the error.</p>
<p>I decided the best way to handle this would be to check to see if the file could find the <strong>get_header</strong> function, and if it could not, simply redirect the visitor to the site&#8217;s home page.  The code I used to do this:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php ini_set('display_errors', 0); ?&gt;
&lt;?php
/**
* @package WordPress
* @subpackage Ars_Theme
*/
if (function_exists('get_header')) {
	get_header();
}else{
    /* Redirect browser */
    header(&quot;Location: http://&quot; . $_SERVER['HTTP_HOST'] . &quot;&quot;);
    /* Make sure that code below does not get executed when we redirect. */
    exit;
}; ?&gt;
</pre>
<p>So there you have it.  No more fatal errors due to <strong>get_header</strong> when loading the WordPress theme&#8217;s index.php file directly.  And if something else in the file should throw an error, <strong>ini_set(&#8216;display_errors&#8217;, 0);</strong> means it still won&#8217;t be sent to the browser.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2011/06/02/fix-for-php-fatal-error-get_header-in-wordpress/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Online tools for detecting malware on web sites</title>
		<link>http://www.ardamis.com/2011/05/07/detecting-malware-on-web-sites/</link>
		<comments>http://www.ardamis.com/2011/05/07/detecting-malware-on-web-sites/#comments</comments>
		<pubDate>Sat, 07 May 2011 18:48:22 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Nonsense]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=1275</guid>
		<description><![CDATA[Online tools for detecting infections on web sites and for identifying vulnerabilites.]]></description>
			<content:encoded><![CDATA[<p>Just a few notes to myself about monitoring web sites for infections/malware and potential vulnerabilities.</p>
<h2>Tools for detecting infections on web sites</h2>
<h3>Google Webmaster Tools</h3>
<p>Your first stop should be here, as I&#8217;ve personally witnessed alerts show up in Webmaster Tools, even when all the following tools gave the site a passing grade.  If your site is registered here, and Google finds weird pages on your site, an alert will appear.  You can also have the messages forwarded to your email account on file, by choosing the Forward option under the All Messages area of the Home page.</p>
<div id="attachment_1382" class="wp-caption aligncenter" style="width: 784px"><a href="http://www.ardamis.com/wp-content/uploads/2011/05/google-webmaster-tools-hack-alert.png"><img src="http://www.ardamis.com/wp-content/uploads/2011/05/google-webmaster-tools-hack-alert.png" alt="" title="google-webmaster-tools-hack-alert" width="774" height="435" class="size-full wp-image-1382" /></a><p class="wp-caption-text">Google Webmaster Tools Hack Alert</p></div>
<h3>Google Safe Browsing</h3>
<p>The Google Safe Browsing report for ardamis.com: <a href="http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=ardamis.com">http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=ardamis.com</a></p>
<h3>Norton Safe Web</h3>
<p><a href="https://safeweb.norton.com/">https://safeweb.norton.com/</a></p>
<p>The Norton Safe Web report for ardamis.com: <a href="https://safeweb.norton.com/report/show?url=ardamis.com">https://safeweb.norton.com/report/show?url=ardamis.com</a></p>
<h2>Tools for analyzing a site for vulnerabilities</h2>
<h3>Sucuri Site Check</h3>
<p><a href="http://sitecheck.sucuri.net/scanner/">http://sitecheck.sucuri.net/scanner/</a></p>
<p>The Sucuri report for ardamis.com: <a href="http://sitecheck.sucuri.net/scanner/?scan=www.ardamis.com">http://sitecheck.sucuri.net/scanner/?scan=www.ardamis.com</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2011/05/07/detecting-malware-on-web-sites/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sitelinks are back on Ardamis</title>
		<link>http://www.ardamis.com/2010/10/17/sitelinks-are-back-on-ardamis/</link>
		<comments>http://www.ardamis.com/2010/10/17/sitelinks-are-back-on-ardamis/#comments</comments>
		<pubDate>Mon, 18 Oct 2010 04:33:48 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Google]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[plugin]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=1079</guid>
		<description><![CDATA[Ardamis.com once again has three Google sitelinks, as it did in mid-2009, and is approaching two million inbound links.]]></description>
			<content:encoded><![CDATA[<p>As of early October, Ardamis.com has its Google sitelinks back.  I first noticed them back in July of 2009, when <a href="http://www.ardamis.com/2009/07/01/toolbar-page-rank-of-6-and-3-one-line-sitelinks/">Ardamis had a toolbar PageRank of 6</a>.  Changes to Google&#8217;s algorithm later cost the site the sitelinks and reduced the PR to 5, which is how the site has appeared for the last year or so.  Three months ago, in July of 2010 and one year after the sitelinks appeared, I noticed that all of the pages combined had over <a href="http://www.ardamis.com/2010/07/13/one-million-inbound-links/">one million inbound links</a>.</p>
<p>This is what a <a href="http://www.google.com/search?q=ardamis">Google search for ardamis</a> returns:</p>
<div id="attachment_1080" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.ardamis.com/wp-content/uploads/2010/10/ardamis-100310-sitelinks.png"><img src="http://www.ardamis.com/wp-content/uploads/2010/10/ardamis-100310-sitelinks.png" alt="Ardamis' Google sitelinks" title="ardamis-100310-sitelinks" width="500" height="414" class="size-full wp-image-1080" /></a><p class="wp-caption-text">Ardamis' Google sitelinks</p></div>
<p>The second result returned, <a href="http://www.ardamis.com/2010/03/12/final-fantasy-xiii-freezing-xbox-360/">Final Fantasy XIII freezing on Xbox 360</a>, is among my longest posts, has 91 comments, and enjoys some of the best inbound links of any page on the site, including from the <a href="http://forums.xbox.com/31685195/PrintPost.aspx">forums at Xbox.com</a>, <a href="http://kotaku.com/5494326/rumor-final-fantasy-xiii-ps3-has-freezing-issues">Kotaku</a> and <a href="http://www.gamesradar.com/ps3/final-fantasy-xiii/news/potentially-major-final-fantasy-xiii-freezing-issue-emerges/a-20100316104130477028/g-20060508175846527007">GamesRadar</a>.</p>
<p>The third result is my primary competition for the term <strong>ardamis</strong>, which briefly held the number one ranking a few months ago.   That site has some <a href="http://googlewebmastercentral.blogspot.com/2009/04/one-line-sitelinks.html">one-line site links</a>.</p>
<p>The actual mechanics of obtaining <a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&#038;answer=47334">sitelinks</a> remains a mystery, but there are plenty of people who are willing to speculate (and a few brave enough to promise they can deliver them for a price).</p>
<p>I&#8217;ve been posting more frequently, the site uses the <a href="http://wordpress.org/extend/plugins/wp-paginate/">WP-Paginate plugin</a> and according to <a href="http://www.google.com/webmasters/tools">Google&#8217;s Webmaster Tools</a>, the home page alone now has well over one million inbound links, but otherwise it&#8217;s been business as usual here.</p>
<div id="attachment_1081" class="wp-caption aligncenter" style="width: 511px"><a href="http://www.ardamis.com/wp-content/uploads/2010/10/ardamis-100310-inbound-links.png"><img src="http://www.ardamis.com/wp-content/uploads/2010/10/ardamis-100310-inbound-links.png" alt="Ardamis home page one million links" title="ardamis-100310-inbound-links" width="501" height="273" class="size-full wp-image-1081" /></a><p class="wp-caption-text">Over one million inbound links to the home page of Ardamis.com</p></div>
<p>I&#8217;m not going to speculate about how to get sitelinks or whether one or more of the changes in the last year was the catalyst, but Google does say to use descriptive and non-repetitive anchor and alt text in a site&#8217;s internal links and to keep important pages within a few clicks of the home page.  These are very basic, fundamental things that any site should do, but it bears repeating.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2010/10/17/sitelinks-are-back-on-ardamis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A massive reduction in the number of spam comments</title>
		<link>http://www.ardamis.com/2010/08/09/reducing-wordpress-spam-comments/</link>
		<comments>http://www.ardamis.com/2010/08/09/reducing-wordpress-spam-comments/#comments</comments>
		<pubDate>Mon, 09 Aug 2010 05:57:51 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[comment spam]]></category>
		<category><![CDATA[spam]]></category>
		<category><![CDATA[themes]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=920</guid>
		<description><![CDATA[How to reduce the number of spam comments that make it into your WordPress database without annoying your visitors.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve written a number of posts on ways to reduce the number of spam comments a blog receives.  In this post, I&#8217;ll revisit an old method that has almost completely stopped spam comments at ardamis.com before they get to the database.</p>
<p><a href="http://www.ardamis.com/2007/09/12/defeating-wordpress-comment-spam/">My first system</a> for blocking WordPress comment spam was an overly complex combination of JavaScript and a <a href="http://en.wikipedia.org/wiki/Challenge-response_authentication">challenge-response</a> to test that the comment was being submitted by a person.  The value of the action attribute in the form was not in the HTML when the page was loaded, so the form couldn&#8217;t be immediately submitted, then JavaScript was used to write the path to a renamed wp-comments-post.php file only after a certain user action was performed.  I was never really satisfied with it.  I didn&#8217;t like relying on JavaScript, I had doubts that any human being (meaning of any mental or physical capacity, speaking any language, etc.) could correctly answer the question, and I was concerned that <a href="http://blog.akismet.com/2009/02/04/make-commenting-easy/">any obstacle to submitting a form discourages legitimate commenting</a>.  </p>
<p>A few months later, I posted a simpler <a href="http://www.ardamis.com/2007/12/15/using-timestamps-to-reduce-wordpress-comment-spam/">timestamp method for reducing WordPress comment spam</a> that compares two timestamps and then rejects any form submission that occurrs within 60 seconds of the post page being loaded.  The visitor wasn&#8217;t bothered by an additional form field solely for anti-spam and there was no JavaScript involved.</p>
<p>Both methods were very effective at blocking spam before it made it to the database.  In the five months leading up to the implementation of the first method, Akismet was catching an average of 1418 spam comments per month.  In the first five months after these methods were put in place, Akismet was catching only 54 spam comments per month.  But I also noticed a reduction in legitimate comments, from an average of 26 per month to 20 per month, which led me to suspect that real visitors attempting to leave comments were being discouraged from doing so.</p>
<p>The timestamp method required changing a core file, which was overwritten each time WordPress was updated.  As time went on, I forgot to replace the file after upgrading WordPress, so the protection was lost and I once again had only Akismet blocking spam.  A few months later, while doing work on the database in an attempt to <a href="http://www.ardamis.com/2010/08/03/how-to-speed-up-wordpress/">speed up WordPress</a>, I happened to check my historical stats and found that Akismet had detected 4,144 comments in July, 2010.  Yikes.  It was time to revisit these old methods.</p>
<p>At 2:30 AM on August 1, 2010, I again implemented my timestamp method, but this time I also renamed the <strong>wp-comments-post.php</strong> file that processes the form.  I changed my theme&#8217;s <strong>comments.php</strong> file to submit the form to the new page, deleted the <strong>wp-comments-post.php</strong> file from the server and tested to make sure that comments could still be submitted.  And then I waited to see what would happen.</p>
<p>The effect was pretty amazing. The spam had almost completely stopped.</p>
<p>My Akismet stats look like this:</p>
<table>
<tr>
<th>Date</th>
<th>Spam</th>
</tr>
<tr>
<td>7.30.10</td>
<td>192</td>
</tr>
<tr class="even">
<td>7.31.10</td>
<td>196</td>
</tr>
<tr>
<td>8.1.10</td>
<td>32</td>
</tr>
<tr class="even">
<td>8.2.10</td>
<td>0</td>
</tr>
<tr>
<td>8.5.10</td>
<td>4</td>
</tr>
<tr class="even">
<td>8.8.10</td>
<td>4</td>
</tr>
<tr>
<td>8.10.10</td>
<td>4</td>
</tr>
<tr class="even">
<td>8.11.10</td>
<td>4</td>
</tr>
<tr>
<td>8.13.10</td>
<td>0</td>
</tr>
<tr class="even">
<td>8.14.10</td>
<td>0</td>
</tr>
</table>
<p>(I don&#8217;t know why so many dates in August are skipped in the log, but whatever.)</p>
<h2>Fast, but only partial protection</h2>
<p>The quick and easy way to reduce the number of spam comments that your WordPress blog receives is to merely change the location of the comment form processing script.</p>
<ol>
<li>Rename <strong>wp-comments-post.php</strong> to anything else.  I like using a string of <a href="https://www.grc.com/passwords.htm">random hexadecimal characters</a>, like: <strong>z1t0zVGuaCZEi.php</strong>.</li>
<li>Edit your current theme&#8217;s <strong>comments.php</strong> so that the form is submitted to this new file.</li>
<li>Upload these files to their respective directories, then delete the <strong>wp-comments-post.php</strong> file from your server.
</ol>
<p>This method works well to stop spam submitted by bots that assume the comment form processing script used by WordPress is always at the same location.  More advanced bots will read the actual location of the file from the <code>action</code> attribute of the <code>form</code> element, but that can be countered by using either the JavaScript or <a href="http://www.ardamis.com/2007/12/15/using-timestamps-to-reduce-wordpress-comment-spam/">timestamp method</a>.</p>
<h2>Access log analysis</h2>
<p>To illustrate the effectiveness of the renamed wp-comments-post file + timestamp check, below are some events from my 06 August 2010 access log.</p>
<h3>Bot defeated by renamed file alone</h3>
<p>Here is a form submission to the non-existent wp-comments-post file that occurs 2 seconds after the post page is requested.</p>
<pre>
173.242.112.44 - - [06/Aug/2010:23:21:37 -0700] "GET www.ardamis.com/2007/07/12/defeating-contact-form-spam/ HTTP/1.0" 200 32530 "http://www.google.com" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 8.50"
173.242.112.44 - - [06/Aug/2010:23:21:39 -0700] "POST www.ardamis.com/wp-comments-post.php HTTP/1.0" 404 15529 "http://www.ardamis.com/2007/07/12/defeating-contact-form-spam/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 8.50"
</pre>
<p>The bot is sent a 404 HTTP status code, which is widely understood to mean that the page isn&#8217;t there and you can stop asking for it.  But that doesn&#8217;t stop this bot!  Two minutes later, it&#8217;s back at another page, trying again.</p>
<pre>
173.242.112.44 - - [06/Aug/2010:23:23:01 -0700] "GET www.ardamis.com/2007/03/29/xbox-360-gamercard-wordpress-plugin/ HTTP/1.0" 200 101259 "http://www.google.com" "Opera/9.64(Windows NT 5.1; U; en) Presto/2.1.1"
173.242.112.44 - - [06/Aug/2010:23:23:05 -0700] "POST www.ardamis.com/wp-comments-post.php HTTP/1.0" 404 15529 "http://www.ardamis.com/2007/03/29/xbox-360-gamercard-wordpress-plugin/" "Opera/9.64(Windows NT 5.1; U; en) Presto/2.1.1"
</pre>
<p>Again, it gets a 404 back.  Some bots never learn. </p>
<h3>Bot defeated by timestamp check</h3>
<p>Here is a form submission to the renamed wp-comments-post file that occurs 4 seconds after the post page is requested.</p>
<pre>
91.201.66.6 - - [06/Aug/2010:23:30:41 -0700] "GET www.ardamis.com/2007/03/29/xbox-360-gamercard-wordpress-plugin/ HTTP/1.1" 200 21787 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729)"
91.201.66.6 - - [06/Aug/2010:23:30:45 -0700] "POST www.ardamis.com/wp-comments-post-timestamp-3.0.1.php HTTP/1.1" 500 1227 "http://www.ardamis.com/2007/03/29/xbox-360-gamercard-wordpress-plugin/" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729)"
</pre>
<p>The 500 HTTP header indicates that this submission was denied and the comment never made it to the database.  This access log doesn&#8217;t indicate which check stopped the POST (eg: the email validation or the timestamp function), but my money is on the timestamp.</p>
<p>Here&#8217;s another form submission to the renamed wp-comments-post file that occurs one second after the post page is requested.  Speed reader or bot?</p>
<pre>
95.220.185.210 - - [06/Aug/2010:23:56:54 -0700] "GET www.ardamis.com/2010/02/26/fixing-word-2007-add-in-issues/ HTTP/1.1" 200 23977 "-" "Opera/9.01 (Windows NT 5.0; U; en)"
95.220.185.210 - - [06/Aug/2010:23:56:55 -0700] "POST www.ardamis.com/wp-comments-post-timestamp-3.0.1.php HTTP/1.1" 500 1213 "http://www.ardamis.com/2010/02/26/fixing-word-2007-add-in-issues/" "Opera/9.01 (Windows NT 5.0; U; en)"
</pre>
<p>The submission is rejected.</p>
<h2>Taking the method even further</h2>
<p>To take this method even further, one could send a 200 OK header even when the comment is blocked, so the bots never know their mission failed.  But this seems unnecessary at this point, as it doesn&#8217;t appear that they change their behavior after being sent a 404 error, or that they try again after being sent a 500 error.  It also makes it harder to figure out from the access logs which comments were rejected and for what reason.</p>
<p>If you still want to do this, first implement the <a href="http://www.ardamis.com/2007/12/15/using-timestamps-to-reduce-wordpress-comment-spam/">timestamp method</a>, then make the following modifications.</p>
<h3>Sending a 200 header</h3>
<pre class="brush: php; title: ; notranslate">
$comment_timestamp    = trim($_POST['timestamp']);
$submitted_timestamp  = time();

if ( $comment_timestamp == '' ) {
// If the value for $_POST['timestamp'] is an empty string, exit (the form wasn't submitted by the theme's comments.php)
	header('HTTP/1.1 200 OK');
	echo '&lt;p style=&quot;text-align:center;&quot;&gt;Error: It looks like this form was not submitted by the form at ' . get_option('siteurl') . '.&lt;/p&gt;';
	exit;
}
if ( $submitted_timestamp - $comment_timestamp &lt; 60 ) {
// If the form was submitted within 60 seconds of page load, exit
	header('HTTP/1.1 200 OK');
	echo '&lt;p style=&quot;text-align:center;&quot;&gt;Error: The comment was posted too soon after the page was loaded.  Please press the Back button on your browser and try again in a few seconds.&lt;/p&gt;';
	exit;
}
// If the form was submitted more than 10 minutes after page load, die
if ( $submitted_timestamp - $comment_timestamp &gt; 600 ) {
	header('HTTP/1.1 200 OK');
	echo '&lt;p style=&quot;text-align:center;&quot;&gt;Error: You waited too long before posting a comment.&lt;/p&gt;';
	exit;
}
</pre>
<p>One could also write a record to a database each time the old wp-comments-post.php file is requested or any of the timestamp checks block a form submission, and pretty quickly generate a list of IP addresses for a black list.  At the same time, one could log which timestamp check caught the spam attempt, which is interesting enough that I&#8217;ll probably do it eventually.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2010/08/09/reducing-wordpress-spam-comments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to speed up WordPress</title>
		<link>http://www.ardamis.com/2010/08/03/how-to-speed-up-wordpress/</link>
		<comments>http://www.ardamis.com/2010/08/03/how-to-speed-up-wordpress/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 05:35:14 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=811</guid>
		<description><![CDATA[How to speed up WordPress by reducing HTTP requests and database look ups, using a faster mod_rewrite code, and shrinking the size of the database.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve written a few posts on how to speed up web sites by <a href="http://www.ardamis.com/2010/07/17/sending-headers-to-leverage-browser-caching/">sending the correct headers to leverage browser caching</a> and <a href="http://www.ardamis.com/2010/07/11/compress-files-without-mod_gzip-or-mod_deflate/">compressing .php, .css and .js files without mod_gzip or mod_deflate</a>.</p>
<p>The intended audience for this post is developers who have already applied most or all of Google&#8217;s <a href="http://code.google.com/speed/page-speed/docs/rules_intro.html">Web Performance Best Practices</a> and Yahoo&#8217;s <a href="http://developer.yahoo.com/performance/rules.html">Best Practices for Speeding Up Your Web Site</a> and are wondering how to speed up WordPress sites in particular.</p>
<p>I assume you&#8217;re familiar with <a href="http://codex.wordpress.org/WordPress_Optimization/Caching">WordPress caching</a> and are already using a caching plugin, such as <a href="http://wordpress.org/extend/plugins/wp-super-cache/">WP Super Cache</a>, <a href="http://wordpress.org/extend/plugins/w3-total-cache/">W3 Total Cache</a> or the like.  </p>
<h2>Reduce HTTP requests</h2>
<p>Reducing HTTP requests should be the very first thing step in speeding up any site.  If you are using plugins, watch them carefully for inefficiencies like added CSS and JavaScript files.  Combine, minify and compress these files.  Some plugins allow you to turn off their bundled CSS in the plugin&#8217;s settings page.  Where possible, copy the plugin&#8217;s CSS into the current theme&#8217;s style.css and turn off the extra file.</p>
<h2>Delete deactivated plugins</h2>
<p>Remove any plugins you&#8217;re not using.  Deactivated plugins can be deleted from the Plugins page.</p>
<h2>Speed up the mod_rewrite code</h2>
<p><a href="http://www.webmasterworld.com/profilev4.cgi?action=view&#038;member=jdMorgan">jdMorgan</a> from WebmasterWorld.com has written a replacement for the .htaccess rewrite rule used by WordPress.  This will speed up the WordPress mod_rewrite code by a factor of more than two.</p>
<blockquote><p>This is a total replacement for the code supplied with WP as bounded by the &#8220;Begin WP&#8221; and &#8220;End WP&#8221; comments, and fixes several performance-affecting problems. Notably, the unnecessary and potentially-problematic <IfModule> container is completely removed, and code is added and re-structured to both prevent completely-unnecessary file- and directory- exists checks and to reduce the number of necessary -exists checks to one-half the original count (due to the way mod_rewrite behaves recursively in .htaccess context).</p>
<p><a href="http://www.webmasterworld.com/apache/4053973.htm">http://www.webmasterworld.com/apache/4053973.htm</a>
</p></blockquote>
<p>The following code is adapted from the original to add png, flv and swf to the list of static file formats:</p>
<pre class="brush: plain; title: ; notranslate">
# BEGIN WordPress
# adapted from http://www.webmasterworld.com/apache/4053973.htm
#
RewriteEngine on
#
# Unless you have set a different RewriteBase preceding this point,
# you may delete or comment-out the following RewriteBase directive
# RewriteBase /
#
# if this request is for &quot;/&quot; or has already been rewritten to WP
RewriteCond $1 ^(index\.php)?$ [OR]
# or if request is for image, css, or js file
RewriteCond $1 \.(gif|jpg|png|ico|css|js|flv|swf)$ [NC,OR]
# or if URL resolves to existing file
RewriteCond %{REQUEST_FILENAME} -f [OR]
# or if URL resolves to existing directory
RewriteCond %{REQUEST_FILENAME} -d
# then skip the rewrite to WP
RewriteRule ^(.*)$ - [S=1]
# else rewrite the request to WP
RewriteRule . /index.php [L]
#
# END wordpress
</pre>
<h2>Only load the comment-reply.js when needed</h2>
<p>In the default WordPress template, the <strong>comment-reply.js</strong> script is included on all single post pages, regardless of whether nested/threaded comments is enabled.  A simple tweak changes the theme to only include <strong>comment-reply.js</strong> on single post pages only when it makes sense to do so: if threaded comments are enabled, commenting on that post is allowed, and a comment already exists.</p>
<p>Remove the following line from your theme&#8217;s <strong>header.php</strong>:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php if ( is_singular() ) wp_enqueue_script( 'comment-reply' ); ?&gt;
</pre>
<p>Add the following lines to your theme&#8217;s <strong>functions.php</strong>.</p>
<pre class="brush: php; title: ; notranslate">
// Don't add the wp-includes/js/comment-reply.js?ver=20090102 script to single post pages unless threaded comments are enabled
// adapted from http://bigredtin.com/behind-the-websites/including-wordpress-comment-reply-js/
function theme_queue_js(){
  if (!is_admin()){
    if (is_singular() &amp;&amp; (get_option('thread_comments') == 1) &amp;&amp; comments_open() &amp;&amp; have_comments())
      wp_enqueue_script('comment-reply');
  }
}
add_action('wp_print_scripts', 'theme_queue_js');
</pre>
<h2>Only load the l10n.js when needed</h2>
<p>In WordPress 3.1, a <strong>l10n.js</strong> script is loaded.  It is &#8220;mostly used for scripts that send over localization data from PHP to the JS side using <em>wp_localize_script()</em>.&#8221; Whether it&#8217;s safe to remove this file seems to be a matter of debate, but should you decide you want to remove it&#8230;</p>
<p>Add the following lines to your theme&#8217;s <strong>functions.php</strong>.</p>
<pre class="brush: php; title: ; notranslate">
// Don't add the wp-includes/js/l10n.js?ver=20101110 script to non-admin pages
// adapted from http://wordpress.stackexchange.com/questions/5451/what-does-l10n-js-do-in-wordpress-3-1-and-how-do-i-remove-it
function remove_l10n_js(){
  if (!is_admin()){
    wp_deregister_script('l10n');
  }
}
add_action('wp_print_scripts', 'remove_l10n_js');
</pre>
<h2>Replace unecessary code executions and database queries</h2>
<p>WordPress saves settings specific to your blog in the database.  These settings include what language your blog is written in, whether text is read left-to-right or vice versa, the path to the template directory, etc.</p>
<p>The default WordPress theme contains a number of database queries in order to figure out these things and build the correct page.  The default theme needs this flexibility, but your theme does not.  Joost de Valk recommends replacing these database queries with static text in your theme files in his post <a href="http://yoast.com/speed-up-wordpress/">Speed up WordPress, and clean it up too!</a></p>
<p>An easy way to do this is to browse to your web site and then view the source code.  Copy the content that won&#8217;t change from page to page and paste it into your theme, overwriting the PHP with the generated HTML.</p>
<p>For example, my theme&#8217;s header.php file contains this line:</p>
<pre class="brush: php; title: ; notranslate">
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; &lt;?php language_attributes(); ?&gt;&gt;
</pre>
<p>The source code of the rendered page displays this line:</p>
<pre class="brush: php; title: ; notranslate">
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; dir=&quot;ltr&quot; lang=&quot;en-US&quot;&gt;
</pre>
<p>On my blog, this HTML output is never going to be anything different, so why make WordPress look these settings up in the database each time a page is loaded?  This line is an excellent candidate for replacement.  The footer.php file contains a handful more opportunities for replacement, but go through each of your theme&#8217;s files and look for references to the template directory and other data that won&#8217;t change as long as you&#8217;re using the theme.  All told, I was able to replace 12 database queries with static HTML.</p>
<p>Joost also recommends checking for unnecessary or slow database queries, and installing a helpful debugging plugin, in his post on <a href="http://yoast.com/wordpress-performance-optimization/">Optimizing WordPress database performance</a>.</p>
<h2>Clean out your MySQL database</h2>
<h3>Delete spam comments</h3>
<p>From the Dashboard, click Comments, then click on Empty Spam.</p>
<h3>Delete post revisions</h3>
<p>If you don&#8217;t use post revisions, you may want to delete them from the <code>wp_posts</code> table.  Back up your database, then run the following SQL query:</p>
<pre class="brush: sql; title: ; notranslate">
DELETE FROM wp_posts WHERE post_type = &quot;revision&quot;;
</pre>
<p>Before: 683 records<br />
After: 165 records</p>
<p>This does not delete the latest draft of unpublished posts.  It&#8217;s a good idea to optimize the table after deleting the revisions.</p>
<p>You can stop WordPress from saving post revisions by adding the following code to wp-config.php:</p>
<pre class="brush: php; title: ; notranslate">
define('WP_POST_REVISIONS', false );
</pre>
<h2>Optimize your MySQL database</h2>
<p>Optimizing your MyISAM tables is comparable to defragmenting your hard drive.  It&#8217;s probably been a while since you&#8217;ve done that, too.</p>
<p>If you&#8217;re using phpMyAdmin, browse to your WordPress database.  Under the Structure tab, at the bottom of the list of tables, click on the link &#8220;Check all&#8221;.  In the &#8220;With selected&#8221; menu, choose &#8220;Optimize table&#8221;.  (I would have recommended just optimizing tables that have overhead, but the <code>wp_posts</code> table can be optimized even when it doesn&#8217;t show any overhead.</p>
<blockquote><p>For MyISAM tables, OPTIMIZE TABLE works as follows:</p>
<ul>
<li>If the table has deleted or split rows, repair the table.</li>
<li>If the index pages are not sorted, sort them.</li>
<li>If the table&#8217;s statistics are not up to date (and the repair could not be accomplished by sorting the index), update them.</li>
</ul>
<p><a href="http://dev.mysql.com/doc/refman/5.1/en/optimize-table.html">http://dev.mysql.com/doc/refman/5.1/en/optimize-table.html</a></p></blockquote>
<h2>Flush the Buffer Early</h2>
<blockquote><p>When users request a page, it can take anywhere from 200 to 500ms for the backend server to stitch together the HTML page. During this time, the browser is idle as it waits for the data to arrive. In PHP you have the function <code><a href="http://php.net/flush">flush()</a></code>. It allows you to send your partially ready HTML response to the browser so that the browser can start fetching components while your backend is busy with the rest of the HTML page. The benefit is mainly seen on busy backends or light frontends.</p>
<p><a href="http://developer.yahoo.com/performance/rules.html#flush">http://developer.yahoo.com/performance/rules.html#flush</a></p></blockquote>
<p>Add <code>flush()</code> between the closing <code></head></code> tag and the opening <code><body></code> tag in <strong>header.php</strong>.</p>
<pre class="brush: php; title: ; notranslate">
&lt;/head&gt;
&lt;?php flush(); // http://developer.yahoo.com/performance/rules.html#flush ?&gt;
&lt;body&gt;
</pre>
<p>OK, so this isn&#8217;t technically a WordPress-specific tweak, but it&#8217;s a good idea.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2010/08/03/how-to-speed-up-wordpress/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>How to compress .php, .css and .js files without mod_gzip or mod_deflate</title>
		<link>http://www.ardamis.com/2010/07/11/compress-files-without-mod_gzip-or-mod_deflate/</link>
		<comments>http://www.ardamis.com/2010/07/11/compress-files-without-mod_gzip-or-mod_deflate/#comments</comments>
		<pubDate>Mon, 12 Jul 2010 04:42:27 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[downloads]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[godaddy]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[themes]]></category>
		<category><![CDATA[web app]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=753</guid>
		<description><![CDATA[How to speed up page load times by compressing .php, .css and .js files on Apache web hosts that do not have mod_gzip or mod_deflate enabled.]]></description>
			<content:encoded><![CDATA[<p>File compression is possible on Apache web hosts that do not have mod_gzip or mod_deflate enabled, and it&#8217;s easier than you might think.</p>
<p>A great explanation of why compression helps the web deliver a better user experience is at <a href="http://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/">betterexplained.com</a>.</p>
<p>Two authoritative articles on the subject are Google&#8217;s <a href="http://code.google.com/speed/page-speed/docs/payload.html#GzipCompression">Performance Best Practices documentation | Enable compression</a> and Yahoo&#8217;s <a href="http://developer.yahoo.com/performance/rules.html#gzip">Best Practices for Speeding Up Your Web Site | Gzip Components</a>.</p>
<h2>Compressing PHP files</h2>
<p>If your Apache server does not have mod_gzip or mod_deflate enabled (Godaddy and JustHost shared hosting, for example), you can use PHP to compress pages on-the-fly.  This is still preferable to sending uncompressed files to the browser, so don&#8217;t worry about the additional work the server has to do to compress the files at each request.  </p>
<h3>Option 1: PHP.INI using zlib.output_compression</h3>
<p>The zlib extension can be used to transparently compress PHP pages on-the-fly if the browser sends an &#8220;Accept-Encoding: gzip&#8221; or &#8220;deflate&#8221; header.  Compression with zlib.output_compression seems to be disabled on most hosts by default, but can be enabled with a custom php.ini file:</p>
<pre class="brush: plain; title: ; notranslate">
[PHP]

zlib.output_compression = On
</pre>
<p>Credit: <a href="http://php.net/manual/en/zlib.configuration.php">http://php.net/manual/en/zlib.configuration.php</a></p>
<p>Check with your host for instructions on how to implement this, and whether you need a php.ini file in each directory.</p>
<h3>Option 2: PHP using ob_gzhandler</h3>
<p>If your host does not allow custom php.ini files, you can add the following line of code to the top of your PHP pages, above the DOCTYPE declaration or first line of output:</p>
<pre class="brush: plain; title: ; notranslate">
&lt;?php if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start(&quot;ob_gzhandler&quot;); else ob_start(); ?&gt;
</pre>
<p>Credit: <a href="http://help.godaddy.com/article/4485">GoDaddy.com</a></p>
<p>For WordPress sites, this code would be added to the top of the theme&#8217;s header.php file.</p>
<p>According to php.net, <a href="http://php.net/manual/en/function.ob-gzhandler.php">using zlib.output_compression is preferred over ob_gzhandler()</a>.</p>
<p>For WordPress or other CMS sites, an advantage of zlib.output_compression over the ob_gzhandler method is that all of the .php pages served will be compressed, not just those that contain the global include (eg.: header.php, etc.).</p>
<p>Running both ob_gzhandler and zlib.output_compression at the same time will throw a warning, similar to:</p>
<p><em>Warning: ob_start() [ref.outcontrol]: output handler &#8216;ob_gzhandler&#8217; conflicts with &#8216;zlib output compression&#8217; in /home/path/public_html/ardamis.com/wp-content/themes/mytheme/header.php on line 7</em></p>
<h2>Compressing CSS and JavaScript files</h2>
<p>Because the on-the-fly methods above only work for PHP pages, you&#8217;ll need something else to compress CSS and JavaScript files.  Furthermore, these files typically don&#8217;t change, so there isn&#8217;t a need to compress them at each request.  A better method is to serve pre-compressed versions of these files.  I&#8217;ll describe a few different ways to do this, but in both cases, you&#8217;ll need to add some lines to your .htaccess file to send user agents the gzipped versions if they support the encoding.  This requires that Apache&#8217;s mod_rewrite be enabled (and I think it&#8217;s almost universally enabled).</p>
<h3>Option 1: Compress locally and upload</h3>
<p>CSS and JavaScript files can be gzipped on the workstation, then uploaded along with the uncompressed files.  Use a utility like <a href="http://www.7-zip.org/">7-Zip</a> (quite possibly the best compression software around, and it&#8217;s free) to compress the CSS and JavaScript files using the gzip format (with extension *.gz), then upload them to your server.</p>
<p>For Windows users, here is a handy command to compress all the .css and .js files in the current directory and all sub directories (adjust the path to the 7-Zip executable, Zz.exe, as necessary):</p>
<pre class="brush: plain; title: ; notranslate">
for /R %i in (*.css *.js) do &quot;C:\Program Files (x86)\7-Zip\7z.exe&quot; a -tgzip &quot;%i.gz&quot; &quot;%i&quot; -mx9
</pre>
<p>Note that the above command is to be run from the command line.  The batch file equivalent would be:</p>
<pre class="brush: plain; title: ; notranslate">
for /R %%i in (*.css *.js) do &quot;C:\Program Files (x86)\7-Zip\7z.exe&quot; a -tgzip &quot;%%i.gz&quot; &quot;%%i&quot; -mx9
</pre>
<h3>Option 2: Compress on the server</h3>
<p>If you have shell access, you can run a command to create a gzip copy of each CSS and JavaScript file on your site (or, if you are developing on Linux, you can run it locally):</p>
<pre class="brush: plain; title: ; notranslate">
find . -regex &quot;.*\(css\|js\)$&quot; -exec bash -c 'echo Compressing &quot;{}&quot; &amp;&amp; gzip -c --best &quot;{}&quot; &gt; &quot;{}.gz&quot;' \;
</pre>
<p>This may be a bit too technical for many people, but is also much more convenient.  It is particularly useful when you need to compress a large number of files (as in the case of a WordPress installation with multiple plugins).  Remember to run it every time you automatically update WordPress, your theme, or any plugins, so as to replace the gzip&#8217;d versions of any updated CSS and JavaScript files.</p>
<h3>The .htaccess (for both options)</h3>
<p>Add the following lines to your .htaccess file to identify the user agents that can accept the gzip encoded versions of these files.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;files *.js.gz&gt;
  AddType &quot;text/javascript&quot; .gz
  AddEncoding gzip .gz
&lt;/files&gt;
&lt;files *.css.gz&gt;
  AddType &quot;text/css&quot; .gz
  AddEncoding gzip .gz
&lt;/files&gt;
RewriteEngine on
#Check to see if browser can accept gzip files.
ReWriteCond %{HTTP:accept-encoding} gzip
RewriteCond %{HTTP_USER_AGENT} !Safari
#make sure there's no trailing .gz on the url
ReWriteCond %{REQUEST_FILENAME} !^.+\.gz$
#check to see if a .gz version of the file exists.
RewriteCond %{REQUEST_FILENAME}.gz -f
#All conditions met so add .gz to URL filename (invisibly)
RewriteRule ^(.+) $1.gz [QSA,L]
</pre>
<p>Credit: <a href="http://www.opensourcetutor.com/2009/06/01/how-to-compress-css-javascript-an-alternative-to-mod_deflate-or-mod_gzip/">opensourcetutor.com</a></p>
<p>I&#8217;m not sure it&#8217;s still necessary to exclude Safari.</p>
<p>For added benefit, minify the CSS and JavaScript files before gzipping them.  Google&#8217;s excellent <a href="http://code.google.com/speed/page-speed/">Page Speed</a> Firefox/Firebug Add-on makes this very easy.  Yahoo&#8217;s <a href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a> is also quite good.</p>
<h2>Verify that your content is being compressed</h2>
<p>Use the nifty Web Page Content Compression Verification tool at <a href="http://www.whatsmyip.org/http_compression/">http://www.whatsmyip.org/http_compression/</a> to confirm that your server is sending the compressed files.</p>
<h2>Speed up page load times for returning visitors</h2>
<p>Compression is only part of the story.  In order to further speed page load times for your returning visitors, you will want to <a href="http://www.ardamis.com/2010/07/17/sending-headers-to-leverage-browser-caching/">send the correct headers to leverage browser caching</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2010/07/11/compress-files-without-mod_gzip-or-mod_deflate/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>My favorite themeforest.net WordPress templates</title>
		<link>http://www.ardamis.com/2010/02/21/my-favorite-themeforest-net-wordpress-templates/</link>
		<comments>http://www.ardamis.com/2010/02/21/my-favorite-themeforest-net-wordpress-templates/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 06:20:56 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[templates]]></category>
		<category><![CDATA[themes]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=483</guid>
		<description><![CDATA[A collection of my favorite themeforest.net WordPress templates, mostly intended for web designers or graphics-related businesses.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been collecting links to good WordPress templates for a long time.  Because I&#8217;ve been asked a few times recently if I can recommend some templates, I&#8217;m putting them together here.</p>
<h2>Huge, isolated, animated slideshow</h2>
<p>I really like these themes for focusing almost exclusively on one&#8217;s portfolio.  They feature a massive, animated slideshow that keeps the visitor&#8217;s attention on the images.  In some cases, a shadow underneath the slideshow, combined with the animation, creates a 3-D effect to put the portfolio right in the visitor&#8217;s face.</p>
<ul>
<li><a href="http://themeforest.net/item/black-eve-wordpress-version/full_screen_preview/93185">http://themeforest.net/item/black-eve-wordpress-version/full_screen_preview/93185</a></li>
<li><a href="http://themeforest.net/item/novatorix-10-in-1-business-portfolio-and-blog/full_screen_preview/111717">http://themeforest.net/item/novatorix-10-in-1-business-portfolio-and-blog/full_screen_preview/111717</a></li>
<li><a href="http://themeforest.net/item/iportfolio/75877">http://themeforest.net/item/iportfolio/full_screen_preview/75877</a></li>
<li><a href="http://themeforest.net/item/display-3-in-1-business-portfolio-wordpress-/full_screen_preview/74542">http://themeforest.net/item/display-3-in-1-business-portfolio-wordpress-/full_screen_preview/74542</a></li>
<li><a href="http://themeforest.net/item/7-in-1-business-success-wordpress-theme/full_screen_preview/88463">http://themeforest.net/item/7-in-1-business-success-wordpress-theme/full_screen_preview/88463</a></li>
<li><a href="http://themeforest.net/item/flexolio-porfolio-blog-business-cms-wp-theme-/full_screen_preview/81146">http://themeforest.net/item/flexolio-porfolio-blog-business-cms-wp-theme-/full_screen_preview/81146</a></li>
<li><a href="http://themeforest.net/item/discovery-wordpress/full_screen_preview/83792">http://themeforest.net/item/discovery-wordpress/full_screen_preview/83792</a></li>
</ul>
<h2>Confined slideshow</h2>
<p>These themes are a bit more modest than the first collection.  They still accentuate a portfolio of images, but in a less flashy way.  The slideshow exists within a defined banner area, so the look is a little more traditional.  These templates would be a better fit for businesses.</p>
<ul>
<li><a href="http://themeforest.net/item/habitat-blog-and-portfolio-theme/full_screen_preview/125365">http://themeforest.net/item/habitat-blog-and-portfolio-theme/full_screen_preview/125365</a></li>
<li><a href="http://themeforest.net/item/vulcan-minimalist-business-wordpress-theme-4/full_screen_preview/111625">http://themeforest.net/item/vulcan-minimalist-business-wordpress-theme-4/full_screen_preview/111625</a></li>
<li><a href="http://themeforest.net/item/creation-minimalist-business-wordpress-theme/full_screen_preview/113734">http://themeforest.net/item/creation-minimalist-business-wordpress-theme/full_screen_preview/113734</a></li>
<li><a href="http://themeforest.net/item/corporate-business-portfolio-wordpress-theme-/full_screen_preview/81507">http://themeforest.net/item/corporate-business-portfolio-wordpress-theme-/full_screen_preview/81507</a></li>
<li><a href="http://themeforest.net/item/luxury-wordpress-template/full_screen_preview/83220">http://themeforest.net/item/luxury-wordpress-template/full_screen_preview/83220</a></li>
<li><a href="http://themeforest.net/item/tylium-premium-wordpress-theme/full_screen_preview/68229">http://themeforest.net/item/tylium-premium-wordpress-theme/full_screen_preview/68229</a></li>
<li><a href="http://themeforest.net/item/shapeshifter-one-page-infinite-possibilities/full_screen_preview/75759">http://themeforest.net/item/shapeshifter-one-page-infinite-possibilities/full_screen_preview/75759</a></li>
<li><a href="http://themeforest.net/item/delericon-businessportfolio-template-wordpress/full_screen_preview/76635">http://themeforest.net/item/delericon-businessportfolio-template-wordpress/full_screen_preview/76635</a></li>
<li><a href="http://themeforest.net/item/twicet-business-portfolio-wordpress-5-in-1/full_screen_preview/49773">http://themeforest.net/item/twicet-business-portfolio-wordpress-5-in-1/full_screen_preview/49773</a></li>
<li><a href="http://themeforest.net/item/benzo/full_screen_preview/50977">http://themeforest.net/item/benzo/full_screen_preview/50977</a></li>
<li><a href="http://themeforest.net/item/creative-wordpress-theme-9-in-1/full_screen_preview/84549">http://themeforest.net/item/creative-wordpress-theme-9-in-1/full_screen_preview/84549</a></li>
<li><a href="http://themeforest.net/item/levitation-wordpress-business-portfolio-4-in-1/full_screen_preview/60299">http://themeforest.net/item/levitation-wordpress-business-portfolio-4-in-1/full_screen_preview/60299</a></li>
<li><a href="http://themeforest.net/item/mapollo/full_screen_preview/60268">http://themeforest.net/item/mapollo/full_screen_preview/60268</a></li>
<li><a href="http://themeforest.net/item/elite-force-premium-wordpress-theme/full_screen_preview/84456">http://themeforest.net/item/elite-force-premium-wordpress-theme/full_screen_preview/84456</a></li>
</ul>
<h2>Partial-banner image rotation</h2>
<p>These themes use only part of the banner to display a rotating group of images, leaving an area for text next to the images.  This allows a short message or tagline to get equal placement.  These are the most conservative themes.</p>
<ul>
<li><a href="http://themeforest.net/item/designer-portfolio-elegant-template-wordpress/full_screen_preview/96810">http://themeforest.net/item/designer-portfolio-elegant-template-wordpress/full_screen_preview/96810</a></li>
<li><a href="http://themeforest.net/item/bluelight-wordpress-20-portfolio-and-blog/full_screen_preview/40433">http://themeforest.net/item/bluelight-wordpress-20-portfolio-and-blog/full_screen_preview/40433</a></li>
<li><a href="http://themeforest.net/item/quadro-wordpress-version/full_screen_preview/79966">http://themeforest.net/item/quadro-wordpress-version/full_screen_preview/79966</a></li>
<li><a href="http://themeforest.net/item/concept-wordpress-a-premium-wp-theme/full_screen_preview/53845">http://themeforest.net/item/concept-wordpress-a-premium-wp-theme/full_screen_preview/53845</a></li>
<li><a href="http://themeforest.net/item/lightcorners/full_screen_preview/82046">http://themeforest.net/item/lightcorners/full_screen_preview/82046</a></li>
<li><a href="http://themeforest.net/item/concise/full_screen_preview/66396">http://themeforest.net/item/concise/full_screen_preview/66396</a></li>
<li><a href="http://themeforest.net/item/spotlight-portfolio-theme-wordpress-edition/full_screen_preview/80959">http://themeforest.net/item/spotlight-portfolio-theme-wordpress-edition/full_screen_preview/80959</a></li>
<li><a href="http://themeforest.net/item/transformer/82402">http://themeforest.net/item/transformer/82402</a></li>
<li><a href="http://themeforest.net/item/scroller-wordpress-theme/full_screen_preview/83162">http://themeforest.net/item/scroller-wordpress-theme/full_screen_preview/83162</a></li>
<li><a href="http://themeforest.net/item/advantage-wordpress-theme-4-in-1/full_screen_preview/88112">http://themeforest.net/item/advantage-wordpress-theme-4-in-1/full_screen_preview/88112</a></li>
<li><a href="http://themeforest.net/item/durable-5-in-1-business-portfolio-wordpress/full_screen_preview/84440">http://themeforest.net/item/durable-5-in-1-business-portfolio-wordpress/full_screen_preview/84440</a></li>
<li><a href="http://themeforest.net/item/equator-global-community-wordpress-theme/full_screen_preview/65549">http://themeforest.net/item/equator-global-community-wordpress-theme/full_screen_preview/65549</a></li>
<li><a href="http://themeforest.net/item/oxygene-clean-environment/full_screen_preview/62657">http://themeforest.net/item/oxygene-clean-environment/full_screen_preview/62657</a></li>
<li><a href="http://themeforest.net/item/foliothemes-portfolio/full_screen_preview/66448">http://themeforest.net/item/foliothemes-portfolio/full_screen_preview/66448</a></li>
<li><a href="http://themeforest.net/item/eclectic-premium-wordpress-theme/full_screen_preview/63212">http://themeforest.net/item/eclectic-premium-wordpress-theme/full_screen_preview/63212</a></li>
<li><a href="http://themeforest.net/item/bitwork-portfolio-and-business-wordpress-theme/full_screen_preview/87092">http://themeforest.net/item/bitwork-portfolio-and-business-wordpress-theme/full_screen_preview/87092</a></li>
<li><a href="http://themeforest.net/item/business-showcase-corporate-layout-html/full_screen_preview/50191">http://themeforest.net/item/business-showcase-corporate-layout-html/full_screen_preview/50191</a></li>
<li><a href="http://themeforest.net/item/corpomino/full_screen_preview/63883">http://themeforest.net/item/corpomino/full_screen_preview/63883</a></li>
<li><a href="http://themeforest.net/item/photography-and-portfolio-wordpress-theme/full_screen_preview/82048">http://themeforest.net/item/photography-and-portfolio-wordpress-theme/full_screen_preview/82048</a></li>
<li><a href="http://themeforest.net/item/kava-wp-theme-for-cms-business-portfolio-blog/full_screen_preview/82551">http://themeforest.net/item/kava-wp-theme-for-cms-business-portfolio-blog/full_screen_preview/82551</a></li>
</ul>
<h2>Creative themes</h2>
<p>This last group of themes break with the conventions of the above themes and use full-screen-width or otherwise larger-than-normal images that rotate behind the other elements of the site.  Undeniably attention-grabbing, but also slower to load.</p>
<ul>
<li><a href="http://themeforest.net/item/the-architect-wp-edition/full_screen_preview/113414">http://themeforest.net/item/the-architect-wp-edition/full_screen_preview/113414</a></li>
<li><a href="http://themeforest.net/item/photome-photography-and-portfolio-template-wp/full_screen_preview/113474">http://themeforest.net/item/photome-photography-and-portfolio-template-wp/full_screen_preview/113474</a></li>
<li><a href="http://themeforest.net/item/wp-portfolius-v9/full_screen_preview/81863">http://themeforest.net/item/wp-portfolius-v9/full_screen_preview/81863</a></li>
<li><a href="http://themeforest.net/item/photo-graphic-studio-wordpress/full_screen_preview/36070">http://themeforest.net/item/photo-graphic-studio-wordpress/full_screen_preview/36070</a></li>
<li><a href="http://themeforest.net/item/desktop-press-creative-wordpress-theme/full_screen_preview/87968">http://themeforest.net/item/desktop-press-creative-wordpress-theme/full_screen_preview/87968</a></li>
<li><a href="http://themeforest.net/item/luna-premium-wordpress-theme/full_screen_preview/85233">http://themeforest.net/item/luna-premium-wordpress-theme/full_screen_preview/85233</a></li>
</ul>
<h2>Single page</h2>
<p>These are single-page web sites.  These types of pages are great as business cards or resumes, or as place holders while a larger site is developed.</p>
<ul>
<li><a href="http://themeforest.net/item/galeria-single-page-wordpress-portfolio/full_screen_preview/105848">http://themeforest.net/item/galeria-single-page-wordpress-portfolio/full_screen_preview/105848</a></li>
<li><a href="http://themeforest.net/item/path-finder-keyboard-navigation-wordpress-theme/full_screen_preview/109983">http://themeforest.net/item/path-finder-keyboard-navigation-wordpress-theme/full_screen_preview/109983</a></li>
</ul>
<h2>The rest</h2>
<p>I like these, too, but they don&#8217;t fit in any of the above categories.</p>
<ul>
<li><a href="http://standardtheme.com/">http://standardtheme.com/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2010/02/21/my-favorite-themeforest-net-wordpress-templates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using timestamps to reduce WordPress comment spam</title>
		<link>http://www.ardamis.com/2007/12/15/using-timestamps-to-reduce-wordpress-comment-spam/</link>
		<comments>http://www.ardamis.com/2007/12/15/using-timestamps-to-reduce-wordpress-comment-spam/#comments</comments>
		<pubDate>Sat, 15 Dec 2007 08:33:15 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[comment spam]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/2007/12/15/using-timestamps-to-reduce-wordpress-comment-spam/</guid>
		<description><![CDATA[The method described in this post uses PHP to generate the timestamps. If your site is using a caching plugin, the timestamps will be stale, and this method will not work. I&#8217;m working on a new method using JavaScript for sites that use page caching. In this post, I&#8217;ll explain how to reduce the amount [...]]]></description>
			<content:encoded><![CDATA[<div class="notice">The method described in this post uses PHP to generate the timestamps.  If your site is using a caching plugin, the timestamps will be stale, and this method will not work. I&#8217;m working on a new method using JavaScript for sites that use page caching.</div>
<p>In this post, I&#8217;ll explain how to reduce the amount of comment spam your WordPress blog receives by using an unobtrusive &#8216;handshake&#8217; between the two files necessary for a valid comment submission to take place.  I&#8217;ve written a few different articles on reducing comment spam by means of a challenge response test that the visitor must complete before submitting a comment, but I&#8217;m now looking for ways to achieve the same results while keeping the anti-spam method invisible to the visitor.</p>
<p>I&#8217;m a big fan of Akismet, but I also want to block as much spam as possible before it is caught by Akisment in order to reduce the number of database entries.</p>
<p>One thing this method does not do is <a href="http://www.ardamis.com/2007/09/12/defeating-wordpress-comment-spam/">rename and hide the path to the form processing script</a>, but it makes that technique obsolete, anyway.</p>
<p>In the timestamp handshake method, a first timestamp is generated and written as a hidden input field when the post page loads.  When the comment is submitted, a second timestamp is generated by the comment-processing script and it and the page-load timestamp are saved as variables.  If the page-load timestamp variable is blank, which should be the case if the spambot uses any other page to populate the comment, the script will die.  The page-load timestamp is then subtracted from the comment-submission timestamp.  If the comment was submitted less than 60 seconds after the post page was loaded, the script dies with a descriptive error message.  Hopefully, this will separate the bots&#8217; comments from those left by thoughtful human visitors who have taken the time to read your post.  If a human visitor does happen to submit a comment within 60 seconds of the page loading, he or she can click his or her browser&#8217;s back button and try resubmitting the comment again in a few seconds.</p>
<p>One drawback is that this method does involve editing a core file &#8211; <strong>wp-comments-post.php</strong>.  You&#8217;ll have to re-edit it each time you upgrade WordPress, which is a nuisance, I know.  The good thing is that if you forget to do this, people can still comment &#8211; you just won&#8217;t have the anti-spam protection.</p>
<p>Note that the instructions in the following steps are based on the code in WordPress version 2.3 and the Kubrick theme included with that release.  You may need to adjust for your version of WordPress.</p>
<h2>Step 1 &#8211; Add the hidden timestamp input field to the comment form</h2>
<p>Open the <strong>comments.php</strong> file in your current theme&#8217;s folder and find the following lines:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;p&gt;&lt;textarea name=&quot;comment&quot; id=&quot;comment&quot; cols=&quot;100%&quot; rows=&quot;10&quot; tabindex=&quot;4&quot;&gt;&lt;/textarea&gt;&lt;/p&gt;

&lt;p&gt;&lt;input name=&quot;submit&quot; type=&quot;submit&quot; id=&quot;submit&quot; tabindex=&quot;5&quot; value=&quot;Submit Comment&quot; /&gt;
</pre>
<p>Add the following line between them:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;p&gt;&lt;input type=&quot;hidden&quot; name=&quot;timestamp&quot; id=&quot;timestamp&quot; value=&quot;&lt;?php echo time(); ?&gt;&quot; size=&quot;22&quot; /&gt;&lt;/p&gt;
</pre>
<h2>Step 2 &#8211; Modify the <strong>wp-comments-post.php</strong> file to create the second timestamp and perform the comparison</h2>
<p>Open <strong>wp-comments-post.php</strong> and find the lines:</p>
<pre class="brush: php; title: ; notranslate">
$comment_author       = trim(strip_tags($_POST['author']));
$comment_author_email = trim($_POST['email']);
$comment_author_url   = trim($_POST['url']);
$comment_content      = trim($_POST['comment']);
</pre>
<p>Immediately after them, add the following lines:</p>
<pre class="brush: php; title: ; notranslate">
$comment_timestamp    = trim($_POST['timestamp']);
$submitted_timestamp  = time();

if ( $comment_timestamp == '' )
	wp_die( __('Hello, spam bot!') );

if ( $submitted_timestamp - $comment_timestamp &lt; 60 )
	wp_die( __('Error: you must wait at least 1 minute before posting a comment.') );
</pre>
<p>That&#8217;s it; you&#8217;re done.  </p>
<h2>Credits</h2>
<p>Thanks to Jonathan Bailey for suggesting the handshake in his post at <a href="http://www.plagiarismtoday.com/2007/07/24/wordpress-and-comment-spam/">http://www.plagiarismtoday.com/2007/07/24/wordpress-and-comment-spam/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2007/12/15/using-timestamps-to-reduce-wordpress-comment-spam/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>

