3rd party JS libraries cause downtime

Facebook Connect went down hard tonight. HuffPo reports that their site was redirecting to a Facebook error page, even when people weren’t attempting to log in.

It makes me more comfortable with our decision to strip so many 3rd party javascripts from GigaOM during our last redesign.

WordPress MU/MS Empty Header and Broken Image Bug Fixed

I just switched to a new server and found myself struggling with empty HTTP headers and broken or partial images. The problem is the memcache extension for PHP and WordPress MU/WordPress multisite’s need to reinstantiate the wp-cache after determining the correct blog for a given request.

Versions of the memcache extension prior to 3.0 go wrong somehow and it shows up when you try to do an HTTP HEAD request on a page (the result is empty) or enable X-SendFile support for WP MU/MS’ file handling (all the files and images in the media library will break). Upgrading to the the 3.x version (in beta since 2007) fixes the problem.

You may have to uninstall the old version before installing the beta, and installing the beta via PECL requires adding “-beta” to the package name. Here are the commands:

pecl uninstall memcache
pecl install memcache-beta

URL Path Bug In WordPress.com Video Server

You’ve got to both respect Automattic for releasing their internal code as open source while also giving them a break for not assuring that it works for anybody else. One of their projects, the WordPress.com Video Server is a sophisticated WordPress plugin that handles video transcoding and offers a bit of a YouTube in a box solution for WordPress.

The bug I found is that the code assumes WPMU is running in subdomain mode, rather than subdirectory mode. This assumption causes an ajax request to go to the wrong URL and return the wrong data. The patch simply applies WordPress’ plugins_url() function that debuted in 2.6.

WordPress Bug In setup_postdata()

WordPress is built around the Loop, and all the cool kids are using multiple loops on the same page to show the main post and feature other posts. The problem is: WordPress doesn’t properly reset the $pages global for each post. If the post in main loop (or default query) is paged, then all the other posts will show the same paged content as in the main post. I started a ticket and submitted a patch, but in the meantime you might have to unset( $GLOBALS['pages'] ) in your custom loops just before calling the_post().

Drobo: Sweet Storage, One Big Flaw

I’ve been a fan of Drobo since I got mine over a year ago. The little(-ish, and sweet looking, for stack of disks) device packs as many as four drives and automatically manages them to ensure the reliability of your data and easy expandability of the storage. However, Thomas Tomchak just pointed out one major […] » about 300 words

Uploading .docx Files In WordPress

It may be a sign that none of the core WordPress developers much likes or uses Microsoft Office, but the core code hasn’t been updated to recognize the Office 2007 file extensions like .docx, .pptx, or .xlsx. It’s no criticism, wouldn’t have discovered it if a user hadn’t complained, and I stewed a bit before deciding it was a bug.

It’s now ticket #8194 in the WordPress.org Trac. It only affects my MU users now, though, and the same patch works there.

You’ll find a few mentions of doc, ppt, and xls in wp-includes/functions.php (around lines 1613-1615 and 1651-1654 in 2.6.3). Once corrected, those lines should look something like this:

``` 'document' => array('doc','docx','pages','odt','rtf','pdf'), 'spreadsheet' => array('xls','xlsx','numbers','ods'), 'interactive' => array('ppt','pptx','key','odp','swf'), ```
``` 'doc|docx' => 'application/msword', 'pot|pps|ppt|pptx' => 'application/vnd.ms-powerpoint', 'wri' => 'application/vnd.ms-write', 'xla|xls|xlsx|xlt|xlw' => 'application/vnd.ms-excel', ```

Update: Sweet! It’s been accepted and should be in the WP2.7 release.

WordPress Bug: Duplicate post_meta Entries

I just submitted a trac ticket about this:

The update_post_meta() and delete_post_meta() functions don’t know how to deal with post revision IDs. add_post_meta() does, it uses the following block of code to make sure the passed $post_id is a real post, not a revision:

``` if ( $the_post = wp_is_post_revision($post_id) ) $post_id = $the_post; ```

This is important because the global $post_id when a post is being saved is for the revision, not the real post. If you pass that to these functions, update_post_meta() and delete_post_meta() will try to update or delete the records related to the revision. When update_post_meta() fails to find any records for the post_id you submitted, it calls add_post_meta(). Each attempt at updating the meta will actually create a new row in the table.

For now I’m checking with wp_is_post_revision() before making any calls to the post_meta functions.

Updated: Mark Jaquith committed the patch less than two hours after I submitted it! I love WP.

MySQL Bug?

After an upgrade to MySQL 5.0.51b on RHEL 5 I started seeing curious results in a fairly common query. Here’s a simplified version:

``` SELECT ID, post_date_gmt FROM wp_posts GROUP BY ID ORDER BY post_date_gmt DESC LIMIT 5 ```

What I expected was to get a handful of post ID numbers sorted in descending order by the post_date_gmt. Instead, I got a list of post IDs sorted in ascending order by the ID number. Something like this:

