* (bug 13768) pt_title field encoding fixed
authorBrion Vibber <brion@users.mediawiki.org>
Thu, 17 Apr 2008 19:11:36 +0000 (19:11 +0000)
committerBrion Vibber <brion@users.mediawiki.org>
Thu, 17 Apr 2008 19:11:36 +0000 (19:11 +0000)
pt_title field in page_protections was added without a binary marker when used on non-binary schema.
This means you get false matches for ASCII case-insensitive bits, and probably for horribly wrong UTF-8 mish-mashes as well.

Adds an updated to fix the field's encoding to binary, matching all our other title keys,
so you can join and get correct matches.

Revert r33473, which seems to assume that pt_title is supposed to be case-insensitive.
(Even if it was, it woudln't work correctly as written.)

RELEASE-NOTES
includes/api/ApiQueryInfo.php
maintenance/archives/patch-protected_titles.sql
maintenance/archives/patch-pt_title-encoding.sql [new file with mode: 0644]
maintenance/tables.sql
maintenance/updaters.inc

index 8121bf7..8356da6 100644 (file)
@@ -195,6 +195,7 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 * When hiding things on WhatLinksHere, generated URLs should hide them too
 * Properly escape search terms with regex chars so they appear highlighted in
   search results
+* (bug 13768) pt_title field encoding fixed
 
 
 === API changes in 1.13 ===
@@ -243,7 +244,6 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 * (bug 13544) Added oldid parameter to action=parse to allow for parsing of old revisions
 * (bug 13718) Return the proper continue parameter for cmsort=timestamp
 * action=login now returns the correct waiting time in the details property
-* (bug 13768) inprop=protection now honors case-insensitivity for protected titles
 
 === Languages updated in 1.13 ===
 
index ef07e94..adc8449 100644 (file)
@@ -116,8 +116,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        $res = $this->select(__METHOD__);
                        $prottitles = array();
                        while($row = $db->fetchObject($res)) {
-                               // Argh, pt_title is case-insensitive
-                               $prottitles[$row->pt_namespace][strtolower($row->pt_title)] = array(
+                               $prottitles[$row->pt_namespace][$row->pt_title] = array(
                                        'type' => 'create',
                                        'level' => $row->pt_create_perm,
                                        'expiry' => Block::decodeExpiry($row->pt_expiry, TS_ISO_8601)
@@ -250,8 +249,8 @@ class ApiQueryInfo extends ApiQueryBase {
                                {
                                        // Apparently the XML formatting code doesn't like array(null)
                                        // This is painful to fix, so we'll just work around it
-                                       if(isset($prottitles[$title->getNamespace()][strtolower($title->getDBkey())]))
-                                               $res['query']['pages'][$pageid]['protection'][] = $prottitles[$title->getNamespace()][strtolower($title->getDBkey())];
+                                       if(isset($prottitles[$title->getNamespace()][$title->getDBkey()]))
+                                               $res['query']['pages'][$pageid]['protection'][] = $prottitles[$title->getNamespace()][$title->getDBkey()];
                                        else
                                                $res['query']['pages'][$pageid]['protection'] = array();
                                        $result->setIndexedTagName($res['query']['pages'][$pageid]['protection'], 'pr');
index 5307cbd..20b6035 100644 (file)
@@ -1,7 +1,7 @@
 -- Protected titles - nonexistent pages that have been protected
 CREATE TABLE /*$wgDBprefix*/protected_titles (
   pt_namespace int NOT NULL,
-  pt_title varchar(255) NOT NULL,
+  pt_title varchar(255) binary NOT NULL,
   pt_user int unsigned NOT NULL,
   pt_reason tinyblob,
   pt_timestamp binary(14) NOT NULL,
diff --git a/maintenance/archives/patch-pt_title-encoding.sql b/maintenance/archives/patch-pt_title-encoding.sql
new file mode 100644 (file)
index 0000000..b0a2393
--- /dev/null
@@ -0,0 +1,5 @@
+-- pt_title was accidentally left with the wrong collation.
+-- This might cause failures with JOINs, and could protect the wrong pages
+-- with different case variants or unrelated UTF-8 chars.
+ALTER TABLE /*$wgDBprefix*/protected_titles
+  CHANGE COLUMN pt_title pt_title varchar(255) binary NOT NULL;
index fa7e75f..7a20ad3 100644 (file)
@@ -1210,7 +1210,7 @@ CREATE TABLE /*$wgDBprefix*/page_restrictions (
 -- Protected titles - nonexistent pages that have been protected
 CREATE TABLE /*$wgDBprefix*/protected_titles (
   pt_namespace int NOT NULL,
-  pt_title varchar(255) NOT NULL,
+  pt_title varchar(255) binary NOT NULL,
   pt_user int unsigned NOT NULL,
   pt_reason tinyblob,
   pt_timestamp binary(14) NOT NULL,
index e0208b6..b871310 100644 (file)
@@ -57,7 +57,7 @@ $wgMysqlUpdates = array(
        // 1.5
        array( 'do_schema_restructuring' ),
        array( 'add_field', 'logging',       'log_params',       'patch-log_params.sql' ),
-       array( 'do_logging_encoding' ),
+       array( 'check_bin', 'logging',       'log_title',        'patch-logging-title.sql', ),
        array( 'add_field', 'archive',       'ar_rev_id',        'patch-archive-rev_id.sql' ),
        array( 'add_field', 'page',          'page_len',         'patch-page_len.sql' ),
        array( 'do_inverse_timestamp' ),
@@ -139,6 +139,7 @@ $wgMysqlUpdates = array(
        array( 'do_category_population' ),
        array( 'add_field', 'archive',       'ar_parent_id',     'patch-ar_parent_id.sql'),
        array( 'do_populate_parent_id' ),
+       array( 'check_bin', 'protected_titles', 'pt_title',      'patch-pt_title-encoding.sql', ),
 );
 
 
@@ -445,20 +446,20 @@ function do_user_update() {
  * 1.4 betas were missing the 'binary' marker from logging.log_title,
  * which causes a collation mismatch error on joins in MySQL 4.1.
  */
-function do_logging_encoding() {
+function check_bin( $table, $field, $patchFile ) {
        global $wgDatabase, $wgDBtype;
        if ($wgDBtype != 'mysql')
                return;
-       $logging = $wgDatabase->tableName( 'logging' );
-       $res = $wgDatabase->query( "SELECT log_title FROM $logging LIMIT 0" );
+       $tableName = $wgDatabase->tableName( $table );
+       $res = $wgDatabase->query( "SELECT $field FROM $tableName LIMIT 0" );
        $flags = explode( ' ', mysql_field_flags( $res->result, 0 ) );
        $wgDatabase->freeResult( $res );
 
        if( in_array( 'binary', $flags ) ) {
-               echo "Logging table has correct title encoding.\n";
+               echo "$table table has correct $field encoding.\n";
        } else {
-               echo "Fixing title encoding on logging table... ";
-               dbsource( archive( 'patch-logging-title.sql' ), $wgDatabase );
+               echo "Fixing $field encoding on $table table... ";
+               dbsource( archive( $patchFile ), $wgDatabase );
                echo "ok\n";
        }
 }