WordPress 2.6 – XML-RPC & AtomPub Changes

WordPress 2.6 has been released.

For those of you interested in keeping up with XML-RPC & AtomPub changes in WordPress, here’s what has changed from 2.5.1 to 2.6:

XML-RPC

  • The starify function was removed from xmlrpc.php (ticket 6634)
  • New method – wp.getUsersBlogs see Blog ID in WordPress and XML-RPC Blog APIs for some background (ticket 7130)
  • New field – xmlrpc in blogger.getUsersBlogs (same background as above, ticket 7130)
  • New method – wp.getPageTemplates (ticket 6098)
  • New field – wp_page_template in the wp.getPage method (ticket 6098)
  • New method – wp.getOptions (ticket 7123)
  • New method – wp.setOptions (ticket 7123)
  • Added support for enclosures in metaWeblog.newPost and metaWeblog.editPost (ticket 3405)
  • The <!––more––> tag is no longer embeds newlines before and after in metaWeblog.newPost and metaWeblog.editPost (ticket 6016)
  • XML-RPC is disabled by default for new installs of WordPress. Upgrading will NOT disable XML-RPC (ticket 7157)

AtomPub

  • If $_SERVER['ORIG_PATH_INFO'] is set, we use that instead of $_SERVER['PATH_INFO'] in determining the $path value (ticket 6995)
  • Fixed problem where using clean URLs (instead of ?p=1 style) would cause wp-app.php/posts requests to return zero posts (ticket 7249)
  • AtomPub is disabled by default for new installs of WordPress. Upgrading will NOT disable AtomPub (ticket 7157)

Since the story around disabling XML-RPC & AtomPub by default has gone through a few twists, I’ll re-state the current situation: new installs of WordPress will have XML-RPC and AtomPub access disabled by default, upgrades of WordPress to version 2.6 from previous versions will not have XML-RPC and AtomPub disabled as part of the upgrade process. There is no check box for enabling these services during the install or upgrade. The process for turning them back on are simple check boxes in wp-admin under Settings -> Writing.

On the security front, there are no known security issues in XML-RPC or AtomPub. If you think you’ve discovered one please email the details to security@wordpress.org.

Another point that I’ve seen a few folks bring up is the feeling that this is just the first step in removing XML-RPC and/or AtomPub entirely or that they’ll stop getting new features. These features are not going away and as for continued development and new features, go back and read the top of this post. That said, we can definitely use more people looking at the XML-RPC and AtomPub code.

If you are interested in XML-RPC/AtomPub, please come join us on the wp-xmlrpc email list.

WordPress 2.6 to Have XML-RPC & AtomPub Disabled by Default

As westi has already noted, the next version of WordPress will have XML-RPC and AtomPub disabled by default. It’s easily turned on via an option in wp-admin, and can be enabled during installation as well.

This reduces the number of potential ways an attacker can break in. To be clear though, I’m not aware of any current security issues with XML-RPC or AtomPub in WordPress.

Blog ID in WordPress and XML-RPC Blog APIs

If you’ve done any sort of work with XML-RPC blog APIs on WordPress you’ve come across blog_id. What blog_id does and does not do in WordPress can be a bit confusing though.

Lets look at the metaWeblog.* XML-RPC methods to get an idea of what the problem looks like. Here’s the metaWeblog.newPost method:

metaWeblog.newPost( blog_id, username, password, struct, publish )

The WordPress implementation of this method doesn’t use the blog_id value at all. For all intents and purposes it is thrown away, only using the last four parameters. It’s kept in the parameter list though in an effort to be compatible with other implementations of metaWeblog.newPost.

For regular WordPress installs that isn’t too confusing. There is some very limited internal use of blog_id, just none at the XML-RPC level. Where things go a little side ways is with WordPress MU (WPMU), which is what WordPress.com uses. WPMU uses the blog_id value quite a bit, since it has to manage multiple blogs.

One reason for including the blod_id in method calls like metaWeblog.newPost is because other services only have one XML-RPC end point (end point is just a URL). One example is TypePad, whose XML-RPC end point is http://www.typepad.com/t/api. This allows them to figure which blog the new post is being assigned to. For WPMU there is a unique XML-RPC end point for each blog, instead of just one for the whole WPMU install. Because of this WPMU doesn’t need the blog_id value to figure out which blog the new post is for because it can figure that out from the XML-RPC end point being used.

But wait, there’s more. Here’s metaWeblog.editPost:

metaWeblog.editPost( post_id, username, password, struct, publish )

You’ll notice that there’s no blog_id in the parameter list. For other services this isn’t an issue because they’ll generate unique post_id values not for just one blog, but for their whole service. WPMU doesn’t do that, post_id’s are only unique in each blog. A given WPMU install could have as many posts with a post_id of 1 as there are blogs setup.

