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.)
* 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 ===
* (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 ===
$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)
{
// 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');
-- 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,
--- /dev/null
+-- 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;
-- 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,
// 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' ),
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', ),
);
* 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";
}
}