public function execute() {
		$userName = '******'; // <- targer username

		$user = new CentralAuthUser( $userName );
		if ( !$user->exists() ) {
			echo "Cannot unsuppress non-existent user {$userName}!\n";
			exit( 0 );
		}
		$userName = $user->getName(); // sanity
		$wikis = $user->listAttached(); // wikis with attached accounts
		foreach ( $wikis as $wiki ) {
			$lb = wfGetLB( $wiki );
			$dbw = $lb->getConnection( DB_MASTER, array(), $wiki );
			# Get local ID like $user->localUserData( $wiki ) does
			$localUserId = $dbw->selectField( 'user', 'user_id',
				array( 'user_name' => $userName ), __METHOD__ );

			$delUserBit = Revision::DELETED_USER;
			$hiddenCount = $dbw->selectField( 'revision', 'COUNT(*)',
				array( 'rev_user' => $localUserId, "rev_deleted & $delUserBit != 0" ), __METHOD__ );
			echo "$hiddenCount edits have the username hidden on \"$wiki\"\n";
			# Unsuppress username on edits
			if ( $hiddenCount > 0 ) {
				echo "Unsuppressed edits of attached account (local id $localUserId) on \"$wiki\"...";
				IPBlockForm::unsuppressUserName( $userName, $localUserId, $dbw );
				echo "done!\n\n";
			}
			$lb->reuseConnection( $dbw ); // not really needed
			# Don't lag too bad
			wfWaitForSlaves( 5 );
		}
	}
 /**
  *
  */
 function showLogExtract()
 {
     $user = $this->mGlobalUser->getName();
     $text = '';
     $numRows = LogEventsList::showLogExtract($text, array('globalauth', 'suppress'), Title::newFromText("User:{$user}@global")->getPrefixedText(), '', array('showIfEmpty' => true));
     if ($numRows) {
         $this->getOutput()->addHTML(Xml::fieldset(wfMsg('centralauth-admin-logsnippet'), $text));
     }
 }
 public function execute()
 {
     $globalUser = new CentralAuthUser($this->getParameter('user'));
     if (!$this->getUser()->isAllowed('centralauth-lock')) {
         $this->dieUsageMsg(array('badaccess-groups'));
     } elseif (!$globalUser->exists()) {
         $this->dieUsageMsg(array('nosuchuser', $globalUser->getName()));
     } elseif ($globalUser->isOversighted() && !$this->getUser()->isAllowed('centralauth-oversight')) {
         $this->dieUsageMsg(array('nosuchuser', $globalUser->getName()));
     } elseif (!$this->getRequest()->getCheck('locked') && $this->getParameter('hidden') === null) {
         $this->dieUsage("At least one of the parameters locked, hidden is required", "missingparam");
     }
     $setLocked = $this->getParameter('locked');
     if (!$setLocked) {
         // Don't lock or unlock
         $setLocked = null;
     } else {
         $setLocked = $setLocked === 'lock';
     }
     $setHidden = $this->getParameter('hidden');
     $reason = $this->getParameter('reason');
     $stateCheck = $this->getParameter('statecheck');
     if ($stateCheck && $stateCheck !== $globalUser->getStateHash(true)) {
         $this->dieUsage('Edit conflict detected, Aborting.', 'editconflict');
     }
     $status = $globalUser->adminLockHide($setLocked, $setHidden, $reason, $this->getContext());
     // Logging etc
     if ($status->isGood()) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('user' => $globalUser->getName(), 'locked' => $globalUser->isLocked(), 'hidden' => $globalUser->getHiddenLevel(), 'reason' => $reason));
     } else {
         if (is_callable(array($this, 'getErrorFormatter'))) {
             $error = $this->getErrorFormatter()->arrayFromStatus($status);
         } else {
             $error = $this->getResult()->convertStatusToArray($status);
         }
         $this->getResult()->addValue('error', null, $error);
         $this->getResult()->addValue(null, $this->getModuleName(), array('user' => $globalUser->getName(), 'locked' => $globalUser->isLocked(), 'hidden' => $globalUser->getHiddenLevel()));
     }
 }
 private function showLogExtract()
 {
     $user = $this->mGlobalUser->getName();
     $text = '';
     $logTypes = array('globalauth');
     if ($this->mCanOversight) {
         $logTypes[] = 'suppress';
     }
     $numRows = LogEventsList::showLogExtract($text, $logTypes, Title::newFromText(MWNamespace::getCanonicalName(NS_USER) . ":{$user}@global")->getPrefixedText(), '', array('showIfEmpty' => true));
     if ($numRows) {
         $this->getOutput()->addHTML(Xml::fieldset($this->msg('centralauth-admin-logsnippet')->text(), $text));
     }
 }
 /**
  * @covers CentralAuthUser::exists
  * @covers CentralAuthUser::getId
  * @covers CentralAuthUser::getName
  * @covers CentralAuthUser::getHomeWiki
  * @covers CentralAuthUser::isAttached
  * @covers CentralAuthUser::getRegistration
  * @covers CentralAuthUser::getStateHash
  */
 public function testBasicAttrs()
 {
     $caUser = new CentralAuthUser('GlobalUser');
     $this->assertSame(true, $caUser->exists());
     $this->assertEquals(1001, $caUser->getId());
     $this->assertEquals('GlobalUser', $caUser->getName());
     $this->assertEquals(wfWikiID(), $caUser->getHomeWiki());
     $this->assertSame(true, $caUser->isAttached());
     $this->assertSame(false, $caUser->isLocked());
     $this->assertEquals('20130627183537', $caUser->getRegistration());
     $this->assertEquals(CentralAuthUser::HIDDEN_NONE, $caUser->getHiddenLevel());
     $this->assertEquals('2234d7949459185926a50073d174b673', $caUser->getStateHash());
 }
 protected function rename($row, DatabaseBase $dbw)
 {
     $wiki = $row->utr_wiki;
     $name = $row->utr_name;
     $newNamePrefix = User::getCanonicalName($name . '~' . str_replace('_', '-', $wiki), 'usable');
     if (!$newNamePrefix) {
         $this->log("ERROR: New name '{$name}~{$wiki}' is not valid");
         return;
     }
     $this->log("Beginning rename of {$newNamePrefix}");
     $newCAUser = new CentralAuthUser($newNamePrefix);
     $count = 0;
     // Edge case: Someone created User:Foo~wiki manually.
     // So just start appending numbers to the end of the name
     // until we get one that isn't used.
     while ($newCAUser->exists()) {
         $count++;
         $newCAUser = new CentralAuthUser($newNamePrefix . (string) $count);
     }
     if ($newNamePrefix !== $newCAUser->getName()) {
         $this->log("WARNING: New name is now {$newCAUser->getName()}");
     }
     $this->log("Renaming {$name} to {$newCAUser->getName()}.");
     $statuses = new GlobalRenameUserStatus($name);
     $success = $statuses->setStatuses(array(array('ru_wiki' => $wiki, 'ru_oldname' => $name, 'ru_newname' => $newCAUser->getName(), 'ru_status' => 'queued')));
     if (!$success) {
         $this->log("WARNING: Race condition, renameuser_status already set for {$newCAUser->getName()}. Skipping.");
         return;
     }
     $this->log("Set renameuser_status for {$newCAUser->getName()}.");
     $job = new LocalRenameUserJob(Title::newFromText('Global rename job'), array('from' => $name, 'to' => $newCAUser->getName(), 'renamer' => 'Maintenance script', 'movepages' => true, 'suppressredirects' => true, 'promotetoglobal' => true, 'reason' => $this->getOption('reason')));
     JobQueueGroup::singleton($row->utr_wiki)->push($job);
     $this->log("Submitted job for {$newCAUser->getName()}.");
     $updates = new UsersToRenameDatabaseUpdates($dbw);
     $updates->markRenamed($row->utr_name, $row->utr_wiki);
 }
 public function execute()
 {
     if (!$this->getUser()->isAllowed('centralauth-unmerge')) {
         $this->dieUsageMsg(array('badaccess-groups'));
     }
     $params = $this->extractRequestParams();
     $globalUser = new CentralAuthUser($params['user']);
     if (!$globalUser->exists()) {
         $this->dieUsageMsg(array('nosuchuser', $globalUser->getName()));
     } elseif ($globalUser->isOversighted() && !$this->getUser()->isAllowed('centralauth-oversight')) {
         $this->dieUsageMsg(array('nosuchuser', $globalUser->getName()));
     }
     $status = $globalUser->adminDelete($params['reason']);
     if ($status->isGood()) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('user' => $globalUser->getName(), 'reason' => $params['reason']));
     } else {
         if (is_callable(array($this, 'getErrorFormatter'))) {
             $error = $this->getErrorFormatter()->arrayFromStatus($status);
         } else {
             $error = $this->getResult()->convertStatusToArray($status);
         }
         $this->getResult()->addValue('error', null, $error);
     }
 }
