diff options
Diffstat (limited to 'AntiSpoof/includes/SpoofUser.php')
-rw-r--r-- | AntiSpoof/includes/SpoofUser.php | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/AntiSpoof/includes/SpoofUser.php b/AntiSpoof/includes/SpoofUser.php new file mode 100644 index 00000000..89ed8f08 --- /dev/null +++ b/AntiSpoof/includes/SpoofUser.php @@ -0,0 +1,217 @@ +<?php +/** + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +use Wikimedia\Rdbms\IDatabase; + +class SpoofUser { + /** @var bool */ + private $legal; + + /** @var string */ + private $name; + + /** @var string */ + private $normalized; + + /** @var null|Status */ + private $error; + + /** + * @param string $name + */ + public function __construct( $name ) { + $this->name = strval( $name ); + $status = AntiSpoof::checkUnicodeStringStatus( $this->name ); + $this->legal = $status->isOK(); + if ( $this->legal ) { + $this->normalized = $status->getValue(); + $this->error = null; + } else { + $this->normalized = null; + $this->error = $status; + } + } + + /** + * Does the username pass Unicode legality and script-mixing checks? + * @return bool + */ + public function isLegal() { + return $this->legal; + } + + /** + * Describe the error. + * @return null|string + */ + public function getError() { + return $this->error ? $this->error->getMessage()->text() : null; + } + + /** + * Describe the error. + * @return null|Status + * @since 1.32 + */ + public function getErrorStatus() { + return $this->error; + } + + /** + * Get the normalized key form + * @return string|null + */ + public function getNormalized() { + return $this->normalized; + } + + /** + * @return string + */ + protected function getTableName() { + return 'user'; + } + + /** + * @return string + */ + protected function getUserColumn() { + return 'user_name'; + } + + /** + * Does the username pass Unicode legality and script-mixing checks? + * + * @return array empty if no conflict, or array containing conflicting usernames + */ + public function getConflicts() { + $dbr = $this->getDBSlave(); + + // Join against the user table to ensure that we skip stray + // entries left after an account is renamed or otherwise munged. + $spoofedUsers = $dbr->select( + [ 'spoofuser', $this->getTableName() ], + [ 'su_name' ], // Same thing due to the join. Saves extra variableness + [ + 'su_normalized' => $this->normalized, + 'su_name = ' . $this->getUserColumn(), + ], + __METHOD__, + [ + 'LIMIT' => 5 + ] ); + + $spoofs = []; + foreach ( $spoofedUsers as $row ) { + array_push( $spoofs, $row->su_name ); + } + return $spoofs; + } + + /** + * Record the username's normalized form into the database + * for later comparison of future names... + * @return bool + */ + public function record() { + return self::batchRecord( $this->getDBMaster(), [ $this ] ); + } + + /** + * @return array + */ + private function insertFields() { + return [ + 'su_name' => $this->name, + 'su_normalized' => $this->normalized, + 'su_legal' => $this->legal ? 1 : 0, + 'su_error' => $this->getError(), + ]; + } + + /** + * Insert a batch of spoof normalization records into the database. + * @param IDatabase $dbw + * @param SpoofUser[] $items + * @return bool + */ + public static function batchRecord( IDatabase $dbw, $items ) { + if ( !count( $items ) ) { + return false; + } + $fields = []; + /** + * @var $item SpoofUser + */ + foreach ( $items as $item ) { + $fields[] = $item->insertFields(); + } + $dbw->replace( + 'spoofuser', + [ 'su_name' ], + $fields, + __METHOD__ ); + return true; + } + + /** + * @param string $oldName + */ + public function update( $oldName ) { + $that = $this; + $method = __METHOD__; + $dbw = $this->getDBMaster(); + // Avoid user rename triggered deadlocks + $dbw->onTransactionPreCommitOrIdle( + function () use ( $dbw, $that, $method, $oldName ) { + if ( $that->record() ) { + $dbw->delete( + 'spoofuser', + [ 'su_name' => $oldName ], + $method + ); + } + } + ); + } + + /** + * Remove a user from the spoofuser table + */ + public function remove() { + $this->getDBMaster()->delete( + 'spoofuser', + [ 'su_name' => $this->name ], + __METHOD__ + ); + } + + /** + * @return IDatabase + */ + protected function getDBSlave() { + return wfGetDB( DB_REPLICA ); + } + + /** + * @return IDatabase + */ + protected function getDBMaster() { + return wfGetDB( DB_MASTER ); + } +} |