Specia:Asksql security fix, Special:Asksql query timeout feature
authorTim Starling <tstarling@users.mediawiki.org>
Wed, 11 Feb 2004 13:03:58 +0000 (13:03 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Wed, 11 Feb 2004 13:03:58 +0000 (13:03 +0000)
includes/Database.php
includes/DefaultSettings.php
includes/OutputPage.php
includes/SpecialAsksql.php

index 6006917..3d24642 100644 (file)
@@ -173,7 +173,8 @@ class Database {
                        } else {
                                wfDebug("SQL ERROR: " . mysql_error( $this->mConn ) . "\n");
                                if ( $this->mOut ) {
-                                       $this->mOut->databaseError( $fname ); // calls wfAbruptExit()
+                                       // this calls wfAbruptExit()
+                                       $this->mOut->databaseError( $fname, $this );                            
                                }
                        }
                }
@@ -385,6 +386,21 @@ class Database {
                $this->mDatabase = $db;
                mysql_select_db( $db, $this->mConn );
        }
+
+       function startTimer( $timeout )
+       {
+               $thisdir = dirname( getenv( "SCRIPT_FILENAME" ) );
+               $tid = mysql_thread_id( $this->mConn );
+               $this->mTimerProc = popen( "php $thisdir/killthread.php $timeout $tid &", "w" );
+       }
+
+       function stopTimer()
+       {
+               if ( $this->mTimerProc ) {
+                       pclose( $this->mTimerProc );
+               }
+       }
+
 }
 
 #------------------------------------------------------------------------------
index 5266466..45b862a 100644 (file)
@@ -40,6 +40,7 @@ $wgDBsqlpassword      = "sqlpass";
 $wgDBminWordLen     = 4;
 $wgDBtransactions      = false; # Set to true if using InnoDB tables
 $wgDBmysql4                    = false; # Set to true to use enhanced fulltext search
+$wgSqlTimeout          = 30;
 
 # Database load balancer
 $wgDBservers           = false; # e.g. array("larousse", "pliny")
index ac7d657..998489e 100644 (file)
@@ -465,7 +465,7 @@ class OutputPage {
                $this->returnToMain();
        }
 
-       function databaseError( $fname )
+       function databaseError( $fname, &$conn )
        {
                global $wgUser, $wgCommandLineMode;
 
@@ -479,10 +479,10 @@ class OutputPage {
                        $msg = wfMsgNoDB( "dberrortext" );
                }
 
-               $msg = str_replace( "$1", htmlspecialchars( wfLastDBquery() ), $msg );
+               $msg = str_replace( "$1", htmlspecialchars( $conn->lastQuery() ), $msg );
                $msg = str_replace( "$2", htmlspecialchars( $fname ), $msg );
-               $msg = str_replace( "$3", wfLastErrno(), $msg );
-               $msg = str_replace( "$4", htmlspecialchars( wfLastError() ), $msg );
+               $msg = str_replace( "$3", $conn->lastErrno(), $msg );
+               $msg = str_replace( "$4", htmlspecialchars( $conn->lastError() ), $msg );
                
                if ( $wgCommandLineMode || !is_object( $wgUser )) {
                        print "$msg\n";
index 2cc45bc..8b8d4ac 100644 (file)
@@ -60,7 +60,7 @@ class SqlQueryForm {
        {
                global $wgOut, $wgUser, $wgServer, $wgScript, $wgArticlePath, $wgLang;
                global $wpSqlQuery;
-               global $wgDBsqluser, $wgDBsqlpassword;
+               global $wgDBserver, $wgDBsqluser, $wgDBsqlpassword, $wgDBname, $wgSqlTimeout;
 
                # Use a limit, folks!
                $wpSqlQuery = trim( $wpSqlQuery );
@@ -68,19 +68,24 @@ class SqlQueryForm {
                        and !preg_match( "/LIMIT/i", $wpSqlQuery ) ) {
                        $wpSqlQuery .= " LIMIT 100";
                }
-               $connection = wfGetDB( $wgDBsqluser, $wgDBsqlpassword );
+               $conn = Database::newFromParams( $wgDBserver, $wgDBsqluser, $wgDBsqlpassword, $wgDBname );
+
                $this->logQuery( $wpSqlQuery );
-               $res = wfQuery( $wpSqlQuery, DB_WRITE, "SpecialAsksql::doSubmit" );
+
+               # Start timer, will kill the DB thread in $wgSqlTimeout seconds
+               $conn->startTimer( $wgSqlTimeout );
+               $res = $conn->query( $wpSqlQuery, "SpecialAsksql::doSubmit" );
+               $conn->stopTimer();
                $this->logFinishedQuery();
 
                $n = 0;
-               @$n = wfNumFields( $res );
+               @$n = $conn->numFields( $res );
                $titleList = false;
 
                if ( $n ) {
                        $k = array();
                        for ( $x = 0; $x < $n; ++$x ) {
-                               array_push( $k, wfFieldName( $res, $x ) );
+                               array_push( $k, $conn->fieldName( $res, $x ) );
                        }
 
                        if ( $n == 2 && in_array( "cur_title", $k ) && in_array( "cur_namespace", $k ) ) {
@@ -88,10 +93,10 @@ class SqlQueryForm {
                        }
 
                        $a = array();
-                       while ( $s = wfFetchObject( $res ) ) {
+                       while ( $s = $conn->fetchObject( $res ) ) {
                                array_push( $a, $s );
                        }
-                       wfFreeResult( $res );
+                       $conn->freeResult( $res );
 
                        if ( $titleList ) {
                                $r = "";