Metatag appears to improperly escape characters such as quotation marks in text fields. I have a hook (see below) that lets users enter a "social media headline" to be used in title metatags, in place of the actual node title. But when that field contains quotation marks (eg, This is my "social" headline), the quotation mark is double-escaped, so the og:title tag looks like this:
<meta property="og:title" content="This is my &quot;social&quot; headline" />
This does not happen if quotation marks are used in the normal title field. In that case, the tag is produced properly:
<meta property="og:title" content="Testing "Quotes" in title" />
I've been having this problem on one of my sites and have been able to consistently reproduce it on a fresh install of Drupal 7.42 plus Metatag 7.x-1.13 and Entity 7.x-1.6:
- Add new "Social Media Headline" text field to the article content type. Set machine name to field_social_hed, and otherwise use default field settings.
- Add this hook to template.php (I used default Bartik theme):
function bartik_metatag_pattern_alter(&$pattern, &$types, $tag_name) { if (strpos($pattern, 'title') !== FALSE) { $wrapper = entity_metadata_wrapper('node', $types['node']); try { if ($val = $wrapper->field_social_hed->value()) { $pattern = str_replace('title','field_social_hed', $pattern); } } catch (EntityMetadataWrapperException $exc) { watchdog('america', 'No social hed field'. __FUNCTION__ . '() <pre>' . $exc->getTraceAsString() . '</pre>',NULL, WATCHDOG_ERROR); } } } - Create test article and insert text with quotation marks into the social media headline field, save and view source. Observe bad escaping in og:title tag.
- Create another test article and insert text with quotation marks into the node title field. Save and view source. Observe correct escaping in og:title tag.
I'll post a patch if I find one, but so far I haven't been able to figure out where this is happening. Any hints on where to look or what to try would be very welcome.
| Comment | File | Size | Author |
|---|---|---|---|
| #17 | metatag-n2667214-17.patch | 3.37 KB | damienmckenna |
| #8 | metatag-n2667214-8.patch | 7.7 KB | damienmckenna |
Comments
Comment #2
kenficara commentedComment #3
kenficara commentedSorry, I should have mentioned that as of the date of this posting, this also happens with 7.x-1.x-dev.
Comment #4
damienmckennaOk, we need to expand the tests in MetatagCoreStringHandlingTest to test field tokens, because right now it's only testing the title. We may also need to verify how it works with normal field tokens and also Entity API -based tokens, which are different.
Comment #5
damienmckennaComment #6
joelstein commentedI'm not sure if this helps in the discussion, but here's an easy way to see this in action:
Here's a patch which uses
htmlspecialchars_decodeto decode things like ampersands, quotes, etc. It usesENT_QUOTESsince that's what check_plain() uses.Comment #7
damienmckennaThanks. I'm glad that the existing tests still pass. However, I think we need an extra test to confirm the encoding works as intended, maybe adding something to the tests/metatag.string_handling.test file?
Comment #8
damienmckennaThis is an updated test for string encoding that shows the current codebase works correctly with values inserted into fields.
Comment #9
damienmckennaI've committed the patch in #8.
Comment #11
damienmckenna@joelstein: Please examine the data stored in the database for the body field when created using the ckeditor module vs when it's inserted using Drupal core's text formats, I would wager that the ckeditor module is storing the data incorrectly.
Comment #12
joelstein commented@DamienMcKenna: I performed the steps in #6 again, and the issue still exists. With CKEditor installed, the data is not stored incorrectly in the database:
<p>This has an & in it.</p>Comment #13
joelstein commented...and even without CKEditor installed, if I have an
&in the body field, I see it double encoded in the 'description' metatag.Comment #14
damienmckenna@joelstein: I just tested on a barebones install. If I add a bare ampersand to a node page it works correctly:
Is it possible you have something else interfering with the tokens?
Comment #15
damienmckennaI forgot to show what the meta tags were like:

Comment #16
joelstein commentedThanks for helping me troubleshoot this.
In your example, you entered
What. & thing., which means it's not storing the HTML representation of an ampersand (&), but just the ampersand itself. In my example, I'm storing the HTML:<p>This has an & in it.</p>. In this case, whether or not I have Filtered HTML or Full HTML text format selected, I see the HTML-encoded ampersand double-encoded in the metatag.Since Metatag is stripping HTML tags, we should also decode special HTML entities, so that they will be ready to be re-encoded when displayed as a meta tag. Is this making sense? :)
Comment #17
damienmckenna@joelstein: ok, you are correct. I looked up _filter_htmlcorrector(), etc and they all either rely upon PHP's automatic UTF8 encoding through e.g. DOMDocument->loadHTML() or use decode_entities().
Lets try this.
Comment #19
damienmckennaCommitted. Thanks for the help, joelstein.
Comment #20
joelstein commentedPerfect, thank you!