Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1145
diff -u -p -r1.1145 common.inc
--- includes/common.inc	7 Apr 2010 17:30:43 -0000	1.1145
+++ includes/common.inc	10 Apr 2010 02:15:53 -0000
@@ -1184,7 +1184,7 @@ function flood_is_allowed($name, $thresh
  * Prepare a URL for use in an HTML attribute. Strips harmful protocols.
  */
 function check_url($uri) {
-  return filter_xss_bad_protocol($uri, FALSE);
+  return check_plain(filter_xss_bad_protocol($uri));
 }
 
 /**
@@ -1363,7 +1363,7 @@ function _filter_xss_attributes($attr) {
       case 2:
         // Attribute value, a URL after href= for instance
         if (preg_match('/^"([^"]*)"(\s+|$)/', $attr, $match)) {
-          $thisval = filter_xss_bad_protocol($match[1]);
+          $thisval = filter_xss_bad_protocol($match[1], TRUE);
 
           if (!$skip) {
             $attrarr[] = "$attrname=\"$thisval\"";
@@ -1375,7 +1375,7 @@ function _filter_xss_attributes($attr) {
         }
 
         if (preg_match("/^'([^']*)'(\s+|$)/", $attr, $match)) {
-          $thisval = filter_xss_bad_protocol($match[1]);
+          $thisval = filter_xss_bad_protocol($match[1], TRUE);
 
           if (!$skip) {
             $attrarr[] = "$attrname='$thisval'";
@@ -1386,7 +1386,7 @@ function _filter_xss_attributes($attr) {
         }
 
         if (preg_match("%^([^\s\"']+)(\s+|$)%", $attr, $match)) {
-          $thisval = filter_xss_bad_protocol($match[1]);
+          $thisval = filter_xss_bad_protocol($match[1], TRUE);
 
           if (!$skip) {
             $attrarr[] = "$attrname=\"$thisval\"";
@@ -1422,25 +1422,30 @@ function _filter_xss_attributes($attr) {
 }
 
 /**
- * Processes an HTML attribute value and ensures it does not contain an URL with a disallowed protocol (e.g. javascript:).
+ * Processes a text or HTML string and ensures it does not contain an URL with a disallowed protocol (e.g. javascript:).
  *
  * @param $string
  *   The string with the attribute value.
- * @param $decode
- *   Whether to decode entities in the $string. Set to FALSE if the $string
- *   is in plain text, TRUE otherwise. Defaults to TRUE.
+ * @param $html_encoded
+ *   Whether $string is already encoded for HTML (for example, if it was parsed
+ *   from an HTML document or an HTML editor). If TRUE, the returned string will
+ *   also be escaped for HTML. If FALSE, the returned string will not be
+ *   HTML-escaped, so check_plain() will need to be called prior to outputting
+ *   to a Drupal page. Defaults to FALSE.
  * @return
- *   Cleaned up and HTML-escaped version of $string.
+ *   Cleaned up version of $string.
+ *
+ * @see check_url()
  */
-function filter_xss_bad_protocol($string, $decode = TRUE) {
+function filter_xss_bad_protocol($string, $html_encoded = FALSE) {
   static $allowed_protocols;
 
   if (!isset($allowed_protocols)) {
     $allowed_protocols = array_flip(variable_get('filter_allowed_protocols', array('ftp', 'http', 'https', 'irc', 'mailto', 'news', 'nntp', 'rtsp', 'sftp', 'ssh', 'telnet', 'webcal')));
   }
 
-  // Get the plain text representation of the attribute value (i.e. its meaning).
-  if ($decode) {
+  // If the string is HTML-encoded, decode it.
+  if ($html_encoded) {
     $string = decode_entities($string);
   }
 
@@ -1465,7 +1470,12 @@ function filter_xss_bad_protocol($string
     }
   } while ($before != $string);
 
-  return check_plain($string);
+  // If the string was HTML-encoded and we decoded it, re-encode it.
+  if ($html_encoded) {
+    $string = check_plain($string);
+  }
+
+  return $string;
 }
 
 /**
@@ -1967,7 +1977,7 @@ function url($path = NULL, array $option
     // Note: we could use url_is_external($path) here, but that would
     // require another function call, and performance inside url() is critical.
     $colonpos = strpos($path, ':');
-    $options['external'] = ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && filter_xss_bad_protocol($path, FALSE) == check_plain($path));
+    $options['external'] = ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && filter_xss_bad_protocol($path) == $path);
   }
 
   // Preserve the original path before altering or aliasing.
@@ -2087,7 +2097,7 @@ function url_is_external($path) {
   $colonpos = strpos($path, ':');
   // Only call the slow filter_xss_bad_protocol if $path contains a ':'
   // before any / ? or #.
-  return $colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && filter_xss_bad_protocol($path, FALSE) == check_plain($path);
+  return $colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && filter_xss_bad_protocol($path) == $path;
 }
 
 /**
Index: modules/comment/comment.tokens.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.tokens.inc,v
retrieving revision 1.10
diff -u -p -r1.10 comment.tokens.inc
--- modules/comment/comment.tokens.inc	9 Jan 2010 21:54:00 -0000	1.10
+++ modules/comment/comment.tokens.inc	10 Apr 2010 02:15:55 -0000
@@ -167,7 +167,7 @@ function comment_tokens($type, $tokens, 
           break;
 
         case 'homepage':
-          $replacements[$original] = $sanitize ? filter_xss_bad_protocol($comment->homepage) : $comment->homepage;
+          $replacements[$original] = $sanitize ? check_url($comment->homepage) : $comment->homepage;
           break;
 
         case 'title':
