merge ORACLE_WORK. sorry, this may break some parts of MySQL, i did not test extensi...
authorRiver Tarnell <kateturner@users.mediawiki.org>
Tue, 2 Aug 2005 13:35:19 +0000 (13:35 +0000)
committerRiver Tarnell <kateturner@users.mediawiki.org>
Tue, 2 Aug 2005 13:35:19 +0000 (13:35 +0000)
43 files changed:
config/index.php
includes/Article.php
includes/BagOStuff.php
includes/Block.php
includes/CategoryPage.php
includes/Database.php
includes/DatabaseFunctions.php
includes/DatabaseOracle.php [new file with mode: 0644]
includes/EditPage.php
includes/GlobalFunctions.php
includes/ImagePage.php
includes/LinkCache.php
includes/LoadBalancer.php
includes/LogPage.php
includes/Namespace.php
includes/ObjectCache.php
includes/PageHistory.php
includes/QueryPage.php
includes/RecentChange.php
includes/Revision.php
includes/SearchEngine.php
includes/SiteStatsUpdate.php
includes/Skin.php
includes/SkinTemplate.php
includes/SpecialAllpages.php
includes/SpecialContributions.php
includes/SpecialLog.php
includes/SpecialPreferences.php
includes/SpecialRandompage.php
includes/SpecialRecentchanges.php
includes/SpecialUndelete.php
includes/Title.php
includes/User.php
includes/UserMailer.php
includes/WatchedItem.php
install-utils.inc
maintenance/InitialiseMessages.inc
maintenance/importDump.php
maintenance/oracle/archives/patch-transcache.sql [new file with mode: 0644]
maintenance/oracle/interwiki.sql [new file with mode: 0644]
maintenance/oracle/tables.sql [new file with mode: 0644]
maintenance/update.php
maintenance/updaters.inc

index bfabc7a..768ab3a 100644 (file)
@@ -367,6 +367,7 @@ print "<li>Script URI path: <tt>" . htmlspecialchars( $conf->ScriptPath ) . "</t
                ? 'root@localhost'
                : $_SERVER["SERVER_ADMIN"];
        $conf->EmergencyContact = importPost( "EmergencyContact", $defaultEmail );
+       $conf->DBtype = importPost( "DBtype", "mysql" );
        $conf->DBserver = importPost( "DBserver", "localhost" );
        $conf->DBname = importPost( "DBname", "wikidb" );
        $conf->DBuser = importPost( "DBuser", "wikiuser" );
@@ -453,6 +454,14 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                $wgCommandLineMode = false;
                chdir( ".." );
                eval($local);
+               if (!in_array($conf->DBtype, array("mysql", "oracle"))) {
+                       $errs["DBtype"] = "Unknown database type.";
+                       continue;
+               }
+               print "<li>Database type: {$conf->DBtype}</li>\n";
+               $dbclass = 'Database'.ucfirst($conf->DBtype);
+               require_once("$dbclass.php");
+               $wgDBtype = $conf->DBtype;
                $wgDBadminuser = "root";
                $wgDBadminpassword = $conf->RootPW;
                $wgDBprefix = $conf->DBprefix;
@@ -471,58 +480,70 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                                see <a href='http://dev.mysql.com/doc/mysql/en/old-client.html'
                                >http://dev.mysql.com/doc/mysql/en/old-client.html</a> for help.</b></li>\n";
                }
