/**
  * Check that we can perform the rename
  *
  * @param User $oldUser
  * @param User $newUser
  *
  * @return Status
  */
 public function validate(User $oldUser, User $newUser)
 {
     $status = new Status();
     if (!User::isCreatableName($newUser->getName())) {
         $status->fatal('centralauth-rename-badusername');
     }
     $caOldUser = CentralAuthUser::getInstance($oldUser);
     if (!$caOldUser->exists()) {
         $status->fatal('centralauth-rename-doesnotexist');
     }
     $caNewUser = CentralAuthUser::getInstance($newUser);
     if ($caNewUser->exists()) {
         $status->fatal('centralauth-rename-alreadyexists');
     }
     $unattached = $caNewUser->listUnattached();
     if ($unattached) {
         $status->fatal('centralauth-rename-unattached-intheway');
     }
     // Check we're not currently renaming the user
     $renameState = $caOldUser->renameInProgress();
     if ($renameState) {
         $status->fatal('centralauth-rename-alreadyinprogress', $renameState[1]);
     }
     return $status;
 }
Example #2
0
 /**
  * Hook function for EditFilterMergedContent
  *
  * @param IContextSource $context
  * @param Content        $content
  * @param Status         $status
  * @param string         $summary
  * @param User           $user
  * @param bool           $minoredit
  *
  * @return bool
  */
 static function filterMergedContent(IContextSource $context, Content $content, Status $status, $summary, User $user, $minoredit)
 {
     $title = $context->getTitle();
     if (isset($title->spamBlackListFiltered) && $title->spamBlackListFiltered) {
         // already filtered
         return true;
     }
     // get the link from the not-yet-saved page content.
     // no need to generate html to get external links
     $pout = $content->getParserOutput($title, null, null, false);
     $links = array_keys($pout->getExternalLinks());
     // HACK: treat the edit summary as a link
     if ($summary !== '') {
         $links[] = $summary;
     }
     $spamObj = BaseBlacklist::getInstance('spam');
     $matches = $spamObj->filter($links, $title);
     if ($matches !== false) {
         $status->fatal('spamprotectiontext');
         foreach ($matches as $match) {
             $status->fatal('spamprotectionmatch', $match);
         }
     }
     // Always return true, EditPage will look at $status->isOk().
     return true;
 }
 /**
  * MovePageCheckPermissions hook (1.25+)
  *
  * @param Title $oldTitle
  * @param Title $newTitle
  * @param User $user
  * @param $reason
  * @param Status $status
  * @return bool
  */
 public static function onMovePageCheckPermissions(Title $oldTitle, Title $newTitle, User $user, $reason, Status $status)
 {
     $titleBlacklist = TitleBlacklist::singleton();
     $blacklisted = $titleBlacklist->userCannot($newTitle, $user, 'move');
     if (!$blacklisted) {
         $blacklisted = $titleBlacklist->userCannot($oldTitle, $user, 'edit');
     }
     if ($blacklisted instanceof TitleBlacklistEntry) {
         $errmsg = $blacklisted->getErrorMessage('move');
         ApiBase::$messageMap[$errmsg] = array('code' => $errmsg, 'info' => 'TitleBlacklist prevents this new title from being created or old title from being edited');
         $status->fatal($errmsg, $blacklisted->getRaw(), $oldTitle->getFullText(), $newTitle->getFullText());
         return false;
     }
     return true;
 }
 /**
  * Send out the message
  *
  * @param $data Array
  * @return Status
  */
 protected function submit(array $data)
 {
     $spamlist = $this->getSpamlist($data['spamlist']);
     // Prep the HTML comment message
     $data['comment'] = array($this->getUser()->getName(), wfWikiID(), $spamlist->getFullURL('', false, PROTO_CANONICAL));
     // Log it.
     $this->logToWiki($spamlist, $data['subject']);
     // Insert it into the job queue.
     $pages = MassMessage::getParserFunctionTargets($spamlist, $this->getContext());
     if (!is_array($pages)) {
         $this->status->fatal($pages);
         return $this->status;
     }
     $params = array('data' => $data, 'pages' => $pages);
     $job = new MassMessageSubmitJob($spamlist, $params);
     JobQueueGroup::singleton()->push($job);
     $this->count = count($pages);
     return $this->status;
 }
