WordPress, don’t be so stupid. How about actually TRYING?

The varnernet server uses a pretty um, strange way of handling virtual directories right now.

I’ve not taken the time to get susexec and cgi for PHP5 setup and running, so we have some peculiar behavior. For instance: websites run from ~/public_html that need write access to the filesystem must have the default ubuntu www-data user granted write permissions.

Yeah, I know….

Anyhow, the way I solved this problem originally was creative use of filesystem ACLs, which works great, so long as software isn’t brain-dead.

Take WordPress for example, with it’s automatic upgrade of plug-ins, which breaks miserably in our current environment.

The following code is to blame:

function get_filesystem_method() {
	$method = false;
	if( function_exists('getmyuid') && function_exists('fileowner') ){
		$temp_file = wp_tempnam();

		if ( getmyuid() == fileowner($temp_file) )
			$method = 'direct';
		unlink($temp_file);
	}

	if ( ! $method && extension_loaded('ftp') ) $method = 'ftpext';
	if ( ! $method && ( extension_loaded('sockets') ||
	     function_exists('fsockopen') ) ) $method = 'ftpsockets';
	     //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread
	return apply_filters('filesystem_method', $method);
}

Note the test for direct file access. It checks to see if the currently running process user id is the same as the owner of a newly created temp file. Uh….

In our environment, something is doing a setuid on sites being served from ~/public_html. So the running process ID is 2000, but the file being written to the file system has an owner UID of 33. Even though the server can read / write to that temp file (thanks to ACLs which give the 2000 user equal rights to the 33 user) WordPress vomits and complains, and won’t work properly.

All because they decided to trust some meta-data from the filesystem, without fully testing the ACL to see if the user has r+ access. Stupid! They should at least try to fopen the file with read/write access if the UID’s don’t match (as a more expensive, but more accurate fail-over process).

The code I’ve applied that fixes this problem (beautifully, I might add) is below:

function get_filesystem_method() {
	$method = false;
	if( function_exists('getmyuid') && function_exists('fileowner') ){
		$temp_file = wp_tempnam();

		if ( getmyuid() == fileowner($temp_file) )
			$method = 'direct';

		$fd = fopen($temp_file, 'r+');
		if ($fd != FALSE) {
			$method = direct;
			fclose($fd);
		}

		unlink($temp_file);
	}

	if ( ! $method && extension_loaded('ftp') ) $method = 'ftpext';
	if ( ! $method && ( extension_loaded('sockets') ||
	     function_exists('fsockopen') ) ) $method = 'ftpsockets';
	     //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread
	return apply_filters('filesystem_method', $method);
}

Leave a Reply

You must be logged in to post a comment.