Sunday, December 12th, 2010
I’ve been working on a big web site that’s built on the superb WordPress. Now I *love* WordPress, it’s just amazing, but then it does some crap stuff.
I was having some issues looking at cache control and gzipping on the site’s server and came across just how WordPress multi-site handles files from the different of sites: it points them through PHP.
Now this isn’t fun, nor is it clever; here’s the file: http://core.trac.wordpress.org/browser/trunk/wp-includes/ms-files.php (look at line 82, it says readfile(), that’s magic!)
Now me being me, I didn’t like this. So I’ve written a simple little WordPress plugin that’ll do a better job, or at least I hope: https://github.com/ahmednuaman/WordPress-Filer.
It’s pretty simple, here’s the (latest) code (but don’t trust it, get it off Github).
<?php
/*
Plugin Name: WordPress Multi-site Filer
Plugin URI: https://github.com/ahmednuaman/WordPress-Filer
Description: It's a plugin that handles files that much better
Version: 1
Author: Ahmed Nuaman
Author URI: http://www.ahmednuaman.com
*/
/**
* @author Ahmed Nuaman (http://www.ahmednuaman.com)
* @langversion 5
*
* This work is licenced under the Creative Commons Attribution-Share Alike 2.0 UK: England & Wales License.
* To view a copy of this licence, visit http://creativecommons.org/licenses/by-sa/2.0/uk/ or send a letter
* to Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
*/
/*
So, how do you use this? Well, in your .htaccess (or whatever rewrite program you use) will be a directive like so:
RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) wp-includes/ms-files.php?file=$2 [L]
You need to rewrite it to:
RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) wp-admin/admin-ajax.php?file=$2&origin=$1&action=get_blog_file [L]
This simply rewrites it to this bad ass plugin
*/
error_reporting( E_ALL ^
E_NOTICE );
add_action
( 'wp_ajax_get_blog_file', 'filer_get_blog_file' );
add_action
( 'wp_ajax_nopriv_get_blog_file', 'filer_get_blog_file' );
$files = '/wp-content/blogs.dir/';
function filer_get_blog_file
()
{
global $files;
$path = _to_word
( $_REQUEST[ 'origin' ] );
$b_id = _filer_get_blog_id
( $path );
$dir = $files . $b_id . '/files/' . $_REQUEST[ 'file' ];
header( 'Location: ' . $dir );
die();
}
if ( !function_exists( '_filer_get_blog_id' ) )
{
function _filer_get_blog_id
($blog_path)
{
global $wpdb;
$blog_path = _to_safe_var
( $blog_path );
$blog = $wpdb->get_row( 'SELECT blog_id FROM wp_blogs WHERE path = "/' . $blog_path . '/"' );
return $blog->blog_id;
}
}
if ( !function_exists( '_to_safe_var' ) )
{
function _to_safe_var
($v)
{
return str_replace( '"', '', mysql_real_escape_string( $v ) );
}
}
if ( !function_exists( '_to_word' ) )
{
function _to_word
($v)
{
return _to_safe_var
( preg_replace( '/[^A-z]/', '', $v ) );
}
}
?>
It’s pretty simple to use: just download and install and update your .htaccess (or whatever rewrite program you use) to do the following:
# uploaded files
#RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) wp-includes/ms-files.php?file=$2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) wp-admin/admin-ajax.php?file=$2&origin=$1&action=get_blog_file [L]
And you’re laughing! Let me know if it’s useful and if you like it. I really wanna look at getting caching in here somewhere, so that’ll be the next update.