Example #5
0
 /**
  * Log an unexpected exception for this backend.
  * This also sets the Status object to have a fatal error.
  *
  * @param Status|null $status
  * @param string $func
  * @param array $params
  * @param string $err Error string
  * @param int $code HTTP status
  * @param string $desc HTTP status description
  */
 public function onError($status, $func, array $params, $err = '', $code = 0, $desc = '')
 {
     if ($status instanceof Status) {
         $status->fatal('backend-fail-internal', $this->name);
     }
     if ($code == 401) {
         // possibly a stale token
         $this->srvCache->delete($this->getCredsCacheKey($this->swiftUser));
     }
     wfDebugLog('SwiftBackend', "HTTP {$code} ({$desc}) in '{$func}' (given '" . FormatJson::encode($params) . "')" . ($err ? ": {$err}" : ""));
 }
Example #6
0
 /**
  * @see SwiftFileBackend::doExecuteOpHandlesInternal()
  */
 protected function _getResponseDelete(CF_Async_Op $cfOp, Status $status, array $params)
 {
     try {
         $cfOp->getLastResponse();
     } catch (NoSuchContainerException $e) {
         $status->fatal('backend-fail-delete', $params['src']);
     } catch (NoSuchObjectException $e) {
         if (empty($params['ignoreMissingSource'])) {
             $status->fatal('backend-fail-delete', $params['src']);
         }
     }
 }
Example #7
0
 /**
  * Actually attempt the history move
  *
  * @todo if all versions of page A are moved to B and then a user
  * tries to do a reverse-merge via the "unmerge" log link, then page
  * A will still be a redirect (as it was after the original merge),
  * though it will have the old revisions back from before (as expected).
  * The user may have to "undo" the redirect manually to finish the "unmerge".
  * Maybe this should delete redirects at the source page of merges?
  *
  * @param User $user
  * @param string $reason
  * @return Status status of the history merge
  */
 public function merge(User $user, $reason = '')
 {
     $status = new Status();
     // Check validity and permissions required for merge
     $validCheck = $this->isValidMerge();
     // Check this first to check for null pages
     if (!$validCheck->isOK()) {
         return $validCheck;
     }
     $permCheck = $this->checkPermissions($user, $reason);
     if (!$permCheck->isOK()) {
         return $permCheck;
     }
     $this->dbw->update('revision', array('rev_page' => $this->dest->getArticleID()), array('rev_page' => $this->source->getArticleID(), $this->timeWhere), __METHOD__);
     // Check if this did anything
     $this->revisionsMerged = $this->dbw->affectedRows();
     if ($this->revisionsMerged < 1) {
         $status->fatal('mergehistory-fail-no-change');
         return $status;
     }
     // Make the source page a redirect if no revisions are left
     $haveRevisions = $this->dbw->selectField('revision', 'rev_timestamp', array('rev_page' => $this->source->getArticleID()), __METHOD__, array('FOR UPDATE'));
     if (!$haveRevisions) {
         if ($reason) {
             $reason = wfMessage('mergehistory-comment', $this->source->getPrefixedText(), $this->dest->getPrefixedText(), $reason)->inContentLanguage()->text();
         } else {
             $reason = wfMessage('mergehistory-autocomment', $this->source->getPrefixedText(), $this->dest->getPrefixedText())->inContentLanguage()->text();
         }
         $contentHandler = ContentHandler::getForTitle($this->source);
         $redirectContent = $contentHandler->makeRedirectContent($this->dest, wfMessage('mergehistory-redirect-text')->inContentLanguage()->plain());
         if ($redirectContent) {
             $redirectPage = WikiPage::factory($this->source);
             $redirectRevision = new Revision(array('title' => $this->source, 'page' => $this->source->getArticleID(), 'comment' => $reason, 'content' => $redirectContent));
             $redirectRevision->insertOn($this->dbw);
             $redirectPage->updateRevisionOn($this->dbw, $redirectRevision);
             // Now, we record the link from the redirect to the new title.
             // It should have no other outgoing links...
             $this->dbw->delete('pagelinks', array('pl_from' => $this->dest->getArticleID()), __METHOD__);
             $this->dbw->insert('pagelinks', array('pl_from' => $this->dest->getArticleID(), 'pl_from_namespace' => $this->dest->getNamespace(), 'pl_namespace' => $this->dest->getNamespace(), 'pl_title' => $this->dest->getDBkey()), __METHOD__);
         } else {
             // Warning if we couldn't create the redirect
             $status->warning('mergehistory-warning-redirect-not-created');
         }
     } else {
         $this->source->invalidateCache();
         // update histories
     }
     $this->dest->invalidateCache();
     // update histories
     // Update our logs
     $logEntry = new ManualLogEntry('merge', 'merge');
     $logEntry->setPerformer($user);
     $logEntry->setComment($reason);
     $logEntry->setTarget($this->source);
     $logEntry->setParameters(array('4::dest' => $this->dest->getPrefixedText(), '5::mergepoint' => $this->timestampLimit->getTimestamp(TS_MW)));
     $logId = $logEntry->insert();
     $logEntry->publish($logId);
     Hooks::run('ArticleMergeComplete', array($this->source, $this->dest));
     return $status;
 }
 /**
  * @covers Status::hasMessage
  */
 public function testHasMessage()
 {
     $status = new Status();
     $status->fatal('bad');
     $status->fatal(wfMessage('bad-msg'));
     $this->assertTrue($status->hasMessage('bad'));
     $this->assertTrue($status->hasMessage('bad-msg'));
     $this->assertTrue($status->hasMessage(wfMessage('bad-msg')));
     $this->assertFalse($status->hasMessage('good'));
 }
