/**
  * Add "x email-confirmed open account requests" notice
  * @param $notice
  * @return bool
  */
 public static function confirmAccountsNotice(OutputPage &$out, Skin &$skin)
 {
     global $wgConfirmAccountNotice;
     $context = $out->getContext();
     if (!$wgConfirmAccountNotice || !$context->getUser()->isAllowed('confirmaccount')) {
         return true;
     }
     # Only show on some special pages
     $title = $context->getTitle();
     if (!$title->isSpecial('Recentchanges') && !$title->isSpecial('Watchlist')) {
         return true;
     }
     $count = ConfirmAccount::getOpenEmailConfirmedCount('*');
     if ($count > 0) {
         $out->prependHtml('<div id="mw-confirmaccount-msg" class="plainlinks mw-confirmaccount-bar">' . $out->parse(wfMsgExt('confirmaccount-newrequests', 'parsemag', $count), false) . '</div>');
         $out->addModules('ext.confirmAccount');
         // CSS
     }
     return true;
 }
 protected function createUserPage(User $user)
 {
     global $wgMakeUserPageFromBio, $wgAutoUserBioText;
     global $wgConfirmAccountSortkey, $wgContLang;
     $body = '';
     // page text
     if ($wgMakeUserPageFromBio) {
         # Add account request bio to userpage
         $body .= $this->bio;
         # Add any automatic text for all confirmed accounts
         if ($wgAutoUserBioText != '') {
             $body .= "\n\n{$wgAutoUserBioText}";
         }
     }
     # Add any automatic text for confirmed accounts of this type
     $autoText = self::getAutoTextFromType($this->type);
     if ($autoText != '') {
         $body .= "\n\n{$autoText}";
     }
     # Add any areas of interest categories...
     foreach (ConfirmAccount::getUserAreaConfig() as $name => $conf) {
         if (in_array($name, $this->areas)) {
             # General userpage text for anyone with this interest
             if ($conf['userText'] != '') {
                 $body .= $conf['userText'];
             }
             # Message for users with this interested with the given account type
             if (isset($conf['grpUserText'][$this->type]) && $conf['grpUserText'][$this->type] != '') {
                 $body .= $conf['grpUserText'];
             }
         }
     }
     # Set sortkey and use it on userpage. This can be used to
     # normalize things like firstname, lastname and so fourth.
     if (!empty($wgConfirmAccountSortkey)) {
         $sortKey = preg_replace($wgConfirmAccountSortkey[0], $wgConfirmAccountSortkey[1], $user->getUserPage()->getText());
         $body .= "\n{{DEFAULTSORT:{$sortKey}}}";
         # Clean up any other categories...
         $catNS = $wgContLang->getNSText(NS_CATEGORY);
         $replace = '/\\[\\[' . preg_quote($catNS) . ':([^\\]]+)\\]\\]/i';
         // [[Category:x]]
         $with = "[[{$catNS}:\$1|" . str_replace('$', '\\$', $sortKey) . "]]";
         // [[Category:x|sortkey]]
         $body = preg_replace($replace, $with, $body);
     }
     # Create userpage!
     $article = new WikiPage($user->getUserPage());
     $article->doEdit($body, wfMsg('confirmaccount-summary'), EDIT_MINOR);
 }
 protected function showList()
 {
     $out = $this->getOutput();
     # Output the list
     $pager = new ConfirmAccountsPager($this, array(), $this->queueType, $this->showRejects, $this->showHeld, $this->showStale);
     if ($pager->getNumRows()) {
         if ($this->showStale) {
             $out->addWikiMsg('confirmaccount-list3');
         } elseif ($this->showRejects) {
             $out->addWikiMsg('confirmaccount-list2');
         } else {
             $out->addWikiMsg('confirmaccount-list');
         }
         $out->addHTML($pager->getNavigationBar());
         $out->addHTML($pager->getBody());
         $out->addHTML($pager->getNavigationBar());
     } else {
         if ($this->showRejects) {
             $out->addWikiMsg('confirmaccount-none-r');
         } elseif ($this->showStale) {
             $out->addWikiMsg('confirmaccount-none-e');
         } elseif ($this->showHeld) {
             $out->addWikiMsg('confirmaccount-none-h');
         } else {
             $out->addWikiMsg('confirmaccount-none-o');
         }
     }
     # Every 30th view, prune old deleted items
     if (0 == mt_rand(0, 29)) {
         ConfirmAccount::runAutoMaintenance();
     }
 }
 /**
  * Attempt to validate and submit this data to the DB
  * @param $context IContextSource
  * @return array( true or error key string, html error msg or null )
  */
 public function submit(IContextSource $context)
 {
     global $wgAuth, $wgAccountRequestThrottle, $wgMemc, $wgContLang;
     global $wgConfirmAccountRequestFormItems;
     $formConfig = $wgConfirmAccountRequestFormItems;
     // convience
     $reqUser = $this->requester;
     # Make sure that basic permissions are checked
     $block = ConfirmAccount::getAccountRequestBlock($reqUser);
     if ($block) {
         return array('accountreq_permission_denied', $context->msg('badaccess-group0')->escaped());
     } elseif (wfReadOnly()) {
         return array('accountreq_readonly', $context->msg('badaccess-group0')->escaped());
     }
     # Now create a dummy user ($u) and check if it is valid
     if ($this->userName === '') {
         return array('accountreq_no_name', $context->msg('noname')->escaped());
     }
     $u = User::newFromName($this->userName, 'creatable');
     if (!$u) {
         return array('accountreq_invalid_name', $context->msg('noname')->escaped());
     }
     # No request spamming...
     if ($wgAccountRequestThrottle && $reqUser->isPingLimitable()) {
         $key = wfMemcKey('acctrequest', 'ip', $this->ip);
         $value = (int) $wgMemc->get($key);
         if ($value > $wgAccountRequestThrottle) {
             return array('accountreq_throttled', $context->msg('acct_request_throttle_hit', $wgAccountRequestThrottle)->text());
         }
     }
     # Make sure user agrees to policy here
     if ($formConfig['TermsOfService']['enabled'] && !$this->tosAccepted) {
         return array('acct_request_skipped_tos', $context->msg('requestaccount-agree')->escaped());
     }
     # Validate email address
     if (!Sanitizer::validateEmail($this->email)) {
         return array('acct_request_invalid_email', $context->msg('invalidemailaddress')->escaped());
     }
     # Check if biography is long enough
     if ($formConfig['Biography']['enabled'] && str_word_count($this->bio) < $formConfig['Biography']['minWords']) {
         $minWords = $formConfig['Biography']['minWords'];
         return array('acct_request_short_bio', $context->msg('requestaccount-tooshort')->numParams($minWords)->text());
     }
     # Per security reasons, file dir cannot be pulled from client,
     # so ask them to resubmit it then...
     # If the extra fields are off, then uploads are off
     $allowFiles = $formConfig['CV']['enabled'];
     if ($allowFiles && $this->attachmentPrevName && !$this->attachmentSrcName) {
         # If the user is submitting forgotAttachment as true with no file,
         # then they saw the notice and choose not to re-select the file.
         # Assume that they don't want to send one anymore.
         if (!$this->attachmentDidNotForget) {
             $this->attachmentPrevName = '';
             $this->attachmentDidNotForget = 0;
             return array(false, $context->msg('requestaccount-resub')->escaped());
         }
     }
     # Check if already in use
     if (0 != $u->idForName() || $wgAuth->userExists($u->getName())) {
         return array('accountreq_username_exists', $context->msg('userexists')->escaped());
     }
     # Set email and real name
     $u->setEmail($this->email);
     $u->setRealName($this->realName);
     $dbw = wfGetDB(DB_MASTER);
     $dbw->begin();
     // ready to acquire locks
     # Check pending accounts for name use
     if (!UserAccountRequest::acquireUsername($u->getName())) {
         $dbw->rollback();
         return array('accountreq_username_pending', $context->msg('requestaccount-inuse')->escaped());
     }
     # Check if someone else has an account request with the same email
     if (!UserAccountRequest::acquireEmail($u->getEmail())) {
         $dbw->rollback();
         return array('acct_request_email_exists', $context->msg('requestaccount-emaildup')->escaped());
     }
     # Process upload...
     if ($allowFiles && $this->attachmentSrcName) {
         global $wgAccountRequestExts, $wgConfirmAccountFSRepos;
         $ext = explode('.', $this->attachmentSrcName);
         $finalExt = $ext[count($ext) - 1];
         # File must have size.
         if (trim($this->attachmentSrcName) == '' || empty($this->attachmentSize)) {
             $this->attachmentPrevName = '';
             $dbw->rollback();
             return array('acct_request_empty_file', $context->msg('emptyfile')->escaped());
         }
         # Look at the contents of the file; if we can recognize the
         # type but it's corrupt or data of the wrong type, we should
         # probably not accept it.
         if (!in_array($finalExt, $wgAccountRequestExts)) {
             $this->attachmentPrevName = '';
             $dbw->rollback();
             return array('acct_request_bad_file_ext', $context->msg('requestaccount-exts')->escaped());
         }
         $veri = ConfirmAccount::verifyAttachment($this->attachmentTempPath, $finalExt);
         if (!$veri->isGood()) {
             $this->attachmentPrevName = '';
             $dbw->rollback();
             return array('acct_request_corrupt_file', $context->msg('verification-error')->escaped());
         }
         # Start a transaction, move file from temp to account request directory.
         $repo = new FSRepo($wgConfirmAccountFSRepos['accountreqs']);
         $key = sha1_file($this->attachmentTempPath) . '.' . $finalExt;
         $pathRel = UserAccountRequest::relPathFromKey($key);
         $triplet = array($this->attachmentTempPath, 'public', $pathRel);
         $status = $repo->storeBatch(array($triplet), FSRepo::OVERWRITE_SAME);
         // save!
         if (!$status->isOk()) {
             $dbw->rollback();
             return array('acct_request_file_store_error', $context->msg('filecopyerror', $this->attachmentTempPath, $pathRel)->escaped());
         }
     }
     $expires = null;
     // passed by reference
     $token = ConfirmAccount::getConfirmationToken($u, $expires);
     # Insert into pending requests...
     $req = UserAccountRequest::newFromArray(array('name' => $u->getName(), 'email' => $u->getEmail(), 'real_name' => $u->getRealName(), 'registration' => $this->registration, 'bio' => $this->bio, 'notes' => $this->notes, 'urls' => $this->urls, 'filename' => isset($this->attachmentSrcName) ? $this->attachmentSrcName : null, 'type' => $this->type, 'areas' => $this->areas, 'storage_key' => isset($key) ? $key : null, 'comment' => '', 'email_token' => md5($token), 'email_token_expires' => $expires, 'ip' => $this->ip, 'xff' => $this->xff, 'agent' => $this->agent));
     $req->insertOn();
     # Send confirmation, required!
     $result = ConfirmAccount::sendConfirmationMail($u, $this->ip, $token, $expires);
     if (!$result->isOK()) {
         $dbw->rollback();
         // nevermind
         if (isset($repo) && isset($pathRel)) {
             // remove attachment
             $repo->cleanupBatch(array(array('public', $pathRel)));
         }
         $param = $context->getOutput()->parse($result->getWikiText());
         return array('acct_request_mail_failed', $context->msg('mailerror')->rawParams($param)->escaped());
     }
     $dbw->commit();
     # Clear cache for notice of how many account requests there are
     ConfirmAccount::clearAccountRequestCountCache();
     # No request spamming...
     if ($wgAccountRequestThrottle && $reqUser->isPingLimitable()) {
         $ip = $context->getRequest()->getIP();
         $key = wfMemcKey('acctrequest', 'ip', $ip);
         $value = $wgMemc->incr($key);
         if (!$value) {
             $wgMemc->set($key, 1, 86400);
         }
     }
     # Done!
     return array(true, null);
 }
 function showCredentials()
 {
     $reqUser = $this->getUser();
     $out = $this->getOutput();
     $titleObj = SpecialPage::getTitleFor('UserCredentials');
     $row = $this->getAccountData();
     if (!$row) {
         $out->addHTML(wfMsgHtml('usercredentials-badid'));
         return;
     }
     $out->addWikiText(wfMsg("usercredentials-text"));
     $user = User::newFromName($this->target);
     $list = array();
     foreach ($user->getGroups() as $group) {
         $list[] = self::buildGroupLink($group);
     }
     $grouplist = '';
     if (count($list) > 0) {
         $grouplist = '<tr><td>' . wfMsgHtml('usercredentials-member') . '</td><td>' . implode(', ', $list) . '</td></tr>';
     }
     $form = "<fieldset>";
     $form .= '<legend>' . wfMsgHtml('usercredentials-leg-user') . '</legend>';
     $form .= '<table cellpadding=\'4\'>';
     $form .= "<tr><td>" . wfMsgHtml('username') . "</td>";
     $form .= "<td>" . Linker::makeLinkObj($user->getUserPage(), htmlspecialchars($user->getUserPage()->getText())) . "</td></tr>\n";
     $econf = $row->acd_email_authenticated ? ' <strong>' . wfMsgHtml('confirmaccount-econf') . '</strong>' : '';
     $form .= "<tr><td>" . wfMsgHtml('usercredentials-email') . "</td>";
     $form .= "<td>" . htmlspecialchars($row->acd_email) . $econf . "</td></tr>\n";
     $form .= $grouplist;
     $form .= '</table></fieldset>';
     $areaSet = UserAccountRequest::expandAreas($row->acd_areas);
     $userAreas = ConfirmAccount::getUserAreaConfig();
     if (count($userAreas) > 0) {
         $form .= '<fieldset>';
         $form .= '<legend>' . wfMsgHtml('confirmaccount-leg-areas') . '</legend>';
         $form .= "<div style='height:150px; overflow:scroll; background-color:#f9f9f9;'>";
         $form .= "<table cellspacing='5' cellpadding='0' style='background-color:#f9f9f9;'><tr valign='top'>";
         $count = 0;
         $att = array('disabled' => 'disabled');
         foreach ($userAreas as $name => $conf) {
             $count++;
             if ($count > 5) {
                 $form .= "</tr><tr valign='top'>";
                 $count = 1;
             }
             $formName = "wpArea-" . htmlspecialchars(str_replace(' ', '_', $name));
             if ($conf['project'] != '') {
                 $pg = Linker::link(Title::newFromText($name), wfMsgHtml('requestaccount-info'), array(), array(), "known");
             } else {
                 $pg = '';
             }
             $form .= "<td>" . Xml::checkLabel($name, $formName, $formName, in_array($formName, $areaSet), $att) . " {$pg}</td>\n";
         }
         $form .= "</tr></table></div>";
         $form .= '</fieldset>';
     }
     $form .= '<fieldset>';
     $form .= '<legend>' . wfMsgHtml('usercredentials-leg-person') . '</legend>';
     $form .= '<table cellpadding=\'4\'>';
     $form .= "<tr><td>" . wfMsgHtml('usercredentials-real') . "</td>";
     $form .= "<td>" . htmlspecialchars($row->acd_real_name) . "</td></tr>\n";
     $form .= '</table>';
     $form .= "<p>" . wfMsgHtml('usercredentials-bio') . "</p>";
     $form .= "<p><textarea tabindex='1' readonly='readonly' name='wpBio' id='wpNewBio' rows='10' cols='80' style='width:100%'>" . htmlspecialchars($row->acd_bio) . "</textarea></p>\n";
     $form .= '</fieldset>';
     $form .= '<fieldset>';
     $form .= '<legend>' . wfMsgHtml('usercredentials-leg-other') . '</legend>';
     global $wgAccountRequestExtraInfo;
     if ($wgAccountRequestExtraInfo) {
         $form .= '<p>' . wfMsgHtml('usercredentials-attach') . ' ';
         if ($row->acd_filename) {
             $form .= Linker::makeKnownLinkObj($titleObj, htmlspecialchars($row->acd_filename), 'file=' . $row->acd_storage_key);
         } else {
             $form .= wfMsgHtml('confirmaccount-none-p');
         }
         $form .= "</p><p>" . wfMsgHtml('usercredentials-notes') . "</p>\n";
         $form .= "<p><textarea tabindex='1' readonly='readonly' name='wpNotes' id='wpNotes' rows='3' cols='80' style='width:100%'>" . htmlspecialchars($row->acd_notes) . "</textarea></p>\n";
         $form .= "<p>" . wfMsgHtml('usercredentials-urls') . "</p>\n";
         $form .= ConfirmAccountsPage::parseLinks($row->acd_urls);
     }
     if ($reqUser->isAllowed('requestips')) {
         $form .= "<p>" . wfMsgHtml('usercredentials-ip') . " " . htmlspecialchars($row->acd_ip) . "</p>\n";
     }
     $form .= '</fieldset>';
     $out->addHTML($form);
 }
 /**
  * (a) Try to confirm an email address via a token
  * (b) Notify $wgConfirmAccountContact on success
  * @param $code string The token
  * @return void
  */
 protected function confirmEmailToken($code)
 {
     global $wgConfirmAccountContact, $wgPasswordSender, $wgPasswordSenderName;
     $reqUser = $this->getUser();
     $out = $this->getOutput();
     # Confirm if this token is in the pending requests
     $name = ConfirmAccount::requestNameFromEmailToken($code);
     if ($name !== false) {
         # Send confirmation email to prospective user
         ConfirmAccount::confirmEmail($name);
         # Send mail to admin after e-mail has been confirmed
         if ($wgConfirmAccountContact != '') {
             $target = new MailAddress($wgConfirmAccountContact);
             $source = new MailAddress($wgPasswordSender, $wgPasswordSenderName);
             $title = SpecialPage::getTitleFor('ConfirmAccounts');
             $subject = wfMsgForContent('requestaccount-email-subj-admin');
             $body = wfMsgForContent('requestaccount-email-body-admin', $name, $title->getFullUrl());
             # Actually send the email...
             $result = UserMailer::send($target, $source, $subject, $body);
             if (!$result->isOK()) {
                 wfDebug("Could not sent email to admin at {$target}\n");
             }
         }
         $out->addWikiMsg('request-account-econf');
         $out->returnToMain();
     } else {
         # Maybe the user confirmed after account was created...
         $user = User::newFromConfirmationCode($code);
         if (is_object($user)) {
             if ($user->confirmEmail()) {
                 $message = $reqUser->isLoggedIn() ? 'confirmemail_loggedin' : 'confirmemail_success';
                 $out->addWikiMsg($message);
                 if (!$reqUser->isLoggedIn()) {
                     $title = SpecialPage::getTitleFor('Userlogin');
                     $out->returnToMain(true, $title->getPrefixedUrl());
                 }
             } else {
                 $out->addWikiMsg('confirmemail_error');
             }
         } else {
             $out->addWikiMsg('confirmemail_invalid');
         }
     }
 }
 /**
  * (a) Try to confirm an email address via a token
  * (b) Notify $wgConfirmAccountContact on success
  * @param $code string The token
  * @return void
  */
 protected function confirmEmailToken($code)
 {
     global $wgConfirmAccountContact, $wgPasswordSender;
     $reqUser = $this->getUser();
     $out = $this->getOutput();
     # Confirm if this token is in the pending requests
     $name = ConfirmAccount::requestNameFromEmailToken($code);
     if ($name !== false) {
         # Send confirmation email to prospective user
         ConfirmAccount::confirmEmail($name);
         $adminsNotify = ConfirmAccount::getAdminsToNotify();
         # Send an email to admin after email has been confirmed
         if ($adminsNotify->count() || $wgConfirmAccountContact != '') {
             $title = SpecialPage::getTitleFor('ConfirmAccounts');
             $subject = $this->msg('requestaccount-email-subj-admin')->inContentLanguage()->escaped();
             $body = $this->msg('requestaccount-email-body-admin', $name)->rawParams($title->getFullUrl())->inContentLanguage()->escaped();
             # Actually send the email...
             if ($wgConfirmAccountContact != '') {
                 $source = new MailAddress($wgPasswordSender, wfMessage('emailsender')->text());
                 $target = new MailAddress($wgConfirmAccountContact);
                 $result = UserMailer::send($target, $source, $subject, $body);
                 if (!$result->isOK()) {
                     wfDebug("Could not sent email to admin at {$target}\n");
                 }
             }
             # Send an email to all users with "confirmaccount-notify" rights
             foreach ($adminsNotify as $adminNotify) {
                 if ($adminNotify->canReceiveEmail()) {
                     $adminNotify->sendMail($subject, $body);
                 }
             }
         }
         $out->addWikiMsg('request-account-econf');
         $out->returnToMain();
     } else {
         # Maybe the user confirmed after account was created...
         $user = User::newFromConfirmationCode($code);
         if (is_object($user)) {
             $user->confirmEmail();
             $user->saveSettings();
             $message = $reqUser->isLoggedIn() ? 'confirmemail_loggedin' : 'confirmemail_success';
             $out->addWikiMsg($message);
             if (!$reqUser->isLoggedIn()) {
                 $title = SpecialPage::getTitleFor('Userlogin');
                 $out->returnToMain(true, $title);
             }
         } else {
             $out->addWikiMsg('confirmemail_invalid');
         }
     }
 }