--- modules\filter\filter.module.org	Sun Jul 01 20:41:14 2007
+++ modules\filter\filter.module	Thu Aug 02 20:22:08 2007
@@ -1083,24 +1083,75 @@ function _filter_url_settings($format) {
  * ftp links, etc.) into hyperlinks.
  */
 function _filter_url($text, $format) {
+  // List of tags - the content of which must be skipped
+  $ignoretags = 'a|script|style';
+  
   // Pass length to regexp callback
   _filter_url_trim(NULL, variable_get('filter_url_length_'. $format, 72));
-
   $text   = ' '. $text .' ';
 
-  // Match absolute URLs.
-  $text = preg_replace_callback("`(<p>|<li>|<br\s*/?>|[ \n\r\t\(])((http://|https://|ftp://|mailto:|smb://|afp://|file://|gopher://|news://|ssl://|sslv2://|sslv3://|tls://|tcp://|udp://)([a-zA-Z0-9@:%_+*~#?&=.,/;-]*[a-zA-Z0-9@:%_+*~#&=/;-]))([.,?!]*?)(?=(</p>|</li>|<br\s*/?>|[ \n\r\t\)]))`i", '_filter_url_parse_full_links', $text);
-
-  // Match e-mail addresses.
-  $text = preg_replace("`(<p>|<li>|<br\s*/?>|[ \n\r\t\(])([A-Za-z0-9._-]+@[A-Za-z0-9._+-]+\.[A-Za-z]{2,4})([.,?!]*?)(?=(</p>|</li>|<br\s*/?>|[ \n\r\t\)]))`i", '\1<a href="mailto:\2">\2</a>\3', $text);
+  // Split at all tags.
+  // This ensures that nothing that is a tagname or attribute will be processed.
+  $chunks = preg_split('´(<.+?>)´i', $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).
 
-  // Match www domains/addresses.
-  $text = preg_replace_callback("`(<p>|<li>|[ \n\r\t\(])(www\.[a-zA-Z0-9@:%_+*~#?&=.,/;-]*[a-zA-Z0-9@:%_+~#\&=/;-])([.,?!]*?)(?=(</p>|</li>|<br\s*/?>|[ \n\r\t\)]))`i", '_filter_url_parse_partial_links', $text);
+  // If an ignoretag is found, it is stored here and removed when the 
+  // closing tag is found.
+  // Think of this as a stack that always has 0 or 1 items
+  $opentag = '';
+  for ( $i = 0; $i < count( $chunks ); $i++ ) {
+    // Even/odd = text/tag
+    if ( $i % 2 == 0 ) { // Text
+      if ( $opentag == '' ) { // No open "ignoretag", may process this text
+
+        // Match absolute URLs. 
+        $protocols = 'http://|https://|ftp://|mailto:|smb://|afp://|file://|gopher://|news://|ssl://|sslv2://|sslv3://|tls://|tcp://|udp://';
+        $urlpattern = "(?:$protocols)(?:[a-zA-Z0-9@:%_+*~#?&=.,/;-]*[a-zA-Z0-9@:%_+*~#&=/;-])";
+        $re = "`($urlpattern)([\.\,\?\!]*?)`i";
+        $chunks[$i] = preg_replace_callback($re, '_filter_url_parse_full_links', $chunks[$i] );
+        
+        // Match e-mail addresses.
+        $urlpattern = '[A-Za-z0-9._-]+@[A-Za-z0-9._+-]+\.[A-Za-z]{2,4}';
+        $re = "`($urlpattern)`i";
+        $chunks[$i] = preg_replace($re, '<a href="mailto:\1">\1</a>', $chunks[$i]);
+                
+/* This regexp now messes up links created by the first regexp...
+
+        // Match www domains/addresses.
+        $urlpattern = 'www\.[a-zA-Z0-9@:%_+*~#?&=.,/;-]*[a-zA-Z0-9@:%_+~#\&=/;-]';
+        $re = "`($urlpattern)([\.\,\?\!]*?)`i";
+        $chunks[$i] = preg_replace_callback($re, '_filter_url_parse_partial_links', $chunks[$i]);
+*/
+      }
+      else { // Do nothing, leave text unprocessed.
+        continue;
+      }
+    }
+    else { // Tag
+      if( $opentag == '' ) { // No open "ignoretag"
+        // Is it an opening tag of the ignoretags?
+        if( preg_match( "´<($ignoretags)(?:\s|>)´i", $chunk[$i], $matches ) ) {
+          // Store and catch the tag in question
+          $opentag = $matches[1];
+        }
+      }
+      else { 
+        // Nobody gets to do anything until we find a matching closing tag
+        if( preg_match( "´<\/$opentag>´i", $chunk[$i], $matches ) ) {
+          $opentag = '';
+        }
+      } // if ( $opentag == '' )
+    } // if ( $i % 2 )
+  } // for
+  
+  $text = implode( $chunks );
+  
   $text = substr($text, 1, -1);
-
   return $text;
 }
 
+
 /**
  * Scan input and make sure that all HTML tags are properly closed and nested.
  */
@@ -1176,23 +1227,27 @@ function _filter_htmlcorrector($text) {
 }
 
 /**
- * Make links out of absolute URLs.
+ * Callback function. Make links out of absolute URLs.
  */
 function _filter_url_parse_full_links($match) {
-  $match[2] = decode_entities($match[2]);
-  $caption = check_plain(_filter_url_trim($match[2]));
-  $match[2] = check_url($match[2]);
-  return $match[1] . '<a href="'. $match[2] .'" title="'. $match[2] .'">'. $caption .'</a>'. $match[5];
+  // Which capturing parenthesis in the regexp contains the url?
+  $i = 1;
+  $match[$i] = decode_entities($match[$i]);
+  $caption = check_plain(_filter_url_trim($match[$i]));
+  $match[$i] = check_url($match[$i]);
+  return '<a href="'. $match[$i] .'" title="'. $match[$i] .'">'. $caption .'</a>'. $match[$i+1];
 }
 
 /**
- * Make links out of domain names starting with "www."
+ * Callback function. Make links out of domain names starting with "www."
  */
 function _filter_url_parse_partial_links($match) {
-  $match[2] = decode_entities($match[2]);
-  $caption = check_plain(_filter_url_trim($match[2]));
-  $match[2] = check_plain($match[2]);
-  return $match[1] . '<a href="http://'. $match[2] .'" title="'. $match[2] .'">'. $caption .'</a>'. $match[3];
+  // Which parenthesis in the regexp contains the url?
+  $i = 1;
+  $match[$i] = decode_entities($match[$i]);
+  $caption = check_plain(_filter_url_trim($match[$i]));
+  $match[$i] = check_plain($match[$i]);
+  return '<a href="http://'. $match[$i] .'" title="'. $match[$i] .'">'. $caption .'</a>'. $match[$i+1];
 }
 
 /**