Example #9
0
 /**
  * Run hooks that can filter edits just before they get saved.
  *
  * @param Content $content The Content to filter.
  * @param Status $status For reporting the outcome to the caller
  * @param User $user The user performing the edit
  *
  * @return bool
  */
 protected function runPostMergeFilters(Content $content, Status $status, User $user)
 {
     // Run old style post-section-merge edit filter
     if (!ContentHandler::runLegacyHooks('EditFilterMerged', array($this, $content, &$this->hookError, $this->summary))) {
         # Error messages etc. could be handled within the hook...
         $status->fatal('hookaborted');
         $status->value = self::AS_HOOK_ERROR;
         return false;
     } elseif ($this->hookError != '') {
         # ...or the hook could be expecting us to produce an error
         $status->fatal('hookaborted');
         $status->value = self::AS_HOOK_ERROR_EXPECTED;
         return false;
     }
     // Run new style post-section-merge edit filter
     if (!wfRunHooks('EditFilterMergedContent', array($this->mArticle->getContext(), $content, $status, $this->summary, $user, $this->minoredit))) {
         # Error messages etc. could be handled within the hook...
         // XXX: $status->value may already be something informative...
         $this->hookError = $status->getWikiText();
         $status->fatal('hookaborted');
         $status->value = self::AS_HOOK_ERROR;
         return false;
     } elseif (!$status->isOK()) {
         # ...or the hook could be expecting us to produce an error
         // FIXME this sucks, we should just use the Status object throughout
         $this->hookError = $status->getWikiText();
         $status->fatal('hookaborted');
         $status->value = self::AS_HOOK_ERROR_EXPECTED;
         return false;
     }
     return true;
 }
 public function onSubmit(array $data)
 {
     global $wgContLang;
     if ($data['pagetitle'] === '') {
         // Initial form view of special page, pass
         return false;
     }
     // At this point, it has to be a POST request. This is enforced by HTMLForm,
     // but lets be safe verify that.
     if (!$this->getRequest()->wasPosted()) {
         throw new RuntimeException("Form submission was not POSTed");
     }
     $this->title = Title::newFromText($data['pagetitle']);
     $titleWithNewContentModel = clone $this->title;
     $titleWithNewContentModel->setContentModel($data['model']);
     $user = $this->getUser();
     // Check permissions and make sure the user has permission to:
     $errors = wfMergeErrorArrays($this->title->getUserPermissionsErrors('editcontentmodel', $user), $this->title->getUserPermissionsErrors('edit', $user), $titleWithNewContentModel->getUserPermissionsErrors('editcontentmodel', $user), $titleWithNewContentModel->getUserPermissionsErrors('edit', $user));
     if ($errors) {
         $out = $this->getOutput();
         $wikitext = $out->formatPermissionsErrorMessage($errors);
         // Hack to get our wikitext parsed
         return Status::newFatal(new RawMessage('$1', [$wikitext]));
     }
     $page = WikiPage::factory($this->title);
     if ($this->oldRevision === null) {
         $this->oldRevision = $page->getRevision() ?: false;
     }
     $oldModel = $this->title->getContentModel();
     if ($this->oldRevision) {
         $oldContent = $this->oldRevision->getContent();
         try {
             $newContent = ContentHandler::makeContent($oldContent->getNativeData(), $this->title, $data['model']);
         } catch (MWException $e) {
             return Status::newFatal($this->msg('changecontentmodel-cannot-convert')->params($this->title->getPrefixedText(), ContentHandler::getLocalizedName($data['model'])));
         }
     } else {
         // Page doesn't exist, create an empty content object
         $newContent = ContentHandler::getForModelID($data['model'])->makeEmptyContent();
     }
     // All other checks have passed, let's check rate limits
     if ($user->pingLimiter('editcontentmodel')) {
         throw new ThrottledError();
     }
     $flags = $this->oldRevision ? EDIT_UPDATE : EDIT_NEW;
     $flags |= EDIT_INTERNAL;
     if ($user->isAllowed('bot')) {
         $flags |= EDIT_FORCE_BOT;
     }
     $log = new ManualLogEntry('contentmodel', $this->oldRevision ? 'change' : 'new');
     $log->setPerformer($user);
     $log->setTarget($this->title);
     $log->setComment($data['reason']);
     $log->setParameters(['4::oldmodel' => $oldModel, '5::newmodel' => $data['model']]);
     $formatter = LogFormatter::newFromEntry($log);
     $formatter->setContext(RequestContext::newExtraneousContext($this->title));
     $reason = $formatter->getPlainActionText();
     if ($data['reason'] !== '') {
         $reason .= $this->msg('colon-separator')->inContentLanguage()->text() . $data['reason'];
     }
     # Truncate for whole multibyte characters.
     $reason = $wgContLang->truncate($reason, 255);
     // Run edit filters
     $derivativeContext = new DerivativeContext($this->getContext());
     $derivativeContext->setTitle($this->title);
     $derivativeContext->setWikiPage($page);
     $status = new Status();
     if (!Hooks::run('EditFilterMergedContent', [$derivativeContext, $newContent, $status, $reason, $user, false])) {
         if ($status->isGood()) {
             // TODO: extensions should really specify an error message
             $status->fatal('hookaborted');
         }
         return $status;
     }
     $status = $page->doEditContent($newContent, $reason, $flags, $this->oldRevision ? $this->oldRevision->getId() : false, $user);
     if (!$status->isOK()) {
         return $status;
     }
     $logid = $log->insert();
     $log->publish($logid);
     return $status;
 }