``` 3 2007-05-21 00:00:00 4 2007-05-21 00:00:00 5 2007-05-21 00:00:00 6 2007-05-21 00:00:00 7 2007-05-21 00:00:00 ```

After some fiddling I discovered that the GROUP BY clause was causing a problem. So this query works:

``` SELECT ID, post_date_gmt FROM wp_posts ORDER BY post_date_gmt DESC LIMIT 5 ```

…and outputs the results I expected:

``` 337832 2008-06-20 15:20:03 335991 2008-06-17 13:00:42 337777 2008-06-02 12:15:46 337390 2008-05-28 00:00:00 337831 2008-05-28 00:00:00 ```

The GROUP BY clause may be unnecessary, though it was originally written in to accommodate conditions where a JOIN (which is often added when the query is dynamically generated) causes MySQL to return multiple rows representing the same record ID.

Still, isn’t this behavior weird? It’s certainly different from previous versions.

Many Eyes, Bugs Being Shallow, All That

WordPress 2.5.1 added a really powerful feature to register_taxonomy(): automatic registration of permalinks and query vars to match the taxonomy. Well, theoretically it added that feature. It wasn’t working in practice. After some searching yesterday and today, I finally found the bug and worked up a fix. I made a diff and set off to […] » about 200 words

bsuite Bug Fixes (release b2v7)

Contentsbsuite FeaturesFixed/Changed/AddedInstallationUpgradingCommandsClear bsuite_speedcacheRebuild bsuite tag indexOptionsMinimum userlevel to view bsuite reportsOutput default CSSDefault pulse graph styleSuggest related entries in postTag input formatHighlight search words and offer search helpFilter incoming search terms using comment moderation and blacklist wordsIgnore hits from registered users at or above userlevelIgnore hits from these IP numbersTag SupportUsing bsuite FunctionsKnown BugsMoney GrubbingWork […] » about 800 words

Displaying Google Calendars in PHP iCal

PHP iCalendar solves a couple problems I’m working on, but I needed a solution to fix the duration display for Gcal-managed ICS calendars.

As it turns out, a fix can be found in the forums, and the trick is to insert the following code in functions/ical_parser.php.

case 'DURATION':
	if (($first_duration == TRUE) && (!stristr($field, '=DURATION'))) {
		ereg ('^P([0-9]{1,2}[W])?([0-9]{1,2}[D])?([T]{0,1})?([0-9]{1,2}[H])?([0-9]{1,2}[M])?([0-9]{1,}[S])?', $data, $duration); 
		$weeks = str_replace('W', '', $duration[1]);
		$days = str_replace('D', '', $duration[2]);
		$hours = str_replace('H', '', $duration[4]);
		$minutes = str_replace('M', '', $duration[5]);
		$seconds = str_replace('S', '', $duration[6]);
		// Convert seconds to hours, minutes, and seconds
		if ($seconds > 60) {
			$rem_seconds = $seconds % 60;
			$minutes = $minutes + (($seconds - $rem_seconds) / 60);
			$seconds = $rem_seconds;
		if ($minutes > 60) {
			$rem_minutes = $minutes % 60;
			$hours = $hours + (($minutes - $rem_minutes) / 60);
			$minutes = $rem_minutes;
		$the_duration = ($weeks * 60 * 60 * 24 * 7) + ($days * 60 * 60 * 24) + ($hours * 60 * 60) + ($minutes * 60) + ($seconds);
		$first_duration = FALSE;

Hopefully this gets worked into the baseline with the next release.

Catching Bugs Before They Catch You

I got itchy about magic quotes the other day because it’s the cause (through a fairly long cascade of errors) of some performance problems and runaways I’ve been seeing lately (pictured above). But I deserve most of the blame for allowing a query like this to run at all: SELECT type, data, count(*) AS hits […] » about 300 words

bsuite Bug Fixes (release b2v6)

Contentsbsuite FeaturesFixed/Changed/AddedInstallationUpgradingCommandsOptionsTag SupportUsing bsuite FunctionsKnown BugsUpdate: bugfix release b2v7 available. It’s been a while since I released a new version of bsuite, my multi-purpose WordPress plugin. I’d been hoping to finish up a series of new features, but those have been delayed and this is mostly just a collection of bugfixes. This update is recommended […] » about 500 words

bsuite Bug Fixes (release b2v3)

ContentsFixedInstallationbsuite FeaturesI’ve fixed another bug in bsuite b2, my multi-purpose plugin. This update is recommended for all bsuite users. Fixed Previous versions would throw errors at the bottom of the page when the http referrer info included search words from a recognized search engine.  Installation Follow the directions for the bsuite b2 release. The download […] » about 300 words

bsuite Bug Fixes (release b2b)

ContentsFixesInstallationbsuite FeaturesI’ve fixed a couple bugs in bsuite b2, released last week. Fixes A bug with search word highlighting that caused it to litter the display in some cases.  A silly mistake of mine that cause a mysql error for some users. Installation Follow the directions for the bsuite b2 release. The download link there […] » about 300 words