newsies

Options Framework: Sanitization Filters

Posted

I’ve been steadily improving the Options Framework plugin these last several weeks and there’s several nice changes in this 0.6 release. The biggest new feature is sanitization filters and better validation, but there’s also a slew of other less noticeable code improvements.

Unfortunately, a couple things that worked in previous versions will break with this release unless theme code is updated. I debated these changes quite a bit but decided it was best to do this while the plugin is still relatively young and would affect the least amount of people.

Validation Filters

Validation filters are the most exciting update in the Options Framework. Not only is there better sanitization (read security), it’s also now possible to change the default validation on any input without hacking the plugin directly.

Several users had mentioned that they wanted to enter some html in the textareas. I updated this so $allowedtags can be used. But if you wanted a different sanitization method, the default can now be removed and a new one added in via your themes functions. (Edit: $allowedposttags might be used soon instead)

Since, “embed” is not one of the $allowedtags- here’s how you could remove the default santization from a text area and allow “embed” to be used:

/*
 * This is an example of how to override a default filter
 * for 'textarea' sanitization and use a different one.
 */
add_action('admin_init','optionscheck_change_santiziation', 100);
function optionscheck_change_santiziation() {
	remove_filter( 'of_sanitize_textarea', 'of_sanitize_textarea' );
	add_filter( 'of_sanitize_textarea', 'of_sanitize_textarea_custom' );
}
function of_sanitize_textarea_custom($input) {
	global $allowedtags;
        $of_custom_allowedtags["embed"] = array(
             "src" => array(),
             "type" => array(),
             "allowfullscreen" => array(),
             "allowscriptaccess" => array(),
             "height" => array(),
	     "width" => array()
	);
        $of_custom_allowedtags = array_merge($of_custom_allowedtags, $allowedtags);
        $output = wp_kses( $input, $of_custom_allowedtags);
	return $output;
}

Allow Script and Embed Tags

A lot of folks have been asking how to include all the $allowedpsttags in addition to script and embed tags. Here’s how you would do it (hat tip Jake Caputo):

/*
 * This is an example of how to override a default filter
 * for 'textarea' sanitization and $allowedposttags + embed and script.
 */
add_action('admin_init','optionscheck_change_santiziation', 100);
function optionscheck_change_santiziation() {
    remove_filter( 'of_sanitize_textarea', 'of_sanitize_textarea' );
    add_filter( 'of_sanitize_textarea', 'custom_sanitize_textarea' );
}
function custom_sanitize_textarea($input) {
    global $allowedposttags;
    $custom_allowedtags["embed"] = array(
      "src" => array(),
      "type" => array(),
      "allowfullscreen" => array(),
      "allowscriptaccess" => array(),
      "height" => array(),
          "width" => array()
      );
      $custom_allowedtags["script"] = array();
      $custom_allowedtags = array_merge($custom_allowedtags, $allowedposttags);
      $output = wp_kses( $input, $custom_allowedtags);
    return $output;
}

Checkbox Code Has Changed

The most noticeable change in version 0.6 is how checkbox data is stored. The reason it’s the most noticeable is because it’s the one most likely to break a current implementation. Instead of storing checkbox data as “true” or “false”, I’ve changed it to “1″ or “0″, which is how WordPress itself stores checkbox values and much smarter way to do it. I’ve written about this more in another post called “Checkboxes and Booleans”.

If you currently are using checkboxes in your theme, you should update options.php to use a default value of “0″ or “1″. You should also update how the theme reads checkbox data to something like:

if ( of_get_option('checkbox_option', "0") ) {
	do_action();
}

Helper Function Returns Boolean False by Default

Instead of having the helper function of_get_option return the string “false” by default, I’ve updated it to return the boolean false (thanks so a suggestion from @sawyerh). Again, there’s more about this in my post on booleans. This should just make it easier to check if options are saved in the database. This change isn’t likely to break something if it isn’t updated, but the new code for your theme should look like this:

if ( !function_exists( 'of_get_option' ) ) {
function of_get_option($name, $default = false) {
	$optionsframework_settings = get_option('optionsframework');
	// Gets the unique option id
	$option_name = $optionsframework_settings['id'];
	if ( get_option($option_name) ) {
		$options = get_option($option_name);
	}
	if ( !empty($options[$name]) ) {
		return $options[$name];
	} else {
		return $default;
	}
}
}

Better Handling of Option Arrays

I updated the code for how arrays of options (like multicheckbox, background, and typography) are processed and stored. I don’t think should affect current users- but it’s something to keep an eye on. The new code allows the options to be stored directly into the array rather than having an additional step in the validation to process it.

Better Display of Messages

For anyone who dug into the code of 0.5, you probably saw my very awkward way of displaying the “Options Reset” and “Options Saved” messages. I had an option in the database for saving the message which was set when the form was submitted and then later cleared after the message was displayed.

By digging through WordPress core I found a more elegant way to do it. At the top of the options page I now use settings_errors(), which automatically displays any messages.

The messages are set in optionsframework_validate() as it processes the form. So, the reset message it now set like so:

// If the reset button was clicked
	if (!empty($_POST['reset'])) {
		// If options are deleted sucessfully update the error message
		if (delete_option($option_name) ) {
			add_settings_error('options-framework', 'restore_defaults', __('Default options restored.'), 'updated fade');
		}
	}

Thanks and Credits

I owe a big thanks to Michael Fields for this release. He advised me on how to implement the validation filters and did a thorough code review which caught many of the html escaping errors. If you need a really solid WordPress developer to check your code, I’d highly recommend him.

I was only able to have a code review done thanks to several generous donations. Having cash to spend on a third party code check was extremely helpful, made the plugin much stronger, and was well spent! If you use the plugin and can contribute, a PayPal donation will make my day.

And finally, several people have been helping out with testing and development on GitHub. I really appreciate it! I’m probably leaving someone out, but big thanks to @mantone, @rejithomas, @sawyerh, @samargulies, @mfields, @adampickeringq, @djevrek, @utkarshkukreti, @celtic7, @helgatheviking, @johnraz, @jmilone, @thumbnet, and @pastorjack.

Update: Version 0.6 has been released

About Devin

I'm a WordPress developer based in Austin, Texas. Follow my projects on GitHub, or more general WordPress ramblings as @devinsays on twitter.