Example #11
0
 /**
  * Sanity checks for when a file is being moved
  *
  * @return Status
  */
 protected function isValidFileMove()
 {
     $status = new Status();
     $file = wfLocalFile($this->oldTitle);
     $file->load(File::READ_LATEST);
     if ($file->exists()) {
         if ($this->newTitle->getText() != wfStripIllegalFilenameChars($this->newTitle->getText())) {
             $status->fatal('imageinvalidfilename');
         }
         if (!File::checkExtensionCompatibility($file, $this->newTitle->getDBkey())) {
             $status->fatal('imagetypemismatch');
         }
     }
     if (!$this->newTitle->inNamespace(NS_FILE)) {
         $status->fatal('imagenocrossnamespace');
     }
     return $status;
 }
Example #12
0
 /**
  * Run hooks that can filter edits just before they get saved.
  *
  * @param Content $content The Content to filter.
  * @param Status $status For reporting the outcome to the caller
  * @param User $user The user performing the edit
  *
  * @return bool
  */
 protected function runPostMergeFilters(Content $content, Status $status, User $user)
 {
     // Run old style post-section-merge edit filter
     if (!ContentHandler::runLegacyHooks('EditFilterMerged', array($this, $content, &$this->hookError, $this->summary))) {
         # Error messages etc. could be handled within the hook...
         $status->fatal('hookaborted');
         $status->value = self::AS_HOOK_ERROR;
         return false;
     } elseif ($this->hookError != '') {
         # ...or the hook could be expecting us to produce an error
         $status->fatal('hookaborted');
         $status->value = self::AS_HOOK_ERROR_EXPECTED;
         return false;
     }
     // Run new style post-section-merge edit filter
     if (!Hooks::run('EditFilterMergedContent', array($this->mArticle->getContext(), $content, $status, $this->summary, $user, $this->minoredit))) {
         # Error messages etc. could be handled within the hook...
         if ($status->isGood()) {
             $status->fatal('hookaborted');
             // Not setting $this->hookError here is a hack to allow the hook
             // to cause a return to the edit page without $this->hookError
             // being set. This is used by ConfirmEdit to display a captcha
             // without any error message cruft.
         } else {
             $this->hookError = $status->getWikiText();
         }
         // Use the existing $status->value if the hook set it
         if (!$status->value) {
             $status->value = self::AS_HOOK_ERROR;
         }
         return false;
     } elseif (!$status->isOK()) {
         # ...or the hook could be expecting us to produce an error
         // FIXME this sucks, we should just use the Status object throughout
         $this->hookError = $status->getWikiText();
         $status->fatal('hookaborted');
         $status->value = self::AS_HOOK_ERROR_EXPECTED;
         return false;
     }
     return true;
 }