So far all of these examples can be addressed by making sure that you point to the correct XML-RPC end point. But the metaWeblog.* methods aren’t the only APIs WordPress makes available, there’s also a subset of the blogger.* methods. One that really causes grief is blogger.getUsersBlogs:

blogger.getUsersBlogs( app_key, username, password )

Ignore the app_key parameter, WordPress does. The intent of this method was to let clients know what blogs a given user had access to. Once the user provided a username and password a client could then just ask the service for a list of all the blogs that the user had access to. Unfortunately for WPMU, clients would make certain incorrect assumptions once they’d asked blogger.getUsersBlogs for information.

Let’s use example.com has an example of a multi-blog site. I’ve got blogs at joseph.example.com, josephscott.example.com and helloworld.example.com. A blog client comes along and asks example.com/xmlrpc.php for a list of blogs that I have access to. They get a list back that looks something like:

{
	{
		url: http://joseph.example.com/,
		blogid: 123123,
		blogName: Joseph
	},
	{
		url: http://josephscott.example.com/,
		blogid: 321321,
		blogName: "Joseph Scott"
	},
	{
		url: http://helloworld.example.com/,
		blogid: 90909090,
		blogName: "Hello World"
	}
}

Nothing wrong so far, but it’s what I see blog clients do next that breaks things. Instead of querying each blog URL to find out what the XML-RPC end point is for each one, they assume that the end point that provided this data will work for all three. I’ve found this to be a very common assumption in blog clients. In this case it means that they send metaWeblog.newPost requests to example.com/xmlrpc.php. For services that have one global end point for all of their blogs this works fine, which works because they send along the unique blog_id value. This doesn’t work for WPMU because it throws away those blog_id values sent to it via XML-RPC methods.

At this point you might be thinking, well, gee, why don’t you just fix WordPress/WPMU to respect the blog_id and then everything will be fine. That was what I thought the first time I ran into this. I started digging through code, and then I ran into metaWeblog.editPost (and others) that don’t require a blog_id value. That’s when I realized that it wasn’t realistic to try and fix this. It would require WPMU to generate unique post_id values across all blogs, something that it does not do, and isn’t likely to be doing in the near future.

In order to minimize the confusion I changed the behavior of the blogger.getUsersBlogs method in WordPress. Instead of sending details for all the blogs that the user had access to, it only sent info for the one blog that it was talking to. Continuing with the example above, lets say the client had sent a blogger.getUsersBlogs request to josephscott.example.com/xmlrpc.php. The response would only contain data about josephscott.example.com. This effectively prevents the client from getting confused about example.com supporting blog_id and only using one global XML-RPC end point. The down side to this approach is that instead of the client being able to discover all of the other blogs that I have access to on example.com, I have to configure each one in the client.

Well, that isn’t completely true. If a client makes a blogger.getUsersBlogs to the master blog in an WPMU install it will still get a list of all the blogs that user has access to. In the example above that would be example.com/xmlrpc.php. This was necessary because some services querying WordPress.com depended on this. Those changes were generalized and are included as part of WPMU.

For blog clients that wanted access to a user blog list but don’t make the single end point assumption I added a new method, wp.getUsersBlogs:

wp.getUsersBlogs( username, password )

It returns the same data that blogger.getUsersBlogs does, with one additional field for each blog: xmlrpc. The xmlrpc field is the XML-RPC end point for each blog. This saves the client from having to go out and detect the end point for each blog. My hope was that if a client knew enough to ask for wp.getUsersBlogs it also knew enough not to make incorrect assumptions about what to do with that data.

Right now the wp.getUsersBlogs is only available on WordPress.com, but it will be hitting WordPress and WordPressMU soon.

It’s still possible that at some point we’ll do enough low level work in WordPress/WPMU to make things work in a manner similar to what others do with blog_id and post_id, but for now this is where things stand. If you are making use of the XML-RPC APIs in WordPress and wondered what the story was with blog_id’s, now you know.

Four Years of WordPress, One Year at Automattic

On April 16, 2007 I started working at Automattic, amazing how fast the last year has gone by. As I started gathering up details for what I’ve been doing this past year, I found that in April 2004 was when I started using WordPress to power this blog.

Four Years of WordPress

My first post on this blog was from April 30, 2004, using a beta of WordPress 1.2. First though, a little history.

In mid-2003 I figured it was time for me to get in on this “weblog” thing. Although I’d had various sites on the web since 1995, there was something about the order and structure of a blog that appealed to me. Like many others during this time I took a look at MovableType as one option to power my blog, since all the cool kids were using it (like Jeremy Zawodny, one of the blogs I’d been reading regularly). That didn’t last very long. I went on to try every piece of blog software that I could find, none of them really worked the way that I’d hoped they would.

