Introducing special page modular extensions, making the board vote special page the...
authorTim Starling <tstarling@users.mediawiki.org>
Sat, 15 May 2004 03:36:39 +0000 (03:36 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Sat, 15 May 2004 03:36:39 +0000 (03:36 +0000)
* Moving common special page handling to SpecialPage.php
* Special page lists in the language classes are obsolete, replaced by the list in SpecialPage.php
* Special:Specialpages uses the standard page titles wfMsg(pagename) instead of the description list previously contained in the $wgSpecialPagesEn arrays
* Ability to add custom messages to the MessageCache. Overridable by the MediaWiki namespace.
* Moving board vote functionality from includes/SpecialBoardvote.php to extensions/BoardVote.php

extensions/BoardVote.php [new file with mode: 0644]
includes/DefaultSettings.php
includes/GlobalFunctions.php
includes/MessageCache.php
includes/Setup.php
includes/SpecialBoardvote.php [deleted file]
includes/SpecialPage.php [new file with mode: 0644]
includes/SpecialSpecialpages.php
index.php
languages/Language.php
maintenance/boardvote.sql

diff --git a/extensions/BoardVote.php b/extensions/BoardVote.php
new file mode 100644 (file)
index 0000000..4659ddb
--- /dev/null
@@ -0,0 +1,412 @@
+<?php
+
+# Wikimedia Foundation Board of Trustees Election
+
+# Register extension
+$wgExtensionFunctions[] = "wfBoardvoteSetup";
+
+
+function wfBoardvoteSetup()
+{
+# Look out, freaky indenting
+# All this happens after SpecialPage.php has been included in Setup.php
+
+class BoardVotePage extends SpecialPage {
+       var $mPosted, $mContributing, $mVolunteer, $mDBname, $mUserDays, $mUserEdits;
+       var $mHasVoted, $mAction, $mUserKey;
+
+       function BoardVotePage() {
+               SpecialPage::SpecialPage( "Boardvote" );
+       }
+
+       function execute( $par ) {
+               global $wgUser, $wgDBname, $wgInputEncoding, $wgRequest, $wgBoardVoteDB;
+
+               $this->mUserKey = iconv( $wgInputEncoding, "UTF-8", $wgUser->getName() ) . "@$wgDBname";
+               $this->mPosted = $wgRequest->wasPosted();
+               $this->mContributing = $wgRequest->getInt( "contributing" );
+               $this->mVolunteer = $wgRequest->getInt( "volunteer" );
+               $this->mDBname = $wgBoardVoteDB;
+               $this->mHasVoted = $this->hasVoted( $wgUser );
+               
+               if ( $par ) {
+                       $this->mAction = $par;
+               } else {
+                       $this->mAction = $wgRequest->getText( "action" );
+               }
+
+               $this->setHeaders();
+
+               if ( $this->mAction == "list" ) {
+                       $this->displayList();
+               } elseif ( $this->mAction == "dump" ) {
+                       $this->dump();
+               } elseif( $this->mAction == "vote" ) {
+                       if ( !$wgUser->getID() ) {
+                               $this->notLoggedIn();
+                       } else {
+                               $this->getQualifications( $wgUser );
+                               if ( $this->mUserDays < 90 ) {
+                                       $this->notQualified();
+                               } elseif ( $this->mPosted ) {
+                                       $this->logVote();
+                               } else {
+                                       $this->displayVote();
+                               }
+                       }
+               } else {
+                       $this->displayEntry();
+               }
+       }
+       
+       function displayEntry() {
+               global $wgOut;
+               $wgOut->addWikiText( wfMsg( "boardvote_entry" ) );
+       }
+
+       function hasVoted( &$user ) {
+               global $wgDBname;
+               $row = wfGetArray( $this->mDBname . ".log", array( "1" ), 
+                 array( "log_user_key" => $this->mUserKey ), "BoardVotePage::getUserVote" );
+               if ( $row === false ) {
+                       return false;
+               } else {
+                       return true;
+               }
+       }
+
+       function logVote() {
+               global $wgUser, $wgDBname, $wgIP, $wgOut;
+               $fname = "BoardVotePage::logVote";
+               
+               $now = wfTimestampNow();
+               $record = $this->encrypt( $this->mContributing, $this->mVolunteer );
+               $db = $this->mDBname;
+               
+               # Mark previous votes as old
+               $encKey = wfStrencode( $this->mUserKey );
+               $sql = "UPDATE $db.log SET log_current=0 WHERE log_user_key='$encKey'";
+               wfQuery( $sql, DB_WRITE, $fname );
+               
+               # Add vote to log
+               wfInsertArray( "$db.log", array(
+                       "log_user" => $wgUser->getID(),
+                       "log_user_text" => $wgUser->getName(),
+                       "log_user_key" => $this->mUserKey,
+                       "log_wiki" => $wgDBname,
+                       "log_edits" => $this->mUserEdits,
+                       "log_days" => $this->mUserDays,
+                       "log_record" => $record,
+                       "log_ip" => $wgIP,
+                       "log_xff" => @$_SERVER['HTTP_X_FORWARDED_FOR'],
+                       "log_ua" => $_SERVER['HTTP_USER_AGENT'],
+                       "log_timestamp" => $now,
+                       "log_current" => 1
+               ), $fname );
+
+               $wgOut->addWikiText( wfMsg( "boardvote_entered", $record ) );
+       }
+       
+       function displayVote() {
+               global $wgContributingCandidates, $wgVolunteerCandidates, $wgOut;
+               
+               $thisTitle = Title::makeTitle( NS_SPECIAL, "Boardvote" );
+               $action = $thisTitle->getLocalURL( "action=vote" );
+               if ( $this->mHasVoted ) {
+                       $intro = wfMsg( "boardvote_intro_change" );
+               } else {
+                       $intro = wfMsg( "boardvote_intro" );
+               }
+               $contributing = wfMsg( "boardvote_contributing" );
+               $volunteer = wfMsg( "boardvote_volunteer" );
+               $ok = wfMsg( "ok" );
+               
+               $candidatesV = $candidatesC = array();
+               foreach( $wgContributingCandidates as $i => $candidate ) {
+                       $candidatesC[] = array( $i, $candidate );
+               }
+               foreach ( $wgVolunteerCandidates as $i => $candidate ) {
+                       $candidatesV[] = array( $i, $candidate );
+               }
+
+               srand ((float)microtime()*1000000);
+               shuffle( $candidatesC );
+               shuffle( $candidatesV );
+
+               $text = "
+                 $intro
+                 <form name=\"boardvote\" id=\"boardvote\" method=\"post\" action=\"$action\">
+                 <table border='0'><tr><td colspan=2>
+                 <h2>$contributing</h2>
+                 </td></tr>";
+               $text .= $this->voteEntry( -1, wfMsg( "boardvote_abstain" ), "contributing" );
+               foreach ( $candidatesC as $candidate ) {
+                       $text .= $this->voteEntry( $candidate[0], $candidate[1], "contributing" );
+               }
+               $text .= "
+                 <tr><td colspan=2>
+                 <h2>$volunteer</h2></td></tr>";
+               $text .= $this->voteEntry( -1, wfMsg( "boardvote_abstain" ), "volunteer" );
+               foreach ( $candidatesV as $candidate ) {
+                       $text .= $this->voteEntry( $candidate[0], $candidate[1], "volunteer" );
+               }
+               
+               $text .= "<tr><td>&nbsp;</td><td>
+                 <input name=\"submit\" type=\"submit\" value=\"$ok\">
+                 </td></tr></table></form>";
+               $text .= wfMsg( "boardvote_footer" );
+               $wgOut->addHTML( $text );
+       }
+
+       function voteEntry( $index, $candidate, $name ) {
+               if ( $index == -1 ) {
+                       $checked = " CHECKED";
+               } else {
+                       $checked = "";
+               }
+
+               return "
+               <tr><td align=\"right\">
+                 <input type=\"radio\" name=\"$name\" value=\"$index\"$checked>
+               </td><td align=\"left\">
+                 $candidate
+               </td></tr>";
+       }
+
+       function notLoggedIn() {
+               global $wgOut;
+               $wgOut->addWikiText( wfMsg( "boardvote_notloggedin" ) );
+       }
+       
+       function notQualified() {
+               global $wgOut;
+               $wgOut->addWikiText( wfMsg( "boardvote_notqualified", $this->mUserDays ) );
+       }
+       
+       function encrypt( $contributing, $volunteer ) {
+               global $wgVolunteerCandidates, $wgContributingCandidates;
+               global $wgGPGCommand, $wgGPGRecipient, $wgGPGHomedir;
+               $file = @fopen( "/dev/urandom", "r" );
+               if ( $file ) {
+                       $salt = implode( "", unpack( "H*", fread( $file, 64 ) ));
+                       fclose( $file );
+               } else {
+                       $salt = Parser::getRandomString() . Parser::getRandomString();
+               }
+               $record = 
+                 "Contributing: $contributing (" .$wgContributingCandidates[$contributing] . ")\n" .
+                 "Volunteer: $volunteer (" . $wgVolunteerCandidates[$volunteer] . ")\n" .
+                 "Salt: $salt\n";
+               # Get file names
+               $input = tempnam( "/tmp", "gpg_" );
+               $output = tempnam( "/tmp", "gpg_" );
+
+               # Write unencrypted record
+               $file = fopen( $input, "w" );
+               fwrite( $file, $record );
+               fclose( $file );
+
+               # Call GPG
+               $command = wfEscapeShellArg( $wgGPGCommand ) . " --batch --yes -ear " . 
+                 wfEscapeShellArg( $wgGPGRecipient ) . " -o " . wfEscapeShellArg( $output );
+               if ( $wgGPGHomedir ) {
+                       $command .= " --homedir " . wfEscapeShellArg( $wgGPGHomedir );
+               } 
+               $command .= " " . wfEscapeShellArg( $input );
+
+               shell_exec( $command );
+
+               # Read result
+               $result = file_get_contents( $output );
+
+               # Delete temporary files
+               unlink( $input );
+               unlink( $output );
+               
+               return $result;
+       }
+
+       function getQualifications( &$user ) {
+               $id = $user->getID();
+               if ( !$id ) {
+                       $this->mUserDays = 0;
+                       $this->mUserEdits = 0;
+                       return;
+               }
+
+               # Count contributions and find earliest edit
+               # First cur
+               $sql = "SELECT COUNT(*) as n, MIN(cur_timestamp) as t FROM cur WHERE cur_user=$id";
+               $res = wfQuery( $sql, DB_READ, "BoardVotePage::getQualifications" );
+               $cur = wfFetchObject( $res );
+               wfFreeResult( $res );
+
+               # If the user has stacks of contributions, don't check old as well
+               $now = time();
+               if ( is_null( $cur->t ) ) {
+                       $signup = $now;
+               } else {
+                       $signup = wfTimestamp2Unix( $cur->t );
+               }
+               
+               $days = ($now - $signup) / 86400;
+               if ( $cur->n > 400 && $days > 180 ) {
+                       $this->mUserDays = 0x7fffffff;
+                       $this->mUserEdits = 0x7fffffff;
+                       return;
+               }
+
+               # Now check old
+               $sql = "SELECT COUNT(*) as n, MIN(old_timestamp) as t FROM old WHERE old_user=$id";
+               $res = wfQuery( $sql, DB_READ, "BoardVotePage::getQualifications" );
+               $old = wfFetchObject( $res );
+               wfFreeResult( $res );
+               
+               if ( !is_null( $old->t ) ) {
+                       $signup = min( wfTimestamp2Unix( $old->t ), $signup );
+               }
+               $this->mUserDays = (int)(($now - $signup) / 86400);
+               $this->mUserEdits = $cur->n + $old->n;
+       }
+       
+       function displayList() {
+               global $wgOut, $wgOutputEncoding, $wgLang, $wgUser;
+               $sql = "SELECT log_timestamp,log_user_key FROM {$this->mDBname}.log ORDER BY log_user_key";
+               $res = wfQuery( $sql, DB_READ, "BoardVotePage::list" );
+               if ( wfNumRows( $res ) == 0 ) {
+                       $wgOut->addWikiText( wfMsg( "boardvote_novotes" ) );
+                       return;
+               }
+               $thisTitle = Title::makeTitle( NS_SPECIAL, "Boardvote" );
+               $sk = $wgUser->getSkin();
+               $dumpLink = $sk->makeKnownLinkObj( $thisTitle, wfMsg( "boardvote_dumplink" ), "action=dump" );
+               
+               $intro = wfMsg( "boardvote_listintro", $dumpLink );
+               $hTime = wfMsg( "boardvote_time" );
+               $hUser = wfMsg( "boardvote_user" );
+               $hContributing = wfMsg( "boardvote_contributing" );
+               $hVolunteer = wfMsg( "boardvote_volunteer" );
+
+               $s = "$intro <table border=1><tr><th>
+                   $hUser
+                 </th><th>
+                   $hTime
+                 </th></tr>";
+
+               while ( $row = wfFetchObject( $res ) ) {
+                       if ( $wgOutputEncoding != "utf-8" ) {
+                               $user = wfUtf8ToHTML( $row->log_user_key );
+                       } else {
+                               $user = $row->log_user_key;
+                       }
+                       $time = $wgLang->timeanddate( $row->log_timestamp );
+                       $s .= "<tr><td>
+                           $user
+                         </td><td>
+                           $time
+                         </td></tr>";
+               }
+               $s .= "</table>";
+               $wgOut->addHTML( $s );
+       }
+
+       function dump() {
+               global $wgOut, $wgOutputEncoding, $wgLang, $wgUser;
+
+               $userRights = $wgUser->getRights();
+               if ( in_array( "boardvote", $userRights ) ) {
+                       $admin = true;
+               } else {
+                       $admin = false;
+               }
+               
+               $sql = "SELECT * FROM {$this->mDBname}.log";
+               $res = wfQuery( $sql, DB_READ, "BoardVotePage::list" );
+               if ( wfNumRows( $res ) == 0 ) {
+                       $wgOut->addWikiText( wfMsg( "boardvote_novotes" ) );
+                       return;
+               }
+               $s = "<table border=1>";
+               if ( $admin ) {
+                       $s .= wfMsg( "boardvote_dumpheader" );
+               }
+               
+               while ( $row = wfFetchObject( $res ) ) {
+                       if ( $wgOutputEncoding != "utf-8" ) {
+                               $user = wfUtf8ToHTML( $row->log_user_key );
+                       } else {
+                               $user = $row->log_user_key;
+                       }
+                       $time = $wgLang->timeanddate( $row->log_timestamp );
+                       $record = nl2br( $row->log_record );
+                       if ( $admin ) {
+                               $edits = $row->log_edits == 0x7fffffff ? "many" : $row->log_edits;
+                               $days = $row->log_days == 0x7fffffff ? "many" : $row->log_days;
+                               $s .= "<tr><td>
+                                 $time
+                               </td><td>
+                                 $user
+                               </td><td>
+                                 $edits
+                               </td><td>
+                                 $days
+                               </td><td>
+                                 {$row->log_ip}
+                               </td><td>
+                                 {$row->log_ua}
+                               </td><td>
+                                 $record
+                               </td></tr>";
+                       } else {
+                               $s .= "<tr><td>$time</td><td>$user</td><td>$record</td></tr>";
+                       }
+               }
+               $s .= "</table>";
+               $wgOut->addHTML( $s );
+       }
+}
+
+SpecialPage::addPage( new BoardVotePage );
+
+global $wgMessageCache;
+$wgMessageCache->addMessages( array(
+# Board vote
+"boardvote"               => "Wikimedia Board of Trustees election",
+"boardvote_entry"         => 
+"* [[Special:Boardvote/vote|Vote]]
+* [[Special:Boardvote/list|List votes to date]]
+* [[Special:Boardvote/dump|Dump encrypted election record]]",
+"boardvote_intro"         => "<p>Please choose your preferred candidate for both the 
+Contributing Representative and the Volunteer Representative.</p>",
+"boardvote_intro_change"  => "<p>You have voted before. However you may change 
+your vote using the form below.</p>",
+"boardvote_abstain"       => "Abstain",
+"boardvote_footer"        => "&nbsp;",
+"boardvote_entered"       => "Thank you, your vote has been recorded.
+
+Following is your encrypted vote record. It will appear publicly at [[Special:Boardvote/dump]]. 
+
+<pre>$1</pre>
+
+[[Special:Boardvote/entry|Back]]",
+"boardvote_notloggedin"   => "You are not logged in. To vote, you must use an account
+which has existed for at least 90 days.",
+"boardvote_notqualified"  => "Sorry, your first contribution was only $1 days ago. 
+You need to have been contributing for at least 90 days to vote in this election.",
+"boardvote_novotes"       => "Nobody has voted yet.",
+"boardvote_contributing"  => "Contributing candidate",
+"boardvote_volunteer"     => "Volunteer candidate",
+"boardvote_time"          => "Time",
+"boardvote_user"          => "User",
+"boardvote_listintro"     => "<p>This is a list of all votes which have been recorded 
+to date. $1 for the full encrypted election record.</p>",
+"boardvote_dumplink"      => "Click here",
+"boardvote_dumpheader"    => "<caption><strong>Election administrator private dump</strong></caption>
+<tr><th>Time</th><th>User</th><th>Edits</th><th>Days</th>
+<th>IP</th><th>User agent</th><th>Record</th></tr>"
+
+));
+
+} # End of extension function
+
+?>
index 9bc9c98..08b9607 100644 (file)
@@ -398,4 +398,7 @@ $wgVolunteerCandidates = array();
 $wgGPGCommand = "gpg";
 $wgGPGRecipient = "boardvote";
 $wgGPGHomedir = false;
+
+# Extensions
+$wgExtensionFunctions = array();
 ?>
index 00ab811..515dd68 100644 (file)
@@ -332,47 +332,6 @@ function wfCleanQueryVar( $var )
        wfDebugDieBacktrace( "Call to obsolete function wfCleanQueryVar(); use wgRequest instead" );
 }
 
