Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.245
diff -u -9 -p -r1.245 bootstrap.inc
--- includes/bootstrap.inc	2 Nov 2008 10:56:35 -0000	1.245
+++ includes/bootstrap.inc	6 Nov 2008 22:09:23 -0000
@@ -809,36 +809,33 @@ function check_plain($text) {
  *
  * When text containing an invalid UTF-8 lead byte (0xC0 - 0xFF) is presented
  * as UTF-8 to Internet Explorer 6, the program may misinterpret subsequent
  * bytes. When these subsequent bytes are HTML control characters such as
  * quotes or angle brackets, parts of the text that were deemed safe by filters
  * end up in locations that are potentially unsafe; An onerror attribute that
  * is outside of a tag, and thus deemed safe by a filter, can be interpreted
  * by the browser as if it were inside the tag.
  *
- * This function exploits preg_match behaviour (since PHP 4.3.5) when used
- * with the u modifier, as a fast way to find invalid UTF-8. When the matched
- * string contains an invalid byte sequence, it will fail silently.
- *
- * preg_match may not fail on 4 and 5 octet sequences, even though they
- * are not supported by the specification.
- *
- * The specific preg_match behaviour is present since PHP 4.3.5.
+ * The function does not return FALSE for strings containing character codes
+ * above U+10FFFF, even though these are prohibited by RFC 3629.
  *
  * @param $text
  *   The text to check.
  * @return
  *   TRUE if the text is valid UTF-8, FALSE if not.
  */
 function drupal_validate_utf8($text) {
   if (strlen($text) == 0) {
     return TRUE;
   }
+  // With the PCRE_UTF8 modifier 'u', preg_match() fails silently on strings
+  // containing invalid UTF-8 byte sequences. It does not reject character
+  // codes above U+10FFFF (represented by 4 or more octets), though.
   return (preg_match('/^./us', $text) == 1);
 }
 
 /**
  * Since $_SERVER['REQUEST_URI'] is only available on Apache, we
  * generate an equivalent using other environment variables.
  */
 function request_uri() {
 
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.816
diff -u -9 -p -r1.816 common.inc
--- includes/common.inc	5 Nov 2008 17:06:18 -0000	1.816
+++ includes/common.inc	6 Nov 2008 22:09:23 -0000
@@ -445,19 +445,19 @@ function drupal_http_request($url, $head
   }
 
   switch ($uri['scheme']) {
     case 'http':
       $port = isset($uri['port']) ? $uri['port'] : 80;
       $host = $uri['host'] . ($port != 80 ? ':' . $port : '');
       $fp = @fsockopen($uri['host'], $port, $errno, $errstr, 15);
       break;
     case 'https':
-      // Note: Only works for PHP 4.3 compiled with OpenSSL.
+      // Note: Only works when PHP is compiled with OpenSSL support.
       $port = isset($uri['port']) ? $uri['port'] : 443;
       $host = $uri['host'] . ($port != 443 ? ':' . $port : '');
       $fp = @fsockopen('ssl://' . $uri['host'], $port, $errno, $errstr, 20);
       break;
     default:
       $result->error = 'invalid schema ' . $uri['scheme'];
       return $result;
   }
 
Index: includes/database/database.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/database.inc,v
retrieving revision 1.21
diff -u -9 -p -r1.21 database.inc
--- includes/database/database.inc	3 Nov 2008 05:55:55 -0000	1.21
+++ includes/database/database.inc	6 Nov 2008 22:09:23 -0000
@@ -2205,24 +2205,20 @@ function db_rewrite_sql($query, $primary
           \( (?P>anonymous_view) \)          # an open parenthesis, more "anonymous view" and finally a close parenthesis.
         )*
       )[^()]+WHERE)
     }x';
     preg_match($pattern, $query, $matches);
     if ($where) {
       $n = strlen($matches[1]);
       $second_part = substr($query, $n);
       $first_part = substr($matches[1], 0, $n - 5) ." $join WHERE $where AND ( ";
-      // PHP 4 does not support strrpos for strings. We emulate it.
-      $haystack_reverse = strrev($second_part);
-      // No need to use strrev on the needle, we supply GROUP, ORDER, LIMIT
-      // reversed.
-      foreach (array('PUORG', 'REDRO', 'TIMIL') as $needle_reverse) {
-        $pos = strpos($haystack_reverse, $needle_reverse);
+      foreach (array('GROUP', 'ORDER', 'LIMIT') as $needle) {
+        $pos = strrpos($second_part, $needle);
         if ($pos !== FALSE) {
           // All needles are five characters long.
           $pos += 5;
           break;
         }
       }
       if ($pos === FALSE) {
         $query = $first_part . $second_part . ')';
       }
