reverted: --- b/core/modules/filter/filter.api.php +++ a/core/modules/filter/filter.api.php @@ -59,9 +59,6 @@ * - settings callback: The name of a function that returns configuration * form elements for the filter. See hook_filter_FILTER_settings() for * details. - * - allowed tags callback: The name of a function that returns an array of - * tags that are allowed by this filter. This is only necessary for filters - * that strip away other tags. * - default settings: An associative array containing default settings for * the filter, to be applied when the filter has not been configured yet. * - prepare callback: The name of a function that escapes the content before @@ -87,7 +84,6 @@ 'description' => t('Allows you to restrict the HTML tags the user can use. It will also remove harmful content such as JavaScript events, JavaScript URLs and CSS styles from those tags that are not removed.'), 'process callback' => '_filter_html', 'settings callback' => '_filter_html_settings', - 'allowed tags callback' => '_filter_html_allowed_tags', 'default settings' => array( 'allowed_html' => '
    1. ', 'filter_html_help' => 1, @@ -177,30 +173,6 @@ } /** - * Filter allowed tags callback for hook_filter_info(). - * - * Note: This is not really a hook. The function name is manually specified via - * 'allowed tags callback' in hook_filter_info(), with this recommended callback - * name pattern. It is called from filter_get_allowed_tags_by_format(). - * - * This callback function is only necessary for filters that strip away other - * tags and allows other modules to gain insight in a generic manner into the - * HTML tags that are allowed by a given filter. Through the API function - * filter_get_allowed_tags_by_format(), modules can easily find out which tags - * are allowed by all filters in a text format (i.e. their intersection). - * - * @param $filter - * The filter object containing settings for the given format. - * - * @return array - * An array of allowed tags, or the empty array in case no tags are allowed. - * A valid return value could be e.g. array('p', 'br', 'a'). - */ -function hook_filter_FILTER_allowed_tags($filter) { - return preg_split('/\s+|<|>/', $filter->settings['allowed_html'], -1, PREG_SPLIT_NO_EMPTY); -} - -/** * Prepare callback for hook_filter_info(). * * Note: This is not really a hook. The function name is manually specified via diff -u b/core/modules/filter/filter.module b/core/modules/filter/filter.module --- b/core/modules/filter/filter.module +++ b/core/modules/filter/filter.module @@ -4,18 +4,19 @@ * @file * Framework for handling the filtering of content. */ + use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Template\Attribute; /** - * HTML generator filters -- MUST generate HTML. + * Non-HTML markup language filters that generate HTML. */ -const FILTER_TYPE_HTML_GENERATOR = 0; +const FILTER_TYPE_MARKUP_LANGUAGE = 0; /** - * HTML tag restricting filters. + * HTML tag and attribute restricting filters. */ -const FILTER_TYPE_HTML_TAG_RESTRICTOR = 1; +const FILTER_TYPE_HTML_RESTRICTOR = 1; /** * Reversible transformation filters. @@ -25,7 +26,7 @@ /** * Irreversible transformation filters. */ -const FILTER_TYPE_TRANSFORM_TEXT = 3; +const FILTER_TYPE_TRANSFORM_IRREVERSIBLE = 3; /** * Implements hook_cache_flush(). @@ -574,6 +575,7 @@ * * @param string $format_id * A text format ID. + * * @return array * All filter types used by filters of a given text format. * @@ -602,60 +604,6 @@ } /** - * Retrieve all tags that are allowed by a given text format. - * - * @param string $format_id - * A text format ID. - * @return array|TRUE - * An array of HTML tags (in "p", not "

      " format) that are allowed by the - * text format. The empty array implies no tags are allowed. TRUE implies all - * tags are allowed. - */ -function filter_get_allowed_tags_by_format($format_id) { - $filters = filter_list_format($format_id); - - // Ignore filters that are disabled or don't have an "allowed tags" setting. - $filters = array_filter($filters, function($filter) { - if (!$filter->status) { - return FALSE; - } - - $filters_info = filter_get_filters(); - if (!empty($filters_info[$filter->name]['allowed tags callback'])) { - return TRUE; - } - }); - - if (empty($filters)) { - return TRUE; - } - else { - // From the set of remaining filters (they were filtered by array_filter() - // above), collect the list of tags that is allowed by *all* filters, i.e. - // the intersection of all allowed tags. - $allowed_tags = array_reduce($filters, function($result, $filter) { - $filters_info = filter_get_filters(); - $function = $filters_info[$filter->name]['allowed tags callback']; - $allowed_tags = $function($filter); - - // The first filter with an "allowed tags" setting provides the initial - // set. - if (!isset($result)) { - return $allowed_tags; - } - // Subsequent filters with an "allowed tags" setting must be intersected - // with the existing set, to ensure we only end up with the tags that are - // allowed by *all* filters with an "allowed tags" setting. - else { - return array_intersect($result, $allowed_tags); - } - }, NULL); - - return $allowed_tags; - } -} - -/** * Returns the ID of the fallback text format that all users have access to. * * The fallback text format is a regular text format in every respect, except @@ -866,10 +814,10 @@ * The caller may set this to FALSE when the output is already cached * elsewhere to avoid duplicate cache lookups and storage. * @param array $filter_types_to_skip - * An array of filter types to skip, or the empty array (default) to skip no - * filter types. All of the format's filters will be applied, except for - * filters of the types that are marked to be skipped. - * FILTER_TYPE_HTML_TAG_RESTRICTOR is the only type that cannot be skipped. + * (optional) An array of filter types to skip, or an empty array (default) + * to skip no filter types. All of the format's filters will be applied, + * except for filters of the types that are marked to be skipped. + * FILTER_TYPE_HTML_RESTRICTOR is the only type that cannot be skipped. * * @return * The filtered text. @@ -886,9 +834,9 @@ return ''; } - // Prevent FILTER_TYPE_HTML_TAG_RESTRICTOR from being skipped. - if (in_array(FILTER_TYPE_HTML_TAG_RESTRICTOR, $filter_types_to_skip)) { - $filter_types_to_skip = array_diff($filter_types_to_skip, array(FILTER_TYPE_HTML_TAG_RESTRICTOR)); + // Prevent FILTER_TYPE_HTML_RESTRICTOR from being skipped. + if (in_array(FILTER_TYPE_HTML_RESTRICTOR, $filter_types_to_skip)) { + $filter_types_to_skip = array_diff($filter_types_to_skip, array(FILTER_TYPE_HTML_RESTRICTOR)); } // When certain filters should be skipped, don't perform caching. @@ -917,7 +865,7 @@ // Give filters the chance to escape HTML-like data such as code or formulas. foreach ($filters as $name => $filter) { // If necessary, skip filters of a certain type. - if ($filter_types_to_skip && in_array($filter_info[$name]['type'], $filter_types_to_skip)) { + if (in_array($filter_info[$name]['type'], $filter_types_to_skip)) { continue; } if ($filter->status && isset($filter_info[$name]['prepare callback'])) { @@ -929,7 +877,7 @@ // Perform filtering. foreach ($filters as $name => $filter) { // If necessary, skip filters of a certain type. - if ($filter_types_to_skip && in_array($filter_info[$name]['type'], $filter_types_to_skip)) { + if (in_array($filter_info[$name]['type'], $filter_types_to_skip)) { continue; } if ($filter->status && isset($filter_info[$name]['process callback'])) { @@ -1356,6 +1304,5 @@ 'title' => t('Limit allowed HTML tags'), - 'type' => FILTER_TYPE_HTML_TAG_RESTRICTOR, + 'type' => FILTER_TYPE_HTML_RESTRICTOR, 'process callback' => '_filter_html', 'settings callback' => '_filter_html_settings', - 'allowed tags callback' => '_filter_html_allowed_tags', 'default settings' => array( @@ -1368,13 +1315,13 @@ ); $filters['filter_autop'] = array( 'title' => t('Convert line breaks into HTML (i.e. <br> and <p>)'), - 'type' => FILTER_TYPE_HTML_GENERATOR, + 'type' => FILTER_TYPE_MARKUP_LANGUAGE, 'process callback' => '_filter_autop', 'tips callback' => '_filter_autop_tips', ); $filters['filter_url'] = array( 'title' => t('Convert URLs into links'), - 'type' => FILTER_TYPE_HTML_GENERATOR, + 'type' => FILTER_TYPE_MARKUP_LANGUAGE, 'process callback' => '_filter_url', 'settings callback' => '_filter_url_settings', 'default settings' => array( @@ -1384,6 +1331,7 @@ ); $filters['filter_html_image_secure'] = array( 'title' => t('Restrict images to this site'), + 'type' => FILTER_TYPE_HTML_RESTRICTOR, 'description' => t('Disallows usage of <img> tag sources that are not hosted on this site by replacing them with a placeholder image.'), 'process callback' => '_filter_html_image_secure_process', 'tips callback' => '_filter_html_image_secure_tips', @@ -1392,13 +1340,13 @@ ); $filters['filter_htmlcorrector'] = array( 'title' => t('Correct faulty and chopped off HTML'), - 'type' => FILTER_TYPE_HTML_TAG_RESTRICTOR, + 'type' => FILTER_TYPE_HTML_RESTRICTOR, 'process callback' => '_filter_htmlcorrector', 'weight' => 10, ); $filters['filter_html_escape'] = array( 'title' => t('Display any HTML as plain text'), - 'type' => FILTER_TYPE_HTML_GENERATOR, + 'type' => FILTER_TYPE_HTML_RESTRICTOR, 'process callback' => '_filter_html_escape', 'tips callback' => '_filter_html_escape_tips', 'weight' => -10, @@ -1425,20 +1373,10 @@ } /** - * Filter allowed tags callback for the HTML content filter. - * - * See hook_filter_FILTER_allowed_tags() for documentation of parameters and - * return value. - */ -function _filter_html_allowed_tags($filter) { - return preg_split('/\s+|<|>/', $filter->settings['allowed_html'], -1, PREG_SPLIT_NO_EMPTY); -} - -/** * Provides filtering of input into accepted HTML. */ function _filter_html($text, $filter) { - $allowed_tags = _filter_html_allowed_tags($filter); + $allowed_tags = preg_split('/\s+|<|>/', $filter->settings['allowed_html'], -1, PREG_SPLIT_NO_EMPTY); $text = filter_xss($text, $allowed_tags); if ($filter->settings['filter_html_nofollow']) { diff -u b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php --- b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php @@ -13,6 +13,7 @@ * Tests the behavior of Filter's API. */ class FilterAPITest extends WebTestBase { + public static function getInfo() { return array( 'name' => 'API', @@ -29,12 +30,12 @@ 'format' => 'filtered_html', 'name' => 'Filtered HTML', 'filters' => array( - // Note that the filter_html filter is of the type FILTER_TYPE_HTML_GENERATOR. + // Note that the filter_html filter is of the type FILTER_TYPE_MARKUP_LANGUAGE. 'filter_url' => array( 'weight' => -1, 'status' => 1, ), - // Note that the filter_html filter is of the type FILTER_TYPE_HTML_TAG_RESTRICTOR. + // Note that the filter_html filter is of the type FILTER_TYPE_HTML_RESTRICTOR. 'filter_html' => array( 'status' => 1, ), @@ -72,72 +73,39 @@ $expected_filtered_text, - t('Expected filter result.') + 'Expected filter result.' ); $this->assertIdentical( - check_markup($text, 'filtered_html', '', FALSE, array(FILTER_TYPE_HTML_GENERATOR)), + check_markup($text, 'filtered_html', '', FALSE, array(FILTER_TYPE_MARKUP_LANGUAGE)), $expected_filter_text_without_html_generators, - t('Expected filter result when skipping FILTER_TYPE_HTML_GENERATOR filters.') + 'Expected filter result when skipping FILTER_TYPE_MARKUP_LANGUAGE filters.' ); // Related to @see FilterSecurityTest.php/testSkipSecurityFilters(), but // this check focuses on the ability to filter multiple filter types at once. // Drupal core only ships with these two types of filters, so this is the // most extensive test possible. $this->assertIdentical( - check_markup($text, 'filtered_html', '', FALSE, array(FILTER_TYPE_HTML_TAG_RESTRICTOR, FILTER_TYPE_HTML_GENERATOR)), + check_markup($text, 'filtered_html', '', FALSE, array(FILTER_TYPE_HTML_RESTRICTOR, FILTER_TYPE_MARKUP_LANGUAGE)), $expected_filter_text_without_html_generators, - t('Expected filter result when skipping FILTER_TYPE_HTML_GENERATOR filters, even when trying to disable filters of the FILTER_TYPE_HTML_TAG_RESTRICTOR type.') + 'Expected filter result when skipping FILTER_TYPE_MARKUP_LANGUAGE filters, even when trying to disable filters of the FILTER_TYPE_HTML_RESTRICTOR type.' ); } + /** + * Tests the function filter_get_filter_types_by_format(). + */ function testFilterFormatAPI() { // Test on filtered_html. $this->assertEqual( - filter_get_allowed_tags_by_format('filtered_html'), - array('a', 'em', 'strong', 'cite', 'blockquote', 'code', 'ul', 'ol', 'li', 'dl', 'dt', 'dd'), - t('filter_get_allowed_tags_by_format() works as expected for the filtered_html format.') - ); - $this->assertEqual( filter_get_filter_types_by_format('filtered_html'), - array(FILTER_TYPE_HTML_TAG_RESTRICTOR, FILTER_TYPE_HTML_GENERATOR), - t('filter_get_filter_types_by_format() works as expected for the filtered_html format.') + array(FILTER_TYPE_HTML_RESTRICTOR, FILTER_TYPE_MARKUP_LANGUAGE), + 'filter_get_filter_types_by_format() works as expected for the filtered_html format.' ); // Test on full_html. $this->assertEqual( - filter_get_allowed_tags_by_format('full_html'), - TRUE, // Every tag is allowed. - t('filter_get_allowed_tags_by_format() works as expected for the full_html format.') - ); - $this->assertEqual( filter_get_filter_types_by_format('full_html'), - array(FILTER_TYPE_HTML_TAG_RESTRICTOR), - t('filter_get_filter_types_by_format() works as expected for the full_html format.') - ); - - // Test on stupid_filtered_html. - $stupid_filtered_html_format = array( - 'format' => 'stupid_filtered_html', - 'name' => 'Stupid Filtered HTML', - 'filters' => array( - // Note that the filter_html filter is of the type FILTER_TYPE_HTML_TAG_RESTRICTOR. - 'filter_html' => array( - 'status' => 1, - 'settings' => array( - 'allowed_html' => '', // Nothing is allowed. - ) - ), - ) - ); - $stupid_filtered_html_format = (object) $stupid_filtered_html_format; - filter_format_save($stupid_filtered_html_format); - $this->assertEqual( - filter_get_allowed_tags_by_format('stupid_filtered_html'), - array(), // No tag is allowed. - t('filter_get_allowed_tags_by_format() works as expected for the stupid_filtered_html format.') - ); - $this->assertEqual( - filter_get_filter_types_by_format('stupid_filtered_html'), - array(FILTER_TYPE_HTML_TAG_RESTRICTOR), - t('filter_get_filter_types_by_format() works as expected for the stupid_filtered_html format.') + array(FILTER_TYPE_HTML_RESTRICTOR), + 'filter_get_filter_types_by_format() works as expected for the full_html format.' ); } + } diff -u b/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php --- b/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php @@ -24,7 +24,7 @@ public static function getInfo() { return array( 'name' => 'Security', - 'description' => 'Test the behavior of check_markup() when a filter or text format vanishes, or when check_markup() is called in such a way that it is instructed to skip all filters of the "FILTER_TYPE_HTML_TAG_RESTRICTOR" type.', + 'description' => 'Test the behavior of check_markup() when a filter or text format vanishes, or when check_markup() is called in such a way that it is instructed to skip all filters of the "FILTER_TYPE_HTML_RESTRICTOR" type.', 'group' => 'Filter', ); } @@ -40,7 +40,7 @@ 'format' => 'filtered_html', 'name' => 'Filtered HTML', 'filters' => array( - // Note that the filter_html filter is of the type FILTER_TYPE_HTML_TAG_RESTRICTOR. + // Note that the filter_html filter is of the type FILTER_TYPE_HTML_RESTRICTOR. 'filter_html' => array( 'status' => 1, ), @@ -91,12 +91,11 @@ /** - * Tests that when security filters are marked to be skipped, they are still - * enforced anyway. + * Tests that security filters are enforced even when marked to be skipped. */ function testSkipSecurityFilters() { $text = "Text with some disallowed tags: