making bbPress (and WordPress) work better!

WP fixes

Fix large image attachments in WordPress

An annoying problem we have encountered with WordPress is that if an attached image is under the alloted dimensions for the post, WordPress will not attempt to further manipulate it or resave it.

This typically happens when non-tech authors upload photos from photoshop saved at the highest quality settings, but already sized down to the post width.

Only the smaller dimensions will be created, sometime leaving main images with extremely large file sizes in posts which are a big problem, especially for mobile visitors. But you really do not want megabytes of images on each page, for any kind of visitor.

So here is a filter I whipped up to catch that problem and resave the jpegs at 90% quality, progressive format, which will typically cut the size down to one-third (100k) or less with no perceptible loss of quality. It has the added bonus of stripping exif data and other meta (like hidden adobe fingerprints) from the images to reduce the size as much as possible for the most speed.

add_filter('wp_generate_attachment_metadata','fix_large_jpg');
function fix_large_jpg($metadata) {
	if (!empty($metadata['width']) && $metadata['width']<601) {
		$file=wp_upload_dir(); $file=$file['basedir'].'/'.$metadata['file']; 
		if (file_exists($file) && filesize($file)>200000) {
			$imageinfo = getimagesize($file);
			if (!empty($imageinfo['mime']) && $imageinfo['mime']=='image/jpeg') {
				$new=imagecreatefromjpeg($file);
				if ($new) {
					imageinterlace($new,1);
					imagejpeg($new,$file,90);
					imagedestroy($new);
				}
			}
		}
	}
	return $metadata;
}

This could be expanded for png but jpeg was really the main problem and easily solvable by forced resaving. Note that the re-save comes AFTER the lower sizes are created, allowing them to use the high quality source before it’s replaced.

The only hardcoded settings are the 600 pixel width which you can edit to what is used for the posts on your site, and the 200k filesize trigger which you can lower or increase as desired.


How web designers can test websites in IE9 on Windows XP

I’m a diehard Windows XP user and have no desire to upgrade to Vista or Windows 7. But this presents a problem now that Internet Explorer 9 has been officially released and in their (endless lack of) wisdom, Microsoft has decided not to allow it to run on Windows XP, to try to get people like me to upgrade.

So here’s how you can test your web designs on IE9 and make sure that everything is okay.

