コード例 #1
0
 /**
  * Unblocks the specified user or provides the reason the unblock failed.
  */
 public function execute()
 {
     $user = $this->getUser();
     $params = $this->extractRequestParams();
     if (is_null($params['id']) && is_null($params['user'])) {
         $this->dieUsageMsg('unblock-notarget');
     }
     if (!is_null($params['id']) && !is_null($params['user'])) {
         $this->dieUsageMsg('unblock-idanduser');
     }
     if (!$user->isAllowed('block')) {
         $this->dieUsageMsg('cantunblock');
     }
     # bug 15810: blocked admins should have limited access here
     if ($user->isBlocked()) {
         $status = SpecialBlock::checkUnblockSelf($params['user'], $user);
         if ($status !== true) {
             $msg = $this->parseMsg($status);
             $this->dieUsage($msg['info'], $msg['code'], 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($user->getBlock())));
         }
     }
     $data = array('Target' => is_null($params['id']) ? $params['user'] : "******", 'Reason' => $params['reason']);
     $block = Block::newFromTarget($data['Target']);
     $retval = SpecialUnblock::processUnblock($data, $this->getContext());
     if ($retval !== true) {
         $this->dieUsageMsg($retval[0]);
     }
     $res['id'] = $block->getId();
     $target = $block->getType() == Block::TYPE_AUTO ? '' : $block->getTarget();
     $res['user'] = $target instanceof User ? $target->getName() : $target;
     $res['userid'] = $target instanceof User ? $target->getId() : 0;
     $res['reason'] = $params['reason'];
     $this->getResult()->addValue(null, $this->getModuleName(), $res);
 }
コード例 #2
0
ファイル: ApiBlock.php プロジェクト: claudinec/galan-wiki
 /**
  * Blocks the user specified in the parameters for the given expiry, with the
  * given reason, and with all other settings provided in the params. If the block
  * succeeds, produces a result containing the details of the block and notice
  * of success. If it fails, the result will specify the nature of the error.
  */
 public function execute()
 {
     global $wgContLang;
     $user = $this->getUser();
     $params = $this->extractRequestParams();
     if (!$user->isAllowed('block')) {
         $this->dieUsageMsg('cantblock');
     }
     # bug 15810: blocked admins should have limited access here
     if ($user->isBlocked()) {
         $status = SpecialBlock::checkUnblockSelf($params['user'], $user);
         if ($status !== true) {
             $msg = $this->parseMsg($status);
             $this->dieUsage($msg['info'], $msg['code'], 0, ['blockinfo' => ApiQueryUserInfo::getBlockInfo($user->getBlock())]);
         }
     }
     $target = User::newFromName($params['user']);
     // Bug 38633 - if the target is a user (not an IP address), but it
     // doesn't exist or is unusable, error.
     if ($target instanceof User && ($target->isAnon() || !User::isUsableName($target->getName()))) {
         $this->dieUsageMsg(['nosuchuser', $params['user']]);
     }
     if ($params['hidename'] && !$user->isAllowed('hideuser')) {
         $this->dieUsageMsg('canthide');
     }
     if ($params['noemail'] && !SpecialBlock::canBlockEmail($user)) {
         $this->dieUsageMsg('cantblock-email');
     }
     $data = ['PreviousTarget' => $params['user'], 'Target' => $params['user'], 'Reason' => [$params['reason'], 'other', $params['reason']], 'Expiry' => $params['expiry'], 'HardBlock' => !$params['anononly'], 'CreateAccount' => $params['nocreate'], 'AutoBlock' => $params['autoblock'], 'DisableEmail' => $params['noemail'], 'HideUser' => $params['hidename'], 'DisableUTEdit' => !$params['allowusertalk'], 'Reblock' => $params['reblock'], 'Watch' => $params['watchuser'], 'Confirm' => true];
     $retval = SpecialBlock::processForm($data, $this->getContext());
     if ($retval !== true) {
         // We don't care about multiple errors, just report one of them
         $this->dieUsageMsg($retval);
     }
     list($target, ) = SpecialBlock::getTargetAndType($params['user']);
     $res['user'] = $params['user'];
     $res['userID'] = $target instanceof User ? $target->getId() : 0;
     $block = Block::newFromTarget($target, null, true);
     if ($block instanceof Block) {
         $res['expiry'] = $wgContLang->formatExpiry($block->mExpiry, TS_ISO_8601, 'infinite');
         $res['id'] = $block->getId();
     } else {
         # should be unreachable
         $res['expiry'] = '';
         $res['id'] = '';
     }
     $res['reason'] = $params['reason'];
     $res['anononly'] = $params['anononly'];
     $res['nocreate'] = $params['nocreate'];
     $res['autoblock'] = $params['autoblock'];
     $res['noemail'] = $params['noemail'];
     $res['hidename'] = $params['hidename'];
     $res['allowusertalk'] = $params['allowusertalk'];
     $res['watchuser'] = $params['watchuser'];
     $this->getResult()->addValue(null, $this->getModuleName(), $res);
 }
