echo "hey, it works" > /dev/null

just enough to be dangerous

WordPress 2.3, the Connections theme, and tags


I've just upgraded to WordPress 2.3 and, while the process was pretty painless, for some reason tags weren't working, even after I added tag support to the theme using the_tags() in The Loop. The problem turned out to be that The Loop in the Connections theme uses deprecated function calls. To enable tagging in the Connections theme edit index.php and find the following code.

<?php if ($posts) : foreach ($posts as $post) : start_wp(); ?> 
    <div class="post">
        <?php require('post.php'); ?>
        <?php comments_template(); // Get wp-comments.php template ?>
    </div>
<?php endforeach; else: ?>
    <p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>

This is The Loop. You need to replace it with this code.

<?php if (have_posts()) : ?>
  <?php while (have_posts()) : the_post(); ?>
    <div class="post">
      <?php require('post.php'); ?>
      <?php comments_template(); // Get wp-comments.php template ?>
    </div>
  <?php endwhile; ?>
<?php else: ?>
  <p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>

You need to make a similar change to single.php, category.php, date.php and search.php.

Finally, you need to edit post.php and add a call to thetags() somewhere. You can add it anywhere, depending on how you want the post laid out. I added thetags(', tagged ', ', ', ''); after the call to the_category().

Implementing WSSE authentication in WordPress


I was excited to learn recently that the Nokia N73 can speak AtomPub, and that a friend of mine owns one. I thought I'd try to make it talk to the new AtomPub implementation in WordPress, but reading through the N73 documentation I found that it only supports WSSE authentication, and WordPress only speaks HTTP Basic Authentication. I'd never heard of WSSE, but Mark Pilgrim has a good write up on XML.com, and the Ape has the ability to speak WSSE, so I thought I'd implement it in WordPress. Bear in mind that I'm not writing this from a security point of view, I'm just looking at authentication as a necessary evil to get cool AtomPub things working. And there's a spoiler: it can't be done :)

A WSSE client will send an Authorization header which, as we know, will get dropped if Apache is passing the request off to a CGI, and a X-WSSE header that looks like this:

X-WSSE: UsernameToken Username="USERNAME", PasswordDigest="PASSWORDDIGEST", Nonce="NONCE", Created="2007-09-08T05:52:36Z"

PasswordDigest is a base64 encoded SHA1 digest of the concatenation of the nonce, the timestamp and the password. The nonce is of course some random string.

So, to add WSSE into WordPress AtomPub, we can add some code to the authentication function in wp-app.php.

First, we check if the client is trying to authenticate using WSSE by looking for a X-WSSE header.

if(isset($username<em>token = $</em>SERVER['HTTP<em>X</em>WSSE'])) {

We then take the Username Token contained therein and split out the user, digest, nonce, created information sent by the client. There are probably nicer ways to do this.

$wsse = array( 'user' => "", 'digest' => "", 'nonce' => "",
                   'created' => "", 'password' => "");
    $tokens = explode(", ", trim(strstr(stripslashes($username_token), " ")));
    foreach ($tokens as $token) {
        $pivot = strpos($token, '=');
        $key = substr($token, 0, $pivot);
        $value = trim(substr($token, $pivot + 1), '"');
        switch ($key) {
        case "Username":
            $wsse['user'] = $value;
            break;
        case "PasswordDigest":
            $wsse['digest'] = $value;
            break;
        case "Nonce":
            $wsse['nonce'] = $value;
            break;
        case "Created":
            $wsse['created'] = $value;
            break;
        }
    }

Finally, we recreate the digest on the server, and compare it to what was sent, and close the if.

$wsse['password'] = get<em>password</em>by<em>login($wsse['user']);
    $server</em>digest = base64['encode(pack("H*", sha1($wsse['nonce'] . $wsse['created'] . $wsse['password'])));
    if ($server_digest == $wsse['digest']) {
        $login_data = array('login' => $wsse['user'], 'password' => $wsse['password']);
    }
}

If you have familiarity with WordPress's code, you might be saying something like, "WTF is this getpasswordby_login() function call? I've never seen such a thing!" Good question. And the dirty little secret is that no such function exists. A weakness of the WSSE authentication scheme appears to be that to recalculate the digest the password needs to be stored in plain text on the server. This is probably at least as bad as sending the password in plain text over the wire, the thing that WSSE is trying to avoid. WordPress, sensibly, does not store passwords in plain text, but computes an md5 hash of them and stores that.

So, as far as I can tell, there is no way to implement WSSE in WordPress in any sensible way.

One little word on security. If we could implement WSSE, the code should keep track of nonces and make sure they aren't repeated, and should reject UsernameTokens created more than a couple of minutes ago (leaving aside any discussion of synchronisation of your client's clock with my server).

