? htmlcorrector.patch
? install_form.patch
? install_form_15.patch
? no_settings_php.patch
? sites/localhost
Index: modules/filter/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v
retrieving revision 1.172
diff -u -p -r1.172 filter.module
--- modules/filter/filter.module	30 Apr 2007 17:03:24 -0000	1.172
+++ modules/filter/filter.module	8 May 2007 14:57:17 -0000
@@ -953,7 +953,7 @@ function theme_filter_tips_more_info() {
 function filter_filter($op, $delta = 0, $format = -1, $text = '') {
   switch ($op) {
     case 'list':
-      return array(0 => t('HTML filter'), 1 => t('Line break converter'), 2 => t('URL filter'));
+      return array(0 => t('HTML filter'), 1 => t('Line break converter'), 2 => t('URL filter'), 3 => t('HTML corrector'));
 
     case 'description':
       switch ($delta) {
@@ -963,6 +963,8 @@ function filter_filter($op, $delta = 0, 
           return t('Converts line breaks into HTML (i.e. &lt;br&gt; and &lt;p&gt; tags).');
         case 2:
           return t('Turns web and e-mail addresses into clickable links.');
+        case 3:
+          return t('Corrects faulty and chopped off HTML in postings.');
         default:
           return;
       }
@@ -975,6 +977,8 @@ function filter_filter($op, $delta = 0, 
           return _filter_autop($text);
         case 2:
           return _filter_url($text, $format);
+        case 3:
+          return _filter_htmlcorrector($text);
         default:
           return $text;
       }
@@ -1097,6 +1101,75 @@ function _filter_url($text, $format) {
 }
 
 /**
+ * Scan input and make sure that all HTML tags are properly closed and nested.
+ */
+function _filter_htmlcorrector($text) {
+  // Tags which cannot be nested but are typically left unclosed.
+  $nonesting = array('li', 'p');
+  
+  // Single use tags in HTML4
+  $singleuse = array('base', 'meta', 'link', 'hr', 'br', 'param', 'img', 'area', 'input', 'col', 'frame');
+
+  // Properly entify angles
+  $text = preg_replace('!<([^a-zA-Z/])!', '&lt;\1', $text);
+
+  // Splits tags from text
+  $split = preg_split('/<([^>]+?)>/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
+  // Note: PHP ensures the array consists of alternating delimiters and literals
+  // and begins and ends with a literal (inserting $null as required).
+
+  $tag = false; // Odd/even counter. Tag or no tag.
+  $stack = array();
+  $output = '';
+  foreach ($split as $value) {
+    // HTML tag
+    if ($tag) {
+      list($tagname) = explode(' ', strtolower($value), 2);
+      // Closing tag
+      if ($tagname{0} == '/') {
+        $tagname = substr($tagname, 1);
+        if (!in_array($tagname, $singleuse)) {
+          // See if we have other tags lingering first, and close them
+          while (($stack[0] != $tagname) && count($stack)) {
+            $output .= '</'. array_shift($stack) .'>';
+          }
+          // If the tag was not found, just leave it out;
+          if (count($stack)) {
+            $output .= '</'. array_shift($stack) .'>';
+          }
+        }
+      }
+      // Opening tag
+      else {
+        // See if we have an identical tag already open and close it if desired.
+        if (count($stack) && ($stack[0] == $tagname) && in_array($stack[0], $nonesting)) {
+          $output .= '</'. array_shift($stack) .'>';
+        }
+        // Push non-single-use tags onto the stack
+        if (!in_array($tagname, $singleuse)) {
+          array_unshift($stack, $tagname);
+        }
+        // Add trailing slash to single-use tags as per X(HT)ML.
+        else {
+          $value = rtrim($value, ' /') . ' /';
+        }
+        $output .= '<'. $value .'>';
+      }
+    }
+    else {
+      // Passthrough
+      $output .= $value;
+    }
+    $tag = !$tag;
+  }
+  // Close remaining tags
+  while (count($stack) > 0) {
+    $output .= '</'. array_shift($stack) .'>';
+  }
+  return $output;
+}
+
+/**
  * Make links out of absolute URLs.
  */
 function _filter_url_parse_full_links($match) {
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.102
diff -u -p -r1.102 system.install
--- modules/system/system.install	6 May 2007 05:50:43 -0000	1.102
+++ modules/system/system.install	8 May 2007 14:57:21 -0000
@@ -1140,12 +1140,16 @@ function system_install() {
   db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES (1, 'filter', 0, 1)");
   // Line break filter.
   db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES (1, 'filter', 1, 2)");
+  // HTML corrector filter.
+  db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES (1, 'filter', 3, 3)");
 
   // Full HTML:
   // URL filter.
   db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES (2, 'filter', 2, 0)");
   // Line break filter.
   db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES (2, 'filter', 1, 1)");
+  // HTML corrector filter.
+  db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES (1, 'filter', 3, 2)");
 
   db_query("INSERT INTO {variable} (name,value) VALUES ('filter_html_1','i:1;')");
 