-               print "<li>Trying to connect to MySQL on $wgDBserver as root...\n";
-               $wgDatabase = Database::newFromParams( $wgDBserver, "root", $conf->RootPW, "", 1 );
-
-               if( $wgDatabase->isOpen() ) {
-                       $myver = mysql_get_server_info( $wgDatabase->mConn );
-                       $wgDatabase->ignoreErrors(true);
-                       $conf->Root = true;
-                       print "<ul><li>Connected as root (automatic)</li></ul></li>\n";
-               } else {
-                       print "<ul><li>MySQL error " . ($err = mysql_errno() ) .
-                               ": " . htmlspecialchars( mysql_error() ) . "</li></ul></li>";
-                       $ok = false;
-                       switch( $err ) {
-                       case 1045:
-                       case 2000:
-                               if( $conf->Root ) {
-                                       $errs["RootPW"] = "Check password";
-                               } else {
-                                       print "<li>Trying regular user...\n";
-                                       /* Try the regular user... */
-                                       $wgDBadminuser = $wgDBuser;
-                                       $wgDBadminpassword = $wgDBpassword;
-                                       /* Wait one second for connection rate limiting, present on some systems */
-                                       sleep(1);
-                                       $wgDatabase = Database::newFromParams( $wgDBserver, $wgDBuser, $wgDBpassword, "", 1 );
-                                       if( !$wgDatabase->isOpen() ) {
-                                               print "<ul><li>MySQL error " . ($err = mysql_errno() ) .
-                                                       ": " . htmlspecialchars( mysql_error() ) . "</li></ul></li>";
-                                               $errs["DBuser"] = "Check name/pass";
-                                               $errs["DBpassword"] = "or enter root";
-                                               $errs["DBpassword2"] = "password below";
-                                               $errs["RootPW"] = "Got root?";
+               $dbc = new $dbclass;
+               if ($conf->DBtype == 'mysql') {
+                       print "<li>Trying to connect to database server on $wgDBserver as root...\n";
+                       $wgDatabase = $dbc->newFromParams( $wgDBserver, "root", $conf->RootPW, "", 1 );
+
+                       if( $wgDatabase->isOpen() ) {
+                               $myver = get_db_version();
+                               $wgDatabase->ignoreErrors(true);
+                               $conf->Root = true;
+                               print "<ul><li>Connected as root (automatic)</li></ul></li>\n";
+                       } else {
+                               print "<ul><li>MySQL error " . ($err = mysql_errno() ) .
+                                       ": " . htmlspecialchars( mysql_error() ) . "</li></ul></li>";
+                               $ok = false;
+                               switch( $err ) {
+                               case 1045:
+                               case 2000:
+                                       if( $conf->Root ) {
+                                               $errs["RootPW"] = "Check password";
                                        } else {
-                                               $myver = mysql_get_server_info( $wgDatabase->mConn );
-                                               $wgDatabase->ignoreErrors(true);
-                                               $conf->Root = false;
-                                               $conf->RootPW = "";
-                                               print " ok.</li>\n";
-                                               # And keep going...
-                                               $ok = true;
+                                               print "<li>Trying regular user...\n";
+                                               /* Try the regular user... */
+                                               $wgDBadminuser = $wgDBuser;
+                                               $wgDBadminpassword = $wgDBpassword;
+                                               /* Wait one second for connection rate limiting, present on some systems */
+                                               sleep(1);
+                                               $wgDatabase = Database::newFromParams( $wgDBserver, $wgDBuser, $wgDBpassword, "", 1 );
+                                               if( !$wgDatabase->isOpen() ) {
+                                                       print "<ul><li>MySQL error " . ($err = mysql_errno() ) .
+                                                               ": " . htmlspecialchars( mysql_error() ) . "</li></ul></li>";
+                                                       $errs["DBuser"] = "Check name/pass";
+                                                       $errs["DBpassword"] = "or enter root";
+                                                       $errs["DBpassword2"] = "password below";
+                                                       $errs["RootPW"] = "Got root?";
+                                               } else {
+                                                       $myver = mysql_get_server_info( $wgDatabase->mConn );
+                                                       $wgDatabase->ignoreErrors(true);
+                                                       $conf->Root = false;
+                                                       $conf->RootPW = "";
+                                                       print " ok.</li>\n";
+                                                       # And keep going...
+                                                       $ok = true;
+                                               }
+                                               break;
                                        }
+                               case 2002:
+                               case 2003:
+                                       $errs["DBserver"] = "Connection failed";
+                                       break;
+                               default:
+                                       $errs["DBserver"] = "Couldn't connect to database";
                                        break;
                                }
-                       case 2002:
-                       case 2003:
-                               $errs["DBserver"] = "Connection failed";
-                               break;
-                       default:
-                               $errs["DBserver"] = "Couldn't connect to database";
-                               break;
+                               if( !$ok ) continue;
+                       }
+               } else /* not mysql */ {
+                       print "<li>Connecting to SQL server...";
+                       $wgDatabase = $dbc->newFromParams($wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, 1);
+                       if (!$wgDatabase->isOpen()) {
+                               print " error: " . $wgDatabase->lastError() . "</li>\n";
+                       } else {
+                               $wgDatabase->ignoreErrors(true);
+                               $myver = get_db_version();
                        }
-                       if( !$ok ) continue;
                }
 
                if ( !$wgDatabase->isOpen() ) {
@@ -545,28 +566,30 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                }
                print "</li>\n";
 
-               @$sel = mysql_select_db( $wgDBname, $wgDatabase->mConn );
-               if( $sel ) {
-                       print "<li>Database <tt>" . htmlspecialchars( $wgDBname ) . "</tt> exists</li>\n";
-               } else {
-                       $err = mysql_errno();
-                       if ( $err != 1049 ) {
-                               print "<ul><li>Error selecting database $wgDBname: $err " . htmlspecialchars( mysql_error() ) .
-                                       "</li></ul>";
-                               continue;
-                       }
-                       $res = $wgDatabase->query( "CREATE DATABASE `$wgDBname`" );
-                       if( !$res ) {
-                               print "<li>Couldn't create database <tt>" .
-                                       htmlspecialchars( $wgDBname ) .
-                                       "</tt>; try with root access or check your username/pass.</li>\n";
-                               $errs["RootPW"] = "&lt;- Enter";
-                               continue;
+               if ($conf->DBtype == 'mysql') {
+                       @$sel = mysql_select_db( $wgDBname, $wgDatabase->mConn );
+                       if( $sel ) {
+                               print "<li>Database <tt>" . htmlspecialchars( $wgDBname ) . "</tt> exists</li>\n";
+                       } else {
+                               $err = mysql_errno();
+                               if ( $err != 1049 ) {
+                                       print "<ul><li>Error selecting database $wgDBname: $err " .
+                                               htmlspecialchars( mysql_error() ) . "</li></ul>";
+                                       continue;
+                               }
+                               $res = $wgDatabase->query( "CREATE DATABASE `$wgDBname`" );
+                               if( !$res ) {
+                                       print "<li>Couldn't create database <tt>" .
+                                               htmlspecialchars( $wgDBname ) .
+                                               "</tt>; try with root access or check your username/pass.</li>\n";
+                                       $errs["RootPW"] = "&lt;- Enter";
+                                       continue;
+                               }
+                               print "<li>Created database <tt>" . htmlspecialchars( $wgDBname ) . "</tt></li>\n";
                        }
-                       print "<li>Created database <tt>" . htmlspecialchars( $wgDBname ) . "</tt></li>\n";
+                       $wgDatabase->selectDB( $wgDBname );
                }
 
-               $wgDatabase->selectDB( $wgDBname );
 
                if( $wgDatabase->tableExists( "cur" ) || $wgDatabase->tableExists( "revision" ) ) {
                        print "<li>There are already MediaWiki tables in this database. Checking if updates are needed...</li>\n";
@@ -597,8 +620,14 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                } else {
                        # FIXME: Check for errors
                        print "<li>Creating tables...";
-                       dbsource( "../maintenance/tables.sql", $wgDatabase );
-                       dbsource( "../maintenance/interwiki.sql", $wgDatabase );
+                       if ($conf->DBtype == 'mysql') {
+                               dbsource( "../maintenance/tables.sql", $wgDatabase );
+                               dbsource( "../maintenance/interwiki.sql", $wgDatabase );
+                       } else {
+                               dbsource( "../maintenance/oracle/tables.sql", $wgDatabase );
+                               dbsource( "../maintenance/oracle/interwiki.sql", $wgDatabase );
+                       }
+
                        print " done.</li>\n";
 
                        print "<li>Initializing data...";
@@ -902,17 +931,31 @@ if( count( $errs ) ) {
 <h2>Database config</h2>
 
 <dl class="setup">
+       <dd>
+               <label class='column'>Database type</label>
+               <div>Select the database server software:</div>
+               <ul class='plain'>
+               <?php
+                       aField( $conf, "DBtype", "MySQL", "radio", "mysql");
+                       aField( $conf, "DBtype", "Oracle", "radio", "oracle" );
+               ?>
+               </ul>
+       </dd>
+
        <dd><?php
-               aField( $conf, "DBserver", "MySQL server" );
+               aField( $conf, "DBserver", "SQL server host" );
        ?></dd>
        <dt>
                If your database server isn't on your web server, enter the name
-               or IP address here.
+               or IP address here.  MySQL only.
        </dt>
 
        <dd><?php
                aField( $conf, "DBname", "Database name" );
        ?></dd>
+       <dt>
+               If using Oracle, set this to your connection identifier.
+       </dt>
        <dd><?php
                aField( $conf, "DBuser", "DB username" );
        ?></dd>
@@ -1131,6 +1174,7 @@ if ( \$wgCommandLineMode ) {
 \$wgDBuser           = \"{$slconf['DBuser']}\";
 \$wgDBpassword       = \"{$slconf['DBpassword']}\";
 \$wgDBprefix         = \"{$slconf['DBprefix']}\";
+\$wgDBtype           = \"{$slconf['DBtype']}\";
 
 # If you're on MySQL 3.x, this next line must be FALSE:
 \$wgDBmysql4 = {$conf->DBmysql4};
@@ -1294,6 +1338,14 @@ function locate_executable($loc, $names, $versioninfo = false) {
        return false;
 }
 
+function get_db_version() {
+       global $wgDatabase, $conf;
+       if ($conf->DBtype == 'mysql')
+               return mysql_get_server_info( $wgDatabase->mConn );
+       else if ($conf->DBtype == 'oracle')
+               return oci_server_version($wgDatabase->mConn);
+}
+
 # Test a memcached server
 function testMemcachedServer( $server ) {
        $hostport = explode(":", $server);
index e0bd201..7242d74 100644 (file)
@@ -486,6 +486,8 @@ class Article {
         * Get the database which should be used for reads
         */
        function &getDB() {
+               $ret = wfGetDB( DB_MASTER );
+               return $ret;
                #if ( $this->mForUpdate ) {
                        $ret =& wfGetDB( DB_MASTER );
                #} else {
@@ -608,7 +610,7 @@ class Article {
 
        function getTimestamp() {
                $this->loadLastEdit();
-               return $this->mTimestamp;
+               return wfTimestamp(TS_MW, $this->mTimestamp);
        }
 
        function getUser() {
@@ -864,7 +866,7 @@ class Article {
 
                $tbtext = "";
                while ($o = $dbr->fetchObject($tbs)) {
-                       $rmvtext = "";
+                       $rmvtxt = "";
                        if ($wgUser->isSysop()) {
                                $delurl = $this->mTitle->getFullURL("action=deletetrackback&tbid="
                                                . $o->tb_id . "&token=" . $wgUser->editToken());
@@ -970,13 +972,14 @@ class Article {
                        # An extra check against threads stepping on each other
                        $conditions['page_latest'] = $lastRevision;
                }
+
                $text = $revision->getText();
                $dbw->update( 'page',
                        array( /* SET */
                                'page_latest'      => $revision->getId(),
                                'page_touched'     => $dbw->timestamp(),
                                'page_is_new'      => ($lastRevision === 0) ? 1 : 0,
-                               'page_is_redirect' => Article::isRedirect( $text ),
+                               'page_is_redirect' => Article::isRedirect( $text ) ? 1 : 0,
                                'page_len'         => strlen( $text ),
                        ),
                        $conditions,
@@ -1005,7 +1008,7 @@ class Article {
                                'page_latest=rev_id' ),
                        $fname );
                if( $row ) {
-                       if( $row->rev_timestamp >= $revision->getTimestamp() ) {
+                       if( wfTimestamp(TS_MW, $row->rev_timestamp) >= $revision->getTimestamp() ) {
                                wfProfileOut( $fname );
                                return false;
                        }
index 662e32c..7e48fb0 100644 (file)
@@ -2,17 +2,17 @@
 #
 # Copyright (C) 2003-2004 Brion Vibber <brion@pobox.com>
 # http://www.mediawiki.org/
-# 
+#
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or 
+# the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
+#
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License along
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
@@ -21,7 +21,7 @@
  *
  * @package MediaWiki
  */
+
 /**
  * Simple generic object store
  *
  */
 class BagOStuff {
        var $debugmode;
-       
+
        function BagOStuff() {
                $this->set_debug( false );
        }
-       
+
        function set_debug($bool) {
                $this->debugmode = $bool;
        }
-       
+
        /* *** THE GUTS OF THE OPERATION *** */
        /* Override these with functional things in subclasses */
-       
+
        function get($key) {
                /* stub */
                return false;
@@ -58,12 +58,12 @@ class BagOStuff {
                /* stub */
                return false;
        }
-       
+
        function delete($key, $time=0) {
                /* stub */
                return false;
        }
-       
+
        function lock($key, $timeout = 0) {
                /* stub */
                return true;
@@ -73,7 +73,7 @@ class BagOStuff {
                /* stub */
                return true;
        }
-       
+
        /* *** Emulated functions *** */
        /* Better performance can likely be got with custom written versions */
        function get_multi($keys) {
@@ -82,19 +82,19 @@ class BagOStuff {
                        $out[$key] = $this->get($key);
                return $out;
        }
-       
+
        function set_multi($hash, $exptime=0) {
                foreach($hash as $key => $value)
                        $this->set($key, $value, $exptime);
        }
-       
+
        function add($key, $value, $exptime=0) {
                if( $this->get($key) == false ) {
                        $this->set($key, $value, $exptime);
                        return true;
                }
        }
-       
+
        function add_multi($hash, $exptime=0) {
                foreach($hash as $key => $value)
                        $this->add($key, $value, $exptime);
@@ -104,12 +104,12 @@ class BagOStuff {
                foreach($keys as $key)
                        $this->delete($key, $time);
        }
-       
+
        function replace($key, $value, $exptime=0) {
                if( $this->get($key) !== false )
                        $this->set($key, $value, $exptime);
        }
-       
+
        function incr($key, $value=1) {
                if ( !$this->lock($key) ) {
                        return false;
@@ -125,7 +125,7 @@ class BagOStuff {
                $this->unlock($key);
                return $n;
        }
-       
+
        function decr($key, $value=1) {
                if ( !$this->lock($key) ) {
                        return false;
@@ -142,7 +142,7 @@ class BagOStuff {
                $this->unlock($key);
                return $m;
        }
-       
+
        function _debug($text) {
                if($this->debugmode)
                        wfDebug("BagOStuff debug: $text\n");
@@ -162,11 +162,11 @@ class HashBagOStuff extends BagOStuff {
           persist between program runs.
        */
        var $bag;
-       
+
        function HashBagOStuff() {
                $this->bag = array();
        }
-       
+
        function _expire($key) {
                $et = $this->bag[$key][1];
                if(($et == 0) || ($et > time()))
@@ -174,7 +174,7 @@ class HashBagOStuff extends BagOStuff {
                $this->delete($key);
                return true;
        }
-       
+
        function get($key) {
                if(!$this->bag[$key])
                        return false;
@@ -182,13 +182,13 @@ class HashBagOStuff extends BagOStuff {
                        return false;
                return $this->bag[$key][0];
        }
-       
+
        function set($key,$value,$exptime=0) {
                if(($exptime != 0) && ($exptime < 3600*24*30))
                        $exptime = time() + $exptime;
                $this->bag[$key] = array( $value, $exptime );
        }
-       
+
        function delete($key,$time=0) {
                if(!$this->bag[$key])
                        return false;
@@ -219,11 +219,11 @@ class SqlBagOStuff extends BagOStuff {
        function SqlBagOStuff($tablename = 'objectcache') {
                $this->table = $tablename;
        }
-       
+
        function get($key) {
                /* expire old entries if any */
                $this->garbageCollect();
-               
+
                $res = $this->_query(
                        "SELECT value,exptime FROM $0 WHERE keyname='$1'", $key);
                if(!$res) {
@@ -238,7 +238,7 @@ class SqlBagOStuff extends BagOStuff {
                }
                return false;
        }
-       
+
        function set($key,$value,$exptime=0) {
                $exptime = intval($exptime);
                if($exptime < 0) $exptime = 0;
@@ -250,22 +250,24 @@ class SqlBagOStuff extends BagOStuff {
                        $exp = $this->_fromunixtime($exptime);
                }
                $this->delete( $key );
-               $this->_query(
-                       "INSERT INTO $0 (keyname,value,exptime) VALUES('$1','$2','$exp')",
-                       $key, $this->_serialize($value));
+               $this->_doinsert($this->getTableName(), array(
+                                       'keyname' => $key,
+                                       'value' => $this->_blobencode($this->_serialize($value)),
+                                       'exptime' => $exp
+                               ));
                return true; /* ? */
        }
-       
+
        function delete($key,$time=0) {
                $this->_query(
                        "DELETE FROM $0 WHERE keyname='$1'", $key );
                return true; /* ? */
        }
-       
+
        function getTableName() {
                return $this->table;
        }
-       
+
        function _query($sql) {
                $reps = func_get_args();
                $reps[0] = $this->getTableName();
@@ -273,7 +275,7 @@ class SqlBagOStuff extends BagOStuff {
                for($i=0;$i<count($reps);$i++) {
                        $sql = str_replace(
                                '$' . $i,
-                               $this->_strencode($reps[$i]),
+                               $i > 0 ? $this->_strencode($reps[$i]) : $reps[$i],
                                $sql);
                }
                $res = $this->_doquery($sql);
@@ -282,38 +284,43 @@ class SqlBagOStuff extends BagOStuff {
                }
                return $res;
        }
-       
+
        function _strencode($str) {
                /* Protect strings in SQL */
                return str_replace( "'", "''", $str );
        }
-       
+       function _blobencode($str) {
+               return $str;
+       }
+       function _doinsert($table, $vals) {
+               die( 'abstract function SqlBagOStuff::_doinsert() must be defined' );
+       }
        function _doquery($sql) {
                die( 'abstract function SqlBagOStuff::_doquery() must be defined' );
        }
-       
+
        function _fetchrow($res) {
                die( 'abstract function SqlBagOStuff::_fetchrow() must be defined' );
        }
-       
+
        function _freeresult($result) {
                /* stub */
                return false;
        }
-       
+
        function _dberror($result) {
                /* stub */
                return 'unknown error';
        }
-       
+
        function _maxdatetime() {
                die( 'abstract function SqlBagOStuff::_maxdatetime() must be defined' );
        }
-       
+
        function _fromunixtime() {
                die( 'abstract function SqlBagOStuff::_fromunixtime() must be defined' );
        }
-       
+
        function garbageCollect() {
                /* Ignore 99% of requests */
                if ( !mt_rand( 0, 100 ) ) {
@@ -325,18 +332,18 @@ class SqlBagOStuff extends BagOStuff {
                        }
                }
        }
-       
+
        function expireall() {
                /* Remove any items that have expired */
                $now = $this->_fromunixtime( time() );
-               $this->_query( "DELETE FROM $0 WHERE exptime<'$now'" );
+               $this->_query( "DELETE FROM $0 WHERE exptime < '$now'" );
        }
-       
+
        function deleteall() {
                /* Clear *all* items from cache table */
                $this->_query( "DELETE FROM $0" );
        }
-       
+
        /**
         * Serialize an object and, if possible, compress the representation.
         * On typical message and page data, this can provide a 3X decrease
@@ -353,7 +360,7 @@ class SqlBagOStuff extends BagOStuff {
                        return $serial;
                }
        }
-       
+
        /**
         * Unserialize and, if necessary, decompress an object.
         * @param string $serial
@@ -366,7 +373,9 @@ class SqlBagOStuff extends BagOStuff {
                                $serial = $decomp;
                        }
                }
-               return unserialize( $serial );
+               wfdebug("serial: [$serial]\n");
+               $ret = unserialize( $serial );
+               return $ret;
        }
 }
 
@@ -379,7 +388,11 @@ class MediaWikiBagOStuff extends SqlBagOStuff {
 
        function _doquery($sql) {
                $dbw =& wfGetDB( DB_MASTER );
-               return $dbw->query($sql, 'MediaWikiBagOStuff:_doquery');
+               return $dbw->query($sql, 'MediaWikiBagOStuff::_doquery');
+       }
+       function _doinsert($t, $v) {
+               $dbw =& wfGetDB( DB_MASTER );
+               return $dbw->insert($t, $v, 'MediaWikiBagOStuff::_doinsert');
        }
        function _fetchobject($result) {
                $dbw =& wfGetDB( DB_MASTER );
@@ -394,15 +407,21 @@ class MediaWikiBagOStuff extends SqlBagOStuff {
                return $dbw->lastError();
        }
        function _maxdatetime() {
-               return '9999-12-31 12:59:59';
+               $dbw =& wfGetDB(DB_MASTER);
+               return $dbw->timestamp('9999-12-31 12:59:59');
        }
        function _fromunixtime($ts) {
-               return gmdate( 'Y-m-d H:i:s', $ts );
+               $dbw =& wfGetDB(DB_MASTER);
+               return $dbw->timestamp($ts);
        }
        function _strencode($s) {
                $dbw =& wfGetDB( DB_MASTER );
                return $dbw->strencode($s);
        }
+       function _blobencode($s) {
+               $dbw =& wfGetDB( DB_MASTER );
+               return $dbw->encodeBlob($s);
+       }
        function getTableName() {
                if ( !$this->tableInitialised ) {
                        $dbw =& wfGetDB( DB_MASTER );
@@ -418,16 +437,16 @@ class MediaWikiBagOStuff extends SqlBagOStuff {
 }
 
 /**
- * This is a wrapper for Turck MMCache's shared memory functions. 
- * 
- * You can store objects with mmcache_put() and mmcache_get(), but Turck seems 
- * to use a weird custom serializer that randomly segfaults. So we wrap calls 
+ * This is a wrapper for Turck MMCache's shared memory functions.
+ *
+ * You can store objects with mmcache_put() and mmcache_get(), but Turck seems
+ * to use a weird custom serializer that randomly segfaults. So we wrap calls
  * with serialize()/unserialize().
- * 
+ *
  * The thing I noticed about the Turck serialized data was that unlike ordinary
- * serialize(), it contained the names of methods, and judging by the amount of 
- * binary data, perhaps even the bytecode of the methods themselves. It may be 
- * that Turck's serializer is faster, so a possible future extension would be 
+ * serialize(), it contained the names of methods, and judging by the amount of
+ * binary data, perhaps even the bytecode of the methods themselves. It may be
+ * that Turck's serializer is faster, so a possible future extension would be
  * to use it for arrays but not for objects.
  *
  * @package MediaWiki
@@ -445,7 +464,7 @@ class TurckBagOStuff extends BagOStuff {
                mmcache_put( $key, serialize( $value ), $exptime );
                return true;
        }
-       
+
        function delete($key, $time=0) {
                mmcache_rm( $key );
                return true;
@@ -460,11 +479,11 @@ class TurckBagOStuff extends BagOStuff {
                mmcache_unlock( $key );
                return true;
        }
-}      
+}
 
 /**
- * This is a wrapper for eAccelerator's shared memory functions. 
- * 
+ * This is a wrapper for eAccelerator's shared memory functions.
+ *
  * This is basically identical to the Turck MMCache version,
  * mostly because eAccelerator is based on Turck MMCache.
  *
@@ -483,7 +502,7 @@ class eAccelBagOStuff extends BagOStuff {
                eaccelerator_put( $key, serialize( $value ), $exptime );
                return true;
        }
-       
+
        function delete($key, $time=0) {
                eaccelerator_rm( $key );
                return true;
@@ -498,5 +517,5 @@ class eAccelBagOStuff extends BagOStuff {
                eaccelerator_unlock( $key );
                return true;
        }
-}      
+}
 ?>
index 0763133..c4110d0 100644 (file)
@@ -12,9 +12,9 @@ define ( 'EB_FOR_UPDATE', 2 );
 
 /**
  * The block class
- * All the functions in this class assume the object is either explicitly 
+ * All the functions in this class assume the object is either explicitly
  * loaded or filled. It is not load-on-demand. There are no accessors.
- * 
+ *
  * To use delete(), you only need to fill $mAddress
  * Globals used: $wgBlockCache, $wgAutoblockExpiry
  *
@@ -25,9 +25,9 @@ class Block
 {
        /* public*/ var $mAddress, $mUser, $mBy, $mReason, $mTimestamp, $mAuto, $mId, $mExpiry;
        /* private */ var $mNetworkBits, $mIntegerAddr, $mForUpdate;
-       
-       function Block( $address = '', $user = '', $by = 0, $reason = '', 
-               $timestamp = '' , $auto = 0, $expiry = '' ) 
+
+       function Block( $address = '', $user = '', $by = 0, $reason = '',
+               $timestamp = '' , $auto = 0, $expiry = '' )
        {
                $this->mAddress = $address;
                $this->mUser = $user;
@@ -40,19 +40,19 @@ class Block
                } else {
                        $this->mExpiry = wfTimestamp( TS_MW, $expiry );
                }
-               
+
                $this->mForUpdate = false;
                $this->initialiseRange();
        }
-       
-       /*static*/ function newFromDB( $address, $user = 0, $killExpired = true ) 
+
+       /*static*/ function newFromDB( $address, $user = 0, $killExpired = true )
        {
                $ban = new Block();
                $ban->load( $address, $user, $killExpired );
                return $ban;
        }
-       
-       function clear() 
+
+       function clear()
        {
                $mAddress = $mReason = $mTimestamp = '';
                $mUser = $mBy = 0;
@@ -61,7 +61,7 @@ class Block
        /**
         * Get a ban from the DB, with either the given address or the given username
         */
-       function load( $address = '', $user = 0, $killExpired = true ) 
+       function load( $address = '', $user = 0, $killExpired = true )
        {
                global $wgDBmysql4, $wgAntiLockFlags;
                $fname = 'Block::load';
@@ -96,7 +96,7 @@ class Block
                } else {
                        # If there are options, a UNION can not be used, use one
                        # SELECT instead. Will do a full table scan.
-                       $sql = "SELECT * FROM $ipblocks WHERE (ipb_address='" . $db->strencode( $address ) . 
+                       $sql = "SELECT * FROM $ipblocks WHERE (ipb_address='" . $db->strencode( $address ) .
                                "' OR ipb_user={$user}) $options";
                }
 
@@ -120,7 +120,7 @@ class Block
                                                }
                                        }
                                } while ( $killed && $row );
-                               
+
                                # If there were any left after the killing finished, return true
                                if ( !$row ) {
                                        $ret = false;
@@ -135,8 +135,8 @@ class Block
                $db->freeResult( $res );
                return $ret;
        }
-       
-       function initFromRow( $row ) 
+
+       function initFromRow( $row )
        {
                $this->mAddress = $row->ipb_address;
                $this->mReason = $row->ipb_reason;
@@ -150,7 +150,7 @@ class Block
                        $row->ipb_expiry;
 
                $this->initialiseRange();
-       }       
+       }
 
        function initialiseRange()
        {
@@ -167,11 +167,11 @@ class Block
                        $this->mIntegerAddr = false;
                }
        }
-       
+
        /**
         * Callback with a Block object for every block
         */
-       /*static*/ function enumBlocks( $callback, $tag, $flags = 0 ) 
+       /*static*/ function enumBlocks( $callback, $tag, $flags = 0 )
        {
                global $wgAntiLockFlags;
 
@@ -187,9 +187,9 @@ class Block
                } else {
                        $db =& wfGetDB( DB_SLAVE );
                        $options = '';
-               }       
+               }
                $ipblocks = $db->tableName( 'ipblocks' );
-               
+
                $sql = "SELECT * FROM $ipblocks ORDER BY ipb_timestamp DESC $options";
                $res = $db->query( $sql, 'Block::enumBans' );
 
@@ -206,7 +206,7 @@ class Block
                wfFreeResult( $res );
        }
 
-       function delete() 
+       function delete()
        {
                $fname = 'Block::delete';
                if (wfReadOnly()) {
@@ -223,12 +223,14 @@ class Block
                $this->clearCache();
        }
 
-       function insert() 
+       function insert()
        {
                wfDebug( "Block::insert; timestamp {$this->mTimestamp}\n" );
                $dbw =& wfGetDB( DB_MASTER );
+               $ipb_id = $dbw->nextSequenceValue('ipblocks_ipb_id_val');
                $dbw->insert( 'ipblocks',
                        array(
+                               'ipb_id' => $ipb_id,
                                'ipb_address' => $this->mAddress,
                                'ipb_user' => $this->mUser,
                                'ipb_by' => $this->mBy,
@@ -238,13 +240,13 @@ class Block
                                'ipb_expiry' => $this->mExpiry ?
                                        $dbw->timestamp($this->mExpiry) :
                                        $this->mExpiry,
-                       ), 'Block::insert' 
+                       ), 'Block::insert'
                );
 
                $this->clearCache();
        }
 
-       function deleteIfExpired() 
+       function deleteIfExpired()
        {
                if ( $this->isExpired() ) {
                        wfDebug( "Block::deleteIfExpired() -- deleting\n" );
@@ -256,8 +258,8 @@ class Block
                }
        }
 
-       function isExpired() 
-       {       
+       function isExpired()
+       {
                wfDebug( "Block::isExpired() checking current " . wfTimestampNow() . " vs $this->mExpiry\n" );
                if ( !$this->mExpiry ) {
                        return false;
@@ -266,27 +268,27 @@ class Block
                }
        }
 
-       function isValid() 
+       function isValid()
        {
                return $this->mAddress != '';
        }
-       
-       function updateTimestamp() 
+
+       function updateTimestamp()
        {
                if ( $this->mAuto ) {
                        $this->mTimestamp = wfTimestamp();
                        $this->mExpiry = Block::getAutoblockExpiry( $this->mTimestamp );
 
                        $dbw =& wfGetDB( DB_MASTER );
-                       $dbw->update( 'ipblocks', 
-                               array( /* SET */ 
+                       $dbw->update( 'ipblocks',
+                               array( /* SET */
                                        'ipb_timestamp' => $dbw->timestamp($this->mTimestamp),
                                        'ipb_expiry' => $dbw->timestamp($this->mExpiry),
                                ), array( /* WHERE */
                                        'ipb_address' => $this->mAddress
-                               ), 'Block::updateTimestamp' 
+                               ), 'Block::updateTimestamp'
                        );
-                       
+
                        $this->clearCache();
                }
        }
@@ -298,12 +300,12 @@ class Block
                        $wgBlockCache->loadFromDB();
                }
        }
-       
+
        function getIntegerAddr()
        {
                return $this->mIntegerAddr;
        }
-       
+
        function getNetworkBits()
        {
                return $this->mNetworkBits;
index bb6314f..e5c11e8 100644 (file)
@@ -5,7 +5,7 @@
  *
  * @package MediaWiki
  */
+
 if( !defined( 'MEDIAWIKI' ) )
        die();
 
@@ -15,7 +15,7 @@ if( $wgCategoryMagicGallery )
        require_once('ImageGallery.php');
 
 /**
- * @package MediaWiki 
+ * @package MediaWiki
  */
 class CategoryPage extends Article {
 
@@ -27,7 +27,7 @@ class CategoryPage extends Article {
                }
 
                Article::view();
-               
+
                # If the article we've just shown is in the "Image" namespace,
                # follow it with the history list and link list for the image
                # it describes.
@@ -40,7 +40,7 @@ class CategoryPage extends Article {
        function openShowCategory() {
                # For overloading
        }
-       
+
        # generate a list of subcategories and pages for a category
        # depending on wfMsg("usenewcategorypage") it either calls the new
        # or the old code. The new code will not work properly for some
@@ -85,7 +85,7 @@ class CategoryPage extends Article {
                        $pageCondition = 'cl_sortkey < ' . $dbr->addQuotes( $until );
                        $flip = true;
                } else {
-                       $pageCondition = '1';
+                       $pageCondition = '1 = 1';
                        $flip = false;
                }
                $limit = 200;
@@ -100,7 +100,7 @@ class CategoryPage extends Article {
                        $fname,
                        array( 'ORDER BY' => $flip ? 'cl_sortkey DESC' : 'cl_sortkey',
                               'LIMIT'    => $limit + 1 ) );
-               
+
                $sk =& $wgUser->getSkin();
                $r = "<br style=\"clear:both;\"/>\n";
                $count = 0;
@@ -112,13 +112,13 @@ class CategoryPage extends Article {
                                $nextPage = $x->cl_sortkey;
                                break;
                        }
-                       
+
                        $title = Title::makeTitle( $x->page_namespace, $x->page_title );
-                       
+
                        if( $title->getNamespace() == NS_CATEGORY ) {
                                // Subcategory; strip the 'Category' namespace from the link text.
                                array_push( $children, $sk->makeKnownLinkObj( $title, $wgContLang->convertHtml( $title->getText() ) ) );
-                               
+
                                // If there's a link from Category:A to Category:B, the sortkey of the resulting
                                // entry in the categorylinks table is Category:A, not A, which it SHOULD be.
                                // Workaround: If sortkey == "Category:".$title, than use $title for sorting,
@@ -151,13 +151,13 @@ class CategoryPage extends Article {
                        $articles            = array_reverse( $articles );
                        $articles_start_char = array_reverse( $articles_start_char );
                }
-               
+
                if( $until != '' ) {
                        $r .= $this->pagingLinks( $this->mTitle, $nextPage, $until, $limit );
                } elseif( $nextPage != '' || $from != '' ) {
                        $r .= $this->pagingLinks( $this->mTitle, $from, $nextPage, $limit );
                }
-               
+
                # Don't show subcategories section if there are none.
                if( count( $children ) > 0 ) {
                        # Showing subcategories
@@ -214,7 +214,7 @@ class CategoryPage extends Article {
                }
                return '';
        }
-       
+
        /**
         * Format a list of articles chunked by letter in a three-column
         * list, ordered vertically.
@@ -231,7 +231,7 @@ class CategoryPage extends Article {
                // get and display header
                $r = '<table width="100%"><tr valign="top">';
 
-               $prev_start_char = 'none'; 
+               $prev_start_char = 'none';
 
                // loop through the chunks
                for($startChunk = 0, $endChunk = $chunk, $chunkIndex = 0;
@@ -275,7 +275,7 @@ class CategoryPage extends Article {
                $r .= '</tr></table>';
                return $r;
        }
-       
+
        /**
         * Format a list of articles chunked by letter in a bullet list.
         * @param array $articles
@@ -298,7 +298,7 @@ class CategoryPage extends Article {
                $r .= '</ul>';
                return $r;
        }
-       
+
        /**
         * @param Title  $title
         * @param string $first
@@ -312,7 +312,7 @@ class CategoryPage extends Article {
                global $wgUser, $wgLang;
                $sk =& $wgUser->getSkin();
                $limitText = $wgLang->formatNum( $limit );
-               
+
                $prevLink = htmlspecialchars( wfMsg( 'prevn', $limitText ) );
                if( $first != '' ) {
                        $prevLink = $sk->makeLinkObj( $title, $prevLink,
@@ -323,7 +323,7 @@ class CategoryPage extends Article {
                        $nextLink = $sk->makeLinkObj( $title, $nextLink,
                                wfArrayToCGI( $query + array( 'from' => $last ) ) );
                }
-               
+
                return "($prevLink) ($nextLink)";
        }
 }
index b66e717..6e8a992 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * This file deals with MySQL interface functions 
+ * This file deals with MySQL interface functions
  * and query specifics/optimisations
  * @package MediaWiki
  */
@@ -23,6 +23,22 @@ define( 'DEADLOCK_DELAY_MIN', 500000 );
 /** Maximum time to wait before retry */
 define( 'DEADLOCK_DELAY_MAX', 1500000 );
 
+class DBObject {
+       var $mData;
+
+       function DBObject($data) {
+               $this->mData = $data;
+       }
+
+       function isLOB() {
+               return false;
+       }
+
+       function data() {
+               return $this->mData;
+       }
+};
+
 /**
  * Database abstraction object
  * @package MediaWiki
@@ -36,11 +52,11 @@ class Database {
         * @access private
         */
        var $mLastQuery = '';
-       
+
        var $mServer, $mUser, $mPassword, $mConn, $mDBname;
        var $mOut, $mOpened = false;
-       
-       var $mFailFunction; 
+
+       var $mFailFunction;
        var $mTablePrefix;
        var $mFlags;
        var $mTrxLevel = 0;
@@ -51,30 +67,30 @@ class Database {
 # Accessors
 #------------------------------------------------------------------------------
        # These optionally set a variable and return the previous state
-       
+
        /**
         * Fail function, takes a Database as a parameter
         * Set to false for default, 1 for ignore errors
         */
-       function failFunction( $function = NULL ) { 
-               return wfSetVar( $this->mFailFunction, $function ); 
+       function failFunction( $function = NULL ) {
+               return wfSetVar( $this->mFailFunction, $function );
        }
-       
+
        /**
         * Output page, used for reporting errors
         * FALSE means discard output
         */
-       function &setOutputPage( &$out ) { 
-               $this->mOut =& $out; 
+       function &setOutputPage( &$out ) {
+               $this->mOut =& $out;
        }
-       
+
        /**
         * Boolean, controls output of large amounts of debug information
         */
-       function debug( $debug = NULL ) { 
-               return wfSetBit( $this->mFlags, DBO_DEBUG, $debug ); 
+       function debug( $debug = NULL ) {
+               return wfSetBit( $this->mFlags, DBO_DEBUG, $debug );
        }
-       
+
        /**
         * Turns buffering of SQL result sets on (true) or off (false).
         * Default is "on" and it should not be changed without good reasons.
@@ -83,7 +99,7 @@ class Database {
                if ( is_null( $buffer ) ) {
                        return !(bool)( $this->mFlags & DBO_NOBUFFER );
                } else {
-                       return !wfSetBit( $this->mFlags, DBO_NOBUFFER, !$buffer ); 
+                       return !wfSetBit( $this->mFlags, DBO_NOBUFFER, !$buffer );
                }
        }
 
@@ -94,10 +110,10 @@ class Database {
         * code should use wfLastErrno() and wfLastError() to handle the
         * situation as appropriate.
         */
-       function ignoreErrors( $ignoreErrors = NULL ) { 
-               return wfSetBit( $this->mFlags, DBO_IGNORE, $ignoreErrors ); 
+       function ignoreErrors( $ignoreErrors = NULL ) {
+               return wfSetBit( $this->mFlags, DBO_IGNORE, $ignoreErrors );
        }
-       
+
        /**
         * The current depth of nested transactions
         * @param integer $level
@@ -106,7 +122,7 @@ class Database {
                return wfSetVar( $this->mTrxLevel, $level );
        }
 
-       /** 
+       /**
         * Number of errors logged, only useful when errors are ignored
         */
        function errorCount( $count = NULL ) {
@@ -130,15 +146,15 @@ class Database {
         * @param string $password database user password
         * @param string $dbname database name
         */
-        
+
        /**
         * @param failFunction
         * @param $flags
         * @param string $tablePrefix Database table prefixes. By default use the prefix gave in LocalSettings.php
         */
-       function Database( $server = false, $user = false, $password = false, $dbName = false, 
+       function Database( $server = false, $user = false, $password = false, $dbName = false,
                $failFunction = false, $flags = 0, $tablePrefix = 'get from global' ) {
-               
+
                global $wgOut, $wgDBprefix, $wgCommandLineMode;
                # Can't get a reference if it hasn't been set yet
                if ( !isset( $wgOut ) ) {
@@ -148,7 +164,7 @@ class Database {
 
                $this->mFailFunction = $failFunction;
                $this->mFlags = $flags;
-               
+
                if ( $this->mFlags & DBO_DEFAULT ) {
                        if ( $wgCommandLineMode ) {
                                $this->mFlags &= ~DBO_TRX;
@@ -163,7 +179,7 @@ class Database {
                        $this->mFlags |= DBO_PERSISTENT;
                        $this->mFlags &= ~DBO_TRX;
                }*/
-               
+
                /** Get the default table prefix*/
                if ( $tablePrefix == 'get from global' ) {
                        $this->mTablePrefix = $wgDBprefix;
@@ -175,18 +191,18 @@ class Database {
                        $this->open( $server, $user, $password, $dbName );
                }
        }
-       
+
        /**
         * @static
         * @param failFunction
         * @param $flags
         */
-       function newFromParams( $server, $user, $password, $dbName, 
+       function newFromParams( $server, $user, $password, $dbName,
                $failFunction = false, $flags = 0 )
        {
                return new Database( $server, $user, $password, $dbName, $failFunction, $flags );
        }
-       
+
        /**
         * Usually aborts on failure
         * If the failFunction is set to a non-zero integer, returns success
@@ -202,15 +218,15 @@ class Database {
                if ( !function_exists( 'mysql_connect' ) ) {
                        die( "MySQL functions missing, have you compiled PHP with the --with-mysql option?\n" );
                }
-               
+
                $this->close();
                $this->mServer = $server;
                $this->mUser = $user;
                $this->mPassword = $password;
                $this->mDBname = $dbName;
-               
+
                $success = false;
-               
+
                if ( $this->mFlags & DBO_PERSISTENT ) {
                        @/**/$this->mConn = mysql_pconnect( $server, $user, $password );
                } else {
@@ -226,7 +242,7 @@ class Database {
                                }
                        } else {
                                wfDebug( "DB connection error\n" );
-                               wfDebug( "Server: $server, User: $user, Password: " . 
+                               wfDebug( "Server: $server, User: $user, Password: " .
                                        substr( $password, 0, 3 ) . "..., error: " . mysql_error() . "\n" );
                                $success = false;
                        }
@@ -234,7 +250,7 @@ class Database {
                        # Delay USE query
                        $success = (bool)$this->mConn;
                }
-               
+
                if ( !$success ) {
                        $this->reportConnectionError();
                        $this->close();
@@ -243,7 +259,7 @@ class Database {
                return $success;
        }
        /**#@-*/
-       
+
        /**
         * Closes a database connection.
         * if it is open : commits any open transactions
@@ -262,7 +278,7 @@ class Database {
                        return true;
                }
        }
-       
+
        /**
         * @access private
         * @param string $msg error message ?
@@ -272,24 +288,24 @@ class Database {
                if ( $this->mFailFunction ) {
                        if ( !is_int( $this->mFailFunction ) ) {
                                $ff = $this->mFailFunction;
-                               $ff( $this, mysql_error() );
+                               $ff( $this, $this->lastError() );
                        }
                } else {
                        wfEmergencyAbort( $this, mysql_error() );
                }
        }
-       
+
        /**
         * Usually aborts on failure
         * If errors are explicitly ignored, returns success
         */
        function query( $sql, $fname = '', $tempIgnore = false ) {
                global $wgProfiling, $wgCommandLineMode;
-               
+
                if ( wfReadOnly() ) {
-                       # This is a quick check for the most common kinds of write query used 
-                       # in MediaWiki, to provide extra safety in addition to UI-level checks. 
-                       # It is not intended to prevent every conceivable write query, or even 
+                       # This is a quick check for the most common kinds of write query used
+                       # in MediaWiki, to provide extra safety in addition to UI-level checks.
+                       # It is not intended to prevent every conceivable write query, or even
                        # to handle such queries gracefully.
                        if ( preg_match( '/^(update|insert|replace|delete)/i', $sql ) ) {
                                wfDebug( "Write query from $fname blocked\n" );
@@ -304,9 +320,9 @@ class Database {
                        wfProfileIn( 'Database::query' );
                        wfProfileIn( $profName );
                }
-               
+
                $this->mLastQuery = $sql;
-               
+
                # Add a comment for easy SHOW PROCESSLIST interpretation
                if ( $fname ) {
                        $commentedSql = "/* $fname */ $sql";
@@ -324,7 +340,7 @@ class Database {
                        $sqlx = strtr( $sqlx, "\t\n", '  ' );
                        wfDebug( "SQL: $sqlx\n" );
                }
-               
+
                # Do the query and handle errors
                $ret = $this->doQuery( $commentedSql );
 
@@ -344,14 +360,14 @@ class Database {
                if ( false === $ret ) {
                        $this->reportQueryError( $this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore );
                }
-                               
+
                if ( $wgProfiling ) {
                        wfProfileOut( $profName );
                        wfProfileOut( 'Database::query' );
                }
                return $ret;
        }
-       
+
        /**
         * The DBMS-dependent part of query()
         * @param string $sql SQL query.
@@ -361,7 +377,7 @@ class Database {
                        $ret = mysql_query( $sql, $this->mConn );
                } else {
                        $ret = mysql_unbuffered_query( $sql, $this->mConn );
-               }       
+               }
                return $ret;
        }
 
@@ -389,13 +405,13 @@ class Database {
                                  "Query: $sql\n" .
                                  "Function: $fname\n" .
                                  "Error: $errno $error\n";
-                               if ( !$wgCommandLineMode ) {    
+                               if ( !$wgCommandLineMode ) {
                                        $message = nl2br( $message );
                                }
                                wfDebugDieBacktrace( $message );
                        } else {
                                // this calls wfAbruptExit()
-                               $this->mOut->databaseError( $fname, $sql, $error, $errno );                             
+                               $this->mOut->databaseError( $fname, $sql, $error, $errno );
                        }
                }
                $this->ignoreErrors( $ignore );
@@ -417,11 +433,11 @@ class Database {
                   the bits later. */
                return array( 'query' => $sql, 'func' => $func );
        }
-       
+
        function freePrepared( $prepared ) {
                /* No-op for MySQL */
        }
-       
+
        /**
         * Execute a prepared query with the various arguments
         * @param string $prepared the prepared sql
@@ -436,7 +452,7 @@ class Database {
                $sql = $this->fillPrepared( $prepared['query'], $args );
                return $this->query( $sql, $prepared['func'] );
        }
-       
+
        /**
         * Prepare & execute an SQL statement, quoting and inserting arguments
         * in the appropriate places.
@@ -454,7 +470,7 @@ class Database {
                $this->freePrepared( $prepared );
                return $retval;
        }
-       
+
        /**
         * For faking prepared SQL statements on DBs that don't support
         * it directly.
@@ -469,12 +485,12 @@ class Database {
                return preg_replace_callback( '/(\\\\[?!&]|[?!&])/',
                        array( &$this, 'fillPreparedArg' ), $preparedQuery );
        }
-       
+
        /**
         * preg_callback func for fillPrepared()
         * The arguments should be in $this->preparedArgs and must not be touched
         * while we're doing this.
-        * 
+        *
         * @param array $matches
         * @return string
         * @access private
@@ -496,7 +512,7 @@ class Database {
                                wfDebugDieBacktrace( 'Received invalid match. This should never happen!' );
                }
        }
-       
+
        /**#@+
         * @param mixed $res A SQL result
         */
@@ -508,7 +524,7 @@ class Database {
                        wfDebugDieBacktrace( "Unable to free MySQL result\n" );
                }
        }
-       
+
        /**
         * Fetch the next row from the given result object, in object form
         */
@@ -530,19 +546,19 @@ class Database {
                        wfDebugDieBacktrace( 'Error in fetchRow(): ' . htmlspecialchars( mysql_error() ) );
                }
                return $row;
-       }       
+       }
 
        /**
         * Get the number of rows in a result object
         */
        function numRows( $res ) {
-               @/**/$n = mysql_num_rows( $res ); 
+               @/**/$n = mysql_num_rows( $res );
                if( mysql_errno() ) {
                        wfDebugDieBacktrace( 'Error in numRows(): ' . htmlspecialchars( mysql_error() ) );
                }
                return $n;
        }
-       
+
        /**
         * Get the number of fields in a result object
         * See documentation for mysql_num_fields()
@@ -566,32 +582,32 @@ class Database {
         * $id = $dbw->insertId();
         */
        function insertId() { return mysql_insert_id( $this->mConn ); }
-       
+
        /**
         * Change the position of the cursor in a result object
         * See mysql_data_seek()
         */
        function dataSeek( $res, $row ) { return mysql_data_seek( $res, $row ); }
-       
+
        /**
         * Get the last error number
         * See mysql_errno()
         */
-       function lastErrno() { 
+       function lastErrno() {
                if ( $this->mConn ) {
-                       return mysql_errno( $this->mConn ); 
+                       return mysql_errno( $this->mConn );
                } else {
                        return mysql_errno();
                }
        }
-       
+
        /**
         * Get a description of the last error
         * See mysql_error() for more details
         */
-       function lastError() { 
+       function lastError() {
                if ( $this->mConn ) {
-                       $error = mysql_error( $this->mConn ); 
+                       $error = mysql_error( $this->mConn );
                } else {
                        $error = mysql_error();
                }
@@ -599,7 +615,7 @@ class Database {
                        $error .= ' (' . $this->mServer . ')';
                }
                return $error;
-       }       
+       }
        /**
         * Get the number of rows affected by the last write query
         * See mysql_affected_rows() for more details
@@ -612,7 +628,7 @@ class Database {
         * Usually aborts on failure
         * If errors are explicitly ignored, returns success
         *
-        * This function exists for historical reasons, Database::update() has a more standard 
+        * This function exists for historical reasons, Database::update() has a more standard
         * calling convention and feature set
         */
        function set( $table, $var, $value, $cond, $fname = 'Database::set' )
@@ -622,7 +638,7 @@ class Database {
                  $this->strencode( $value ) . "' WHERE ($cond)";
                return (bool)$this->query( $sql, DB_MASTER, $fname );
        }
-       
+
        /**
         * Simple SELECT wrapper, returns a single field, input must be encoded
         * Usually aborts on failure
@@ -646,7 +662,7 @@ class Database {
                        return false;
                }
        }
-       
+
        /**
         * Returns an optional USE INDEX clause to go after the table, and a
         * string to go at the end of the query
@@ -665,15 +681,12 @@ class Database {
                }
                if ( isset( $options['ORDER BY'] ) ) {
                        $tailOpts .= " ORDER BY {$options['ORDER BY']}";
-               } 
-               if ( isset( $options['LIMIT'] ) ) {
-                       $tailOpts .= " LIMIT {$options['LIMIT']}";
                }
 
                if ( is_numeric( array_search( 'FOR UPDATE', $options ) ) ) {
                        $tailOpts .= ' FOR UPDATE';
                }
-               
+
                if ( is_numeric( array_search( 'LOCK IN SHARE MODE', $options ) ) ) {
                        $tailOpts .= ' LOCK IN SHARE MODE';
                }
@@ -694,6 +707,9 @@ class Database {
                if( is_array( $vars ) ) {
                        $vars = implode( ',', $vars );
                }
+               if( !is_array( $options ) ) {
+                       $options = array( $options );
+               }
                if( is_array( $table ) ) {
                        $from = ' FROM ' . implode( ',', array_map( array( &$this, 'tableName' ), $table ) );
                } elseif ($table!='') {
@@ -702,8 +718,8 @@ class Database {
                        $from = '';
                }
 
-               list( $useIndex, $tailOpts ) = $this->makeSelectOptions( (array)$options );
-               
+               list( $useIndex, $tailOpts ) = $this->makeSelectOptions( array($options) );
+
                if( !empty( $conds ) ) {
                        if ( is_array( $conds ) ) {
                                $conds = $this->makeList( $conds, LIST_AND );
@@ -712,15 +728,18 @@ class Database {
                } else {
                        $sql = "SELECT $vars $from $useIndex $tailOpts";
                }
+               if (isset($options['LIMIT'])) {
+                       $sql = $this->limitResult($sql, $options['LIMIT'], false);
+               }
                return $this->query( $sql, $fname );
        }
 
        /**
         * Single row SELECT wrapper
         * Aborts or returns FALSE on error
-        * 
+        *
         * $vars: the selected variables
-        * $conds: a condition map, terms are ANDed together. 
+        * $conds: a condition map, terms are ANDed together.
         *   Items with numeric keys are taken to be literal conditions
         * Takes an array of selected variables, and a condition map, which is ANDed
         * e.g: selectRow( "page", array( "page_id" ), array( "page_namespace" =>
@@ -732,15 +751,18 @@ class Database {
        function selectRow( $table, $vars, $conds, $fname = 'Database::selectRow', $options = array() ) {
                $options['LIMIT'] = 1;
                $res = $this->select( $table, $vars, $conds, $fname, $options );
-               if ( $res === false || !$this->numRows( $res ) ) {
+               if ( $res === false )
+                       return false;
+               if ( !$this->numRows($res) ) {
+                       $this->freeResult($res);
                        return false;
                }
                $obj = $this->fetchObject( $res );
                $this->freeResult( $res );
                return $obj;
-               
+
        }
-       
+
        /**
         * Removes most variables from an SQL query and replaces them with X or N for numbers.
         * It's only slightly flawed. Don't use for anything important.
@@ -748,26 +770,26 @@ class Database {
         * @param string $sql A SQL Query
         * @static
         */
-       function generalizeSQL( $sql ) {        
+       function generalizeSQL( $sql ) {
                # This does the same as the regexp below would do, but in such a way
                # as to avoid crashing php on some large strings.
                # $sql = preg_replace ( "/'([^\\\\']|\\\\.)*'|\"([^\\\\\"]|\\\\.)*\"/", "'X'", $sql);
-       
+
                $sql = str_replace ( "\\\\", '', $sql);
                $sql = str_replace ( "\\'", '', $sql);
                $sql = str_replace ( "\\\"", '', $sql);
                $sql = preg_replace ("/'.*'/s", "'X'", $sql);
                $sql = preg_replace ('/".*"/s', "'X'", $sql);
-       
+
                # All newlines, tabs, etc replaced by single space
                $sql = preg_replace ( "/\s+/", ' ', $sql);
-       
-               # All numbers => N      
+
+               # All numbers => N
                $sql = preg_replace ('/-?[0-9]+/s', 'N', $sql);
-       
+
                return $sql;
        }
-       
+
        /**
         * Determines whether a field exists in a table
         * Usually aborts on failure
@@ -779,9 +801,9 @@ class Database {
                if ( !$res ) {
                        return NULL;
                }
-               
+
                $found = false;
-               
+
                while ( $row = $this->fetchObject( $res ) ) {
                        if ( $row->Field == $field ) {
                                $found = true;
@@ -790,7 +812,7 @@ class Database {
                }
                return $found;
        }
-       
+
        /**
         * Determines whether an index exists
         * Usually aborts on failure
@@ -804,8 +826,8 @@ class Database {
                        return $info !== false;
                }
        }
-       
-       
+
+
        /**
         * Get information about an index into an object
         * Returns false if the index does not exist
@@ -820,7 +842,7 @@ class Database {
                if ( !$res ) {
                        return NULL;
                }
-               
+
                while ( $row = $this->fetchObject( $res ) ) {
                        if ( $row->Key_name == $index ) {
                                return $row;
@@ -828,7 +850,7 @@ class Database {
                }
                return false;
        }
-       
+
        /**
         * Query whether a given table exists
         */
@@ -864,7 +886,7 @@ class Database {
                }
                return false;
        }
-       
+
        /**
         * mysql_field_type() wrapper
         */
@@ -886,7 +908,7 @@ class Database {
        /**
         * INSERT wrapper, inserts an array into a table
         *
-        * $a may be a single associative array, or an array of these with numeric keys, for 
+        * $a may be a single associative array, or an array of these with numeric keys, for
         * multi-row insert.
         *
         * Usually aborts on failure
@@ -910,7 +932,7 @@ class Database {
                        $keys = array_keys( $a );
                }
 
-               $sql = 'INSERT ' . implode( ' ', $options ) . 
+               $sql = 'INSERT ' . implode( ' ', $options ) .
                        " INTO $table (" . implode( ',', $keys ) . ') VALUES ';
 
                if ( $multi ) {
@@ -968,7 +990,7 @@ class Database {
                }
                $this->query( $sql, $fname );
        }
-       
+
        /**
         * Makes a wfStrencoded list from an array
         * $mode: LIST_COMMA         - comma separated, no field names
@@ -1006,7 +1028,7 @@ class Database {
                }
                return $list;
        }
-       
+
        /**
         * Change the current database
         */
@@ -1036,13 +1058,13 @@ class Database {
 
        /**
         * Format a table name ready for use in constructing an SQL query
-        * 
-        * This does two important things: it quotes table names which as necessary, 
+        *
+        * This does two important things: it quotes table names which as necessary,
         * and it adds a table prefix if there is one.
-        * 
-        * All functions of this object which require a table name call this function 
+        *
+        * All functions of this object which require a table name call this function
         * themselves. Pass the canonical name to such functions. This is only needed
-        * when calling query() directly. 
+        * when calling query() directly.
         *
         * @param string $name database table name
         */
@@ -1059,7 +1081,7 @@ class Database {
                                # Standard quoting
                                $name = "`$name`";
                        }
-               }               
+               }
                return $name;
        }
 
@@ -1069,7 +1091,7 @@ class Database {
         *
         * Example:
         * extract($dbr->tableNames('user','watchlist'));
-        * $sql = "SELECT wl_namespace,wl_title FROM $watchlist,$user 
+        * $sql = "SELECT wl_namespace,wl_title FROM $watchlist,$user
         *         WHERE wl_user=user_id AND wl_user=$nameWithQuotes";
         */
        function tableNames() {
@@ -1080,7 +1102,7 @@ class Database {
                }
                return $retVal;
        }
-       
+
        /**
         * Wrapper for addslashes()
         * @param string $s String to be slashed.
@@ -1103,9 +1125,9 @@ class Database {
                        # _are_ strings such as article titles and string->number->string
                        # conversion is not 1:1.
                        return "'" . $this->strencode( $s ) . "'";
-               } 
+               }
        }
-               
+
        /**
         * Returns an appropriately quoted sequence value for inserting a new row.
         * MySQL has autoincrement fields, so this is just NULL. But the PostgreSQL
@@ -1127,11 +1149,11 @@ class Database {
         * REPLACE query wrapper
         * PostgreSQL simulates this with a DELETE followed by INSERT
         * $row is the row to insert, an associative array
-        * $uniqueIndexes is an array of indexes. Each element may be either a 
+        * $uniqueIndexes is an array of indexes. Each element may be either a
         * field name or an array of field names
-        * 
-        * It may be more efficient to leave off unique indexes which are unlikely to collide. 
-        * However if you do this, you run the risk of encountering errors which wouldn't have 
+        *
+        * It may be more efficient to leave off unique indexes which are unlikely to collide.
+        * However if you do this, you run the risk of encountering errors which wouldn't have
         * occurred in MySQL
         *
         * @todo migrate comment to phodocumentor format
@@ -1161,7 +1183,7 @@ class Database {
         * DELETE where the condition is a join
         * MySQL does this with a multi-table DELETE syntax, PostgreSQL does it with sub-selects
         *
-        * For safety, an empty $conds will not delete everything. If you want to delete all rows where the 
+        * For safety, an empty $conds will not delete everything. If you want to delete all rows where the
         * join condition matches, set $conds='*'
         *
         * DO NOT put the join condition in $conds
@@ -1183,7 +1205,7 @@ class Database {
                if ( $conds != '*' ) {
                        $sql .= ' AND ' . $this->makeList( $conds, LIST_AND );
                }
-               
+
                return $this->query( $sql, $fname );
        }
 
@@ -1240,11 +1262,11 @@ class Database {
                $destTable = $this->tableName( $destTable );
                 if( is_array( $srcTable ) ) {
                         $srcTable =  implode( ',', array_map( array( &$this, 'tableName' ), $srcTable ) );
-               } else { 
+               } else {
                        $srcTable = $this->tableName( $srcTable );
                }
                $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' .
-                       ' SELECT ' . implode( ',', $varMap ) . 
+                       ' SELECT ' . implode( ',', $varMap ) .
                        " FROM $srcTable";
                if ( $conds != '*' ) {
                        $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
@@ -1256,8 +1278,11 @@ class Database {
         * Construct a LIMIT query with optional offset
         * This is used for query pages
         */
-       function limitResult($limit,$offset) {
-               return ' LIMIT '.(is_numeric($offset)?"{$offset},":"")."{$limit} ";
+       function limitResult($sql, $limit, $offset) {
+               return "$sql LIMIT ".((is_numeric($offset) && $offset != 0)?"{$offset},":"")."{$limit} ";
+       }
+       function limitResultForUpdate($sql, $num) {
+               return $this->limitResult($sql, $num, 0);
        }
 
        /**
@@ -1283,23 +1308,23 @@ class Database {
        /**
         * Perform a deadlock-prone transaction.
         *
-        * This function invokes a callback function to perform a set of write 
-        * queries. If a deadlock occurs during the processing, the transaction 
+        * This function invokes a callback function to perform a set of write
+        * queries. If a deadlock occurs during the processing, the transaction
         * will be rolled back and the callback function will be called again.
         *
-        * Usage: 
+        * Usage:
         *   $dbw->deadlockLoop( callback, ... );
         *
-        * Extra arguments are passed through to the specified callback function. 
-        * 
-        * Returns whatever the callback function returned on its successful, 
-        * iteration, or false on error, for example if the retry limit was 
+        * Extra arguments are passed through to the specified callback function.
+        *
+        * Returns whatever the callback function returned on its successful,
+        * iteration, or false on error, for example if the retry limit was
         * reached.
         */
        function deadlockLoop() {
                $myFname = 'Database::deadlockLoop';
-               
-               $this->query( 'BEGIN', $myFname );
+
+               $this->begin();
                $args = func_get_args();
                $function = array_shift( $args );
                $oldIgnore = $this->ignoreErrors( true );
@@ -1314,7 +1339,7 @@ class Database {
                        $error = $this->lastError();
                        $errno = $this->lastErrno();
                        $sql = $this->lastQuery();
-                       
+
                        if ( $errno ) {
                                if ( $this->wasDeadlock() ) {
                                        # Retry
@@ -1345,11 +1370,11 @@ class Database {
        function masterPosWait( $file, $pos, $timeout ) {
                $fname = 'Database::masterPosWait';
                wfProfileIn( $fname );
-               
-               
+
+
                # Commit any open transactions
                $this->immediateCommit();
-               
+
                # Call doQuery() directly, to avoid opening a transaction if DBO_TRX is set
                $encFile = $this->strencode( $file );
                $sql = "SELECT MASTER_POS_WAIT('$encFile', $pos, $timeout)";
@@ -1376,7 +1401,7 @@ class Database {
                        return array( false, false );
                }
        }
-       
+
        /**
         * Get the position of the master from SHOW MASTER STATUS
         */
@@ -1428,7 +1453,7 @@ class Database {
                $this->query( 'BEGIN', $fname );
                $this->mTrxLevel = 1;
        }
-       
+
        /**
         * Commit transaction, if one is open
         */
@@ -1443,7 +1468,7 @@ class Database {
        function timestamp( $ts=0 ) {
                return wfTimestamp(TS_MW,$ts);
        }
-       
+
        /**
         * Local database timestamp format or null
         */
@@ -1454,7 +1479,7 @@ class Database {
                        return $this->timestamp( $ts );
                }
        }
-       
+
        /**
         * @todo document
         */
@@ -1472,14 +1497,14 @@ class Database {
        function aggregateValue ($valuedata,$valuename='value') {
                return $valuename;
        }
-       
+
        /**
         * @return string wikitext of a link to the server software's web site
         */
        function getSoftwareLink() {
                return "[http://www.mysql.com/ MySQL]";
        }
-       
+
        /**
         * @return string Version information from the database
         */
@@ -1498,14 +1523,14 @@ class Database {
                        return true;
                }
        }
-       
+
        /**
         * Get slave lag.
         * At the moment, this will only work if the DB user has the PROCESS privilege
         */
        function getLag() {
                $res = $this->query( 'SHOW PROCESSLIST' );
-               # Find slave SQL thread. Assumed to be the second one running, which is a bit 
+               # Find slave SQL thread. Assumed to be the second one running, which is a bit
                # dubious, but unfortunately there's no easy rigorous way
                $slaveThreads = 0;
                while ( $row = $this->fetchObject( $res ) ) {
@@ -1530,7 +1555,25 @@ class Database {
                }
                return $status;
        }
-} 
+
+       /**
+        * Return the maximum number of items allowed in a list, or 0 for unlimited.
+        */
+       function maxListLen() {
+               return 0;
+       }
+
+       function encodeBlob($b) {
+               return $b;
+       }
+
+       function notNullTimestamp() {
+               return "!= 0";
+       }
+       function isNullTimestamp() {
+               return "= '0'";
+       }
+}
 
 /**
  * Database abstraction object for mySQL
@@ -1551,7 +1594,7 @@ class DatabaseMysql extends Database {
  */
 class ResultWrapper {
        var $db, $result;
-       
+
        /**
         * @todo document
         */
@@ -1566,21 +1609,21 @@ class ResultWrapper {
        function numRows() {
                return $this->db->numRows( $this->result );
        }
-       
+
        /**
         * @todo document
         */
        function fetchObject() {
                return $this->db->fetchObject( $this->result );
        }
-       
+
        /**
         * @todo document
         */
        function &fetchRow() {
                return $this->db->fetchRow( $this->result );
        }
-       
+
        /**
         * @todo document
         */
@@ -1607,11 +1650,11 @@ class ResultWrapper {
 function wfEmergencyAbort( &$conn, $error ) {
        global $wgTitle, $wgUseFileCache, $title, $wgInputEncoding, $wgOutputEncoding;
        global $wgSitename, $wgServer;
-       
+
        # I give up, Brion is right. Getting the message cache to work when there is no DB is tricky.
        # Hard coding strings instead.
 
-       $noconnect = 'Sorry! The wiki is experiencing some technical difficulties, and cannot contact the database server. <br />
+       $noconnect = 'Sorry! The wiki is experiencing some technical difficulties, and cannot contact the database server: $1. <br />
 $1';
        $mainpage = 'Main Page';
        $searchdisabled = <<<EOT
@@ -1663,7 +1706,7 @@ border=\"0\" ALT=\"Google\"></A>
                        } elseif (@/**/$_REQUEST['search']) {
                                $search = $_REQUEST['search'];
                                echo $searchdisabled;
-                               echo str_replace( array( '$1', '$2' ), array( htmlspecialchars( $search ), 
+                               echo str_replace( array( '$1', '$2' ), array( htmlspecialchars( $search ),
                                  $wgInputEncoding ), $googlesearch );
                                wfErrorExit();
                        } else {
@@ -1675,7 +1718,7 @@ border=\"0\" ALT=\"Google\"></A>
                if( $cache->isFileCached() ) {
                        $msg = '<p style="color: red"><b>'.$msg."<br />\n" .
                                $cachederror . "</b></p>\n";
-                       
+
                        $tag = '<div id="article">';
                        $text = str_replace(
                                $tag,
@@ -1683,7 +1726,7 @@ border=\"0\" ALT=\"Google\"></A>
                                $cache->fetchPageText() );
                }
        }
-       
+
        echo $text;
        wfErrorExit();
 }
index 3705969..0618950 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /**
  * Backwards compatibility wrapper for Database.php
- * 
+ *
  * Note: $wgDatabase has ceased to exist. Destroy all references.
  *
  * @package MediaWiki
@@ -23,7 +23,7 @@ function wfQuery( $sql, $db, $fname = '' ) {
        $c =& wfGetDB( $db );
        if ( $c !== false ) {
                return $c->query( $sql, $fname );
-       } else {        
+       } else {
                return false;
        }
 }
@@ -52,7 +52,7 @@ function &wfGetDB( $db = DB_LAST, $groups = array() ) {
        $ret =& $wgLoadBalancer->getConnection( $db, true, $groups );
        return $ret;
 }
-       
+
 /**
  * Turns on (false) or off (true) the automatic generation and sending
  * of a "we're sorry, but there has been a database error" page on
@@ -82,13 +82,13 @@ function wfIgnoreSQLErrors( $newstate, $dbi = DB_LAST ) {
  * Free a database result
  * @return bool whether result is sucessful or not
  */
-function wfFreeResult( $res, $dbi = DB_LAST ) 
-{ 
+function wfFreeResult( $res, $dbi = DB_LAST )
+{
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
-               $db->freeResult( $res ); 
+               $db->freeResult( $res );
                return true;
-       } else {        
+       } else {
                return false;
        }
 }
@@ -97,11 +97,11 @@ function wfFreeResult( $res, $dbi = DB_LAST )
  * Get an object from a database result
  * @return object|false object we requested
  */
-function wfFetchObject( $res, $dbi = DB_LAST ) { 
+function wfFetchObject( $res, $dbi = DB_LAST ) {
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
-               return $db->fetchObject( $res, $dbi = DB_LAST ); 
-       } else {        
+               return $db->fetchObject( $res, $dbi = DB_LAST );
+       } else {
                return false;
        }
 }
@@ -114,7 +114,7 @@ function wfFetchRow( $res, $dbi = DB_LAST ) {
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
                return $db->fetchRow ( $res, $dbi = DB_LAST );
-       } else {        
+       } else {
                return false;
        }
 }
@@ -123,11 +123,11 @@ function wfFetchRow( $res, $dbi = DB_LAST ) {
  * Get a number of rows from a database result
  * @return integer|false number of rows
  */
-function wfNumRows( $res, $dbi = DB_LAST ) { 
+function wfNumRows( $res, $dbi = DB_LAST ) {
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
-               return $db->numRows( $res, $dbi = DB_LAST ); 
-       } else {        
+               return $db->numRows( $res, $dbi = DB_LAST );
+       } else {
                return false;
        }
 }
@@ -136,11 +136,11 @@ function wfNumRows( $res, $dbi = DB_LAST ) {
  * Get the number of fields from a database result
  * @return integer|false number of fields
  */
-function wfNumFields( $res, $dbi = DB_LAST ) { 
+function wfNumFields( $res, $dbi = DB_LAST ) {
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
-               return $db->numFields( $res ); 
-       } else {        
+               return $db->numFields( $res );
+       } else {
                return false;
        }
 }
@@ -150,12 +150,12 @@ function wfNumFields( $res, $dbi = DB_LAST ) {
  * @param integer $n id of the field
  * @return string|false name of field
  */
-function wfFieldName( $res, $n, $dbi = DB_LAST ) 
-{ 
+function wfFieldName( $res, $n, $dbi = DB_LAST )
+{
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
-               return $db->fieldName( $res, $n, $dbi = DB_LAST ); 
-       } else {        
+               return $db->fieldName( $res, $n, $dbi = DB_LAST );
+       } else {
                return false;
        }
 }
@@ -164,11 +164,11 @@ function wfFieldName( $res, $n, $dbi = DB_LAST )
 /**
  * @todo document function
  */
-function wfInsertId( $dbi = DB_LAST ) { 
+function wfInsertId( $dbi = DB_LAST ) {
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
-               return $db->insertId(); 
-       } else {        
+               return $db->insertId();
+       } else {
                return false;
        }
 }
@@ -176,11 +176,11 @@ function wfInsertId( $dbi = DB_LAST ) {
 /**
  * @todo document function
  */
-function wfDataSeek( $res, $row, $dbi = DB_LAST ) { 
+function wfDataSeek( $res, $row, $dbi = DB_LAST ) {
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
-               return $db->dataSeek( $res, $row ); 
-       } else {        
+               return $db->dataSeek( $res, $row );
+       } else {
                return false;
        }
 }
@@ -188,11 +188,11 @@ function wfDataSeek( $res, $row, $dbi = DB_LAST ) {
 /**
  * @todo document function
  */
-function wfLastErrno( $dbi = DB_LAST ) { 
+function wfLastErrno( $dbi = DB_LAST ) {
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
-               return $db->lastErrno(); 
-       } else {        
+               return $db->lastErrno();
+       } else {
                return false;
        }
 }
@@ -200,11 +200,11 @@ function wfLastErrno( $dbi = DB_LAST ) {
 /**
  * @todo document function
  */
-function wfLastError( $dbi = DB_LAST ) { 
+function wfLastError( $dbi = DB_LAST ) {
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
-               return $db->lastError(); 
-       } else {        
+               return $db->lastError();
+       } else {
                return false;
        }
 }
@@ -212,11 +212,11 @@ function wfLastError( $dbi = DB_LAST ) {
 /**
  * @todo document function
  */
-function wfAffectedRows( $dbi = DB_LAST ) { 
+function wfAffectedRows( $dbi = DB_LAST ) {
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
-               return $db->affectedRows(); 
-       } else {        
+               return $db->affectedRows();
+       } else {
                return false;
        }
 }
@@ -228,7 +228,7 @@ function wfLastDBquery( $dbi = DB_LAST ) {
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
                return $db->lastQuery();
-       } else {        
+       } else {
                return false;
        }
 }
@@ -241,7 +241,7 @@ function wfSetSQL( $table, $var, $value, $cond, $dbi = DB_MASTER )
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
                return $db->set( $table, $var, $value, $cond );
-       } else {        
+       } else {
                return false;
        }
 }
@@ -255,7 +255,7 @@ function wfGetSQL( $table, $var, $cond='', $dbi = DB_LAST )
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
                return $db->selectField( $table, $var, $cond );
-       } else {        
+       } else {
                return false;
        }
 }
@@ -267,7 +267,7 @@ function wfFieldExists( $table, $field, $dbi = DB_LAST ) {
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
                return $db->fieldExists( $table, $field );
-       } else {        
+       } else {
                return false;
        }
 }
@@ -279,7 +279,7 @@ function wfIndexExists( $table, $index, $dbi = DB_LAST ) {
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
                return $db->indexExists( $table, $index );
-       } else {        
+       } else {
                return false;
        }
 }
@@ -291,7 +291,7 @@ function wfInsertArray( $table, $array, $fname = 'wfInsertArray', $dbi = DB_MAST
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
                return $db->insert( $table, $array, $fname );
-       } else {        
+       } else {
                return false;
        }
 }
@@ -303,7 +303,7 @@ function wfGetArray( $table, $vars, $conds, $fname = 'wfGetArray', $dbi = DB_LAS
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
                return $db->getArray( $table, $vars, $conds, $fname );
-       } else {        
+       } else {
                return false;
        }
 }
diff --git a/includes/DatabaseOracle.php b/includes/DatabaseOracle.php
new file mode 100644 (file)
index 0000000..5aa0aa5
--- /dev/null
@@ -0,0 +1,706 @@
+<?php
+
+/**
+ * Oracle.
+ *
+ * @package MediaWiki
+ */
+
+/**
+ * Depends on database
+ */
+require_once( 'Database.php' );
+
+class OracleBlob extends DBObject {
+       function isLOB() {
+               return true;
+       }
+       function data() {
+               return $this->mData;
+       }
+};
+
+/**
+ *
+ * @package MediaWiki
+ */
+class DatabaseOracle extends Database {
+       var $mInsertId = NULL;
+       var $mLastResult = NULL;
+       var $mFetchCache = array();
+       var $mFetchID = array();
+       var $mNcols = array();
+       var $mFieldNames = array(), $mFieldTypes = array();
+       var $mAffectedRows = array();
+       var $mErr;
+
+       function DatabaseOracle($server = false, $user = false, $password = false, $dbName = false,
+               $failFunction = false, $flags = 0, $tablePrefix = 'get from global' )
+       {
+               Database::Database( $server, $user, $password, $dbName, $failFunction, $flags, $tablePrefix );
+       }
+
+       /* static */ function newFromParams( $server = false, $user = false, $password = false, $dbName = false,
+               $failFunction = false, $flags = 0, $tablePrefix = 'get from global' )
+       {
+               return new DatabaseOracle( $server, $user, $password, $dbName, $failFunction, $flags, $tablePrefix );
+       }
+
+       /**
+        * Usually aborts on failure
+        * If the failFunction is set to a non-zero integer, returns success
+        */
+       function open( $server, $user, $password, $dbName ) {
+               if ( !function_exists( 'oci_connect' ) ) {
+                       die( "Oracle functions missing, have you compiled PHP with the --with-oci8 option?\n" );
+               }
+               $this->close();
+               $this->mServer = $server;
+               $this->mUser = $user;
+               $this->mPassword = $password;
+               $this->mDBname = $dbName;
+
+               $success = false;
+
+               $hstring="";
+               $this->mConn = oci_new_connect($user, $password, $dbName, "AL32UTF8");
+               if ( $this->mConn === false ) {
+                       wfDebug( "DB connection error\n" );
+                       wfDebug( "Server: $server, Database: $dbName, User: $user, Password: "
+                               . substr( $password, 0, 3 ) . "...\n" );
+                       wfDebug( $this->lastError()."\n" );
+               } else {
+                       $this->mOpened = true;
+               }
+               return $this->mConn;
+       }
+
+       /**
+        * Closes a database connection, if it is open
+        * Returns success, true if already closed
+        */
+       function close() {
+               $this->mOpened = false;
+               if ($this->mConn) {
+                       return oci_close($this->mConn);
+               } else {
+                       return true;
+               }
+       }
+
+       function parseStatement($sql) {
+               $this->mErr = $this->mLastResult = false;
+               if (($stmt = oci_parse($this->mConn, $sql)) === false) {
+                       $this->lastError();
+                       return $this->mLastResult = false;
+               }
+               $this->mAffectedRows[$stmt] = 0;
+               return $this->mLastResult = $stmt;
+       }
+
+       function doQuery($sql) {
+               if (($stmt = $this->parseStatement($sql)) === false)
+                       return false;
+               return $this->executeStatement($stmt);
+       }
+
+       function executeStatement($stmt) {
+               if (!oci_execute($stmt, OCI_DEFAULT)) {
+                       $this->lastError();
+                       oci_free_statement($stmt);
+                       return false;
+               }
+               $this->mAffectedRows[$stmt] = oci_num_rows($stmt);
+               $this->mFetchCache[$stmt] = array();
+               $this->mFetchID[$stmt] = 0;
+               $this->mNcols[$stmt] = oci_num_fields($stmt);
+               if ($this->mNcols[$stmt] == 0)
+                       return $this->mLastResult;
+               for ($i = 1; $i <= $this->mNcols[$stmt]; $i++) {
+                       $this->mFieldNames[$stmt][$i] = oci_field_name($stmt, $i);
+                       $this->mFieldTypes[$stmt][$i] = oci_field_type($stmt, $i);
+               }
+               while (($o = oci_fetch_array($stmt)) !== false) {
+                       foreach ($o as $key => $value) {
+                               if (is_object($value)) {
+                                       $o[$key] = $value->load();
+                               }
+                       }
+                       $this->mFetchCache[$stmt][] = $o;
+               }
+               return $this->mLastResult;
+       }
+
+       function queryIgnore( $sql, $fname = '' ) {
+               return $this->query( $sql, $fname, true );
+       }
+
+       function freeResult( $res ) {
+               if (!oci_free_statement($res)) {
+                       wfDebugDieBacktrace( "Unable to free Oracle result\n" );
+               }
+               unset($this->mFetchID[$res]);
+               unset($this->mFetchCache[$res]);
+               unset($this->mNcols[$res]);
+               unset($this->mFieldNames[$res]);
+               unset($this->mFieldTypes[$res]);
+       }
+
+       function fetchAssoc($res) {
+               if ($this->mFetchID[$res] >= count($this->mFetchCache[$res]))
+                       return false;
+
+               for ($i = 1; $i <= $this->mNcols[$res]; $i++) {
+                       $name = $this->mFieldNames[$res][$i];
+                       $type = $this->mFieldTypes[$res][$i];
+                       if (isset($this->mFetchCache[$res][$this->mFetchID[$res]][$name]))
+                               $value = $this->mFetchCache[$res][$this->mFetchID[$res]][$name];
+                       else    $value = NULL;
+                       $key = strtolower($name);
+                       wfdebug("'$key' => '$value'\n");
+                       $ret[$key] = $value;
+               }
+               $this->mFetchID[$res]++;
+               return $ret;
+       }
+
+       function fetchRow($res) {
+               $r = $this->fetchAssoc($res);
+               if (!$r)
+                       return false;
+               $i = 0;
+               $ret = array();
+               foreach ($r as $key => $value) {
+                       wfdebug("ret[$i]=[$value]\n");
+                       $ret[$i++] = $value;
+               }
+               return $ret;
+       }
+
+       function fetchObject($res) {
+               $row = $this->fetchAssoc($res);
+               if (!$row)
+                       return false;
+               $ret = new stdClass;
+               foreach ($row as $key => $value)
+                       $ret->$key = $value;
+               return $ret;
+       }
+
+       function numRows($res) {
+               return count($this->mFetchCache[$res]);
+       }
+       function numFields( $res ) { return pg_num_fields( $res ); }
+       function fieldName( $res, $n ) { return pg_field_name( $res, $n ); }
+
+       /**
+        * This must be called after nextSequenceVal
+        */
+       function insertId() {
+               return $this->mInsertId;
+       }
+
+       function dataSeek($res, $row) {
+               $this->mFetchID[$res] = $row;
+       }
+
+       function lastError() {
+               if ($this->mErr === false) {
+                       if ($this->mLastResult !== false) $what = $this->mLastResult;
+                       else if ($this->mConn !== false) $what = $this->mConn;
+                       else $what = false;
+                       $err = ($what !== false) ? oci_error($what) : oci_error();
+                       if ($err === false)
+                               $this->mErr = 'no error';
+                       else
+                               $this->mErr = $err['message'];
+               }
+               return str_replace("\n", '<br />', $this->mErr);
+       }
+       function lastErrno() {
+               return 0;
+       }
+
+       function affectedRows() {
+               return $this->mAffectedRows[$this->mLastResult];
+       }
+
+       /**
+        * Returns information about an index
+        * If errors are explicitly ignored, returns NULL on failure
+        */
+       function indexInfo ($table, $index, $fname = 'Database::indexInfo' ) {
+               $table = $this->tableName($table, true);
+               if ($index == 'PRIMARY')
+                       $index = "${table}_pk";
+               $sql = "SELECT uniqueness FROM all_indexes WHERE table_name='" .
+                       $table . "' AND index_name='" .
+                       $this->strencode(strtoupper($index)) . "'";
+               $res = $this->query($sql, $fname);
+               if (!$res)
+                       return NULL;
+               if (($row = $this->fetchObject($res)) == NULL)
+                       return false;
+               $this->freeResult($res);
+               $row->Non_unique = !$row->uniqueness;
+               return $row;
+       }
+
+       function indexUnique ($table, $index, $fname = 'indexUnique') {
+               if (!($i = $this->indexInfo($table, $index, $fname)))
+                       return $i;
+               return $i->uniqueness == 'UNIQUE';
+       }
+
+       function fieldInfo( $table, $field ) {
+               $o = new stdClass;
+               $o->multiple_key = true; /* XXX */
+               return $o;
+       }
+
+       function getColumnInformation($table, $field) {
+               $table = $this->tableName($table, true);
+               $field = strtoupper($field);
+
+               $res = $this->doQuery("SELECT * FROM all_tab_columns " .
+                       "WHERE table_name='".$table."' " .
+                       "AND   column_name='".$field."'");
+               if (!$res)
+                       return false;
+               $o = $this->fetchObject($res);
+               $this->freeResult($res);
+               return $o;
+       }
+
+       function fieldExists( $table, $field, $fname = 'Database::fieldExists' ) {
+               $column = $this->getColumnInformation($table, $field);
+               if (!$column)
+                       return false;
+               return true;
+       }
+
+       function startTimer( $timeout )
+       {
+               global $IP;
+               wfDebugDieBacktrace( 'Database::startTimer() error : mysql_thread_id() not implemented for postgre' );
+               /*$tid = mysql_thread_id( $this->mConn );
+               exec( "php $IP/killthread.php $timeout $tid &>/dev/null &" );*/
+       }
+
+       function tableName($name, $forddl = false) {
+               # First run any transformations from the parent object
+               $name = parent::tableName( $name );
+
+               # Replace backticks into empty
+               # Note: "foo" and foo are not the same in Oracle!
+               $name = str_replace('`', '', $name);
+
+               # Now quote Oracle reserved keywords
+               switch( $name ) {
+                       case 'user':
+                       case 'group':
+                       case 'validate':
+                               if ($forddl)
+                                       return $name;
+                               else
+                                       return '"' . $name . '"';
+
+                       default:
+                               return strtoupper($name);
+               }
+       }
+
+       function strencode( $s ) {
+               return str_replace("'", "''", $s);
+       }
+
+       /**
+        * Return the next in a sequence, save the value for retrieval via insertId()
+        */
+       function nextSequenceValue( $seqName ) {
+               $r = $this->doQuery("SELECT $seqName.nextval AS val FROM dual");
+               $o = $this->fetchObject($r);
+               $this->freeResult($r);
+               return $this->mInsertId = (int)$o->val;
+       }
+
+       /**
+        * USE INDEX clause
+        * PostgreSQL doesn't have them and returns ""
+        */
+       function useIndexClause( $index ) {
+               return '';
+       }
+
+       # REPLACE query wrapper
+       # PostgreSQL simulates this with a DELETE followed by INSERT
+       # $row is the row to insert, an associative array
+       # $uniqueIndexes is an array of indexes. Each element may be either a
+       # field name or an array of field names
+       #
+       # It may be more efficient to leave off unique indexes which are unlikely to collide.
+       # However if you do this, you run the risk of encountering errors which wouldn't have
+       # occurred in MySQL
+       function replace( $table, $uniqueIndexes, $rows, $fname = 'Database::replace' ) {
+               $table = $this->tableName( $table );
+
+               if (count($rows)==0) {
+                       return;
+               }
+
+               # Single row case
+               if ( !is_array( reset( $rows ) ) ) {
+                       $rows = array( $rows );
+               }
+
+               foreach( $rows as $row ) {
+                       # Delete rows which collide
+                       if ( $uniqueIndexes ) {
+                               $sql = "DELETE FROM $table WHERE ";
+                               $first = true;
+                               foreach ( $uniqueIndexes as $index ) {
+                                       if ( $first ) {
+                                               $first = false;
+                                               $sql .= "(";
+                                       } else {
+                                               $sql .= ') OR (';
+                                       }
+                                       if ( is_array( $index ) ) {
+                                               $first2 = true;
+                                               foreach ( $index as $col ) {
+                                                       if ( $first2 ) {
+                                                               $first2 = false;
+                                                       } else {
+                                                               $sql .= ' AND ';
+                                                       }
+                                                       $sql .= $col.'=' . $this->addQuotes( $row[$col] );
+                                               }
+                                       } else {
+                                               $sql .= $index.'=' . $this->addQuotes( $row[$index] );
+                                       }
+                               }
+                               $sql .= ')';
+                               $this->query( $sql, $fname );
+                       }
+
+                       # Now insert the row
+                       $sql = "INSERT INTO $table (" . $this->makeList( array_keys( $row ), LIST_NAMES ) .') VALUES (' .
+                               $this->makeList( $row, LIST_COMMA ) . ')';
+                       $this->query( $sql, $fname );
+               }
+       }
+
+       # DELETE where the condition is a join
+       function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname = "Database::deleteJoin" ) {
+               if ( !$conds ) {
+                       wfDebugDieBacktrace( 'Database::deleteJoin() called with empty $conds' );
+               }
+
+               $delTable = $this->tableName( $delTable );
+               $joinTable = $this->tableName( $joinTable );
+               $sql = "DELETE FROM $delTable WHERE $delVar IN (SELECT $joinVar FROM $joinTable ";
+               if ( $conds != '*' ) {
+                       $sql .= 'WHERE ' . $this->makeList( $conds, LIST_AND );
+               }
+               $sql .= ')';
+
+               $this->query( $sql, $fname );
+       }
+
+       # Returns the size of a text field, or -1 for "unlimited"
+       function textFieldSize( $table, $field ) {
+               $table = $this->tableName( $table );
+               $sql = "SELECT t.typname as ftype,a.atttypmod as size
+                       FROM pg_class c, pg_attribute a, pg_type t
+                       WHERE relname='$table' AND a.attrelid=c.oid AND
+                               a.atttypid=t.oid and a.attname='$field'";
+               $res =$this->query($sql);
+               $row=$this->fetchObject($res);
+               if ($row->ftype=="varchar") {
+                       $size=$row->size-4;
+               } else {
+                       $size=$row->size;
+               }
+               $this->freeResult( $res );
+               return $size;
+       }
+
+       function lowPriorityOption() {
+               return '';
+       }
+
+       function limitResult($sql, $limit, $offset) {
+               $ret = "SELECT * FROM ($sql) WHERE ROWNUM < " . ((int)$limit + (int)($offset+1));
+               if (is_numeric($offset))
+                       $ret .= " AND ROWNUM >= " . (int)$offset;
+               return $ret;
+       }
+       function limitResultForUpdate($sql, $limit) {
+               return $sql;
+       }
+       /**
+        * Returns an SQL expression for a simple conditional.
+        * Uses CASE on PostgreSQL.
+        *
+        * @param string $cond SQL expression which will result in a boolean value
+        * @param string $trueVal SQL expression to return if true
+        * @param string $falseVal SQL expression to return if false
+        * @return string SQL fragment
+        */
+       function conditional( $cond, $trueVal, $falseVal ) {
+               return " (CASE WHEN $cond THEN $trueVal ELSE $falseVal END) ";
+       }
+
+       # FIXME: actually detecting deadlocks might be nice
+       function wasDeadlock() {
+               return false;
+       }
+
+       # Return DB-style timestamp used for MySQL schema
+       function timestamp($ts = 0) {
+               return $this->strencode(wfTimestamp(TS_ORACLE, $ts));
+#              return "TO_TIMESTAMP('" . $this->strencode(wfTimestamp(TS_DB, $ts)) . "', 'RRRR-MM-DD HH24:MI:SS')";
+       }
+
+       function notNullTimestamp() {
+               return "IS NOT NULL";
+       }
+       function isNullTimestamp() {
+               return "IS NULL";
+       }
+        /**
+         * Return aggregated value function call
+         */
+        function aggregateValue ($valuedata,$valuename='value') {
+                return $valuedata;
+        }
+
+
+       function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) {
+               $message = "A database error has occurred\n" .
+                       "Query: $sql\n" .
+                       "Function: $fname\n" .
+                       "Error: $errno $error\n";
+               wfDebugDieBacktrace($message);
+       }
+
+       /**
+        * @return string wikitext of a link to the server software's web site
+        */
+       function getSoftwareLink() {
+               return "[http://www.oracle.com/ Oracle]";
+       }
+
+       /**
+        * @return string Version information from the database
+        */
+       function getServerVersion() {
+               return oci_server_version($this->mConn);
+       }
+
+       function setSchema($schema=false) {
+               $schemas=$this->mSchemas;
+               if ($schema) { array_unshift($schemas,$schema); }
+               $searchpath=$this->makeList($schemas,LIST_NAMES);
+               $this->query("SET search_path = $searchpath");
+       }
+
+       function begin() {
+       }
+
+       function immediateCommit( $fname = 'Database::immediateCommit' ) {
+               oci_commit($this->mConn);
+               $this->mTrxLevel = 0;
+        }
+       function rollback( $fname = 'Database::rollback' ) {
+               oci_rollback($this->mConn);
+               $this->mTrxLevel = 0;
+       }
+       function getLag() {
+               return false;
+       }
+       function getStatus() {
+               $result = array('Threads_running' => 0, 'Threads_connected' => 0);
+               return $result;
+       }
+
+       /**
+        * Returns an optional USE INDEX clause to go after the table, and a
+        * string to go at the end of the query
+        *
+        * @access private
+        *
+        * @param array $options an associative array of options to be turned into
+        *              an SQL query, valid keys are listed in the function.
+        * @return array
+        */
+       function makeSelectOptions($options) {
+               $tailOpts = '';
+
+               if (isset( $options['ORDER BY'])) {
+                       $tailOpts .= " ORDER BY {$options['ORDER BY']}";
+               }
+
+               return array('', $tailOpts);
+       }
+
+       function maxListLen() {
+               return 1000;
+       }
+
+       /**
+        * Query whether a given table exists
+        */
+       function tableExists( $table ) {
+               $table = $this->tableName($table, true);
+               $res = $this->query( "SELECT COUNT(*) as NUM FROM user_tables WHERE table_name='"
+                       . $table . "'" );
+               if (!$res)
+                       return false;
+               $row = $this->fetchObject($res);
+               $this->freeResult($res);
+               return $row->num >= 1;
+       }
+
+       /**
+        * UPDATE wrapper, takes a condition array and a SET array
+        */
+       function update( $table, $values, $conds, $fname = 'Database::update' ) {
+               $table = $this->tableName( $table );
+
+               $sql = "UPDATE $table SET ";
+               $first = true;
+               foreach ($values as $field => $v) {
+                       if ($first)
+                               $first = false;
+                       else
+                               $sql .= ", ";
+                       $sql .= "$field = :n$field ";
+               }
+               if ( $conds != '*' ) {
+                       $sql .= " WHERE " . $this->makeList( $conds, LIST_AND );
+               }
+               $stmt = $this->parseStatement($sql);
+               if ($stmt === false) {
+                       $this->reportQueryError( $this->lastError(), $this->lastErrno(), $stmt );
+                       return false;
+               }
+               if ($this->debug())
+                       wfDebug("SQL: $sql\n");
+               $s = '';
+               foreach ($values as $field => $v) {
+                       oci_bind_by_name($stmt, ":n$field", $values[$field]);
+                       if ($this->debug())
+                               $s .= " [$field] = [$v]\n";
+               }
+               if ($this->debug())
+                       wfdebug(" PH: $s\n");
+               $ret = $this->executeStatement($stmt);
+               return $ret;
+       }
+
+       /**
+        * INSERT wrapper, inserts an array into a table
+        *
+        * $a may be a single associative array, or an array of these with numeric keys, for
+        * multi-row insert.
+        *
+        * Usually aborts on failure
+        * If errors are explicitly ignored, returns success
+        */
+       function insert( $table, $a, $fname = 'Database::insert', $options = array() ) {
+               # No rows to insert, easy just return now
+               if ( !count( $a ) ) {
+                       return true;
+               }
+
+               $table = $this->tableName( $table );
+               if (!is_array($options))
+                       $options = array($options);
+
+               $oldIgnore = false;
+               if (in_array('IGNORE', $options))
+                       $oldIgnore = $this->ignoreErrors( true );
+
+               if ( isset( $a[0] ) && is_array( $a[0] ) ) {
+                       $multi = true;
+                       $keys = array_keys( $a[0] );
+               } else {
+                       $multi = false;
+                       $keys = array_keys( $a );
+               }
+
+               $sql = "INSERT INTO $table (" . implode( ',', $keys ) . ') VALUES (';
+               $return = '';
+               $first = true;
+               foreach ($a as $key => $value) {
+                       if ($first)
+                               $first = false;
+                       else
+                               $sql .= ", ";
+                       if (is_object($value) && $value->isLOB()) {
+                               $sql .= "EMPTY_BLOB()";
+                               $return = "RETURNING $key INTO :bobj";
+                       } else
+                               $sql .= ":$key";
+               }
+               $sql .= ") $return";
+
+               if ($this->debug()) {
+                       wfDebug("SQL: $sql\n");
+               }
+
+               if (($stmt = $this->parseStatement($sql)) === false) {
+                       $this->reportQueryError($this->lastError(), $this->lastErrno(), $sql, $fname);
+                       $this->ignoreErrors($oldIgnore);
+                       return false;
+               }
+
+               /*
+                * If we're inserting multiple rows, parse the statement once and
+                * execute it for each set of values.  Otherwise, convert it into an
+                * array and pretend.
+                */
+               if (!$multi)
+                       $a = array($a);
+
+               foreach ($a as $key => $row) {
+                       $blob = false;
+                       $bdata = false;
+                       $s = '';
+                       foreach ($row as $k => $value) {
+                               if (is_object($value) && $value->isLOB()) {
+                                       $blob = oci_new_descriptor($this->mConn, OCI_D_LOB);
+                                       $bdata = $value->data();
+                                       oci_bind_by_name($stmt, ":bobj", &$blob, -1, OCI_B_BLOB);
+                               } else
+                                       oci_bind_by_name($stmt, ":$k", $a[$key][$k], -1);
+                               if ($this->debug())
+                                       $s .= " [$k] = {$row[$k]}";
+                       }
+                       if ($this->debug())
+                               wfDebug(" PH: $s\n");
+                       if (($s = $this->executeStatement($stmt)) === false) {
+                               $this->reportQueryError($this->lastError(), $this->lastErrno(), $sql, $fname);
+                               $this->ignoreErrors($oldIgnore);
+                               return false;
+                       }
+
+                       if ($blob) {
+                               $blob->save($bdata);
+                       }
+               }
+               $this->ignoreErrors($oldIgnore);
+               return $this->mLastResult = $s;
+       }
+
+       function ping() {
+               return true;
+       }
+
+       function encodeBlob($b) {
+               return new OracleBlob($b);
+       }
+}
+
+?>
index 1bf5650..b259aad 100644 (file)
@@ -17,14 +17,14 @@ class EditPage {
        var $mArticle;
        var $mTitle;
        var $mMetaData = '';
-       
+
        # Form values
        var $save = false, $preview = false, $diff = false;
        var $minoredit = false, $watchthis = false;
        var $textbox1 = '', $textbox2 = '', $summary = '';
        var $edittime = '', $section = '';
        var $oldid = 0;
-       
+
        /**
         * @todo document
         * @param $article
@@ -97,7 +97,7 @@ class EditPage {
                        {
                                $sat[] = strtolower ( $x ) ;
                        }
-                          
+
                }
 
                # Templates, but only some
@@ -139,7 +139,7 @@ class EditPage {
                $wgOut->setArticleFlag(false);
 
                $this->importFormData( $wgRequest );
-               
+
                if( $this->live ) {
                        $this->livePreview();
                        return;
@@ -189,7 +189,7 @@ class EditPage {
                        }
                }
        }
-       
+
        /**
         * Return true if this page should be previewed when the edit form
         * is initially opened.
@@ -215,7 +215,7 @@ class EditPage {
                        $this->textbox2 = $this->safeUnicodeInput( $request, 'wpTextbox2' );
                        $this->mMetaData = rtrim( $request->getText( 'metadata'   ) );
                        $this->summary   =        $request->getText( 'wpSummary'  );
-       
+
                        $this->edittime = $request->getVal( 'wpEdittime' );
                        if( is_null( $this->edittime ) ) {
                                # If the form is incomplete, force to preview.
@@ -238,7 +238,7 @@ class EditPage {
                        if( !preg_match( '/^\d{14}$/', $this->edittime )) {
                                $this->edittime = null;
                        }
-       
+
                        $this->minoredit = $request->getCheck( 'wpMinoredit' );
                        $this->watchthis = $request->getCheck( 'wpWatchthis' );
                } else {
@@ -259,7 +259,7 @@ class EditPage {
 
                # Section edit can come from either the form or a link
                $this->section = $request->getVal( 'wpSection', $request->getVal( 'section' ) );
-               
+
                $this->live = $request->getCheck( 'live' );
        }
 
@@ -280,7 +280,7 @@ class EditPage {
                        return $wgUser->matchEditToken( $request->getVal( 'wpEditToken' ) );
                }
        }
-       
+
        function submit() {
                $this->edit();
        }
@@ -314,7 +314,7 @@ class EditPage {
                                if(isset($introtitle) && $introtitle->userCanRead()) {
                                        $rev=Revision::newFromTitle($introtitle);
                                        if($rev) {
-                                               $wgOut->addWikiText($rev->getText());   
+                                               $wgOut->addWikiText($rev->getText());
                                                $addstandardintro=false;
                                        }
                                }
@@ -401,6 +401,7 @@ class EditPage {
                        $this->mArticle->clear(); # Force reload of dates, etc.
                        $this->mArticle->forUpdate( true ); # Lock the article
 
+wfdebug("CONFLICT: edittime=".$this->edittime." article timestamp=".$this->mArticle->getTimestamp()."\n");
                        if( ( $this->section != 'new' ) &&
                                ($this->mArticle->getTimestamp() != $this->edittime ) ) {
                                $isConflict = true;
@@ -450,7 +451,7 @@ class EditPage {
                                        # XXX: might be better to integrate this into Article::getTextOfLastEditWithSectionReplacedOrAdded
                                        # for duplicate heading checking and maybe parsing
                                        $hasmatch = preg_match( "/^ *([=]{1,6})(.*?)(\\1) *\\n/i", $this->textbox1, $matches );
-                                       # we can't deal with anchors, includes, html etc in the header for now, 
+                                       # we can't deal with anchors, includes, html etc in the header for now,
                                        # headline would need to be parsed to improve this
                                        #if($hasmatch and strlen($matches[2]) > 0 and !preg_match( "/[\\['{<>]/", $matches[2])) {
                                        if($hasmatch and strlen($matches[2]) > 0) {
@@ -466,16 +467,17 @@ class EditPage {
                                $this->section = '';
                                
                                if (wfRunHooks('ArticleSave', array(&$this->mArticle, &$wgUser, &$text,
-                                                                                                       &$this->summary, &$this->minoredit,
-                                                                                                       &$this->watchthis, &$sectionanchor)))
+                                                               &$this->summary, &$this->minoredit,
+                                                               &$this->watchthis, &$sectionanchor)))
                                {
                                        # update the article here
                                        if($this->mArticle->updateArticle( $text, $this->summary, $this->minoredit,
-                                                                                                          $this->watchthis, '', $sectionanchor ))
+                                                                          $this->watchthis, '', $sectionanchor ))
                                        {
-                                               wfRunHooks('ArticleSaveComplete', array(&$this->mArticle, &$wgUser, $text,
-                                                                                                                               $this->summary, $this->minoredit,
-                                                                                                                               $this->watchthis, $sectionanchor));
+                                               wfRunHooks('ArticleSaveComplete',
+                                                       array(&$this->mArticle, &$wgUser, $text,
+                                                               $this->summary, $this->minoredit,
+                                                               $this->watchthis, $sectionanchor));
                                                return;
                                        } else {
                                                $isConflict = true;
@@ -613,9 +615,11 @@ class EditPage {
                $watchhtml = '';
 
                if ( $wgUser->isLoggedIn() ) {
-                       $watchhtml = "<input tabindex='4' type='checkbox' name='wpWatchthis'".($this->watchthis?" checked='checked'":"").
-                               " accesskey='".wfMsg('accesskey-watch')."' id='wpWatchthis'  />".
-                               "<label for='wpWatchthis' title='".wfMsg('tooltip-watch')."'>{$watchthis}</label>";
+                       $watchhtml = "<input tabindex='4' type='checkbox' name='wpWatchthis'".
+                               ($this->watchthis?" checked='checked'":"").
+                               " accesskey=\"".htmlspecialchars(wfMsg('accesskey-watch'))."\" id='wpWatchthis'  />".
+                               "<label for='wpWatchthis' title=\"" .
+                                       htmlspecialchars(wfMsg('tooltip-watch'))."\">{$watchthis}</label>";
                }
 
                $checkboxhtml = $minoredithtml . $watchhtml . '<br />';
@@ -627,7 +631,7 @@ class EditPage {
                                $wgOut->addHTML( $previewOutput );
                                if($this->mTitle->getNamespace() == NS_CATEGORY) {
                                        $this->mArticle->closeShowCategory();
-                               }                               
+                               }
                                $wgOut->addHTML( "<br style=\"clear:both;\" />\n" );
                        }
                }
@@ -666,7 +670,7 @@ class EditPage {
                        }
                        $templates .= '</ul>';
                }
-               
+
                global $wgLivePreview, $wgStylePath;
                /**
                 * Live Preview lets us fetch rendered preview page content and
@@ -687,7 +691,7 @@ class EditPage {
                } else {
                        $liveOnclick = '';
                }
-               
+
                global $wgUseMetadataEdit ;
                if ( $wgUseMetadataEdit )
                {
@@ -743,8 +747,8 @@ END
                        $wgOut->addHTML( "
 <input type='hidden' value=\"$token\" name=\"wpEditToken\" />\n" );
                }
-               
-               
+
+
                if ( $isConflict ) {
                        require_once( "DifferenceEngine.php" );
                        $wgOut->addWikiText( '==' . wfMsg( "yourdiff" ) . '==' );
@@ -809,18 +813,18 @@ END
                        }
                        
                        if ( $this->mMetaData != "" ) $toparse .= "\n" . $this->mMetaData ;
-                       
+
                        $parserOutput = $wgParser->parse( $this->mArticle->preSaveTransform( $toparse ) ."\n\n",
-                                       $wgTitle, $parserOptions );             
-                       
+                                       $wgTitle, $parserOptions );
+
                        $previewHTML = $parserOutput->mText;
-                       
+
                        $wgOut->addCategoryLinks($parserOutput->getCategoryLinks());
                        $wgOut->addLanguageLinks($parserOutput->getLanguageLinks());
                        return $previewhead . $previewHTML;
                }
        }
-       
+
        /**
         * @todo document
         */
@@ -834,7 +838,7 @@ END
                $id = $wgUser->blockedBy();
                $reason = $wgUser->blockedFor();
                $ip = $wgIP;
-               
+
                if ( is_numeric( $id ) ) {
                        $name = User::whoIs( $id );
                } else {
@@ -885,11 +889,11 @@ END
        function proxyCheck() {
                global $wgBlockOpenProxies, $wgProxyPorts, $wgProxyScriptPath;
                global $wgIP, $wgUseMemCached, $wgMemc, $wgDBname, $wgProxyMemcExpiry;
-               
+
                if ( !$wgBlockOpenProxies ) {
                        return;
                }
-               
+
                # Get MemCached key
                $skip = false;
                if ( $wgUseMemCached ) {
@@ -931,7 +935,7 @@ END
                wfProfileIn( $fname );
 
                $db =& wfGetDB( DB_MASTER );
-               
+
                // This is the revision the editor started from
                $baseRevision = Revision::loadFromTimestamp(
                        $db, $this->mArticle->mTitle, $this->edittime );
@@ -949,7 +953,7 @@ END
                        return false;
                }
                $currentText = $currentRevision->getText();
-               
+
                if( wfMerge( $baseText, $editText, $currentText, $result ) ){
                        $editText = $result;
                        wfProfileOut( $fname );
@@ -980,7 +984,7 @@ END
         */
        function sectionAnchor( $text ) {
                $headline = Sanitizer::decodeCharReferences( $text );
-               # strip out HTML 
+               # strip out HTML
                $headline = preg_replace( '/<.*?' . '>/', '', $headline );
                $headline = trim( $headline );
                $sectionanchor = '#' . urlencode( str_replace( ' ', '_', $headline ) );
@@ -1120,7 +1124,7 @@ END
                $toolbar.="/*]]>*/\n</script>";
                return $toolbar;
        }
-       
+
        /**
         * Output preview text only. This can be sucked into the edit page
         * via JavaScript, and saves the server time rendering the skin as
@@ -1162,7 +1166,7 @@ END
                if ( $oldtext != wfMsg( 'noarticletext' ) || $newtext != '' ) {
                        $difftext = DifferenceEngine::getDiff( $oldtext, $newtext, $oldtitle, $newtitle );
                }
-               
+
                return '<div id="wikiDiff">' . $difftext . '</div>';
        }
 
index 0b85b00..a0cee45 100644 (file)
@@ -8,7 +8,7 @@
 /**
  * Some globals and requires needed
  */
+
 /**
  * Total number of articles
  * @global integer $wgNumberOfArticles
@@ -67,14 +67,14 @@ if( !function_exists('is_a') ) {
 
 # UTF-8 substr function based on a PHP manual comment
 if ( !function_exists( 'mb_substr' ) ) {
-       function mb_substr( $str, $start ) { 
+       function mb_substr( $str, $start ) {
                preg_match_all( '/./us', $str, $ar );
 
                if( func_num_args() >= 3 ) {
-                       $end = func_get_arg( 2 ); 
-                       return join( '', array_slice( $ar[0], $start, $end ) ); 
-               } else { 
-                       return join( '', array_slice( $ar[0], $start ) ); 
+                       $end = func_get_arg( 2 );
+                       return join( '', array_slice( $ar[0], $start, $end ) );
+               } else {
+                       return join( '', array_slice( $ar[0], $start ) );
                }
        }
 }
@@ -235,7 +235,7 @@ function wfReadOnly() {
        if ( '' == $wgReadOnlyFile ) {
                return false;
        }
-       
+
        // Set $wgReadOnly and unset $wgReadOnlyFile, for faster access next time
        if ( is_file( $wgReadOnlyFile ) ) {
                $wgReadOnly = true;
@@ -250,7 +250,7 @@ function wfReadOnly() {
 /**
  * Get a message from anywhere, for the current user language
  *
- * @param string 
+ * @param string
  */
 function wfMsg( $key ) {
        $args = func_get_args();
@@ -302,7 +302,7 @@ function wfMsgNoDBForContent( $key ) {
 function wfMsgReal( $key, $args, $useDB, $forContent=false ) {
        $fname = 'wfMsgReal';
        wfProfileIn( $fname );
-       
+
        $message = wfMsgGetKey( $key, $useDB, $forContent );
        $message = wfMsgReplaceArgs( $message, $args );
        wfProfileOut( $fname );
@@ -321,7 +321,7 @@ function wfMsgGetKey( $key, $useDB, $forContent = false ) {
        global $wgParser, $wgMsgParserOptions;
        global $wgContLang, $wgLanguageCode;
        global $wgMessageCache, $wgLang;
-       
+
        if( is_object( $wgMessageCache ) ) {
                $message = $wgMessageCache->get( $key, $useDB, $forContent );
        } else {
@@ -332,7 +332,7 @@ function wfMsgGetKey( $key, $useDB, $forContent = false ) {
                }
 
                wfSuppressWarnings();
-               
+
                if( is_object( $lang ) ) {
                        $message = $lang->getMessage( $key );
                } else {
@@ -358,7 +358,7 @@ function wfMsgGetKey( $key, $useDB, $forContent = false ) {
  */
 function wfMsgReplaceArgs( $message, $args ) {
        static $replacementKeys = array( '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9' );
-       
+
        # Fix windows line-endings
        # Some messages are split with explode("\n", $msg)
        $message = str_replace( "\r", '', $message );
@@ -449,7 +449,7 @@ function wfBacktrace() {
        if ( !function_exists( 'debug_backtrace' ) ) {
                return false;
        }
-       
+
        if ( $wgCommandLineMode ) {
                $msg = '';
        } else {
@@ -519,7 +519,7 @@ function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) {
        $fmtLimit = $wgLang->formatNum( $limit );
        $prev = wfMsg( 'prevn', $fmtLimit );
        $next = wfMsg( 'nextn', $fmtLimit );
-       
+
        if( is_object( $link ) ) {
                $title =& $link;
        } else {
@@ -528,7 +528,7 @@ function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) {
                        return false;
                }
        }
-       
+
        $sk = $wgUser->getSkin();
        if ( 0 != $offset ) {
                $po = $offset - $limit;
@@ -611,7 +611,7 @@ function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) {
  * @param string $text Text to be escaped
  */
 function wfEscapeWikiText( $text ) {
-       $text = str_replace( 
+       $text = str_replace(
                array( '[',             '|',      '\'',    'ISBN '        , '://'         , "\n=", '{{' ),
                array( '&#91;', '&#124;', '&#39;', 'ISBN&#32;', '&#58;//' , "\n&#61;", '&#123;&#123;' ),
                htmlspecialchars($text) );
@@ -655,7 +655,7 @@ function wfEscapeJsString( $string ) {
                '\'' => '\\\'',
                "\n" => "\\n",
                "\r" => "\\r",
-               
+
                # To avoid closing the element or CDATA section
                "<" => "\\x3c",
                ">" => "\\x3e",
@@ -741,7 +741,7 @@ function wfPurgeSquidServers ($urlArr) {
 
 /**
  * Windows-compatible version of escapeshellarg()
- * Windows doesn't recognise single-quotes in the shell, but the escapeshellarg() 
+ * Windows doesn't recognise single-quotes in the shell, but the escapeshellarg()
  * function puts single quotes in regardless of OS
  */
 function wfEscapeShellArg( ) {
@@ -754,7 +754,7 @@ function wfEscapeShellArg( ) {
                } else {
                        $first = false;
                }
-       
+
                if ( wfIsWindows() ) {
                        $retVal .= '"' . str_replace( '"','\"', $arg ) . '"';
                } else {
@@ -843,8 +843,8 @@ function wfHttpError( $code, $label, $desc ) {
 
        header( 'Content-type: text/html' );
        print "<html><head><title>" .
-               htmlspecialchars( $label ) . 
-               "</title></head><body><h1>" . 
+               htmlspecialchars( $label ) .
+               "</title></head><body><h1>" .
                htmlspecialchars( $label ) .
                "</h1><p>" .
                htmlspecialchars( $desc ) .
@@ -958,7 +958,7 @@ function wfNegotiateType( $cprefs, $sprefs ) {
  * Array lookup
  * Returns an array where the values in the first array are replaced by the
  * values in the second array with the corresponding keys
- * 
+ *
  * @return array
  */
 function wfArrayLookup( $a, $b ) {
@@ -1005,7 +1005,7 @@ function wfRestoreWarnings() {
 
 # Autodetect, convert and provide timestamps of various types
 
-/** 
+/**
  * Unix time - the number of seconds since 1970-01-01 00:00:00 UTC
  */
 define('TS_UNIX', 0);
@@ -1034,6 +1034,10 @@ define('TS_RFC2822', 3);
  */
 define('TS_EXIF', 4);
 
+/**
+ * Oracle format time.
+ */
+define('TS_ORACLE', 5);
 
 /**
  * @param mixed $outputtype A timestamp in one of the supported formats, the
@@ -1042,8 +1046,9 @@ define('TS_EXIF', 4);
  * @return string Time in the format specified in $outputtype
  */
 function wfTimestamp($outputtype=TS_UNIX,$ts=0) {
-       if ($ts==0) { 
-               $uts=time(); 
+wfdebug("ts: $ts\n");
+       if ($ts==0) {
+               $uts=time();
        } elseif (preg_match("/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)$/",$ts,$da)) {
                # TS_DB
                $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6],
@@ -1059,13 +1064,17 @@ function wfTimestamp($outputtype=TS_UNIX,$ts=0) {
        } elseif (preg_match("/^(\d{1,13})$/",$ts,$datearray)) {
                # TS_UNIX
                $uts=$ts;
+       } elseif (preg_match('/^(\d{1,2})-(...)-(\d\d(\d\d)?) (\d\d)\.(\d\d)\.(\d\d)/', $ts, $da)) {
+               # TS_ORACLE
+               $uts = strtotime(preg_replace('/(\d\d)\.(\d\d)\.(\d\d)(\.(\d+))?/', "$1:$2:$3",
+                               str_replace("+00:00", "UTC", $ts)));
        } else {
                # Bogus value; fall back to the epoch...
                wfDebug("wfTimestamp() fed bogus time value: $outputtype; $ts\n");
                $uts = 0;
        }
 
-               
+
        switch($outputtype) {
                case TS_UNIX:
                        return $uts;
@@ -1078,6 +1087,8 @@ function wfTimestamp($outputtype=TS_UNIX,$ts=0) {
                        return gmdate(  'Y:m:d H:i:s', $uts );
                case TS_RFC2822:
                        return gmdate( 'D, d M Y H:i:s', $uts ) . ' GMT';
+               case TS_ORACLE:
+                       return gmdate( 'd-M-y h.i.s A', $uts) . ' +00:00';
                default:
                        wfDebugDieBacktrace( 'wfTimestamp() called with illegal output type.');
        }
@@ -1103,13 +1114,13 @@ function wfTimestampOrNull( $outputtype = TS_UNIX, $ts = null ) {
  *
  * @return bool True if it's windows, False otherwise.
  */
-function wfIsWindows() {   
-       if (substr(php_uname(), 0, 7) == 'Windows') {   
-               return true;   
-       } else {   
-               return false;   
-       }   
-} 
+function wfIsWindows() {
+       if (substr(php_uname(), 0, 7) == 'Windows') {
+               return true;
+       } else {
+               return false;
+       }
+}
 
 /**
  * Swap two variables
@@ -1228,7 +1239,7 @@ function &HTMLnamespaceselector($selected = '', $allnamespaces = null) {
 
 /** Global singleton instance of MimeMagic. This is initialized on demand,
 * please always use the wfGetMimeMagic() function to get the instance.
-* 
+*
 * @private
 */
 $wgMimeMagic= NULL;
@@ -1241,7 +1252,7 @@ $wgMimeMagic= NULL;
 */
 function &wfGetMimeMagic() {
        global $wgMimeMagic;
-       
+
        if (!is_null($wgMimeMagic)) {
                return $wgMimeMagic;
        }
@@ -1250,9 +1261,9 @@ function &wfGetMimeMagic() {
                #include on demand
                require_once("MimeMagic.php");
        }
-       
+
        $wgMimeMagic= new MimeMagic();
-       
+
        return $wgMimeMagic;
 }
 
index 5808580..f3ead55 100644 (file)
@@ -312,7 +312,7 @@ class ImagePage extends Article {
                if ( $line ) {
                        $list =& new ImageHistoryList( $sk );
                        $s = $list->beginImageHistoryList() .
-                               $list->imageHistoryLine( true, $line->img_timestamp,
+                               $list->imageHistoryLine( true, wfTimestamp(TS_MW, $line->img_timestamp),
                                        $this->mTitle->getDBkey(),  $line->img_user,
                                        $line->img_user_text, $line->img_size, $line->img_description );
 
@@ -344,8 +344,8 @@ class ImagePage extends Article {
                $imagelinks = $dbr->tableName( 'imagelinks' );
 
                $sql = "SELECT page_namespace,page_title FROM $imagelinks,$page WHERE il_to=" .
-                 $dbr->addQuotes( $this->mTitle->getDBkey() ) . " AND il_from=page_id"
-                 . " LIMIT 500"; # quickie emergency brake
+                 $dbr->addQuotes( $this->mTitle->getDBkey() ) . " AND il_from=page_id";
+               $sql = $dbr->limitResult($sql, 500, 0);
                $res = $dbr->query( $sql, "ImagePage::imageLinks" );
 
                if ( 0 == $dbr->numRows( $res ) ) {
index dae7533..4eda8d2 100644 (file)
@@ -18,7 +18,7 @@ define ('LINKCACHE_PAGE', 3);
  * @package MediaWiki
  * @subpackage Cache
  */
-class LinkCache {      
+class LinkCache {
        // Increment $mClassVer whenever old serialized versions of this class
        // becomes incompatible with the new version.
        /* private */ var $mClassVer = 3;
@@ -33,7 +33,7 @@ class LinkCache {
                global $wgDBname;
                return $wgDBname.':lc:title:'.$title;
        }
-       
+
        function LinkCache() {
                $this->mActive = true;
                $this->mPreFilled = false;
@@ -51,10 +51,10 @@ class LinkCache {
        /**
         * General accessor to get/set whether SELECT FOR UPDATE should be used
         */
-       function forUpdate( $update = NULL ) { 
+       function forUpdate( $update = NULL ) {
                return wfSetVar( $this->mForUpdate, $update );
        }
-       
+
        function getGoodLinkID( $title ) {
                if ( array_key_exists( $title, $this->mGoodLinks ) ) {
                        return $this->mGoodLinks[$title];
@@ -64,7 +64,7 @@ class LinkCache {
        }
 
        function isBadLink( $title ) {
-               return array_key_exists( $title, $this->mBadLinks ); 
+               return array_key_exists( $title, $this->mBadLinks );
        }
 
        function addGoodLinkObj( $id, $title ) {
@@ -90,11 +90,11 @@ class LinkCache {
        function addImageLinkObj( $nt ) {
                if ( $this->mActive ) { $this->mImageLinks[$nt->getDBkey()] = 1; }
        }
-       
+
        function addCategoryLink( $title, $sortkey ) {
                if ( $this->mActive ) { $this->mCategoryLinks[$title] = $sortkey; }
        }
-       
+
        function addCategoryLinkObj( &$nt, $sortkey ) {
                $this->addCategoryLink( $nt->getDBkey(), $sortkey );
        }
@@ -103,7 +103,7 @@ class LinkCache {
                unset( $this->mBadLinks[$title] );
                $this->clearLink( $title );
        }
-       
+
        function clearLink( $title ) {
                global $wgMemc, $wgLinkCacheMemcached;
                if( $wgLinkCacheMemcached )
@@ -126,11 +126,11 @@ class LinkCache {
                        return 0;
                }
        }
-       
+
        function addLinkObj( &$nt ) {
                global $wgMemc, $wgLinkCacheMemcached, $wgAntiLockFlags;
                $title = $nt->getPrefixedDBkey();
-               if ( $this->isBadLink( $title ) ) { return 0; }         
+               if ( $this->isBadLink( $title ) ) { return 0; }
                $id = $this->getGoodLinkID( $title );
                if ( 0 != $id ) { return $id; }
 
@@ -140,11 +140,11 @@ class LinkCache {
                $ns = $nt->getNamespace();
                $t = $nt->getDBkey();
 
-               if ( '' == $title ) { 
+               if ( '' == $title ) {
                        wfProfileOut( $fname );
-                       return 0; 
+                       return 0;
                }
-               
+
                $id = NULL;
                if( $wgLinkCacheMemcached )
                        $id = $wgMemc->get( $key = $this->getKey( $title ) );
@@ -159,14 +159,17 @@ class LinkCache {
                                $options = array();
                        }
 
-                       $id = $db->selectField( 'page', 'page_id', array( 'page_namespace' => $ns, 'page_title' => $t ), $fname, $options );
+                       $id = $db->selectField( 'page', 'page_id',
+                                       array( 'page_namespace' => $ns, 'page_title' => $t ),
+                                       $fname, $options );
+wfdebug("link cache: id=$id\n");
                        if ( !$id ) {
                                $id = 0;
                        }
                        if( $wgLinkCacheMemcached )
                                $wgMemc->add( $key, $id, 3600*24 );
                }
-               
+
                if( 0 == $id ) {
                        $this->addBadLinkObj( $nt );
                } else {
@@ -188,13 +191,13 @@ class LinkCache {
                $this->suspend();
                $id = $fromtitle->getArticleID();
                $this->resume();
-               
+
                if( $id == 0 ) {
                        wfDebug( "$fname - got id 0 for title '" . $fromtitle->getPrefixedDBkey() . "'\n" );
                        wfProfileOut( $fname );
                        return;
                }
-               
+
                if ( $this->mForUpdate ) {
                        $db =& wfGetDB( DB_MASTER );
                        if ( !( $wgAntiLockFlags & ALF_NO_LINK_LOCK ) ) {
@@ -254,7 +257,7 @@ class LinkCache {
        function getImageDeletions() {
                return array_diff_assoc( $this->mOldImageLinks, $this->mImageLinks );
        }
-       
+
        function getPageAdditions() {
                $set = array_diff( array_keys( $this->mPageLinks ), array_keys( $this->mOldPageLinks ) );
                $out = array();
@@ -263,7 +266,7 @@ class LinkCache {
                }
                return $out;
        }
-       
+
        function getPageDeletions() {
                $set = array_diff( array_keys( $this->mOldPageLinks ), array_keys( $this->mPageLinks ) );
                $out = array();
@@ -308,14 +311,14 @@ class LinkCache {
                                $add = $this->getPageAdditions();
                                break;
                        default: # LINKCACHE_IMAGE
-                               return false;           
+                               return false;
                }
-               
+
                return true;
        }
 
        /**
-        * Clears cache 
+        * Clears cache
         */
        function clear() {
                $this->mPageLinks = array();
@@ -347,7 +350,7 @@ class LinkCache {
  * @subpackage Cache
  */
 class LinkBatch {
-       /** 
+       /**
         * 2-d array, first index namespace, second index dbkey, value arbitrary
         */
        var $data = array();
@@ -357,7 +360,7 @@ class LinkBatch {
                        $this->addObj( $item );
                }
        }
-       
+
        function addObj( $title ) {
                $this->add( $title->getNamespace(), $title->getDBkey() );
        }
@@ -389,7 +392,7 @@ class LinkBatch {
                $page = $dbr->tableName( 'page' );
                $sql = "SELECT page_id, page_namespace, page_title FROM $page WHERE "
                        . $this->constructSet( 'page', $dbr );
-               
+
                // Do query
                $res = $dbr->query( $sql, $fname );
 
@@ -414,7 +417,7 @@ class LinkBatch {
 
                wfProfileOut( $fname );
        }
-       
+
        /**
         * Construct a WHERE clause which will match all the given titles.
         * Give the appropriate table's field name prefix ('page', 'pl', etc).
index ee402d6..54fc617 100644 (file)
@@ -74,9 +74,9 @@ class LoadBalancer {
                                        $this->mGroupLoads[$group][$i] = $ratio;
                                }
                        }
-               }       
+               }
        }
-       
+
        /**
         * Given an array of non-normalised probabilities, this function will select
         * an element and return the appropriate key
@@ -101,7 +101,7 @@ class LoadBalancer {
                }
                $max = mt_getrandmax();
                $rand = mt_rand(0, $max) / $max * $sum;
-               
+
                $sum = 0;
                foreach ( $weights as $i => $w ) {
                        $sum += $w;
@@ -130,7 +130,7 @@ class LoadBalancer {
                if ( $sum == 0 ) {
                        # No appropriate DB servers except maybe the master and some slaves with zero load
                        # Do NOT use the master
-                       # Instead, this function will return false, triggering read-only mode, 
+                       # Instead, this function will return false, triggering read-only mode,
                        # and a lagged slave will be used instead.
                        unset ( $loads[0] );
                }
@@ -147,7 +147,7 @@ class LoadBalancer {
 
        /**
         * Get the index of the reader connection, which may be a slave
-        * This takes into account load ratios and lag times. It should 
+        * This takes into account load ratios and lag times. It should
         * always return a consistent index during a given invocation
         *
         * Side effect: opens connections to databases
@@ -185,15 +185,15 @@ class LoadBalancer {
                                        if ( $i !== false ) {
                                                wfDebug( "Using reader #$i: {$this->mServers[$i]['host']}...\n" );
                                                $this->openConnection( $i );
-                                               
+
                                                if ( !$this->isOpen( $i ) ) {
                                                        wfDebug( "Failed\n" );
                                                        unset( $loads[$i] );
                                                        $sleepTime = 0;
                                                } else {
                                                        $status = $this->mConnections[$i]->getStatus();
-                                                       if ( isset( $this->mServers[$i]['max threads'] ) && 
-                                                         $status['Threads_running'] > $this->mServers[$i]['max threads'] ) 
+                                                       if ( isset( $this->mServers[$i]['max threads'] ) &&
+                                                         $status['Threads_running'] > $this->mServers[$i]['max threads'] )
                                                        {
                                                                # Slave is lagged, wait for a while
                                                                $sleepTime = 5000 * $status['Threads_connected'];
@@ -232,7 +232,7 @@ class LoadBalancer {
                wfProfileOut( $fname );
                return $i;
        }
-       
+
        /**
         * Get a random server to use in a query group
         */
@@ -245,7 +245,7 @@ class LoadBalancer {
                wfDebug( "Query group $group => $i\n" );
                return $i;
        }
-       
+
        /**
         * Set the master wait position
         * If a DB_SLAVE connection has been opened already, waits
@@ -269,7 +269,7 @@ class LoadBalancer {
                                        $this->mServers[$i]['slave pos'] = $this->mConnections[$i]->getSlavePos();
                                        $this->mLaggedSlaveMode = true;
                                }
-                       } 
+                       }
                }
                wfProfileOut( $fname );
        }
@@ -279,7 +279,7 @@ class LoadBalancer {
         */
        function doWait( $index ) {
                global $wgMemc;
-               
+
                $retVal = false;
 
                # Debugging hacks
@@ -314,7 +314,7 @@ class LoadBalancer {
                        }
                }
                return $retVal;
-       }               
+       }
 
        /**
         * Get a connection by index
@@ -323,7 +323,7 @@ class LoadBalancer {
        {
                $fname = 'LoadBalancer::getConnection';
                wfProfileIn( $fname );
-               
+
                # Query groups
                $groupIndex = false;
                foreach ( $groups as $group ) {
@@ -333,9 +333,9 @@ class LoadBalancer {
                                break;
                        }
                }
-               
+
                # Operation-based index
-               if ( $i == DB_SLAVE ) { 
+               if ( $i == DB_SLAVE ) {
                        $i = $this->getReaderIndex();
                } elseif ( $i == DB_MASTER ) {
                        $i = $this->getWriterIndex();
@@ -350,7 +350,7 @@ class LoadBalancer {
                }
                # Now we have an explicit index into the servers array
                $this->openConnection( $i, $fail );
-               
+
                wfProfileOut( $fname );
                return $this->mConnections[$i];
        }
@@ -369,6 +369,7 @@ class LoadBalancer {
                if ( !$this->isOpen( $i ) ) {
                        $this->mConnections[$i] = $this->reallyOpenConnection( $this->mServers[$i] );
                }
+
                if ( !$this->isOpen( $i ) ) {
                        wfDebug( "Failed to connect to database $i at {$this->mServers[$i]['host']}\n" );
                        if ( $fail ) {
@@ -390,15 +391,15 @@ class LoadBalancer {
                if( !is_integer( $index ) ) {
                        return false;
                }
-               if ( array_key_exists( $index, $this->mConnections ) && is_object( $this->mConnections[$index] ) && 
-                 $this->mConnections[$index]->isOpen() ) 
+               if ( array_key_exists( $index, $this->mConnections ) && is_object( $this->mConnections[$index] ) &&
+                 $this->mConnections[$index]->isOpen() )
                {
                        return true;
                } else {
                        return false;
                }
        }
-       
+
        /**
         * Really opens a connection
         * @private
@@ -407,7 +408,7 @@ class LoadBalancer {
                if( !is_array( $server ) ) {
                        wfDebugDieBacktrace( 'You must update your load-balancing configuration. See DefaultSettings.php entry for $wgDBservers.' );
                }
-               
+
                extract( $server );
                # Get class for this database type
                $class = 'Database' . ucfirst( $type );
@@ -418,13 +419,13 @@ class LoadBalancer {
                # Create object
                return new $class( $host, $user, $password, $dbname, 1, $flags );
        }
-       
+
        function reportConnectionError( &$conn )
        {
                $fname = 'LoadBalancer::reportConnectionError';
                wfProfileIn( $fname );
                # Prevent infinite recursion
-               
+
                static $reporting = false;
                if ( !$reporting ) {
                        $reporting = true;
@@ -441,7 +442,7 @@ class LoadBalancer {
                }
                wfProfileOut( $fname );
        }
-       
+
        function getWriterIndex()
        {
                return 0;
@@ -470,7 +471,7 @@ class LoadBalancer {
        function saveMasterPos() {
                global $wgSessionStarted;
                if ( $wgSessionStarted && count( $this->mServers ) > 1 ) {
-                       # If this entire request was served from a slave without opening a connection to the 
+                       # If this entire request was served from a slave without opening a connection to the
                        # master (however unlikely that may be), then we can fetch the position from the slave.
                        if ( empty( $this->mConnections[0] ) ) {
                                $conn =& $this->getConnection( DB_SLAVE );
@@ -556,7 +557,7 @@ class LoadBalancer {
                }
                return array( $host, $maxLag );
        }
-       
+
        /**
         * Get lag time for each DB
         * Results are cached for a short time in memcached
index 4447dd7..1fc5116 100644 (file)
@@ -2,17 +2,17 @@
 #
 # Copyright (C) 2002, 2004 Brion Vibber <brion@pobox.com>
 # http://www.mediawiki.org/
-# 
+#
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or 
+# the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
+#
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License along
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
@@ -67,7 +67,7 @@ class LogPage {
                                'log_params' => $this->params
                        ), $fname
                );
-               
+
                # And update recentchanges
                if ( $this->updateRecentChanges ) {
                        $titleObj = Title::makeTitle( NS_SPECIAL, 'Log/' . $this->type );
@@ -78,7 +78,7 @@ class LogPage {
                                else
                                        $rcComment .= ': ' . $this->comment;
                        }
-                       
+
                        RecentChange::notifyLog( $now, $titleObj, $wgUser, $rcComment );
                }
                return true;
@@ -92,7 +92,7 @@ class LogPage {
                wfRunHooks( 'LogPageValidTypes', array( &$types) );
                return $types;
        }
-       
+
        /**
         * @static
         */
@@ -108,14 +108,14 @@ class LogPage {
                );
                return $actions[$type];
        }
-       
+
        /**
         * @static
         */
        function isLogType( $type ) {
                return in_array( $type, LogPage::validTypes() );
        }
-       
+
        /**
         * @static
         */
@@ -133,7 +133,7 @@ class LogPage {
                
                return str_replace( '_', ' ', wfMsg( $typeText[$type] ) );
        }
-       
+
        /**
         * @static
         */
@@ -151,7 +151,7 @@ class LogPage {
                
                return wfMsg( $headerText[$type] );
        }
-       
+
        /**
         * @static
         */
@@ -175,7 +175,7 @@ class LogPage {
                $key = "$type/$action";
                if( isset( $actions[$key] ) ) {
                        if( is_null( $title ) ) {
-                               $rv=wfMsgForContent( $actions[$key] );
+                               $rv=wfMsg( $actions[$key] );
                        } else {
                                if( $skin ) {
                                        if ( $type == 'move' ) {
@@ -190,10 +190,10 @@ class LogPage {
                                        $titleLink = $title->getPrefixedText();
                                }
                                if( count( $params ) == 0 ) {
-                                       $rv = wfMsgForContent( $actions[$key], $titleLink );
+                                       $rv = wfMsg( $actions[$key], $titleLink );
                                } else {
                                        array_unshift( $params, $titleLink );
-                                       $rv = wfMsgReal( $actions[$key], $params, true, true );
+                                       $rv = wfMsgReal( $actions[$key], $params, true, false );
                                }
                        }
                } else {
@@ -218,18 +218,18 @@ class LogPage {
                if ( !is_array( $params ) ) {
                        $params = array( $params );
                }
-               
+
                $this->action = $action;
                $this->target =& $target;
                $this->comment = $comment;
                $this->params = LogPage::makeParamBlob( $params );
-               
+
                $this->actionText = LogPage::actionText( $this->type, $action, $target, NULL, $params );
 
                return $this->saveContent();
        }
 
-       /** 
+       /**
         * Create a blob from a parameter array
         * @static
         */
index d1d06ac..8466137 100644 (file)
@@ -3,13 +3,13 @@
  * Provide things related to namespaces
  * @package MediaWiki
  */
+
 /**
  * This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
  */
 if( defined( 'MEDIAWIKI' ) ) {
 
+
 /**
  * Definitions of the NS_ constants are in Defines.php
  * @private
@@ -56,8 +56,8 @@ class Namespace {
         * @return bool
         */
        function isMovable( $index ) {
-               if ( $index < NS_MAIN || $index == NS_IMAGE  || $index == NS_CATEGORY ) { 
-                       return false; 
+               if ( $index < NS_MAIN || $index == NS_IMAGE  || $index == NS_CATEGORY ) {
+                       return false;
                }
                return true;
        }
@@ -71,10 +71,10 @@ class Namespace {
                return ( $index == NS_TALK           || $index == NS_USER_TALK     ||
                                 $index == NS_PROJECT_TALK   || $index == NS_IMAGE_TALK    ||
                                 $index == NS_MEDIAWIKI_TALK || $index == NS_TEMPLATE_TALK ||
-                                $index == NS_HELP_TALK      || $index == NS_CATEGORY_TALK 
+                                $index == NS_HELP_TALK      || $index == NS_CATEGORY_TALK
                                 ||  ( (isset($wgExtraNamespaces) && $index % 2) )
                                 );
-               
+
        }
 
        /**
index dbf6221..f01171e 100644 (file)
@@ -53,9 +53,9 @@ function &wfGetCache( $inputType ) {
        }
 
        if ( $type == CACHE_MEMCACHED ) {
-               if ( !array_key_exists( CACHE_MEMCACHED, $wgCaches ) ){ 
+               if ( !array_key_exists( CACHE_MEMCACHED, $wgCaches ) ){
                        require_once( 'memcached-client.php' );
-                       
+
                        if (!class_exists("MemcachedClientforWiki")) {
                                class MemCachedClientforWiki extends memcached {
                                        function _debugprint( $text ) {
@@ -64,7 +64,7 @@ function &wfGetCache( $inputType ) {
                                }
                        }
 
-                       $wgCaches[CACHE_DB] = new MemCachedClientforWiki( 
+                       $wgCaches[CACHE_DB] = new MemCachedClientforWiki(
                                array('persistant' => false, 'compress_threshold' => 1500 ) );
                        $cache =& $wgCaches[CACHE_DB];
                        $cache->set_servers( $wgMemCachedServers );
@@ -94,7 +94,7 @@ function &wfGetCache( $inputType ) {
                }
                $cache =& $wgCaches[CACHE_DB];
        }
-       
+
        if ( $cache === false ) {
                if ( !array_key_exists( CACHE_NONE, $wgCaches ) ) {
                        $wgCaches[CACHE_NONE] = new FakeMemCachedClient;
index 1bf67a5..5079a3b 100644 (file)
@@ -64,6 +64,8 @@ class PageHistory {
                $fname = 'PageHistory::history';
                wfProfileIn( $fname );
 
+               $dbr = wfGetDB(DB_SLAVE);
+
                /*
                 * Setup page variables.
                 */
@@ -93,7 +95,9 @@ class PageHistory {
                /* Offset must be an integral. */
                if (!strlen($offset) || !preg_match("/^[0-9]+$/", $offset))
                        $offset = 0;
-
+#              $offset = $dbr->timestamp($offset);
+               $dboffset = $dbr->timestamp($offset);
+wfdebug("offset=[$offset] dboffset=[$dboffset]\n");
                /*
                 * "go=last" means to jump to the last history page.
                 */
@@ -102,7 +106,8 @@ class PageHistory {
                        case "first":
                                if (($lastid = $this->getLastOffsetForPaging($id, $limit)) === NULL)
                                        break;
-                               $gourl = $wgTitle->getLocalURL("action=history&limit={$limit}&offset={$lastid}");
+                               $gourl = $wgTitle->getLocalURL("action=history&limit={$limit}&offset=".
+                                               wfTimestamp(TS_MW, $lastid));
                                break;
                        default:
                                $gourl = NULL;
@@ -122,7 +127,7 @@ class PageHistory {
                 * previous revisions when generating the URL.
                 */
                $direction = $this->getDirection();
-               $revisions = $this->fetchRevisions($limit, $offset, $direction);
+               $revisions = $this->fetchRevisions($limit, $dboffset, $direction);
                $navbar = $this->makeNavbar($revisions, $offset, $limit, $direction);
 
                /*
@@ -261,7 +266,7 @@ class PageHistory {
        /** @todo document */
        function revLink( $row ) {
                global $wgUser, $wgLang;
-               $date = $wgLang->timeanddate( $row->rev_timestamp, true );
+               $date = $wgLang->timeanddate( wfTimestamp(TS_MW, $row->rev_timestamp), true );
                if( $row->rev_deleted && !$wgUser->isAllowed( 'undelete' ) ) {
                        return $date;
                } else {
@@ -382,7 +387,8 @@ class PageHistory {
                $db =& wfGetDB(DB_SLAVE);
                $revision = $db->tableName( 'revision' );
                $sql = "SELECT rev_timestamp FROM $revision WHERE rev_page = $id " .
-                       "ORDER BY rev_timestamp ASC LIMIT $step";
+                       "ORDER BY rev_timestamp ASC";
+               $sql = $db->limitResult($sql, $step, 0);
                $res = $db->query( $sql, "PageHistory::getLastOffsetForPaging" );
                $n = $db->numRows( $res );
 
@@ -429,8 +435,6 @@ class PageHistory {
                if ($offset)
                        $offsets .= " AND rev_timestamp $oper '$offset' ";
 
-               if ($limit)
-                       $limits .= " LIMIT $limitplus ";
                $page_id = $this->mTitle->getArticleID();
 
                $sql = "SELECT rev_id,rev_user," .
@@ -438,8 +442,9 @@ class PageHistory {
                  "FROM $revision $use_index " .
                  "WHERE rev_page=$page_id " .
                  $offsets .
-                 "ORDER BY rev_timestamp $dirs " .
-                 $limits;
+                 "ORDER BY rev_timestamp $dirs ";
+               if ($limit)
+                       $sql = $db->limitResult($sql, $limitplus, 0);
                $res = $db->query($sql, "PageHistory::fetchRevisions");
 
                $result = array();
@@ -480,8 +485,8 @@ class PageHistory {
                $revisions = array_slice($revisions, 0, $limit);
 
                $pageid = $this->mTitle->getArticleID();
-               $latestTimestamp = $this->getLatestOffset( $pageid );
-               $earliestTimestamp = $this->getEarliestOffset( $pageid );
+               $latestTimestamp = wfTimestamp(TS_MW, $this->getLatestOffset( $pageid ));
+               $earliestTimestamp = wfTimestamp(TS_MW, $this->getEarliestOffset( $pageid ));
 
                /*
                 * When we're displaying previous revisions, we need to reverse
@@ -498,8 +503,8 @@ class PageHistory {
                $lowts = $hights = 0;
 
                if( count( $revisions ) ) {
-                       $latestShown = $revisions[0]->rev_timestamp;
-                       $earliestShown = $revisions[count($revisions) - 1]->rev_timestamp;
+                       $latestShown = wfTimestamp(TS_MW, $revisions[0]->rev_timestamp);
+                       $earliestShown = wfTimestamp(TS_MW, $revisions[count($revisions) - 1]->rev_timestamp);
                }
 
                $firsturl = $wgTitle->escapeLocalURL("action=history&limit={$limit}&go=first");
@@ -507,13 +512,14 @@ class PageHistory {
                $firsttext = wfMsgHtml('histfirst');
                $lasttext = wfMsgHtml('histlast');
 
-               $prevurl = $wgTitle->escapeLocalURL("action=history&dir=prev&offset={$latestShown}&limit={$limit}");
-               $nexturl = $wgTitle->escapeLocalURL("action=history&offset={$earliestShown}&limit={$limit}");
+               $prevurl = $wgTitle->escapeLocalURL("action=history&dir=prev&offset=$latestShown&limit={$limit}");
+               $nexturl = $wgTitle->escapeLocalURL("action=history&offset=$earliestShown&limit={$limit}");
 
                $urls = array();
                foreach (array(20, 50, 100, 250, 500) as $num) {
                        $urls[] = "<a href=\"".$wgTitle->escapeLocalURL(
-                               "action=history&offset={$offset}&limit={$num}")."\">".$wgLang->formatNum($num)."</a>";
+                               "action=history&offset=" . wfTimestamp(TS_MW, $offset) .
+                                "&limit={$num}")."\">".$wgLang->formatNum($num)."</a>";
                }
 
                $bits = implode($urls, ' | ');
index 8c6e110..3d94b6c 100644 (file)
@@ -20,7 +20,7 @@ $wgQueryPages = array(
     array( 'DeadendPagesPage',          'Deadendpages'      ),
     array( 'DisambiguationsPage',       'Disambiguations'   ),
     array( 'DoubleRedirectsPage',       'DoubleRedirects'   ),
-    array( 'ListUsersPage',             'Listusers'         ), 
+    array( 'ListUsersPage',             'Listusers'         ),
     array( 'LonelyPagesPage',           'Lonelypages'       ),
     array( 'LongPagesPage',             'Longpages'         ),
     array( 'NewPagesPage',              'Newpages'          ),
@@ -118,7 +118,7 @@ class QueryPage {
        function getPageHeader( ) {
                return '';
        }
-       
+
        /**
         * If using extra form wheely-dealies, return a set of parameters here
         * as an associative array. They will be encoded and added to the paging
@@ -128,7 +128,7 @@ class QueryPage {
        function linkParameters() {
                return array();
        }
-       
+
        /**
         * Some special pages (for example SpecialListusers) might not return the
         * current object formatted, but return the previous one instead.
@@ -151,7 +151,7 @@ class QueryPage {
                }
 
                $querycache = $dbr->tableName( 'querycache' );
-               
+
                if ( $ignoreErrors ) {
                        $ignoreW = $dbw->ignoreErrors( true );
                        $ignoreR = $dbr->ignoreErrors( true );
@@ -236,21 +236,21 @@ class QueryPage {
                                $wgOut->addWikiText( wfMsg( 'perfcached' ) );
                        }
                }
-               
-               $res = $dbr->query( $sql . $this->getOrder() .
-                                   $dbr->limitResult( $limit,$offset ), $fname );
+
+               $sql = $dbr->limitResult($sql . $this->getOrder(), $limit, $offset);
+               $res = $dbr->query( $sql );
                $num = $dbr->numRows($res);
-               
+
                $sk = $wgUser->getSkin( );
 
                if($shownavigation) {
                        $wgOut->addHTML( $this->getPageHeader() );
                        $top = wfShowingResults( $offset, $num);
                        $wgOut->addHTML( "<p>{$top}\n" );
-       
+
                        # often disable 'next' link when we reach the end
                        if($num < $limit) { $atend = true; } else { $atend = false; }
-                       
+
                        $sl = wfViewPrevNext( $offset, $limit ,
                                $wgContLang->specialPage( $sname ),
                                wfArrayToCGI( $this->linkParameters() ), $atend );
@@ -279,7 +279,7 @@ class QueryPage {
                                        $s .= "<li{$attr}>{$format}</li>\n";
                                }
                        }
-                       
+
                        $dbr->freeResult( $res );
                        $s .= '</ol>';
                        $wgOut->addHTML( $s );
index 69cbb17..48dcf12 100644 (file)
@@ -118,8 +118,9 @@ class RecentChange
                }
 
                # Fixup database timestamps
-               $this->mAttribs['rc_timestamp']=$dbw->timestamp($this->mAttribs['rc_timestamp']);
-               $this->mAttribs['rc_cur_time']=$dbw->timestamp($this->mAttribs['rc_cur_time']);
+               $this->mAttribs['rc_timestamp'] = $dbw->timestamp($this->mAttribs['rc_timestamp']);
+               $this->mAttribs['rc_cur_time'] = $dbw->timestamp($this->mAttribs['rc_cur_time']);
+               $this->mAttribs['rc_id'] = $dbw->nextSequenceValue( 'rc_rc_id_seq' );
 
                # Insert new row
                $dbw->insert( 'recentchanges', $this->mAttribs, $fname );
@@ -357,6 +358,7 @@ class RecentChange
        function loadFromRow( $row )
        {
                $this->mAttribs = get_object_vars( $row );
+               $this->mAttribs["rc_timestamp"] = wfTimestamp(TS_MW, $this->mAttribs["rc_timestamp"]);
                $this->mExtra = array();
        }
 
@@ -364,7 +366,7 @@ class RecentChange
        function loadFromCurRow( $row )
        {
                $this->mAttribs = array(
-                       'rc_timestamp' => $row->rev_timestamp,
+                       'rc_timestamp' => wfTimestamp(TS_MW, $row->rev_timestamp),
                        'rc_cur_time' => $row->rev_timestamp,
                        'rc_user' => $row->rev_user,
                        'rc_user_text' => $row->rev_user_text,
index e7e9b3b..d9cdf55 100644 (file)
@@ -25,8 +25,9 @@ class Revision {
                return Revision::newFromConds(
                        array( 'page_id=rev_page',
                               'rev_id' => IntVal( $id ) ) );
+               return $ret;
        }
-       
+
        /**
         * Load either the current, or a specified, revision
         * that's attached to a given title. If not attached
@@ -50,7 +51,7 @@ class Revision {
                               'page_namespace' => $title->getNamespace(),
                               'page_title'     => $title->getDbkey() ) );
        }
-       
+
        /**
         * Load either the current, or a specified, revision
         * that's attached to a given page. If not attached
@@ -68,13 +69,14 @@ class Revision {
                } else {
                        $matchId = 'page_latest';
                }
-               return Revision::loadFromConds(
+               $ret = Revision::loadFromConds(
                        $db,
                        array( "rev_id=$matchId",
                               'rev_page' => IntVal( $pageid ),
                               'page_id=rev_page' ) );
+               return $ret;
        }
-       
+
        /**
         * Load either the current, or a specified, revision
         * that's attached to a given page. If not attached
@@ -99,7 +101,7 @@ class Revision {
                               'page_namespace' => $title->getNamespace(),
                               'page_title'     => $title->getDbkey() ) );
        }
-       
+
        /**
         * Load the revision for the given title with the given timestamp.
         * WARNING: Timestamps may in some circumstances not be unique,
@@ -120,7 +122,7 @@ class Revision {
                               'page_namespace' => $title->getNamespace(),
                               'page_title'     => $title->getDbkey() ) );
        }
-       
+
        /**
         * Given a set of conditions, fetch a revision.
         *
@@ -138,7 +140,7 @@ class Revision {
                }
                return $row;
        }
-       
+
        /**
         * Given a set of conditions, fetch a revision from
         * the given database connection.
@@ -155,12 +157,14 @@ class Revision {
                        $row = $res->fetchObject();
                        $res->free();
                        if( $row ) {
-                               return new Revision( $row );
+                               $ret = new Revision( $row );
+                               return $ret;
                        }
                }
-               return null;
+               $ret = null;
+               return $ret;
        }
-       
+
        /**
         * Return a wrapper for a series of database rows to
         * fetch all of a given page's revisions in turn.
@@ -176,9 +180,9 @@ class Revision {
                        wfGetDB( DB_SLAVE ),
                        array( 'page_namespace' => $title->getNamespace(),
                               'page_title'     => $title->getDbkey(),
-                              'page_id=rev_page' ) );          
+                              'page_id=rev_page' ) );
        }
-       
+
        /**
         * Return a wrapper for a series of database rows to
         * fetch all of a given page's revisions in turn.
@@ -195,9 +199,9 @@ class Revision {
                        array( 'rev_id=page_latest',
                               'page_namespace' => $title->getNamespace(),
                               'page_title'     => $title->getDbkey(),
-                              'page_id=rev_page' ) );          
+                              'page_id=rev_page' ) );
        }
-       
+
        /**
         * Given a set of conditions, return a ResultWrapper
         * which will return matching database rows with the
@@ -227,9 +231,10 @@ class Revision {
                        $conditions,
                        'Revision::fetchRow',
                        array( 'LIMIT' => 1 ) );
-               return $db->resultObject( $res );
+               $ret = $db->resultObject( $res );
+               return $ret;
        }
-       
+
        /**
         * @param object $row
         * @access private
@@ -245,11 +250,11 @@ class Revision {
                        $this->mMinorEdit = IntVal( $row->rev_minor_edit );
                        $this->mTimestamp =         $row->rev_timestamp;
                        $this->mDeleted   = IntVal( $row->rev_deleted );
-               
+
                        $this->mCurrent   = ( $row->rev_id == $row->page_latest );
                        $this->mTitle     = Title::makeTitle( $row->page_namespace,
                                                              $row->page_title );
-                       
+
                        if( isset( $row->old_text ) ) {
                                $this->mText  = $this->getRevisionText( $row );
                        } else {
@@ -258,7 +263,7 @@ class Revision {
                } elseif( is_array( $row ) ) {
                        // Build a new revision to be saved...
                        global $wgUser;
-                       
+
                        $this->mId        = isset( $row['id']         ) ? IntVal( $row['id']         ) : null;
                        $this->mPage      = isset( $row['page']       ) ? IntVal( $row['page']       ) : null;
                        $this->mTextId    = isset( $row['text_id']    ) ? IntVal( $row['text_id']    ) : null;
@@ -267,36 +272,36 @@ class Revision {
                        $this->mMinorEdit = isset( $row['minor_edit'] ) ? IntVal( $row['minor_edit'] ) : 0;
                        $this->mTimestamp = isset( $row['timestamp']  ) ? StrVal( $row['timestamp']  ) : wfTimestamp( TS_MW );
                        $this->mDeleted   = isset( $row['deleted']    ) ? IntVal( $row['deleted']    ) : 0;
-                       
+
                        // Enforce spacing trimming on supplied text
                        $this->mComment   = isset( $row['comment']    ) ?  trim( StrVal( $row['comment'] ) ) : null;
                        $this->mText      = isset( $row['text']       ) ? rtrim( StrVal( $row['text']    ) ) : null;
-                       
+
                        $this->mTitle     = null; # Load on demand if needed
                        $this->mCurrent   = false;
                } else {
                        wfDebugDieBacktrace( 'Revision constructor passed invalid row format.' );
                }
        }
-       
+
        /**#@+
         * @access public
         */
-       
+
        /**
         * @return int
         */
        function getId() {
                return $this->mId;
        }
-       
+
        /**
         * @return int
         */
        function getTextId() {
                return $this->mTextId;
        }
-       
+
        /**
         * Returns the title of the page associated with this entry.
         * @return Title
@@ -318,49 +323,49 @@ class Revision {
                }
                return $this->mTitle;
        }
-       
+
        /**
         * @return int
         */
        function getPage() {
                return $this->mPage;
        }
-       
+
        /**
         * @return int
         */
        function getUser() {
                return $this->mUser;
        }
-       
+
        /**
         * @return string
         */
        function getUserText() {
                return $this->mUserText;
        }
-       
+
        /**
         * @return string
         */
        function getComment() {
                return $this->mComment;
        }
-       
+
        /**
         * @return bool
         */
        function isMinor() {
                return (bool)$this->mMinorEdit;
        }
-       
+
        /**
         * @return bool
         */
        function isDeleted() {
                return (bool)$this->mDeleted;
        }
-       
+
        /**
         * @return string
         */
@@ -371,21 +376,21 @@ class Revision {
                }
                return $this->mText;
        }
-       
+
        /**
         * @return string
         */
        function getTimestamp() {
-               return $this->mTimestamp;
+               return wfTimestamp(TS_MW, $this->mTimestamp);
        }
-       
+
        /**
         * @return bool
         */
        function isCurrent() {
                return $this->mCurrent;
        }
-       
+
        /**
         * @return Revision
         */
@@ -415,7 +420,7 @@ class Revision {
        function getRevisionText( $row, $prefix = 'old_' ) {
                $fname = 'Revision::getRevisionText';
                wfProfileIn( $fname );
-               
+
                # Get data
                $textField = $prefix . 'text';
                $flagsField = $prefix . 'flags';
@@ -451,7 +456,7 @@ class Revision {
                        # as pages are saved if $wgCompressRevisions is set.
                        $text = gzinflate( $text );
                }
-                       
+
                if( in_array( 'object', $flags ) ) {
                        # Generic compressed storage
                        $obj = unserialize( $text );
@@ -463,7 +468,7 @@ class Revision {
 
                        $text = $obj->getText();
                }
-       
+
                global $wgLegacyEncoding;
                if( $wgLegacyEncoding && !in_array( 'utf-8', $flags ) ) {
                        # Old revisions kept around in a legacy encoding?
@@ -489,11 +494,11 @@ class Revision {
        function compressRevisionText( &$text ) {
                global $wgCompressRevisions;
                $flags = array();
-               
+
                # Revisions not marked this way will be converted
                # on load if $wgLegacyCharset is set in the future.
                $flags[] = 'utf-8';
-               
+
                if( $wgCompressRevisions ) {
                        if( function_exists( 'gzdeflate' ) ) {
                                $text = gzdeflate( $text );
@@ -504,7 +509,7 @@ class Revision {
                }
                return implode( ',', $flags );
        }
-       
+
        /**
         * Insert a new revision into the database, returning the new revision ID
         * number on success and dies horribly on failure.
@@ -515,10 +520,10 @@ class Revision {
        function insertOn( &$dbw ) {
                $fname = 'Revision::insertOn';
                wfProfileIn( $fname );
-               
+
                $mungedText = $this->mText;
                $flags = Revision::compressRevisionText( $mungedText );
-               
+
                # Record the text to the text table
                if( !isset( $this->mTextId ) ) {
                        $old_id = $dbw->nextSequenceValue( 'text_old_id_val' );
@@ -531,7 +536,7 @@ class Revision {
                        );
                        $this->mTextId = $dbw->insertId();
                }
-               
+
                # Record the edit in revisions
                $rev_id = isset( $this->mId )
                        ? $this->mId
@@ -549,13 +554,13 @@ class Revision {
                                'rev_deleted'    => $this->mDeleted,
                        ), $fname
                );
-               
-               $this->mId = $dbw->insertId();
-               
+
+               $this->mId = !is_null($rev_id) ? $rev_id : $dbw->insertId();
+
                wfProfileOut( $fname );
                return $this->mId;
        }
-       
+
        /**
         * Lazy-load the revision's text.
         * Currently hardcoded to the 'text' table storage engine.
@@ -566,13 +571,13 @@ class Revision {
        function loadText() {
                $fname = 'Revision::loadText';
                wfProfileIn( $fname );
-               
+
                $dbr =& wfGetDB( DB_SLAVE );
                $row = $dbr->selectRow( 'text',
                        array( 'old_text', 'old_flags' ),
                        array( 'old_id' => $this->getTextId() ),
                        $fname);
-               
+
                if( !$row ) {
                        $dbw =& wfGetDB( DB_MASTER );
                        $row = $dbw->selectRow( 'text',
@@ -580,10 +585,10 @@ class Revision {
                                array( 'old_id' => $this->getTextId() ),
                                $fname);
                }
-               
+
                $text = Revision::getRevisionText( $row );
                wfProfileOut( $fname );
-               
+
                return $text;
        }
 
@@ -604,7 +609,7 @@ class Revision {
        function newNullRevision( &$dbw, $pageId, $summary, $minor ) {
                $fname = 'Revision::newNullRevision';
                wfProfileIn( $fname );
-               
+
                $current = $dbw->selectRow(
                        array( 'page', 'revision' ),
                        array( 'page_latest', 'rev_text_id' ),
@@ -613,7 +618,7 @@ class Revision {
                                'page_latest=rev_id',
                                ),
                        $fname );
-               
+
                if( $current ) {
                        $revision = new Revision( array(
                                'page'       => $pageId,
@@ -624,10 +629,10 @@ class Revision {
                } else {
                        $revision = null;
                }
-               
+
                wfProfileOut( $fname );
                return $revision;
        }
-       
+
 }
 ?>
index 45642ee..b335a38 100644 (file)
@@ -14,7 +14,7 @@ class SearchEngine {
        var $searchTerms = array();
        var $namespaces = array( 0 );
        var $showRedirects = false;
-       
+
        /**
         * Perform a full text search query and return a result set.
         * If title searches are not supported or disabled, return null.
@@ -40,7 +40,7 @@ class SearchEngine {
        function searchTitle( $term ) {
                return null;
        }
-       
+
        /**
         * If an exact title match can be find, or a very slightly close match,
         * return the title. If no match, returns NULL.
@@ -107,15 +107,15 @@ class SearchEngine {
                if ( $title->getNamespace() == NS_USER ) {
                        return $title;
                }
-               
+
                # Quoted term? Try without the quotes...
                if( preg_match( '/^"([^"]+)"$/', $term, $matches ) ) {
                        return SearchEngine::getNearMatch( $matches[1] );
                }
-               
+
                return NULL;
        }
-       
+
        function legalSearchChars() {
                return "A-Za-z_'0-9\\x80-\\xFF\\-";
        }
@@ -132,7 +132,7 @@ class SearchEngine {
                $this->limit = IntVal( $limit );
                $this->offset = IntVal( $offset );
        }
-       
+
        /**
         * Set which namespaces the search should include.
         * Give an array of namespace index numbers.
@@ -143,7 +143,7 @@ class SearchEngine {
        function setNamespaces( $namespaces ) {
                $this->namespaces = $namespaces;
        }
-       
+
        /**
         * Make a list of searchable namespaces and their canonical names.
         * @return array
@@ -159,7 +159,7 @@ class SearchEngine {
                }
                return $arr;
        }
-       
+
        /**
         * Return a 'cleaned up' search string
         *
@@ -199,7 +199,7 @@ class SearchEngine {
                $search->setLimitOffset(0,0);
                return $search;
        }
-       
+
        /**
         * Create or update the search index record for the given page.
         * Title and text should be pre-processed.
@@ -239,11 +239,11 @@ class SearchResultSet {
        function termMatches() {
                return array();
        }
-       
+
        function numRows() {
                return 0;
        }
-       
+
        /**
         * Return true if results are included in this result set.
         * @return bool
@@ -252,7 +252,7 @@ class SearchResultSet {
        function hasResults() {
                return false;
        }
-       
+
        /**
         * Some search modes return a total hit count for the query
         * in the entire article database. This may include pages
@@ -267,7 +267,7 @@ class SearchResultSet {
        function getTotalHits() {
                return null;
        }
-       
+
        /**
         * Some search modes return a suggested alternate term if there are
         * no exact hits. Returns true if there is one on this set.
@@ -278,7 +278,7 @@ class SearchResultSet {
        function hasSuggestion() {
                return false;
        }
-       
+
        /**
         * Some search modes return a suggested alternate term if there are
         * no exact hits. Check hasSuggestion() first.
@@ -289,7 +289,7 @@ class SearchResultSet {
        function getSuggestion() {
                return '';
        }
-       
+
        /**
         * Fetches next search result, or false.
         * @return SearchResult
@@ -306,7 +306,7 @@ class SearchResult {
        function SearchResult( $row ) {
                $this->mTitle = Title::makeTitle( $row->page_namespace, $row->page_title );
        }
-       
+
        /**
         * @return Title
         * @access public
@@ -314,7 +314,7 @@ class SearchResult {
        function getTitle() {
                return $this->mTitle;
        }
-       
+
        /**
         * @return double or null if not supported
         */
@@ -330,5 +330,11 @@ class SearchEngineDummy {
        function search( $term ) {
                return null;
        }
+       function setLimitOffset($l, $o) {}
+       function legalSearchChars() {}
+       function update() {}
+       function setnamespaces() {}
+       function searchtitle() {}
+       function searchtext() {}
 }
 
index 00e5494..1c82d08 100644 (file)
@@ -33,7 +33,7 @@ class SiteStatsUpdate {
                        }
                }
        }
-       
+
        function doUpdate() {
                global $wgDBname;
                $fname = 'SiteStatsUpdate::doUpdate';
@@ -43,7 +43,7 @@ class SiteStatsUpdate {
                $row = $dbw->selectRow( 'site_stats', '*', false, $fname );
 
                $updates = '';
-               
+
                $this->appendUpdate( $updates, 'ss_total_views', $this->mViews );
                $this->appendUpdate( $updates, 'ss_total_edits', $this->mEdits );
                $this->appendUpdate( $updates, 'ss_good_articles', $this->mGood );
@@ -63,19 +63,19 @@ class SiteStatsUpdate {
                                $res = $dbr->query( $sql, $fname );
                                $userRow = $dbr->fetchObject( $res );
                                $users = $userRow->total + $this->mUsers;
-                               
+
                                if ( $updates ) {
                                        $updates .= ',';
                                }
                                $updates .= "ss_total_pages=$pages, ss_users=$users";
-                       } else {        
+                       } else {
                                $this->appendUpdate( $updates, 'ss_total_pages', $this->mPages );
                                $this->appendUpdate( $updates, 'ss_users', $this->mUsers );
                        }
                }
                if ( $updates ) {
                        $site_stats = $dbw->tableName( 'site_stats' );
-                       $sql = "UPDATE $site_stats SET $updates LIMIT 1";
+                       $sql = $dbw->limitResultForUpdate("UPDATE $site_stats SET $updates", 1);
                        $dbw->query( $sql, $fname );
                }
        }
index dc1fa4a..84dc210 100644 (file)
@@ -644,7 +644,7 @@ END;
                                $n = $wgIP;
 
                                $tl = $this->makeKnownLinkObj( $wgUser->getTalkPage(),
-                                 $wgContLang->getNsText( NS_TALK ) );
+                                 $wgLang->getNsText( NS_TALK ) );
 
                                $s .= $n . ' ('.$tl.')';
                        } else {
@@ -663,7 +663,7 @@ END;
                        $n = $wgUser->getName();
                        $rt = $wgTitle->getPrefixedURL();
                        $tl = $this->makeKnownLinkObj( $wgUser->getTalkPage(),
-                         $wgContLang->getNsText( NS_TALK ) );
+                         $wgLang->getNsText( NS_TALK ) );
 
                        $tl = " ({$tl})";
 
index 0cd2963..3138224 100644 (file)
@@ -540,16 +540,18 @@ class SkinTemplate extends Skin {
                $content_actions = array();
 
                if( $this->iscontent ) {
+                       $subjpage = $this->mTitle->getSubjectPage();
+                       $talkpage = $this->mTitle->getTalkPage();
 
                        $nskey = $this->getNameSpaceKey();
                        $content_actions[$nskey] = $this->tabAction(
-                               $this->mTitle->getSubjectPage(),
+                               $subjpage,
                                $nskey,
                                !$this->mTitle->isTalkPage(),
                                '', true);
 
                        $content_actions['talk'] = $this->tabAction(
-                               $this->mTitle->getTalkPage(),
+                               $talkpage,
                                'talk',
                                $this->mTitle->isTalkPage(),
                                '',
index 8ab20b1..359e6fc 100644 (file)
@@ -155,7 +155,6 @@ function showToplevel ( $namespace = NS_MAIN, $including = false ) {
                $out .= $this->showline ( $inpoint, $outpoint, $namespace, false );
        }
        $out .= '</table>';
-       
        $nsForm = $this->namespaceForm ( $namespace, '', false );
        
        # Is there more?
@@ -178,7 +177,7 @@ function showToplevel ( $namespace = NS_MAIN, $including = false ) {
 
 /**
  * @todo Document
- * @param string $from 
+ * @param string $from
  * @param integer $namespace (Default NS_MAIN)
  */
 function showline( $inpoint, $outpoint, $namespace = NS_MAIN ) {
@@ -191,7 +190,7 @@ function showline( $inpoint, $outpoint, $namespace = NS_MAIN ) {
        $queryparams = ($namespace ? "namespace=$namespace" : '');
        $special = Title::makeTitle( NS_SPECIAL, 'Allpages/' . $inpoint );
        $link = $special->escapeLocalUrl( $queryparams );
-       
+
        $out = wfMsg(
                'alphaindexline',
                "<a href=\"$link\">$inpointf</a></td><td><a href=\"$link\">",
@@ -239,7 +238,7 @@ function showChunk( $namespace = NS_MAIN, $from, $including = false ) {
 
        $n = 0;
        $out = '<table style="background: inherit;" border="0" width="100%">';
-       
+
        $namespaces = $wgContLang->getFormattedNamespaces();
        while( ($n < $this->maxPerPage) && ($s = $dbr->fetchObject( $res )) ) {
                $t = Title::makeTitle( $s->page_namespace, $s->page_title );
@@ -263,7 +262,7 @@ function showChunk( $namespace = NS_MAIN, $from, $including = false ) {
                $out .= '</tr>';
        }
        $out .= '</table>';
-       
+
        if ( $including ) {
                $out2 = '';
        } else {
index 0e55285..5a04b59 100644 (file)
@@ -83,9 +83,10 @@ class contribs_finder {
 
                $sql =  "SELECT rev_timestamp FROM $page, $revision $use_index " .
                        "WHERE page_id = rev_page AND rev_timestamp > '" . $this->offset . "' AND " .
-                       "rev_user_text = " . $this->dbr->addQuotes($this->username) .
-                       $nscond;
-               $sql .= " ORDER BY rev_timestamp ASC LIMIT " . ($this->limit+1);
+                       "rev_user_text = " . $this->dbr->addQuotes($this->username)
+                       . $nscond
+               $sql .= " ORDER BY rev_timestamp ASC";
+               $sql = $this->dbr->limitResult($sql, $this->limit, 0);
                $res = $this->dbr->query($sql);
                $rows = array();
                while ($obj = $this->dbr->fetchObject($res))
@@ -101,9 +102,10 @@ class contribs_finder {
                $nscond = $this->get_namespace_cond();
                $sql =  "SELECT rev_timestamp FROM $page, $revision $use_index " .
                        "WHERE page_id = rev_page AND " .
-                       "rev_user_text = " . $this->dbr->addQuotes($this->username) .
-                       $nscond;
-               $sql .= " ORDER BY rev_timestamp ASC LIMIT " . $this->limit;
+                       "rev_user_text = " . $this->dbr->addQuotes($this->username)
+                       . $nscond
+               $sql .= " ORDER BY rev_timestamp ASC";
+               $sql = $this->dbr->limitResult($sql, $this->limit + 1, 0);
                $res = $this->dbr->query($sql);
                $rows = array();
                while ($obj = $this->dbr->fetchObject($res))
@@ -130,7 +132,8 @@ class contribs_finder {
                        rev_deleted
                        FROM $page,$revision $use_index
                        WHERE page_id=rev_page AND $userCond $nscond $offsetQuery
-                       ORDER BY rev_timestamp DESC $limitQuery";
+                       ORDER BY rev_timestamp DESC";
+               $sql = $this->dbr->limitResult($sql, $this->limit, 0);
                return $sql;
        }
 
@@ -369,7 +372,7 @@ function ucListEdit( $sk, $row ) {
        $histlink='('.$sk->makeKnownLinkObj( $page, $messages['hist'], 'action=history' ) . ')';
 
        $comment = $sk->commentBlock( $row->rev_comment, $page );
-       $d = $wgLang->timeanddate( $row->rev_timestamp, true );
+       $d = $wgLang->timeanddate( wfTimestamp(TS_MW, $row->rev_timestamp), true );
 
        if( $row->rev_minor_edit ) {
                $mflag = '<span class="minor">' . $messages['minoreditletter'] . '</span> ';
index 7a7b046..8e59e93 100644 (file)
@@ -1,17 +1,17 @@
 <?php
 # Copyright (C) 2004 Brion Vibber <brion@pobox.com>
 # http://www.mediawiki.org/
-# 
+#
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or 
+# the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
+#
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License along
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
@@ -44,7 +44,7 @@ function wfSpecialLog( $par = '' ) {
 class LogReader {
        var $db, $joinClauses, $whereClauses;
        var $type = '', $user = '', $title = null;
-       
+
        /**
         * @param WebRequest $request For internal use use a FauxRequest object to pass arbitrary parameters.
         */
@@ -52,7 +52,7 @@ class LogReader {
                $this->db =& wfGetDB( DB_SLAVE );
                $this->setupQuery( $request );
        }
-       
+
        /**
         * Basic setup and applies the limiting factors from the WebRequest object.
         * @param WebRequest $request
@@ -63,16 +63,16 @@ class LogReader {
                $user = $this->db->tableName( 'user' );
                $this->joinClauses = array( "LEFT OUTER JOIN $page ON log_namespace=page_namespace AND log_title=page_title" );
                $this->whereClauses = array( 'user_id=log_user' );
-               
+
                $this->limitType( $request->getVal( 'type' ) );
                $this->limitUser( $request->getText( 'user' ) );
                $this->limitTitle( $request->getText( 'page' ) );
                $this->limitTime( $request->getVal( 'from' ), '>=' );
                $this->limitTime( $request->getVal( 'until' ), '<=' );
-               
+
                list( $this->limit, $this->offset ) = $request->getLimitOffset();
        }
-       
+
        /**
         * Set the log reader to return only entries of the given type.
         * @param string $type A log type ('upload', 'delete', etc)
@@ -86,7 +86,7 @@ class LogReader {
                $safetype = $this->db->strencode( $type );
                $this->whereClauses[] = "log_type='$safetype'";
        }
-       
+
        /**
         * Set the log reader to return only entries by the given user.
         * @param string $name Valid user name
@@ -102,7 +102,7 @@ class LogReader {
                $user = $this->db->tableName( 'user' );
                $this->whereClauses[] = "user_name='$safename'";
        }
-       
+
        /**
         * Set the log reader to return only entries affecting the given page.
         * (For the block and rights logs, this is a user page.)
@@ -119,7 +119,7 @@ class LogReader {
                $ns = $title->getNamespace();
                $this->whereClauses[] = "log_namespace=$ns AND log_title='$safetitle'";
        }
-       
+
        /**
         * Set the log reader to return only entries in a given time range.
         * @param string $time Timestamp of one endpoint
@@ -134,7 +134,7 @@ class LogReader {
                $safetime = $this->db->strencode( wfTimestamp( TS_MW, $time ) );
                $this->whereClauses[] = "log_timestamp $direction '$safetime'";
        }
-       
+
        /**
         * Build an SQL query from all the set parameters.
         * @return string the SQL query
@@ -154,32 +154,33 @@ class LogReader {
                        $sql .= " WHERE " . implode( ' AND ', $this->whereClauses );
                }
                $sql .= " ORDER BY log_timestamp DESC ";
-               $sql .= $this->db->limitResult( $this->limit, $this->offset );
+               $sql = $this->db->limitResult( $sql, $this->limit, $this->offset );
                return $sql;
        }
-       
+
        /**
         * Execute the query and start returning results.
         * @return ResultWrapper result object to return the relevant rows
         */
        function getRows() {
-               return $this->db->resultObject( $this->db->query( $this->getQuery() ) );
+               $res = $this->db->query( $this->getQuery() );
+               return $this->db->resultObject( $res );
        }
-       
+
        /**
         * @return string The query type that this LogReader has been limited to.
         */
        function queryType() {
                return $this->type;
        }
-       
+
        /**
         * @return string The username type that this LogReader has been limited to, if any.
         */
        function queryUser() {
                return $this->user;
        }
-       
+
        /**
         * @return string The text of the title that this LogReader has been limited to.
         */
@@ -203,7 +204,7 @@ class LogViewer {
         */
        var $reader;
        var $numResults = 0;
-       
+
        /**
         * @param LogReader &$reader where to get our data from
         */
@@ -212,7 +213,7 @@ class LogViewer {
                $this->skin =& $wgUser->getSkin();
                $this->reader =& $reader;
        }
-       
+
        /**
         * Take over the whole output page in $wgOut with the log display.
         */
@@ -230,7 +231,7 @@ class LogViewer {
         * Load the data from the linked LogReader
         * Preload the link cache
         * Initialise numResults
-        * 
+        *
         * Must be called before calling showPrevNext
         *
         * @return object database result set
@@ -260,7 +261,7 @@ class LogViewer {
                return $result;
        }
 
-       
+
        /**
         * Output just the list of entries given by the linked LogReader,
         * with extraneous UI elements. Use for displaying log fragments in
@@ -270,7 +271,7 @@ class LogViewer {
        function showList( &$out ) {
                $this->doShowList( $out, $this->getLogRows() );
        }
-       
+
        function doShowList( &$out, $result ) {
                // Rewind result pointer and go through it again, making the HTML
                $html='';
@@ -285,7 +286,7 @@ class LogViewer {
                $result->free();
                $out->addHTML( $html );
        }
-       
+
        /**
         * @param Object $s a single row from the result set
         * @return string Formatted HTML list item
@@ -295,7 +296,7 @@ class LogViewer {
                global $wgLang, $wgLinkCache;
                $title = Title::makeTitle( $s->log_namespace, $s->log_title );
                $user = Title::makeTitleSafe( NS_USER, $s->user_name );
-               $time = $wgLang->timeanddate( $s->log_timestamp, true );
+               $time = $wgLang->timeanddate( wfTimestamp(TS_MW, $s->log_timestamp), true );
 
                // Enter the existence or non-existence of this page into the link cache,
                // for faster makeLinkObj() in LogPage::actionText()
@@ -304,7 +305,7 @@ class LogViewer {
                } else {
                        $wgLinkCache->addBadLinkObj( $title );
                }
-               
+
                $userLink = $this->skin->makeLinkObj( $user, htmlspecialchars( $s->user_name ) );
                $comment = $this->skin->commentBlock( $s->log_comment );
                $paramArray = LogPage::extractParams( $s->log_params );
@@ -314,7 +315,7 @@ class LogViewer {
                        $destTitle = Title::newFromText( $paramArray[0] );
                        if ( $destTitle ) {
                                $revert = '(' . $this->skin->makeKnownLinkObj( $specialTitle, wfMsg( 'revertmove' ),
-                                       'wpOldTitle=' . urlencode( $destTitle->getPrefixedDBkey() ) . 
+                                       'wpOldTitle=' . urlencode( $destTitle->getPrefixedDBkey() ) .
                                        '&wpNewTitle=' . urlencode( $title->getPrefixedDBkey() ) .
                                        '&wpReason=' . urlencode( wfMsgForContent( 'revertmove' ) ) .
                                        '&wpMovetalk=0' ) . ')';
@@ -325,7 +326,7 @@ class LogViewer {
                $out = "<li>$time $userLink $action $comment $revert</li>\n";
                return $out;
        }
-       
+
        /**
         * @param OutputPage &$out where to send output
         * @private
@@ -337,7 +338,7 @@ class LogViewer {
                        $out->addWikiText( LogPage::logHeader( $type ) );
                }
        }
-       
+
        /**
         * @param OutputPage &$out where to send output
         * @private
@@ -355,7 +356,7 @@ class LogViewer {
                        "<input type='submit' value=\"" . wfMsg( 'allpagessubmit' ) . "\" />" .
                        "</form>" );
        }
-       
+
        /**
         * @return string Formatted HTML
         * @private
@@ -370,7 +371,7 @@ class LogViewer {
                $out .= "</select>\n";
                return $out;
        }
-       
+
        /**
         * @return string Formatted HTML
         * @private
@@ -379,7 +380,7 @@ class LogViewer {
                $user = htmlspecialchars( $this->reader->queryUser() );
                return wfMsg('specialloguserlabel') . "<input type='text' name='user' size='12' value=\"$user\" />\n";
        }
-       
+
        /**
         * @return string Formatted HTML
         * @private
@@ -388,7 +389,7 @@ class LogViewer {
                $title = htmlspecialchars( $this->reader->queryTitle() );
                return wfMsg('speciallogtitlelabel') . "<input type='text' name='page' size='20' value=\"$title\" />\n";
        }
-       
+
        /**
         * @param OutputPage &$out where to send output
         * @private
@@ -401,7 +402,7 @@ class LogViewer {
                $pieces[] = 'page=' . urlencode( $this->reader->queryTitle() );
                $bits = implode( '&', $pieces );
                list( $limit, $offset ) = $wgRequest->getLimitOffset();
-               
+
                # TODO: use timestamps instead of offsets to make it more natural
                # to go huge distances in time
                $html = wfViewPrevNext( $offset, $limit,
index 6e99b3f..91e59ff 100644 (file)
@@ -378,7 +378,7 @@ class PreferencesForm {
                $checked = $wgUser->getOption( $tname ) == 1 ? ' checked="checked"' : '';
                $trailer = $trailer ? $trailer : '';
                return "<div class='toggle'><input type='checkbox' value='1' id=\"$tname\" name=\"wpOp$tname\"$checked />" .
-                       " <span class='toggletext'><label for=\"$tname\">$ttext</label>$trailer</span></div>";
+                       " <span class='toggletext'><label for=\"$tname\">$ttext</label>$trailer</span></div>\n";
        }
 
        function getToggles( $items ) {
@@ -769,7 +769,7 @@ class PreferencesForm {
 <option value=\"1\"$s1>$msgUnderlinealways</option>
 <option value=\"2\"$s2>$msgUnderlinedefault</option>
 </select>
-</label></div>
+</label>
 ");
                foreach ( $togs as $tname ) {
                        if( !array_key_exists( $tname, $this->mUsedToggles ) ) {
index 82d580c..53138af 100644 (file)
@@ -7,7 +7,7 @@
 /**
  * Constructor
  *
- * @param string $par the namespace to get a random page from (default NS_MAIN), 
+ * @param string $par the namespace to get a random page from (default NS_MAIN),
  *               used as e.g. Special:Randompage/Category
  */
 function wfSpecialRandompage( $par = NS_MAIN ) {
@@ -19,7 +19,7 @@ function wfSpecialRandompage( $par = NS_MAIN ) {
        if ($namespace === false || $namespace < NS_MAIN) {
                $namespace = NS_MAIN;
        }
-       
+
        # NOTE! We use a literal constant in the SQL instead of the RAND()
        # function because RAND() will return a different value for every row
        # in the table. That's both very slow and returns results heavily
@@ -28,10 +28,10 @@ function wfSpecialRandompage( $par = NS_MAIN ) {
        #
        # Using a literal constant means the whole thing gets optimized on
        # the index, and the comparison is both fast and fair.
-       
+
        # interpolation and sprintf() can muck up with locale-specific decimal separator
        $randstr = wfRandom();
-       
+
        $db =& wfGetDB( DB_SLAVE );
        $use_index = $db->useIndexClause( 'page_random' );
        $page = $db->tableName( 'page' );
@@ -41,14 +41,14 @@ function wfSpecialRandompage( $par = NS_MAIN ) {
                FROM $page $use_index
                WHERE page_namespace=$namespace AND page_is_redirect=0 $extra
                AND page_random>$randstr
-               ORDER BY page_random
-               LIMIT 1";
+               ORDER BY page_random";
+       $sql = $db->limitResult($sql, 1, 0);
        $res = $db->query( $sql, $fname );
-       
+
        $title = null;
        if( $s = $db->fetchObject( $res ) ) {
                $title =& Title::makeTitle( $namespace, $s->page_title );
-       }       
+       }
        if( is_null( $title ) ) {
                # That's not supposed to happen :)
                $title = Title::newFromText( wfMsg( 'mainpage' ) );
index 653cf84..e31758f 100644 (file)
@@ -39,7 +39,7 @@ function wfSpecialRecentchanges( $par, $specialPage ) {
        );
 
        extract($defaults);
-       
+
 
        $days = $wgUser->getOption( 'rcdays' );
        if ( !$days ) { $days = $defaults['days']; }
@@ -52,9 +52,9 @@ function wfSpecialRecentchanges( $par, $specialPage ) {
        $limit = $wgRequest->getInt( 'limit', $limit );
 
        /* order of selection: url > preferences > default */
-       $hideminor = $wgRequest->getBool( 'hideminor', $wgUser->getOption( 'hideminor') ? true : $defaults['hideminor'] );      
+       $hideminor = $wgRequest->getBool( 'hideminor', $wgUser->getOption( 'hideminor') ? true : $defaults['hideminor'] );
+
 
-       
        # As a feed, use limited settings only
        if( $feedFormat ) {
                global $wgFeedLimit;
@@ -69,7 +69,7 @@ function wfSpecialRecentchanges( $par, $specialPage ) {
                $hidebots = $wgRequest->getBool( 'hidebots', $defaults['hidebots'] );
                $hideliu = $wgRequest->getBool( 'hideliu', $defaults['hideliu'] );
                $hidepatrolled = $wgRequest->getBool( 'hidepatrolled', $defaults['hidepatrolled'] );
-               $from = $wgRequest->getVal( 'from', $defaults['from'] );        
+               $from = $wgRequest->getVal( 'from', $defaults['from'] );
 
                # Get query parameters from path
                if( $par ) {
@@ -104,7 +104,7 @@ function wfSpecialRecentchanges( $par, $specialPage ) {
        $dbr =& wfGetDB( DB_SLAVE );
        extract( $dbr->tableNames( 'recentchanges', 'watchlist' ) );
 
-       
+
        $cutoff_unixtime = time() - ( $days * 86400 );
        $cutoff_unixtime = $cutoff_unixtime - ($cutoff_unixtime % 86400);
        $cutoff = $dbr->timestamp( $cutoff_unixtime );
@@ -113,7 +113,7 @@ function wfSpecialRecentchanges( $par, $specialPage ) {
        } else {
                $from = $defaults['from'];
        }
-               
+
        # 10 seconds server-side caching max
        $wgOut->setSquidMaxage( 10 );
 
@@ -138,10 +138,11 @@ function wfSpecialRecentchanges( $par, $specialPage ) {
        $uid = $wgUser->getID();
 
        // Perform query
-       $sql2 = "SELECT *" . ($uid ? ",wl_user,wl_notificationtimestamp" : "") . " FROM $recentchanges " .
+       $sql2 = "SELECT * FROM $recentchanges " .
          ($uid ? "LEFT OUTER JOIN $watchlist ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace " : "") .
          "WHERE rc_timestamp > '{$cutoff}' {$hidem} " .
-         "ORDER BY rc_timestamp DESC LIMIT {$limit}";
+         "ORDER BY rc_timestamp DESC";
+       $sql2 = $dbr->limitResult($sql2, $limit, 0);
        $res = $dbr->query( $sql2, $fname );
 
        // Fetch results, prepare a batch link existence check query
@@ -172,7 +173,7 @@ function wfSpecialRecentchanges( $par, $specialPage ) {
                // Output header
                if ( !$specialPage->including() ) {
                        $wgOut->addWikiText( wfMsgForContent( "recentchangestext" ) );
-               
+
                        // Dump everything here
                        $nondefaults = array();
                
@@ -235,15 +236,15 @@ function wfSpecialRecentchanges( $par, $specialPage ) {
 function rcOutputFeed( $rows, $feedFormat, $limit, $hideminor, $lastmod ) {
        global $messageMemc, $wgDBname, $wgFeedCacheTimeout;
        global $wgFeedClasses, $wgTitle, $wgSitename, $wgContLanguageCode;
-       
+
        if( !isset( $wgFeedClasses[$feedFormat] ) ) {
                wfHttpError( 500, "Internal Server Error", "Unsupported feed type." );
                return false;
        }
-       
+
        $timekey = "$wgDBname:rcfeed:$feedFormat:timestamp";
        $key = "$wgDBname:rcfeed:$feedFormat:limit:$limit:minor:$hideminor";
-       
+
        $feedTitle = $wgSitename . ' - ' . wfMsgForContent( 'recentchanges' ) .
                ' [' . $wgContLanguageCode . ']';
        $feed = new $wgFeedClasses[$feedFormat](
@@ -284,7 +285,7 @@ function rcOutputFeed( $rows, $feedFormat, $limit, $hideminor, $lastmod ) {
                rcDoOutputFeed( $rows, $feed );
                $cachedFeed = ob_get_contents();
                ob_end_flush();
-               
+
                $expire = 3600 * 24; # One day
                $messageMemc->set( $key, $cachedFeed );
                $messageMemc->set( $timekey, wfTimestamp( TS_MW ), $expire );
@@ -294,9 +295,9 @@ function rcOutputFeed( $rows, $feedFormat, $limit, $hideminor, $lastmod ) {
 
 function rcDoOutputFeed( $rows, &$feed ) {
        global $wgSitename, $wgFeedClasses, $wgContLanguageCode;
-       
+
        $feed->outHeader();
-       
+
        # Merge adjacent edits by one user
        $sorted = array();
        $n = 0;
@@ -312,7 +313,7 @@ function rcDoOutputFeed( $rows, &$feed ) {
                }
                $first = false;
        }
-       
+
        foreach( $sorted as $obj ) {
                $title = Title::makeTitle( $obj->rc_namespace, $obj->rc_title );
                $talkpage = $title->getTalkPage();
@@ -431,11 +432,11 @@ function rcOptionsPanel( $defaults, $nondefaults ) {
                array( 'hidepatrolled' => 1-$options['hidepatrolled'] ), $nondefaults);
 
        $hl = wfMsg( 'showhideminor', $minorLink, $botLink, $liuLink, $patrLink );
-       
+
        // show from this onward link
        $now = $wgLang->timeanddate( wfTimestampNow(), true );
        $tl =  makeOptionsLink( $now, array( 'from' => wfTimestampNow()), $nondefaults );
-       
+
        $rclinks = wfMsg( 'rclinks', $cl, $dl, $hl );
        $rclistfrom = wfMsg( 'rclistfrom', $tl );
        return "$note<br />$rclinks<br />$rclistfrom";
@@ -486,16 +487,16 @@ function rcNamespaceForm ( $namespace, $invert, $nondefaults ) {
 function rcFormatDiff( $row ) {
        $fname = 'rcFormatDiff';
        wfProfileIn( $fname );
-       
+
        require_once( 'DifferenceEngine.php' );
        $comment = "<p>" . htmlspecialchars( $row->rc_comment ) . "</p>\n";
-       
+
        if( $row->rc_namespace >= 0 ) {
                global $wgContLang;
-               
+
                #$diff =& new DifferenceEngine( $row->rc_this_oldid, $row->rc_last_oldid, $row->rc_id );
                #$diff->showDiffPage();
-               
+
                $titleObj = Title::makeTitle( $row->rc_namespace, $row->rc_title );
                $dbr =& wfGetDB( DB_SLAVE );
                $newrev =& Revision::newFromTitle( $titleObj, $row->rc_this_oldid );
@@ -516,11 +517,11 @@ function rcFormatDiff( $row ) {
                                return $comment . $diffText;
                        }
                        $oldtext = $oldrev->getText();
-                               
+
                        # Old entries may contain illegal characters
                        # which will damage output
                        $oldtext = UtfNormal::cleanUp( $oldtext );
-                       
+
                        global $wgFeedDiffCutoff;
                        if( strlen( $newtext ) > $wgFeedDiffCutoff ||
                                strlen( $oldtext ) > $wgFeedDiffCutoff ) {
@@ -539,16 +540,16 @@ function rcFormatDiff( $row ) {
                        }
                        wfProfileOut( "$fname-dodiff" );
                } else {
-                       $diffText = '<p><b>' . wfMsg( 'newpage' ) . '</b></p>' . 
+                       $diffText = '<p><b>' . wfMsg( 'newpage' ) . '</b></p>' .
                                '<div>' . nl2br( htmlspecialchars( $newtext ) ) . '</div>';
                }
-               
+
                wfProfileOut( $fname );
                return $comment . $diffText;
        }
-       
+
        wfProfileOut( $fname );
-       return $comment;        
+       return $comment;
 }
 
 ?>
index 09ef867..eb73ff3 100644 (file)
@@ -25,14 +25,14 @@ function wfSpecialUndelete( $par ) {
  */
 class PageArchive {
        var $title;
-       
+
        function PageArchive( &$title ) {
                if( is_null( $title ) ) {
                        wfDebugDieBacktrace( 'Archiver() given a null title.');
                }
                $this->title =& $title;
        }
-       
+
        /**
         * List all deleted pages recorded in the archive table. Returns result
         * wrapper with (ar_namespace, ar_title, count) fields, ordered by page
@@ -44,12 +44,12 @@ class PageArchive {
                $dbr =& wfGetDB( DB_SLAVE );
                $archive = $dbr->tableName( 'archive' );
 
-               $sql = "SELECT ar_namespace,ar_title, COUNT(*) AS count FROM $archive " . 
+               $sql = "SELECT ar_namespace,ar_title, COUNT(*) AS count FROM $archive " .
                  "GROUP BY ar_namespace,ar_title ORDER BY ar_namespace,ar_title";
 
                return $dbr->resultObject( $dbr->query( $sql, 'PageArchive::listAllPages' ) );
        }
-       
+
        /**
         * List the revisions of the given page. Returns result wrapper with
         * (ar_minor_edit, ar_timestamp, ar_user, ar_user_text, ar_comment) fields.
@@ -58,14 +58,16 @@ class PageArchive {
         */
        function listRevisions() {
                $dbr =& wfGetDB( DB_SLAVE );
-               return $dbr->resultObject( $dbr->select( 'archive',
+               $res = $dbr->select( 'archive',
                        array( 'ar_minor_edit', 'ar_timestamp', 'ar_user', 'ar_user_text', 'ar_comment' ),
                        array( 'ar_namespace' => $this->title->getNamespace(),
                               'ar_title' => $this->title->getDBkey() ),
                        'PageArchive::listRevisions',
-                       array( 'ORDER BY' => 'ar_timestamp DESC' ) ) );
+                       array( 'ORDER BY' => 'ar_timestamp DESC' ) );
+               $ret = $dbr->resultObject( $res );
+               return $ret;
        }
-       
+
        /**
         * Fetch (and decompress if necessary) the stored text for the deleted
         * revision of the page with the given timestamp.
@@ -94,7 +96,7 @@ class PageArchive {
                        return Revision::getRevisionText( $text );
                }
        }
-       
+
        /**
         * Fetch (and decompress if necessary) the stored text of the most
         * recently edited deleted revision of the page.
@@ -117,7 +119,7 @@ class PageArchive {
                        return NULL;
                }
        }
-       
+
        /**
         * Quick check if any archived revisions are present for the page.
         * @return bool
@@ -129,7 +131,7 @@ class PageArchive {
                               'ar_title' => $this->title->getDBkey() ) );
                return ($n > 0);
        }
-       
+
        /**
         * This is the meaty bit -- restores archived revisions of the given page
         * to the cur/old tables. If the page currently exists, all revisions will
@@ -178,18 +180,18 @@ class PageArchive {
                        $previousRevId = 0;
                        $previousTimestamp = 0;
                }
-               
+
                if( $restoreAll ) {
-                       $oldones = '1'; # All revisions...
+                       $oldones = '1 = 1'; # All revisions...
                } else {
                        $oldts = implode( ',',
                                array_map( array( &$dbw, 'addQuotes' ),
                                        array_map( array( &$dbw, 'timestamp' ),
                                                $timestamps ) ) );
-                       
+
                        $oldones = "ar_timestamp IN ( {$oldts} )";
                }
-               
+
                /**
                 * Restore each revision...
                 */
@@ -227,28 +229,28 @@ class PageArchive {
                                ) );
                        $revision->insertOn( $dbw );
                }
-               
+
                if( $revision ) {
                        # FIXME: Update latest if newer as well...
                        if( $newid ) {
                                # FIXME: update article count if changed...
                                $article->updateRevisionOn( $dbw, $revision, $previousRevId );
-                               
+
                                # Finally, clean up the link tables
                                $wgLinkCache = new LinkCache();
                                # Select for update
                                $wgLinkCache->forUpdate( true );
-                               
+
                                # Create a dummy OutputPage to update the outgoing links
                                $dummyOut = new OutputPage();
                                $dummyOut->addWikiText( $revision->getText() );
 
                                $u = new LinksUpdate( $newid, $this->title->getPrefixedDBkey() );
                                array_push( $wgDeferredUpdateList, $u );
-                               
+
                                #TODO: SearchUpdate, etc.
                        }
-                               
+
                        if( $newid ) {
                                Article::onArticleCreate( $this->title );
                        } else {
@@ -265,7 +267,7 @@ class PageArchive {
                                'ar_title' => $this->title->getDBkey(),
                                $oldones ),
                        $fname );
-               
+
                # Touch the log!
                $log = new LogPage( 'delete' );
                if( $restoreAll ) {
@@ -332,10 +334,10 @@ class UndeleteForm {
        /* private */ function showList() {
                global $wgLang, $wgContLang, $wgUser, $wgOut;
                $fname = "UndeleteForm::showList";
-               
-               # List undeletable articles    
+
+               # List undeletable articles
                $result = PageArchive::listAllPages();
-               
+
                $wgOut->setPagetitle( wfMsg( "undeletepage" ) );
                $wgOut->addWikiText( wfMsg( "undeletepagetext" ) );
 
@@ -343,7 +345,7 @@ class UndeleteForm {
                $undelete =& Title::makeTitle( NS_SPECIAL, 'Undelete' );
                $wgOut->addHTML( "<ul>\n" );
                while( $row = $result->fetchObject() ) {
-                       $n = ($row->ar_namespace ? 
+                       $n = ($row->ar_namespace ?
                                ($wgContLang->getNsText( $row->ar_namespace ) . ":") : "").
                                $row->ar_title;
                        $link = $sk->makeKnownLinkObj( $undelete,
@@ -354,10 +356,10 @@ class UndeleteForm {
                }
                $result->free();
                $wgOut->addHTML( "</ul>\n" );
-               
+
                return true;
        }
-       
+
        /* private */ function showRevision( $timestamp ) {
                global $wgLang, $wgUser, $wgOut;
                $fname = "UndeleteForm::showRevision";
@@ -366,7 +368,7 @@ class UndeleteForm {
 
                $archive =& new PageArchive( $this->mTargetObj );
                $text = $archive->getRevisionText( $timestamp );
-               
+
                $wgOut->setPagetitle( wfMsg( "undeletepage" ) );
                $wgOut->addWikiText( "(" . wfMsg( "undeleterevision",
                        $wgLang->date( $timestamp ) ) . ")\n<hr />\n" . $text );
@@ -374,7 +376,7 @@ class UndeleteForm {
 
        /* private */ function showHistory() {
                global $wgLang, $wgUser, $wgOut;
-               
+
                $sk = $wgUser->getSkin();
                $wgOut->setPagetitle( wfMsg( "undeletepage" ) );
 
@@ -388,13 +390,13 @@ class UndeleteForm {
 
                # List all stored revisions
                $revisions = $archive->listRevisions();
-               
+
                $titleObj = Title::makeTitle( NS_SPECIAL, "Undelete" );
                $action = $titleObj->escapeLocalURL( "action=submit" );
                $encTarget = htmlspecialchars( $this->mTarget );
                $button = htmlspecialchars( wfMsg("undeletebtn") );
                $token = htmlspecialchars( $wgUser->editToken() );
-               
+
                $wgOut->addHTML("
        <form id=\"undelete\" method=\"post\" action=\"{$action}\">
        <input type=\"hidden\" name=\"target\" value=\"{$encTarget}\" />
@@ -411,7 +413,7 @@ class UndeleteForm {
                                        array( 'page' => $this->mTargetObj->getPrefixedText(),
                                               'type' => 'delete' ) ) ) );
                $logViewer->showList( $wgOut );
-               
+
                # The page's stored (deleted) history:
                $wgOut->addHTML( "<h2>" . htmlspecialchars( wfMsg( "history" ) ) . "</h2>\n" );
                $wgOut->addHTML("<ul>");
@@ -420,7 +422,7 @@ class UndeleteForm {
                        $ts = wfTimestamp( TS_MW, $row->ar_timestamp );
                        $checkBox = "<input type=\"checkbox\" name=\"ts$ts\" value=\"1\" />";
                        $pageLink = $sk->makeKnownLinkObj( $titleObj,
-                               $wgLang->timeanddate( $row->ar_timestamp, true ),
+                               $wgLang->timeanddate( $ts, true ),
                                "target=$target&timestamp=$ts" );
                        $userLink = htmlspecialchars( $row->ar_user_text );
                        if( $row->ar_user ) {
@@ -438,7 +440,7 @@ class UndeleteForm {
                }
                $revisions->free();
                $wgOut->addHTML("</ul>\n</form>");
-               
+
                return true;
        }
 
index 4d7994b..e005c63 100644 (file)
@@ -145,7 +145,8 @@ class Title {
                        return $t;
                } else {
                        wfProfileOut( $fname );
-                       return NULL;
+                       $ret = NULL;
+                       return $ret;
                }
        }
 
@@ -1139,7 +1140,6 @@ class Title {
         */
        function getArticleID( $flags = 0 ) {
                global $wgLinkCache;
-
                if ( $flags & GAID_FOR_UPDATE ) {
                        $oldUpdate = $wgLinkCache->forUpdate( true );
                        $this->mArticleID = $wgLinkCache->addLinkObj( $this );
@@ -1149,6 +1149,7 @@ class Title {
                                $this->mArticleID = $wgLinkCache->addLinkObj( $this );
                        }
                }
+wfdebug("title: articleid = ".$this->mArticleID."\n");
                return $this->mArticleID;
        }
 
@@ -2088,7 +2089,8 @@ class Title {
                while( $row = $dbw->fetchObject( $res ) ) {
                        $toucharr[] = $row->pl_from;
                }
-
+               if (!count($toucharr))
+                       return;
                $dbw->update( 'page', /* SET */ array( 'page_touched' => $dbw->timestamp() ),
                                                        /* WHERE */ array( 'page_id' => $toucharr ),$fname);
        }
index 9022831..6a97109 100644 (file)
@@ -756,7 +756,7 @@ class User {
                                        array( 'wl_title'     => $this->getTitleKey(),
                                                   'wl_namespace' => NS_USER_TALK,
                                                   'wl_user'      => $this->mId,
-                                                  'wl_notificationtimestamp != 0' ),
+                                                  'wl_notificationtimestamp ' . $dbr->notNullTimestamp() ),
                                        'User::getNewtalk' );
                                if( $dbr->numRows($res) > 0 ) {
                                        $this->mNewtalk = 1;
@@ -1151,7 +1151,7 @@ class User {
                        $dbw =& wfGetDB( DB_MASTER );
                        $success = $dbw->update( 'watchlist',
                                        array( /* SET */
-                                               'wl_notificationtimestamp' => 0
+                                               'wl_notificationtimestamp' => NULL
                                        ), array( /* WHERE */
                                                'wl_title' => $title->getDBkey(),
                                                'wl_namespace' => $title->getNamespace(),
index 274c066..d032cc2 100644 (file)
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  * http://www.gnu.org/copyleft/gpl.html
- * 
+ *
  * @author <brion@pobox.com>
  * @author <mail@tgries.de>
- * 
+ *
  * @package MediaWiki
  */
 
@@ -49,12 +49,12 @@ function wfRFC822Phrase( $phrase ) {
  */
 function userMailer( $to, $from, $subject, $body, $replyto=false ) {
        global $wgUser, $wgSMTP, $wgOutputEncoding, $wgErrorString, $wgEmergencyContact;
-       
+
        if (is_array( $wgSMTP )) {
                require_once( 'Mail.php' );
-               
+
                $timestamp = time();
-       
+
                $headers['From'] = $from;
                if ( $replyto ) {
                        $headers['Reply-To'] = $replyto;
@@ -65,13 +65,13 @@ function userMailer( $to, $from, $subject, $body, $replyto=false ) {
                $headers['Content-transfer-encoding'] = '8bit';
                $headers['Message-ID'] = "<{$timestamp}" . $wgUser->getName() . '@' . $wgSMTP['IDHost'] . '>';
                $headers['X-Mailer'] = 'MediaWiki mailer';
-       
+
                // Create the mail object using the Mail::factory method
                $mail_object =& Mail::factory('smtp', $wgSMTP);
                wfDebug( "Sending mail via PEAR::Mail\n" );
                $mailResult =& $mail_object->send($to, $headers, $body);
-               
-               # Based on the result return an error string, 
+
+               # Based on the result return an error string,
                if ($mailResult === true)
                        return '';
                else if (is_object($mailResult))
@@ -130,9 +130,9 @@ function mailErrorHandler( $code, $string ) {
  * same timeoffset in their preferences.
  *
  * Visit the documentation pages under http://meta.wikipedia.com/Enotif
- * 
+ *
  * @package MediaWiki
- * 
+ *
  */
 class EmailNotification {
        /**#@+
@@ -140,9 +140,9 @@ class EmailNotification {
         */
        var $to, $subject, $body, $replyto, $from;
        var $user, $title, $timestamp, $summary, $minorEdit, $oldid;
-       
+
        /**#@-*/
-       
+
        /**
         * @todo document
         * @param $currentPage
@@ -153,7 +153,7 @@ class EmailNotification {
         * @param $oldid (default: false)
         */
        function notifyOnPageChange(&$title, $timestamp, $summary, $minorEdit, $oldid=false) {
-       
+
                # we use $wgEmergencyContact as sender's address
                global $wgUser, $wgLang, $wgEmergencyContact;
                global $wgEnotifWatchlist, $wgEnotifMinorEdits;
@@ -165,30 +165,30 @@ class EmailNotification {
 
                $fname = 'UserMailer::notifyOnPageChange';
                wfProfileIn( $fname );
-               
+
                # The following code is only run, if several conditions are met:
                # 1. EmailNotification for pages (other than user_talk pages) must be enabled
                # 2. minor edits (changes) are only regarded if the global flag indicates so
-       
+
                $isUserTalkPage = ($title->getNamespace() == NS_USER_TALK);
                $enotifusertalkpage = ($isUserTalkPage && $wgEnotifUserTalk);
-               $enotifwatchlistpage = (!$isUserTalkPage && $wgEnotifWatchlist);        
+               $enotifwatchlistpage = (!$isUserTalkPage && $wgEnotifWatchlist);
 
 
                if ( ($enotifusertalkpage || $enotifwatchlistpage) && (!$minorEdit || $wgEnotifMinorEdits) ) {
                        $dbr =& wfGetDB( DB_MASTER );
                        extract( $dbr->tableNames( 'watchlist' ) );
-                       $res = $dbr->select( 'watchlist', array( 'wl_user' ), 
+                       $res = $dbr->select( 'watchlist', array( 'wl_user' ),
                                array(
                                        'wl_title' => $title->getDBkey(),
                                        'wl_namespace' => $title->getNamespace(),
                                        'wl_user <> ' . $wgUser->getID(),
-                                       'wl_notificationtimestamp <= 1',
+                                       'wl_notificationtimestamp ' . $dbr->isNullTimestamp(),
                                ), $fname );
 
                        # if anyone is watching ... set up the email message text which is
                        # common for all receipients ...
-                       if ( $dbr->numRows( $res ) > 0 ) { 
+                       if ( $dbr->numRows( $res ) > 0 ) {
                                $this->user &= $wgUser;
                                $this->title =& $title;
                                $this->timestamp = $timestamp;
@@ -198,9 +198,9 @@ class EmailNotification {
 
                                $this->composeCommonMailtext();
                                $watchingUser = new User();
-       
+
                                # ... now do for all watching users ... if the options fit
-                               for ($i = 1; $i <= $dbr->numRows( $res ); $i++) { 
+                               for ($i = 1; $i <= $dbr->numRows( $res ); $i++) {
 
                                        $wuser = $dbr->fetchObject( $res );
                                        $watchingUser->setID($wuser->wl_user);
@@ -218,12 +218,12 @@ class EmailNotification {
                } # if $wgEnotifWatchlist = true
 
                if ( $wgShowUpdatedMarker || $wgEnotifWatchlist ) {
-                       # mark the changed watch-listed page with a timestamp, so that the page is 
+                       # mark the changed watch-listed page with a timestamp, so that the page is
                        # listed with an "updated since your last visit" icon in the watch list, ...
                        $dbw =& wfGetDB( DB_MASTER );
                        $success = $dbw->update( 'watchlist',
                                array( /* SET */
-                                       'wl_notificationtimestamp' => $timestamp
+                                       'wl_notificationtimestamp' => $dbw->timestamp($timestamp)
                                ), array( /* WHERE */
                                        'wl_title' => $title->getDBkey(),
                                        'wl_namespace' => $title->getNamespace(),
@@ -232,7 +232,7 @@ class EmailNotification {
                }
 
        } # function NotifyOnChange
-       
+
        /**
         * @access private
         */
@@ -241,20 +241,20 @@ class EmailNotification {
                global $wgEnotifRevealEditorAddress;
                global $wgEnotifFromEditor;
                global $wgNoReplyAddress;
-               
+
                $summary = ($this->summary == '') ? ' - ' : $this->summary;
                $medit   = ($this->minorEdit) ? wfMsg( 'minoredit' ) : '';
-               
+
                # You as the WikiAdmin and Sysops can make use of plenty of
                # named variables when composing your notification emails while
                # simply editing the Meta pages
-               
+
                $subject = wfMsgForContent( 'enotif_subject' );
                $body    = wfMsgForContent( 'enotif_body' );
                $from    = ''; /* fail safe */
                $replyto = ''; /* fail safe */
                $keys    = array();
-               
+
                # regarding the use of oldid as an indicator for the last visited version, see also
                # http://bugzilla.wikipeda.org/show_bug.cgi?id=603 "Delete + undelete cycle doesn't preserve old_id"
                # However, in the case of a new page which is already watched, we have no previous version to compare
@@ -269,16 +269,15 @@ class EmailNotification {
                        $keys['$OLDID']   = '';
                        $keys['$CHANGEDORCREATED'] = wfMsgForContent( 'created' );
                }
-               
-               $body = strtr( $body, $keys ); 
+
+               $body = strtr( $body, $keys );
                $pagetitle = $this->title->getPrefixedText();
-               
                $keys['$PAGETITLE']          = $pagetitle;
                $keys['$PAGETITLE_URL']      = $this->title->getFullUrl();
                
                $keys['$PAGEMINOREDIT']      = $medit;
                $keys['$PAGESUMMARY']        = $summary;
-       
+
                $subject = strtr( $subject, $keys );
 
                # Reveal the page editor's address as REPLY-TO address only if
@@ -300,13 +299,13 @@ class EmailNotification {
                        $from    = $adminAddress;
                        $replyto = $wgNoReplyAddress;
                }
-       
+
                if( $wgUser->isIP( $name ) ) {
                        #real anon (user:xxx.xxx.xxx.xxx)
                        $anon    = $name . ' (anonymous user)';
                        $anonUrl = wfUrlencode( $name ) . ' (anonymous user)';
                        $subject = str_replace('$PAGEEDITOR', 'anonymous user '. $name, $subject);
-                       
+
                        $keys['$PAGEEDITOR']       = 'anonymous user ' . $name;
                        $keys['$PAGEEDITOR_EMAIL'] = wfMsgForContent( 'noemailtitle' );
                } else {
@@ -318,7 +317,6 @@ class EmailNotification {
                $userPage = $wgUser->getUserPage();
                $keys['$PAGEEDITOR_WIKI'] = $userPage->getFullUrl();
                $body = strtr( $body, $keys );
-               
                $body = wordwrap( $body, 72 );
 
                # now save this as the constant user-independent part of the message
@@ -329,7 +327,7 @@ class EmailNotification {
        }
 
 
-       
+
        /**
         * Does the per-user customizations to a notification e-mail (name,
         * timestamp in proper timezone, etc) and sends it out.
@@ -343,11 +341,11 @@ class EmailNotification {
        function composeAndSendPersonalisedMail( $watchingUser ) {
                global $wgLang;
                // From the PHP manual:
-               //     Note:  The to parameter cannot be an address in the form of "Something <someone@example.com>". 
+               //     Note:  The to parameter cannot be an address in the form of "Something <someone@example.com>".
                //     The mail command will not parse this properly while talking with the MTA.
                $to = $watchingUser->getEmail();
                $body = str_replace( '$WATCHINGUSERNAME', $watchingUser->getName() , $this->body );
-       
+
                $timecorrection = $watchingUser->getOption( 'timecorrection' );
                if( !$timecorrection ) {
                        # fail safe - I prefer it. TomGries
@@ -359,7 +357,7 @@ class EmailNotification {
                $body = str_replace('$PAGEEDITDATE',
                        $wgLang->timeanddate( $this->timestamp, true, false, $timecorrection ),
                        $body);
-               
+
                $error = userMailer( $to, $this->from, $this->subject, $body, $this->replyto );
                return ($error == '');
        }
index b27c53f..fbbc366 100644 (file)
@@ -38,7 +38,7 @@ class WatchedItem {
                global $wgDBname;
                return "$wgDBname:watchlist:user:$this->id:page:$this->ns:$this->ti";
        }
-       
+
        /**
         * Is mTitle being watched by mUser?
         */
@@ -51,9 +51,9 @@ class WatchedItem {
                $key = $this->watchKey();
                $iswatched = $wgMemc->get( $key );
                if( is_integer( $iswatched ) ) return $iswatched;
-               
+
                $dbr =& wfGetDB( DB_SLAVE );
-               $res = $dbr->select( 'watchlist', 1, array( 'wl_user' => $this->id, 'wl_namespace' => $this->ns, 
+               $res = $dbr->select( 'watchlist', 1, array( 'wl_user' => $this->id, 'wl_namespace' => $this->ns,
                        'wl_title' => $this->ti ), $fname );
                $iswatched = ($dbr->numRows( $res ) > 0) ? 1 : 0;
                $wgMemc->set( $key, $iswatched );
@@ -70,11 +70,11 @@ class WatchedItem {
                # accidentally reloads a watch-add operation.
                $dbw =& wfGetDB( DB_MASTER );
                $dbw->replace( 'watchlist', array(array('wl_user', 'wl_namespace', 'wl_title', 'wl_notificationtimestamp')),
-                 array( 
+                 array(
                    'wl_user' => $this->id,
                        'wl_namespace' => ($this->ns & ~1),
                        'wl_title' => $this->ti,
-                       'wl_notificationtimestamp' => '0'
+                       'wl_notificationtimestamp' => NULL
                  ), $fname );
 
                # the following code compensates the new behaviour, introduced by the enotif patch,
@@ -85,7 +85,7 @@ class WatchedItem {
                        'wl_user' => $this->id,
                        'wl_namespace' => ($this->ns | 1 ),
                        'wl_title' => $this->ti,
-                       'wl_notificationtimestamp' => '0'
+                       'wl_notificationtimestamp' => NULL
                  ), $fname );
 
                global $wgMemc;
@@ -100,9 +100,9 @@ class WatchedItem {
 
                $success = false;
                $dbw =& wfGetDB( DB_MASTER );
-               $dbw->delete( 'watchlist', 
-                       array( 
-                               'wl_user' => $this->id, 
+               $dbw->delete( 'watchlist',
+                       array(
+                               'wl_user' => $this->id,
                                'wl_namespace' => ($this->ns & ~1),
                                'wl_title' => $this->ti
                        ), $fname
@@ -122,7 +122,7 @@ class WatchedItem {
                                'wl_title' => $this->ti
                        ), $fname
                );
-               
+
                if ( $dbw->affectedRows() ) {
                        $success = true;
                }
@@ -145,8 +145,8 @@ class WatchedItem {
 
                $dbw =& wfGetDB( DB_MASTER );
                $watchlist = $dbw->tableName( 'watchlist' );
-               
-               $res = $dbw->select( 'watchlist', 'wl_user', 
+
+               $res = $dbw->select( 'watchlist', 'wl_user',
                        array( 'wl_namespace' => $oldnamespace, 'wl_title' => $oldtitle ),
                        $fname, 'FOR UPDATE'
                );
index 62d35c6..faabab6 100644 (file)
@@ -4,7 +4,7 @@ function install_version_checks() {
        # We dare not turn output buffer _off_ since this will break completely
        # if PHP is globally configured to run through a gzip filter.
        @ob_implicit_flush( true );
-       
+
        if( !function_exists( 'version_compare' ) ) {
                # version_compare was introduced in 4.1.0
                die( "Your PHP version is much too old; 4.0.x will _not_ work. 4.3.2 or higher is recommended. ABORTING.\n" );
@@ -12,7 +12,7 @@ function install_version_checks() {
        if( version_compare( phpversion(), '4.3.2' ) < 0 ) {
                echo "WARNING: PHP 4.3.2 or higher is recommended. Older versions from 4.1.x up may work but are not actively supported.\n\n";
        }
-       
+
        if (!extension_loaded('mysql')) {
                if (!dl('mysql.so')) {
                        print 'Could not load MySQL driver! Please compile '.
@@ -20,7 +20,7 @@ function install_version_checks() {
                exit;
                }
        }
-       
+
        global $wgCommandLineMode;
        $wgCommandLineMode = true;
        umask( 000 );
@@ -108,18 +108,19 @@ function dbsource( $fname, $database = false ) {
                if ( $sl < 0 ) { continue; }
                if ( '-' == $line{0} && '-' == $line{1} ) { continue; }
 
-               if ( ';' == $line{$sl} ) {
+               if ( ';' == $line{$sl} && ($sl < 2 || ';' != $line{$sl - 1})) {
                        $done = true;
                        $line = substr( $line, 0, $sl );
                }
 
                if ( '' != $cmd ) { $cmd .= ' '; }
-               $cmd .= $line;
+               $cmd .= "$line\n";
 
                if ( $done ) {
+                       $cmd = str_replace(';;', ";", $cmd);
                        $cmd = replacevars( $cmd );
                        if( $database )
-                               $res = $database->query( $cmd );
+                               $res = $database->query( $cmd, 'dbsource', true );
                        else
                                $res = mysql_query( $cmd );
 
@@ -142,7 +143,7 @@ function field_exists( $table, $field ) {
        $db =& wfGetDB( DB_SLAVE );
        $res = $db->query( "DESCRIBE $table", $fname );
        $found = false;
-       
+
        while ( $row = $db->fetchObject( $res ) ) {
                if ( $row->Field == $field ) {
                        $found = true;
index 3976d18..f858083 100755 (executable)
@@ -108,9 +108,6 @@ function initialiseMessagesReal( $overwrite = false, $messageArray = false ) {
        $timestamp = wfTimestampNow();
 
        #$sql = "SELECT cur_title,cur_is_new,cur_user_text FROM $cur WHERE cur_namespace=$ns AND cur_title IN(";
-       $sql = "SELECT page_title,page_is_new,rev_user_text FROM $page, $revision WHERE
-               page_namespace=$ns AND rev_page=page_id AND page_title IN(";
-
        # Get keys from $wgAllMessagesEn, which is more complete than the local language
        $first = true;
        if ( $messageArray ) {
@@ -123,34 +120,49 @@ function initialiseMessagesReal( $overwrite = false, $messageArray = false ) {
 
        # SELECT all existing messages
        # Can't afford to be locking all rows for update, this script can take quite a long time to complete
-       foreach ( $sortedArray as $key => $enMsg ) {
-               if ( $key == '' ) {
-                       continue; // Skip odd members
-               }
-               if ( $first ) {
-                       $first = false;
-               } else {
-                       $sql .= ',';
+       $rows = array();
+       $nitems = count($sortedArray);
+       $maxitems = $dbr->maxListLen();
+       $pos = 0;
+       if ($maxitems)
+               $chunks = array_chunk($sortedArray, $maxitems);
+       else
+               $chucks = array($sortedArray);
+
+       foreach ($chunks as $chunk) {
+               $first = true;
+               $sql = "SELECT page_title,page_is_new,rev_user_text FROM $page, $revision WHERE
+                       page_namespace=$ns AND rev_page=page_id AND page_title IN(";
+
+               foreach ( $chunk as $key => $enMsg ) {
+                       if ( $key == '' ) {
+                               continue; // Skip odd members
+                       }
+                       if ( $first ) {
+                               $first = false;
+                       } else {
+                               $sql .= ',';
+                       }
+                       $titleObj = Title::newFromText( $wgContLang->ucfirst( $key ) );
+                       $enctitle = $dbr->strencode($titleObj->getDBkey());
+                       $sql .= "'$enctitle'";
                }
-               $titleObj = Title::newFromText( $wgContLang->ucfirst( $key ) );
-               $enctitle = $dbr->strencode($titleObj->getDBkey());
-               $sql .= "'$enctitle'";
-       }
-       $sql .= ')';
-       $res = $dbr->query( $sql );
-       $row = $dbr->fetchObject( $res );
 
+               $sql .= ')';
+               $res = $dbr->query( $sql );
+               while ($row = $dbr->fetchObject($res))
+                       $rows[] = $row;
+       }
+       
        # Read the results into an array
        # Decide whether or not each one needs to be overwritten
        $existingTitles = array();
-       while ( $row ) {
+       foreach ($rows as $row) {
                if ( $row->rev_user_text != $username  && $row->rev_user_text != 'Template namespace initialisation script' ) {
                        $existingTitles[$row->page_title] = 'keep';
                } else {
                        $existingTitles[$row->page_title] = 'chuck';
                }
-
-               $row = $dbr->fetchObject( $res );
        }
 
        # Insert queries are done in one multi-row insert
index 95c0f31..314c44c 100644 (file)
@@ -2,17 +2,17 @@
 /**
  * Copyright (C) 2005 Brion Vibber <brion@pobox.com>
  * http://www.mediawiki.org/
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
+ * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License along
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
@@ -33,35 +33,38 @@ class BackupReader {
        var $pageCount = 0;
        var $revCount  = 0;
        var $dryRun    = false;
-       
+
        function BackupReader() {
                $this->stderr = fopen( "php://stderr", "wt" );
        }
-       
+
        function reportPage( $page ) {
                $this->pageCount++;
        }
-       
+
        function handleRevision( $rev ) {
                $title = $rev->getTitle();
+               if (!$title) {
+                       return;
+               }
                $display = $title->getPrefixedText();
                $timestamp = $rev->getTimestamp();
                #echo "$display $timestamp\n";
-               
+
                $this->revCount++;
                $this->report();
-               
+
                if( !$this->dryRun ) {
                        call_user_func( $this->importCallback, $rev );
                }
        }
-       
+
        function report( $final = false ) {
                if( $final xor ( $this->pageCount % $this->reportingInterval == 0 ) ) {
                        $this->showReport();
                }
        }
-       
+
        function showReport() {
                if( $this->reporting ) {
                        $delta = wfTime() - $this->startTime;
@@ -75,11 +78,11 @@ class BackupReader {
                        $this->progress( "$this->pageCount ($rate pages/sec $revrate revs/sec)" );
                }
        }
-       
+
        function progress( $string ) {
                fwrite( $this->stderr, $string . "\n" );
        }
-       
+
        function importFromFile( $filename ) {
                if( preg_match( '/\.gz$/', $filename ) ) {
                        $filename = 'compress.zlib://' . $filename;
@@ -87,22 +90,22 @@ class BackupReader {
                $file = fopen( $filename, 'rt' );
                $this->importFromHandle( $file );
        }
-       
+
        function importFromStdin() {
                $file = fopen( 'php://stdin', 'rt' );
                $this->importFromHandle( $file );
        }
-       
+
        function importFromHandle( $handle ) {
                $this->startTime = wfTime();
-               
+
                $source = new ImportStreamSource( $handle );
                $importer = new WikiImporter( $source );
-               
+
                $importer->setPageCallback( array( &$this, 'reportPage' ) );
                $this->importCallback =  $importer->setRevisionCallback(
                        array( &$this, 'handleRevision' ) );
-               
+
                $importer->doImport();
        }
 }
diff --git a/maintenance/oracle/archives/patch-transcache.sql b/maintenance/oracle/archives/patch-transcache.sql
new file mode 100644 (file)
index 0000000..62ad2c7
--- /dev/null
@@ -0,0 +1,5 @@
+CREATE TABLE transcache (
+       tc_url          VARCHAR2(255) NOT NULL UNIQUE,
+       tc_contents     CLOB,
+       tc_time         TIMESTAMP NOT NULL
+);
diff --git a/maintenance/oracle/interwiki.sql b/maintenance/oracle/interwiki.sql
new file mode 100644 (file)
index 0000000..09d01c6
--- /dev/null
@@ -0,0 +1,178 @@
+-- Based more or less on the public interwiki map from MeatballWiki
+-- Default interwiki prefixes...
+
+CALL add_interwiki('abbenormal','http://www.ourpla.net/cgi-bin/pikie.cgi?$1',0);
+CALL add_interwiki('acadwiki','http://xarch.tu-graz.ac.at/autocad/wiki/$1',0);
+CALL add_interwiki('acronym','http://www.acronymfinder.com/af-query.asp?String=exact&Acronym=$1',0);
+CALL add_interwiki('advogato','http://www.advogato.org/$1',0);
+CALL add_interwiki('aiwiki','http://www.ifi.unizh.ch/ailab/aiwiki/aiw.cgi?$1',0);
+CALL add_interwiki('alife','http://news.alife.org/wiki/index.php?$1',0);
+CALL add_interwiki('annotation','http://bayle.stanford.edu/crit/nph-med.cgi/$1',0);
+CALL add_interwiki('annotationwiki','http://www.seedwiki.com/page.cfm?wikiid=368&doc=$1',0);
+CALL add_interwiki('arxiv','http://www.arxiv.org/abs/$1',0);
+CALL add_interwiki('aspienetwiki','http://aspie.mela.de/Wiki/index.php?title=$1',0);
+CALL add_interwiki('bemi','http://bemi.free.fr/vikio/index.php?$1',0);
+CALL add_interwiki('benefitswiki','http://www.benefitslink.com/cgi-bin/wiki.cgi?$1',0);
+CALL add_interwiki('brasilwiki','http://rio.ifi.unizh.ch/brasilienwiki/index.php/$1',0);
+CALL add_interwiki('bridgeswiki','http://c2.com/w2/bridges/$1',0);
+CALL add_interwiki('c2find','http://c2.com/cgi/wiki?FindPage&value=$1',0);
+CALL add_interwiki('cache','http://www.google.com/search?q=cache:$1',0);
+CALL add_interwiki('ciscavate','http://ciscavate.org/index.php/$1',0);
+CALL add_interwiki('cliki','http://ww.telent.net/cliki/$1',0);
+CALL add_interwiki('cmwiki','http://www.ourpla.net/cgi-bin/wiki.pl?$1',0);
+CALL add_interwiki('codersbase','http://www.codersbase.com/$1',0);
+CALL add_interwiki('commons','http://commons.wikimedia.org/wiki/$1',0);
+CALL add_interwiki('consciousness','http://teadvus.inspiral.org/',0);
+CALL add_interwiki('corpknowpedia','http://corpknowpedia.org/wiki/index.php/$1',0);
+CALL add_interwiki('creationmatters','http://www.ourpla.net/cgi-bin/wiki.pl?$1',0);
+CALL add_interwiki('dejanews','http://www.deja.com/=dnc/getdoc.xp?AN=$1',0);
+CALL add_interwiki('demokraatia','http://wiki.demokraatia.ee/',0);
+CALL add_interwiki('dictionary','http://www.dict.org/bin/Dict?Database=*&Form=Dict1&Strategy=*&Query=$1',0);
+CALL add_interwiki('disinfopedia','http://www.disinfopedia.org/wiki.phtml?title=$1',0);
+CALL add_interwiki('diveintoosx','http://diveintoosx.org/$1',0);
+CALL add_interwiki('docbook','http://docbook.org/wiki/moin.cgi/$1',0);
+CALL add_interwiki('dolphinwiki','http://www.object-arts.com/wiki/html/Dolphin/$1',0);
+CALL add_interwiki('drumcorpswiki','http://www.drumcorpswiki.com/index.php/$1',0);
+CALL add_interwiki('dwjwiki','http://www.suberic.net/cgi-bin/dwj/wiki.cgi?$1',0);
+CALL add_interwiki('eĉei','http://www.ikso.net/cgi-bin/wiki.pl?$1',0);
+CALL add_interwiki('echei','http://www.ikso.net/cgi-bin/wiki.pl?$1',0);
+CALL add_interwiki('ecxei','http://www.ikso.net/cgi-bin/wiki.pl?$1',0);
+CALL add_interwiki('efnetceewiki','http://purl.net/wiki/c/$1',0);
+CALL add_interwiki('efnetcppwiki','http://purl.net/wiki/cpp/$1',0);
+CALL add_interwiki('efnetpythonwiki','http://purl.net/wiki/python/$1',0);
+CALL add_interwiki('efnetxmlwiki','http://purl.net/wiki/xml/$1',0);
+CALL add_interwiki('eljwiki','http://elj.sourceforge.net/phpwiki/index.php/$1',0);
+CALL add_interwiki('emacswiki','http://www.emacswiki.org/cgi-bin/wiki.pl?$1',0);
+CALL add_interwiki('elibre','http://enciclopedia.us.es/index.php/$1',0);
+CALL add_interwiki('eokulturcentro','http://esperanto.toulouse.free.fr/wakka.php?wiki=$1',0);
+CALL add_interwiki('evowiki','http://www.evowiki.org/index.php/$1',0);
+CALL add_interwiki('finalempire','http://final-empire.sourceforge.net/cgi-bin/wiki.pl?$1',0);
+CALL add_interwiki('firstwiki','http://firstwiki.org/index.php/$1',0);
+CALL add_interwiki('foldoc','http://www.foldoc.org/foldoc/foldoc.cgi?$1',0);
+CALL add_interwiki('foxwiki','http://fox.wikis.com/wc.dll?Wiki~$1',0);
+CALL add_interwiki('fr.be','http://fr.wikinations.be/$1',0);
+CALL add_interwiki('fr.ca','http://fr.ca.wikinations.org/$1',0);
+CALL add_interwiki('fr.fr','http://fr.fr.wikinations.org/$1',0);
+CALL add_interwiki('fr.org','http://fr.wikinations.org/$1',0);
+CALL add_interwiki('freebsdman','http://www.FreeBSD.org/cgi/man.cgi?apropos=1&query=$1',0);
+CALL add_interwiki('gamewiki','http://gamewiki.org/wiki/index.php/$1',0);
+CALL add_interwiki('gej','http://www.esperanto.de/cgi-bin/aktivikio/wiki.pl?$1',0);
+CALL add_interwiki('gentoo-wiki','http://gentoo-wiki.com/$1',0);
+CALL add_interwiki('globalvoices','http://cyber.law.harvard.edu/dyn/globalvoices/wiki/$1',0);
+CALL add_interwiki('gmailwiki','http://www.gmailwiki.com/index.php/$1',0);
+CALL add_interwiki('google','http://www.google.com/search?q=$1',0);
+CALL add_interwiki('googlegroups','http://groups.google.com/groups?q=$1',0);
+CALL add_interwiki('gotamac','http://www.got-a-mac.org/$1',0);
+CALL add_interwiki('greencheese','http://www.greencheese.org/$1',0);
+CALL add_interwiki('hammondwiki','http://www.dairiki.org/HammondWiki/index.php3?$1',0);
+CALL add_interwiki('haribeau','http://wiki.haribeau.de/cgi-bin/wiki.pl?$1',0);
+CALL add_interwiki('hewikisource','http://he.wikisource.org/wiki/$1',1);
+CALL add_interwiki('herzkinderwiki','http://www.herzkinderinfo.de/Mediawiki/index.php/$1',0);
+CALL add_interwiki('hrwiki','http://www.hrwiki.org/index.php/$1',0);
+CALL add_interwiki('iawiki','http://www.IAwiki.net/$1',0);
+CALL add_interwiki('imdb','http://us.imdb.com/Title?$1',0);
+CALL add_interwiki('infosecpedia','http://www.infosecpedia.org/pedia/index.php/$1',0);
+CALL add_interwiki('jargonfile','http://sunir.org/apps/meta.pl?wiki=JargonFile&redirect=$1',0);
+CALL add_interwiki('jefo','http://www.esperanto-jeunes.org/vikio/index.php?$1',0);
+CALL add_interwiki('jiniwiki','http://www.cdegroot.com/cgi-bin/jini?$1',0);
+CALL add_interwiki('jspwiki','http://www.ecyrd.com/JSPWiki/Wiki.jsp?page=$1',0);
+CALL add_interwiki('kerimwiki','http://wiki.oxus.net/$1',0);
+CALL add_interwiki('kmwiki','http://www.voght.com/cgi-bin/pywiki?$1',0);
+CALL add_interwiki('knowhow','http://www2.iro.umontreal.ca/~paquetse/cgi-bin/wiki.cgi?$1',0);
+CALL add_interwiki('lanifexwiki','http://opt.lanifex.com/cgi-bin/wiki.pl?$1',0);
+CALL add_interwiki('lasvegaswiki','http://wiki.gmnow.com/index.php/$1',0);
+CALL add_interwiki('linuxwiki','http://www.linuxwiki.de/$1',0);
+CALL add_interwiki('lojban','http://www.lojban.org/tiki/tiki-index.php?page=$1',0);
+CALL add_interwiki('lqwiki','http://wiki.linuxquestions.org/wiki/$1',0);
+CALL add_interwiki('lugkr','http://lug-kr.sourceforge.net/cgi-bin/lugwiki.pl?$1',0);
+CALL add_interwiki('lutherwiki','http://www.lutheranarchives.com/mw/index.php/$1',0);
+CALL add_interwiki('mathsongswiki','http://SeedWiki.com/page.cfm?wikiid=237&doc=$1',0);
+CALL add_interwiki('mbtest','http://www.usemod.com/cgi-bin/mbtest.pl?$1',0);
+CALL add_interwiki('meatball','http://www.usemod.com/cgi-bin/mb.pl?$1',0);
+CALL add_interwiki('mediazilla','http://bugzilla.wikipedia.org/$1',1);
+CALL add_interwiki('memoryalpha','http://www.memory-alpha.org/en/index.php/$1',0);
+CALL add_interwiki('metaweb','http://www.metaweb.com/wiki/wiki.phtml?title=$1',0);
+CALL add_interwiki('metawiki','http://sunir.org/apps/meta.pl?$1',0);
+CALL add_interwiki('metawikipedia','http://meta.wikimedia.org/wiki/$1',0);
+CALL add_interwiki('moinmoin','http://purl.net/wiki/moin/$1',0);
+CALL add_interwiki('mozillawiki','http://wiki.mozilla.org/index.php/$1',0);
+CALL add_interwiki('muweb','http://www.dunstable.com/scripts/MuWebWeb?$1',0);
+CALL add_interwiki('netvillage','http://www.netbros.com/?$1',0);
+CALL add_interwiki('oeis','http://www.research.att.com/cgi-bin/access.cgi/as/njas/sequences/eisA.cgi?Anum=$1',0);
+CALL add_interwiki('openfacts','http://openfacts.berlios.de/index.phtml?title=$1',0);
+CALL add_interwiki('openwiki','http://openwiki.com/?$1',0);
+CALL add_interwiki('opera7wiki','http://nontroppo.org/wiki/$1',0);
+CALL add_interwiki('orgpatterns','http://www.bell-labs.com/cgi-user/OrgPatterns/OrgPatterns?$1',0);
+CALL add_interwiki('osi reference model','http://wiki.tigma.ee/',0);
+CALL add_interwiki('pangalacticorg','http://www.pangalactic.org/Wiki/$1',0);
+CALL add_interwiki('personaltelco','http://www.personaltelco.net/index.cgi/$1',0);
+CALL add_interwiki('patwiki','http://gauss.ffii.org/$1',0);
+CALL add_interwiki('phpwiki','http://phpwiki.sourceforge.net/phpwiki/index.php?$1',0);
+CALL add_interwiki('pikie','http://pikie.darktech.org/cgi/pikie?$1',0);
+CALL add_interwiki('pmeg','http://www.bertilow.com/pmeg/$1.php',0);
+CALL add_interwiki('ppr','http://c2.com/cgi/wiki?$1',0);
+CALL add_interwiki('purlnet','http://purl.oclc.org/NET/$1',0);
+CALL add_interwiki('pythoninfo','http://www.python.org/cgi-bin/moinmoin/$1',0);
+CALL add_interwiki('pythonwiki','http://www.pythonwiki.de/$1',0);
+CALL add_interwiki('pywiki','http://www.voght.com/cgi-bin/pywiki?$1',0);
+CALL add_interwiki('raec','http://www.raec.clacso.edu.ar:8080/raec/Members/raecpedia/$1',0);
+CALL add_interwiki('revo','http://purl.org/NET/voko/revo/art/$1.html',0);
+CALL add_interwiki('rfc','http://www.rfc-editor.org/rfc/rfc$1.txt',0);
+CALL add_interwiki('s23wiki','http://is-root.de/wiki/index.php/$1',0);
+CALL add_interwiki('scoutpedia','http://www.scoutpedia.info/index.php/$1',0);
+CALL add_interwiki('seapig','http://www.seapig.org/$1',0);
+CALL add_interwiki('seattlewiki','http://seattlewiki.org/wiki/$1',0);
+CALL add_interwiki('seattlewireless','http://seattlewireless.net/?$1',0);
+CALL add_interwiki('seeds','http://www.IslandSeeds.org/wiki/$1',0);
+CALL add_interwiki('senseislibrary','http://senseis.xmp.net/?$1',0);
+CALL add_interwiki('shakti','http://cgi.algonet.se/htbin/cgiwrap/pgd/ShaktiWiki/$1',0);
+CALL add_interwiki('slashdot','http://slashdot.org/article.pl?sid=$1',0);
+CALL add_interwiki('smikipedia','http://www.smikipedia.org/$1',0);
+CALL add_interwiki('sockwiki','http://wiki.socklabs.com/$1',0);
+CALL add_interwiki('sourceforge','http://sourceforge.net/$1',0);
+CALL add_interwiki('squeak','http://minnow.cc.gatech.edu/squeak/$1',0);
+CALL add_interwiki('strikiwiki','http://ch.twi.tudelft.nl/~mostert/striki/teststriki.pl?$1',0);
+CALL add_interwiki('susning','http://www.susning.nu/$1',0);
+CALL add_interwiki('svgwiki','http://www.protocol7.com/svg-wiki/default.asp?$1',0);
+CALL add_interwiki('tavi','http://tavi.sourceforge.net/$1',0);
+CALL add_interwiki('tejo','http://www.tejo.org/vikio/$1',0);
+CALL add_interwiki('terrorwiki','http://www.liberalsagainstterrorism.com/wiki/index.php/$1',0);
+CALL add_interwiki('tmbw','http://www.tmbw.net/wiki/index.php/$1',0);
+CALL add_interwiki('tmnet','http://www.technomanifestos.net/?$1',0);
+CALL add_interwiki('tmwiki','http://www.EasyTopicMaps.com/?page=$1',0);
+CALL add_interwiki('turismo','http://www.tejo.org/turismo/$1',0);
+CALL add_interwiki('theopedia','http://www.theopedia.com/$1',0);
+CALL add_interwiki('twiki','http://twiki.org/cgi-bin/view/$1',0);
+CALL add_interwiki('twistedwiki','http://purl.net/wiki/twisted/$1',0);
+CALL add_interwiki('uea','http://www.tejo.org/uea/$1',0);
+CALL add_interwiki('unreal','http://wiki.beyondunreal.com/wiki/$1',0);
+CALL add_interwiki('ursine','http://ursine.ca/$1',0);
+CALL add_interwiki('usej','http://www.tejo.org/usej/$1',0);
+CALL add_interwiki('usemod','http://www.usemod.com/cgi-bin/wiki.pl?$1',0);
+CALL add_interwiki('visualworks','http://wiki.cs.uiuc.edu/VisualWorks/$1',0);
+CALL add_interwiki('warpedview','http://www.warpedview.com/index.php/$1',0);
+CALL add_interwiki('webdevwikinl','http://www.promo-it.nl/WebDevWiki/index.php?page=$1',0);
+CALL add_interwiki('webisodes','http://www.webisodes.org/$1',0);
+CALL add_interwiki('webseitzwiki','http://webseitz.fluxent.com/wiki/$1',0);
+CALL add_interwiki('why','http://clublet.com/c/c/why?$1',0);
+CALL add_interwiki('wiki','http://c2.com/cgi/wiki?$1',0);
+CALL add_interwiki('wikia','http://www.wikia.com/wiki/index.php/$1',0);
+CALL add_interwiki('wikibooks','http://en.wikibooks.org/wiki/$1',1);
+CALL add_interwiki('wikicities','http://www.wikicities.com/index.php/$1',0);
+CALL add_interwiki('wikif1','http://www.wikif1.org/$1',0);
+CALL add_interwiki('wikinfo','http://www.wikinfo.org/wiki.php?title=$1',0);
+CALL add_interwiki('wikimedia','http://wikimediafoundation.org/wiki/$1',0);
+CALL add_interwiki('wikiquote','http://en.wikiquote.org/wiki/$1',1);
+CALL add_interwiki('wikinews','http://en.wikinews.org/wiki/$1',0);
+CALL add_interwiki('wikisource','http://sources.wikipedia.org/wiki/$1',1);
+CALL add_interwiki('wikispecies','http://species.wikipedia.org/wiki/$1',1);
+CALL add_interwiki('wikitravel','http://wikitravel.org/en/$1',0);
+CALL add_interwiki('wikiworld','http://WikiWorld.com/wiki/index.php/$1',0);
+CALL add_interwiki('wiktionary','http://en.wiktionary.org/wiki/$1',1);
+CALL add_interwiki('wlug','http://www.wlug.org.nz/$1',0);
+CALL add_interwiki('wlwiki','http://winslowslair.supremepixels.net/wiki/index.php/$1',0);
+CALL add_interwiki('ypsieyeball','http://sknkwrks.dyndns.org:1957/writewiki/wiki.pl?$1',0);
+CALL add_interwiki('zwiki','http://www.zwiki.org/$1',0);
+CALL add_interwiki('zzz wiki','http://wiki.zzz.ee/',0);
+CALL add_interwiki('wikt','http://en.wiktionary.org/wiki/$1',1);
+
diff --git a/maintenance/oracle/tables.sql b/maintenance/oracle/tables.sql
new file mode 100644 (file)
index 0000000..7ccdb60
--- /dev/null
@@ -0,0 +1,344 @@
+-- SQL to create the initial tables for the MediaWiki database.
+-- This is read and executed by the install script; you should
+-- not have to run it by itself unless doing a manual install.
+
+CREATE SEQUENCE user_user_id_seq;
+
+CREATE TABLE "user" (
+  user_id              NUMBER(5) NOT NULL PRIMARY KEY,
+  user_name            VARCHAR2(255) DEFAULT '' NOT NULL,
+  user_real_name       VARCHAR2(255) DEFAULT '',
+  user_password                VARCHAR2(128) DEFAULT '',
+  user_newpassword     VARCHAR2(128) default '',
+  user_email           VARCHAR2(255) default '',
+  user_options         CLOB default '',
+  user_touched         TIMESTAMP WITH TIME ZONE,
+  user_token           CHAR(32) default '',
+  user_email_authenticated TIMESTAMP WITH TIME ZONE DEFAULT NULL,
+  user_email_token     CHAR(32),
+  user_email_token_expires TIMESTAMP WITH TIME ZONE DEFAULT NULL
+);
+CREATE UNIQUE INDEX user_name_idx ON "user" (user_name);
+CREATE INDEX user_email_token_idx ON "user" (user_email_token);
+
+CREATE TABLE user_groups (
+       ug_user         NUMBER(5) DEFAULT '0' NOT NULL
+                               REFERENCES "user" (user_id)
+                               ON DELETE CASCADE,
+       ug_group        VARCHAR2(16) NOT NULL,
+       CONSTRAINT user_groups_pk PRIMARY KEY (ug_user, ug_group)
+);
+CREATE INDEX user_groups_group_idx ON user_groups(ug_group);
+
+CREATE TABLE user_newtalk (
+       user_id         NUMBER(5) DEFAULT 0 NOT NULL,
+       user_ip         VARCHAR2(40) DEFAULT '' NOT NULL
+);
+CREATE INDEX user_newtalk_id_idx ON user_newtalk(user_id);
+CREATE INDEX user_newtalk_ip_idx ON user_newtalk(user_ip);
+
+CREATE SEQUENCE page_page_id_seq;
+CREATE TABLE page (
+       page_id                 NUMBER(8) NOT NULL PRIMARY KEY,
+       page_namespace          NUMBER(5) NOT NULL,
+       page_title              VARCHAR(255) NOT NULL,
+       page_restrictions       CLOB DEFAULT '',
+       page_counter            NUMBER(20) DEFAULT 0 NOT NULL,
+       page_is_redirect        NUMBER(1) DEFAULT 0 NOT NULL,
+       page_is_new             NUMBER(1) DEFAULT 0 NOT NULL,
+       page_random             NUMBER(25, 24) NOT NULL,
+       page_touched            TIMESTAMP WITH TIME ZONE,
+       page_latest             NUMBER(8) NOT NULL,
+       page_len                NUMBER(8) DEFAULT 0
+);
+CREATE UNIQUE INDEX page_id_namespace_title_idx ON page(page_namespace, page_title);
+CREATE INDEX page_random_idx ON page(page_random);
+CREATE INDEX page_len_idx ON page(page_len);
+
+CREATE SEQUENCE rev_rev_id_val;
+CREATE TABLE revision (
+       rev_id          NUMBER(8) NOT NULL,
+       rev_page        NUMBER(8) NOT NULL
+                               REFERENCES page (page_id)
+                               ON DELETE CASCADE,
+       rev_text_id     NUMBER(8) NOT NULL,
+       rev_comment     CLOB,
+       rev_user        NUMBER(8) DEFAULT 0 NOT NULL,
+       rev_user_text   VARCHAR2(255) DEFAULT '' NOT NULL,
+       rev_timestamp   TIMESTAMP WITH TIME ZONE NOT NULL,
+       rev_minor_edit  NUMBER(1) DEFAULT 0 NOT NULL,
+       rev_deleted     NUMBER(1) DEFAULT 0 NOT NULL,
+       CONSTRAINT revision_pk PRIMARY KEY (rev_page, rev_id)
+);
+
+CREATE UNIQUE INDEX rev_id_idx ON revision(rev_id);
+CREATE INDEX rev_timestamp_idx ON revision(rev_timestamp);
+CREATE INDEX rev_page_timestamp_idx ON revision(rev_page, rev_timestamp);
+CREATE INDEX rev_user_timestamp_idx ON revision(rev_user, rev_timestamp);
+CREATE INDEX rev_usertext_timestamp_idx ON revision(rev_user_text, rev_timestamp);
+
+CREATE SEQUENCE text_old_id_val;
+
+CREATE TABLE text (
+       old_id          NUMBER(8) NOT NULL,
+       old_text        CLOB,
+       old_flags       CLOB,
+       CONSTRAINT text_pk PRIMARY KEY (old_id)
+);
+
+CREATE TABLE archive (
+       ar_namespace    NUMBER(5) NOT NULL,
+       ar_title        VARCHAR2(255) NOT NULL,
+       ar_text         CLOB,
+       ar_comment      CLOB,
+       ar_user         NUMBER(8),
+       ar_user_text    VARCHAR2(255) NOT NULL,
+       ar_timestamp    TIMESTAMP WITH TIME ZONE NOT NULL,
+       ar_minor_edit   NUMBER(1) DEFAULT 0 NOT NULL,
+       ar_flags        CLOB,
+       ar_rev_id       NUMBER(8),
+       ar_text_id      NUMBER(8)
+);
+CREATE INDEX archive_name_title_timestamp ON archive(ar_namespace,ar_title,ar_timestamp);
+
+CREATE TABLE pagelinks (
+       pl_from NUMBER(8) NOT NULL
+                               REFERENCES page(page_id)
+                               ON DELETE CASCADE,
+       pl_namespace    NUMBER(4) DEFAULT 0 NOT NULL,
+       pl_title        VARCHAR2(255) NOT NULL
+);
+CREATE UNIQUE INDEX pl_from ON pagelinks(pl_from, pl_namespace, pl_title);
+CREATE INDEX pl_namespace ON pagelinks(pl_namespace, pl_title);
+
+CREATE TABLE imagelinks (
+       il_from  NUMBER(8) NOT NULL REFERENCES page(page_id) ON DELETE CASCADE,
+       il_to    VARCHAR2(255) NOT NULL
+);
+CREATE UNIQUE INDEX il_from ON imagelinks(il_from, il_to);
+CREATE INDEX il_to ON imagelinks(il_to);
+
+CREATE TABLE categorylinks (
+  cl_from      NUMBER(8) NOT NULL REFERENCES page(page_id) ON DELETE CASCADE,
+  cl_to                VARCHAR2(255) NOT NULL,
+  cl_sortkey   VARCHAR2(86) default '',
+  cl_timestamp TIMESTAMP WITH TIME ZONE NOT NULL
+);
+CREATE UNIQUE INDEX cl_from ON categorylinks(cl_from, cl_to);
+CREATE INDEX cl_sortkey ON categorylinks(cl_to, cl_sortkey);
+CREATE INDEX cl_timestamp ON categorylinks(cl_to, cl_timestamp);
+
+--
+-- Contains a single row with some aggregate info
+-- on the state of the site.
+--
+CREATE TABLE site_stats (
+  ss_row_id            NUMBER(8) NOT NULL,
+  ss_total_views       NUMBER(20) default 0,
+  ss_total_edits       NUMBER(20) default 0,
+  ss_good_articles     NUMBER(20) default 0,
+  ss_total_pages       NUMBER(20) default -1,
+  ss_users             NUMBER(20) default -1,
+  ss_admins            NUMBER(10) default -1
+);
+CREATE UNIQUE INDEX ss_row_id ON site_stats(ss_row_id);
+
+--
+-- Stores an ID for every time any article is visited;
+-- depending on $wgHitcounterUpdateFreq, it is
+-- periodically cleared and the page_counter column
+-- in the page table updated for the all articles
+-- that have been visited.)
+--
+CREATE TABLE hitcounter (
+       hc_id   NUMBER NOT NULL
+);
+
+--
+-- The internet is full of jerks, alas. Sometimes it's handy
+-- to block a vandal or troll account.
+--
+CREATE SEQUENCE ipblocks_ipb_id_val;
+CREATE TABLE ipblocks (
+       ipb_id          NUMBER(8) NOT NULL,
+       ipb_address     VARCHAR2(40),
+       ipb_user        NUMBER(8),
+       ipb_by          NUMBER(8) NOT NULL
+                               REFERENCES "user" (user_id)
+                               ON DELETE CASCADE,
+       ipb_reason      CLOB,
+       ipb_timestamp   TIMESTAMP WITH TIME ZONE NOT NULL,
+       ipb_auto        NUMBER(1) DEFAULT 0 NOT NULL,
+       ipb_expiry      TIMESTAMP WITH TIME ZONE,
+       CONSTRAINT ipblocks_pk PRIMARY KEY (ipb_id)
+);
+CREATE INDEX ipb_address ON ipblocks(ipb_address);
+CREATE INDEX ipb_user ON ipblocks(ipb_user);
+
+CREATE TABLE image (
+       img_name        VARCHAR2(255) NOT NULL,
+       img_size        NUMBER(8) NOT NULL,
+       img_width       NUMBER(5) NOT NULL,
+       img_height      NUMBER(5) NOT NULL,
+       img_metadata    CLOB,
+       img_bits        NUMBER(3),
+       img_media_type  VARCHAR2(10),
+       img_major_mime  VARCHAR2(12) DEFAULT 'unknown',
+       img_minor_mime  VARCHAR2(32) DEFAULT 'unknown',
+       img_description CLOB NOT NULL,
+       img_user        NUMBER(8) NOT NULL REFERENCES "user"(user_id) ON DELETE CASCADE,
+       img_user_text   VARCHAR2(255) NOT NULL,
+       img_timestamp   TIMESTAMP WITH TIME ZONE,
+       CONSTRAINT image_pk PRIMARY KEY (img_name)
+);
+CREATE INDEX img_size_idx ON image(img_size);
+CREATE INDEX img_timestamp_idx ON image(img_timestamp);
+
+CREATE TABLE oldimage (
+       oi_name         VARCHAR2(255) NOT NULL,
+       oi_archive_name VARCHAR2(255) NOT NULL,
+       oi_size         NUMBER(8) NOT NULL,
+       oi_width        NUMBER(5) NOT NULL,
+       oi_height       NUMBER(5) NOT NULL,
+       oi_bits         NUMBER(3) NOT NULL,
+       oi_description  CLOB,
+       oi_user         NUMBER(8) NOT NULL REFERENCES "user"(user_id),
+       oi_user_text    VARCHAR2(255) NOT NULL,
+       oi_timestamp    TIMESTAMP WITH TIME ZONE NOT NULL
+);
+CREATE INDEX oi_name ON oldimage (oi_name);
+
+CREATE SEQUENCE rc_rc_id_seq;
+CREATE TABLE recentchanges (
+       rc_id           NUMBER(8) NOT NULL,
+       rc_timestamp    TIMESTAMP WITH TIME ZONE,
+       rc_cur_time     TIMESTAMP WITH TIME ZONE,
+       rc_user         NUMBER(8) DEFAULT 0 NOT NULL,
+       rc_user_text    VARCHAR2(255),
+       rc_namespace    NUMBER(4) DEFAULT 0 NOT NULL,
+       rc_title        VARCHAR2(255) NOT NULL,
+       rc_comment      VARCHAR2(255),
+       rc_minor        NUMBER(3) DEFAULT 0 NOT NULL,
+       rc_bot          NUMBER(3) DEFAULT 0 NOT NULL,
+       rc_new          NUMBER(3) DEFAULT 0 NOT NULL,
+       rc_cur_id       NUMBER(8),
+       rc_this_oldid   NUMBER(8) NOT NULL,
+       rc_last_oldid   NUMBER(8) NOT NULL,
+       rc_type         NUMBER(3) DEFAULT 0 NOT NULL,
+       rc_moved_to_ns  NUMBER(3),
+       rc_moved_to_title       VARCHAR2(255),
+       rc_patrolled    NUMBER(3) DEFAULT 0 NOT NULL,
+       rc_ip           VARCHAR2(40),
+       CONSTRAINT rc_pk PRIMARY KEY (rc_id)
+);
+CREATE INDEX rc_timestamp ON recentchanges (rc_timestamp);
+CREATE INDEX rc_namespace_title ON recentchanges(rc_namespace, rc_title);
+CREATE INDEX rc_cur_id ON recentchanges(rc_cur_id);
+CREATE INDEX new_name_timestamp ON recentchanges(rc_new, rc_namespace, rc_timestamp);
+CREATE INDEX rc_ip ON recentchanges(rc_ip);
+
+CREATE TABLE watchlist (
+       wl_user                         NUMBER(8) NOT NULL
+                                               REFERENCES "user"(user_id)
+                                               ON DELETE CASCADE,
+       wl_namespace                    NUMBER(8) DEFAULT 0 NOT NULL,
+       wl_title                        VARCHAR2(255) NOT NULL,
+       wl_notificationtimestamp        TIMESTAMP WITH TIME ZONE DEFAULT NULL
+);
+CREATE UNIQUE INDEX wl_user_namespace_title ON watchlist
+       (wl_user, wl_namespace, wl_title);
+CREATE INDEX wl_namespace_title ON watchlist(wl_namespace, wl_title);
+
+--
+-- Used by texvc math-rendering extension to keep track
+-- of previously-rendered items.
+--
+CREATE TABLE math (
+       math_inputhash                  VARCHAR2(16) NOT NULL UNIQUE,
+       math_outputhash                 VARCHAR2(16) NOT NULL,
+       math_html_conservativeness      NUMBER(1) NOT NULL,
+       math_html                       CLOB,
+       math_mathml                     CLOB
+);
+
+--
+-- Recognized interwiki link prefixes
+--
+CREATE TABLE interwiki (
+  iw_prefix    VARCHAR2(32) NOT NULL UNIQUE,
+  iw_url       VARCHAR2(127) NOT NULL,
+  iw_local     NUMBER(1) NOT NULL,
+  iw_trans     NUMBER(1) DEFAULT 0 NOT NULL
+);
+
+CREATE TABLE querycache (
+       qc_type         VARCHAR2(32) NOT NULL,
+       qc_value        NUMBER(5) DEFAULT 0 NOT NULL,
+       qc_namespace    NUMBER(4) DEFAULT 0 NOT NULL,
+       qc_title        VARCHAR2(255)
+);
+CREATE INDEX querycache_type_value ON querycache(qc_type, qc_value);
+
+--
+-- For a few generic cache operations if not using Memcached
+--
+CREATE TABLE objectcache (
+       keyname         CHAR(255) DEFAULT '',
+       value           CLOB,
+       exptime         TIMESTAMP WITH TIME ZONE
+);
+CREATE UNIQUE INDEX oc_keyname_idx ON objectcache(keyname);
+CREATE INDEX oc_exptime_idx ON objectcache(exptime);
+
+CREATE TABLE "validate" (
+       val_user        NUMBER(11) DEFAULT 0 NOT NULL,
+       val_page        NUMBER(11) DEFAULT 0 NOT NULL,
+       val_revision    NUMBER(11) DEFAULT 0 NOT NULL,
+       val_type        NUMBER(11) DEFAULT 0 NOT NULL,
+       val_value       NUMBER(11) DEFAULT 0,
+       val_comment     VARCHAR2(255),
+       val_ip          VARCHAR2(20)
+);
+CREATE INDEX val_user ON "validate" (val_user,val_revision);
+
+CREATE TABLE logging (
+  log_type             VARCHAR2(10) NOT NULL,
+  log_action           VARCHAR2(10) NOT NULL,
+  log_timestamp                TIMESTAMP WITH TIME ZONE NOT NULL,
+  log_user             NUMBER(8) REFERENCES "user"(user_id),
+  log_namespace                NUMBER(4),
+  log_title            VARCHAR2(255) NOT NULL,
+  log_comment          VARCHAR2(255),
+  log_params           CLOB
+);
+CREATE INDEX logging_type_name ON logging(log_type, log_timestamp);
+CREATE INDEX logging_user_time ON logging(log_user, log_timestamp);
+CREATE INDEX logging_page_time ON logging(log_namespace, log_title, log_timestamp);
+
+-- Hold group name and description
+--CREATE TABLE /*$wgDBprefix*/groups (
+--  gr_id int(5) unsigned NOT NULL auto_increment,
+--  gr_name varchar(50) NOT NULL default '',
+--  gr_description varchar(255) NOT NULL default '',
+--  gr_rights tinyblob,
+--  PRIMARY KEY  (gr_id)
+--
+--) TYPE=InnoDB;
+
+CREATE OR REPLACE PROCEDURE add_user_right (name VARCHAR2, new_right VARCHAR2) AS
+       user_id         "user".user_id%TYPE;;
+       user_is_missing EXCEPTION;;
+BEGIN
+       SELECT user_id INTO user_id FROM "user" WHERE user_name = name;;
+       INSERT INTO user_groups (ug_user, ug_group) VALUES(user_id, new_right);;
+EXCEPTION
+       WHEN NO_DATA_FOUND THEN
+               DBMS_OUTPUT.PUT_LINE('The specified user does not exist.');;
+END add_user_right;;
+;
+
+CREATE OR REPLACE PROCEDURE add_interwiki (prefix VARCHAR2, url VARCHAR2, is_local NUMBER) AS
+BEGIN
+       INSERT INTO interwiki (iw_prefix, iw_url, iw_local) VALUES(prefix, url, is_local);;
+END add_interwiki;;
+;
\ No newline at end of file
index 41d9e9c..ccb21bc 100644 (file)
@@ -5,21 +5,24 @@
  * @todo document
  * @package MediaWiki
  * @subpackage Maintenance
- */ 
+ */
 
 /** */
 $options = array( 'quick' );
 require_once( "commandLine.inc" );
 require_once( "updaters.inc" );
 $wgTitle = Title::newFromText( "MediaWiki database updater" );
-$wgDatabase = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
+$dbclass = 'Database'.ucfirst($wgDBtype);
+require_once("$dbclass.php");
+$dbc = new $dbclass;
+$wgDatabase = $dbc->newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
 
 print "Going to run database updates for $wgDBname\n";
 print "Depending on the size of your database this may take a while!\n";
 
 if( !isset( $options['quick'] ) ) {
        print "Abort with control-c in the next five seconds... ";
-       
+
        for ($i = 5; $i >= 0; --$i) {
                echo $i;
                sleep(1);
index c2034ce..2676b35 100644 (file)
@@ -3,7 +3,7 @@
  * @package MediaWiki
  * @subpackage Maintenance
  */
+
  /** */
 
 require_once 'convertLinks.inc';
@@ -59,7 +59,7 @@ function rename_table( $from, $to, $patch ) {
                        echo "...can't move table $from to $to, $to already exists.\n";
                } else {
                        echo "Moving table $from to $to...";
-                       dbsource( "maintenance/archives/$patch", $wgDatabase );
+                       dbsource( archive($patch), $wgDatabase );
                        echo "ok\n";
                }
        } else {
@@ -75,7 +75,7 @@ function add_table( $name, $patch ) {
                echo "...$name table already exists.\n";
        } else {
                echo "Creating $name table...";
-               dbsource( "maintenance/archives/$patch", $wgDatabase );
+               dbsource( archive($patch), $wgDatabase );
                echo "ok\n";
        }
 }
@@ -88,7 +88,7 @@ function add_field( $table, $field, $patch ) {
                echo "...have $field field in $table table.\n";
        } else {
                echo "Adding $field field to table $table...";
-               dbsource( "maintenance/archives/$patch" , $wgDatabase );
+               dbsource( archive($patch) , $wgDatabase );
                echo "ok\n";
        }
 }
@@ -102,7 +102,7 @@ function do_revision_updates() {
 
 function update_passwords() {
        wfDebugDieBacktrace( "This function needs to be updated or removed.\n" );
-       
+
        global $wgDatabase;
        $fname = "Update script: update_passwords()";
        print "\nIt appears that you need to update the user passwords in your\n" .
@@ -136,7 +136,7 @@ function do_interwiki_update() {
                return true;
        }
        echo "Creating interwiki table: ";
-       dbsource( "maintenance/archives/patch-interwiki.sql" );
+       dbsource( archive("patch-interwiki.sql") );
        echo "ok\n";
        echo "Adding default interwiki definitions: ";
        dbsource( "maintenance/interwiki.sql" );
@@ -149,7 +149,7 @@ function do_index_update() {
        $meta = $wgDatabase->fieldInfo( "recentchanges", "rc_timestamp" );
        if( $meta->multiple_key == 0 ) {
                echo "Updating indexes to 20031107: ";
-               dbsource( "maintenance/archives/patch-indexes.sql" );
+               dbsource( archive("patch-indexes.sql") );
                echo "ok\n";
                return true;
        }
@@ -163,7 +163,7 @@ function do_image_name_unique_update() {
                echo "...image primary key already set.\n";
        } else {
                echo "Making img_name the primary key... ";
-               dbsource( "maintenance/archives/patch-image_name_primary.sql", $wgDatabase );
+               dbsource( archive("patch-image_name_primary.sql"), $wgDatabase );
                echo "ok\n";
        }
 }
@@ -235,12 +235,14 @@ function do_user_update() {
  * which causes a collation mismatch error on joins in MySQL 4.1.
  */
 function do_logging_encoding() {
-       global $wgDatabase;
+       global $wgDatabase, $wgDBtype;
+       if ($wgDBtype != 'mysql')
+               return;
        $logging = $wgDatabase->tableName( 'logging' );
        $res = $wgDatabase->query( "SELECT log_title FROM $logging LIMIT 0" );
        $flags = explode( ' ', mysql_field_flags( $res, 0 ) );
        $wgDatabase->freeResult( $res );
-       
+
        if( in_array( 'binary', $flags ) ) {
                echo "Logging table has correct title encoding.\n";
        } else {
@@ -259,7 +261,7 @@ function do_schema_restructuring() {
                echo "...converting from cur/old to page/revision/text DB structure.\n"; flush();
                echo wfTimestamp();
                echo "......checking for duplicate entries.\n"; flush();
-               
+
                extract( $wgDatabase->tableNames( 'cur', 'old', 'page', 'revision', 'text' ) );
 
                $rows = $wgDatabase->query( "SELECT cur_title, cur_namespace, COUNT(cur_namespace) AS c
@@ -277,7 +279,7 @@ function do_schema_restructuring() {
                                echo ( sprintf( "      %-60s %3s %5s\n", $row->cur_title, $row->cur_namespace, $row->c ) );
                        }
                        $sql = "SELECT cur_title, cur_namespace, cur_id, cur_timestamp FROM $cur WHERE ";
-                       $firstCond = true; 
+                       $firstCond = true;
                        foreach ( $duplicate as $ns => $titles ) {
                                if ( $firstCond ) {
                                        $firstCond = false;
@@ -317,7 +319,7 @@ function do_schema_restructuring() {
                        echo wfTimestamp();
                        echo "......<b>Deleted</b> ".$wgDatabase->affectedRows()." records.\n";
                }
-               
+
 
                echo wfTimestamp();
                echo "......Creating tables.\n";
@@ -348,7 +350,7 @@ function do_schema_restructuring() {
                        rev_timestamp char(14) binary NOT NULL default '',
                        rev_minor_edit tinyint(1) unsigned NOT NULL default '0',
                        rev_deleted tinyint(1) unsigned NOT NULL default '0',
-  
+
                        PRIMARY KEY rev_page_id (rev_page, rev_id),
                        UNIQUE INDEX rev_id (rev_id),
                        INDEX rev_timestamp (rev_timestamp),
@@ -409,7 +411,7 @@ function do_schema_restructuring() {
                echo wfTimestamp();
                echo "......Renaming old.\n";
                $wgDatabase->query( "ALTER TABLE $old RENAME TO $text", $fname );
-               
+
                echo wfTimestamp();
                echo "...done.\n";
        }
@@ -454,22 +456,24 @@ function do_namespace_size() {
 }
 
 function do_namespace_size_on( $table, $prefix ) {
-       global $wgDatabase;
+       global $wgDatabase, $wgDBtype;
+       if ($wgDBtype != 'mysql')
+               return;
        $field = $prefix . '_namespace';
-       
+
        $tablename = $wgDatabase->tableName( $table );
        $result = $wgDatabase->query( "SHOW COLUMNS FROM $tablename LIKE '$field'" );
        $info = $wgDatabase->fetchObject( $result );
        $wgDatabase->freeResult( $result );
-       
+
        if( substr( $info->Type, 0, 3 ) == 'int' ) {
                echo "...$field is already a full int ($info->Type).\n";
        } else {
                echo "Promoting $field from $info->Type to int... ";
-               
+
                $sql = "ALTER TABLE $tablename MODIFY $field int NOT NULL";
                $wgDatabase->query( $sql );
-               
+
                echo "ok\n";
        }
 }
@@ -483,7 +487,7 @@ function do_pagelinks_update() {
                dbsource( "maintenance/archives/patch-pagelinks.sql", $wgDatabase );
                echo "ok\n";
                flush();
-               
+
                global $wgCanonicalNamespaceNames;
                foreach( $wgCanonicalNamespaceNames as $ns => $name ) {
                        if( $ns != 0 ) {
@@ -495,28 +499,28 @@ function do_pagelinks_update() {
 
 function do_pagelinks_namespace( $namespace ) {
        global $wgDatabase, $wgContLang;
-       
+
        $ns = IntVal( $namespace );
        echo "Cleaning up broken links for namespace $ns... ";
-       
+
        $pagelinks = $wgDatabase->tableName( 'pagelinks' );
        $name = $wgContLang->getNsText( $ns );
        $prefix = $wgDatabase->strencode( $name );
        $likeprefix = str_replace( '_', '\\_', $prefix);
-       
+
        $sql = "UPDATE $pagelinks
                   SET pl_namespace=$ns,
                       pl_title=TRIM(LEADING '$prefix:' FROM pl_title)
                 WHERE pl_namespace=0
                   AND pl_title LIKE '$likeprefix:%'";
-       
+
        $wgDatabase->query( $sql, 'do_pagelinks_namespace' );
        echo "ok\n";
 }
 
 function do_drop_img_type() {
        global $wgDatabase;
-       
+
        if( $wgDatabase->fieldExists( 'image', 'img_type' ) ) {
                echo "Dropping unused img_type field in image table... ";
                dbsource( "maintenance/archives/patch-drop_img_type.sql", $wgDatabase );
@@ -553,16 +557,16 @@ function do_user_unique_update() {
 function do_user_groups_update() {
        $fname = 'do_user_groups_update';
        global $wgDatabase;
-       
+
        if( $wgDatabase->tableExists( 'user_groups' ) ) {
                echo "...user_groups table already exists.\n";
                return do_user_groups_reformat();
        }
-       
+
        echo "Adding user_groups table... ";
        dbsource( 'maintenance/archives/patch-user_groups.sql', $wgDatabase );
        echo "ok\n";
-       
+
        if( !$wgDatabase->tableExists( 'user_rights' ) ) {
                if( $wgDatabase->fieldExists( 'user', 'user_rights' ) ) {
                        echo "Upgrading from a 1.3 or older database? Breaking out user_rights for conversion...";
@@ -575,18 +579,18 @@ function do_user_groups_update() {
                        return;
                }
        }
-       
+
        echo "Converting user_rights table to user_groups... ";
        $result = $wgDatabase->select( 'user_rights',
                array( 'ur_user', 'ur_rights' ),
                array( "ur_rights != ''" ),
                $fname );
-       
+
        while( $row = $wgDatabase->fetchObject( $result ) ) {
                $groups = array_unique(
                        array_map( 'trim',
                                explode( ',', $row->ur_rights ) ) );
-               
+
                foreach( $groups as $group ) {
                        $wgDatabase->insert( 'user_groups',
                                array(
@@ -603,18 +607,18 @@ function do_user_groups_reformat() {
        # Check for bogus formats from previous 1.5 alpha code.
        global $wgDatabase;
        $info = $wgDatabase->fieldInfo( 'user_groups', 'ug_group' );
-       
+
        if( $info->type == 'int' ) {
                $oldug = $wgDatabase->tableName( 'user_groups' );
                $newug = $wgDatabase->tableName( 'user_groups_bogus' );
                echo "user_groups is in bogus intermediate format. Renaming to $newug... ";
                $wgDatabase->query( "ALTER TABLE $oldug RENAME TO $newug" );
                echo "ok\n";
-               
+
                echo "Re-adding fresh user_groups table... ";
                dbsource( 'maintenance/archives/patch-user_groups.sql', $wgDatabase );
                echo "ok\n";
-               
+
                echo "***\n";
                echo "*** WARNING: You will need to manually fix up user permissions in the user_groups\n";
                echo "*** table. Old 1.5 alpha versions did some pretty funky stuff...\n";
@@ -622,12 +626,12 @@ function do_user_groups_reformat() {
        } else {
                echo "...user_groups is in current format.\n";
        }
-       
+
 }
 
 function do_all_updates() {
        global $wgNewTables, $wgNewFields, $wgRenamedTables;
-       
+
        # Rename tables
        foreach ( $wgRenamedTables as $tableRecord ) {
                rename_table( $tableRecord[0], $tableRecord[1], $tableRecord[2] );
@@ -644,7 +648,7 @@ function do_all_updates() {
                add_field( $fieldRecord[0], $fieldRecord[1], $fieldRecord[2] );
                flush();
        }
-       
+
        # Do schema updates which require special handling
        do_interwiki_update(); flush();
        do_index_update(); flush();
@@ -654,20 +658,29 @@ function do_all_updates() {
        do_user_update(); flush();
 ###### do_copy_newtalk_to_watchlist(); flush();
        do_logging_encoding(); flush();
-       
+
        do_schema_restructuring(); flush();
        do_inverse_timestamp(); flush();
        do_text_id(); flush();
        do_namespace_size(); flush();
-       
+
        do_pagelinks_update(); flush();
-       
+
        do_drop_img_type(); flush();
-       
+
        do_user_unique_update(); flush();
        do_user_groups_update(); flush();
-       
+
        initialiseMessages(); flush();
 }
 
+function archive($name) {
+       global $wgDBtype;
+       switch ($wgDBtype) {
+       case "oracle":
+               return "maintenance/oracle/archives/$name";
+       default:
+               return "maintenance/archives/$name";
+       }
+}
 ?>