diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/field/field.module | 2 | ||||
-rw-r--r-- | modules/field/modules/text/text.module | 17 | ||||
-rw-r--r-- | modules/filter/filter.module | 15 | ||||
-rw-r--r-- | modules/filter/filter.test | 49 | ||||
-rw-r--r-- | modules/simpletest/tests/filter_test.module | 22 | ||||
-rw-r--r-- | modules/system/system-messages.css | 2 | ||||
-rw-r--r-- | modules/system/system.admin.inc | 16 |
7 files changed, 105 insertions, 18 deletions
diff --git a/modules/field/field.module b/modules/field/field.module index 5225adb5e..5bb7f0d7f 100644 --- a/modules/field/field.module +++ b/modules/field/field.module @@ -219,7 +219,7 @@ function field_modules_disabled($modules) { ->condition('storage_module', $modules, 'IN') ->execute(); - field_cache_clear(TRUE); + field_cache_clear(); } /** diff --git a/modules/field/modules/text/text.module b/modules/field/modules/text/text.module index dd7b602fc..600081c1b 100644 --- a/modules/field/modules/text/text.module +++ b/modules/field/modules/text/text.module @@ -649,3 +649,20 @@ function text_field_prepare_translation($entity_type, $entity, $field, $instance } } } + +/** + * Implements hook_filter_format_update(). + */ +function text_filter_format_update() { + field_cache_clear(); +} + +/** + * Implements hook_filter_format_delete(). + * + * @todo D8: Properly update filter format references in all fields. See + * http://drupal.org/node/556022 for details. + */ +function text_filter_format_delete() { + field_cache_clear(); +} diff --git a/modules/filter/filter.module b/modules/filter/filter.module index 395260e64..0654cc926 100644 --- a/modules/filter/filter.module +++ b/modules/filter/filter.module @@ -187,6 +187,10 @@ function filter_format_load($format_id) { function filter_format_save(&$format) { $format->name = trim($format->name); $format->cache = _filter_format_is_cacheable($format); + // Programmatic saves may not contain any filters. + if (!isset($format->filters)) { + $format->filters = array(); + } // Add a new text format. if (empty($format->format)) { @@ -197,10 +201,6 @@ function filter_format_save(&$format) { } $filter_info = filter_get_filters(); - // Programmatic saves may not contain any filters. - if (!isset($format->filters)) { - $format->filters = array(); - } foreach ($filter_info as $name => $filter) { // Add new filters without weight to the bottom. if (!isset($format->filters[$name]['weight'])) { @@ -280,6 +280,7 @@ function filter_format_delete($format, $fallback_id = NULL) { $fallback = filter_format_load($fallback_id); module_invoke_all('filter_format_delete', $format, $fallback); + // Clear the filter cache whenever a text format is deleted. filter_formats_reset(); cache_clear_all($format->format . ':', 'cache_filter', TRUE); } @@ -681,7 +682,11 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE) if (empty($format_id)) { $format_id = filter_fallback_format(); } - $format = filter_format_load($format_id); + // If the requested text format does not exist, the text cannot be filtered. + if (!$format = filter_format_load($format_id)) { + watchdog('filter', 'Missing text format: %format.', array('%format' => $format_id), WATCHDOG_ALERT); + return ''; + } // Check for a cached version of this piece of text. $cache = $cache && !empty($format->cache); diff --git a/modules/filter/filter.test b/modules/filter/filter.test index 973a0b779..113ed53d5 100644 --- a/modules/filter/filter.test +++ b/modules/filter/filter.test @@ -640,6 +640,55 @@ class FilterNoFormatTestCase extends DrupalWebTestCase { } /** + * Security tests for missing/vanished text formats or filters. + */ +class FilterSecurityTestCase extends DrupalWebTestCase { + public static function getInfo() { + return array( + 'name' => 'Security', + 'description' => 'Test the behavior of check_markup() when a filter or text format vanishes.', + 'group' => 'Filter', + ); + } + + function setUp() { + parent::setUp('php', 'filter_test'); + $this->admin_user = $this->drupalCreateUser(array('administer modules', 'administer filters', 'administer site configuration')); + $this->drupalLogin($this->admin_user); + } + + /** + * Test that filtered content is emptied when an actively used filter module is disabled. + */ + function testDisableFilterModule() { + // Create a new node. + $node = $this->drupalCreateNode(array('promote' => 1)); + $body_raw = $node->body[LANGUAGE_NONE][0]['value']; + $format_id = $node->body[LANGUAGE_NONE][0]['format']; + $this->drupalGet('node/' . $node->nid); + $this->assertText($body_raw, t('Node body found.')); + + // Enable the filter_test_replace filter. + $edit = array( + 'filters[filter_test_replace][status]' => 1, + ); + $this->drupalPost('admin/config/content/formats/' . $format_id, $edit, t('Save configuration')); + + // Verify that filter_test_replace filter replaced the content. + $this->drupalGet('node/' . $node->nid); + $this->assertNoText($body_raw, t('Node body not found.')); + $this->assertText('Filter: Testing filter', t('Testing filter output found.')); + + // Delete the text format entirely. + $this->drupalPost('admin/config/content/formats/' . $format_id . '/delete', array(), t('Delete')); + + // Verify that the content is empty, because the text format does not exist. + $this->drupalGet('node/' . $node->nid); + $this->assertNoText($body_raw, t('Node body not found.')); + } +} + +/** * Unit tests for core filters. */ class FilterUnitTestCase extends DrupalUnitTestCase { diff --git a/modules/simpletest/tests/filter_test.module b/modules/simpletest/tests/filter_test.module index 691d2231f..01a69315b 100644 --- a/modules/simpletest/tests/filter_test.module +++ b/modules/simpletest/tests/filter_test.module @@ -36,6 +36,28 @@ function filter_test_filter_info() { 'description' => 'Does nothing, but makes a text format uncacheable.', 'cache' => FALSE, ); + $filters['filter_test_replace'] = array( + 'title' => 'Testing filter', + 'description' => 'Replaces all content with filter and text format information.', + 'process callback' => 'filter_test_replace', + ); return $filters; } +/** + * Process handler for filter_test_replace filter. + * + * Replaces all text with filter and text format information. + */ +function filter_test_replace($text, $filter, $format, $langcode, $cache, $cache_id) { + $text = array(); + $text[] = 'Filter: ' . $filter->title . ' (' . $filter->name . ')'; + $text[] = 'Format: ' . $format->name . ' (' . $format->format . ')'; + $text[] = 'Language: ' . $langcode; + $text[] = 'Cache: ' . ($cache ? 'Enabled' : 'Disabled'); + if ($cache_id) { + $text[] = 'Cache ID: ' . $cache_id; + } + return implode("<br />\n", $text); +} + diff --git a/modules/system/system-messages.css b/modules/system/system-messages.css index e68b0b8aa..0fe890a6b 100644 --- a/modules/system/system-messages.css +++ b/modules/system/system-messages.css @@ -12,7 +12,7 @@ div.messages { } div.error, -tr.error { +table tr.error { background-color: #fcc; } diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc index be9c63001..d5de2f811 100644 --- a/modules/system/system.admin.inc +++ b/modules/system/system.admin.inc @@ -1243,16 +1243,12 @@ function system_modules_submit($form, &$form_state) { drupal_set_message(t('The configuration options have been saved.')); } - // Clear all caches. - registry_rebuild(); - system_rebuild_theme_data(); - drupal_theme_rebuild(); - node_types_rebuild(); - menu_rebuild(); - cache_clear_all('schema', 'cache'); + // Clear all caches. We need to invoke drupal_flush_all_caches() to ensure + // that also dependent caches are flushed, e.g. the filter cache and field + // cache, and also registered themes are rebuilt, since modules can also + // register themes. + drupal_flush_all_caches(); entity_info_cache_clear(); - drupal_clear_css_cache(); - drupal_clear_js_cache(); $form_state['redirect'] = 'admin/modules'; @@ -1263,8 +1259,6 @@ function system_modules_submit($form, &$form_state) { // Synchronize to catch any actions that were added or removed. actions_synchronize(); - - return; } /** |