<?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>Fazal Majid&#039;s low intensity weblog &#187; Web</title>
	<atom:link href="http://majid.info/blog/category/web/feed/" rel="self" type="application/rss+xml" />
	<link>http://majid.info/blog</link>
	<description>Sporadic pontification</description>
	<lastBuildDate>Sat, 24 Mar 2012 16:49:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Changing the WordPress table prefix</title>
		<link>http://majid.info/blog/wordpress-prefix/</link>
		<comments>http://majid.info/blog/wordpress-prefix/#comments</comments>
		<pubDate>Sat, 29 Jan 2011 00:48:36 +0000</pubDate>
		<dc:creator>majid</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://majid.info/blog/?p=141242418</guid>
		<description><![CDATA[This may be of use to people experiencing the dreaded &#8220;You do not have sufficient permissions to access this page.&#8221; message when trying to reach WordPress&#8217; admin page, even when logging in as a proper administrator. WordPress embeds the table &#8230; <a href="http://majid.info/blog/wordpress-prefix/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This may be of use to people experiencing the dreaded <em>&#8220;You do not have sufficient permissions to access this page.&#8221;</em> message when trying to reach WordPress&#8217; admin page, even when logging in as a proper administrator. WordPress embeds the table prefix in 4 different locations:</p>
<ul>
<li>The <tt>wp-config.php</tt> file</li>
<li>The name of the tables</li>
<li>The name of user metadata keys</li>
<li>The name of blog options</li>
</ul>
<p>Thus if you want to change the prefix, you have to:</p>
<ol>
<li>Edit <tt>wp-config.php</tt> to change the prefix</li>
<li>Rename your tables</li>
<li>Rename your user metadata</li>
<li>Rename your site options</li>
</ol>
<p>Missing steps 1 or 2 will cause WordPress to not find the tables, and it will go through the initial install process again.</p>
<p>Missing step 3 will cause the account to lose its roles, and thus not be authorized to do much besides read public posts.</p>
<p>Missing step 4 is more insidious, as it destroys the option <tt>wp_user_roles</tt>, the link between roles and capabilities, and thus even if your account is an administrator, it is no longer authorized for anything.</p>
<p>It feels quite clunky to embed the database prefix in column values, not just tables, just like WordPress&#8217; insistence on converting relative links to absolute links. The former makes moving tables around (e.g. when consolidating multiple blogs on a single MySQL database) harder than necessary. The latter makes moving a blog around in a site&#8217;s URL hierarchy break internal links. I suppose there are security reasons underlying Automattic&#8217;s design choice, but security by obscurity of the WordPress table prefix is hardly a foolproof measure.</p>
<p>If you are renaming the tables, say, from the default prefix <tt>wp_</tt> to <tt>foo_</tt>, the MySQL commands necessary for steps 2–4 would be the following:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">UPDATE</span> wp_usermeta <span style="color: #993333; font-weight: bold;">SET</span> meta_key<span style="color: #66cc66;">=</span><span style="color: #993333; font-weight: bold;">REPLACE</span><span style="color: #66cc66;">&#40;</span>meta_key<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'wp_'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'foo_'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">WHERE</span> meta_key <span style="color: #993333; font-weight: bold;">LIKE</span> <span style="color: #ff0000;">'wp_%'</span>;
<span style="color: #993333; font-weight: bold;">UPDATE</span> wp_options <span style="color: #993333; font-weight: bold;">SET</span> option_name<span style="color: #66cc66;">=</span><span style="color: #993333; font-weight: bold;">REPLACE</span><span style="color: #66cc66;">&#40;</span>option_name<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'wp_'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'foo_'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">WHERE</span> option_name <span style="color: #993333; font-weight: bold;">LIKE</span> <span style="color: #ff0000;">'wp_%'</span>;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_commentmeta <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_commentmeta;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_comments <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_comments;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_links <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_links;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_options <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_options;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_postmeta <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_postmeta;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_posts <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_posts;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_redirection_groups <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_redirection_groups;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_redirection_items <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_redirection_items;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_redirection_logs <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_redirection_logs;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_redirection_modules <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_redirection_modules;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_term_relationships <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_term_relationships;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_term_taxonomy <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_term_taxonomy;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_terms <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_terms;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_usermeta <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_usermeta;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> wp_users <span style="color: #993333; font-weight: bold;">RENAME</span> <span style="color: #993333; font-weight: bold;">TO</span> foo_users;</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://majid.info/blog/wordpress-prefix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Incensed at Mozilla</title>
		<link>http://majid.info/blog/incensed-at-mozilla/</link>
		<comments>http://majid.info/blog/incensed-at-mozilla/#comments</comments>
		<pubDate>Tue, 31 Aug 2010 23:39:39 +0000</pubDate>
		<dc:creator>majid</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Soapbox]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://majid.info/blog/?p=141242332</guid>
		<description><![CDATA[One of the greatest features in the Webkit-based browsers (Apple&#8217;s Safari and Google Chrome) is WebSQLdatabase, the ability for a web site to store information in a SQLite database on your browser accessible via JavaScript. This allows web developers to &#8230; <a href="http://majid.info/blog/incensed-at-mozilla/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One of the greatest features in the Webkit-based browsers (Apple&#8217;s Safari and Google Chrome) is <a href="http://www.w3.org/TR/webdatabase/">WebSQLdatabase</a>, the ability for a web site to store information in a SQLite database on your browser accessible via JavaScript. This allows web developers to build database-enabled applications that run entirely in the browser, without requiring a server. This is very useful for mobile devices, which in the US enjoy flaky network connectivity at best. One very handsome example is the iPad-optimized <a href="http://everytimezone.com/">Every Time Zone</a> webapp.</p>
<p><a href="http://www.sqlite.org/">SQLite</a> is probably the most important open-source project you have never heard of. It is a simple, streamlined and efficient embedded database. Firefox stores its bookmarks in it. Google distributes its database of phishing sites in that format. Sun&#8217;s industrial-strength Solaris operating system stores the list of services it runs on boot in it—if it were to fail, a server would be crippled so that is a pretty strong vote of confidence. Adobe Lightroom and Apple&#8217;s Aperture use it to store their database, as do most Mac applications that use the CoreData framework, and many iPhone apps. In other words, it is robust and proven mission-critical software that is widely yet invisibly deployed.</p>
<p>WebSQLdatabase basically makes the power of SQLite available to web developers trying to build apps that work offline, specially on mobile devices. No good deed goes unpunished, and the Mozilla foundation teamed up with unlikely bedfellow Microsoft to torpedo formal adoption of WebSQLdatabase as a web standard, on <a href="http://hacks.mozilla.org/2010/06/beyond-html5-database-apis-and-the-road-to-indexeddb/">spurious grounds</a>, and pushed an alternate standard called IndexedDB instead. To <a href="http://www.chromium.org/developers/design-documents/indexeddb">quote</a> the Chromium team:</p>
<blockquote><p>Q: Why this over WebSQLDatabase?</p>
<p>A: Microsoft and Mozilla have made it very clear they will not implement SQL in the browser.  If you want to argue this is silly, talk to them, not me.</p></blockquote>
<p>IndexedDB is several steps backwards. Instead of using powerful, expressive and mature SQL technology, it uses a verbose JavaScript B-tree API that is a throwback to the 1960s bad old days of hierarchical databases and ISAM, requires a lot more work from the developer, for no good reason. To add injury to insult, Firefox 4&#8242;s implementation of IndexedDB is actually built on top of SQLite. The end result will be that web developers will need to build a SQL emulation library on top of IndexedDB to restore the SQLite functionality deliberately crippled by IndexedDB. If there is one constant in software engineering, it is that multiple layers add brittleness and impair performance.</p>
<p>Of course, both Mozilla and Microsoft are irrelevant on mobiles, where WebKit has essentially won the day, so why should this matter? Microsoft has always been a hindrance to the development of the web, since they have to protect the Windows API from competition by increasingly capable webapps, but I cannot understand Mozilla&#8217;s attitude, except possibly knee-jerk not-invented-here syndrome and petulance at being upstaged by WebKit. WebSQLdatabase is not perfect—to reach its full potential, it needs and automatic replication and sync facility between the local database and the website&#8217;s own database, but it is light years ahead of IndexedDB in terms of power and productivity.</p>
<p>I am so irritated by Mozilla&#8217;s attitude that after 10 years of using Mozilla-based browsers, I switched today from Firefox to Chrome as my primary browser. Migrating was surprisingly easy. Key functionality like bookmark keywords, AdBlock, FlashBlock, a developer console, and the ability to whitelist domains for cookies, all have equivalents on Chrome. The main regressions are bookmark tags, and Chrome&#8217;s sync options are not yet equivalent to <a href="http://majid.info/blog/mozilla-weave/">Weave</a>&#8216;s. At some point I will need to roll my own password syncing facility (Chrome stores its passwords in the OS X keychain, which is also used by Safari and Camino).</p>
]]></content:encoded>
			<wfw:commentRss>http://majid.info/blog/incensed-at-mozilla/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>RapidSSL 1 &#8211; GoDaddy 0</title>
		<link>http://majid.info/blog/godaddy-incompetent-morons/</link>
		<comments>http://majid.info/blog/godaddy-incompetent-morons/#comments</comments>
		<pubDate>Fri, 25 Jun 2010 04:32:38 +0000</pubDate>
		<dc:creator>majid</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Network]]></category>
		<category><![CDATA[Soapbox]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://majid.info/blog/?p=141242290</guid>
		<description><![CDATA[My new company&#8217;s website uses SSL. I ordered an &#8220;extended validation&#8221; certificate from GoDaddy, instead of my usual CA, RapidSSL/GeoTrust, because GoDaddy&#8217;s EV certificates were cheap. EV certificates are security theater more than anything else, I probably should not have &#8230; <a href="http://majid.info/blog/godaddy-incompetent-morons/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My new company&#8217;s website uses SSL. I ordered an &#8220;extended validation&#8221; certificate from GoDaddy, instead of my usual CA, <a href="http://www.rapidssl.com/">RapidSSL/GeoTrust</a>, because GoDaddy&#8217;s EV certificates were cheap. EV certificates are security theater more than anything else, I probably should not have bothered.</p>
<p>Immediately after switching from my earlier &#8220;snake oil&#8221; self-signed test certificate to the production certificate, I saw SSL errors on Google Chrome for Mac and Safari for Mac, i.e. the two browsers that use OS X&#8217;s built-in crypto and certificate store. I suppose I should have tested the certificate on another server before  going live, but I trusted GoDaddy (they are my DNS registrars, and  competent, if garish).</p>
<p>Big mistake.</p>
<p><a href="http://majid.info/blog/wp-content/uploads/2010/06/Screen-shot-2010-06-24-at-20.49.14-.png"><img class="aligncenter size-large wp-image-141242291" title="Screen shot 2010-06-24 at 20.49.14" src="http://majid.info/blog/wp-content/uploads/2010/06/Screen-shot-2010-06-24-at-20.49.14--598x620.png" alt="" width="598" height="620" /></a><a href="http://majid.info/blog/wp-content/uploads/2010/06/Screen-shot-2010-06-24-at-20.48.20-.png"><img class="aligncenter size-large wp-image-141242292" title="Screen shot 2010-06-24 at 20.48.20" src="http://majid.info/blog/wp-content/uploads/2010/06/Screen-shot-2010-06-24-at-20.48.20--557x620.png" alt="" width="557" height="620" /></a>I called their tech support hotline, which is incredibly grating because of the verbose phone tree that keeps trying to push add-ons (I guess it is consistent with the monstrosity that is their home page).</p>
<p>After a while, I got a first-level tech. He asked whether I saw the certificate error on Google Chrome for Windows. At that point, I was irate enough to use a four-letter word. Our customers are Android mobile app developers. A significant chunk of them use Macs, and almost none (less than 5%) use IE, so know-nothing &#8220;All the world is IE&#8221; demographics are not exactly applicable.</p>
<p>After about half an hour of getting the run-around and escalating to level 2, with my business partner Michael getting progressively more anxious in the background, the level 1 CSR tells me the level 2 one can&#8217;t reproduce the problem (I reproduced it on three different Macs in two different locations). I gave them an ultimatum: fix it within 10 minutes or I would switch. At this point, the L1 CSR told me he had exhausted all his options, but I could call their &#8220;RA&#8221; department, and offered to switch me. Inevitably, the call transfer failed.</p>
<p>I dialed their SSL number, and in parallel started the certificate application process on RapidSSL. They offered a free competitive upgrade, I tried it, and within 3 minutes I had my fresh new, and functional certificate, valid for 3 years, all for free and in less time than it takes to listen to GoDaddy&#8217;s obnoxious phone tree (all bout &#8220;we pride ourselves in customer service&#8221; and other Orwellian corporate babble).</p>
<p>I then called GoDaddy&#8217;s billing department to get a refund. Surprisingly, the process was very fast and smooth. I guess it is well-trod.</p>
<p>The moral of the story: GoDaddy—bad. RapidSSL—good.</p>
]]></content:encoded>
			<wfw:commentRss>http://majid.info/blog/godaddy-incompetent-morons/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Scientific papers now citing blogs?</title>
		<link>http://majid.info/blog/scientific-papers-citing-blogs/</link>
		<comments>http://majid.info/blog/scientific-papers-citing-blogs/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 08:55:11 +0000</pubDate>
		<dc:creator>majid</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://majid.info/blog/?p=141242104</guid>
		<description><![CDATA[In my misspent youth I spent about a year as a visiting scholar researching wavelets under Raphy Coifman&#8217;s supervision at Yale&#8217;s small but excellent Mathematics Department. Professor Coifman was head of a department that also featured Benoît Mandelbrot (of fractals &#8230; <a href="http://majid.info/blog/scientific-papers-citing-blogs/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In my misspent youth I spent about a year as a visiting scholar researching wavelets under <a href="http://www.cs.yale.edu/people/coifman.html">Raphy Coifman&#8217;s</a> supervision at Yale&#8217;s small but excellent Mathematics Department. Professor Coifman was head of a department that also featured Benoît Mandelbrot (of fractals fame), the late <a href="http://www.math.yale.edu/public_html/WalterFeit/WalterFeit.html">Walter Feit</a> (as in the <a href="http://en.wikipedia.org/wiki/Feit%E2%80%93Thompson_theorem">Feit-Thompson theorem</a>), and Fields medalist Gregory Margulis. He was kind enough to credit me on a <a href="http://books.google.com/books?id=aHux78oQbbkC&amp;lpg=PA63&amp;ots=Dy4EwoMVIB&amp;dq=majid%20wavelets%20roques&amp;pg=PA63#v=onepage&amp;q=&amp;f=false">published paper</a>, even though he did all the work, reverse delegation in action. That paper had modest success and was cited, so I can claim (not with a straight face) to be a published mathematician.</p>
<p>While perusing my blog&#8217;s web analytics referrer report, I was surprised to find out my article on the <a href="http://majid.info/blog/is-the-nikon-d70-nef-raw-format-truly-lossless/">Nikon D70&#8242;s not-so-raw RAW format</a> is actually cited in a <a href="http://www.ploscompbiol.org/article/info:doi/10.1371/journal.pcbi.1000677">serious scientific paper</a> on human vision. We keep hearing about students getting flunking grades for citing Wikipedia, are blogs really considered more authoritative?</p>
<p>The citation uses the old URL for the blog entry, <a href="http://www.majid.info/mylos/weblog/2004/05/02-1.html">http://www.majid.info/mylos/weblog/2004/05/02-1.html</a>. When I migrated to WordPress at the end of 2009, I took great pains to provide redirects whenever possible and avoid broken links. Many bloggers don&#8217;t have the time or expertise to do this, and simply leave dangling permalinks around. If quoting blogs is to become standard practice, authors should probably provide some sort of fallback mechanism like linking to Archive.org, but dead-tree journals do not have this capability. Absent that, linkrot may spread to an entire new category of documents, scientific papers.</p>
<p>Update (2011-07-18):</p>
<p>Here&#8217;s <a href="http://mit.tut.fi/staff/Hytti/Noise_characterization.pdf">another paper</a> (PDF) referencing the same article. What&#8217;s next, CiteSeer?</p>
]]></content:encoded>
			<wfw:commentRss>http://majid.info/blog/scientific-papers-citing-blogs/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Securing WordPress</title>
		<link>http://majid.info/blog/securing-wordpress/</link>
		<comments>http://majid.info/blog/securing-wordpress/#comments</comments>
		<pubDate>Sun, 06 Sep 2009 21:40:16 +0000</pubDate>
		<dc:creator>majid</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://majid.info/blog/?p=391</guid>
		<description><![CDATA[WordPress has been getting a lot of bad press the last few days, as a worm is out in the wild exploiting a security vulnerability. This is leading to somewhat unfair comparisons with Windows, and thoughtful articles from John Gruber &#8230; <a href="http://majid.info/blog/securing-wordpress/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>WordPress has been getting a lot of bad press the last few days, as a <a href="http://www.guardian.co.uk/technology/blog/2009/sep/05/wordpress-hacked-blogs-threat">worm is out in the wild</a> exploiting a security vulnerability. This is leading to somewhat unfair comparisons with Windows, and thoughtful articles from <a href="http://daringfireball.net/2009/09/regarding_wordpress_and_security">John Gruber</a> and <a href="http://idlewords.com/2009/09/how_to_not_get_your_blog_hacked.htm">Maciej Ceglowski</a>.</p>
<p>To be sure, the ease of programming in PHP leads a great many people to contribute to projects, who may not have the experience or security awareness they should. This is not helped by poorly designed features in PHP that were enabled by default in previous versions, and cannot always be disabled outright due to legacy compatibility concerns, reminiscent of the persistent security woes due to the C standard library&#8217;s insecure old string processing facilities.</p>
<p>For many users, migrating away from WordPress may not be a practical option. My recommendations would be:</p>
<ul>
<li>Reduce your exposure by exporting a static HTML version of your site, as suggested by Maciej. This is really only simple if you use a non-default permalink structure that does not use question mark characters in URLs, like that used by the SEO plugins. Otherwise you would need quite a bit of mod_rewrite jiggery-pokery to get it to work. In any case, this will also disable quite a bit of functionality on your site, such as comments.</li>
<li>If you are an Apache user, install <a href="http://www.modsecurity.org/">modsecurity</a>, a truly outstanding Apache module that acts as a firewall of sorts and will inspect requests for suspicious behavior like SQL injection attempts and malformed requests. Configuring modsecurity is not for the faint of heart, but there are some papers online like <a href="http://blogsecurity.net/projects/wordpress-modsecurity-paper.pdf">this one by Daniel Cuthbert</a> (PDF) that walk you through this. This is probably the single most significant thing you can do to make your WordPress blog safer.</li>
<li>Practice security in depth — keep regular backups of both your wordpress directory and database, so you can recover in case of attack, and if possible run WordPress in an isolated account with minimal privileges.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://majid.info/blog/securing-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mozilla Weave</title>
		<link>http://majid.info/blog/mozilla-weave/</link>
		<comments>http://majid.info/blog/mozilla-weave/#comments</comments>
		<pubDate>Sun, 19 Jul 2009 08:02:45 +0000</pubDate>
		<dc:creator>majid</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://majid.info/blog/?p=334</guid>
		<description><![CDATA[Mozilla Weave is a project of the Mozilla Labs to build synchronization of bookmarks, tabs, passwords and so on between multiple instances of the Firefox browser. It used to be a private beta, but with the release of version 0.4 &#8230; <a href="http://majid.info/blog/mozilla-weave/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://labs.mozilla.com/projects/weave/">Mozilla Weave</a> is a project of the Mozilla Labs to build synchronization of bookmarks, tabs, passwords and so on between multiple instances of the Firefox browser. It used to be a private beta, but with the release of version 0.4 recently, it has been opened up to the general public.</p>
<p>Where version 0.2 was pretty rough, 0.4 actually works quite well, even if it is not yet feature complete. Bookmarks and passwords are handled just fine. Furthermore, you can <a href="https://wiki.mozilla.org/Labs/Weave/0.3/Setup/Server">set up your own server</a>, all that is needed is PHP. Previous versions required WebDAV support, and the WebDAV module in nginx is not functional enough for Weave (or anything else, for that matter).</p>
<p>The first synchronization is painfully slow, but once it is done, later synchronizations are essentially instant. When combined with the Awesome bar&#8217;s tagging components, it has completely supplanted Del.icio.us for my bookmarking needs (I never liked the rewritten user interface).</p>
<p><img class="aligncenter size-full wp-image-346" title="Thomas Pink weave cufflinks" src="http://majid.info/blog/wp-content/uploads/2009/07/weave_cufflinks.jpg" alt="Thomas Pink weave cufflinks" width="500" height="388" /></p>
<p>Amusingly,  I came across these cufflinks at Thomas Pink in San Francisco last Friday — they are the mirror image of the Weave logo.<br />
<img class="aligncenter size-full wp-image-346" title="Thomas Pink weave cufflinks" src="http://majid.info/blog/wp-content/uploads/2009/07/weave-header.png" alt="Thomas Pink weave cufflinks" width="600" height="200" /></p>
<p>Below are the relevant sections of my nginx config.<br />
magic_quotes_gpc = Off<br />
session.auto_start = 0<br />
file_uploads = On<br />
error_reporting = E_ALL &amp; ~E_NOTICE<br />
allow_url_include = Off<br />
allow_url_fopen = Off<br />
session.use_only_cookies = 1<br />
session.cookie_httponly = 1<br />
expose_php = Off<br />
display_errors = Off<br />
register_globals = Off<br />
disable_functions = phpinfo<br />
error_log = /home/majid/web/logs/php_error_log</pre>
<h2>nginx.conf</h2>
<pre>
root /home/majid/web/html;
location ~ .php$ {
  auth_basic		"gondwana";
  auth_basic_user_file	/home/majid/web/conf/htpasswd;
  fastcgi_pass		127.0.0.1:8888;
  fastcgi_index		index.php;
  fastcgi_param		SCRIPT_FILENAME  /home/majid/web/html$fastcgi_script_name;
  include		/home/majid/web/conf/fastcgi.conf;
}
# Mozilla Weave
rewrite ^/weave/admin$	/weave/admin.php;
location /0.3/api {
  return		404;
}
location /0.3/user {
  fastcgi_pass		127.0.0.1:8888;
  fastcgi_index		index.php;
  include		/home/majid/web/conf/fastcgi.conf;
  fastcgi_param		SCRIPT_FILENAME	/home/majid/web/html/weave/index.php;
  fastcgi_param		SCRIPT_NAME	/home/majid/web/html/weave/index.php;
  if ( $request_uri ~ "/0.3/user/([^?]*)" ) {
    set $path_info	/$1;
  }
  fastcgi_param		PATH_INFO	$path_info;
}</pre>
<h2>fastcgi.conf</h2>
<pre>fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx;

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;</pre>
]]></content:encoded>
			<wfw:commentRss>http://majid.info/blog/mozilla-weave/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>@font-face embedding</title>
		<link>http://majid.info/blog/font-face-embedding/</link>
		<comments>http://majid.info/blog/font-face-embedding/#comments</comments>
		<pubDate>Fri, 10 Jul 2009 20:01:16 +0000</pubDate>
		<dc:creator>majid</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://majid.info/blog/?p=317</guid>
		<description><![CDATA[I updated my wife&#8217;s home page to use embedded fonts (in this case the Fonthead GoodDog typeface for headings) with the @font-face CSS primitive. With the introduction of Firefox 3.5, all the major browsers now support embedded typography. As usual, &#8230; <a href="http://majid.info/blog/font-face-embedding/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I updated my wife&#8217;s <a href="http://www.shaheenbilgrami.com/">home page</a> to use embedded fonts (in this case the Fonthead <a href="http://www.fonthead.com/fonts/GoodDog">GoodDog</a> typeface for headings) with the <a href="http://craigmod.com/journal/font-face/">@font-face</a> CSS primitive. With the introduction of Firefox 3.5, all the major browsers now support embedded typography.</p>
<p>As usual, Microsoft had to do its proprietary thing in Internet Exploder and devised a crackpot font format called EOT (Embedded OpenType), ostensibly at font foundries&#8217; request, with weak DRM-like metadata that allows the font supplier to restrict which sites the font can be used on. Microsoft has an incredibly convoluted tool called WEFT (Web Embedded Font Tool) to do this, but I used the open-source and incredibly easy to use <a href="http://code.google.com/p/ttf2eot/">ttf2eot</a> tool instead. The only hitch in this case was that this tool takes a TrueType TTF font as input, and GoodDog is a (PostScript-ish) OpenType OTF instead. Fortunately, <a href="http://www.fontlab.com/font-editor/typetool/">TypeTool</a> can do the conversion.</p>
<p>We finally have semi-decent typography on the web without having to embed images (bad for page load times or accessibility) or the even worse sIFR hacks using the noxious Adobe Flash. The only question remains whether type foundries will follow. Fonthead has enlightened licensing policies for GoodDog (free for up to 5 sites, no insistence on DRM). Typeface design is a painstaking craft and designers certainly deserve what they charge for their fonts, but I hope the typographic industry does not follow the RIAA in its self-destructive crusade against its own customers.</p>
<p>Update (2011-03-03):</p>
<p>One option for hassle-free embedded font licensing is <a href="http://www.typekit.com/">TypeKit</a>. It does require JavaScript in the browser to work, unlike a pure CSS solution like the one I used, but the convenience can&#8217;t be beat. We use it on Apsalar&#8217;s <a href="http://apsalar.com/">public website</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://majid.info/blog/font-face-embedding/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Feedburner down again</title>
		<link>http://majid.info/blog/feedburner-down-again/</link>
		<comments>http://majid.info/blog/feedburner-down-again/#comments</comments>
		<pubDate>Thu, 30 Apr 2009 01:34:37 +0000</pubDate>
		<dc:creator>majid</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://majid.info/blog/?p=264</guid>
		<description><![CDATA[I just tried unsuccessfully to subscribe to a feed hosted by the annoying bozos at FeedBurner. From my Temboz feed error counters, it seems FB feeds have been failing with 503 errors for at least the last 5 hours or &#8230; <a href="http://majid.info/blog/feedburner-down-again/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I just tried unsuccessfully to subscribe to a feed hosted by the annoying bozos at FeedBurner. From my Temboz feed error counters, it seems FB feeds have been failing with 503 errors for at least the last 5 hours or so, par for the course.</p>
<p>Just another reason why outsourcing vital services to the cloud is not always a good strategy.</p>
<pre>
gondwana ~&gt;GET -eUS http://feeds.feedburner.com/Fooducate
GET http://feeds.feedburner.com/Fooducate
User-Agent: lwp-request/1.39

GET http://feeds.feedburner.com/Fooducate --&gt; 503 Service Unavailable
Connection: close
Server: NS_6.1
Content-Length: 62
Client-Date: Thu, 30 Apr 2009 01:31:18 GMT
Client-Peer: 66.150.96.119:80

&lt;HTML&gt;
&lt;HEAD&gt;&lt;TITLE&gt;An Error Occurred&lt;/TITLE&gt;&lt;/HEAD&gt;
&lt;BODY&gt;
&lt;H1&gt;An Error Occurred&lt;/h1&gt;
503 Service Unavailable
&lt;/BODY&gt;
&lt;/HTML&gt;
</pre>
<p>Update (2009-04-30):</p>
<p>It is possible the problem lies with my ISP (although I could replicate it at work as well). I can ping FB from my Joyent accelerator but not from home where my Temboz instance runs.</p>
<p>A work-around is to use the newer Google server <tt>feeds2.feedburner.com</tt> instead. For Temboz, all you need to do is run <tt>sqlite3 rss.db</tt> and the command:</p>
<pre>
update fm_feeds
set feed_xml=replace(feed_xml, 'feeds.feedburner.com', 'feeds2.feedburner.com')
where feed_xml like 'http://feeds.feedburner%';
</pre>
]]></content:encoded>
			<wfw:commentRss>http://majid.info/blog/feedburner-down-again/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The importance of short iteration feedback cycles</title>
		<link>http://majid.info/blog/the-importance-of-short-iteration-feedback-cycles/</link>
		<comments>http://majid.info/blog/the-importance-of-short-iteration-feedback-cycles/#comments</comments>
		<pubDate>Sat, 20 Sep 2008 17:47:25 +0000</pubDate>
		<dc:creator>majid</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://majid.info/blog/?p=68</guid>
		<description><![CDATA[I blog at best once or twice a month on my regular low-intensity blog, which runs my home-grown Mylos software, but am surprising myself by blogging on an almost daily schedule with this WordPress-based blog. Mylos is batch-based: you edit &#8230; <a href="http://majid.info/blog/the-importance-of-short-iteration-feedback-cycles/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I blog at best once or twice a month on my regular low-intensity blog, which runs my home-grown <a href="http://www.majid.info/mylos/stories/2003/06/18/mylos.html">Mylos</a> software, but am surprising myself by blogging on an almost daily schedule with this WordPress-based blog. Mylos is batch-based: you edit a post, run the script to regenerate the static pages, review, edit and iterate. It takes a minute to regenerate the entire site.</p>
<p>This is a similar effect to using an interpreted language like Python or PHP vs. a compiled language like C or Java. Even though I am more comfortable editing in Emacs (used by Mylos) than in a browser window, the short cycle between edit and preview in WordPress makes for a more satisfying experience and encourages me to blog more freely.</p>
<p>I suspect I will end up importing my Mylos weblog into WordPress, once I figure out how to address some niggling differences in functionality, such as the way images or attachments are handled, and how to use nginx as a caching reverse proxy in front of WordPress for performance reasons.</p>
]]></content:encoded>
			<wfw:commentRss>http://majid.info/blog/the-importance-of-short-iteration-feedback-cycles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazon wishlist optimizer</title>
		<link>http://majid.info/blog/amazon-wishlist-optimizer/</link>
		<comments>http://majid.info/blog/amazon-wishlist-optimizer/#comments</comments>
		<pubDate>Tue, 22 Nov 2005 05:49:23 +0000</pubDate>
		<dc:creator>majid</dc:creator>
				<category><![CDATA[Economics]]></category>
		<category><![CDATA[Stuff]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Mylos]]></category>

		<guid isPermaLink="false">http://www.majid.info/mylos/weblog/2005/11/21-1.html</guid>
		<description><![CDATA[I wrote a script several months ago to go through an Amazon wish list and find the combination of items that will best fit within a given budget. Given that the Christmas holiday shopping season seems to have started before &#8230; <a href="http://majid.info/blog/amazon-wishlist-optimizer/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I wrote a script several months ago to go through an Amazon wish list and find the combination of items that will best fit within a given budget. Given that the <span style="text-decoration: line-through;">Christmas</span> holiday shopping season seems to have started before Thanksgiving, it seemed topical to release it.</p>
<p>It used the Amazon Web Services API, which is a complete crock (among other failings, it will consistently not return the Amazon.com price for an item, even when explicitly instructed to do so). It does not look like Amazon pays any particular attention to the bug reports I filed. I just gave up on the API and re-implemented it the old-fashioned way, by &#8220;scraping&#8221; Amazon&#8217;s regular (and most definitely <em>not</em> XML-compliant) HTML pages.</p>
<p>It is still very much work in progress, but already somewhat useful. You can use it directly by stuffing your wish list ID in the URL (or using the form below):</p>
<form action="http://www.majid.info/cgi/amawish.cgi" method="get">
<table>
<tr>
<td>Wish list ID</td>
<td>
<input name="wl_id" value="P735P8BBZV3S" /></td>
<td>Amount</td>
<td>
<input name="amt" size="4" value="100" /></td>
<td>
<input type="submit" value="Optimize" /></td>
</tr>
</table>
</form>
<p></p>
<p>A better way is to drag and drop the highlighted <a style="background-color: yellow;" href="javascript:d=document;var ref=d.location.href;for (var f in document.forms) { if (document.forms[f].action &amp;&amp; document.forms[f].action.indexOf('/registry/wishlist/')!=-1) {ref=document.forms[f].action} };void(open('http://www.majid.info/cgi/amawish.cgi?client=bookmarklet&amp;ref='+escape(ref)))">Amazon optimizer</a> bookmarklet link (version 6 as of 2007-05-08) to your browser&#8217;s toolbar. You can then browse through Amazon, and once you have found the wish list you are looking for, click on the bookmarklet to open the optimizer in a new window (or tab). By default, it will try and fit a budget of $100 (my decadent tastes are showing, are they not?), but you can change that amount and experiment with different budgets. Surprisingly often, it will find an exact fit. Otherwise, it will try to find the closest match <em>under</em> the budget with as little left over as possible.</p>
<p>There are many caveats. The wishlist optimizer only works for public Amazon.com (US) wish lists. There does not seem to be an easy way to buy multiple items for somebody else&#8217;s wish list in one step, although I am working on it, so you will have to go through the wish list and add the items by hand. Shipping costs and wish list priorities are currently not taken into account. Sometimes Amazon will not show a price straight away but instead require you to click on a link, the optimizer will decline to play these marketer&#8217;s games and just skip those products.</p>
<p>Be patient &#8211; Amazon.com is rather slow right now — it seems they did not learn the lessons of their poor performance towards the end of last year. One of my coworkers ran the optimizer through an acid test with his wife&#8217;s 13-page wish list, and it took well over a minute and half to fetch the list, let alone optimize it. One can only imagine how bad it will get when the Christmas shopping season begins in earnest. To mitigate this somewhat, I have added caching &#8211; the script will only hit Amazon once per hour for any given wish list. As it works by scraping the web site rather than using the buggy and unreliable Amazon Web Services API, there is a real risk it will stop working if Amazon blocks my server&#8217;s IP or if they radically change their wish list UI (they would do better to add additional machines and load-balancers, but that would be too logical).</p>
<p>Update (2005-12-02):</p>
<p>Predictably, Amazon changed their form (they changed the form name from <tt>edit-items</tt> to <tt>editItems</tt>) and broke not only the wishlist optimizer, but also the bookmarklet. I fixed this and upgraded to the scraping module <a href="http://www.crummy.com/software/BeautifulSoup/">BeautifulSoup</a>, but you will need to use the revised bookmarklet above to make it work again.</p>
<p>Update (2010-04-27):</p>
<p>The script has been broken for quite a while, but I fixed it and it should work again.</p>
]]></content:encoded>
			<wfw:commentRss>http://majid.info/blog/amazon-wishlist-optimizer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