(the #1 problem I have found is that IE9 does NOT like or deal well with special IE6 fixes that are left over that were either ignored or did no harm in IE7 or IE8 – I will give you a solution for that following this)

First downloaded the free and legal Microsoft Windows 7 enterprise trial ISO (2.2GB)
microsoft.com x86fre_enterprise_en-us_EVAL_Eval_Enterprise-GRMCENEVAL_EN_DVD.iso
(you only need the 32bit version, it will run faster, if it won’t download it’s because of the refer, copy the link and paste it directly in your browser – download is speed limited so it will take at least 20 minutes)

Next install the free VMWare Player into Windows XP
http://download3.vmware.com/software/vmplayer/VMware-player-2.5.5-328052.exe
( or http://www.vmware.com/download/player/download.html you might actually need version 3+ for windows 7)

Last, use one of the free vmx generator tools to make a configuration for VMplayer ready for Windows 7 and set the Windows7 ISO as the CD drive

http://www.easyvmx.com/supersimple.shtml
(choose Vista, not Vista 64 – also, Windows7 needs a TON of space so choose 12GB at a minimum, I did 8GB and it’s already maxed out with nothing else installed – the file starts off small but will grow as needed)

Edit the vmx file and add these lines (removing any existing ide1:0 lines)

ide1:0.present = "TRUE"
ide1:0.deviceType = "cdrom-image"
ide1:0.fileName = "7600.16385.090713-1255_x86fre_enterprise_en-us_EVAL_Eval_Enterprise-GRMCENEVAL_EN_DVD.iso"

It should take 30 minutes to do all this, except maybe the ISO download which is huge and takes quite awhile.

The great thing about the enterprise trial is it lasts for 60 days, then you can “rearm” (google it) for a couple more times, but even when it’s expired, you can use it for an hour before auto-shutdown which is plenty of time to test pages in IE9

Okay now I promised a trick to help deal with IE9 – here’s my solution:

Most javascript that detects IE doesn’t detect the version, just if it’s IE or not. For example: isIE=/blah/; What we really need is something to replace that which is short and sweet and accurate.

So here’s what I came up with:

isIE=window.opera?0:parseInt((navigator.userAgent.match(/MSIE (\d+)/) || [0,0])[1]);

Then just replace any instance of

if (isIE) {blah}

With this:

if (isIE && isIE<9) {blah}

Hope that helps!


Turn on Chrome Frame for Internet Explorer in WordPress (and bbPress)

Google is promoting their Chrome “frame” enhancement for Internet Explorer users that allows people to stay with the IE interface but run the much faster and safer Chrome browser inside it.

However ChromeFrame has to be turned on for each website they visit.

To turn it on in WordPress and bbPress you should be able to add this single line as a mini-plugin, or in header.php or even in functions.php.


<?php if (strpos($_SERVER['HTTP_USER_AGENT'],"chromeframe")) {header("X-UA-Compatible: chrome=1");} ?>

Update: the above will not work, apparently Chrome needs it to be a META tag and not in the page headers 😦 – thanks Matt

If you want to just put it in header.php use this (before </head>)

if (strpos($_SERVER['HTTP_USER_AGENT'],"chromeframe")) {echo '<meta http-equiv="X-UA-Compatible" content="chrome=1" />'}

If you want it to be a real plugin, use this:

<?php
add_action('bb_head','chromeframe');
add_action('wp_head','chromeframe');
function chromeframe() {
if (strpos($_SERVER['HTTP_USER_AGENT'],"chromeframe")) {echo '<meta http-equiv="X-UA-Compatible" content="chrome=1" />';}
}
?>


WordPress still uses the nasty SQL_CALC_FOUND_ROWS

(update: please don’t try this patch as is on WP versions newer than 2.8 – I am only leaving it here as a suggestion if some coder in the future decides to tackle the problem)

We’ve known for over two whole years now that SQL_CALC_FOUND_ROWS did nasty things in bbPress 0.8

It was fixed by mdawaffe (Michael) after discovering how SQL_CALC_FOUND_ROWS caused an overload on the Automattic wordpress.org forum servers due to a MySQL bug.

But to this very day, it’s still used in all WordPress versions, up to and including 2.8.2

(Even more ironic, now that bbPress 1.0 has switched to the backPress core which is based on WordPress, SQL_CALC_FOUND_ROWS is back inside bbPress, though it works around the bug)

SQL_CALC_FOUND_ROWS is typically three times slower than using COUNT() on the same query without LIMIT and ORDER restrictions.

I’ve seen at least one slow-log for MySQL that is FULL of SQL_CALC_FOUND_ROWS queries from a large WordPress installation on a dedicated server that took 11-15 seconds per query (and crashed MySQL, repeatedly).

Here is my quick & dirty patch to the WordPress (and BackPress) core that attempts to change SQL_CALC_FOUND_ROWS to the COUNT() workaround – it’s inside wp-includes/query.php – it’s tested working but not heavily tested so use with caution and let me know if you have improvements?

My changes are against the file from WP 2.5.1 but the file has barely changed since 2.5, even 2.8 is virtually the same so it should be easy to modify other versions.

There is one other use of SQL_CALC_FOUND_ROWS left in WordPress but it’s in the admin section so I am not going to worry about it for now.

More about the MySQL bug due to it’s poor optimization:
http://bugs.mysql.com/bug.php?id=18454 (cache)
http://bugs.mysql.com/bug.php?id=19553 (cache)
http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/


every WordPress install vulnerable to new security hack

Remember the mysterious babloo/blyat attack that hit many blogs including xkcd and is continuing in the wild? Here’s how they did it:

coresecurity.com : WordPress Privileges Unchecked

It’s just mind boggling that the WordPress people:

1. knew about it since June 4th
2. took OVER A FULL MONTH to release a fix (June 4th – July 8th)
3. left ALL previous versions of WordPress flapping in the wind
4. there is no advisory as to how to manually patch existing installs

bbPress 1.0 is possibly affected by this vulnerability now that it uses the WP core
bbPress 0.9 might be immune

added 7/13

I don’t know if this is a reasonable security patch for existing WP installs but the logic seems to make sense to me so far. It might break plugins like subscribe-to-comments or anything else that interacts with regular users through the admin interface.

The problem seems to be this line in admin.php

include(ABSPATH . PLUGINDIR . "/$plugin_page");

Since there is not a natural, singular action before it to hook (it adds the plugin name) the file will have to be edited, and maybe add something like this BEFORE the above line:

if ( ! current_user_can('level_2') ) {
wp_die(__('You are not allowed here.'));
}

This only allows Authors and above to use plugins via the admin menu.

The WP legacy where regular members are allowed into the admin area, but with reduced privileges, has always been very messy. And this is (yet another time) where it’s coming to haunt WP adopters. The good news is at least bbPress learned from the mistake and does it differently.


How to fix Internet Explorer 8 messing up WordPress themes

Here’s a mini-plugin (single line of code actually) that will prevent the new IE8 (aka Internet Explorer 8 ) from messing up your carefully crafted WordPress or bbPress design.

<?php if (strpos($_SERVER['HTTP_USER_AGENT'],"MSIE 8")) {
header("X-UA-Compatible: IE=7");} ?>

Make a mini-plugin out of it and activate.
(you might be able to put it into functions.php if that executes before other data is sent but I am uncertain – for the extremely lazy you could in theory put it as the very very first line of header.php in your template)

I also have it listed as a more formal plugin over here

For those that don’t want to install IE8 permanently to just test their webpages, this version will run in it’s own virtual box so it doesn’t affect the rest of your system:
http://start-o.xenocode.com/layers/ie8/8-0-0-0__2/ie8.exe
There’s no install, it just runs instantly from that one file.