Index: modules/filter/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v
retrieving revision 1.177
diff -u -r1.177 filter.module
--- modules/filter/filter.module	4 Jun 2007 07:22:17 -0000	1.177
+++ modules/filter/filter.module	4 Jun 2007 20:07:04 -0000
@@ -13,6 +13,7 @@
 
 define('FILTER_HTML_STRIP', 1);
 define('FILTER_HTML_ESCAPE', 2);
+define('FILTER_HTML_ESCAPE_DISALLOWED', 3);
 
 /**
  * Implementation of hook_help().
@@ -155,7 +156,7 @@
   global $base_url;
   switch ($delta) {
     case 0:
-      if (variable_get("filter_html_$format", FILTER_HTML_STRIP) ==  FILTER_HTML_STRIP) {
+      if (in_array(variable_get("filter_html_$format", FILTER_HTML_STRIP), array(FILTER_HTML_STRIP, FILTER_HTML_ESCAPE_DISALLOWED))) {
         if ($allowed_html = variable_get("allowed_html_$format", '<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>')) {
           switch ($long) {
             case 0:
@@ -1013,7 +1014,11 @@
     '#type' => 'radios',
     '#title' => t('Filter HTML tags'),
     '#default_value' => variable_get("filter_html_$format", FILTER_HTML_STRIP),
-    '#options' => array(FILTER_HTML_STRIP => t('Strip disallowed tags'), FILTER_HTML_ESCAPE => t('Escape all tags')),
+    '#options' => array(
+      FILTER_HTML_STRIP => t('Strip disallowed tags'),
+      FILTER_HTML_ESCAPE => t('Escape all tags'),
+      FILTER_HTML_ESCAPE_DISALLOWED => t('Escape disallowed tags')
+    ),
     '#description' => t('How to deal with HTML tags in user-contributed content. If set to "Strip disallowed tags", dangerous tags are removed (see below). If set to "Escape tags", all HTML is escaped and presented as it was typed.'),
   );
   $form['filter_html']["allowed_html_$format"] = array(
@@ -1053,6 +1058,12 @@
     $text = check_plain($text);
   }
 
+  if (variable_get("filter_html_$format", FILTER_HTML_STRIP) == FILTER_HTML_ESCAPE_DISALLOWED) {
+    // Escape disallowed HTML.
+    $allowed_tags = preg_split('/\s+|<|>/', variable_get("allowed_html_$format", '<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>'), -1, PREG_SPLIT_NO_EMPTY);
+    $text = filter_xss($text, $allowed_tags, TRUE);
+  }
+
   if (variable_get("filter_html_nofollow_$format", FALSE)) {
     $text = preg_replace('/<a([^>]+)>/i', '<a\\1 rel="nofollow">', $text);
   }
@@ -1305,9 +1316,9 @@
  * @param $format
  *   The format to use.
  */
-function filter_xss($string, $allowed_tags = array('a', 'em', 'strong', 'cite', 'code', 'ul', 'ol', 'li', 'dl', 'dt', 'dd')) {
+function filter_xss($string, $allowed_tags = array('a', 'em', 'strong', 'cite', 'code', 'ul', 'ol', 'li', 'dl', 'dt', 'dd'), $escape = FALSE) {
   // Store the input format
-  _filter_xss_split($allowed_tags, TRUE);
+  _filter_xss_split($allowed_tags, TRUE, $escape);
   // Remove NUL characters (ignored by some browsers)
   $string = str_replace(chr(0), '', $string);
   // Remove Netscape 4 JS entities
@@ -1346,11 +1357,13 @@
  *   If the element isn't allowed, an empty string. Otherwise, the cleaned up
  *   version of the HTML element.
  */
-function _filter_xss_split($m, $store = FALSE) {
+function _filter_xss_split($m, $store = FALSE, $escape = FALSE) {
   static $allowed_html;
+  static $need_escape;
 
   if ($store) {
     $allowed_html = array_flip($m);
+    $need_escape = $escape;
     return;
   }
 
@@ -1367,7 +1380,7 @@
 
   if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $string, $matches)) {
     // Seriously malformed
-    return '';
+    return $need_escape ? check_plain($string) : '';
   }
 
   $slash = trim($matches[1]);
@@ -1376,7 +1389,7 @@
 
   if (!isset($allowed_html[strtolower($elem)])) {
     // Disallowed HTML element
-    return '';
+    return $need_escape ? check_plain($string) : '';
   }
 
   if ($slash != '') {
