Fix/Tricks for plugin auto-update on WordPress 2.5

[READ THIS FIRST!!!  Update 6/13/2009: If you’ve come here looking to get plugin updates to work and you’re using WordPress 2.8, you really want to start with this more recent post on the topic and then come back for the permission information.]

One of the neat features of WordPress 2.5 is the click to install plugin upgrades, assuming the plugin is registered in the WordPress Plugin Directory. If certain conditions are correct on the server it can do it in place, otherwise it tries to do it via FTP.

To make it so wordpress could upgrade them on the server without FTP requires doing some permission changes. You should be aware, the changes I made allow the web server (Apache) to be able to write to the plugin directory. This creates some security exposure. Since I do nightly backups, for me this is an acceptable risk. You may make a different call.

The way I’ve done it also assumes you have admin rights on the unix box or you’re friendly with (s)he who does. Without admin rights to do the group ownership changes, you’re stuck having to make files writable by the world, and that’s not something I’d do. Luckily, I hold the power on the box(es) I care about.

The changes I made were as follows:

chgrp -R apache wp-content/plugins
find wp-content/plugins -type d | xargs chmod g+ws
find wp-content/plugins -type f | xargs chmod g+w

After doing that, I fired off upgrading the google-sitemap-generator plugin, as that was out of date. It brought me to a screen asking for FTP information, which means the server-side update failed. That sent me to the code. After walking the code I found two things:

  1. Without WP_TEMP_DIR specified in your config, the upgrade will use wp-content as a temp directory.
  2. A bug/feature of the code that prevents it from work.

To get around #1, I defined WP_TEMP_DIR in my wp-config so it looked like this:

define('WP_TEMP_DIR', ABSPATH . 'wp-content/tmp');

I then created a tmp directory and set its permissions inline with what I have above.

mkdir wp-content/tmp
chgrp apache wp-content/tmp
chmod 2775 wp-content/tmp

As I called #2 above, I’m not sure if its a bug or a feature. One of the sanity checks that wordpress does to see if it can do the update is to make sure it can write into the temp directory and if the current process owns the resultant file. I’m thinking its a bug because it looks like they expected the PHP function call used to be reasonable rather than suffer from the occasional brain-dead PHPism.

The sanity check uses getmyuid() which anyone with unix coding experience would assume its the user id of the running process. Not so! If you read the PHP documentation, it actually returns the UID of who owns the script file. Since my user owns the file, but the script is being executed by apache’s user, it ends up returning the wrong information. In reading the code, and guessing its intent, what they actually wanted to use was either posix_getuid() or posix_geteuid(). Once I switched to using posix_getuid() everything worked as expected.

To make this change, open up wp-admin/includes/file.php in your editor of choice and go to somewhere around line 323. You’ll want to change the line that looks like this:

if ( getmyuid() == fileowner($tempFile) ) {

To look something like this:

if ( posix_getuid() == fileowner($tempFile) ) {

And boom, I have working click to upgrade for plugins.

As a note, I have no idea if this will work on Windows or not as I’m not up with the permissions there or if the posix_ functions are available on that platform.