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.



How to get email through to hotmail users (and maybe aol)

You may have noticed (or discovered after some complaints) that hotmail (hotmail.com hotmail.co.uk) users are not getting their WordPress or bbPress registration emails from your server. Try not to get too frustrated, Hotmail and AOL email accounts are the worst.

This is essentially because microsoft wants your server to conform to their own system and if they don’t like something, it’s your problem. If your users are on AOL and not getting your emails, you are mostly screwed short of paying them major $$$ to get off their bad email list (or paying a lawyer to pester them) but with Microsoft you can try to fix the issue yourself if you are patient.

Essentially make sure your server has reverse DNS (rDNS) (ie. it’s IP address resolves to the same domain name you use) and that it has a proper SPF. Ask your host’s technical support for help if you don’t know how to do that, it’s definitely something they should cover.

But with Microsoft that’s not enough. They cache that info for awhile, so if it’s changed (ie. you sent emails to hotmail users before you put in a proper SPF) you’ll need to send an email to
senderid@microsoft.com with the domain name(s) in the text of the message on new lines.

Then you have to wait, sometimes up to two weeks, to get an automated reply.
(more…)


The Vertical Nature of WordPress 2.5 Can Be Changed

Some people are concerned about how vertical all the options have become in WordPress 2.5 under “write post” etc.

With just 10 minutes of hacking I was able to use jquery.ui to make all the options draggable from the main area to the sidebar (and back) as well as change the order.

Once 2.5 hits a release candidate stage I’ll post the changes as a diff for anyone that wants it.


It’s “Content-Type” not “Content-type”

I accidentally discovered some of my feeds were not validating, not because of content, but because of the headers!

Upon inspection, I noticed some of them were being formatted nicely as RSS feeds and others looked like a dump of text or html.

It was driving me crazy, started blaming all sorts of things like eaccelerator and/or wp-cache.

Guess what, it comes down to a single uppercase/lowercase typo that a search found in a few plugins and some older RSS templates I was using from pre WP 2.1

If you find anything sending “Content-type” (note “type” vs “Type”) then some browsers, readers, feeders will break and not know what that means. Why? Because the RFC2616 specification says the case matters and some programmers follow the rules without allowing room for others that (accidentally) don’t.

You’ll need a good search/replace tool that’s case-sensitive. I use this old program and have been too lazy to see if there are any replacements around. It works fairly well so there’s never been a need.

One latent bug fixed, 1000 more to go… sigh…


more feed fixing including text super-sanitizer

If you like the idea of serving up all your content in a way that makes it super easy for search engine spammers and other nasties to grab it all, and/or allow a human reader to never actually visit the pretty website you worked so hard on – well then the default WP feeds are for you.

Unfortunately I’m not in the above group. The default WP feeds for posts, comments, rss and atom formats, all give up EVERYTHING in ugly, CDATA wrappers that aren’t correct technique. They also ignore any plugins you have active to manipulate your text before it’s seen (ie. [poll=2] )

It kills me how people spend hours and days making things validate on their website which does nothing for human visitors but don’t think twice about how they appear via their feeds.

So I wanted the feeds to
1. actually process any plugins used for the posts (ie. [poll=2] )
2. only give teaser excerpts (50 words or less)
3. not use ugly CDATA wrappers
4. not include the images
5. not include javascript, embeds or active-x

WordPress doesn’t do ANY of the above by default!

First I had to create a way to completely process the posts (#1) but scrub them clean of #2-#5.
Below the break you’ll find the function to do that “function scrub_text()”

Then you have to go into wp-rss2.php and replae where it dumps the description/content with:
<description><?php echo scrub_text(apply_filters(‘the_content’, $post->post_content) ,50); ?></description>

Repeat with similar technique for wp-commentsrss2.php wp-atom.php and wp-commentsatom.php
ie. for wp-commentsrss2.php
<description><? echo scrub_text(get_comment_text(),50); ?></description>

The nice thing about the scrub_text is it will convert foreign entities to unicode which will pass virtually all xml parsers including IE6’s ancient code.
(more…)