-function wfSpecialPage()
-{
-       global $wgUser, $wgOut, $wgTitle, $wgLang;
-
-       /* FIXME: this list probably shouldn't be language-specific, per se */
-       $validSP = $wgLang->getValidSpecialPages();
-       $sysopSP = $wgLang->getSysopSpecialPages();
-       $devSP = $wgLang->getDeveloperSpecialPages();
-
-       $wgOut->setArticleRelated( false );
-       $wgOut->setRobotpolicy( "noindex,follow" );
-
-       $bits = split( "/", $wgTitle->getDBkey(), 2 );
-       $t = $bits[0];
-       if( empty( $bits[1] ) ) {
-               $par = NULL;
-       } else {
-               $par = $bits[1];
-       }
-
-       if ( array_key_exists( $t, $validSP ) ||
-         ( $wgUser->isSysop() && array_key_exists( $t, $sysopSP ) ) ||
-         ( $wgUser->isDeveloper() && array_key_exists( $t, $devSP ) ) ) {
-               if($par !== NULL)
-                       $wgTitle = Title::makeTitle( Namespace::getSpecial(), $t );
-
-               $wgOut->setPageTitle( wfMsg( strtolower( $wgTitle->getText() ) ) );
-
-               $inc = "Special" . $t . ".php";
-               require_once( $inc );
-               $call = "wfSpecial" . $t;
-               $call( $par );
-       } else if ( array_key_exists( $t, $sysopSP ) ) {
-               $wgOut->sysopRequired();
-       } else if ( array_key_exists( $t, $devSP ) ) {
-               $wgOut->developerRequired();
-       } else {
-               $wgOut->errorpage( "nosuchspecialpage", "nospecialpagetext" );
-       }
-}
-
 function wfSearch( $s )
 {
        $se = new SearchEngine( $s );
index e3a44e9..66285e1 100755 (executable)
@@ -11,7 +11,8 @@ class MessageCache
 {
        var $mCache, $mUseCache, $mDisable, $mExpiry;
        var $mMemcKey, $mKeys, $mParserOptions, $mParser;
-       
+       var $mExtensionMessages;
+
        var $mInitialised = false;
 
        function initialise( &$memCached, $useDB, $expiry, $memcPrefix ) {
@@ -155,26 +156,29 @@ class MessageCache
                        return "&lt;$key&gt;";
                }
                
-               if ( $this->mDisable ) {
-                       return $this->transform( $wgLang->getMessage( $key ) );
-               }
-               $title = $wgLang->ucfirst( $key );
-               
                $message = false;
+               if ( !$this->mDisable ) {
+                       $title = $wgLang->ucfirst( $key );
+                       
 
-               # Try the cache
-               if ( $this->mUseCache && $this->mCache && array_key_exists( $title, $this->mCache ) ) {
-                       $message = $this->mCache[$title];
-               }
-               
-               # If it wasn't in the cache, load each message from the DB individually
-               if ( !$message && $useDB) {
-                       $result = wfGetArray( "cur", array("cur_text"), 
-                         array( "cur_namespace" => NS_MEDIAWIKI, "cur_title" => $title ),
-                         "MessageCache::get" );
-                       if ( $result ) {
-                               $message = $result->cur_text;
+                       # Try the cache
+                       if ( $this->mUseCache && $this->mCache && array_key_exists( $title, $this->mCache ) ) {
+                               $message = $this->mCache[$title];
                        }
+                       
+                       # If it wasn't in the cache, load each message from the DB individually
+                       if ( !$message && $useDB) {
+                               $result = wfGetArray( "cur", array("cur_text"), 
+                                 array( "cur_namespace" => NS_MEDIAWIKI, "cur_title" => $title ),
+                                 "MessageCache::get" );
+                               if ( $result ) {
+                                       $message = $result->cur_text;
+                               }
+                       }
+               }
+               # Try the extension array
+               if ( !$message ) {
+                       $message = @$this->mExtensionMessages[$key];
                }
 
                # Try the array in $wgLang
@@ -210,5 +214,14 @@ class MessageCache
        function enable() { $this->mDisable = false; }
        function disableTransform() { $this->mDisableTransform = true; }
 
+       function addMessage( $key, $value ) {
+               $this->mExtensionMessages[$key] = $value;
+       }
+
+       function addMessages( $messages ) {
+               foreach ( $messages as $key => $value ) {
+                       $this->mExtensionMessages[$key] = $value;
+               }
+       }
 }
 ?>
index dabad2b..7a66808 100644 (file)
@@ -58,6 +58,8 @@ require_once( "BlockCache.php" );
 require_once( "Parser.php" );
 require_once( "ParserCache.php" );
 require_once( "WebRequest.php" );
+require_once( "SpecialPage.php" );
+
 $wgRequest = new WebRequest();
 
 
@@ -187,6 +189,18 @@ $wgParserCache = new ParserCache();
 $wgParser = new Parser();
 $wgOut->setParserOptions( ParserOptions::newFromUser( $wgUser ) );
 
+if ( !$wgAllowSysopQueries ) {
+       SpecialPage::removePage( "Asksql" );
+}
+
+# Extension setup functions
+# Entries should be added to this variable during the inclusion 
+# of the extension file. This allows the extension to perform 
+# any necessary initialisation in the fully initialised environment
+foreach ( $wgExtensionFunctions as $func ) {
+       $func();
+}
+
 wfProfileOut( "$fname-misc" );
 wfProfileOut( $fname );
 
diff --git a/includes/SpecialBoardvote.php b/includes/SpecialBoardvote.php
deleted file mode 100644 (file)
index 8a52377..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-<?php
-
-function wfSpecialBoardvote( $par = "" ) {
-       global $wgRequest, $wgBoardVoteDB;
-
-       $form = new BoardVoteForm( $wgRequest, $wgBoardVoteDB );
-       if ( $par ) {
-               $form->mAction = $par;
-       }
-       
-       $form->execute();
-}
-
-class BoardVoteForm {
-       var $mPosted, $mContributing, $mVolunteer, $mDBname, $mUserDays, $mUserEdits;
-       var $mHasVoted, $mAction, $mUserKey;
-
-       function BoardVoteForm( &$request, $dbName ) {
-               global $wgUser, $wgDBname, $wgInputEncoding;
-
-               $this->mUserKey = iconv( $wgInputEncoding, "UTF-8", $wgUser->getName() ) . "@$wgDBname";
-               $this->mPosted = $request->wasPosted();
-               $this->mContributing = $request->getInt( "contributing" );
-               $this->mVolunteer = $request->getInt( "volunteer" );
-               $this->mDBname = $dbName;
-               $this->mHasVoted = $this->hasVoted( $wgUser );
-               $this->mAction = $request->getText( "action" );
-       }
-
-       function execute() {
-               global $wgUser;
-               if ( $this->mAction == "list" ) {
-                       $this->displayList();
-               } elseif ( $this->mAction == "dump" ) {
-                       $this->dump();
-               } elseif( $this->mAction == "vote" ) {
-                       if ( !$wgUser->getID() ) {
-                               $this->notLoggedIn();
-                       } else {
-                               $this->getQualifications( $wgUser );
-                               if ( $this->mUserDays < 90 ) {
-                                       $this->notQualified();
-                               } elseif ( $this->mPosted ) {
-                                       $this->logVote();
-                               } else {
-                                       $this->displayVote();
-                               }
-                       }
-               } else {
-                       $this->displayEntry();
-               }
-       }
-       
-       function displayEntry() {
-               global $wgOut;
-               $wgOut->addWikiText( wfMsg( "boardvote_entry" ) );
-       }
-
-       function hasVoted( &$user ) {
-               global $wgDBname;
-               $row = wfGetArray( $this->mDBname . ".vote", array( "1" ), 
-                 array( "vote_key" => $this->mUserKey ), "BoardVoteForm::getUserVote" );
-               if ( $row === false ) {
-                       return false;
-               } else {
-                       return true;
-               }
-       }
-
-       function logVote() {
-               global $wgUser, $wgDBname, $wgIP, $wgOut;
-               $now = wfTimestampNow();
-               $record = $this->encrypt( $this->mContributing, $this->mVolunteer );
-               $db = $this->mDBname;
-
-               # Add vote to log
-               wfInsertArray( "$db.log", array(
-                       "log_user" => $wgUser->getID(),
-                       "log_user_text" => $wgUser->getName(),
-                       "log_user_key" => $this->mUserKey,
-                       "log_wiki" => $wgDBname,
-                       "log_edits" => $this->mUserEdits,
-                       "log_days" => $this->mUserDays,
-                       "log_record" => $record,
-                       "log_ip" => $wgIP,
-                       "log_xff" => @$_SERVER['HTTP_X_FORWARDED_FOR'],
-                       "log_ua" => $_SERVER['HTTP_USER_AGENT'],
-                       "log_timestamp" => $now
-               ));
-
-               # Record vote in non-duplicating vote table
-               $sql = "REPLACE INTO $db.vote (vote_key,vote_record) " .
-                 "VALUES ('". wfStrencode( $this->mUserKey ) . "','" . wfStrencode( $record ) . "')";
-               wfQuery( $sql, DB_WRITE );
-
-               $wgOut->addWikiText( wfMsg( "boardvote_entered", $record ) );
-       }
-       
-       function displayVote() {
-               global $wgContributingCandidates, $wgVolunteerCandidates, $wgOut;
-               
-               $thisTitle = Title::makeTitle( NS_SPECIAL, "Boardvote" );
-               $action = $thisTitle->getLocalURL( "action=vote" );
-               if ( $this->mHasVoted ) {
-                       $intro = wfMsg( "boardvote_intro_change" );
-               } else {
-                       $intro = wfMsg( "boardvote_intro" );
-               }
-               $contributing = wfMsg( "boardvote_contributing" );
-               $volunteer = wfMsg( "boardvote_volunteer" );
-               $ok = wfMsg( "ok" );
-               
-               $candidatesV = $candidatesC = array();
-               foreach( $wgContributingCandidates as $i => $candidate ) {
-                       $candidatesC[] = array( $i, $candidate );
-               }
-               foreach ( $wgVolunteerCandidates as $i => $candidate ) {
-                       $candidatesV[] = array( $i, $candidate );
-               }
-
-               srand ((float)microtime()*1000000);
-               shuffle( $candidatesC );
-               shuffle( $candidatesV );
-
-               $text = "
-                 $intro
-                 <form name=\"boardvote\" id=\"boardvote\" method=\"post\" action=\"$action\">
-                 <table border='0'><tr><td colspan=2>
-                 <h2>$contributing</h2>
-                 </td></tr>";
-               $text .= $this->voteEntry( -1, wfMsg( "boardvote_abstain" ), "contributing" );
-               foreach ( $candidatesC as $candidate ) {
-                       $text .= $this->voteEntry( $candidate[0], $candidate[1], "contributing" );
-               }
-               $text .= "
-                 <tr><td colspan=2>
-                 <h2>$volunteer</h2></td></tr>";
-               $text .= $this->voteEntry( -1, wfMsg( "boardvote_abstain" ), "volunteer" );
-               foreach ( $candidatesV as $candidate ) {
-                       $text .= $this->voteEntry( $candidate[0], $candidate[1], "volunteer" );
-               }
-               
-               $text .= "<tr><td>&nbsp;</td><td>
-                 <input name=\"submit\" type=\"submit\" value=\"$ok\">
-                 </td></tr></table></form>";
-               $text .= wfMsg( "boardvote_footer" );
-               $wgOut->addHTML( $text );
-       }
-
-       function voteEntry( $index, $candidate, $name ) {
-               if ( $index == -1 ) {
-                       $checked = " CHECKED";
-               } else {
-                       $checked = "";
-               }
-
-               return "
-               <tr><td align=\"right\">
-                 <input type=\"radio\" name=\"$name\" value=\"$index\"$checked>
-               </td><td align=\"left\">
-                 $candidate
-               </td></tr>";
-       }
-
-       function notLoggedIn() {
-               global $wgOut;
-               $wgOut->addWikiText( wfMsg( "boardvote_notloggedin" ) );
-       }
-       
-       function notQualified() {
-               global $wgOut;
-               $wgOut->addWikiText( wfMsg( "boardvote_notqualified", $this->mUserDays ) );
-       }
-       
-       function encrypt( $contributing, $volunteer ) {
-               global $wgVolunteerCandidates, $wgContributingCandidates;
-               global $wgGPGCommand, $wgGPGRecipient, $wgGPGHomedir;
-               $file = @fopen( "/dev/urandom", "r" );
-               if ( $file ) {
-                       $salt = implode( "", unpack( "H*", fread( $file, 64 ) ));
-                       fclose( $file );
-               } else {
-                       $salt = Parser::getRandomString() . Parser::getRandomString();
-               }
-               $record = 
-                 "Contributing: $contributing (" .$wgContributingCandidates[$contributing] . ")\n" .
-                 "Volunteer: $volunteer (" . $wgVolunteerCandidates[$volunteer] . ")\n" .
-                 "Salt: $salt\n";
-               # Get file names
-               $input = tempnam( "/tmp", "gpg_" );
-               $output = tempnam( "/tmp", "gpg_" );
-
-               # Write unencrypted record
-               $file = fopen( $input, "w" );
-               fwrite( $file, $record );
-               fclose( $file );
-
-               # Call GPG
-               $command = wfEscapeShellArg( $wgGPGCommand ) . " --batch --yes -ear " . 
-                 wfEscapeShellArg( $wgGPGRecipient ) . " -o " . wfEscapeShellArg( $output );
-               if ( $wgGPGHomedir ) {
-                       $command .= " --homedir " . wfEscapeShellArg( $wgGPGHomedir );
-               } 
-               $command .= " " . wfEscapeShellArg( $input );
-
-               shell_exec( $command );
-
-               # Read result
-               $result = file_get_contents( $output );
-
-               # Delete temporary files
-               unlink( $input );
-               unlink( $output );
-               
-               return $result;
-       }
-
-       function getQualifications( &$user ) {
-               $id = $user->getID();
-               if ( !$id ) {
-                       $this->mUserDays = 0;
-                       $this->mUserEdits = 0;
-                       return;
-               }
-
-               # Count contributions and find earliest edit
-               # First cur
-               $sql = "SELECT COUNT(*) as n, MIN(cur_timestamp) as t FROM cur WHERE cur_user=$id";
-               $res = wfQuery( $sql, DB_READ, "BoardVoteForm::getQualifications" );
-               $cur = wfFetchObject( $res );
-               wfFreeResult( $res );
-
-               # If the user has stacks of contributions, don't check old as well
-               $now = time();
-               if ( is_null( $cur->t ) ) {
-                       $signup = $now;
-               } else {
-                       $signup = wfTimestamp2Unix( $cur->t );
-               }
-               
-               $days = ($now - $signup) / 86400;
-               if ( $cur->n > 400 && $days > 180 ) {
-                       $this->mUserDays = 0x7fffffff;
-                       $this->mUserEdits = 0x7fffffff;
-                       return;
-               }
-
-               # Now check old
-               $sql = "SELECT COUNT(*) as n, MIN(old_timestamp) as t FROM old WHERE old_user=$id";
-               $res = wfQuery( $sql, DB_READ, "BoardVoteForm::getQualifications" );
-               $old = wfFetchObject( $res );
-               wfFreeResult( $res );
-               
-               if ( !is_null( $old->t ) ) {
-                       $signup = min( wfTimestamp2Unix( $old->t ), $signup );
-               }
-               $this->mUserDays = (int)(($now - $signup) / 86400);
-               $this->mUserEdits = $cur->n + $old->n;
-       }
-       
-       function displayList() {
-               global $wgOut, $wgOutputEncoding, $wgLang, $wgUser;
-               $sql = "SELECT log_timestamp,log_user_key FROM {$this->mDBname}.log";
-               $res = wfQuery( $sql, DB_READ, "BoardVoteForm::list" );
-               if ( wfNumRows( $res ) == 0 ) {
-                       $wgOut->addWikiText( wfMsg( "boardvote_novotes" ) );
-                       return;
-               }
-               $thisTitle = Title::makeTitle( NS_SPECIAL, "Boardvote" );
-               $sk = $wgUser->getSkin();
-               $dumpLink = $sk->makeKnownLinkObj( $thisTitle, wfMsg( "boardvote_dumplink" ), "action=dump" );
-               
-               $intro = wfMsg( "boardvote_listintro", $dumpLink );
-               $hTime = wfMsg( "boardvote_time" );
-               $hUser = wfMsg( "boardvote_user" );
-               $hContributing = wfMsg( "boardvote_contributing" );
-               $hVolunteer = wfMsg( "boardvote_volunteer" );
-
-               $s = "$intro <table border=0><tr><th>
-                   $hTime
-                 </th><th>
-                   $hUser
-                 </th></tr>";
-
-               while ( $row = wfFetchObject( $res ) ) {
-                       if ( $wgOutputEncoding != "utf-8" ) {
-                               $user = wfUtf8ToHTML( $row->log_user_key );
-                       } else {
-                               $user = $row->log_user_key;
-                       }
-                       $time = $wgLang->timeanddate( $row->log_timestamp );
-                       $s .= "<tr><td>
-                           $time
-                         </td><td>
-                           $user
-                         </td></tr>";
-               }
-               $s .= "</table>";
-               $wgOut->addHTML( $s );
-       }
-
-       function dump() {
-               global $wgOut, $wgOutputEncoding, $wgLang, $wgUser;
-
-               $userRights = $wgUser->getRights();
-               if ( in_array( "boardvote", $userRights ) ) {
-                       $admin = true;
-               } else {
-                       $admin = false;
-               }
-               
-               $sql = "SELECT * FROM {$this->mDBname}.log";
-               $res = wfQuery( $sql, DB_READ, "BoardVoteForm::list" );
-               if ( wfNumRows( $res ) == 0 ) {
-                       $wgOut->addWikiText( wfMsg( "boardvote_novotes" ) );
-                       return;
-               }
-               $s = "<table border=1>";
-               if ( $admin ) {
-                       $s .= wfMsg( "boardvote_dumpheader" );
-               }
-               
-               while ( $row = wfFetchObject( $res ) ) {
-                       if ( $wgOutputEncoding != "utf-8" ) {
-                               $user = wfUtf8ToHTML( $row->log_user_key );
-                       } else {
-                               $user = $row->log_user_key;
-                       }
-                       $time = $wgLang->timeanddate( $row->log_timestamp );
-                       $record = nl2br( $row->log_record );
-                       if ( $admin ) {
-                               $edits = $row->log_edits == 0x7fffffff ? "many" : $row->log_edits;
-                               $days = $row->log_days == 0x7fffffff ? "many" : $row->log_days;
-                               $s .= "<tr><td>
-                                 $time
-                               </td><td>
-                                 $user
-                               </td><td>
-                                 $edits
-                               </td><td>
-                                 $days
-                               </td><td>
-                                 {$row->log_ip}
-                               </td><td>
-                                 {$row->log_ua}
-                               </td><td>
-                                 $record
-                               </td></tr>";
-                       } else {
-                               $s .= "<tr><td>$time</td><td>$user</td><td>$record</td></tr>";
-                       }
-               }
-               $s .= "</table>";
-               $wgOut->addHTML( $s );
-       }
-}
-?>
diff --git a/includes/SpecialPage.php b/includes/SpecialPage.php
new file mode 100644 (file)
index 0000000..01e7185
--- /dev/null
@@ -0,0 +1,180 @@
+<?php
+
+$wgSpecialPages = array(
+       "Userlogin"             => new UnlistedSpecialPage( "Userlogin" ),
+       "Userlogout"    => new UnlistedSpecialPage( "Userlogout" ),
+       "Preferences"   => new SpecialPage( "Preferences" ),
+       "Watchlist"             => new SpecialPage( "Watchlist" ),
+       "Recentchanges" => new SpecialPage( "Recentchanges" ),
+       "Upload"                => new SpecialPage( "Upload" ),
+       "Imagelist"             => new SpecialPage( "Imagelist" ),
+       "Listusers"             => new SpecialPage( "Listusers" ),
+       "Statistics"    => new SpecialPage( "Statistics" ),
+       "Randompage"    => new SpecialPage( "Randompage" ),
+       "Lonelypages"   => new SpecialPage( "Lonelypages" ),
+       "Unusedimages"  => new SpecialPage( "Unusedimages" ),
+       "Popularpages"  => new SpecialPage( "Popularpages" ),
+       "Wantedpages"   => new SpecialPage( "Wantedpages" ),
+       "Shortpages"    => new SpecialPage( "Shortpages" ),
+       "Longpages"             => new SpecialPage( "Longpages" ),
+       "Newpages"              => new SpecialPage( "Newpages" ),
+       "Ancientpages"  => new SpecialPage( "Ancientpages" ),
+       "Deadendpages"  => new SpecialPage( "Deadendpages" ),
+       "Allpages"              => new SpecialPage( "Allpages" ),
+       "Ipblocklist"   => new SpecialPage( "Ipblocklist" ),
+       "Maintenance"   => new SpecialPage( "Maintenance" ),
+       "Specialpages"  => new UnlistedSpecialPage( "Specialpages" ),
+       "Contributions" => new UnlistedSpecialPage( "Contributions" ),
+       "Emailuser"             => new UnlistedSpecialPage( "Emailuser" ),
+       "Whatlinkshere" => new UnlistedSpecialPage( "Whatlinkshere" ),
+       "Recentchangeslinked" => new UnlistedSpecialPage( "Recentchangeslinked" ),
+       "Movepage"              => new UnlistedSpecialPage( "Movepage" ),
+       "Blockme"       => new UnlistedSpecialPage( "Blockme" ),
+       "Booksources"   => new SpecialPage( "Booksources" ),
+       "Categories"    => new SpecialPage( "Categories" ),
+       "Export"                => new SpecialPage( "Export" ),
+       "Version"               => new SpecialPage( "Version" ),
+       "Allmessages"   => new SpecialPage( "Allmessages" ),
+       "Search"                => new UnlistedSpecialPage( "Search" ),
+       "Blockip"               => new SpecialPage( "Blockip", "sysop" ),
+       "Asksql"                => new SpecialPage( "Asksql", "sysop" ),
+       "Undelete"              => new SpecialPage( "Undelete", "sysop" ),
+       "Makesysop"             => new SpecialPage( "Makesysop", "sysop" ),
+       "Import"                => new SpecialPage( "Import", "sysop" ),
+       "Lockdb"                => new SpecialPage( "Lockdb", "developer" ),
+       "Unlockdb"              => new SpecialPage( "Unlockdb", "developer" )
+);
+
+class SpecialPage
+{
+       /* private */ var $mName, $mRestriction, $mListed, $mFunction, $mFile;
+       
+       /* static */ function addPage( &$obj ) {
+               global $wgSpecialPages;
+               $wgSpecialPages[$obj->mName] = $obj;
+       }
+
+       /* static */ function removePage( $name ) {
+               global $wgSpecialPages;
+               unset( $wgSpecialPages[$name] );
+       }
+
+       /* static */ function &getPage( $name ) {
+               global $wgSpecialPages;
+               if ( array_key_exists( $name, $wgSpecialPages ) ) {
+                       return $wgSpecialPages[$name];
+               } else {
+                       return NULL;
+               }
+       }
+
+       # Execute a special page path, which may contain slashes
+       /* static */ function executePath( &$title ) {
+               global $wgSpecialPages, $wgOut, $wgTitle;
+
+               $bits = split( "/", $title->getDBkey(), 2 );
+               $name = $bits[0];
+               if( empty( $bits[1] ) ) {
+                       $par = NULL;
+               } else {
+                       $par = $bits[1];
+               }
+
+               $page =& SpecialPage::getPage( $name );
+               if ( is_null( $page ) ) {
+                       $wgOut->setArticleRelated( false );
+                       $wgOut->setRobotpolicy( "noindex,follow" );
+                       $wgOut->errorpage( "nosuchspecialpage", "nospecialpagetext" );
+               } else {
+                       if($par !== NULL) {
+                               $wgTitle = Title::makeTitle( NS_SPECIAL, $name );
+                       } else {
+                               $wgTitle = $title;
+                       }
+
+                       $page->execute( $par );
+               }
+       }
+
+       function SpecialPage( $name = "", $restriction = "", $listed = true, $function = false, $file = "default" ) {
+               $this->mName = $name;
+               $this->mRestriction = $restriction;
+               $this->mListed = $listed;
+               if ( $function == false ) {
+                       $this->mFunction = "wfSpecial{$name}";
+               } else {
+                       $this->mFunction = $function;
+               }
+               if ( $file === "default" ) { 
+                       $this->mFile = "Special{$name}.php";
+               } else {
+                       $this->mFile = $file;
+               }
+       }
+
+       function getName() { return $this->mName; }
+       function getRestriction() { return $this->mRestriction; }
+       function isListed() { return $this->mListed; }
+
+       function userCanExecute( &$user ) {
+               if ( $this->mRestriction == "" ) {
+                       return true;
+               } else {
+                       if ( in_array( $this->mRestriction, $user->getRights() ) ) {
+                               return true;
+                       } else {
+                               return false;
+                       }
+               }
+       }
+
+       function displayRestrictionError() {
+               if ( $this->mRestriction == "developer" ) {
+                       $wgOut->developerRequired();
+               } else {
+                       $wgOut->sysopRequired();
+               }
+       }
+       
+       function setHeaders() {
+               global $wgOut;
+               $wgOut->setArticleRelated( false );
+               $wgOut->setRobotPolicy( "noindex,follow" );
+               $wgOut->setPageTitle( $this->getDescription() );
+       }
+
+       function execute( $par ) {
+               global $wgUser, $wgOut, $wgTitle;
+
+               $this->setHeaders();
+               
+               if ( $this->userCanExecute( $wgUser ) ) {
+                       if ( $this->mFile ) {
+                               require_once( $this->mFile );
+                       }               
+                       $func = $this->mFunction;
+                       $func( $par );
+               } else {
+                       $this->displayRestrictionError();
+               }
+       }
+
+       function getDescription() {
+               return wfMsg( strtolower( $this->mName ) );
+       }
+
+       function getTitle() {
+               return Title::makeTitle( NS_SPECIAL, $this->mName );
+       }
+
+       function setListed( $listed ) {
+               return wfSetVar( $this->mListed, $listed );
+       }
+}
+
+class UnlistedSpecialPage extends SpecialPage
+{
+       function UnlistedSpecialPage( $name, $restriction = "", $function = false, $file = "default" ) {
+               SpecialPage::SpecialPage( $name, $restriction, false, $function, $file );
+       }
+}
index 03f2750..094ae61 100644 (file)
@@ -2,47 +2,57 @@
 
 function wfSpecialSpecialpages()
 {
-       global $wgLang, $wgOut, $wgUser;
+       global $wgLang, $wgOut, $wgUser, $wgSpecialPages;
        
-       # sub function generating the list of pages
-       #   $SP      : the list of pages
-       #   $heading : header to be used
-       #   $sk      : skin object ???
-       
-       function wfSpecialSpecialpages_gen($SP,$heading,$sk)
-       {
-               global $wgLang, $wgOut, $wgAllowSysopQueries;
-
-               $wgOut->addHTML( "<h2>" . wfMsg( $heading ) . "</h2>\n<ul>" );
-               foreach ( $SP as $name => $desc ) {
-                       if( "" == $desc ) {
-                               continue;
-                       }
-                       if( "Asksql" == $name && !$wgAllowSysopQueries ) {
-                               continue;
-                       }
-                       $link = $sk->makeKnownLink( $wgLang->specialPage( $name ), $desc );
-                       $wgOut->addHTML( "<li>{$link}</li>\n" );
-               }
-               $wgOut->addHTML( "</ul>\n" );
-       }
-
        $wgOut->setRobotpolicy( "index,nofollow" );
        $sk = $wgUser->getSkin();       
 
+       # Categorise special pages
+
+       $pages = array(
+         "" => array(),
+         "sysop" => array(),
+         "developer" => array()
+       );
+
+       foreach ( $wgSpecialPages as $page ) {
+               $pages[$page->getRestriction()][$page->getName()] = $page;
+       }
+
+
        # all users special pages
-       wfSpecialSpecialpages_gen($wgLang->getValidSpecialPages(),"spheading",$sk);
+       wfSpecialSpecialpages_gen($pages[""],"spheading",$sk);
 
        # sysops only special pages
        if ( $wgUser->isSysop() ) {
-               wfSpecialSpecialpages_gen($wgLang->getSysopSpecialPages(),"sysopspheading",$sk);
+               wfSpecialSpecialpages_gen($pages["sysop"],"sysopspheading",$sk);
        }
 
        # developers only special pages
        if ( $wgUser->isDeveloper() ) {
-               wfSpecialSpecialpages_gen($wgLang->getDeveloperSpecialPages(),"developerspheading",$sk);
+               wfSpecialSpecialpages_gen($pages["developer"],"developerspheading",$sk);
+
+       }
+}
 
+# sub function generating the list of pages
+#   $pages   : the list of pages
+#   $heading : header to be used
+#   $sk      : skin object ???
+
+function wfSpecialSpecialpages_gen($pages,$heading,$sk)
+{
+       global $wgLang, $wgOut, $wgAllowSysopQueries;
+
+       $wgOut->addHTML( "<h2>" . wfMsg( $heading ) . "</h2>\n<ul>" );
+       foreach ( $pages as $name => $page ) {
+               if( !$page->isListed() ) {
+                       continue;
+               }
+               $link = $sk->makeKnownLinkObj( $page->getTitle(), $page->getDescription() );
+               $wgOut->addHTML( "<li>{$link}</li>\n" );
        }
+       $wgOut->addHTML( "</ul>\n" );
 }
 
 ?>
index d2ec9fc..b52395b 100644 (file)
--- a/index.php
+++ b/index.php
@@ -77,7 +77,7 @@ if ( $search = $wgRequest->getText( 'search' ) ) {
        /* redirect to canonical url, make it a 301 to allow caching */
        $wgOut->redirect( $wgTitle->getFullURL(), '301');
 } else if ( Namespace::getSpecial() == $wgTitle->getNamespace() ) {
-       wfSpecialPage();
+       SpecialPage::executePath( $wgTitle );
 } else {
        if ( Namespace::getMedia() == $wgTitle->getNamespace() ) {
                $wgTitle = Title::makeTitle( Namespace::getImage(), $wgTitle->getDBkey() );
index 96cb90f..81116a3 100644 (file)
@@ -381,65 +381,6 @@ $wgLanguageNamesEn =& $wgLanguageNames;
        MAG_SERVER               => array( 0,    "SERVER"                 )
 );
 
-# All special pages have to be listed here: a description of ""
-# will make them not show up on the "Special Pages" page, which
-# is the right thing for some of them (such as the "targeted" ones).
-#
-/* private */ $wgValidSpecialPagesEn = array(
-       "Userlogin"             => "",
-       "Userlogout"    => "",
-       "Preferences"   => "Set my user preferences",
-       "Watchlist"             => "My watchlist",
-       "Recentchanges" => "Recently updated pages",
-       "Upload"                => "Upload image files",
-       "Imagelist"             => "Image list",
-       "Listusers"             => "Registered users",
-       "Statistics"    => "Site statistics",
-       "Randompage"    => "Random article",
-
-       "Lonelypages"   => "Orphaned articles",
-       "Unusedimages"  => "Orphaned images",
-       "Popularpages"  => "Popular articles",
-       "Wantedpages"   => "Most wanted articles",
-       "Shortpages"    => "Short articles",
-       "Longpages"             => "Long articles",
-       "Newpages"              => "Newly created articles",
-       "Ancientpages"  => "Oldest articles",
-       "Deadendpages"  => "Dead-end pages",
-#      "Intl"                => "Interlanguage Links",
-       "Allpages"              => "All pages by title",
-
-       "Ipblocklist"   => "Blocked users/IP addresses",
-       "Maintenance"   => "Maintenance page",
-       "Specialpages"  => "",
-       "Contributions" => "",
-       "Emailuser"             => "",
-       "Whatlinkshere" => "",
-       "Recentchangeslinked" => "",
-       "Movepage"              => "",
-       "Blockme"       => "",
-       "Booksources"   => "External book sources",
-       "Categories"    => "Page categories",
-       "Export"                => "XML page export",
-       "Version"               => "Show MediaWiki version",
-       "Allmessages"   => "All system messages",
-       "Search"                => ""
-#      "Boardvote"     => "Wikimedia Foundation Board of Trustees election"
-);
-
-/* private */ $wgSysopSpecialPagesEn = array(
-       "Blockip"               => "Block a user/IP address",
-       "Asksql"                => "Query the database",
-       "Undelete"              => "Restore deleted pages",
-       "Makesysop"             => "Turn a user into a sysop",
-       "Import"                => "Import a page with history",
-);
-
-/* private */ $wgDeveloperSpecialPagesEn = array(
-       "Lockdb"                => "Make database read-only",
-       "Unlockdb"              => "Restore DB write access"
-);
-
 #-------------------------------------------------------------------
 # Default messages
 #-------------------------------------------------------------------
@@ -1594,42 +1535,8 @@ amusement.",
 "lastmodifiedby" => "This page was last modified $1 by $2.",
 "and" => "and",
 "othercontribs" => "Based on work by $1.",
-"siteusers" => "$wgSitename user(s) $1",
-
-# Board vote
-"boardvote" => "Wikimedia Board of Trustees election",
-"boardvote_entry" => 
-"* [[Special:Boardvote/vote|Vote]]
-* [[Special:Boardvote/list|List votes to date]]
-* [[Special:Boardvote/dump|Dump encrypted election record]]",
-"boardvote_intro" => "<p>Please choose your preferred candidate for both the 
-Contributing Representative and the Volunteer Representative.</p>",
-"boardvote_intro_change" => "<p>You have voted before. However you may change 
-your vote using the form below.</p>",
-"boardvote_abstain" => "Abstain",
-"boardvote_footer" => "&nbsp;",
-"boardvote_entered" => "Thank you, your vote has been recorded.
-
-Following is your encrypted vote record. It will appear publicly at [[Special:Boardvote/dump]]. 
-
-<pre>$1</pre>
-
-[[Special:Boardvote/entry|Back]]",
-"boardvote_notloggedin" => "You are not logged in. To vote, you must use an account
-which has existed for at least 90 days.",
-"boardvote_notqualified" => "Sorry, your first contribution was only $1 days ago. 
-You need to have been contributing for at least 90 days to vote in this election.",
-"boardvote_novotes" => "Nobody has voted yet.",
-"boardvote_contributing" => "Contributing candidate",
-"boardvote_volunteer" => "Volunteer candidate",
-"boardvote_time" => "Time",
-"boardvote_user" => "User",
-"boardvote_listintro" => "<p>This is a list of all votes which have been recorded 
-to date. $1 for the full encrypted election record.</p>",
-"boardvote_dumplink" => "Click here",
-"boardvote_dumpheader" => "<caption><strong>Election administrator private dump</strong></caption>
-<tr><th>Time</th><th>User</th><th>Edits</th><th>Days</th>
-<th>IP</th><th>User agent</th><th>Record</th></tr>"
+"siteusers" => "$wgSitename user(s) $1"
+
 );
 
 #--------------------------------------------------------------------------
index a365c48..0fc4391 100644 (file)
@@ -13,15 +13,9 @@ CREATE TABLE log (
        log_xff varchar(255) not null default '',
        log_ua varchar(255) not null default '',
        log_timestamp char(14) not null default '',
-       unique key log_id (log_id)
-);
-
-CREATE TABLE vote (
-       vote_key varchar(255) not null default '',
-       vote_record blob not null default '',
-       vote_contributing text not null default '',
-       vote_volunteer text not null default '',
-       unique key vote_key (vote_key)
+       log_current tinyint(1) not null default 0,
+       unique index log_id (log_id),
+       index log_user_key (log_user_key)
 );