58 thoughts on “Options Framework: Sanitization Filters

  1. pixenjoy wrote:

    Great work Devin :-)

    Is the theme version will also be updated ?

    • Devin wrote:

      Yep. As soon as this is released I’ll start updating the theme version.

  2. Reji Thomas wrote:

    Thanks for mention @devin, and as always great work :)

  3. kathy wrote:

    great job devin! saw this got updated in my WP panels. and an update to portfolio press. seriously, how do you get so much done? geez.

    also i think you gave me a shoutout, but you forgot the THE in my handle. @helgatheviking (although that isn’t actually my twitter handle and i just checked.. there is some OTHER person masquerading as helgatheviking. grumble.

    • Devin wrote:

      Hi Kathy. I updated your handle. It only gets done because there is a lot of encouragement from folks using it. :)

      • kathy wrote:

        just looking at all the filters now. very cool. but it seems that you’re still stuck using 1 type of sanitation for all inputs of the same type. for instance, what about leaving textareas as they are most of the time, but toggling off the validation only on specific textareas?

      • Devin wrote:

        I left the $option variable in there so that you could do a conditional check against $option['id']. You can check if its a certain id for specialize sanatization, otherwise return the default.

      • kathy wrote:

        thought i was going to have to report an epic fail on my part, but it just clicked.

        i think you have a typo above in your remove_filter. you don’t have a function called sanitize_text_field… both your function and filter are called of_sanitize_textarea. so your example wasn’t actually removing the filter for me.

        you said you left $option in there, but it took me a while to figure out how to access it. in case anyone else needs to know, the key was that i needed to tell my add_filter to accept 2 arguments.


        add_action('admin_init','optionscheck_change_santiziation', 100);

        function optionscheck_change_santiziation() {
        remove_filter( 'of_sanitize_textarea', 'of_sanitize_textarea' );
        add_filter( 'of_sanitize_textarea', 'my_sanitize_textarea',10,2 );
        }

        function my_sanitize_textarea($input, $option) {
        global $allowedtags;

        if($option['validate'] == 'none'){
        return $input;
        } else {
        $output = wp_kses( $input, $allowedtags);
        return $output;
        }
        }

        i’m probably going to leave my options array w/ the validate parameter = none anywhere i don’t care to validate… i think it will be a bit more “set it and forget it” than checking against the $option['id']

        thanks devin!

      • Devin wrote:

        Hi Kathy. Text input does have a filter: add_filter( ‘of_sanitize_text’, ‘sanitize_text_field’ ). Check at the top of options-sanitize.php.

        of_sanitize_textarea looks a bit confusing because it is applying the filter “of_sanitize_textarea” and then calling the function “of_sanitize_textarea”. To remove it and add your own you would do:

        remove_filter( ‘of_sanitize_textarea’, ‘of_sanitize_textarea’ );
        add_filter( ‘of_sanitize_textarea’, ‘custom_sanitize_textarea’, 10, 2 );

      • kathy wrote:

        a little more progress. in lieu of not sanitizing at all, i found a good post on how to add items to your allowed tags. i figure once for accepting embeds and another time for allowing scripts, and i should be good.


        function my_sanitize_textarea($input, $option) {
        global $allowedtags;

        if($option['validate'] == 'embed'){
        $my_tags = array();
        $my_tags = $allowedtags; //duplicate $allowed tags

        $my_tags["iframe"] = array( //add new allowed tags
        "src" => array(),
        "height" => array(),
        "width" => array(),
        "frameborder" => array();
        "allowfullscreen" => array();
        );

        $my_tags["object"] = array(
        "height" => array(),
        "width" => array()
        );

        $my_tags["param"] = array(
        "name" => array(),
        "value" => array()
        );

        $my_tags["embed"] = array(
        "src" => array(),
        "type" => array(),
        "allowfullscreen" => array(),
        "allowscriptaccess" => array(),
        "height" => array(),
        "width" => array()
        );

        $output = wp_kses( $input, $my_tags); //kses filter against my new list of allowed tags
        return $output;
        } else {
        $output = wp_kses( $input, $allowedtags);
        return $output;
        }
        }

  4. brian wrote:

    is there a way i can make this on its own tab and change it so editors can have access to it? I usually set my clients up as editors and hide the appearance tab from them! :) thanks for such a great plugin.

    BH

    • Devin wrote:

      Not without customizing the plugin. The Options Framework Theme might be a better option if you need to make significant customizations.

      If you’re unsure how to proceed it might be best to hire a developer. I can’t offer specific customization advice for this, though I will occasionally take on small freelance projects.

  5. James wrote:

    I’ve been doing extensive testing with v.0.6. It’s great work. One minor suggestion. Add a second “Save Options” button in the header of the options panel. I think it’s the way they have it set up in Canvas and it really helps usability (IMO) because the the most used options tend to be at the top of the page. Depending on how your options panel is set up, having to scroll to the bottom of the page every time can be a bit of a pain. A minor point but something to consider for a future update. Thanks again for the outstanding work.

  6. kathy wrote:

    agree with james. something else i was going to try to take a stab at was having the panel “remember” which tab was last active after the save. if you’d been using the jquery UI tabs i’d know how to do that, but i’m less sure w/ your custom js.

  7. Hi Devin,

    Great plugin, have you considered adding a wysiwyg editor to the options? I’ve used it sometimes before it’s useful to customize say footer text to allow users to bold, underline text etc without using html tags.

    • Devin wrote:

      Not planning to add a text editor, but you can set your text boxes to allow html tags and explain in the description how to use them.

  8. Paul wrote:

    What you did with this is a big contribution for me. I really appreciate you sharing it and as soon as I get a project that uses the framework I will donate.

    thanks so much,
    Paul

  9. Paul Winslow wrote:

    Great framework, mate.

    I really can’t get HTML allowed in the text inputs, though.. I’ve tried absolutely everything with the code you’ve given above to remove the filter and add the new one.. for a start I’m not 100% sure where the code is supposed to go as it doesn’t say, but I’ve tried it now in every file in the framework folder as well as functions.php

    I’ve tried some code from the comments, as well. I just cannot get the fields to allow and save HTML code.

    :/

    • Paul Winslow wrote:

      Okay so now I see this code does work for text fields, I can now save HTML to them.. but the paragraph above the code block says it’s for textareas which seems misleading? I’m assuming I can use the same code but tweak it to remove the filters from textareas, as well.

      Again, thanks for a great options framework.

      • Paul Winslow wrote:

        I should probably clarify that I’m looking to add tags to textareas – just saying HTML above was pretty vague as anchors tags and the like do work.

  10. Mark wrote:

    Problem with IE7, your input radio and multicheck show all value in 1 field and the others don’t have any value. :)

  11. kathy wrote:

    can we stop supporting IE7? if all the web devs out there we stop supporting it won’t people have to upgrade? :)

  12. Paul wrote:

    +1 Also, some of the biggest WP marketplaces out there already drop support for IE7, I think its time.

  13. AJ wrote:

    First, for the record, you’ve done a lot of great work with this framework and overall I give it a thumbs up! However…..with regards to the textarea, this still continues to be a major frustration because all of the tips and suggestions to allow pasting of code into the textarea is not working for me and I’ve tried many things as well. So for the theme I wanted to do, the google analytics code option is being stripped out, plus if someone wants to paste a php tag into the textarea (for example when using a slideshow plugin and wanting to add this to a part of a page), it gets stripped out totally. I’m not sure what the solution is for my situation, but in the mean time, I will have to scrap any options that lets a person paste code. I should note though, basic html seems to work ok, but javascript and php tags are stripped.

    • Devin wrote:

      Did you follow the directions in the post? The code under the heading “Allow Script and Embed Tags” should allow you to use script and embed tags for your theme.

      • AJ wrote:

        Hi Devin…yes, but to confirm, where am I pasting that code…just so I know I’m doing it in the right place? I tried a couple areas, in my functions.php and also the options-sanitize.php under the /* Textarea */ comment and I got errors, like this:
        Warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'custom_sanitize_textarea' was given in /mysite/html/proto/wp-includes/plugin.php on line 170

        Warning: Cannot modify header information - headers already sent by (output started at /mysite/html/proto/wp-includes/plugin.php:170) in /mysite/html/proto/wp-includes/pluggable.php on line 934

  14. James wrote:

    Hi Devin, first off, I love the framework and it’s proved extremely usfull, however it’s been extremely frustrating trying to get HTML in any boxes. I’ve placed the code in every functions file I could find and I’ve had no luck.. Can you explain where EXACTLY it’s got to go? I’d be extremely grateful.
    Many thanks.

    • Devin wrote:

      It goes in the functions.php file of your theme. Or download the latest version of the plugin from GitHub (0.9). That allows most HTML tags in the textarea (embed and script will still need to be a conscious override).

  15. Fikri Rasyid wrote:

    Hello Devin, it’s a really great update and tutorials! Thanks! :D

    However, error message appeared when i tried your ‘allow scripts tag’ snippet.

    I think you should change the $of_custom_allowedtags variable into $custom_allowedtags. A typo, i guess :)

    • Devin wrote:

      Thanks, you just saved someone else a headache.

    • AJ wrote:

      Nice catch ….although, still not working for me as the field is stripped of it’s content when I click Save Options. HTML, PHP, etc., still not doable for me. I will have to forget about this one and have people manually paste their code in the theme files. Cheers!

  16. Satrya wrote:

    Devin,

    Check again your code in Allow Script and Embed Tags , you write function custom_sanitize_textarea_custom($input) it should be function custom_sanitize_textarea($input) :)

    • Devin wrote:

      Thanks. Updated.

  17. Zach wrote:

    Hey Devin,
    Just had a real-world usecase for the sanitized text area (for adding in script/link tags to the header) which is awesome BTW!

    One thing I’m running into is that it looks like when I introduce the sanitized function, I get the ‘Cheatin’ uh?’ message for user roles that do not have access to the main WP options screen I’m assuming. The entire theme options works fine, except for when I add these options in (which unfortunately effects the entire them options panel). Any advice on how to fix that? Thanks!

  18. Great plugin Devin,
    Just Like the others, I really get headache in “textarea”. It won’t render all of global html tags. It’s just only can render a few html tags. In my issue, I can/t include the “” tag. It’s really gave me frustration.

  19. Ceyhun wrote:

    Hello, I tried to do this for link target, but it didn’t work.

    $of_custom_allowedtags["a"] = array(
    “target” => array()
    );

  20. saleeh wrote:

    any idea about WYSIWYG implementation

  21. Wailynnoo wrote:


    <form action="http://www.aweber.com/scripts/addlead.pl" method="post">
    <input type="hidden" value="1" name="meta_message">
    <input type="hidden" value="email" name="meta_required">
    <input id="acpro_inp4" class="email" type="text" size="20" value="your@email.com" name="email">
    <input id="" class="submit" name="submit" value="Submint">
    </form>

    I want to add above code in my textarea but i can’t. Could you help me? Thank!

  22. Deryck Oñate Espinel wrote:

    Hi, I’m using a textarea (because editor does not work, does not show) and when I save the content the framework automatically strips all my HTML tags. I’m trying to include a but the sanitisers converts to plain text.

    I have checked $allowedposttags an it shows and as allowed tags.

    Any suggestion? Thanks in advance.

  23. Martin Schaer wrote:

    Thank you for the framework! Is there a way to allow element attributes using regular expressions? I need to allow data-[something]=”[value]“…

  24. Matt Brett wrote:

    Is it just me, or are the sanitization filters no longer working? After upgrading to WP 3.5, the scripts I had used in a textarea are now displayed without any of the attributes; empty script tags. They worked previously.

    • Devin wrote:

      Nothing was changed in the sanitization filters. Can you reproduce the issue?

      • Matt Brett wrote:

        Sorry, this seems to have been an issue on my end. I recently moved servers, and I think something got botched in the process. Seems to be all good now.

  25. Nino wrote:

    How can I allow any content in the textareas?

    Thanks for your great work!

    • Devin wrote:

      Add a custom filter that just returns in the input.

  26. Carmelo wrote:

    hi Devin, if i want set color link of theme? i have added to function.php


    $link = of_get_option('a_color');
    if ($link) {
    echo ' a:link {color:'.$link['color'].'}';
    }

    and on file option.php


    $options[] = array( "name" => "Link color",
    "desc" => "Choose the link (a:link) color.",
    "id" => "a_color",
    "std" => "",
    "type" => "color");

    can you help me?

  27. John Brown wrote:

    Is this still information still relevant?

    The reason I am asking is that I had been playing around with the filters to allow HTML in a text area with the Options Framework Theme 1.6 and I couldn’t get it to work.

    Then I integrated the options framework theme with the theme I have been working on and inputted HTML worked without adding any sort of filters. So, I was a bit perplexed. Thanks. Working with the Roots Theme.

  28. Imon wrote:

    i am using Options Framework Theme 1.4. when i am past adsense code it does not work. i am also try $allowedtags filter .

  29. P Nut wrote:

    the > symbol gets changed to >

    how do i get around this?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>