--- modules\filter\filter.module.org	Sun Jul 01 20:41:14 2007
+++ modules\filter\filter.module	Mon Jul 23 23:50:47 2007
@@ -1083,21 +1083,60 @@ function _filter_url_settings($format) {
  * ftp links, etc.) into hyperlinks.
  */
 function _filter_url($text, $format) {
+  //The following tags may contain text with a URL that should be converted to a link
+  //List also contains standalone/empty tags like img and br
+  $tags_begin =  'caption|td|th|div|dd|dt|li|blockquote|address|p|h[1-6]|i|b|u|tt|big|small|strike|s|em|strong|font|dfn|samp|kbd|var|cite|abbr|acronym|sub|sup|q|ins|del|img|br|object|applet';
+
+
+  //transform each tagname from 'p' to '<\/?p[^>]*>'
+  //this pattern will match <p>, </p>, <p class="foo"> and <p />
+  //the last one is significant for xhtml standalone tags like <img /> and <br />
+  //note: <img/> and <br/>, won't work. While valid xhtml their use is discouraged anyway
+  //note: the pattern will obviously match many invalid tags too like <p &&&>    
+  $arr_tags_begin = explode( "|", $tags_begin );
+  for ( $i = 0; $i < count( $arr_tags_begin ); $i++ ){
+    $arr_tags_begin[$i] = '<\/?' . $arr_tags_begin[$i] . '[^>]*>'; 
+  }
+  $tags_begin = implode( "|", $arr_tags_begin );
+
   // 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);
-
+  //The structure of each three matches below is
+  // 1. a tag from the list above or newline or </a>
+  // 2. any characters except "<" 
+  // 3. the url to match
+  // 4. possible period or other marks at end of url are considered separate (end of sentence)
+  // 5. end url in space, newline or tag ("<" character)
+
+  //In many cases the patterns below only match the first url if there are many in the same paragraph. 
+  //Therefore the preg_replace are encapsulate in loops that will re-run the replace as many times as needed.
+
+  // 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 = "`(($tags_begin|\n|\r|</a>)([^<])*?)($urlpattern)(([\.\,\?\!]*?)[\<\s\n\r])`i";
+  while(preg_match($re, $text)) {
+    $text = preg_replace_callback($re, '_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);
-
+  $urlpattern = '[A-Za-z0-9._-]+@[A-Za-z0-9._+-]+\.[A-Za-z]{2,4}';
+  $re = "`(($tags_begin|\n|\r|</a>)([^<])*?)($urlpattern)(([\.\,\?\!]*?)[\<\s\n\r])`i";
+  while(preg_match($re, $text)) {
+    $text = preg_replace($re, '\1<a href="mailto:\4">\4</a>\5', $text);
+  }
+  
   // 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);
+  $urlpattern = 'www\.[a-zA-Z0-9@:%_+*~#?&=.,/;-]*[a-zA-Z0-9@:%_+~#\&=/;-]';
+  $re = "`(($tags_begin|\n|\r|</a>)([^<])*?)($urlpattern)(([\.\,\?\!]*?)[\<\s\n\r])`i";
+  while(preg_match($re, $text)) {
+    $text = preg_replace_callback($re, '_filter_url_parse_partial_links', $text);
+  }
+  
   $text = substr($text, 1, -1);
-
   return $text;
 }
 
@@ -1179,21 +1218,26 @@ function _filter_htmlcorrector($text) {
  * 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 parenthesis in the regexp contains the url?
+  $i = 4;
+  $match[$i] = decode_entities($match[$i]);
+  $caption = check_plain(_filter_url_trim($match[$i]));
+  $match[$i] = check_url($match[$i]);
+  return $match[1] . '<a href="'. $match[$i] .'" title="'. $match[$i] .'">'. $caption .'</a>'. $match[$i+3];
 }
 
 /**
  * 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 = 4;
+  $match[$i] = decode_entities($match[$i]);
+  $caption = check_plain(_filter_url_trim($match[$i]));
+  $match[$i] = check_plain($match[$i]);
+  return $match[1] . '<a href="http://'. $match[$i] .'" title="'. $match[$i] .'">'. $caption .'</a>'. $match[$i+1];
 }
+
 
 /**
  * Shortens long URLs to http://www.example.com/long/url...
