Fix for bug http://bugzilla.wikimedia.org/show_bug.cgi?id=1138 (ip block related).
authorNicolas Weeger <ryo_saeba@users.mediawiki.org>
Mon, 14 Feb 2005 23:21:07 +0000 (23:21 +0000)
committerNicolas Weeger <ryo_saeba@users.mediawiki.org>
Mon, 14 Feb 2005 23:21:07 +0000 (23:21 +0000)
New behaviour: check slave when user asks for the edit page, nothing when previewing, master when saving the page. Don't use memcache, as apparently it was causing issues.

includes/BlockCache.php
includes/EditPage.php
includes/User.php

index 8f9a5a6..6f53e61 100644 (file)
@@ -1,139 +1 @@
-<?php
-/**
- * Contain the blockcache class
- * @package MediaWiki
- */
-
-/**
- * Object for fast lookup of IP blocks
- * Represents a memcached value, and in some sense, the entire ipblocks table
- * @package MediaWiki
- */
-class BlockCache
-{
-       var $mData = false, $mMemcKey;
-
-       /**
-        * Constructor
-        * Create a new BlockCache object
-        *
-        * @param Boolean $deferLoad   specifies whether to immediately load the data from memcached.
-        * @param String $dbName       specifies the memcached dbName prefix to be used. Defaults to $wgDBname.
-        */
-       function BlockCache( $deferLoad = false, $dbName = '' ) {
-               global $wgDBname;
-
-               if ( $dbName == '' ) {
-                       $dbName = $wgDBname;
-               }
-
-               $this->mMemcKey = $dbName.':ipblocks';
-
-               if ( !$deferLoad ) {
-                       $this->load();
-               }
-       }
-
-       /**
-        * Load the blocks from the database and save them to memcached
-        */
-       function loadFromDB() {
-               global $wgUseMemCached, $wgMemc;
-               $this->mData = array();
-               # Selecting FOR UPDATE is a convenient way to serialise the memcached and DB operations,
-               # which is necessary even though we don't update the DB
-               if ( $wgUseMemCached ) {
-                       Block::enumBlocks( 'wfBlockCacheInsert', '', EB_FOR_UPDATE );
-                       $wgMemc->set( $this->mMemcKey, $this->mData, 0 );
-               } else {
-                       Block::enumBlocks( 'wfBlockCacheInsert', '' );
-               }
-       }
-               
-       /**
-        * Load the cache from memcached or, if that's not possible, from the DB
-        */
-       function load() {
-               global $wgUseMemCached, $wgMemc;
-
-               if ( $this->mData === false) {
-                       # Try memcached
-                       if ( $wgUseMemCached ) {
-                               $this->mData = $wgMemc->get( $this->mMemcKey );
-                       }
-
-                       if ( !is_array( $this->mData ) ) {
-                               $this->loadFromDB();
-                       }
-               }
-       }
-
-       /**
-        * Add a block to the cache
-        *
-        * @param Object &$block   Reference to a "Block" object.
-        */
-       function insert( &$block ) {
-               if ( $block->mUser == 0 ) {
-                       $nb = $block->getNetworkBits();
-                       $ipint = $block->getIntegerAddr();
-                       $index = $ipint >> ( 32 - $nb );
-
-                       if ( !array_key_exists( $nb, $this->mData ) ) {
-                               $this->mData[$nb] = array();
-                       }
-               
-                       $this->mData[$nb][$index] = 1;
-               }
-       }
-       
-       /**
-        * Find out if a given IP address is blocked
-        *
-        * @param String $ip   IP address
-        */
-       function get( $ip ) {
-               $this->load();
-               $ipint = ip2long( $ip );
-               $blocked = false;
-
-               foreach ( $this->mData as $networkBits => $blockInts ) {
-                       if ( array_key_exists( $ipint >> ( 32 - $networkBits ), $blockInts ) ) {
-                               $blocked = true;
-                               break;
-                       }
-               }
-               if ( $blocked ) {
-                       # Clear low order bits
-                       if ( $networkBits != 32 ) {
-                               $ip .= '/'.$networkBits;
-                               $ip = Block::normaliseRange( $ip );
-                       }
-                       $block = new Block();
-                       $block->load( $ip );
-               } else {
-                       $block = false;
-               }
-
-               return $block;
-       }
-
-       /**
-        * Clear the local cache
-        * There was once a clear() to clear memcached too, but I deleted it
-        */
-       function clearLocal() {
-               $this->mData = false;
-       }
-}
-
-/**
- * Add a block to the global $wgBlockCache
- *
- * @param Object $block  A "Block"-object
- * @param Any    $tag    unused
- */
-function wfBlockCacheInsert( $block, $tag ) {
-       global $wgBlockCache;
-       $wgBlockCache->insert( $block );
-}
+<?php/** * Blocks and bans object * @package MediaWiki *//** * Some globals */define ( 'EB_KEEP_EXPIRED', 1 );define ( 'EB_FOR_UPDATE', 2 );/** * The block class * 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 * * @todo This could be used everywhere, but it isn't. * @package MediaWiki */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 = '' )     {               $this->mAddress = $address;             $this->mUser = $user;           $this->mBy = $by;               $this->mReason = $reason;               $this->mTimestamp = wfTimestamp(TS_MW,$timestamp);              $this->mAuto = $auto;           if( empty( $expiry ) ) {                        $this->mExpiry = $expiry;               } else {                        $this->mExpiry = wfTimestamp( TS_MW, $expiry );         }                               $this->mForUpdate = false;              $this->initialiseRange();       }               /*static*/ function newFromDB( $address, $user = 0, $killExpired = true )       {               $ban = new Block();             $ban->load( $address, $user, $killExpired );            return $ban;    }               function clear()        {               $mAddress = $mReason = $mTimestamp = '';                $mUser = $mBy = 0;      }       /**      * Get a ban from the DB, with either the given address or the given username    */     function load( $address = '', $user = 0, $killExpired = true )  {               $fname = 'Block::load';         wfDebug( "Block::load: '$address', '$user', $killExpired\n" );          $ret = false;           $killed = false;                if ( $this->forUpdate() ) {                     $db =& wfGetDB( DB_MASTER );                    $options = 'FOR UPDATE';                } else {                        $db =& wfGetDB( DB_SLAVE );                     $options = '';          }               $ipblocks = $db->tableName( 'ipblocks' );               if ( 0 == $user && $address=='' ) {                     $sql = "SELECT * from $ipblocks $options";              } elseif ($address=="") {                       $sql = "SELECT * FROM $ipblocks WHERE ipb_user={$user} $options";               } elseif ($user=="") {                  $sql = "SELECT * FROM $ipblocks WHERE ipb_address='" . $db->strencode( $address ) . "' $options";               } elseif ( $options=='' ) {                     # If there are no optiones (e.g. FOR UPDATE), use a UNION                       # so that the query can make efficient use of indices                   $sql = "SELECT * FROM $ipblocks WHERE ipb_address='" . $db->strencode( $address ) .                             "' UNION SELECT * FROM $ipblocks WHERE ipb_user={$user}";               } 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 ) .                            "' OR ipb_user={$user}) $options";              }               $res = $db->query( $sql, $fname );              if ( 0 == $db->numRows( $res ) ) {                      # User is not blocked                   $this->clear();         } else {                        # Get first block                       $row = $db->fetchObject( $res );                        $this->initFromRow( $row );                     if ( $killExpired ) {                           # If requested, delete expired rows                             do {                                    $killed = $this->deleteIfExpired();                                     if ( $killed ) {                                                $row = $db->fetchObject( $res );                                                if ( $row ) {                                                   $this->initFromRow( $row );                                             }                                       }                               } while ( $killed && $row );                                                            # If there were any left after the killing finished, return true                                if ( !$row ) {                                  $ret = false;                                   $this->clear();                         } else {                                        $ret = true;                            }                       } else {                                $ret = true;                    }               }               $db->freeResult( $res );                return $ret;    }               function initFromRow( $row )    {               $this->mAddress = $row->ipb_address;            $this->mReason = $row->ipb_reason;              $this->mTimestamp = wfTimestamp(TS_MW,$row->ipb_timestamp);             $this->mUser = $row->ipb_user;          $this->mBy = $row->ipb_by;              $this->mAuto = $row->ipb_auto;          $this->mId = $row->ipb_id;              $this->mExpiry = $row->ipb_expiry ?                     wfTimestamp(TS_MW,$row->ipb_expiry) :                   $row->ipb_expiry;               $this->initialiseRange();       }               function initialiseRange()      {               if ( $this->mUser == 0 ) {                      $rangeParts = explode( '/', $this->mAddress );                  if ( count( $rangeParts ) == 2 ) {                              $this->mNetworkBits = $rangeParts[1];                   } else {                                $this->mNetworkBits = 32;                       }                       $this->mIntegerAddr = ip2long( $rangeParts[0] );                } else {                        $this->mNetworkBits = false;                    $this->mIntegerAddr = false;            }       }               /**      * Callback with a Block object for every block  */     /*static*/ function enumBlocks( $callback, $tag, $flags = 0 )   {               $block = new Block();           if ( $flags & EB_FOR_UPDATE ) {                 $db =& wfGetDB( DB_MASTER );                    $options = 'FOR UPDATE';                        $block->forUpdate( true );              } 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' );           while ( $row = $db->fetchObject( $res ) ) {                     $block->initFromRow( $row );                    if ( !( $flags & EB_KEEP_EXPIRED ) ) {                          if ( !$block->deleteIfExpired() ) {                                     $callback( $block, $tag );                              }                       } else {                                $callback( $block, $tag );                      }               }               wfFreeResult( $res );   }       function delete()       {               $fname = 'Block::delete';               $dbw =& wfGetDB( DB_MASTER );           if ( $this->mAddress == '' ) {                  $condition = array( 'ipb_id' => $this->mId );           } else {                        $condition = array( 'ipb_address' => $this->mAddress );         }               $dbw->delete( 'ipblocks', $condition, $fname );         $this->clearCache();    }       function insert()       {               wfDebug( "Block::insert; timestamp {$this->mTimestamp}\n" );            $dbw =& wfGetDB( DB_MASTER );           $dbw->insert( 'ipblocks',                       array(                          'ipb_address' => $this->mAddress,                               'ipb_user' => $this->mUser,                             'ipb_by' => $this->mBy,                         'ipb_reason' => $this->mReason,                         'ipb_timestamp' => $dbw->timestamp($this->mTimestamp),                          'ipb_auto' => $this->mAuto,                             'ipb_expiry' => $this->mExpiry ?                                        $dbw->timestamp($this->mExpiry) :                                       $this->mExpiry,                 ), 'Block::insert'              );              $this->clearCache();    }       function deleteIfExpired()      {               if ( $this->isExpired() ) {                     wfDebug( "Block::deleteIfExpired() -- deleting\n" );                    $this->delete();                        return true;            } else {                        wfDebug( "Block::deleteIfExpired() -- not expired\n" );                 return false;           }       }       function isExpired()    {                       wfDebug( "Block::isExpired() checking current " . wfTimestampNow() . " vs $this->mExpiry\n" );          if ( !$this->mExpiry ) {                        return false;           } else {                        return wfTimestampNow() > $this->mExpiry;               }       }       function isValid()      {               return $this->mAddress != '';   }               function updateTimestamp()      {               if ( $this->mAuto ) {                   $this->mTimestamp = wfTimestamp();                      $this->mExpiry = Block::getAutoblockExpiry( $this->mTimestamp );                        $dbw =& wfGetDB( DB_MASTER );                   $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'                     );                                              $this->clearCache();            }       }       /* private */ function clearCache()     {               global $wgBlockCache;           if ( is_object( $wgBlockCache ) ) {                     $wgBlockCache->loadFromDB();            }       }               function getIntegerAddr()       {               return $this->mIntegerAddr;     }               function getNetworkBits()       {               return $this->mNetworkBits;     }       function forUpdate( $x = NULL ) {               return wfSetVar( $this->mForUpdate, $x );       }       /* static */ function getAutoblockExpiry( $timestamp )  {               global $wgAutoblockExpiry;              return wfTimestamp( TS_MW, wfTimestamp( TS_UNIX, $timestamp ) + $wgAutoblockExpiry );   }       /* static */ function normaliseRange( $range )  {               $parts = explode( '/', $range );                if ( count( $parts ) == 2 ) {                   $shift = 32 - $parts[1];                        $ipint = ip2long( $parts[0] );                  $ipint = $ipint >> $shift << $shift;                    $newip = long2ip( $ipint );                     $range = "$newip/{$parts[1]}";          }               return $range;  }}?>
\ No newline at end of file
index 95e59c8..be22b47 100644 (file)
@@ -150,7 +150,9 @@ class EditPage {
                        $wgOut->readOnlyPage( $this->mArticle->getContent( true ), true );
                        return;
                }
-               if ( $wgUser->isBlocked() ) {
+               if ( !$this->preview && $wgUser->isBlocked( !$this->save ) ) {
+                       # When previewing, don't check blocked state - will get caught at save time.
+                       # Also, check when starting edition is done against slave to improve performance.
                        $this->blockedIPpage();
                        return;
                }
@@ -184,51 +186,21 @@ class EditPage {
         * @todo document
         */
        function importFormData( &$request ) {
-               if( $request->wasPosted() ) {
-                       # These fields need to be checked for encoding.
-                       # Also remove trailing whitespace, but don't remove _initial_
-                       # whitespace from the text boxes. This may be significant formatting.
-                       $this->textbox1  = rtrim( $request->getText( 'wpTextbox1' ) );
-                       $this->textbox2  = rtrim( $request->getText( 'wpTextbox2' ) );
-                       $this->mMetaData = rtrim( $request->getText( 'metadata'   ) );
-                       $this->summary   =  trim( $request->getText( 'wpSummary'  ) );
-       
-                       $this->edittime = $request->getVal( 'wpEdittime' );
-                       if( is_null( $this->edittime ) ) {
-                               # If the form is incomplete, force to preview.
-                               $this->preview  = true;
-                       } else {
-                               if( $this->tokenOk( $request ) ) {
-                                       # Some browsers will not report any submit button
-                                       # if the user hits enter in the comment box.
-                                       # The unmarked state will be assumed to be a save,
-                                       # if the form seems otherwise complete.
-                                       $this->preview = $request->getCheck( 'wpPreview' );
-                               } else {
-                                       # Page might be a hack attempt posted from
-                                       # an external site. Preview instead of saving.
-                                       $this->preview = true;
-                               }
-                       }
-                       $this->save    = !$this->preview;
-                       if( !preg_match( '/^\d{14}$/', $this->edittime )) {
-                               $this->edittime = null;
-                       }
-       
-                       $this->minoredit = $request->getCheck( 'wpMinoredit' );
-                       $this->watchthis = $request->getCheck( 'wpWatchthis' );
-               } else {
-                       # Not a posted form? Start with nothing.
-                       $this->textbox1  = '';
-                       $this->textbox2  = '';
-                       $this->mMetaData = '';
-                       $this->summary   = '';
-                       $this->edittime  = '';
-                       $this->preview   = false;
-                       $this->save      = false;
-                       $this->minoredit = false;
-                       $this->watchthis = false;
-               }
+               # These fields need to be checked for encoding.
+               # Also remove trailing whitespace, but don't remove _initial_
+               # whitespace from the text boxes. This may be significant formatting.
+               $this->textbox1 = rtrim( $request->getText( 'wpTextbox1' ) );
+               $this->textbox2 = rtrim( $request->getText( 'wpTextbox2' ) );
+               $this->mMetaData = rtrim( $request->getText( 'metadata' ) );
+               $this->summary = trim( $request->getText( 'wpSummary' ) );
+
+               $this->edittime = $request->getVal( 'wpEdittime' );
+               if( !preg_match( '/^\d{14}$/', $this->edittime )) $this->edittime = '';
+
+               $this->preview = $request->getCheck( 'wpPreview' );
+               $this->save = $request->wasPosted() && !$this->preview;
+               $this->minoredit = $request->getCheck( 'wpMinoredit' );
+               $this->watchthis = $request->getCheck( 'wpWatchthis' );
 
                $this->oldid = $request->getInt( 'oldid' );
 
@@ -239,24 +211,15 @@ class EditPage {
        }
 
        /**
-        * Make sure the form isn't faking a user's credentials.
-        *
-        * @param WebRequest $request
-        * @return bool
-        * @access private
+        * Since there is only one text field on the edit form,
+        * pressing <enter> will cause the form to be submitted, but
+        * the submit button value won't appear in the query, so we
+        * Fake it here before going back to edit().  This is kind of
+        * ugly, but it helps some old URLs to still work.
         */
-       function tokenOk( &$request ) {
-               global $wgUser;
-               if( $wgUser->getId() == 0 ) {
-                       # Anonymous users may not have a session
-                       # open. Don't tokenize.
-                       return true;
-               } else {
-                       return $wgUser->matchEditToken( $request->getVal( 'wpEditToken' ) );
-               }
-       }
-       
        function submit() {
+               if( !$this->preview ) $this->save = true;
+
                $this->edit();
        }
 
@@ -310,7 +273,8 @@ class EditPage {
                                # Error messages or other handling should be performed by the filter function
                                return;
                        }
-                       if ( $wgUser->isBlocked() ) {
+                       if ( $wgUser->isBlocked( false ) ) {
+                               # Check block state against master, thus 'false'.
                                $this->blockedIPpage();
                                return;
                        }
@@ -580,27 +544,24 @@ class EditPage {
                        $wgOut->setOnloadHandler( 'document.editform.wpTextbox1.focus()' );
                }
                # Prepare a list of templates used by this page
-               $templates = '';
+               $db =& wfGetDB( DB_SLAVE );
+               $page = $db->tableName( 'page' );
+               $links = $db->tableName( 'links' );
                $id = $this->mTitle->getArticleID();
-               if ( 0 !== $id ) {
-                       $db =& wfGetDB( DB_SLAVE );
-                       $page = $db->tableName( 'page' );
-                       $links = $db->tableName( 'links' );
-                       $sql = "SELECT page_namespace,page_title,page_id ".
-                               "FROM $page,$links WHERE l_to=page_id AND l_from={$id} and page_namespace=".NS_TEMPLATE;
-                       $res = $db->query( $sql, "EditPage::editform" );
-                       if ( false !== $res ) {
-                               if ( $db->numRows( $res ) ) {
-                                       $templates = '<br />'. wfMsg( 'templatesused' ) . '<ul>';
-                                       while ( $row = $db->fetchObject( $res ) ) {
-                                               if ( $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title ) ) {
-                                                       $templates .= '<li>' . $sk->makeLinkObj( $titleObj ) . '</li>';
-                                               }
-                                       }
-                                       $templates .= '</ul>';
+               $sql = "SELECT page_namespace,page_title,page_id ".
+                       "FROM $page,$links WHERE l_to=page_id AND l_from={$id} and page_namespace=".NS_TEMPLATE;
+               $res = $db->query( $sql, "EditPage::editform" );
+
+               if ( $db->numRows( $res ) ) {
+                       $templates = '<br />'. wfMsg( 'templatesused' ) . '<ul>';
+                       while ( $row = $db->fetchObject( $res ) ) {
+                               if ( $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title ) ) {
+                                       $templates .= '<li>' . $sk->makeLinkObj( $titleObj ) . '</li>';
                                }
-                               $db->freeResult( $res );
                        }
+                       $templates .= '</ul>';
+               } else {        
+                       $templates = '';
                }
                
                global $wgLivePreview, $wgStylePath;
@@ -659,21 +620,6 @@ END
 <input type='hidden' value=\"" . htmlspecialchars( $this->section ) . "\" name=\"wpSection\" />
 <input type='hidden' value=\"{$this->edittime}\" name=\"wpEdittime\" />\n" );
 
-               if ( 0 != $wgUser->getID() ) {
-                       /**
-                        * To make it harder for someone to slip a user a page
-                        * which submits an edit form to the wiki without their
-                        * knowledge, a random token is associated with the login
-                        * session. If it's not passed back with the submission,
-                        * we won't save the page, or render user JavaScript and
-                        * CSS previews.
-                        */
-                       $token = htmlspecialchars( $wgUser->editToken() );
-                       $wgOut->addHTML( "
-<input type='hidden' value=\"$token\" name=\"wpEditToken\" />\n" );
-               }
-               
-               
                if ( $isConflict ) {
                        require_once( "DifferenceEngine.php" );
                        $wgOut->addHTML( "<h2>" . wfMsg( "yourdiff" ) . "</h2>\n" );
@@ -716,7 +662,6 @@ END
                        }
                        $parserOutput = $wgParser->parse( $previewtext , $wgTitle, $parserOptions );
                        $wgOut->addHTML( $parserOutput->mText );
-                       return $previewhead;
                } else {
                        # if user want to see preview when he edit an article
                        if( $wgUser->getOption('previewonfirst') and ($this->textbox1 == '')) {
@@ -732,8 +677,8 @@ END
                        $previewHTML = $parserOutput->mText;
                        $wgOut->addCategoryLinks($parserOutput->getCategoryLinks());
                        $wgOut->addLanguageLinks($parserOutput->getLanguageLinks());
-                       return $previewhead . $previewHTML;
                }
+               return $previewhead . $previewHTML;
        }
        
        /**
index a116389..5272730 100644 (file)
@@ -242,8 +242,16 @@ class User {
        /**
         * Get blocking information
         * @access private
+        * @param bool $bFromSlave Specify whether to check slave or master. To improve performance,
+        *  non-critical checks are done against slaves. Check when actually saving should be done against
+        *  master.
+        *
+        * Note that even if $bFromSlave is false, the check is done first against slave, then master.
+        * The logic is that if blocked on slave, we'll assume it's either blocked on master or
+        * just slightly outta sync and soon corrected - safer to block slightly more that less.
+        * And it's cheaper to check slave first, then master if needed, than master always.
         */
-       function getBlockedStatus() {
+       function getBlockedStatus( $bFromSlave = false ) {
                global $wgIP, $wgBlockCache, $wgProxyList;
 
                if ( -1 != $this->mBlockedby ) { return; }
@@ -253,7 +261,8 @@ class User {
                # User blocking
                if ( $this->mId ) {
                        $block = new Block();
-                       if ( $block->load( $wgIP , $this->mId ) ) {
+                       $block->forUpdate( $bFromSlave );
+                       if ( $block->load( $wgIP , $this->mId ) ) {
                                $this->mBlockedby = $block->mBy;
                                $this->mBlockreason = $block->mReason;
                        }
@@ -261,7 +270,14 @@ class User {
 
                # IP/range blocking
                if ( !$this->mBlockedby ) {
-                       $block = $wgBlockCache->get( $wgIP );
+                       # Check first against slave, and optionally from master.
+                       $block = $wgBlockCache->get( $wgIP, true );
+                       if ( !block && !$bFromSlave )
+                               {
+                               # Not blocked: check against master, to make sure.
+                               $wgBlockCache->clearLocal( );
+                               $block = $wgBlockCache->get( $wgIP, false );
+                               }
                        if ( $block !== false ) {
                                $this->mBlockedby = $block->mBy;
                                $this->mBlockreason = $block->mReason;
@@ -281,8 +297,8 @@ class User {
         * Check if user is blocked
         * @return bool True if blocked, false otherwise
         */
-       function isBlocked() {
-               $this->getBlockedStatus();
+       function isBlocked( $bFromSlave = false ) {
+               $this->getBlockedStatus( $bFromSlave );
                if ( 0 === $this->mBlockedby ) { return false; }
                return true;
        }
@@ -1187,39 +1203,6 @@ class User {
                }
                return false;
        }
-       
-       /**
-        * Initialize (if necessary) and return a session token value
-        * which can be used in edit forms to show that the user's
-        * login credentials aren't being hijacked with a foreign form
-        * submission.
-        *
-        * @return string
-        * @access public
-        */
-       function editToken() {
-               if( !isset( $_SESSION['wsEditToken'] ) ) {
-                       $token = dechex( mt_rand() ) . dechex( mt_rand() );
-                       $_SESSION['wsEditToken'] = $token;
-               }
-               return $_SESSION['wsEditToken'];
-       }
-       
-       /**
-        * Check given value against the token value stored in the session.
-        * A match should confirm that the form was submitted from the
-        * user's own login session, not a form submission from a third-party
-        * site.
-        *
-        * @param string $val
-        * @return bool
-        * @access public
-        */
-       function matchEditToken( $val ) {
-               if( !isset( $_SESSION['wsEditToken'] ) ) 
-                       return false;
-               return $_SESSION['wsEditToken'] == $val;
-       }
 }
 
 ?>