like a ninja from heaven (deriksmith) wrote,
like a ninja from heaven

  • Mood:

The last helicopter out of Wikia (usernames)

First in my (presumed) series about Decamping from Wikia... is the question of usernames.

Someone else has set up a dedicated mediawiki install, and downloaded a copy of the (full) wikiaarticle database and image archive, (about 700mb each in the Transformers wikia's case,) and done an import- taking ~10 hours. (It re-does every single edit ever done to an article in order.)

The problem: On Wikia (Server A) I'm User:Derik, and there is a User:Derik page on the new site (Server B), having been imported... but there ISN'T a user named Derik. Or rather- the Wikia export included all the pages- but not the user accounts. So now anyone can sign up for the name Derik on the new server. Potentially quite confusing, especially with a number of persistent trolls we have who might pass themselves off as existing users, or later claim an 'abandoned' username.

My solution: To register a username on Server B that also exists on Sever A (Wikia,) you must provide the same password used for this account on Server A.


Code changes live in:
=====CODE CHANGES======

=====NEW FILES=====

Starting from the bottom (because where else would one start? Well- it is the logical order anyway...)

"Snoopy" is a php class used to emulate a web browser when communicating with other sites.

When someone tries to register an account on our new server (that also exists on our new one,) we will use Snoopy to see if the username/password combo they provided can be used to log in to the old server. If it can, then we know they're actually the "owner" of this account, and we allow the registration to continue.

Snoopy is used in a completely out-of-the-box fashion, you won't need to understand it to use it.

"usernames.txt" is exactly what it sounds like. A plaintext-formatted list of the usernames from the old wiki on Server A, one per line. I just used Special:Listusers and cut-and-pasted by hand into notepad, then cleaned up with some search-and-replace. A messy solution- but even Wookiepecia
has less than 5000 users... or a ~65kb text file. (You can manually edit the 'limit' number in the URL to make all the users list on one page.)

When someone attempts to register a new account, this file will be loaded into memory and read line-by-line (the line is trimmed so if you miss some whitespace at the end of a line, this will catch it,) and the name compared with the username the person is trying to register. If there is a match, it does the post-to-wikia trick using Snoopy. (above.) This is a computationally 'lossy' procedure, but it only occurs when someone is registering an account and the memory overhead isn't terrible so... who cares?

Known issue: If you've got usernames that have Unicode characters in them, you'll have to use a different text format and adjust your code. (Or just let them take their chances while you protect the other user accounts.)

•"transition" folder.
Both of the above files go into a folder named 'transition' in the siteroot.
I could have tucked them someplace else, but I wanted to be neat. This folder (depending on how your server is configured) may be listable. postable-to, etc... but who cares? The Snoopy class file ignores posts, and a list of (publicly-available) usernames isn't exactly a state secret. You can stick 'em someplace else if it makes you feel better but they're perfectly safe in a standard location.


This file contains all the user messages used by the Mediawiki software. It was easier to add one 'properly' than to try to hack it.

~line 865 I added a new error message named 'wikiauser-password'. I think you can add it anywhere, but I stuck it right after 'wrongpassword', a similar error message. The line I added reads like this;

'wikiauser-password' => 'The username "$1" is active on the <a href="">Transformers Wikia</a> must be regisered using the same password used on Wikia. <small>(You may change this once registration is completed.)</small>',

The "$1" bit will be replaced by username. Notice that you can use HTML here, just be careful of nested quotes.


Here's the big one. Fortunately, it's a 'clean' addition. (You just need to customize a couple URL's.)
Within the function "addNewAccountInternal()", ~line 213, after the first if-block:
// If the user passes an invalid domain, something is fishy
if( !$wgAuth->validDomain( $this->mDomain ) ) {
$this->mainLoginForm( wfMsg( 'wrongpassword' ) );
return false;

...but before the 'local authentication' block marked by this comment...
// If we are not allowing users to login locally, we should
// be checking to see if the user is actually able to
// authenticate to the authentication server before they
// create an account (otherwise, they can create a local account
// and login as any domain user). We only need to check this for
// domains that aren't local.

You add... this!

$filename = "transition/usernames.txt";
$lines = file($filename); //Turn the file into an array, each element containing 1 line of the file.
for($i = 0; $i < count($lines); $i++){
$nameTaken = '';

if ( !strcasecmp(trim($lines[$i]), $this->mName) ){
//Provided username matches a reserved 'un.
$nameTaken = trim($lines[$i]);

$username = $this->mName; // Provided username
$passwd = $this->mPassword; // Provided password

require_once("transition/Snoopy.class.php"); // Uses Snoopy class, from
$snoopy = new Snoopy();
$snoopy->agent = "Mozilla/5.0 Snoopy/1.2.3"; //We're pretending to be Firefox.

// Log into wikipedia (sets cookies for writing use):
$login_url = ""; //The login page of your wikia.
$login_vars = array(
"wpName" => $username,
"wpPassword" => $passwd,
"wpRemember" => "0",
"wpLoginattempt" => "Log in");

$snoopy->submit($login_url, $login_vars);
$result = $snoopy->results;

$result = stripos($result, '<h1 class="firstHeading">Login successful</h1>'); //True if it finds this text on wiki after trying to log in. (Markup is the same in Monaco and Monobook. May differ if you're running some weird-ass custom skin.)

if ($result){
//Login successful! Do nuthin.
//Login unsuccessful!
$this->mainLoginForm( wfMsg( 'wikiauser-password',$nameTaken) ); //Displays the custom error message we created.
return false; //Stops the login proscess prematurely and displays errors.
} //Error out if Wikia login fails
} //ifMatch
} // foreach


That's about it. It's pretty straightforward. Uh- this is probably PHP5 only, though I don't imagine it'd take much work to adapt it for PHP4.

Difficulty: low-to-moderate. You want someone who's done PHP before executing this... but just so they know to avoid the basic pitfalls.

If you did it right... try to sign up using someone else's account and you'll end up with a result like this!

Tags: . php, login, monaco, wikia

  • Post a new comment


    default userpic

    Your reply will be screened

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.