P.S. I hadn't read Joe Cheng's comment or Joseph Scott's reply in the comments of the post I linked to above before I started off on this wild goose chase.

PUT and DELETE dropped on the floor


I mentioned previously that the AtomPub server in my WordPress installation wasn't successfully deleting entries. More specifically, I get a 403 Forbidden when trying to PUT or DELETE posts or media files. I posted to the wp-testers mailing list and Joseph Scott passed the question along to Sam Ruby, Tim Bray, Elias Torres, and Pete Lacey, and I basically eavesdropped on their conversation.

Turns out that the problem is likely to be a firewall rejecting PUTs and DELETEs. This started a discussion of how WordPress should workaround the problem. Some options are URL munging, custom headers, or message in a message. All horrible for various and obvious reasons, and none going to make it into 2.3. Sam cautioned, and suggested revisiting PacePutDelete, a method proposed by Joe Gregorio on the Atom lists to overcome a lack of PUT and DELETE support on clients, which led me off on a fascinating journey through the Atom mailing list archives.

I'm not sure how big the problem really is now. It may take more time and effort to come up with a "fix" than it would to lobby purveyors of broken internet devices to really fix them. The biggest concern with a workaround, however, is that it may slow said fix. Why should we fix our firewall when your client can just use X-Method-That-Really-Is: delete? If such a workaround is implemented it should be a fallback in case a correct request fails.

It sure is frustrating that the solution is baked right in to HTTP.

Indenting your code


In HTML whitespace is not treated as significant, and therefore it gets collapsed. This is a problem when you want to publish code because your indenting will disappear. The most common way around this is to wrap code in a pre element, but that looks like crap because it's always the default monospace font, and you can't style it. A better way is to use CSS, specifically white-space: pre;.

In WordPress, log in to the admin section, click Presentation and select Theme Editor. Choose Stylesheet from the list on the right, then look for the code declaration. Add white-space: pre; and you're done. Now, whenever you want to display code, wrap it in a code element.

WordPress AtomPub FAQ


I've posted a small WordPress AtomPub FAQ. It's a temporary home until I can find somewhere sensible to put it. If you have anything you'd like to add or correct or mock, comment here. If you can offer a sensible place to put it, let me know.

Changing the format of WordPress quote posts


The WordPress 'new post' bookmarklet lets you highlight some text on a page, run the bookmarklet and redirects you to your admin new posts page with the title prefilled with the title of the page you were on and the content prefilled with a link to the page you were on and the text you had highlighted. However, the default layout isn't the way I like to do quote posts, so I had a poke around to find out how to change it.

In the file wp-admin/admin-functions.php there is a function getdefaultposttoedit(). Midway through the function the variable $post_content is set with an HTML snippet. Edit this snippet to how you would like quotes to be displayed.

I wonder what The Right Way to do this is.

AtomPub and WordPress


So, WordPress 2.3 beta adds support for AtomPub. All good. I installed it (separately to this blog, I'm just playing around), but all I could get out of the APE was a 401, even though I'd provided the correct authentication credentials. Looking at the code, with liberal use of the logging therein, I worked out that PHPAUTH* weren't being set, so I pulled out some auth code and tried it on it's own. No luck. Weird. I then grabbed a previously working snippet and tried that, but it was broken too. On both the servers to which I have easy access. I sent the snippet to Donal, and the snippet worked for him. WTF?

Turns out, that both the servers I was testing on are running PHP as a CGI, not using modphp, and if PHP is being run as a CGI PHPAUTH_* aren't available. Who knew? Well, someone, but not me. And they knew a workaround too.

Thanks for your help, Donal! And to all the cool people who are working on this (Elias Torres, Pete Lacey, Sam Ruby, Tim Bray get special mention).

The APE now exercises my beta blog. Now I have to work out why it can't delete stuff ...

WordPress links fixed


So, now links work. I had decided to change the permalink mode from the "ugly" default to "almost pretty", which makes permalinks look like http://www.twofishcreative.com/michael/blog/2007/02/27/wordpress-woes/. What I didn't do was create an .htaccess file so that WordPress could use apache's mod_rewrite to make sure that those almost pretty links actually work. All I needed to do was ssh to my host, change to my blog directory and

% touch .htaccess
% chmod 666 .htaccess

Then when I chose the almost pretty permalink option WordPress updated the .htaccess file to include the necessary rewrite rules. More information can be found under the Wordpress permalinks documentation.