Hacking Kses
If you're new here, you may want to subscribe to my RSS feed. Thanks for visiting!
As I spent a great deal of time (and hunting on the Internets) on this I thought I would share the result of my efforts and hopefully save your sanity and hairline.
kses is an HTML/XHTML filter written in PHP. It removes all unwanted HTML elements and attributes, and it also does several checks on attribute values. kses can be used to avoid Cross-Site Scripting (XSS).
It is built into WordPress and WordPress MU and acts on all the content you enter into your posts and pages and strips out all the nasties that WordPress doesn’t think you should be using. 99% of the time you won’t even notice that it is there, but everynow and then you will try to include something in your post and it just won’t save. In a round-a-bout way, this is the situation I found myself in earlier this week.
Try as I might, I just couldn’t get WordPress MU to accept style attributes (this is also the case for normal WordPress). Everytime I saved a post the style would be stripped out completely (MU also removes class and id attributes as well). Most annoying and after pulling out what little hair I had left I turned to the Oracle of all knowledge.
Donncha, one of the main developers behind WordPress MU, wrote a post back in September 2007 descibing how to re-enable the class and id attributes and we can use this method to also add back the style attribute. Hoorah, so let’s create a plugin to do just that.
$attr ) {
$attr[ 'class' ] = array();
$attr[ 'id' ] = array();
$attr[ 'style' ] = array();
$allowedposttags[ $tag ] = $attr;
}
return $allowedposttags;
}
function addaspanner($tags) {
global $allowedtags;
$allowedtags['span'] = array();
return $allowedtags;
}
add_filter( 'edit_allowedposttags', 'addabitofclass' );
add_filter( 'edit_allowedtags', 'addaspanner' );
?>
Cut and paste the code into a new .php file, upload it to your plugins directory and enable it (or just place it in your mu-plugins directory). You will then be able to add class, style and id attributes to your blog posts.
Well that didn’t take too long did it?
Oh if only things were that simple. Whilst the above will allow me to add a style attribute, the content of my style is still stripped out. so my carefully prepared:
Hello
Will become:
Hello
Not what I wanted at all. Finding out how to solve this problem took me the best part of an evening and ended up with me modifying the kses.php file that was included with the latest version of WordPress (2.5). I won’t go into all the details of the changes here, but I ended up extending the kses.php file and added an extra filter to allow styles to be included. You can download my version of the file here.
Unzip the file and replace the existing kses.php file in your wp-includes directory. Simply replacing the existing kses.php file with the new version won’t have any effect at all on your system, in it’s standard form it will function exactly the same as the standard kses.php file. However it does add an extra WordPress filter that will allow us specify which styles we want to be allowed via our plugin.
Once you have uploaded the new kses.php file, we can add the following lines of code to the plugin we created earlier:
function addabitofprotocol($allowed_protocols) {
$new_protocols = array(
'background',
'background-color',
'border',
'border-bottom',
'border-bottom-color',
'border-bottom-style',
'border-bottom-width',
'border-collapse',
'border-color',
'border-left',
'border-left-color',
'border-left-style',
'border-left-width',
'border-right',
'border-right-color',
'border-right-style',
'border-right-width',
'border-spacing',
'border-style',
'border-top',
'border-top-color',
'border-top-style',
'border-top-width',
'border-width',
'caption-side',
'clear',
'color',
'cursor',
'direction',
'display',
'float',
'font',
'font-family',
'font-size',
'font-style',
'font-variant',
'font-weight',
'height',
'letter-spacing',
'line-height',
'margin',
'margin-bottom',
'margin-left',
'margin-right',
'margin-top',
'overflow',
'padding',
'padding-bottom',
'padding-left',
'padding-right',
'padding-top',
'text-align',
'text-decoration',
'text-indent',
'unicode-bidi',
'vertical-align',
'width'
);
$allowed_protocols = array_merge($allowed_protocols, $new_protocols);
return $allowed_protocols;
}
add_filter('edit_allowedprotocols', 'addabitofprotocol');
Save the plugin file and re-upload it to your server. You will now be able to include the styles listed in the $new_protocols array. Any styles not listed will still be stripped out in the normal way.
I do hope this post has helped save your sanity, and hopefully saved you a lot of time and hair-pulling. The full code for the plugin is shown below for your cut and pasting pleasure.
$attr ) {
$attr[ 'class' ] = array();
$attr[ 'id' ] = array();
$attr[ 'style' ] = array();
$allowedposttags[ $tag ] = $attr;
}
return $allowedposttags;
}
function addaspanner($tags) {
global $allowedtags;
$allowedtags['span'] = array();
return $allowedtags;
}
function addabitofprotocol($allowed_protocols) {
$new_protocols = array(
'background',
'background-color',
'border',
'border-bottom',
'border-bottom-color',
'border-bottom-style',
'border-bottom-width',
'border-collapse',
'border-color',
'border-left',
'border-left-color',
'border-left-style',
'border-left-width',
'border-right',
'border-right-color',
'border-right-style',
'border-right-width',
'border-spacing',
'border-style',
'border-top',
'border-top-color',
'border-top-style',
'border-top-width',
'border-width',
'caption-side',
'clear',
'color',
'cursor',
'direction',
'display',
'float',
'font',
'font-family',
'font-size',
'font-style',
'font-variant',
'font-weight',
'height',
'letter-spacing',
'line-height',
'margin',
'margin-bottom',
'margin-left',
'margin-right',
'margin-top',
'overflow',
'padding',
'padding-bottom',
'padding-left',
'padding-right',
'padding-top',
'text-align',
'text-decoration',
'text-indent',
'unicode-bidi',
'vertical-align',
'width'
);
$allowed_protocols = array_merge($allowed_protocols, $new_protocols);
return $allowed_protocols;
}
add_filter( 'edit_allowedposttags', 'addabitofclass' );
add_filter( 'edit_allowedtags', 'addaspanner' );
add_filter('edit_allowedprotocols', 'addabitofprotocol');
?>
Update: In case you are curious, the changes I made to the kses.php file can be found in the new file at lines 323, 365, 967, 968, 984 and 985
April 14th, 2008 at 2:11 pm
Thanks for going to all that effort! I’m looking through this to fix http://trac.mu.wordpress.org/ticket/581 so hopefully we’ll get at least the styles used by the uploader in before 1.5 is released.
BTW - I think you could probably use the ‘pre_kses’ filter to change the protocols. I’ll give it a go and hopefully get it into trunk later today or tomorrow!
April 14th, 2008 at 2:19 pm
Thanks Donncha
I didn’t 100% understand the pre_kses filter and what it returned (or expected to be returned so I took that safest (easiest) option for me.
April 14th, 2008 at 6:07 pm
Looks like it’s not the right hook to use actually. I copied portions of code Andy Skelton did for WordPress.com and add my own filtering routine. Check out the revision here: http://trac.mu.wordpress.org/changeset/1235
What do you think? I’m going to post to the mu forum with this.
May 2nd, 2008 at 10:13 am
http://wpmudev.org/project/Allow-Embedded-Videos
Maybe it helps… I don’t know… It helped me to show my videos.
Cheers