Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have been trying to figure out how to escape quotes (single and double) from shortcode attributes.

Basically the content is written by the user and therefore can potentially include " and ' quotes. Problem being, with " quotes it is stopping the shortcode attribute from functioning eg:

attibute="some text here with "quotes" so it stops the attribute...."

So instead of getting the entire string it is stopping at the second pair of quotes.

Now, I know it could be possible to set it up with single quotes but that leaves the same predicament if a user uses single quotes in the text.

I have looked at a variety of PHP/WP resolutions but I cant seem to get any of them to work, eg esc_html, htmlspecialchars, htmlentities.

Maybe I have set it up wrong or am not actioning the encoding at the right place.

This is currently what I am using (without encoding) as the shortcode (shortened a bit)

function aps_person_schema_shortcode( $atts, $content = null)   {

extract( shortcode_atts( array(     
            'aps_person_description' => ''
        ), $atts
    )
);

$aps_person_return = '<div class="aps_person_container aps_container">';
$aps_person_return .= '<p class="aps_person_description" itemprop="description">' . $aps_person_description . '</p>';
$aps_person_return .= '</div>';

return $aps_person_return;

}
add_shortcode('aps_person', 'aps_person_schema_shortcode');

I've tried adding in after the extract array things like

$aps_person_description = esc_html($atts['aps_person_description']); 

but as the attribute is already broken (print_r displays that the string after the quote is separated into an array item for each word) escaping the string there doesnt work.

Tried it before the array and it doesn't work either I get a Notice: Undefined index

So, to clarify, how do you go about sanitizing user input for shortcode attribute data?

share|improve this question
add comment

3 Answers 3

up vote 1 down vote accepted

It seems you are working on the wrong end.

Try sanitizing the user input, for instance by means of sanitize_textfield, not the shortcode output.

share|improve this answer
    
Thanks! Though I didn't use the sanitize_textfield you led me back to where I needed to be. The input is added with jQuery so I added a .replace to change the quotes, not perfect but stops it from breaking. –  Apina Mar 8 '13 at 18:41
add comment

It turns out WordPress shortcode system uses function shortcode_parse_atts($text); to parse a shortcode entry to retrive attributes' names and values and store them in pairs in the array $atts, which is then passed to the shortcode function. So in your case adding escaping actions in the shortcode function like this:

$aps_person_description = esc_html($atts['aps_person_description']); 

will not work because shortcode_parse_atts() has already retrived attributes' names and values, and might have wrongly interpreted quotes in attributes' values.

To look closer, function shortcode_parse_atts() use this regex pattern:

/(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s|$)/

to recognize attributes' names and values in the formats belows:

1. attr1="value1"
2. attr2='value2'
3. attr3=value3
4. "value4"
5. value5

So if a user puts quotes in values, it can easily go wrong. For example:

[my_shortcode dog='Santa's Little Helper' /]    
// $attr is Array ( [0] => dog='Santa's [1] => Little [2] => Helper' )
// should be Array ( [dog] => Santa's Little Helper )

Sanitizing after the parsing is obviously too late, what about sanitizing before the parsing? We will have to sanitize the entire entry since we don't have any attribute's values to work on yet. But this also causes problems, for example:

html_entities("[my_shortcode dog='Santa's Little Helper' /]", ENT_QUOTES);
// now entry is [my_shortcode dog=&#039;Santa&#039;s Little Helper&#039; /]
// after parsing: 
Array
(
    [dog] => &#039;Santa&#039;s
    [0] => Little
    [1] => Helper&#039;
)

The paradox is: in order to make sure the parsing engine parses correctly, you have to sanitize the attributes values; but to do this you have to run the parsing engine first to get the values.

In conclusion, I think the reasonable way to make sure everything goes fine is to ensure users input attributes in proper formats, once users posted poorly formatted attributes, it will be a big headache. FYI, my experience is to make use of $content. In your case, I would put aps_person_description in the $content, it may look like this:

[my_shortcode]some text here with "quotes" so it stops the attribute....[/my_shortcode]

and quotes will be less a problem.

share|improve this answer
add comment

You can check out esc_attr()

Encodes the <, >, &, " and ' (less than, greater than, ampersand, double quote and single quote) characters. Will never double encode entities.

http://codex.wordpress.org/Function_Reference/esc_attr

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.