コード例 #3
0
 public function execute()
 {
     $this->useTransactionalTimeLimit();
     $params = $this->extractRequestParams();
     if (!$this->getUser()->isAllowed('undelete')) {
         $this->dieUsageMsg('permdenied-undelete');
     }
     if ($this->getUser()->isBlocked()) {
         $this->dieUsage('You have been blocked from editing', 'blocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($this->getUser()->getBlock())));
     }
     $titleObj = Title::newFromText($params['title']);
     if (!$titleObj || $titleObj->isExternal()) {
         $this->dieUsageMsg(array('invalidtitle', $params['title']));
     }
     // Convert timestamps
     if (!isset($params['timestamps'])) {
         $params['timestamps'] = array();
     }
     if (!is_array($params['timestamps'])) {
         $params['timestamps'] = array($params['timestamps']);
     }
     foreach ($params['timestamps'] as $i => $ts) {
         $params['timestamps'][$i] = wfTimestamp(TS_MW, $ts);
     }
     $pa = new PageArchive($titleObj, $this->getConfig());
     $retval = $pa->undelete(isset($params['timestamps']) ? $params['timestamps'] : array(), $params['reason'], $params['fileids'], false, $this->getUser());
     if (!is_array($retval)) {
         $this->dieUsageMsg('cannotundelete');
     }
     if ($retval[1]) {
         Hooks::run('FileUndeleteComplete', array($titleObj, $params['fileids'], $this->getUser(), $params['reason']));
     }
     $this->setWatch($params['watchlist'], $titleObj);
     $info['title'] = $titleObj->getPrefixedText();
     $info['revisions'] = intval($retval[0]);
     $info['fileversions'] = intval($retval[1]);
     $info['reason'] = $retval[2];
     $this->getResult()->addValue(null, $this->getModuleName(), $info);
 }
コード例 #4
0
ファイル: ApiTag.php プロジェクト: xfstudio/mediawiki
 public function execute()
 {
     $params = $this->extractRequestParams();
     $user = $this->getUser();
     // make sure the user is allowed
     if (!$user->isAllowed('changetags')) {
         $this->dieUsage("You don't have permission to add or remove change tags from individual edits", 'permissiondenied');
     }
     if ($user->isBlocked()) {
         $block = $user->getBlock();
         // Die using the appropriate message depending on block type
         if ($block->getType() == TYPE_AUTO) {
             $this->dieUsage('Your IP address has been blocked automatically, because it was used by a blocked user', 'autoblocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($block)));
         } else {
             $this->dieUsage('You have been blocked from editing', 'blocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($block)));
         }
     }
     // validate and process each revid, rcid and logid
     $this->requireAtLeastOneParameter($params, 'revid', 'rcid', 'logid');
     $ret = array();
     if ($params['revid']) {
         foreach ($params['revid'] as $id) {
             $ret[] = $this->processIndividual('revid', $params, $id);
         }
     }
     if ($params['rcid']) {
         foreach ($params['rcid'] as $id) {
             $ret[] = $this->processIndividual('rcid', $params, $id);
         }
     }
     if ($params['logid']) {
         foreach ($params['logid'] as $id) {
             $ret[] = $this->processIndividual('logid', $params, $id);
         }
     }
     ApiResult::setIndexedTagName($ret, 'result');
     $this->getResult()->addValue(null, $this->getModuleName(), $ret);
 }
コード例 #5
0
ファイル: ApiQueryUsers.php プロジェクト: paladox/mediawiki
 public function execute()
 {
     $params = $this->extractRequestParams();
     if (!is_null($params['prop'])) {
         $this->prop = array_flip($params['prop']);
     } else {
         $this->prop = [];
     }
     $users = (array) $params['users'];
     $goodNames = $done = [];
     $result = $this->getResult();
     // Canonicalize user names
     foreach ($users as $u) {
         $n = User::getCanonicalName($u);
         if ($n === false || $n === '') {
             $vals = ['name' => $u, 'invalid' => true];
             $fit = $result->addValue(['query', $this->getModuleName()], null, $vals);
             if (!$fit) {
                 $this->setContinueEnumParameter('users', implode('|', array_diff($users, $done)));
                 $goodNames = [];
                 break;
             }
             $done[] = $u;
         } else {
             $goodNames[] = $n;
         }
     }
     $result = $this->getResult();
     if (count($goodNames)) {
         $this->addTables('user');
         $this->addFields(User::selectFields());
         $this->addWhereFld('user_name', $goodNames);
         $this->showHiddenUsersAddBlockInfo(isset($this->prop['blockinfo']));
         $data = [];
         $res = $this->select(__METHOD__);
         $this->resetQueryParams();
         // get user groups if needed
         if (isset($this->prop['groups']) || isset($this->prop['rights'])) {
             $userGroups = [];
             $this->addTables('user');
             $this->addWhereFld('user_name', $goodNames);
             $this->addTables('user_groups');
             $this->addJoinConds(['user_groups' => ['INNER JOIN', 'ug_user=user_id']]);
             $this->addFields(['user_name', 'ug_group']);
             $userGroupsRes = $this->select(__METHOD__);
             foreach ($userGroupsRes as $row) {
                 $userGroups[$row->user_name][] = $row->ug_group;
             }
         }
         foreach ($res as $row) {
             // create user object and pass along $userGroups if set
             // that reduces the number of database queries needed in User dramatically
             if (!isset($userGroups)) {
                 $user = User::newFromRow($row);
             } else {
                 if (!isset($userGroups[$row->user_name]) || !is_array($userGroups[$row->user_name])) {
                     $userGroups[$row->user_name] = [];
                 }
                 $user = User::newFromRow($row, ['user_groups' => $userGroups[$row->user_name]]);
             }
             $name = $user->getName();
             $data[$name]['userid'] = $user->getId();
             $data[$name]['name'] = $name;
             if (isset($this->prop['editcount'])) {
                 $data[$name]['editcount'] = $user->getEditCount();
             }
             if (isset($this->prop['registration'])) {
                 $data[$name]['registration'] = wfTimestampOrNull(TS_ISO_8601, $user->getRegistration());
             }
             if (isset($this->prop['groups'])) {
                 $data[$name]['groups'] = $user->getEffectiveGroups();
             }
             if (isset($this->prop['implicitgroups'])) {
                 $data[$name]['implicitgroups'] = $user->getAutomaticGroups();
             }
             if (isset($this->prop['rights'])) {
                 $data[$name]['rights'] = $user->getRights();
             }
             if ($row->ipb_deleted) {
                 $data[$name]['hidden'] = true;
             }
             if (isset($this->prop['blockinfo']) && !is_null($row->ipb_by_text)) {
                 $data[$name]['blockid'] = (int) $row->ipb_id;
                 $data[$name]['blockedby'] = $row->ipb_by_text;
                 $data[$name]['blockedbyid'] = (int) $row->ipb_by;
                 $data[$name]['blockedtimestamp'] = wfTimestamp(TS_ISO_8601, $row->ipb_timestamp);
                 $data[$name]['blockreason'] = $row->ipb_reason;
                 $data[$name]['blockexpiry'] = $row->ipb_expiry;
             }
             if (isset($this->prop['emailable'])) {
                 $data[$name]['emailable'] = $user->canReceiveEmail();
             }
             if (isset($this->prop['gender'])) {
                 $gender = $user->getOption('gender');
                 if (strval($gender) === '') {
                     $gender = 'unknown';
                 }
                 $data[$name]['gender'] = $gender;
             }
             if (isset($this->prop['centralids'])) {
                 $data[$name] += ApiQueryUserInfo::getCentralUserInfo($this->getConfig(), $user, $params['attachedwiki']);
             }
             if (!is_null($params['token'])) {
                 $tokenFunctions = $this->getTokenFunctions();
                 foreach ($params['token'] as $t) {
                     $val = call_user_func($tokenFunctions[$t], $user);
                     if ($val === false) {
                         $this->setWarning("Action '{$t}' is not allowed for the current user");
                     } else {
                         $data[$name][$t . 'token'] = $val;
                     }
                 }
             }
         }
     }
     $context = $this->getContext();
     // Second pass: add result data to $retval
     foreach ($goodNames as $u) {
         if (!isset($data[$u])) {
             $data[$u] = ['name' => $u];
             $urPage = new UserrightsPage();
             $urPage->setContext($context);
             $iwUser = $urPage->fetchUser($u);
             if ($iwUser instanceof UserRightsProxy) {
                 $data[$u]['interwiki'] = true;
                 if (!is_null($params['token'])) {
                     $tokenFunctions = $this->getTokenFunctions();
                     foreach ($params['token'] as $t) {
                         $val = call_user_func($tokenFunctions[$t], $iwUser);
                         if ($val === false) {
                             $this->setWarning("Action '{$t}' is not allowed for the current user");
                         } else {
                             $data[$u][$t . 'token'] = $val;
                         }
                     }
                 }
             } else {
                 $data[$u]['missing'] = true;
                 if (isset($this->prop['cancreate'])) {
                     $status = MediaWiki\Auth\AuthManager::singleton()->canCreateAccount($u);
                     $data[$u]['cancreate'] = $status->isGood();
                     if (!$status->isGood()) {
                         $data[$u]['cancreateerror'] = $this->getErrorFormatter()->arrayFromStatus($status);
                     }
                 }
             }
         } else {
             if (isset($this->prop['groups']) && isset($data[$u]['groups'])) {
                 ApiResult::setArrayType($data[$u]['groups'], 'array');
                 ApiResult::setIndexedTagName($data[$u]['groups'], 'g');
             }
             if (isset($this->prop['implicitgroups']) && isset($data[$u]['implicitgroups'])) {
                 ApiResult::setArrayType($data[$u]['implicitgroups'], 'array');
                 ApiResult::setIndexedTagName($data[$u]['implicitgroups'], 'g');
             }
             if (isset($this->prop['rights']) && isset($data[$u]['rights'])) {
                 ApiResult::setArrayType($data[$u]['rights'], 'array');
                 ApiResult::setIndexedTagName($data[$u]['rights'], 'r');
             }
         }
         $fit = $result->addValue(['query', $this->getModuleName()], null, $data[$u]);
         if (!$fit) {
             $this->setContinueEnumParameter('users', implode('|', array_diff($users, $done)));
             break;
         }
         $done[] = $u;
     }
     $result->addIndexedTagName(['query', $this->getModuleName()], 'user');
 }
コード例 #6
0
ファイル: ApiEditPage.php プロジェクト: D66Ha/mediawiki
 public function execute()
 {
     $user = $this->getUser();
     $params = $this->extractRequestParams();
     if (is_null($params['text']) && is_null($params['appendtext']) && is_null($params['prependtext']) && $params['undo'] == 0) {
         $this->dieUsageMsg('missingtext');
     }
     $pageObj = $this->getTitleOrPageId($params);
     $titleObj = $pageObj->getTitle();
     $apiResult = $this->getResult();
     if ($params['redirect']) {
         if ($params['prependtext'] === null && $params['appendtext'] === null && $params['section'] !== 'new') {
             $this->dieUsage('You have attempted to edit using the "redirect"-following' . ' mode, which must be used in conjuction with section=new, prependtext' . ', or appendtext.', 'redirect-appendonly');
         }
         if ($titleObj->isRedirect()) {
             $oldTitle = $titleObj;
             $titles = Revision::newFromTitle($oldTitle, false, Revision::READ_LATEST)->getContent(Revision::FOR_THIS_USER, $user)->getRedirectChain();
             // array_shift( $titles );
             $redirValues = array();
             /** @var $newTitle Title */
             foreach ($titles as $id => $newTitle) {
                 if (!isset($titles[$id - 1])) {
                     $titles[$id - 1] = $oldTitle;
                 }
                 $redirValues[] = array('from' => $titles[$id - 1]->getPrefixedText(), 'to' => $newTitle->getPrefixedText());
                 $titleObj = $newTitle;
             }
             ApiResult::setIndexedTagName($redirValues, 'r');
             $apiResult->addValue(null, 'redirects', $redirValues);
             // Since the page changed, update $pageObj
             $pageObj = WikiPage::factory($titleObj);
         }
     }
     if (!isset($params['contentmodel']) || $params['contentmodel'] == '') {
         $contentHandler = $pageObj->getContentHandler();
     } else {
         $contentHandler = ContentHandler::getForModelID($params['contentmodel']);
     }
     $name = $titleObj->getPrefixedDBkey();
     $model = $contentHandler->getModelID();
     if ($contentHandler->supportsDirectApiEditing() === false) {
         $this->dieUsage("Direct editing via API is not supported for content model {$model} used by {$name}", 'no-direct-editing');
     }
     if (!isset($params['contentformat']) || $params['contentformat'] == '') {
         $params['contentformat'] = $contentHandler->getDefaultFormat();
     }
     $contentFormat = $params['contentformat'];
     if (!$contentHandler->isSupportedFormat($contentFormat)) {
         $this->dieUsage("The requested format {$contentFormat} is not supported for content model " . " {$model} used by {$name}", 'badformat');
     }
     if ($params['createonly'] && $titleObj->exists()) {
         $this->dieUsageMsg('createonly-exists');
     }
     if ($params['nocreate'] && !$titleObj->exists()) {
         $this->dieUsageMsg('nocreate-missing');
     }
     // Now let's check whether we're even allowed to do this
     $errors = $titleObj->getUserPermissionsErrors('edit', $user);
     if (!$titleObj->exists()) {
         $errors = array_merge($errors, $titleObj->getUserPermissionsErrors('create', $user));
     }
     if (count($errors)) {
         if (is_array($errors[0])) {
             switch ($errors[0][0]) {
                 case 'blockedtext':
                     $this->dieUsage('You have been blocked from editing', 'blocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($user->getBlock())));
                     break;
                 case 'autoblockedtext':
                     $this->dieUsage('Your IP address has been blocked automatically, because it was used by a blocked user', 'autoblocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($user->getBlock())));
                     break;
                 default:
                     $this->dieUsageMsg($errors[0]);
             }
         } else {
             $this->dieUsageMsg($errors[0]);
         }
     }
     $toMD5 = $params['text'];
     if (!is_null($params['appendtext']) || !is_null($params['prependtext'])) {
         $content = $pageObj->getContent();
         if (!$content) {
             if ($titleObj->getNamespace() == NS_MEDIAWIKI) {
                 # If this is a MediaWiki:x message, then load the messages
                 # and return the message value for x.
                 $text = $titleObj->getDefaultMessageText();
                 if ($text === false) {
                     $text = '';
                 }
                 try {
                     $content = ContentHandler::makeContent($text, $this->getTitle());
                 } catch (MWContentSerializationException $ex) {
                     $this->dieUsage($ex->getMessage(), 'parseerror');
                     return;
                 }
             } else {
                 # Otherwise, make a new empty content.
                 $content = $contentHandler->makeEmptyContent();
             }
         }
         // @todo Add support for appending/prepending to the Content interface
         if (!$content instanceof TextContent) {
             $mode = $contentHandler->getModelID();
             $this->dieUsage("Can't append to pages using content model {$mode}", 'appendnotsupported');
         }
         if (!is_null($params['section'])) {
             if (!$contentHandler->supportsSections()) {
                 $modelName = $contentHandler->getModelID();
                 $this->dieUsage("Sections are not supported for this content model: {$modelName}.", 'sectionsnotsupported');
             }
             if ($params['section'] == 'new') {
                 // DWIM if they're trying to prepend/append to a new section.
                 $content = null;
             } else {
                 // Process the content for section edits
                 $section = $params['section'];
                 $content = $content->getSection($section);
                 if (!$content) {
                     $this->dieUsage("There is no section {$section}.", 'nosuchsection');
                 }
             }
         }
         if (!$content) {
             $text = '';
         } else {
             $text = $content->serialize($contentFormat);
         }
         $params['text'] = $params['prependtext'] . $text . $params['appendtext'];
         $toMD5 = $params['prependtext'] . $params['appendtext'];
     }
     if ($params['undo'] > 0) {
         if ($params['undoafter'] > 0) {
             if ($params['undo'] < $params['undoafter']) {
                 list($params['undo'], $params['undoafter']) = array($params['undoafter'], $params['undo']);
             }
             $undoafterRev = Revision::newFromId($params['undoafter']);
         }
         $undoRev = Revision::newFromId($params['undo']);
         if (is_null($undoRev) || $undoRev->isDeleted(Revision::DELETED_TEXT)) {
             $this->dieUsageMsg(array('nosuchrevid', $params['undo']));
         }
         if ($params['undoafter'] == 0) {
             $undoafterRev = $undoRev->getPrevious();
         }
         if (is_null($undoafterRev) || $undoafterRev->isDeleted(Revision::DELETED_TEXT)) {
             $this->dieUsageMsg(array('nosuchrevid', $params['undoafter']));
         }
         if ($undoRev->getPage() != $pageObj->getID()) {
             $this->dieUsageMsg(array('revwrongpage', $undoRev->getID(), $titleObj->getPrefixedText()));
         }
         if ($undoafterRev->getPage() != $pageObj->getID()) {
             $this->dieUsageMsg(array('revwrongpage', $undoafterRev->getID(), $titleObj->getPrefixedText()));
         }
         $newContent = $contentHandler->getUndoContent($pageObj->getRevision(), $undoRev, $undoafterRev);
         if (!$newContent) {
             $this->dieUsageMsg('undo-failure');
         }
         $params['text'] = $newContent->serialize($params['contentformat']);
         // If no summary was given and we only undid one rev,
         // use an autosummary
         if (is_null($params['summary']) && $titleObj->getNextRevisionID($undoafterRev->getID()) == $params['undo']) {
             $params['summary'] = wfMessage('undo-summary')->params($params['undo'], $undoRev->getUserText())->inContentLanguage()->text();
         }
     }
     // See if the MD5 hash checks out
     if (!is_null($params['md5']) && md5($toMD5) !== $params['md5']) {
         $this->dieUsageMsg('hashcheckfailed');
     }
     // EditPage wants to parse its stuff from a WebRequest
     // That interface kind of sucks, but it's workable
     $requestArray = array('wpTextbox1' => $params['text'], 'format' => $contentFormat, 'model' => $contentHandler->getModelID(), 'wpEditToken' => $params['token'], 'wpIgnoreBlankSummary' => true, 'wpIgnoreBlankArticle' => true, 'wpIgnoreSelfRedirect' => true, 'bot' => $params['bot']);
     if (!is_null($params['summary'])) {
         $requestArray['wpSummary'] = $params['summary'];
     }
     if (!is_null($params['sectiontitle'])) {
         $requestArray['wpSectionTitle'] = $params['sectiontitle'];
     }
     // TODO: Pass along information from 'undoafter' as well
     if ($params['undo'] > 0) {
         $requestArray['wpUndidRevision'] = $params['undo'];
     }
     // Watch out for basetimestamp == '' or '0'
     // It gets treated as NOW, almost certainly causing an edit conflict
     if ($params['basetimestamp'] !== null && (bool) $this->getMain()->getVal('basetimestamp')) {
         $requestArray['wpEdittime'] = $params['basetimestamp'];
     } else {
         $requestArray['wpEdittime'] = $pageObj->getTimestamp();
     }
     if ($params['starttimestamp'] !== null) {
         $requestArray['wpStarttime'] = $params['starttimestamp'];
     } else {
         $requestArray['wpStarttime'] = wfTimestampNow();
         // Fake wpStartime
     }
     if ($params['minor'] || !$params['notminor'] && $user->getOption('minordefault')) {
         $requestArray['wpMinoredit'] = '';
     }
     if ($params['recreate']) {
         $requestArray['wpRecreate'] = '';
     }
     if (!is_null($params['section'])) {
         $section = $params['section'];
         if (!preg_match('/^((T-)?\\d+|new)$/', $section)) {
             $this->dieUsage("The section parameter must be a valid section id or 'new'", "invalidsection");
         }
         $content = $pageObj->getContent();
         if ($section !== '0' && $section != 'new' && (!$content || !$content->getSection($section))) {
             $this->dieUsage("There is no section {$section}.", 'nosuchsection');
         }
         $requestArray['wpSection'] = $params['section'];
     } else {
         $requestArray['wpSection'] = '';
     }
     $watch = $this->getWatchlistValue($params['watchlist'], $titleObj);
     // Deprecated parameters
     if ($params['watch']) {
         $this->logFeatureUsage('action=edit&watch');
         $watch = true;
     } elseif ($params['unwatch']) {
         $this->logFeatureUsage('action=edit&unwatch');
         $watch = false;
     }
     if ($watch) {
         $requestArray['wpWatchthis'] = '';
     }
     // Apply change tags
     if (count($params['tags'])) {
         if ($user->isAllowed('applychangetags')) {
             $requestArray['wpChangeTags'] = implode(',', $params['tags']);
         } else {
             $this->dieUsage('You don\'t have permission to set change tags.', 'taggingnotallowed');
         }
     }
     // Pass through anything else we might have been given, to support extensions
     // This is kind of a hack but it's the best we can do to make extensions work
     $requestArray += $this->getRequest()->getValues();
     global $wgTitle, $wgRequest;
     $req = new DerivativeRequest($this->getRequest(), $requestArray, true);
     // Some functions depend on $wgTitle == $ep->mTitle
     // TODO: Make them not or check if they still do
     $wgTitle = $titleObj;
     $articleContext = new RequestContext();
     $articleContext->setRequest($req);
     $articleContext->setWikiPage($pageObj);
     $articleContext->setUser($this->getUser());
     /** @var $articleObject Article */
     $articleObject = Article::newFromWikiPage($pageObj, $articleContext);
     $ep = new EditPage($articleObject);
     $ep->setApiEditOverride(true);
     $ep->setContextTitle($titleObj);
     $ep->importFormData($req);
     $content = $ep->textbox1;
     // The following is needed to give the hook the full content of the
     // new revision rather than just the current section. (Bug 52077)
     if (!is_null($params['section']) && $contentHandler->supportsSections() && $titleObj->exists()) {
         // If sectiontitle is set, use it, otherwise use the summary as the section title (for
         // backwards compatibility with old forms/bots).
         if ($ep->sectiontitle !== '') {
             $sectionTitle = $ep->sectiontitle;
         } else {
             $sectionTitle = $ep->summary;
         }
         $contentObj = $contentHandler->unserializeContent($content, $contentFormat);
         $fullContentObj = $articleObject->replaceSectionContent($params['section'], $contentObj, $sectionTitle);
         if ($fullContentObj) {
             $content = $fullContentObj->serialize($contentFormat);
         } else {
             // This most likely means we have an edit conflict which means that the edit
             // wont succeed anyway.
             $this->dieUsageMsg('editconflict');
         }
     }
     // Run hooks
     // Handle APIEditBeforeSave parameters
     $r = array();
     if (!Hooks::run('APIEditBeforeSave', array($ep, $content, &$r))) {
         if (count($r)) {
             $r['result'] = 'Failure';
             $apiResult->addValue(null, $this->getModuleName(), $r);
             return;
         }
         $this->dieUsageMsg('hookaborted');
     }
     // Do the actual save
     $oldRevId = $articleObject->getRevIdFetched();
     $result = null;
     // Fake $wgRequest for some hooks inside EditPage
     // @todo FIXME: This interface SUCKS
     $oldRequest = $wgRequest;
     $wgRequest = $req;
     $status = $ep->attemptSave($result);
     $wgRequest = $oldRequest;
     switch ($status->value) {
         case EditPage::AS_HOOK_ERROR:
         case EditPage::AS_HOOK_ERROR_EXPECTED:
             if (isset($status->apiHookResult)) {
                 $r = $status->apiHookResult;
                 $r['result'] = 'Failure';
                 $apiResult->addValue(null, $this->getModuleName(), $r);
                 return;
             } else {
                 $this->dieUsageMsg('hookaborted');
             }
         case EditPage::AS_PARSE_ERROR:
             $this->dieUsage($status->getMessage(), 'parseerror');
         case EditPage::AS_IMAGE_REDIRECT_ANON:
             $this->dieUsageMsg('noimageredirect-anon');
         case EditPage::AS_IMAGE_REDIRECT_LOGGED:
             $this->dieUsageMsg('noimageredirect-logged');
         case EditPage::AS_SPAM_ERROR:
             $this->dieUsageMsg(array('spamdetected', $result['spam']));
         case EditPage::AS_BLOCKED_PAGE_FOR_USER:
             $this->dieUsage('You have been blocked from editing', 'blocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($user->getBlock())));
         case EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED:
         case EditPage::AS_CONTENT_TOO_BIG:
             $this->dieUsageMsg(array('contenttoobig', $this->getConfig()->get('MaxArticleSize')));
         case EditPage::AS_READ_ONLY_PAGE_ANON:
             $this->dieUsageMsg('noedit-anon');
         case EditPage::AS_READ_ONLY_PAGE_LOGGED:
             $this->dieUsageMsg('noedit');
         case EditPage::AS_READ_ONLY_PAGE:
             $this->dieReadOnly();
         case EditPage::AS_RATE_LIMITED:
             $this->dieUsageMsg('actionthrottledtext');
         case EditPage::AS_ARTICLE_WAS_DELETED:
             $this->dieUsageMsg('wasdeleted');
         case EditPage::AS_NO_CREATE_PERMISSION:
             $this->dieUsageMsg('nocreate-loggedin');
         case EditPage::AS_NO_CHANGE_CONTENT_MODEL:
             $this->dieUsageMsg('cantchangecontentmodel');
         case EditPage::AS_BLANK_ARTICLE:
             $this->dieUsageMsg('blankpage');
         case EditPage::AS_CONFLICT_DETECTED:
             $this->dieUsageMsg('editconflict');
         case EditPage::AS_TEXTBOX_EMPTY:
             $this->dieUsageMsg('emptynewsection');
         case EditPage::AS_CHANGE_TAG_ERROR:
             $this->dieStatus($status);
         case EditPage::AS_SUCCESS_NEW_ARTICLE:
             $r['new'] = true;
             // fall-through
         // fall-through
         case EditPage::AS_SUCCESS_UPDATE:
             $r['result'] = 'Success';
             $r['pageid'] = intval($titleObj->getArticleID());
             $r['title'] = $titleObj->getPrefixedText();
             $r['contentmodel'] = $articleObject->getContentModel();
             $newRevId = $articleObject->getLatest();
             if ($newRevId == $oldRevId) {
                 $r['nochange'] = true;
             } else {
                 $r['oldrevid'] = intval($oldRevId);
                 $r['newrevid'] = intval($newRevId);
                 $r['newtimestamp'] = wfTimestamp(TS_ISO_8601, $pageObj->getTimestamp());
             }
             break;
         case EditPage::AS_SUMMARY_NEEDED:
             // Shouldn't happen since we set wpIgnoreBlankSummary, but just in case
             $this->dieUsageMsg('summaryrequired');
         case EditPage::AS_END:
         default:
             // $status came from WikiPage::doEdit()
             $errors = $status->getErrorsArray();
             $this->dieUsageMsg($errors[0]);
             // TODO: Add new errors to message map
             break;
     }
     $apiResult->addValue(null, $this->getModuleName(), $r);
 }
コード例 #7
0
ファイル: ApiBase.php プロジェクト: xiebinyi/mediawiki
 /**
  * Throw a UsageException, which will (if uncaught) call the main module's
  * error handler and die with an error message including block info.
  *
  * @since 1.27
  * @param Block $block The block used to generate the UsageException
  * @throws UsageException always
  */
 public function dieBlocked(Block $block)
 {
     // Die using the appropriate message depending on block type
     if ($block->getType() == Block::TYPE_AUTO) {
         $this->dieUsage('Your IP address has been blocked automatically, because it was used by a blocked user', 'autoblocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($block)));
     } else {
         $this->dieUsage('You have been blocked from editing', 'blocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($block)));
     }
 }
コード例 #8
0
ファイル: ApiLogin.php プロジェクト: MediaWiki-stable/1.26.1
 /**
  * Executes the log-in attempt using the parameters passed. If
  * the log-in succeeds, it attaches a cookie to the session
  * and outputs the user id, username, and session token. If a
  * log-in fails, as the result of a bad password, a nonexistent
  * user, or any other reason, the host is cached with an expiry
  * and no log-in attempts will be accepted until that expiry
  * is reached. The expiry is $this->mLoginThrottle.
  */
 public function execute()
 {
     // If we're in a mode that breaks the same-origin policy, no tokens can
     // be obtained
     if ($this->lacksSameOriginSecurity()) {
         $this->getResult()->addValue(null, 'login', array('result' => 'Aborted', 'reason' => 'Cannot log in when the same-origin policy is not applied'));
         return;
     }
     $params = $this->extractRequestParams();
     $result = array();
     // Init session if necessary
     if (session_id() == '') {
         wfSetupSession();
     }
     $context = new DerivativeContext($this->getContext());
     $context->setRequest(new DerivativeRequest($this->getContext()->getRequest(), array('wpName' => $params['name'], 'wpPassword' => $params['password'], 'wpDomain' => $params['domain'], 'wpLoginToken' => $params['token'], 'wpRemember' => '')));
     $loginForm = new LoginForm();
     $loginForm->setContext($context);
     $authRes = $loginForm->authenticateUserData();
     switch ($authRes) {
         case LoginForm::SUCCESS:
             $user = $context->getUser();
             $this->getContext()->setUser($user);
             $user->setCookies($this->getRequest(), null, true);
             ApiQueryInfo::resetTokenCache();
             // Run hooks.
             // @todo FIXME: Split back and frontend from this hook.
             // @todo FIXME: This hook should be placed in the backend
             $injected_html = '';
             Hooks::run('UserLoginComplete', array(&$user, &$injected_html));
             $result['result'] = 'Success';
             $result['lguserid'] = intval($user->getId());
             $result['lgusername'] = $user->getName();
             $result['lgtoken'] = $user->getToken();
             $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix');
             $result['sessionid'] = session_id();
             break;
         case LoginForm::NEED_TOKEN:
             $result['result'] = 'NeedToken';
             $result['token'] = $loginForm->getLoginToken();
             $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix');
             $result['sessionid'] = session_id();
             break;
         case LoginForm::WRONG_TOKEN:
             $result['result'] = 'WrongToken';
             break;
         case LoginForm::NO_NAME:
             $result['result'] = 'NoName';
             break;
         case LoginForm::ILLEGAL:
             $result['result'] = 'Illegal';
             break;
         case LoginForm::WRONG_PLUGIN_PASS:
             $result['result'] = 'WrongPluginPass';
             break;
         case LoginForm::NOT_EXISTS:
             $result['result'] = 'NotExists';
             break;
             // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin:
             // The e-mailed temporary password should not be used for actual logins.
         // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin:
         // The e-mailed temporary password should not be used for actual logins.
         case LoginForm::RESET_PASS:
         case LoginForm::WRONG_PASS:
             $result['result'] = 'WrongPass';
             break;
         case LoginForm::EMPTY_PASS:
             $result['result'] = 'EmptyPass';
             break;
         case LoginForm::CREATE_BLOCKED:
             $result['result'] = 'CreateBlocked';
             $result['details'] = 'Your IP address is blocked from account creation';
             $block = $context->getUser()->getBlock();
             if ($block) {
                 $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block));
             }
             break;
         case LoginForm::THROTTLED:
             $result['result'] = 'Throttled';
             $throttle = $this->getConfig()->get('PasswordAttemptThrottle');
             $result['wait'] = intval($throttle['seconds']);
             break;
         case LoginForm::USER_BLOCKED:
             $result['result'] = 'Blocked';
             $block = User::newFromName($params['name'])->getBlock();
             if ($block) {
                 $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block));
             }
             break;
         case LoginForm::ABORTED:
             $result['result'] = 'Aborted';
             $result['reason'] = $loginForm->mAbortLoginErrorMsg;
             break;
         default:
             ApiBase::dieDebug(__METHOD__, "Unhandled case value: {$authRes}");
     }
     $this->getResult()->addValue(null, 'login', $result);
     LoggerFactory::getInstance('authmanager')->info('Login attempt', array('event' => 'login', 'successful' => $authRes === LoginForm::SUCCESS, 'status' => LoginForm::$statusCodes[$authRes]));
 }
コード例 #9
0
 public function execute()
 {
     $this->useTransactionalTimeLimit();
     $params = $this->extractRequestParams();
     $user = $this->getUser();
     if (!$user->isAllowed(RevisionDeleter::getRestriction($params['type']))) {
         $this->dieUsageMsg('badaccess-group0');
     }
     if ($user->isBlocked()) {
         $block = $user->getBlock();
         // Die using the appropriate message depending on block type
         if ($block->getType() == TYPE_AUTO) {
             $this->dieUsage('Your IP address has been blocked automatically, because it was used by a blocked user', 'autoblocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($block)));
         } else {
             $this->dieUsage('You have been blocked from editing', 'blocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($block)));
         }
     }
     if (!$params['ids']) {
         $this->dieUsage("At least one value is required for 'ids'", 'badparams');
     }
     $hide = $params['hide'] ?: array();
     $show = $params['show'] ?: array();
     if (array_intersect($hide, $show)) {
         $this->dieUsage("Mutually exclusive values for 'hide' and 'show'", 'badparams');
     } elseif (!$hide && !$show) {
         $this->dieUsage("At least one value is required for 'hide' or 'show'", 'badparams');
     }
     $bits = array('content' => RevisionDeleter::getRevdelConstant($params['type']), 'comment' => Revision::DELETED_COMMENT, 'user' => Revision::DELETED_USER);
     $bitfield = array();
     foreach ($bits as $key => $bit) {
         if (in_array($key, $hide)) {
             $bitfield[$bit] = 1;
         } elseif (in_array($key, $show)) {
             $bitfield[$bit] = 0;
         } else {
             $bitfield[$bit] = -1;
         }
     }
     if ($params['suppress'] === 'yes') {
         if (!$user->isAllowed('suppressrevision')) {
             $this->dieUsageMsg('badaccess-group0');
         }
         $bitfield[Revision::DELETED_RESTRICTED] = 1;
     } elseif ($params['suppress'] === 'no') {
         $bitfield[Revision::DELETED_RESTRICTED] = 0;
     } else {
         $bitfield[Revision::DELETED_RESTRICTED] = -1;
     }
     $targetObj = null;
     if ($params['target']) {
         $targetObj = Title::newFromText($params['target']);
     }
     $targetObj = RevisionDeleter::suggestTarget($params['type'], $targetObj, $params['ids']);
     if ($targetObj === null) {
         $this->dieUsage('A target title is required for this RevDel type', 'needtarget');
     }
     $list = RevisionDeleter::createList($params['type'], $this->getContext(), $targetObj, $params['ids']);
     $status = $list->setVisibility(array('value' => $bitfield, 'comment' => $params['reason'], 'perItemStatus' => true));
     $result = $this->getResult();
     $data = $this->extractStatusInfo($status);
     $data['target'] = $targetObj->getFullText();
     $data['items'] = array();
     foreach ($status->itemStatuses as $id => $s) {
         $data['items'][$id] = $this->extractStatusInfo($s);
         $data['items'][$id]['id'] = $id;
     }
     $list->reloadFromMaster();
     // @codingStandardsIgnoreStart Avoid function calls in a FOR loop test part
     for ($item = $list->reset(); $list->current(); $item = $list->next()) {
         $data['items'][$item->getId()] += $item->getApiData($this->getResult());
     }
     // @codingStandardsIgnoreEnd
     $data['items'] = array_values($data['items']);
     ApiResult::setIndexedTagName($data['items'], 'i');
     $result->addValue(null, $this->getModuleName(), $data);
 }
コード例 #10
0
ファイル: ApiCreateAccount.php プロジェクト: D66Ha/mediawiki
 public function execute()
 {
     // If we're in a mode that breaks the same-origin policy, no tokens can
     // be obtained
     if ($this->lacksSameOriginSecurity()) {
         $this->dieUsage('Cannot create account when the same-origin policy is not applied', 'aborted');
     }
     // $loginForm->addNewaccountInternal will throw exceptions
     // if wiki is read only (already handled by api), user is blocked or does not have rights.
     // Use userCan in order to hit GlobalBlock checks (according to Special:userlogin)
     $loginTitle = SpecialPage::getTitleFor('Userlogin');
     if (!$loginTitle->userCan('createaccount', $this->getUser())) {
         $this->dieUsage('You do not have the right to create a new account', 'permdenied-createaccount');
     }
     if ($this->getUser()->isBlockedFromCreateAccount()) {
         $this->dieUsage('You cannot create a new account because you are blocked', 'blocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($this->getUser()->getBlock())));
     }
     $params = $this->extractRequestParams();
     // Init session if necessary
     if (session_id() == '') {
         wfSetupSession();
     }
     if ($params['mailpassword'] && !$params['email']) {
         $this->dieUsageMsg('noemail');
     }
     if ($params['language'] && !Language::isSupportedLanguage($params['language'])) {
         $this->dieUsage('Invalid language parameter', 'langinvalid');
     }
     $context = new DerivativeContext($this->getContext());
     $context->setRequest(new DerivativeRequest($this->getContext()->getRequest(), array('type' => 'signup', 'uselang' => $params['language'], 'wpName' => $params['name'], 'wpPassword' => $params['password'], 'wpRetype' => $params['password'], 'wpDomain' => $params['domain'], 'wpEmail' => $params['email'], 'wpRealName' => $params['realname'], 'wpCreateaccountToken' => $params['token'], 'wpCreateaccount' => $params['mailpassword'] ? null : '1', 'wpCreateaccountMail' => $params['mailpassword'] ? '1' : null)));
     $loginForm = new LoginForm();
     $loginForm->setContext($context);
     Hooks::run('AddNewAccountApiForm', array($this, $loginForm));
     $loginForm->load();
     $status = $loginForm->addNewaccountInternal();
     $result = array();
     if ($status->isGood()) {
         // Success!
         $user = $status->getValue();
         if ($params['language']) {
             $user->setOption('language', $params['language']);
         }
         if ($params['mailpassword']) {
             // If mailpassword was set, disable the password and send an email.
             $user->setPassword(null);
             $status->merge($loginForm->mailPasswordInternal($user, false, 'createaccount-title', 'createaccount-text'));
         } elseif ($this->getConfig()->get('EmailAuthentication') && Sanitizer::validateEmail($user->getEmail())) {
             // Send out an email authentication message if needed
             $status->merge($user->sendConfirmationMail());
         }
         // Save settings (including confirmation token)
         $user->saveSettings();
         Hooks::run('AddNewAccount', array($user, $params['mailpassword']));
         if ($params['mailpassword']) {
             $logAction = 'byemail';
         } elseif ($this->getUser()->isLoggedIn()) {
             $logAction = 'create2';
         } else {
             $logAction = 'create';
         }
         $user->addNewUserLogEntry($logAction, (string) $params['reason']);
         // Add username, id, and token to result.
         $result['username'] = $user->getName();
         $result['userid'] = $user->getId();
         $result['token'] = $user->getToken();
     }
     $apiResult = $this->getResult();
     if ($status->hasMessage('sessionfailure') || $status->hasMessage('nocookiesfornew')) {
         // Token was incorrect, so add it to result, but don't throw an exception
         // since not having the correct token is part of the normal
         // flow of events.
         $result['token'] = LoginForm::getCreateaccountToken();
         $result['result'] = 'NeedToken';
     } elseif (!$status->isOK()) {
         // There was an error. Die now.
         $this->dieStatus($status);
     } elseif (!$status->isGood()) {
         // Status is not good, but OK. This means warnings.
         $result['result'] = 'Warning';
         // Add any warnings to the result
         $warnings = $status->getErrorsByType('warning');
         if ($warnings) {
             foreach ($warnings as &$warning) {
                 ApiResult::setIndexedTagName($warning['params'], 'param');
             }
             ApiResult::setIndexedTagName($warnings, 'warning');
             $result['warnings'] = $warnings;
         }
     } else {
         // Everything was fine.
         $result['result'] = 'Success';
     }
     // Give extensions a chance to modify the API result data
     Hooks::run('AddNewAccountApiResult', array($this, $loginForm, &$result));
     $apiResult->addValue(null, 'createaccount', $result);
 }
コード例 #11
0
 public function execute()
 {
     $params = $this->extractRequestParams();
     $activeUserDays = $this->getConfig()->get('ActiveUserDays');
     $db = $this->getDB();
     $prop = $params['prop'];
     if (!is_null($prop)) {
         $prop = array_flip($prop);
         $fld_blockinfo = isset($prop['blockinfo']);
         $fld_editcount = isset($prop['editcount']);
         $fld_groups = isset($prop['groups']);
         $fld_rights = isset($prop['rights']);
         $fld_registration = isset($prop['registration']);
         $fld_implicitgroups = isset($prop['implicitgroups']);
         $fld_centralids = isset($prop['centralids']);
     } else {
         $fld_blockinfo = $fld_editcount = $fld_groups = $fld_registration = $fld_rights = $fld_implicitgroups = $fld_centralids = false;
     }
     $limit = $params['limit'];
     $this->addTables('user');
     $dir = $params['dir'] == 'descending' ? 'older' : 'newer';
     $from = is_null($params['from']) ? null : $this->getCanonicalUserName($params['from']);
     $to = is_null($params['to']) ? null : $this->getCanonicalUserName($params['to']);
     # MySQL can't figure out that 'user_name' and 'qcc_title' are the same
     # despite the JOIN condition, so manually sort on the correct one.
     $userFieldToSort = $params['activeusers'] ? 'qcc_title' : 'user_name';
     # Some of these subtable joins are going to give us duplicate rows, so
     # calculate the maximum number of duplicates we might see.
     $maxDuplicateRows = 1;
     $this->addWhereRange($userFieldToSort, $dir, $from, $to);
     if (!is_null($params['prefix'])) {
         $this->addWhere($userFieldToSort . $db->buildLike($this->getCanonicalUserName($params['prefix']), $db->anyString()));
     }
     if (!is_null($params['rights']) && count($params['rights'])) {
         $groups = array();
         foreach ($params['rights'] as $r) {
             $groups = array_merge($groups, User::getGroupsWithPermission($r));
         }
         // no group with the given right(s) exists, no need for a query
         if (!count($groups)) {
             $this->getResult()->addIndexedTagName(array('query', $this->getModuleName()), '');
             return;
         }
         $groups = array_unique($groups);
         if (is_null($params['group'])) {
             $params['group'] = $groups;
         } else {
             $params['group'] = array_unique(array_merge($params['group'], $groups));
         }
     }
     if (!is_null($params['group']) && !is_null($params['excludegroup'])) {
         $this->dieUsage('group and excludegroup cannot be used together', 'group-excludegroup');
     }
     if (!is_null($params['group']) && count($params['group'])) {
         // Filter only users that belong to a given group. This might
         // produce as many rows-per-user as there are groups being checked.
         $this->addTables('user_groups', 'ug1');
         $this->addJoinConds(array('ug1' => array('INNER JOIN', array('ug1.ug_user=user_id', 'ug1.ug_group' => $params['group']))));
         $maxDuplicateRows *= count($params['group']);
     }
     if (!is_null($params['excludegroup']) && count($params['excludegroup'])) {
         // Filter only users don't belong to a given group. This can only
         // produce one row-per-user, because we only keep on "no match".
         $this->addTables('user_groups', 'ug1');
         if (count($params['excludegroup']) == 1) {
             $exclude = array('ug1.ug_group' => $params['excludegroup'][0]);
         } else {
             $exclude = array($db->makeList(array('ug1.ug_group' => $params['excludegroup']), LIST_OR));
         }
         $this->addJoinConds(array('ug1' => array('LEFT OUTER JOIN', array_merge(array('ug1.ug_user=user_id'), $exclude))));
         $this->addWhere('ug1.ug_user IS NULL');
     }
     if ($params['witheditsonly']) {
         $this->addWhere('user_editcount > 0');
     }
     $this->showHiddenUsersAddBlockInfo($fld_blockinfo);
     if ($fld_groups || $fld_rights) {
         $this->addFields(array('groups' => $db->buildGroupConcatField('|', 'user_groups', 'ug_group', 'ug_user=user_id')));
     }
     if ($params['activeusers']) {
         $activeUserSeconds = $activeUserDays * 86400;
         // Filter query to only include users in the active users cache.
         // There shouldn't be any duplicate rows in querycachetwo here.
         $this->addTables('querycachetwo');
         $this->addJoinConds(array('querycachetwo' => array('INNER JOIN', array('qcc_type' => 'activeusers', 'qcc_namespace' => NS_USER, 'qcc_title=user_name'))));
         // Actually count the actions using a subquery (bug 64505 and bug 64507)
         $timestamp = $db->timestamp(wfTimestamp(TS_UNIX) - $activeUserSeconds);
         $this->addFields(array('recentactions' => '(' . $db->selectSQLText('recentchanges', 'COUNT(*)', array('rc_user_text = user_name', 'rc_type != ' . $db->addQuotes(RC_EXTERNAL), 'rc_log_type IS NULL OR rc_log_type != ' . $db->addQuotes('newusers'), 'rc_timestamp >= ' . $db->addQuotes($timestamp))) . ')'));
     }
     $sqlLimit = $limit + $maxDuplicateRows;
     $this->addOption('LIMIT', $sqlLimit);
     $this->addFields(array('user_name', 'user_id'));
     $this->addFieldsIf('user_editcount', $fld_editcount);
     $this->addFieldsIf('user_registration', $fld_registration);
     $res = $this->select(__METHOD__);
     $count = 0;
     $countDuplicates = 0;
     $lastUser = false;
     $result = $this->getResult();
     foreach ($res as $row) {
         $count++;
         if ($lastUser === $row->user_name) {
             // Duplicate row due to one of the needed subtable joins.
             // Ignore it, but count the number of them to sanely handle
             // miscalculation of $maxDuplicateRows.
             $countDuplicates++;
             if ($countDuplicates == $maxDuplicateRows) {
                 ApiBase::dieDebug(__METHOD__, 'Saw more duplicate rows than expected');
             }
             continue;
         }
         $countDuplicates = 0;
         $lastUser = $row->user_name;
         if ($count > $limit) {
             // We've reached the one extra which shows that there are
             // additional pages to be had. Stop here...
             $this->setContinueEnumParameter('from', $row->user_name);
             break;
         }
         if ($count == $sqlLimit) {
             // Should never hit this (either the $countDuplicates check or
             // the $count > $limit check should hit first), but check it
             // anyway just in case.
             ApiBase::dieDebug(__METHOD__, 'Saw more duplicate rows than expected');
         }
         if ($params['activeusers'] && $row->recentactions === 0) {
             // activeusers cache was out of date
             continue;
         }
         $data = array('userid' => (int) $row->user_id, 'name' => $row->user_name);
         if ($fld_centralids) {
             $data += ApiQueryUserInfo::getCentralUserInfo($this->getConfig(), User::newFromId($row->user_id), $params['attachedwiki']);
         }
         if ($fld_blockinfo && !is_null($row->ipb_by_text)) {
             $data['blockid'] = (int) $row->ipb_id;
             $data['blockedby'] = $row->ipb_by_text;
             $data['blockedbyid'] = (int) $row->ipb_by;
             $data['blockedtimestamp'] = wfTimestamp(TS_ISO_8601, $row->ipb_timestamp);
             $data['blockreason'] = $row->ipb_reason;
             $data['blockexpiry'] = $row->ipb_expiry;
         }
         if ($row->ipb_deleted) {
             $data['hidden'] = true;
         }
         if ($fld_editcount) {
             $data['editcount'] = intval($row->user_editcount);
         }
         if ($params['activeusers']) {
             $data['recentactions'] = intval($row->recentactions);
             // @todo 'recenteditcount' is set for BC, remove in 1.25
             $data['recenteditcount'] = $data['recentactions'];
         }
         if ($fld_registration) {
             $data['registration'] = $row->user_registration ? wfTimestamp(TS_ISO_8601, $row->user_registration) : '';
         }
         if ($fld_implicitgroups || $fld_groups || $fld_rights) {
             $implicitGroups = User::newFromId($row->user_id)->getAutomaticGroups();
             if (isset($row->groups) && $row->groups !== '') {
                 $groups = array_merge($implicitGroups, explode('|', $row->groups));
             } else {
                 $groups = $implicitGroups;
             }
             if ($fld_groups) {
                 $data['groups'] = $groups;
                 ApiResult::setIndexedTagName($data['groups'], 'g');
                 ApiResult::setArrayType($data['groups'], 'array');
             }
             if ($fld_implicitgroups) {
                 $data['implicitgroups'] = $implicitGroups;
                 ApiResult::setIndexedTagName($data['implicitgroups'], 'g');
                 ApiResult::setArrayType($data['implicitgroups'], 'array');
             }
             if ($fld_rights) {
                 $data['rights'] = User::getGroupPermissions($groups);
                 ApiResult::setIndexedTagName($data['rights'], 'r');
                 ApiResult::setArrayType($data['rights'], 'array');
             }
         }
         $fit = $result->addValue(array('query', $this->getModuleName()), null, $data);
         if (!$fit) {
             $this->setContinueEnumParameter('from', $data['name']);
             break;
         }
     }
     $result->addIndexedTagName(array('query', $this->getModuleName()), 'u');
 }
コード例 #12
0
ファイル: ApiLogin.php プロジェクト: Gomyul/mediawiki
 /**
  * Executes the log-in attempt using the parameters passed. If
  * the log-in succeeds, it attaches a cookie to the session
  * and outputs the user id, username, and session token. If a
  * log-in fails, as the result of a bad password, a nonexistent
  * user, or any other reason, the host is cached with an expiry
  * and no log-in attempts will be accepted until that expiry
  * is reached. The expiry is $this->mLoginThrottle.
  */
 public function execute()
 {
     // If we're in a mode that breaks the same-origin policy, no tokens can
     // be obtained
     if ($this->lacksSameOriginSecurity()) {
         $this->getResult()->addValue(null, 'login', array('result' => 'Aborted', 'reason' => 'Cannot log in when the same-origin policy is not applied'));
         return;
     }
     $params = $this->extractRequestParams();
     $result = array();
     // Make sure session is persisted
     $session = MediaWiki\Session\SessionManager::getGlobalSession();
     $session->persist();
     // Make sure it's possible to log in
     if (!$session->canSetUser()) {
         $this->getResult()->addValue(null, 'login', array('result' => 'Aborted', 'reason' => 'Cannot log in when using ' . $session->getProvider()->describe(Language::factory('en'))));
         return;
     }
     $authRes = false;
     $context = new DerivativeContext($this->getContext());
     $loginType = 'N/A';
     // Check login token
     $token = LoginForm::getLoginToken();
     if (!$token) {
         LoginForm::setLoginToken();
         $authRes = LoginForm::NEED_TOKEN;
     } elseif (!$params['token']) {
         $authRes = LoginForm::NEED_TOKEN;
     } elseif ($token !== $params['token']) {
         $authRes = LoginForm::WRONG_TOKEN;
     }
     // Try bot passwords
     if ($authRes === false && $this->getConfig()->get('EnableBotPasswords') && strpos($params['name'], BotPassword::getSeparator()) !== false) {
         $status = BotPassword::login($params['name'], $params['password'], $this->getRequest());
         if ($status->isOk()) {
             $session = $status->getValue();
             $authRes = LoginForm::SUCCESS;
             $loginType = 'BotPassword';
         } else {
             LoggerFactory::getInstance('authmanager')->info('BotPassword login failed: ' . $status->getWikiText());
         }
     }
     // Normal login
     if ($authRes === false) {
         $context->setRequest(new DerivativeRequest($this->getContext()->getRequest(), array('wpName' => $params['name'], 'wpPassword' => $params['password'], 'wpDomain' => $params['domain'], 'wpLoginToken' => $params['token'], 'wpRemember' => '')));
         $loginForm = new LoginForm();
         $loginForm->setContext($context);
         $authRes = $loginForm->authenticateUserData();
         $loginType = 'LoginForm';
     }
     switch ($authRes) {
         case LoginForm::SUCCESS:
             $user = $context->getUser();
             $this->getContext()->setUser($user);
             $user->setCookies($this->getRequest(), null, true);
             ApiQueryInfo::resetTokenCache();
             // Run hooks.
             // @todo FIXME: Split back and frontend from this hook.
             // @todo FIXME: This hook should be placed in the backend
             $injected_html = '';
             Hooks::run('UserLoginComplete', array(&$user, &$injected_html));
             $result['result'] = 'Success';
             $result['lguserid'] = intval($user->getId());
             $result['lgusername'] = $user->getName();
             // @todo: These are deprecated, and should be removed at some
             // point (1.28 at the earliest, and see T121527). They were ok
             // when the core cookie-based login was the only thing, but
             // CentralAuth broke that a while back and
             // SessionManager/AuthManager are *really* going to break it.
             $result['lgtoken'] = $user->getToken();
             $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix');
             $result['sessionid'] = $session->getId();
             break;
         case LoginForm::NEED_TOKEN:
             $result['result'] = 'NeedToken';
             $result['token'] = LoginForm::getLoginToken();
             // @todo: See above about deprecation
             $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix');
             $result['sessionid'] = $session->getId();
             break;
         case LoginForm::WRONG_TOKEN:
             $result['result'] = 'WrongToken';
             break;
         case LoginForm::NO_NAME:
             $result['result'] = 'NoName';
             break;
         case LoginForm::ILLEGAL:
             $result['result'] = 'Illegal';
             break;
         case LoginForm::WRONG_PLUGIN_PASS:
             $result['result'] = 'WrongPluginPass';
             break;
         case LoginForm::NOT_EXISTS:
             $result['result'] = 'NotExists';
             break;
             // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin:
             // The e-mailed temporary password should not be used for actual logins.
         // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin:
         // The e-mailed temporary password should not be used for actual logins.
         case LoginForm::RESET_PASS:
         case LoginForm::WRONG_PASS:
             $result['result'] = 'WrongPass';
             break;
         case LoginForm::EMPTY_PASS:
             $result['result'] = 'EmptyPass';
             break;
         case LoginForm::CREATE_BLOCKED:
             $result['result'] = 'CreateBlocked';
             $result['details'] = 'Your IP address is blocked from account creation';
             $block = $context->getUser()->getBlock();
             if ($block) {
                 $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block));
             }
             break;
         case LoginForm::THROTTLED:
             $result['result'] = 'Throttled';
             $throttle = $this->getConfig()->get('PasswordAttemptThrottle');
             $result['wait'] = intval($throttle['seconds']);
             break;
         case LoginForm::USER_BLOCKED:
             $result['result'] = 'Blocked';
             $block = User::newFromName($params['name'])->getBlock();
             if ($block) {
                 $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block));
             }
             break;
         case LoginForm::ABORTED:
             $result['result'] = 'Aborted';
             $result['reason'] = $loginForm->mAbortLoginErrorMsg;
             break;
         default:
             ApiBase::dieDebug(__METHOD__, "Unhandled case value: {$authRes}");
     }
     $this->getResult()->addValue(null, 'login', $result);
     LoggerFactory::getInstance('authmanager')->info('Login attempt', array('event' => 'login', 'successful' => $authRes === LoginForm::SUCCESS, 'loginType' => $loginType, 'status' => LoginForm::$statusCodes[$authRes]));
 }
コード例 #13
0
ファイル: ApiLogin.php プロジェクト: claudinec/galan-wiki
 /**
  * Executes the log-in attempt using the parameters passed. If
  * the log-in succeeds, it attaches a cookie to the session
  * and outputs the user id, username, and session token. If a
  * log-in fails, as the result of a bad password, a nonexistent
  * user, or any other reason, the host is cached with an expiry
  * and no log-in attempts will be accepted until that expiry
  * is reached. The expiry is $this->mLoginThrottle.
  */
 public function execute()
 {
     // If we're in a mode that breaks the same-origin policy, no tokens can
     // be obtained
     if ($this->lacksSameOriginSecurity()) {
         $this->getResult()->addValue(null, 'login', ['result' => 'Aborted', 'reason' => 'Cannot log in when the same-origin policy is not applied']);
         return;
     }
     $params = $this->extractRequestParams();
     $result = [];
     // Make sure session is persisted
     $session = MediaWiki\Session\SessionManager::getGlobalSession();
     $session->persist();
     // Make sure it's possible to log in
     if (!$session->canSetUser()) {
         $this->getResult()->addValue(null, 'login', ['result' => 'Aborted', 'reason' => 'Cannot log in when using ' . $session->getProvider()->describe(Language::factory('en'))]);
         return;
     }
     $authRes = false;
     $context = new DerivativeContext($this->getContext());
     $loginType = 'N/A';
     // Check login token
     $token = $session->getToken('', 'login');
     if ($token->wasNew() || !$params['token']) {
         $authRes = 'NeedToken';
     } elseif (!$token->match($params['token'])) {
         $authRes = 'WrongToken';
     }
     // Try bot passwords
     if ($authRes === false && $this->getConfig()->get('EnableBotPasswords') && strpos($params['name'], BotPassword::getSeparator()) !== false) {
         $status = BotPassword::login($params['name'], $params['password'], $this->getRequest());
         if ($status->isOK()) {
             $session = $status->getValue();
             $authRes = 'Success';
             $loginType = 'BotPassword';
         } else {
             $authRes = 'Failed';
             $message = $status->getMessage();
             LoggerFactory::getInstance('authmanager')->info('BotPassword login failed: ' . $status->getWikiText(false, false, 'en'));
         }
     }
     if ($authRes === false) {
         if ($this->getConfig()->get('DisableAuthManager')) {
             // Non-AuthManager login
             $context->setRequest(new DerivativeRequest($this->getContext()->getRequest(), ['wpName' => $params['name'], 'wpPassword' => $params['password'], 'wpDomain' => $params['domain'], 'wpLoginToken' => $params['token'], 'wpRemember' => '']));
             $loginForm = new LoginForm();
             $loginForm->setContext($context);
             $authRes = $loginForm->authenticateUserData();
             $loginType = 'LoginForm';
             switch ($authRes) {
                 case LoginForm::SUCCESS:
                     $authRes = 'Success';
                     break;
                 case LoginForm::NEED_TOKEN:
                     $authRes = 'NeedToken';
                     break;
             }
         } else {
             // Simplified AuthManager login, for backwards compatibility
             $manager = AuthManager::singleton();
             $reqs = AuthenticationRequest::loadRequestsFromSubmission($manager->getAuthenticationRequests(AuthManager::ACTION_LOGIN, $this->getUser()), ['username' => $params['name'], 'password' => $params['password'], 'domain' => $params['domain'], 'rememberMe' => true]);
             $res = AuthManager::singleton()->beginAuthentication($reqs, 'null:');
             switch ($res->status) {
                 case AuthenticationResponse::PASS:
                     if ($this->getConfig()->get('EnableBotPasswords')) {
                         $warn = 'Main-account login via action=login is deprecated and may stop working ' . 'without warning.';
                         $warn .= ' To continue login with action=login, see [[Special:BotPasswords]].';
                         $warn .= ' To safely continue using main-account login, see action=clientlogin.';
                     } else {
                         $warn = 'Login via action=login is deprecated and may stop working without warning.';
                         $warn .= ' To safely log in, see action=clientlogin.';
                     }
                     $this->setWarning($warn);
                     $authRes = 'Success';
                     $loginType = 'AuthManager';
                     break;
                 case AuthenticationResponse::FAIL:
                     // Hope it's not a PreAuthenticationProvider that failed...
                     $authRes = 'Failed';
                     $message = $res->message;
                     \MediaWiki\Logger\LoggerFactory::getInstance('authentication')->info(__METHOD__ . ': Authentication failed: ' . $message->plain());
                     break;
                 default:
                     $authRes = 'Aborted';
                     break;
             }
         }
     }
     $result['result'] = $authRes;
     switch ($authRes) {
         case 'Success':
             if ($this->getConfig()->get('DisableAuthManager')) {
                 $user = $context->getUser();
                 $this->getContext()->setUser($user);
                 $user->setCookies($this->getRequest(), null, true);
             } else {
                 $user = $session->getUser();
             }
             ApiQueryInfo::resetTokenCache();
             // Deprecated hook
             $injected_html = '';
             Hooks::run('UserLoginComplete', [&$user, &$injected_html]);
             $result['lguserid'] = intval($user->getId());
             $result['lgusername'] = $user->getName();
             // @todo: These are deprecated, and should be removed at some
             // point (1.28 at the earliest, and see T121527). They were ok
             // when the core cookie-based login was the only thing, but
             // CentralAuth broke that a while back and
             // SessionManager/AuthManager *really* break it.
             $result['lgtoken'] = $user->getToken();
             $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix');
             $result['sessionid'] = $session->getId();
             break;
         case 'NeedToken':
             $result['token'] = $token->toString();
             $this->setWarning('Fetching a token via action=login is deprecated. ' . 'Use action=query&meta=tokens&type=login instead.');
             $this->logFeatureUsage('action=login&!lgtoken');
             // @todo: See above about deprecation
             $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix');
             $result['sessionid'] = $session->getId();
             break;
         case 'WrongToken':
             break;
         case 'Failed':
             $result['reason'] = $message->useDatabase('false')->inLanguage('en')->text();
             break;
         case 'Aborted':
             $result['reason'] = 'Authentication requires user interaction, ' . 'which is not supported by action=login.';
             if ($this->getConfig()->get('EnableBotPasswords')) {
                 $result['reason'] .= ' To be able to login with action=login, see [[Special:BotPasswords]].';
                 $result['reason'] .= ' To continue using main-account login, see action=clientlogin.';
             } else {
                 $result['reason'] .= ' To log in, see action=clientlogin.';
             }
             break;
             // Results from LoginForm for when $wgDisableAuthManager is true
         // Results from LoginForm for when $wgDisableAuthManager is true
         case LoginForm::WRONG_TOKEN:
             $result['result'] = 'WrongToken';
             break;
         case LoginForm::NO_NAME:
             $result['result'] = 'NoName';
             break;
         case LoginForm::ILLEGAL:
             $result['result'] = 'Illegal';
             break;
         case LoginForm::WRONG_PLUGIN_PASS:
             $result['result'] = 'WrongPluginPass';
             break;
         case LoginForm::NOT_EXISTS:
             $result['result'] = 'NotExists';
             break;
             // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin:
             // The e-mailed temporary password should not be used for actual logins.
         // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin:
         // The e-mailed temporary password should not be used for actual logins.
         case LoginForm::RESET_PASS:
         case LoginForm::WRONG_PASS:
             $result['result'] = 'WrongPass';
             break;
         case LoginForm::EMPTY_PASS:
             $result['result'] = 'EmptyPass';
             break;
         case LoginForm::CREATE_BLOCKED:
             $result['result'] = 'CreateBlocked';
             $result['details'] = 'Your IP address is blocked from account creation';
             $block = $context->getUser()->getBlock();
             if ($block) {
                 $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block));
             }
             break;
         case LoginForm::THROTTLED:
             $result['result'] = 'Throttled';
             $result['wait'] = intval($loginForm->mThrottleWait);
             break;
         case LoginForm::USER_BLOCKED:
             $result['result'] = 'Blocked';
             $block = User::newFromName($params['name'])->getBlock();
             if ($block) {
                 $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block));
             }
             break;
         case LoginForm::ABORTED:
             $result['result'] = 'Aborted';
             $result['reason'] = $loginForm->mAbortLoginErrorMsg;
             break;
         default:
             ApiBase::dieDebug(__METHOD__, "Unhandled case value: {$authRes}");
     }
     $this->getResult()->addValue(null, 'login', $result);
     if ($loginType === 'LoginForm' && isset(LoginForm::$statusCodes[$authRes])) {
         $authRes = LoginForm::$statusCodes[$authRes];
     }
     LoggerFactory::getInstance('authmanager')->info('Login attempt', ['event' => 'login', 'successful' => $authRes === 'Success', 'loginType' => $loginType, 'status' => $authRes]);
 }