.../ckeditor/Plugin/CKEditorPlugin/Internal.php | 6 ++-- .../lib/Drupal/ckeditor/Tests/CKEditorTest.php | 2 +- core/modules/filter/filter.module | 34 +++++++++---------- .../lib/Drupal/filter/Plugin/Filter/FilterHtml.php | 6 ++-- .../filter/Plugin/Filter/FilterHtmlEscape.php | 2 +- .../lib/Drupal/filter/Plugin/FilterInterface.php | 35 ++++++++++++++++---- .../lib/Drupal/filter/Tests/FilterAPITest.php | 8 ++--- .../Filter/FilterTestRestrictTagsAndAttributes.php | 18 +++++----- 8 files changed, 66 insertions(+), 45 deletions(-) diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/CKEditorPlugin/Internal.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/CKEditorPlugin/Internal.php index 5e8dec8..56f9a6e 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/CKEditorPlugin/Internal.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/CKEditorPlugin/Internal.php @@ -311,7 +311,7 @@ protected function generateAllowedContentSetting(Editor $editor) { return TRUE; } $setting = array(); - foreach ($html_restrictions['allowedTags'] as $tag => $attributes) { + foreach ($html_restrictions['allowed'] as $tag => $attributes) { // Tell CKEditor the tag is allowed, but no attributes. if ($attributes === FALSE) { $setting[$tag] = array( @@ -343,8 +343,8 @@ protected function generateAllowedContentSetting(Editor $editor) { // for either the "style" or "class" attribute, it cannot possibly be // more permissive than what was set above. Hence: inherit from the // "*" tag where possible. - if (isset($html_restrictions['allowedTags']['*'])) { - $wildcard = $html_restrictions['allowedTags']['*']; + if (isset($html_restrictions['allowed']['*'])) { + $wildcard = $html_restrictions['allowed']['*']; if (isset($wildcard['style'])) { if (!is_array($wildcard['style'])) { $setting[$tag]['styles'] = $wildcard['style']; diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php index 15228d2..971d12e 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php @@ -132,7 +132,7 @@ function testGetJSSettings() { 'status' => 1, 'settings' => array( 'restrictions' => array( - 'allowedTags' => array( + 'allowed' => array( 'p' => TRUE, 'a' => array( 'href' => TRUE, diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module index 272d382..1b90cde 100644 --- a/core/modules/filter/filter.module +++ b/core/modules/filter/filter.module @@ -467,22 +467,22 @@ function filter_get_html_restrictions_by_format($format_id) { // allowed by *all* filters with an "allowed html" setting. else { // Track the union of forbidden (blacklisted) tags. - if (isset($new_restrictions['forbiddenTags'])) { - if (!isset($restrictions['forbiddenTags'])) { - $restrictions['forbiddenTags'] = $new_restrictions['forbiddenTags']; + if (isset($new_restrictions['forbidden_tags'])) { + if (!isset($restrictions['forbidden_tags'])) { + $restrictions['forbidden_tags'] = $new_restrictions['forbidden_tags']; } else { - $restrictions['forbiddenTags'] = array_unique(array_merge($restrictions['forbiddenTags'], $new_restrictions['forbiddenTags'])); + $restrictions['forbidden_tags'] = array_unique(array_merge($restrictions['forbidden_tags'], $new_restrictions['forbidden_tags'])); } } // Track the intersection of allowed (whitelisted) tags. - if (isset($restrictions['allowedTags'])) { - $intersection = $restrictions['allowedTags']; + if (isset($restrictions['allowed'])) { + $intersection = $restrictions['allowed']; foreach ($intersection as $tag => $attributes) { // If the current tag is not whitelisted by the new filter, then // it's outside of the intersection. - if (!array_key_exists($tag, $new_restrictions['allowedTags'])) { + if (!array_key_exists($tag, $new_restrictions['allowed'])) { // The exception is the asterisk (which applies to all tags): it // does not need to be whitelisted by every filter in order to be // used; not every filter needs attribute restrictions on all tags. @@ -495,7 +495,7 @@ function filter_get_html_restrictions_by_format($format_id) { // intersection of the allowed attributes. else { $current_attributes = $intersection[$tag]; - $new_attributes = $new_restrictions['allowedTags'][$tag]; + $new_attributes = $new_restrictions['allowed'][$tag]; // The current intersection does not allow any attributes, never // allow. if (!is_array($current_attributes) && $current_attributes == FALSE) { @@ -530,7 +530,7 @@ function filter_get_html_restrictions_by_format($format_id) { } } } - $restrictions['allowedTags'] = $intersection; + $restrictions['allowed'] = $intersection; } return $restrictions; @@ -541,21 +541,21 @@ function filter_get_html_restrictions_by_format($format_id) { // blacklist, then remove any tags from the whitelist that also exist in the // blacklist. Now the whitelist alone expresses all tag-level restrictions, // and we can delete the blacklist. - if (isset($restrictions['allowedTags']) && isset($restrictions['forbiddenTags'])) { - foreach ($restrictions['forbiddenTags'] as $tag) { - if (isset($restrictions['allowedTags'][$tag])) { - unset($restrictions['allowedTags'][$tag]); + if (isset($restrictions['allowed']) && isset($restrictions['forbidden_tags'])) { + foreach ($restrictions['forbidden_tags'] as $tag) { + if (isset($restrictions['allowed'][$tag])) { + unset($restrictions['allowed'][$tag]); } } - unset($restrictions['forbiddenTags']); + unset($restrictions['forbidden_tags']); } // Simplification: if the only remaining allowed tag is the asterisk (which // contains attribute restrictions that apply to all tags), and only // whitelisting filters were used, then effectively nothing is allowed. - if (isset($restrictions['allowedTags'])) { - if (count($restrictions['allowedTags']) === 1 && array_key_exists('*', $restrictions['allowedTags']) && !isset($restrictions['forbiddenTags'])) { - $restrictions['allowedTags'] = array(); + if (isset($restrictions['allowed'])) { + if (count($restrictions['allowed']) === 1 && array_key_exists('*', $restrictions['allowed']) && !isset($restrictions['forbidden_tags'])) { + $restrictions['allowed'] = array(); } } diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtml.php b/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtml.php index d894c49..177ccdb 100644 --- a/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtml.php +++ b/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtml.php @@ -69,14 +69,14 @@ public function process($text, $langcode, $cache, $cache_id) { * {@inheritdoc} */ public function getHTMLRestrictions() { - $restrictions = array('allowedTags' => array()); + $restrictions = array('allowed' => array()); $tags = preg_split('/\s+|<|>/', $this->settings['allowed_html'], -1, PREG_SPLIT_NO_EMPTY); // List the allowed HTML tags. foreach ($tags as $tag) { - $restrictions['allowedTags'][$tag] = TRUE; + $restrictions['allowed'][$tag] = TRUE; } // The 'style' and 'on*' ('onClick' etc.) attributes are always forbidden. - $restrictions['allowedTags']['*'] = array('style' => FALSE, 'on*' => FALSE); + $restrictions['allowed']['*'] = array('style' => FALSE, 'on*' => FALSE); return $restrictions; } diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtmlEscape.php b/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtmlEscape.php index ea05822..24e3114 100644 --- a/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtmlEscape.php +++ b/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtmlEscape.php @@ -36,7 +36,7 @@ public function process($text, $langcode, $cache, $cache_id) { */ public function getHTMLRestrictions() { // Nothing is allowed. - return array('allowedTags' => array()); + return array('allowed' => array()); } /** diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php b/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php index fd93ced..5b231a9 100644 --- a/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php +++ b/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php @@ -187,15 +187,31 @@ public function process($text, $langcode, $cache, $cache_id); * format. * * @return array|FALSE - * A nested array with the allowed tags as keys, and for each of those tags - * (keys) the corresponding allowed attributes. An empty array for allowed - * attributes means no attributes are allowed, TRUE means all attributes are - * allowed. An example: + * A nested array with *either* of the following keys: + * - 'allowed': (optional) the allowed tags as keys, and for each of those + * tags (keys) either of the following values: + * - TRUE to indicate any attribute is allowed + * - FALSE to indicate no attributes are allowed + * - an array to convey attribute restrictions: the keys must be + * attribute names (which may use a wildcard, e.g. "data-*"), the + * possible values are similar to the above: + * - TRUE to indicate any attribute value is allowed + * - FALSE to indicate the attribute is forbidden + * - an array to convey attribute value restrictions: the key must + * be attribute values (which may use a wildcard, e.g. "xsd:*"), + * the possible values are TRUE or FALSE: to mark the attribute + * value as allowed or forbidden, respectively + * - 'forbidden_tags': (optional) the forbidden tags + * + * There is one special case: the "wildcard tag", "*": any attribute + * restrictions on that pseudotag apply to all tags. + * + * If no restrictions apply, then FALSE must be returned. * * Here is a concrete example, for a very granular filter: * @code * array( - * 'allowedTags' => array( + * 'allowed' => array( * // Allows any attribute with any value on the
tag. * 'div' => TRUE, * // Allows no attributes on the

tag. @@ -233,17 +249,22 @@ public function process($text, $langcode, $cache, $cache_id); * A simpler example, for a very coarse filter: * @code * array( - * 'forbiddenTags' => array('iframe', 'script') + * 'forbidden_tags' => array('iframe', 'script') * ) * @endcode * * The simplest example possible: a filter that doesn't allow any HTML: * @code * array( - * 'allowedTags' => array() + * 'allowed' => array() * ) * @endcode * + * And for a filter that applies no restrictions, i.e. allows any HTML: + * @code + * FALSE + * @endcode + * * @see filter_get_html_restrictions_by_format() */ public function getHTMLRestrictions(); diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php index a742c5d..f32d30b 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php @@ -98,7 +98,7 @@ function testFilterFormatAPI() { // Test on filtered_html. $this->assertIdentical( filter_get_html_restrictions_by_format('filtered_html'), - array('allowedTags' => array('p' => TRUE, 'br' => TRUE, 'strong' => TRUE, 'a' => TRUE, '*' => array('style' => FALSE, 'on*' => FALSE))), + array('allowed' => array('p' => TRUE, 'br' => TRUE, 'strong' => TRUE, 'a' => TRUE, '*' => array('style' => FALSE, 'on*' => FALSE))), 'filter_get_html_restrictions_by_format() works as expected for the filtered_html format.' ); $this->assertIdentical( @@ -135,7 +135,7 @@ function testFilterFormatAPI() { $stupid_filtered_html_format->save(); $this->assertIdentical( filter_get_html_restrictions_by_format('stupid_filtered_html'), - array('allowedTags' => array()), // No tag is allowed. + array('allowed' => array()), // No tag is allowed. 'filter_get_html_restrictions_by_format() works as expected for the stupid_filtered_html format.' ); $this->assertIdentical( @@ -160,7 +160,7 @@ function testFilterFormatAPI() { 'status' => 1, 'settings' => array( 'restrictions' => array( - 'allowedTags' => array( + 'allowed' => array( 'p' => TRUE, 'br' => FALSE, 'a' => array('href' => TRUE), @@ -174,7 +174,7 @@ function testFilterFormatAPI() { $very_restricted_html->save(); $this->assertIdentical( filter_get_html_restrictions_by_format('very_restricted_html'), - array('allowedTags' => array('p' => TRUE, 'br' => FALSE, 'a' => array('href' => TRUE), '*' => array('style' => FALSE, 'on*' => FALSE))), + array('allowed' => array('p' => TRUE, 'br' => FALSE, 'a' => array('href' => TRUE), '*' => array('style' => FALSE, 'on*' => FALSE))), 'filter_get_html_restrictions_by_format() works as expected for the very_restricted_html format.' ); $this->assertIdentical( diff --git a/core/modules/filter/tests/filter_test/lib/Drupal/filter_test/Plugin/Filter/FilterTestRestrictTagsAndAttributes.php b/core/modules/filter/tests/filter_test/lib/Drupal/filter_test/Plugin/Filter/FilterTestRestrictTagsAndAttributes.php index b80ea92..86f4452 100644 --- a/core/modules/filter/tests/filter_test/lib/Drupal/filter_test/Plugin/Filter/FilterTestRestrictTagsAndAttributes.php +++ b/core/modules/filter/tests/filter_test/lib/Drupal/filter_test/Plugin/Filter/FilterTestRestrictTagsAndAttributes.php @@ -29,7 +29,7 @@ class FilterTestRestrictTagsAndAttributes extends FilterBase { * {@inheritdoc} */ public function process($text, $langcode, $cache, $cache_id) { - $allowed_tags = array_filter($this->settings['restrictions']['allowedTags'], function($value) { + $allowed_tags = array_filter($this->settings['restrictions']['allowed'], function($value) { return is_array($value) || (bool) $value !== FALSE; }); return Xss::filter($text, array_keys($allowed_tags)); @@ -42,28 +42,28 @@ public function getHTMLRestrictions() { $restrictions = $this->settings['restrictions']; // The configuration system stores FALSE as '0' and TRUE as '1'. Fix that. - if (isset($restrictions['allowedTags'])) { - foreach ($restrictions['allowedTags'] as $tag => $attrs_or_bool) { + if (isset($restrictions['allowed'])) { + foreach ($restrictions['allowed'] as $tag => $attrs_or_bool) { if (!is_array($attrs_or_bool)) { - $restrictions['allowedTags'][$tag] = (bool) $attrs_or_bool; + $restrictions['allowed'][$tag] = (bool) $attrs_or_bool; } else { foreach ($attrs_or_bool as $attr => $attrvals_or_bool) { if (!is_array($attrvals_or_bool)) { - $restrictions['allowedTags'][$tag][$attr] = (bool) $attrvals_or_bool; + $restrictions['allowed'][$tag][$attr] = (bool) $attrvals_or_bool; } else { foreach ($attrvals_or_bool as $attrval => $bool) { - $restrictions['allowedTags'][$tag][$attr][$attrval] = (bool) $bool; + $restrictions['allowed'][$tag][$attr][$attrval] = (bool) $bool; } } } } } } - if (isset($restrictions['forbiddenTags'])) { - foreach ($restrictions['forbiddenTags'] as $tag => $bool) { - $restrictions['forbiddenTags'][$tag] = (bool) $bool; + if (isset($restrictions['forbidden_tags'])) { + foreach ($restrictions['forbidden_tags'] as $tag => $bool) { + $restrictions['forbidden_tags'][$tag] = (bool) $bool; } }