Example #13
0
 /**
  * Sets HTTPRequest status member to a fatal value with the error
  * message if the returned integer value of the status code was
  * not successful (< 300) or a redirect (>=300 and < 400).  (see
  * RFC2616, section 10,
  * http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html for a
  * list of status codes.)
  *
  * @return nothing
  */
 protected function setStatus()
 {
     if (!$this->respHeaders) {
         $this->parseHeader();
     }
     if ((int) $this->respStatus > 399) {
         list($code, $message) = explode(" ", $this->respStatus, 2);
         $this->status->fatal("http-bad-status", $code, $message);
     }
 }
 /**
  * @see FSFileBackend::doExecuteOpHandlesInternal()
  */
 protected function _getResponseDelete($errors, Status $status, array $params, $cmd)
 {
     if ($errors !== '' && !(wfIsWindows() && $errors[0] === " ")) {
         $status->fatal('backend-fail-delete', $params['src']);
         trigger_error("{$cmd}\n{$errors}", E_USER_WARNING);
         // command output
     }
 }
 public static function onMovePageIsValidMove(Title $oldTitle, Title $newTitle, Status $status)
 {
     global $wgFlowOccupyNamespaces, $wgUser;
     // We only care about moving flow boards
     if ($oldTitle->getContentModel() !== CONTENT_MODEL_FLOW_BOARD) {
         return true;
     }
     // pages within the Topic namespace are not movable
     if ($oldTitle->getNamespace() === NS_TOPIC) {
         $status->fatal('flow-error-move-topic');
         return false;
     }
     $occupationController = self::getOccupationController();
     if (!$occupationController->isTalkpageOccupied($newTitle, false) && !$wgUser->isAllowed('flow-create-board')) {
         $status->fatal('flow-error-move-no-create-permissions');
         return false;
     }
     return true;
 }
Example #16
0
 /**
  * An efficient edit filter callback based on the text after section merging
  * @param RequestContext $context
  * @param Content $content
  * @param Status $status
  * @param $summary
  * @param $user
  * @param $minorEdit
  * @return bool
  */
 function confirmEditMerged($context, $content, $status, $summary, $user, $minorEdit)
 {
     $legacyMode = !defined('MW_EDITFILTERMERGED_SUPPORTS_API');
     if (defined('MW_API') && $legacyMode) {
         # API mode
         # The CAPTCHA was already checked and approved
         return true;
     }
     $page = $context->getWikiPage();
     if (!$this->doConfirmEdit($page, $content, false, true)) {
         if ($legacyMode) {
             $status->fatal('hookaborted');
         }
         $status->value = EditPage::AS_HOOK_ERROR_EXPECTED;
         $status->apiHookResult = array();
         $this->addCaptchaAPI($status->apiHookResult);
         $page->ConfirmEdit_ActivateCaptcha = true;
         return $legacyMode;
     }
     return true;
 }
Example #17
0
 /**
  * An efficient edit filter callback based on the text after section merging
  * @param RequestContext $context
  * @param Content $content
  * @param Status $status
  * @param $summary
  * @param $user
  * @param $minorEdit
  * @return bool
  */
 function confirmEditMerged($context, $content, $status, $summary, $user, $minorEdit)
 {
     $legacyMode = !defined('MW_EDITFILTERMERGED_SUPPORTS_API');
     if (defined('MW_API') && $legacyMode) {
         # API mode
         # The CAPTCHA was already checked and approved
         return true;
     }
     if (!$context->canUseWikiPage()) {
         // we check WikiPage only
         // try to get an appropriate title for this page
         $title = $context->getTitle();
         if ($title instanceof Title) {
             $title = $title->getFullText();
         } else {
             // otherwise it's an unknown page where this function is called from
             $title = 'unknown';
         }
         // log this error, it could be a problem in another extension, edits should always have a WikiPage if
         // they go through EditFilterMergedContent.
         wfDebug(__METHOD__ . ': Skipped ConfirmEdit check: No WikiPage for title ' . $title);
         return true;
     }
     $page = $context->getWikiPage();
     if (!$this->doConfirmEdit($page, $content, false, $context)) {
         if ($legacyMode) {
             $status->fatal('hookaborted');
         }
         $status->value = EditPage::AS_HOOK_ERROR_EXPECTED;
         $status->apiHookResult = array();
         $this->addCaptchaAPI($status->apiHookResult);
         $page->ConfirmEdit_ActivateCaptcha = true;
         return $legacyMode;
     }
     return true;
 }