Feeling that all the available options out there weren’t going to cut it, I started writing my own (another thing that seemly everyone else was doing at the time). I quickly got it up to the point where publicly it was good enough. I used that for months, while continuing to look at other options.

Fast forward to March/April 2004 where I finally found WordPress. It was being actively developed and was easily the best out of all the other options that I tried. And I had installed pretty much everything out there.

Since then I’ve published more than 1,000 posts with over 1,500 comments. I started using Akismet, which has blocked more that 500,000 pieces of spam.

One Year at Automattic

It is amazing that a whole year has gone by since my Friday the 13th post. Fortunately though it’s pretty easy to sum up. This job is freaking awesome!

The people at Automattic are amazing. At one point I had met everyone in the company, which is saying something since we are scattered all across the globe. Since then more people have come aboard, and I look forward to meeting them face to face latter this year.

Before joining Automattic full time in April 2007, I had been doing contract work starting back in January 2007. The result of that work was the new wp.* XML-RPC methods. For the most part I really enjoy working on XML-RPC, though some of the specific APIs that are built on top of it are a bit quirky.

Working on WordPress.com has been absolutely fascinating. The scale and growth are pretty impressive. Check out some of the stats and you’ll see what I’m talking about. We are fast approaching 3 million blogs. Not bad considering we hit 2 million in December 2007, some 4 months ago.

The Future

There are so many ways in which WordPress still has amazing amount of potential. In the social network sphere we are seeing things like BuddyPress and Diso. From the WordPress as a platform department there’s Prologue (which reminds me, I need to get a new version out the door, keep an eye on prologuetheme.org) and WP Contact Manager. Even good old XML-RPC will continue to see improvement as time goes on.

The next year will bring a few more releases of WordPress. What’s really exciting though is seeing how people will continue to take WordPress to new and different places.

WordPresss 2.5

WordPress 2.5 is officially out the door. Matt hits the long list of highlights of what is new in the release announcement. This coincides with the new layout at WordPress.rog. Peter Westwood (one of the WordPress core developers) put together a tag cloud of people who contributed to this release.

For the XML-RPC blog client developers out there 2.5 adds four new methods:

  • wp.deleteCategory( blog_id, username, password, category_id ) – Delete a category.
  • wp.getCommentCount( blog_id, username, password, post_id ) – Provides a struct of all the comment counts ( approved, awaiting_moderation, spam, total_comments ) for a given post_id. The post_id parameter is optional (or can be set to zero), if it is not provided then the same struct is returned, but for the entire blog instead of just one post.
  • wp.getPostStatusList( blog_id, username, password ) – Provides a struct of all the valid post statuses ( draft, pending, private, publish ) and their descriptions ( Draft, Pending Review, Private, Published ).
  • wp.getPageStatusList( blog_id, username, password ) – Provides a struct of all the valid page statuses ( draft, private, publish ) and their descriptions ( Draft, Private, Published).

To go along with the new status methods, you can now explicitly set the post and page status using the post_status and page_status fields. Like wise the status is also exposed via the various get* methods. One note about future posts, for the purposes of XML-RPC clients we set the post_status to publish when the actual database value is future.

The wp.suggestCategories method has been fixed to return data in the same format that it did originally. I never heard anyone complain about this though, so I guess it isn’t getting much use.

Custom fields for posts and pages are now exposed and manageable from metaWeblog.getPost/newPost/editPost, wp.getPage/newPage/editPage via the custom_fields field. I was really happy to get this in, I think there is a lot of potential in being able to manage custom fields externally.

The mt_allow_comments field now understands the value of 2 to be the same as the value of zero. This was done because other platforms expect to be able use the value 2, so some clients assume that we support it. Now we do, but from the WordPress point of view is does exactly the same thing as zero.

If the field date_created_gmt is provided in metaWeblog.newPost/editPost, wp.newPage/editPage then it is used instead of the dateCreated field. This same field was already exposed via metaWeblog.getPost, wp.getPage. By definition the date_created_gmt field is always GMT, even if you don’t provide a time zone offset or a trailing Z. I’m hoping this will help ease the many headaches that have been brought on by trying to deal with date/time issues in the XML-RPC blog APIs.

If you are a developer that makes use of the WordPress XML-RPC interface, or are interested in doing development work on the WordPress XML-RPC code please subscribe to the wp-xmlrpc email list. Along with various tickets in Trac this is where we discuss ideas and issues for the XML-RPC APIs that WordPress supports.

Links for Thu 7 Feb 2008

Links for Thu 8 Nov 2007