Esempio n. 8
0
 /**
  * Switches a user's preferences off
  * @param $user User object to set preferences for
  * @param $global bool Whether to apply this change on all wikis in $wgPrefSwitchWikis
  */
 public static function switchOff($user, $global = false)
 {
     self::switchOffUser($user);
     if ($global) {
         $globalUser = new CentralAuthUser($user->getName());
         if (!$globalUser->exists()) {
             return;
         }
         $accounts = $globalUser->queryAttached();
         foreach ($accounts as $account) {
             $remoteUser = UserRightsProxy::newFromName($account['wiki'], $globalUser->getName(), true);
             if ($remoteUser) {
                 self::switchOffUser($remoteUser);
             }
         }
     }
 }
 /**
  * @param CentralAuthUser $globalUser
  * @return string
  */
 private function getUserTableRow(CentralAuthUser $globalUser)
 {
     $rowHtml = '';
     // @TODO: Don't use methods from the special page directly,
     // rather move them somewhere sane
     $sca = new SpecialCentralAuth();
     $sca->setContext($this->getContext());
     $guName = $globalUser->getName();
     $guLink = Linker::link(SpecialPage::getTitleFor('CentralAuth', $guName), htmlspecialchars($guName));
     $guHidden = $sca->formatHiddenLevel($globalUser->getHiddenLevel());
     $accountAge = time() - wfTimestamp(TS_UNIX, $globalUser->getRegistration());
     $guRegister = $sca->prettyTimespan($accountAge);
     $guLocked = $this->msg('centralauth-admin-status-locked-no')->escaped();
     if ($globalUser->isLocked()) {
         $guLocked = $this->msg('centralauth-admin-status-locked-yes')->escaped();
     }
     $guEditCount = htmlspecialchars($this->getLanguage()->formatNum($globalUser->getGlobalEditCount()));
     $guAttachedLocalAccounts = htmlspecialchars($this->getLanguage()->formatNum(count($globalUser->listAttached())));
     $rowHtml .= Html::rawElement('td', array(), Html::input('wpActionTarget[' . $guName . ']', $guName, 'checkbox', array('checked' => 'checked')));
     $rowHtml .= Html::rawElement('td', array(), $guLink);
     $rowHtml .= Html::element('td', array('data-sort-value' => $accountAge), $guRegister);
     $rowHtml .= Html::element('td', array(), $guLocked);
     $rowHtml .= Html::element('td', array(), $guHidden);
     $rowHtml .= Html::element('td', array(), $guEditCount);
     $rowHtml .= Html::element('td', array(), $guAttachedLocalAccounts);
     return $rowHtml;
 }
 /**
  * @param array $users
  *
  * @return LocalUserMergeJob
  */
 private function getJob(array $users)
 {
     return new LocalUserMergeJob(Title::newFromText('Global merge job'), array('to' => $this->newCAUser->getName(), 'renamer' => $this->performingUser->getName(), 'from' => $users, 'session' => $this->session));
 }
 /**
  * @param User $user
  * @param CentralAuthUser $centralUser
  * @param string $inject_html
  * @return bool
  */
 protected static function doCentralLoginRedirect(User $user, CentralAuthUser $centralUser, &$inject_html)
 {
     global $wgCentralAuthLoginWiki, $wgMemc, $wgSecureLogin;
     $context = RequestContext::getMain();
     $request = $context->getRequest();
     if (!$wgCentralAuthLoginWiki || defined('MW_API')) {
         // Mark the session to include edge login imgs on the next pageview
         $request->setSessionData('CentralAuthDoEdgeLogin', true);
         return true;
     }
     // Check that this is actually for a special login page view
     if ($context->getTitle()->isSpecial('Userlogin') && $request->wasPosted()) {
         // User will be redirected to Special:CentralLogin/start (central wiki),
         // then redirected back to Special:CentralLogin/complete (this wiki).
         // Sanity check that "returnto" is not one of the central login pages. If it
         // is, then clear the "returnto" options (LoginForm will use the main page).
         $returnTo = $request->getVal('returnto', '');
         $returnToQuery = $request->getVal('returntoquery', '');
         $returnToTitle = Title::newFromText($returnTo);
         if ($returnToTitle && $returnToTitle->isSpecial('CentralLogin')) {
             $returnTo = '';
             $returnToQuery = '';
         }
         // Determine the final protocol of page, after login
         $finalProto = $request->detectProtocol();
         $secureCookies = $finalProto === 'https';
         if ($wgSecureLogin) {
             $finalProto = 'http';
             if ($request->getBool('wpForceHttps', false) || $user->getBoolOption('prefershttps') && wfCanIPUseHTTPS($request->getIP())) {
                 $finalProto = 'https';
             }
             $secureCookies = $finalProto === 'https' && $user->getBoolOption('prefershttps');
         }
         // When POSTs triggered from Special:CentralLogin/start are sent back to
         // this wiki, the token will be checked to see if it was signed with this.
         // This is needed as Special:CentralLogin/start only takes a token argument
         // and we need to make sure an agent requesting such a URL actually initiated
         // the login request that spawned that token server-side.
         $secret = MWCryptRand::generateHex(32);
         $_SESSION['CentralAuth:autologin:current-attempt'] = array('secret' => $secret, 'remember' => $request->getCheck('wpRemember'), 'returnTo' => $returnTo, 'returnToQuery' => $returnToQuery, 'stickHTTPS' => $secureCookies, 'finalProto' => $finalProto, 'type' => $request->getText('type'));
         // Create a new token to pass to Special:CentralLogin/start (central wiki)
         $token = MWCryptRand::generateHex(32);
         $key = CentralAuthUser::memcKey('central-login-start-token', $token);
         $data = array('secret' => $secret, 'name' => $centralUser->getName(), 'guid' => $centralUser->getId(), 'wikiId' => wfWikiId(), 'secureCookies' => $secureCookies, 'finalProto' => $finalProto, 'currentProto' => $request->detectProtocol());
         Hooks::run('CentralAuthLoginRedirectData', array($centralUser, &$data));
         $wgMemc->set($key, $data, 60);
         $wiki = WikiMap::getWiki($wgCentralAuthLoginWiki);
         // Use WikiReference::getFullUrl(), returns a protocol-relative URL if needed
         $context->getOutput()->redirect(wfAppendQuery($wiki->getFullUrl('Special:CentralLogin/start'), "token={$token}"));
         // Set $inject_html to some text to bypass the LoginForm redirection
         $inject_html .= '<!-- do CentralAuth redirect -->';
     } else {
         // Mark the session to include edge login imgs on the next pageview
         $request->setSessionData('CentralAuthDoEdgeLogin', true);
     }
     return true;
 }
 function migrate($username, $homewiki = null)
 {
     $this->total++;
     $this->output("CentralAuth account migration for: " . $username . "\n");
     $central = new CentralAuthUser($username);
     try {
         $unattached = $central->queryUnattached();
     } catch (Exception $e) {
         // This might happen due to localnames inconsistencies (bug 67350)
         $this->output("ERROR: Fetching unattached accounts for {$username} failed.");
         return;
     }
     /**
      * Migration with an existing global account
      */
     if ($central->exists()) {
         $this->output("INFO: A global account already exists for: {$username}\n");
         if ($this->getOption('attachmissing', false) && !is_null($central->getEmailAuthenticationTimestamp())) {
             foreach ($unattached as $wiki => $local) {
                 if ($central->getEmail() === $local['email'] && !is_null($local['emailAuthenticated'])) {
                     $this->output("ATTACHING: {$username}@{$wiki}\n");
                     $central->attach($wiki, 'mail', !$this->suppressRC);
                 }
             }
         }
         if ($this->getOption('attachbroken', false)) {
             // This option is for bug 61876 / bug 39996 where the account has
             // an empty password and email set, and became unattached.
             // Since there is no way an account can have an empty password manually
             // it has to be due to a CentralAuth bug. So just attach it then.
             // But just to be on the safe side, check that it also has 0 edits.
             foreach ($unattached as $wiki => $local) {
                 if ($local['email'] === '' && $local['password'] === '' && $local['editCount'] === '0') {
                     $this->output("ATTACHING: {$username}@{$wiki}\n");
                     // Ironically, the attachment is made due to lack of a password.
                     $central->attach($wiki, 'password', !$this->suppressRC);
                 }
             }
         }
     } else {
         if (count($unattached) == 0) {
             $this->output("ERROR: No local accounts found for: {$username}\n");
             return;
         }
         if ($this->safe && count($unattached) !== 1) {
             $this->output("ERROR: More than 1 local user account found for username: {$username}\n");
             foreach ($unattached as $local) {
                 $this->output("\t" . $central->getName() . "@" . $local['wiki'] . "\n");
             }
             return;
         }
         if ($homewiki !== null) {
             if (!array_key_exists($homewiki, $unattached)) {
                 $this->output("ERROR: Unattached user not found for {$username}@{$homewiki}\n");
                 return;
             }
             $this->output("INFO: Setting homewiki for '{$username}' to {$homewiki}\n");
             $central->mHomeWiki = $homewiki;
         }
         // Check that all unattached (i.e. ALL) accounts have a confirmed email
         // address and that the addresses are all the same. We are using this
         // to match accounts to the same user, since we can't use the password.
         $emailMatch = true;
         $email = null;
         foreach ($unattached as $local) {
             if (is_null($email)) {
                 $email = $local['email'];
             }
             if ($local['email'] === $email && !is_null($local['emailAuthenticated'])) {
                 continue;
             }
             $emailMatch = false;
             break;
         }
         // All of the emails are the same and confirmed? Merge all the accounts.
         // They aren't? Skip, or merge the winner if --auto was specified.
         if ($emailMatch) {
             $this->output("Email addresses match and are confirmed for: {$username}\n");
             $central->storeAndMigrate(array(), !$this->suppressRC);
         } else {
             if (isset($central->mHomeWiki) || $this->autoMigrate) {
                 $central->storeAndMigrate(array(), !$this->suppressRC);
             } else {
                 $this->output("ERROR: Auto migration is disabled and email addresses do not match for: {$username}\n");
             }
         }
     }
     $unattachedAfter = $central->queryUnattached();
     if (count($unattachedAfter) == 0) {
         $this->migrated++;
         return;
     } elseif (count($unattachedAfter) > 0 && count($unattachedAfter) < count($unattached)) {
         $this->partial++;
         $this->output("INFO: Incomplete migration for '{$username}'\n");
     }
     if ($this->resetToken) {
         $this->output("INFO: Resetting CentralAuth auth token for '{$username}'\n");
         $central->resetAuthToken();
     }
 }
 public function execute()
 {
     $params = $this->extractRequestParams();
     $prop = array_flip((array) $params['prop']);
     if (is_null($params['user'])) {
         $params['user'] = $this->getUser()->getName();
     }
     $user = new CentralAuthUser($params['user']);
     // Add basic info
     $result = $this->getResult();
     $data = array();
     $userExists = $user->exists();
     if ($userExists && ($user->getHiddenLevel() === CentralAuthUser::HIDDEN_NONE || $this->getUser()->isAllowed('centralauth-oversight'))) {
         // The global user exists and it's not hidden or the current user is allowed to see it
         $data['home'] = $user->getHomeWiki();
         $data['id'] = $user->getId();
         $data['registration'] = wfTimestamp(TS_ISO_8601, $user->getRegistration());
         $data['name'] = $user->getName();
         if ($user->isLocked()) {
             $data['locked'] = '';
         }
         if ($user->isHidden()) {
             $data['hidden'] = '';
         }
     } else {
         // The user doesn't exist or we pretend it doesn't if it's hidden
         $data['missing'] = '';
     }
     $result->addValue('query', $this->getModuleName(), $data);
     // Add requested info
     if ($userExists && isset($prop['groups'])) {
         $groups = $user->getGlobalGroups();
         $result->setIndexedTagName($groups, 'g');
         $result->addValue(array('query', $this->getModuleName()), 'groups', $groups);
     }
     if ($userExists && isset($prop['rights'])) {
         $rights = $user->getGlobalRights();
         $result->setIndexedTagName($rights, 'r');
         $result->addValue(array('query', $this->getModuleName()), 'rights', $rights);
     }
     $attachedAccounts = null;
     if ($userExists && (isset($prop['merged']) || isset($prop['editcount']))) {
         $attachedAccounts = $user->queryAttached();
     }
     if ($userExists && isset($prop['merged'])) {
         foreach ($attachedAccounts as $account) {
             $dbname = $account['wiki'];
             $wiki = WikiMap::getWiki($dbname);
             $a = array('wiki' => $dbname, 'url' => $wiki->getCanonicalServer(), 'timestamp' => wfTimestamp(TS_ISO_8601, $account['attachedTimestamp']), 'method' => $account['attachedMethod'], 'editcount' => $account['editCount']);
             if ($account['blocked']) {
                 $a['blocked'] = array('expiry' => $this->getLanguage()->formatExpiry($account['block-expiry'], TS_ISO_8601), 'reason' => $account['block-reason']);
             }
             $result->addValue(array('query', $this->getModuleName(), 'merged'), null, $a);
         }
         if (defined('ApiResult::META_CONTENT')) {
             $result->addIndexedTagName(array('query', $this->getModuleName(), 'merged'), 'account');
         } else {
             $result->setIndexedTagName_internal(array('query', $this->getModuleName(), 'merged'), 'account');
         }
     }
     if ($userExists && isset($prop['editcount'])) {
         $editcount = 0;
         foreach ($attachedAccounts as $account) {
             $editcount += $account['editCount'];
         }
         $result->addValue('query', $this->getModuleName(), array('editcount' => $editcount));
     }
     if (isset($prop['unattached'])) {
         $accounts = $user->queryUnattached();
         foreach ($accounts as $account) {
             $a = array('wiki' => $account['wiki'], 'editcount' => $account['editCount']);
             if ($account['blocked']) {
                 $a['blocked'] = array('expiry' => $this->getLanguage()->formatExpiry($account['block-expiry'], TS_ISO_8601), 'reason' => $account['block-reason']);
             }
             $result->addValue(array('query', $this->getModuleName(), 'unattached'), null, $a);
         }
         if (defined('ApiResult::META_CONTENT')) {
             $result->addIndexedTagName(array('query', $this->getModuleName(), 'unattached'), 'account');
         } else {
             $result->setIndexedTagName_internal(array('query', $this->getModuleName(), 'unattached'), 'account');
         }
     }
 }
 /**
  * Sets up jobs to create and attach a local account for the given user on every wiki listed in
  * $wgCentralAuthAutoCreateWikis.
  * @param CentralAuthUser $centralUser
  */
 private function autoCreateAccounts(CentralAuthUser $centralUser)
 {
     global $wgCentralAuthAutoCreateWikis;
     $name = $centralUser->getName();
     $thisWiki = wfWikiID();
     $session = RequestContext::getMain()->exportSession();
     foreach ($wgCentralAuthAutoCreateWikis as $wiki) {
         if ($wiki === $thisWiki) {
             continue;
         }
         $job = Job::factory('CentralAuthCreateLocalAccountJob', Title::makeTitleSafe(NS_USER, $name), array('name' => $name, 'from' => $thisWiki, 'session' => $session));
         JobQueueGroup::singleton($wiki)->push($job);
     }
 }
 function execute($par)
 {
     global $wgMemc, $wgCentralAuthLoginWiki;
     $request = $this->getRequest();
     $this->loginWiki = $wgCentralAuthLoginWiki;
     if (!$this->loginWiki) {
         // Ugh, no central wiki. If we're coming from an edge login, make
         // the logged-into wiki the de-facto central wiki for this request
         // so auto-login still works.
         $fromwiki = $request->getVal('from', $request->getVal('notifywiki'));
         if ($fromwiki !== null && WikiMap::getWiki($fromwiki)) {
             $this->loginWiki = $fromwiki;
         }
     } elseif ($request->getVal('from') === wfWikiId() && $wgCentralAuthLoginWiki !== wfWikiId()) {
         // Remote wiki must not have wgCentralAuthLoginWiki set, but we do. Redirect them.
         $this->do302Redirect($wgCentralAuthLoginWiki, $par, $request->getValues());
         return;
     }
     $params = $request->getValues('type', 'from', 'return', 'returnto', 'returntoquery', 'proto', 'mobile');
     switch (strval($par)) {
         case 'P3P':
             // Explain the bogus P3P header
             $this->setHeaders();
             $this->getOutput()->addWikiMsg('centralauth-centralautologin-p3p-explanation');
             return;
         case 'toolslist':
             // Do not cache this, we want updated Echo numbers and such.
             $this->getOutput()->enableClientCache(false);
             $user = $this->getUser();
             if (!$user->isAnon()) {
                 if (!CentralAuthHooks::isUIReloadRecommended($user)) {
                     $html = $this->getSkin()->getPersonalToolsList();
                     $json = FormatJSON::encode(array('toolslist' => $html));
                 } else {
                     $gender = $this->getUser()->getOption('gender');
                     if (strval($gender) === '') {
                         $gender = 'unknown';
                     }
                     $json = FormatJSON::encode(array('notify' => array('username' => $user->getName(), 'gender' => $gender)));
                 }
                 $this->doFinalOutput(true, 'OK', $json, 'json');
             } else {
                 $this->doFinalOutput(false, 'Not logged in', '', 'json');
             }
             return;
         case 'refreshCookies':
             // Refresh central cookies (e.g. in case 'remember me' was set)
             // Do not cache this, we need to reset the cookies every time.
             $this->getOutput()->enableClientCache(false);
             if (!$wgCentralAuthLoginWiki || !$this->checkIsCentralWiki($wikiid)) {
                 return;
             }
             CentralAuthUser::setP3P();
             $centralUser = CentralAuthUser::getInstance($this->getUser());
             if ($centralUser && $centralUser->getId()) {
                 $centralSession = $this->getCentralSession($centralUser, $this->getUser());
                 // Refresh 'remember me' preference
                 $remember = (bool) $centralSession['remember'];
                 if ($remember != $this->getUser()->getBoolOption('rememberpassword')) {
                     $this->getUser()->setOption('rememberpassword', $remember ? 1 : 0);
                     $this->getUser()->saveSettings();
                 }
                 $secureCookie = $centralSession['secureCookies'];
                 $centralUser->setGlobalCookies($remember, false, $secureCookie, $centralSession);
                 $this->doFinalOutput(true, 'success');
             } else {
                 $this->doFinalOutput(false, 'Not logged in');
             }
             return;
         case 'deleteCookies':
             // Delete central cookies
             // Do not cache this, we need to reset the cookies every time.
             $this->getOutput()->enableClientCache(false);
             if ($this->getUser()->isLoggedIn()) {
                 $this->doFinalOutput(false, 'Cannot delete cookies while still logged in');
                 return;
             }
             CentralAuthUser::setP3P();
             CentralAuthUser::deleteGlobalCookies();
             $this->doFinalOutput(true, 'success');
             return;
         case 'start':
             // Main entry point
             // Note this is safe to cache, because the cache already varies on
             // the session cookies.
             $this->getOutput()->setSquidMaxage(1200);
             if (!$this->checkIsLocalWiki()) {
                 return;
             }
             CentralAuthUser::setP3P();
             $this->do302Redirect($this->loginWiki, 'checkLoggedIn', array('wikiid' => wfWikiID(), 'proto' => $request->detectProtocol()) + $params);
             return;
         case 'checkLoggedIn':
             // Check if we're logged in centrally
             // Note this is safe to cache, because the cache already varies on
             // the session cookies.
             $this->getOutput()->setSquidMaxage(1200);
             if (!$this->checkIsCentralWiki($wikiid)) {
                 return;
             }
             CentralAuthUser::setP3P();
             if ($this->getUser()->isLoggedIn()) {
                 $centralUser = CentralAuthUser::getInstance($this->getUser());
             } else {
                 $this->doFinalOutput(false, 'Not centrally logged in', self::getInlineScript('anon-set.js'));
                 return;
             }
             // We're pretty sure this user is logged in, so pass back
             // headers to prevent caching, just in case
             $this->getOutput()->enableClientCache(false);
             $memcData = array('gu_id' => $centralUser->getId());
             $token = MWCryptRand::generateHex(32);
             $key = CentralAuthUser::memcKey('centralautologin-token', $token);
             $wgMemc->set($key, $memcData, 60);
             $this->do302Redirect($wikiid, 'createSession', array('token' => $token) + $params);
             return;
         case 'createSession':
             // Create the local session and shared memcache token
             if (!$this->checkIsLocalWiki()) {
                 return;
             }
             CentralAuthUser::setP3P();
             $token = $request->getVal('token', '');
             $gid = $request->getVal('gu_id', '');
             if ($token !== '') {
                 // Load memc data
                 $key = CentralAuthUser::memcKey('centralautologin-token', $token);
                 $memcData = $wgMemc->get($key);
                 $wgMemc->delete($key);
                 if (!$memcData || !isset($memcData['gu_id'])) {
                     $this->doFinalOutput(false, 'Invalid parameters');
                     return;
                 }
                 $gu_id = intval($memcData['gu_id']);
             } elseif ($gid !== '') {
                 // Cached, or was logging in as we switched from gu_id to token
                 $gu_id = intval($gid);
             } else {
                 $this->doFinalOutput(false, 'Invalid parameters');
                 return;
             }
             if ($gu_id <= 0) {
                 $this->doFinalOutput(false, 'Not centrally logged in', self::getInlineScript('anon-set.js'));
                 return;
             }
             // At this point we can't cache anymore because we need to set
             // cookies and memc each time.
             $this->getOutput()->enableClientCache(false);
             // Ensure that a session exists
             if (session_id() == '') {
                 wfSetupSession();
             }
             // Create memc token
             $wikiid = wfWikiID();
             $memcData = array('gu_id' => $gu_id, 'wikiid' => $wikiid);
             $token = MWCryptRand::generateHex(32);
             $key = CentralAuthUser::memcKey('centralautologin-token', $token, $wikiid);
             $wgMemc->set($key, $memcData, 60);
             // Save memc token for the 'setCookies' step
             $request->setSessionData('centralautologin-token', $token);
             $this->do302Redirect($this->loginWiki, 'validateSession', array('token' => $token, 'wikiid' => $wikiid) + $params);
             return;
         case 'validateSession':
             // Validate the shared memcached token
             // Do not cache this, we need to reset the cookies and memc every time.
             $this->getOutput()->enableClientCache(false);
             if (!$this->checkIsCentralWiki($wikiid)) {
                 return;
             }
             if (!$this->getUser()->isLoggedIn()) {
                 $this->doFinalOutput(false, 'Not logged in');
                 return;
             }
             CentralAuthUser::setP3P();
             // Validate params
             $token = $request->getVal('token', '');
             if ($token === '') {
                 $this->doFinalOutput(false, 'Invalid parameters');
                 return;
             }
             // Load memc data
             $key = CentralAuthUser::memcKey('centralautologin-token', $token, $wikiid);
             $memcData = $wgMemc->get($key);
             $wgMemc->delete($key);
             // Check memc data
             $centralUser = CentralAuthUser::getInstance($this->getUser());
             if (!$memcData || $memcData['wikiid'] !== $wikiid || !$centralUser || !$centralUser->getId() || $memcData['gu_id'] != $centralUser->getId()) {
                 $this->doFinalOutput(false, 'Invalid parameters');
                 return;
             }
             // Write info for session creation into memc
             $centralSession = $this->getCentralSession($centralUser, $this->getUser());
             $memcData += array('userName' => $centralUser->getName(), 'token' => $centralUser->getAuthToken(), 'finalProto' => $centralSession['finalProto'], 'secureCookies' => $centralSession['secureCookies'], 'remember' => $centralSession['remember'], 'sessionId' => $centralSession['sessionId']);
             $wgMemc->set($key, $memcData, 60);
             $this->do302Redirect($wikiid, 'setCookies', $params);
             return;
         case 'setCookies':
             // Check that memcached is validated, and set cookies
             // Do not cache this, we need to reset the cookies and memc every time.
             $this->getOutput()->enableClientCache(false);
             if (!$this->checkIsLocalWiki()) {
                 return;
             }
             CentralAuthUser::setP3P();
             // Check saved memc token
             $token = $this->getRequest()->getSessionData('centralautologin-token');
             if ($token === null) {
                 $this->doFinalOutput(false, 'Lost session');
                 return;
             }
             // Load memc data
             $wikiid = wfWikiID();
             $key = CentralAuthUser::memcKey('centralautologin-token', $token, $wikiid);
             $memcData = $wgMemc->get($key);
             $wgMemc->delete($key);
             // Check memc data
             if (!$memcData || $memcData['wikiid'] !== $wikiid || !isset($memcData['userName']) || !isset($memcData['token'])) {
                 $this->doFinalOutput(false, 'Lost session');
                 return;
             }
             // Load and check CentralAuthUser. But don't check if it's
             // attached, because then if the user is missing en.site they
             // won't be auto logged in to any of the non-en versions either.
             $centralUser = new CentralAuthUser($memcData['userName']);
             if (!$centralUser->getId() || $centralUser->getId() != $memcData['gu_id']) {
                 $msg = "Wrong user: expected {$memcData['gu_id']}, got {$centralUser->getId()}";
                 wfDebug(__METHOD__ . ": {$msg}\n");
                 $this->doFinalOutput(false, 'Lost session');
                 return;
             }
             $loginResult = $centralUser->authenticateWithToken($memcData['token']);
             if ($loginResult != 'ok') {
                 $msg = "Bad token: {$loginResult}";
                 wfDebug(__METHOD__ . ": {$msg}\n");
                 $this->doFinalOutput(false, 'Lost session');
                 return;
             }
             // Set a new session cookie, Just In Case™
             wfResetSessionID();
             // Set central cookies too, with a refreshed sessionid. Also, check if we
             // need to override the default cookie security policy
             $secureCookie = $memcData['secureCookies'];
             $centralUser->setGlobalCookies($memcData['remember'], $memcData['sessionId'], $secureCookie, array('finalProto' => $memcData['finalProto'], 'secureCookies' => $memcData['secureCookies'], 'remember' => $memcData['remember']));
             // Now, figure out how to report this back to the user.
             // First, set to redo the edge login on the next pageview
             $request->setSessionData('CentralAuthDoEdgeLogin', true);
             // If it's not a script callback, just go for it.
             if ($request->getVal('type') !== 'script') {
                 $this->doFinalOutput(true, 'success');
                 return;
             }
             // If it is a script callback, then we do want to create the user
             // if it doesn't already exist locally (and fail if that can't be
             // done).
             if (!User::idFromName($centralUser->getName())) {
                 $user = new User();
                 $user->setName($centralUser->getName());
                 if (CentralAuthHooks::attemptAddUser($user)) {
                     $centralUser->invalidateCache();
                 }
             }
             if (!$centralUser->isAttached()) {
                 $this->doFinalOutput(false, 'Local user is not attached', self::getInlineScript('anon-set.js'));
                 return;
             }
             $script = self::getInlineScript('anon-remove.js');
             // If we're returning to returnto, do that
             if ($request->getCheck('return')) {
                 global $wgRedirectOnLogin;
                 if ($wgRedirectOnLogin !== null) {
                     $returnTo = $wgRedirectOnLogin;
                     $returnToQuery = array();
                 } else {
                     $returnTo = $request->getVal('returnto', '');
                     $returnToQuery = wfCgiToArray($request->getVal('returntoquery', ''));
                 }
                 $returnToTitle = Title::newFromText($returnTo);
                 if (!$returnToTitle) {
                     $returnToTitle = Title::newMainPage();
                     $returnToQuery = array();
                 }
                 $redirectUrl = $returnToTitle->getFullURL($returnToQuery);
                 $script .= "\n" . 'location.href = ' . Xml::encodeJsVar($redirectUrl) . ';';
                 $this->doFinalOutput(true, 'success', $script);
                 return;
             }
             // Otherwise, we need to rewrite p-personal and maybe notify the user too
             global $wgCentralAuthUseEventLogging;
             if ($wgCentralAuthUseEventLogging) {
                 EventLogging::logEvent('CentralAuth', 5690875, array('version' => 1, 'userId' => $centralUser->getId(), 'action' => 'sul2-autologin-fallbacklogin'));
             }
             // Add a script to the page that will pull in the user's toolslist
             // via ajax, and update the UI. Don't write out the tools here (bug 57081).
             $code = $this->getUser()->getOption('language');
             $code = RequestContext::sanitizeLangCode($code);
             Hooks::run('UserGetLanguageObject', array($this->getUser(), &$code, $this->getContext()));
             $script .= "\n" . Xml::encodeJsCall('mediaWiki.messages.set', array(array('centralauth-centralautologin-logged-in' => wfMessage('centralauth-centralautologin-logged-in')->inLanguage($code)->plain(), 'centralauth-centralautologin-logged-in-nouser' => wfMessage('centralauth-centralautologin-logged-in-nouser')->inLanguage($code)->plain(), 'centralautologin' => wfMessage('centralautologin')->inLanguage($code)->plain())));
             $script .= "\n" . self::getInlineScript('autologin.js');
             // And for good measure, add the edge login HTML images to the page.
             $script .= "\n" . Xml::encodeJsCall("jQuery( 'body' ).append", array(CentralAuthHooks::getEdgeLoginHTML()));
             $this->doFinalOutput(true, 'success', $script);
             return;
         default:
             $this->setHeaders();
             $this->getOutput()->addWikiMsg('centralauth-centralautologin-desc');
             return;
     }
 }