summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/field/field.module2
-rw-r--r--modules/field/modules/text/text.module17
-rw-r--r--modules/filter/filter.module15
-rw-r--r--modules/filter/filter.test49
-rw-r--r--modules/simpletest/tests/filter_test.module22
-rw-r--r--modules/system/system-messages.css2
-rw-r--r--modules/system/system.admin.inc16
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;
}
/**