When CKEDITOR runs security filters during the AJAX callback ckeditor_filter_xss(), it provides the currently selected text format as a string and not an object:

// ckeditor.page.inc, line 241:
$text = $filters[$name]['process callback']($text, $format_filters[$name], $_POST['input_format']);
// $_POST['input_format'] is a string, obviously, but should be an object.

This causes the "process callback" function to be incapable of determining the text format context, and prevents the filter from loading any per-format settings defined in the {filter} table. For example, HTMLPurifier's process callback:

function _htmlpurifier_process_text($text, $filter, $format, $langcode, $cache = TRUE) {
  // ...
  $config = _htmlpurifier_get_config($format->format);

Since $format isn't an object here, _htmlpurifier_get_config() returns the default configuration settings. If you've allowed any extra HTML elements, CSS classes, etc. for your text format, they will be filtered out and the resulting content when re-saved will lose this information. This isn't a problem with HTMLPurifier, since the spec for "process callback" defined $format as an object. CKEDITOR needs to pass the parameter in an equivalent manner. See hook_filter_FILTER_process.

This issue also exists in the current 7.x-1.x-dev branch, as of August 13, 2012.

Here's a fix for 7.x-1.9, and I've attached a patch for 7.x-1.x.

--- a/includes/ckeditor.page.inc
+++ b/includes/ckeditor.page.inc
@@ -238,7 +238,16 @@
             continue;
         }
 
-        $text = $filters[$name]['process callback']($text, $format_filters[$name], $_POST['input_format']);
+        // Filter process callbacks expect parameter 3 ($format parameter) to be
+        // an object; especially important is the $format->format string, which
+        // tells the filter what input format it is operating on. Without this,
+        // filters (particularly HTMLPurifier) will be unable to look up their
+        // settings in the {filter} table and will either fail or use defaults.
+        //
+        // @see http://api.drupal.org/api/drupal/modules!filter!filter.api.php/function/hook_filter_FILTER_process/7
+        // @see _htmlpurifier_process_text()
+        $format_object = (object) array('format' => $_POST['input_format']);
+        $text = $filters[$name]['process callback']($text, $format_filters[$name], $format_object);
     }
 
     echo $text;
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mkesicki’s picture

Status: Active » Needs review

@jay.dansand,
thank you for noticing this issue and for your patch. We try check it as soon as possible.

dczepierga’s picture

Title: Text format filters are not properly given $format; cannot look up their per-format settings » [D7] Text format filters are not properly given $format; cannot look up their per-format settings
Status: Needs review » Fixed

I commit changes to GIT (diff).

@jay.dansand, really thx for notice and report this... also really thx for patch. In this function u have $format variable with object of text format, so create new fake object is not needed here...

Again really thx for help, and try to update to last DEV to check that everything works...

Greetings

jay.dansand’s picture

I updated and ran my tests and it's working for me. I double-checked and changing the input filter and clicking Preview/Save causes the appropriate (and different) HTMLPurifier/etc. rules to be loaded as well, so everything looks great. Thanks!

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

Anonymous’s picture

Issue summary: View changes

Clarified why this is a CKEDITOR and not an HTMLPurifier issue.