public function getHTML()
 {
     wfProfileIn(__METHOD__);
     if ($this->isVisible()) {
         $ownerName = $this->ownerUser->getName();
         $tmplData = array();
         $tmplData['ownerBadges'] = $this->getBadgesAnnotated();
         $tmplData['challengesBadges'] = $this->getChallengesAnnotated();
         $tmplData['title_no'] = wfMsg('achievements-profile-title-no', $ownerName);
         $tmplData['title'] = wfMsgExt('achievements-profile-title', array('parsemag'), $ownerName, $this->owner->getBadgesCount());
         $tmplData['title_challenges'] = wfMsg('achievements-profile-title-challenges', $ownerName);
         $tmplData['leaderboard_url'] = Skin::makeSpecialUrl("Leaderboard");
         if ($this->owner->getBadgesCount() > 0) {
             $rankingService = new AchRankingService();
             $tmplData['user_rank'] = $rankingService->getUserRankingPosition($this->ownerUser);
         }
         if ($this->viewerUser->isAllowed('editinterface')) {
             $tmplData['customize_url'] = Skin::makeSpecialUrl("AchievementsCustomize");
         }
         $template = new EasyTemplate(dirname(__FILE__) . '/../templates');
         $template->set_vars($tmplData);
         $out = $template->render('ProfileBox');
     } else {
         $out = '';
     }
     wfProfileOut(__METHOD__);
     return $out;
 }
 public function execute($par)
 {
     global $wgOut, $wgRequest, $wgUser;
     // Yes, the use of getVal() and getText() is wanted, see bug 20365
     $this->text = $wgRequest->getVal('wpTitle', $par);
     $this->title = Title::newFromText($this->text);
     $this->reason = $wgRequest->getText('reason');
     // Checkboxes that default being checked are tricky
     $this->doSubpages = $wgRequest->getBool('subpages', !$wgRequest->wasPosted());
     $this->user = $wgUser;
     if ($this->doBasicChecks() !== true) {
         return;
     }
     // Real stuff starts here
     if (TranslatablePage::isSourcePage($this->title)) {
         $wgOut->setPagetitle(wfMsg('pt-deletepage-full-title', $this->title->getPrefixedText()));
         $this->code = '';
         $this->page = TranslatablePage::newFromTitle($this->title);
     } else {
         $page = TranslatablePage::isTranslationPage($this->title);
         if ($page) {
             $wgOut->setPagetitle(wfMsg('pt-deletepage-lang-title', $this->title->getPrefixedText()));
             list(, $this->code) = TranslateUtils::figureMessage($this->title->getText());
             $this->page = $page;
         } else {
             $wgOut->showErrorPage('pt-deletepage-invalid-title', 'pt-deletepage-invalid-text');
             return;
         }
     }
     if (!$this->user->isAllowed('pagetranslation')) {
         $wgOut->permissionRequired('pagetranslation');
         return;
     }
     // Is there really no better way to do this?
     $subactionText = $wgRequest->getText('subaction');
     switch ($subactionText) {
         case wfMsg('pt-deletepage-action-check'):
             $subaction = 'check';
             break;
         case wfMsg('pt-deletepage-action-perform'):
             $subaction = 'perform';
             break;
         case wfMsg('pt-deletepage-action-other'):
             $subaction = '';
             break;
         default:
             $subaction = '';
     }
     if ($subaction === 'check' && $this->checkToken() && $wgRequest->wasPosted()) {
         $this->showConfirmation();
     } elseif ($subaction === 'perform' && $this->checkToken() && $wgRequest->wasPosted()) {
         $this->performAction();
     } else {
         $this->showForm();
     }
 }
Example #3
0
 /**
  * Checks if the user is allowed to use the upload-by-URL feature. If the
  * user is not allowed, return the name of the user right as a string. If
  * the user is allowed, have the parent do further permissions checking.
  *
  * @param User $user
  *
  * @return bool|string
  */
 public static function isAllowed($user)
 {
     if (!$user->isAllowed('upload_by_url')) {
         return 'upload_by_url';
     }
     return parent::isAllowed($user);
 }
 /**
  * @param $group MessageGroup
  */
 public function doModLangs($group)
 {
     global $wgLang;
     $languages = array_keys(Language::getLanguageNames(false));
     $modified = $codes = array();
     foreach ($languages as $code) {
         if ($code === 'en') {
             continue;
         }
         $cache = new MessageGroupCache($group, $code);
         if ($cache->isValid()) {
             continue;
         }
         $link = $this->skin->link($this->getTitle(), htmlspecialchars(TranslateUtils::getLanguageName($code, false, $wgLang->getCode()) . " ({$code})"), array(), array('group' => $group->getId(), 'language' => $code));
         if (!$cache->exists()) {
             $modified[] = wfMsgHtml('translate-manage-modlang-new', $link);
         } else {
             $modified[] = $link;
         }
         $codes[] = $code;
     }
     if (count($modified)) {
         $this->out->addWikiMsg('translate-manage-modlangs', $wgLang->formatNum(count($modified)));
         if ($this->user->isAllowed('translate-manage')) {
             $this->out->addHTML($this->rebuildButton($group, $codes, 'import'));
         }
         $this->out->addHTML('<ul><li>' . implode("</li>\n<li>", $modified) . '</li></ul>');
     }
 }
Example #5
0
 /**
  * Given a username, if the current user has permission to do so, ban the user
  * from chat on the current wiki. This can be reversed by removing them from
  * the 'bannedfromchat' group.
  *
  * Will set doKickAnyway to true if the user should be kicked despite any error
  * messages (this is used primarily when the user is already banned from the wiki.
  * in that case, there is an error, but if the user is present they should be kicked).
  *
  * @param string $userNameToKickBan
  * @param User $kickingUser
  * @param int $time
  * @param string $reason
  *
  * @return bool|string Returns true on success, returns an error message as a string on failure.
  */
 public static function banUser($userNameToKickBan, $kickingUser, $time, $reason)
 {
     ChatHelper::info(__METHOD__ . ': Method called', ['userNameToKickBan' => $userNameToKickBan, 'kickingUser' => $kickingUser, 'time' => $time, 'reason' => $reason]);
     $kickBanPermission = 'chatmoderator';
     $userToKickBan = User::newFromName($userNameToKickBan);
     // Make sure user doing the kick/ban has permission to do so
     if (!$userToKickBan instanceof User || !$kickingUser->isAllowed($kickBanPermission)) {
         return wfMessage('chat-ban-you-need-permission', $kickBanPermission)->inContentLanguage()->text() . "\n";
     }
     // Make sure we aren't trying to kick/ban someone who shouldn't be kick/banned
     if ($userToKickBan->isAllowed($kickBanPermission) && !$kickingUser->isAllowed('chatstaff') && !$kickingUser->isAllowed('chatadmin')) {
         return wfMessage('chat-ban-cant-ban-moderator')->inContentLanguage()->text() . "\n";
     }
     self::banUserDB(F::app()->wg->CityId, $userToKickBan, $kickingUser, $time, $reason, $time == 0 ? 'remove' : 'add');
     return true;
 }
Example #6
0
 /**
  * @deprecated since 1.27 Use User::removeWatch()
  * @return bool
  */
 public function removeWatch()
 {
     wfDeprecated(__METHOD__, '1.27');
     if ($this->checkRights && !$this->user->isAllowed('editmywatchlist')) {
         return false;
     }
     $this->user->removeWatch($this->getTitle(), $this->checkRights);
     return true;
 }
 protected function autoreview_current(User $user)
 {
     $this->output("Auto-reviewing all current page versions...\n");
     if (!$user->getID()) {
         $this->output("Invalid user specified.\n");
         return;
     } elseif (!$user->isAllowed('review')) {
         $this->output("User specified (id: {$user->getID()}) does not have \"review\" rights.\n");
         return;
     }
     $db = wfGetDB(DB_MASTER);
     $this->output("Reviewer username: "******"\n");
     $start = $db->selectField('page', 'MIN(page_id)', false, __METHOD__);
     $end = $db->selectField('page', 'MAX(page_id)', false, __METHOD__);
     if (is_null($start) || is_null($end)) {
         $this->output("...page table seems to be empty.\n");
         return;
     }
     # Do remaining chunk
     $end += $this->mBatchSize - 1;
     $blockStart = $start;
     $blockEnd = $start + $this->mBatchSize - 1;
     $count = 0;
     $changed = 0;
     $flags = FlaggedRevs::quickTags(FR_CHECKED);
     // Assume basic level
     while ($blockEnd <= $end) {
         $this->output("...doing page_id from {$blockStart} to {$blockEnd}\n");
         $res = $db->select(array('page', 'revision'), '*', array("page_id BETWEEN {$blockStart} AND {$blockEnd}", 'page_namespace' => FlaggedRevs::getReviewNamespaces(), 'rev_id = page_latest'), __METHOD__);
         # Go through and autoreview the current version of every page...
         foreach ($res as $row) {
             $title = Title::newFromRow($row);
             $rev = Revision::newFromRow($row);
             # Is it already reviewed?
             $frev = FlaggedRevision::newFromTitle($title, $row->page_latest, FR_MASTER);
             # Rev should exist, but to be safe...
             if (!$frev && $rev) {
                 $article = new Article($title);
                 $db->begin();
                 FlaggedRevs::autoReviewEdit($article, $user, $rev, $flags, true);
                 FlaggedRevs::HTMLCacheUpdates($article->getTitle());
                 $db->commit();
                 $changed++;
             }
             $count++;
         }
         $db->freeResult($res);
         $blockStart += $this->mBatchSize - 1;
         $blockEnd += $this->mBatchSize - 1;
         // XXX: Don't let deferred jobs array get absurdly large (bug 24375)
         DeferredUpdates::doUpdates('commit');
         wfWaitForSlaves(5);
     }
     $this->output("Auto-reviewing of all pages complete ..." . "{$count} rows [{$changed} changed]\n");
 }
Example #8
0
 /**
  * Shows a deleted thread. Returns true to show the thread body
  */
 function showDeletedThread($thread)
 {
     if ($this->user->isAllowed('deletedhistory')) {
         $this->output->addWikiMsg('lqt_thread_deleted_for_sysops');
         return true;
     } else {
         $msg = wfMessage('lqt_thread_deleted')->parse();
         $msg = Xml::tags('em', null, $msg);
         $msg = Xml::tags('p', null, $msg);
         $this->output->addHTML($msg);
         return false;
     }
 }
Example #9
0
 /**
  * Check if a given user has permission to use this functionality.
  * @param User $user
  * @param bool $displayPassword If set, also check whether the user is allowed to reset the
  *   password of another user and see the temporary password.
  * @return StatusValue
  */
 public function isAllowed(User $user, $displayPassword = false)
 {
     $statuses = $this->permissionCache->get($user->getName());
     if ($statuses) {
         list($status, $status2) = $statuses;
     } else {
         $resetRoutes = $this->config->get('PasswordResetRoutes');
         $status = StatusValue::newGood();
         if (!is_array($resetRoutes) || !in_array(true, array_values($resetRoutes), true)) {
             // Maybe password resets are disabled, or there are no allowable routes
             $status = StatusValue::newFatal('passwordreset-disabled');
         } elseif (($providerStatus = $this->authManager->allowsAuthenticationDataChange(new TemporaryPasswordAuthenticationRequest(), false)) && !$providerStatus->isGood()) {
             // Maybe the external auth plugin won't allow local password changes
             $status = StatusValue::newFatal('resetpass_forbidden-reason', $providerStatus->getMessage());
         } elseif (!$this->config->get('EnableEmail')) {
             // Maybe email features have been disabled
             $status = StatusValue::newFatal('passwordreset-emaildisabled');
         } elseif (!$user->isAllowed('editmyprivateinfo')) {
             // Maybe not all users have permission to change private data
             $status = StatusValue::newFatal('badaccess');
         } elseif ($user->isBlocked()) {
             // Maybe the user is blocked (check this here rather than relying on the parent
             // method as we have a more specific error message to use here
             $status = StatusValue::newFatal('blocked-mailpassword');
         }
         $status2 = StatusValue::newGood();
         if (!$user->isAllowed('passwordreset')) {
             $status2 = StatusValue::newFatal('badaccess');
         }
         $this->permissionCache->set($user->getName(), [$status, $status2]);
     }
     if (!$displayPassword || !$status->isGood()) {
         return $status;
     } else {
         return $status2;
     }
 }
 public function userAllowedRequirementCheck(User $user, $action)
 {
     $result = false;
     $mapping = $this->userAllowedRequirementMapping();
     $requiredPerms = array_key_exists($action, $mapping) ? $mapping[$action] : $this->userAccessDefaultRequirement;
     if (!is_array($requiredPerms)) {
         $requiredPerms = [$requiredPerms];
     }
     foreach ($requiredPerms as $perm) {
         if (!$user->isAllowed($perm)) {
             $result = true;
             $this->onUserAllowedRequirementFailed($user, $requiredPerms);
         }
     }
     return $result;
 }
 /**
  * @param WikiPage $article
  * @param User $user
  * @param $content
  * @param $summary
  * @param Bool $isMinor
  * @param Bool $isWatch
  * @param $section
  * @param $flags
  * @param Revision $revision
  * @param $status
  * @param $baseRevId
  *
  * @return bool
  */
 public static function onPageContentSaveComplete(WikiPage $article, User $user, $content, $summary, $isMinor, $isWatch, $section, $flags, $revision, $status, $baseRevId)
 {
     if (is_null($revision)) {
         // Ignore null edits
         return true;
     }
     $title = $article->getTitle();
     $oldRevisionId = $revision->getParentId();
     if ($oldRevisionId !== null && ApprovedRevs::isAssignedToProject($title) && ApprovedRevs::getApprovedRevID($title) === $oldRevisionId) {
         if ($user->isAllowed('auto-reapproval-on-save')) {
             ApprovedRevs::performAutoReapproval($title, $revision->getId());
         } else {
             ApprovedRevs::logUnapprovedSave($title, $user, $revision->getId());
         }
     }
     return true;
 }
 /**
  * Do a prefix search of user names and return a list of matching user names.
  *
  * @param string|User $audience The string 'public' or a user object to show the search for
  * @param string $search
  * @param int $limit
  * @param int $offset How many results to offset from the beginning
  * @return array Array of strings
  */
 public static function search($audience, $search, $limit, $offset = 0)
 {
     $user = User::newFromName($search);
     $dbr = wfGetDB(DB_SLAVE);
     $prefix = $user ? $user->getName() : '';
     $tables = ['user'];
     $cond = ['user_name ' . $dbr->buildLike($prefix, $dbr->anyString())];
     $joinConds = [];
     // Filter out hidden user names
     if ($audience === 'public' || !$audience->isAllowed('hideuser')) {
         $tables[] = 'ipblocks';
         $cond['ipb_deleted'] = [0, null];
         $joinConds['ipblocks'] = ['LEFT JOIN', 'user_id=ipb_user'];
     }
     $res = $dbr->selectFieldValues($tables, 'user_name', $cond, __METHOD__, ['LIMIT' => $limit, 'ORDER BY' => 'user_name', 'OFFSET' => $offset], $joinConds);
     return $res === false ? [] : $res;
 }
Example #13
0
 /**
  * @desc blockCheck() will return false if user is blocked. The reason why it was
  * written in such way is below when you look at method UserBlock::onUserCanSendEmail().
  */
 public static function blockCheck(User $user, &$block)
 {
     global $wgUser, $wgMemc, $wgRequest;
     wfProfileIn(__METHOD__);
     if ($user->isAllowed('phalanxexempt')) {
         wfDebug(__METHOD__ . ": user has 'phalanxexempt' right - no block will be applied\n");
         wfProfileOut(__METHOD__);
         return true;
     }
     $ret = true;
     $text = $user->getName();
     // RT#42011: RegexBlock records strange results
     // don't write stats for other user than visiting user
     $isCurrentUser = $text == $wgUser->getName();
     // check cache first before proceeding
     $cachedState = self::getBlockFromCache($user, $isCurrentUser);
     if (!is_null($cachedState)) {
         wfProfileOut(__METHOD__);
         $block = (object) $cachedState['block'];
         return $cachedState['return'];
     }
     if (!empty($text)) {
         if ($user->isAnon()) {
             $ret = self::blockCheckIP($user, $text, $block, $isCurrentUser);
         } else {
             $blocksData = PhalanxFallback::getFromFilterShort(self::TYPE);
             if (!empty($blocksData)) {
                 $ret = self::blockCheckInternal($user, $blocksData, $text, $block, $isCurrentUser);
             }
             //do not check IP for current user when checking block status of different user
             if ($ret && $isCurrentUser) {
                 // if the user name was not blocked, check for an IP block
                 $ret = self::blockCheckIP($user, $wgRequest->getIP(), $block, $isCurrentUser);
             }
         }
     }
     // populate cache if not done before
     if ($ret) {
         $cachedState = array('timestamp' => wfTimestampNow(), 'block' => false, 'return' => $ret);
         $wgMemc->set(self::getCacheKey($user), $cachedState);
     }
     wfProfileOut(__METHOD__);
     return $ret;
 }
Example #14
0
 /**
  * @param User $user the user object
  * @return boolean whether the rule applies to the role
  */
 protected function matchRole($user)
 {
     if (empty($this->roles)) {
         // TODO: MAKE THIS FALSE
         return true;
     }
     foreach ($this->roles as $role) {
         if ($role === '?') {
             if ($user->getIsGuest()) {
                 return true;
             }
         } else {
             if (!$user->getIsGuest() && $user->isAllowed($role)) {
                 return true;
             }
         }
     }
     return false;
 }
 /**
  * getUserPermissionsErrors hook
  *
  * @param Title $title
  * @param User $user
  * @param string $action
  * @param $result
  * @return bool
  */
 public static function getUserPermissionsErrors(Title $title, User $user, $action, &$result)
 {
     if (!$title->inNamespace(NS_HIERA)) {
         return true;
     }
     if ($action === 'create' || $action === 'edit') {
         if (!$user->isLoggedIn()) {
             $result = array('openstackmanager-notloggedin');
             return false;
         }
         $userLDAP = new OpenStackNovaUser();
         if (!$userLDAP->exists()) {
             $result = array('openstackmanager-nonovacred-admincreate');
         }
         $project = $title->getText();
         if (!$userLDAP->inRole('projectadmin', $project) && !$user->isAllowed('editallhiera')) {
             $result = array('openstackmanager-hiera-noadmin', $project);
             return false;
         }
     }
     return true;
 }
 /**
  * Constructs an instance of ApiMain that utilizes the module and format specified by $request.
  *
  * @param $request object - if this is an instance of FauxRequest, errors are thrown and no printing occurs
  * @param $enableWrite bool should be set to true if the api may modify data
  */
 public function __construct($request, $enableWrite = false)
 {
     $this->mInternalMode = $request instanceof FauxRequest;
     // Special handling for the main module: $parent === $this
     parent::__construct($this, $this->mInternalMode ? 'main_int' : 'main');
     if (!$this->mInternalMode) {
         // Impose module restrictions.
         // If the current user cannot read,
         // Remove all modules other than login
         global $wgUser;
         if ($request->getVal('callback') !== null) {
             // JSON callback allows cross-site reads.
             // For safety, strip user credentials.
             wfDebug("API: stripping user credentials for JSON callback\n");
             $wgUser = new User();
         }
         if (!$wgUser->isAllowed('read')) {
             self::$Modules = array('login' => self::$Modules['login'], 'logout' => self::$Modules['logout'], 'help' => self::$Modules['help']);
         }
     }
     global $wgAPIModules, $wgEnableWriteAPI;
     // extension modules
     $this->mModules = $wgAPIModules + self::$Modules;
     if ($wgEnableWriteAPI) {
         $this->mModules += self::$WriteModules;
     }
     $this->mModuleNames = array_keys($this->mModules);
     // todo: optimize
     $this->mFormats = self::$Formats;
     $this->mFormatNames = array_keys($this->mFormats);
     // todo: optimize
     $this->mResult = new ApiResult($this);
     $this->mShowVersions = false;
     $this->mEnableWrite = $enableWrite;
     $this->mRequest =& $request;
     $this->mSquidMaxage = 0;
 }
Example #17
0
 /**
  * Determines if $user is unable to edit this page because it has been protected
  * by $wgNamespaceProtection.
  *
  * @param User $user User object to check permissions
  * @return bool
  */
 public function isNamespaceProtected(User $user)
 {
     global $wgNamespaceProtection;
     if (isset($wgNamespaceProtection[$this->mNamespace])) {
         foreach ((array) $wgNamespaceProtection[$this->mNamespace] as $right) {
             if ($right != '' && !$user->isAllowed($right)) {
                 return true;
             }
         }
     }
     return false;
 }
Example #18
0
 /**
  * Backend implementation of doRollback(), please refer there for parameter
  * and return value documentation
  *
  * NOTE: This function does NOT check ANY permissions, it just commits the
  * rollback to the DB. Therefore, you should only call this function direct-
  * ly if you want to use custom permissions checks. If you don't, use
  * doRollback() instead.
  * @param string $fromP Name of the user whose edits to rollback.
  * @param string $summary Custom summary. Set to default summary if empty.
  * @param bool $bot If true, mark all reverted edits as bot.
  *
  * @param array $resultDetails Contains result-specific array of additional values
  * @param User $guser The user performing the rollback
  * @param array|null $tags Change tags to apply to the rollback
  * Callers are responsible for permission checks
  * (with ChangeTags::canAddTagsAccompanyingChange)
  *
  * @return array
  */
 public function commitRollback($fromP, $summary, $bot, &$resultDetails, User $guser, $tags = null)
 {
     global $wgUseRCPatrol, $wgContLang;
     $dbw = wfGetDB(DB_MASTER);
     if (wfReadOnly()) {
         return [['readonlytext']];
     }
     // Get the last editor
     $current = $this->getRevision();
     if (is_null($current)) {
         // Something wrong... no page?
         return [['notanarticle']];
     }
     $from = str_replace('_', ' ', $fromP);
     // User name given should match up with the top revision.
     // If the user was deleted then $from should be empty.
     if ($from != $current->getUserText()) {
         $resultDetails = ['current' => $current];
         return [['alreadyrolled', htmlspecialchars($this->mTitle->getPrefixedText()), htmlspecialchars($fromP), htmlspecialchars($current->getUserText())]];
     }
     // Get the last edit not by this person...
     // Note: these may not be public values
     $user = intval($current->getUser(Revision::RAW));
     $user_text = $dbw->addQuotes($current->getUserText(Revision::RAW));
     $s = $dbw->selectRow('revision', ['rev_id', 'rev_timestamp', 'rev_deleted'], ['rev_page' => $current->getPage(), "rev_user != {$user} OR rev_user_text != {$user_text}"], __METHOD__, ['USE INDEX' => 'page_timestamp', 'ORDER BY' => 'rev_timestamp DESC']);
     if ($s === false) {
         // No one else ever edited this page
         return [['cantrollback']];
     } elseif ($s->rev_deleted & Revision::DELETED_TEXT || $s->rev_deleted & Revision::DELETED_USER) {
         // Only admins can see this text
         return [['notvisiblerev']];
     }
     // Generate the edit summary if necessary
     $target = Revision::newFromId($s->rev_id, Revision::READ_LATEST);
     if (empty($summary)) {
         if ($from == '') {
             // no public user name
             $summary = wfMessage('revertpage-nouser');
         } else {
             $summary = wfMessage('revertpage');
         }
     }
     // Allow the custom summary to use the same args as the default message
     $args = [$target->getUserText(), $from, $s->rev_id, $wgContLang->timeanddate(wfTimestamp(TS_MW, $s->rev_timestamp)), $current->getId(), $wgContLang->timeanddate($current->getTimestamp())];
     if ($summary instanceof Message) {
         $summary = $summary->params($args)->inContentLanguage()->text();
     } else {
         $summary = wfMsgReplaceArgs($summary, $args);
     }
     // Trim spaces on user supplied text
     $summary = trim($summary);
     // Truncate for whole multibyte characters.
     $summary = $wgContLang->truncate($summary, 255);
     // Save
     $flags = EDIT_UPDATE | EDIT_INTERNAL;
     if ($guser->isAllowed('minoredit')) {
         $flags |= EDIT_MINOR;
     }
     if ($bot && $guser->isAllowedAny('markbotedits', 'bot')) {
         $flags |= EDIT_FORCE_BOT;
     }
     $targetContent = $target->getContent();
     $changingContentModel = $targetContent->getModel() !== $current->getContentModel();
     // Actually store the edit
     $status = $this->doEditContent($targetContent, $summary, $flags, $target->getId(), $guser, null, $tags);
     // Set patrolling and bot flag on the edits, which gets rollbacked.
     // This is done even on edit failure to have patrolling in that case (bug 62157).
     $set = [];
     if ($bot && $guser->isAllowed('markbotedits')) {
         // Mark all reverted edits as bot
         $set['rc_bot'] = 1;
     }
     if ($wgUseRCPatrol) {
         // Mark all reverted edits as patrolled
         $set['rc_patrolled'] = 1;
     }
     if (count($set)) {
         $dbw->update('recentchanges', $set, ['rc_cur_id' => $current->getPage(), 'rc_user_text' => $current->getUserText(), 'rc_timestamp > ' . $dbw->addQuotes($s->rev_timestamp)], __METHOD__);
     }
     if (!$status->isOK()) {
         return $status->getErrorsArray();
     }
     // raise error, when the edit is an edit without a new version
     $statusRev = isset($status->value['revision']) ? $status->value['revision'] : null;
     if (!$statusRev instanceof Revision) {
         $resultDetails = ['current' => $current];
         return [['alreadyrolled', htmlspecialchars($this->mTitle->getPrefixedText()), htmlspecialchars($fromP), htmlspecialchars($current->getUserText())]];
     }
     if ($changingContentModel) {
         // If the content model changed during the rollback,
         // make sure it gets logged to Special:Log/contentmodel
         $log = new ManualLogEntry('contentmodel', 'change');
         $log->setPerformer($guser);
         $log->setTarget($this->mTitle);
         $log->setComment($summary);
         $log->setParameters(['4::oldmodel' => $current->getContentModel(), '5::newmodel' => $targetContent->getModel()]);
         $logId = $log->insert($dbw);
         $log->publish($logId);
     }
     $revId = $statusRev->getId();
     Hooks::run('ArticleRollbackComplete', [$this, $guser, $target, $current]);
     $resultDetails = ['summary' => $summary, 'current' => $current, 'target' => $target, 'newid' => $revId];
     return [];
 }
Example #19
0
 /**
  * Indicate whether change tag editing UI is relevant
  *
  * Returns true if the user has the necessary right and there are any
  * editable tags defined.
  *
  * This intentionally doesn't check "any addable || any deletable", because
  * it seems like it would be more confusing than useful if the checkboxes
  * suddenly showed up because some abuse filter stopped defining a tag and
  * then suddenly disappeared when someone deleted all uses of that tag.
  *
  * @param User $user
  * @return bool
  */
 public static function showTagEditingUI(User $user)
 {
     return $user->isAllowed('changetags') && (bool) self::listExplicitlyDefinedTags();
 }
Example #20
0
 /**
  * Determine which restriction levels it makes sense to use in a namespace,
  * optionally filtered by a user's rights.
  *
  * @since 1.23
  * @param int $index Index to check
  * @param User $user User to check
  * @return array
  */
 public static function getRestrictionLevels($index, User $user = null)
 {
     global $wgNamespaceProtection, $wgRestrictionLevels;
     if (!isset($wgNamespaceProtection[$index])) {
         // All levels are valid if there's no namespace restriction.
         // But still filter by user, if necessary
         $levels = $wgRestrictionLevels;
         if ($user) {
             $levels = array_values(array_filter($levels, function ($level) use($user) {
                 $right = $level;
                 if ($right == 'sysop') {
                     $right = 'editprotected';
                     // BC
                 }
                 if ($right == 'autoconfirmed') {
                     $right = 'editsemiprotected';
                     // BC
                 }
                 return $right == '' || $user->isAllowed($right);
             }));
         }
         return $levels;
     }
     // First, get the list of groups that can edit this namespace.
     $namespaceGroups = [];
     $combine = 'array_merge';
     foreach ((array) $wgNamespaceProtection[$index] as $right) {
         if ($right == 'sysop') {
             $right = 'editprotected';
             // BC
         }
         if ($right == 'autoconfirmed') {
             $right = 'editsemiprotected';
             // BC
         }
         if ($right != '') {
             $namespaceGroups = call_user_func($combine, $namespaceGroups, User::getGroupsWithPermission($right));
             $combine = 'array_intersect';
         }
     }
     // Now, keep only those restriction levels where there is at least one
     // group that can edit the namespace but would be blocked by the
     // restriction.
     $usableLevels = [''];
     foreach ($wgRestrictionLevels as $level) {
         $right = $level;
         if ($right == 'sysop') {
             $right = 'editprotected';
             // BC
         }
         if ($right == 'autoconfirmed') {
             $right = 'editsemiprotected';
             // BC
         }
         if ($right != '' && (!$user || $user->isAllowed($right)) && array_diff($namespaceGroups, User::getGroupsWithPermission($right))) {
             $usableLevels[] = $level;
         }
     }
     return $usableLevels;
 }
Example #21
0
 /**
  * Get a revision-deletion link, or disabled link, or nothing, depending
  * on user permissions & the settings on the revision.
  *
  * Will use forward-compatible revision ID in the Special:RevDelete link
  * if possible, otherwise the timestamp-based ID which may break after
  * undeletion.
  *
  * @param User $user
  * @param Revision $rev
  * @param Revision $title
  * @return string HTML fragment
  */
 public static function getRevDeleteLink(User $user, Revision $rev, Title $title)
 {
     $canHide = $user->isAllowed('deleterevision');
     if (!$canHide && !($rev->getVisibility() && $user->isAllowed('deletedhistory'))) {
         return '';
     }
     if (!$rev->userCan(Revision::DELETED_RESTRICTED, $user)) {
         return Linker::revDeleteLinkDisabled($canHide);
         // revision was hidden from sysops
     } else {
         if ($rev->getId()) {
             // RevDelete links using revision ID are stable across
             // page deletion and undeletion; use when possible.
             $query = array('type' => 'revision', 'target' => $title->getPrefixedDBkey(), 'ids' => $rev->getId());
         } else {
             // Older deleted entries didn't save a revision ID.
             // We have to refer to these by timestamp, ick!
             $query = array('type' => 'archive', 'target' => $title->getPrefixedDBkey(), 'ids' => $rev->getTimestamp());
         }
         return Linker::revDeleteLink($query, $rev->isDeleted(Revision::DELETED_RESTRICTED), $canHide);
     }
 }
Example #22
0
 /**
  * Immediate version of notifyOnPageChange().
  *
  * Send emails corresponding to the user $editor editing the page $title.
  *
  * @note Do not call directly. Use notifyOnPageChange so that wl_notificationtimestamp is updated.
  * @param User $editor
  * @param Title $title
  * @param string $timestamp Edit timestamp
  * @param string $summary Edit summary
  * @param bool $minorEdit
  * @param int $oldid Revision ID
  * @param array $watchers Array of user IDs
  * @param string $pageStatus
  * @throws MWException
  */
 public function actuallyNotifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid, $watchers, $pageStatus = 'changed')
 {
     # we use $wgPasswordSender as sender's address
     global $wgEnotifWatchlist;
     global $wgEnotifMinorEdits, $wgEnotifUserTalk;
     # The following code is only run, if several conditions are met:
     # 1. EmailNotification for pages (other than user_talk pages) must be enabled
     # 2. minor edits (changes) are only regarded if the global flag indicates so
     $isUserTalkPage = $title->getNamespace() == NS_USER_TALK;
     $this->title = $title;
     $this->timestamp = $timestamp;
     $this->summary = $summary;
     $this->minorEdit = $minorEdit;
     $this->oldid = $oldid;
     $this->editor = $editor;
     $this->composed_common = false;
     $this->pageStatus = $pageStatus;
     $formattedPageStatus = array('deleted', 'created', 'moved', 'restored', 'changed');
     Hooks::run('UpdateUserMailerFormattedPageStatus', array(&$formattedPageStatus));
     if (!in_array($this->pageStatus, $formattedPageStatus)) {
         throw new MWException('Not a valid page status!');
     }
     $userTalkId = false;
     if (!$minorEdit || $wgEnotifMinorEdits && !$editor->isAllowed('nominornewtalk')) {
         if ($wgEnotifUserTalk && $isUserTalkPage && $this->canSendUserTalkEmail($editor, $title, $minorEdit)) {
             $targetUser = User::newFromName($title->getText());
             $this->compose($targetUser);
             $userTalkId = $targetUser->getId();
         }
         if ($wgEnotifWatchlist) {
             // Send updates to watchers other than the current editor
             $userArray = UserArray::newFromIDs($watchers);
             foreach ($userArray as $watchingUser) {
                 if ($watchingUser->getOption('enotifwatchlistpages') && (!$minorEdit || $watchingUser->getOption('enotifminoredits')) && $watchingUser->isEmailConfirmed() && $watchingUser->getID() != $userTalkId) {
                     if (Hooks::run('SendWatchlistEmailNotification', array($watchingUser, $title, $this))) {
                         $this->compose($watchingUser);
                     }
                 }
             }
         }
     }
     global $wgUsersNotifiedOnAllChanges;
     foreach ($wgUsersNotifiedOnAllChanges as $name) {
         if ($editor->getName() == $name) {
             // No point notifying the user that actually made the change!
             continue;
         }
         $user = User::newFromName($name);
         $this->compose($user);
     }
     $this->sendMails();
 }
Example #23
0
 /**
  * @param User $user
  * @param IContextSource $context
  * @param array $defaultPreferences
  */
 static function watchlistPreferences($user, IContextSource $context, &$defaultPreferences)
 {
     $config = $context->getConfig();
     $watchlistdaysMax = ceil($config->get('RCMaxAge') / (3600 * 24));
     # # Watchlist #####################################
     if ($user->isAllowed('editmywatchlist')) {
         $editWatchlistLinks = array();
         $editWatchlistModes = array('edit' => array('EditWatchlist', false), 'raw' => array('EditWatchlist', 'raw'), 'clear' => array('EditWatchlist', 'clear'));
         foreach ($editWatchlistModes as $editWatchlistMode => $mode) {
             // Messages: prefs-editwatchlist-edit, prefs-editwatchlist-raw, prefs-editwatchlist-clear
             $editWatchlistLinks[] = Linker::linkKnown(SpecialPage::getTitleFor($mode[0], $mode[1]), $context->msg("prefs-editwatchlist-{$editWatchlistMode}")->parse());
         }
         $defaultPreferences['editwatchlist'] = array('type' => 'info', 'raw' => true, 'default' => $context->getLanguage()->pipeList($editWatchlistLinks), 'label-message' => 'prefs-editwatchlist-label', 'section' => 'watchlist/editwatchlist');
     }
     $defaultPreferences['watchlistdays'] = array('type' => 'float', 'min' => 0, 'max' => $watchlistdaysMax, 'section' => 'watchlist/displaywatchlist', 'help' => $context->msg('prefs-watchlist-days-max')->numParams($watchlistdaysMax)->escaped(), 'label-message' => 'prefs-watchlist-days');
     $defaultPreferences['wllimit'] = array('type' => 'int', 'min' => 0, 'max' => 1000, 'label-message' => 'prefs-watchlist-edits', 'help' => $context->msg('prefs-watchlist-edits-max')->escaped(), 'section' => 'watchlist/displaywatchlist');
     $defaultPreferences['extendwatchlist'] = array('type' => 'toggle', 'section' => 'watchlist/advancedwatchlist', 'label-message' => 'tog-extendwatchlist');
     $defaultPreferences['watchlisthideminor'] = array('type' => 'toggle', 'section' => 'watchlist/advancedwatchlist', 'label-message' => 'tog-watchlisthideminor');
     $defaultPreferences['watchlisthidebots'] = array('type' => 'toggle', 'section' => 'watchlist/advancedwatchlist', 'label-message' => 'tog-watchlisthidebots');
     $defaultPreferences['watchlisthideown'] = array('type' => 'toggle', 'section' => 'watchlist/advancedwatchlist', 'label-message' => 'tog-watchlisthideown');
     $defaultPreferences['watchlisthideanons'] = array('type' => 'toggle', 'section' => 'watchlist/advancedwatchlist', 'label-message' => 'tog-watchlisthideanons');
     $defaultPreferences['watchlisthideliu'] = array('type' => 'toggle', 'section' => 'watchlist/advancedwatchlist', 'label-message' => 'tog-watchlisthideliu');
     $defaultPreferences['watchlistreloadautomatically'] = array('type' => 'toggle', 'section' => 'watchlist/advancedwatchlist', 'label-message' => 'tog-watchlistreloadautomatically');
     if ($config->get('RCWatchCategoryMembership')) {
         $defaultPreferences['watchlisthidecategorization'] = array('type' => 'toggle', 'section' => 'watchlist/advancedwatchlist', 'label-message' => 'tog-watchlisthidecategorization');
     }
     if ($user->useRCPatrol()) {
         $defaultPreferences['watchlisthidepatrolled'] = array('type' => 'toggle', 'section' => 'watchlist/advancedwatchlist', 'label-message' => 'tog-watchlisthidepatrolled');
     }
     $watchTypes = array('edit' => 'watchdefault', 'move' => 'watchmoves', 'delete' => 'watchdeletion');
     // Kinda hacky
     if ($user->isAllowed('createpage') || $user->isAllowed('createtalk')) {
         $watchTypes['read'] = 'watchcreations';
     }
     if ($user->isAllowed('rollback')) {
         $watchTypes['rollback'] = 'watchrollback';
     }
     foreach ($watchTypes as $action => $pref) {
         if ($user->isAllowed($action)) {
             // Messages:
             // tog-watchdefault, tog-watchmoves, tog-watchdeletion, tog-watchcreations
             // tog-watchrollback
             $defaultPreferences[$pref] = array('type' => 'toggle', 'section' => 'watchlist/advancedwatchlist', 'label-message' => "tog-{$pref}");
         }
     }
     if ($config->get('EnableAPI')) {
         $defaultPreferences['watchlisttoken'] = array('type' => 'api');
         $defaultPreferences['watchlisttoken-info'] = array('type' => 'info', 'section' => 'watchlist/tokenwatchlist', 'label-message' => 'prefs-watchlist-token', 'default' => $user->getTokenFromOption('watchlisttoken'), 'help-message' => 'prefs-help-watchlist-token2');
     }
 }
 /**
  * Check if a user is the last uploader
  *
  * @param $user User object
  * @param string $img image name
  * @return Boolean
  */
 public static function userCanReUpload(User $user, $img)
 {
     if ($user->isAllowed('reupload')) {
         return true;
         // non-conditional
     }
     if (!$user->isAllowed('reupload-own')) {
         return false;
     }
     if (is_string($img)) {
         $img = wfLocalFile($img);
     }
     if (!$img instanceof LocalFile) {
         return false;
     }
     return $user->getId() == $img->getUser('id');
 }
Example #25
0
 /**
  * bug 15810: blocked admins should not be able to block/unblock
  * others, and probably shouldn't be able to unblock themselves
  * either.
  * @param $user User|Int|String
  * @param $performer User user doing the request
  * @return Bool|String true or error message key
  */
 public static function checkUnblockSelf($user, User $performer)
 {
     if (is_int($user)) {
         $user = User::newFromId($user);
     } elseif (is_string($user)) {
         $user = User::newFromName($user);
     }
     if ($performer->isBlocked()) {
         if ($user instanceof User && $user->getId() == $performer->getId()) {
             # User is trying to unblock themselves
             if ($performer->isAllowed('unblockself')) {
                 return true;
                 # User blocked themselves and is now trying to reverse it
             } elseif ($performer->blockedBy() === $performer->getName()) {
                 return true;
             } else {
                 return 'ipbnounblockself';
             }
         } else {
             # User is trying to block/unblock someone else
             return 'ipbblocked';
         }
     } else {
         return true;
     }
 }
Example #26
0
 /**
  * Can we do an email block?
  * @param User $user The sysop wanting to make a block
  * @return boolean
  */
 public static function canBlockEmail($user)
 {
     global $wgEnableUserEmail, $wgSysopEmailBans;
     return $wgEnableUserEmail && $wgSysopEmailBans && $user->isAllowed('blockemail');
 }
 public function userCanExecute(User $user)
 {
     return $user->isAllowed('createaccount');
 }
Example #28
0
	/**
	 * Backend implementation of doRollback(), please refer there for parameter
	 * and return value documentation
	 *
	 * NOTE: This function does NOT check ANY permissions, it just commits the
	 * rollback to the DB. Therefore, you should only call this function direct-
	 * ly if you want to use custom permissions checks. If you don't, use
	 * doRollback() instead.
	 * @param string $fromP Name of the user whose edits to rollback.
	 * @param string $summary Custom summary. Set to default summary if empty.
	 * @param $bot Boolean: If true, mark all reverted edits as bot.
	 *
	 * @param array $resultDetails contains result-specific array of additional values
	 * @param $guser User The user performing the rollback
	 * @return array
	 */
	public function commitRollback( $fromP, $summary, $bot, &$resultDetails, User $guser ) {
		global $wgUseRCPatrol, $wgContLang;

		$dbw = wfGetDB( DB_MASTER );

		if ( wfReadOnly() ) {
			return array( array( 'readonlytext' ) );
		}

		// Get the last editor
		$current = $this->getRevision();
		if ( is_null( $current ) ) {
			// Something wrong... no page?
			return array( array( 'notanarticle' ) );
		}

		$from = str_replace( '_', ' ', $fromP );
		// User name given should match up with the top revision.
		// If the user was deleted then $from should be empty.
		if ( $from != $current->getUserText() ) {
			$resultDetails = array( 'current' => $current );
			return array( array( 'alreadyrolled',
				htmlspecialchars( $this->mTitle->getPrefixedText() ),
				htmlspecialchars( $fromP ),
				htmlspecialchars( $current->getUserText() )
			) );
		}

		// Get the last edit not by this guy...
		// Note: these may not be public values
		$user = intval( $current->getRawUser() );
		$user_text = $dbw->addQuotes( $current->getRawUserText() );
		$s = $dbw->selectRow( 'revision',
			array( 'rev_id', 'rev_timestamp', 'rev_deleted' ),
			array( 'rev_page' => $current->getPage(),
				"rev_user != {$user} OR rev_user_text != {$user_text}"
			), __METHOD__,
			array( 'USE INDEX' => 'page_timestamp',
				'ORDER BY' => 'rev_timestamp DESC' )
			);
		if ( $s === false ) {
			// No one else ever edited this page
			return array( array( 'cantrollback' ) );
		} elseif ( $s->rev_deleted & Revision::DELETED_TEXT || $s->rev_deleted & Revision::DELETED_USER ) {
			// Only admins can see this text
			return array( array( 'notvisiblerev' ) );
		}

		$set = array();
		if ( $bot && $guser->isAllowed( 'markbotedits' ) ) {
			// Mark all reverted edits as bot
			$set['rc_bot'] = 1;
		}

		if ( $wgUseRCPatrol ) {
			// Mark all reverted edits as patrolled
			$set['rc_patrolled'] = 1;
		}

		if ( count( $set ) ) {
			$dbw->update( 'recentchanges', $set,
				array( /* WHERE */
					'rc_cur_id' => $current->getPage(),
					'rc_user_text' => $current->getUserText(),
					'rc_timestamp > ' . $dbw->addQuotes( $s->rev_timestamp ),
				), __METHOD__
			);
		}

		// Generate the edit summary if necessary
		$target = Revision::newFromId( $s->rev_id );
		if ( empty( $summary ) ) {
			if ( $from == '' ) { // no public user name
				$summary = wfMessage( 'revertpage-nouser' );
			} else {
				$summary = wfMessage( 'revertpage' );
			}
		}

		// Allow the custom summary to use the same args as the default message
		$args = array(
			$target->getUserText(), $from, $s->rev_id,
			$wgContLang->timeanddate( wfTimestamp( TS_MW, $s->rev_timestamp ) ),
			$current->getId(), $wgContLang->timeanddate( $current->getTimestamp() )
		);
		if ( $summary instanceof Message ) {
			$summary = $summary->params( $args )->inContentLanguage()->text();
		} else {
			$summary = wfMsgReplaceArgs( $summary, $args );
		}

		// Trim spaces on user supplied text
		$summary = trim( $summary );

		// Truncate for whole multibyte characters.
		$summary = $wgContLang->truncate( $summary, 255 );

		// Save
		$flags = EDIT_UPDATE;

		if ( $guser->isAllowed( 'minoredit' ) ) {
			$flags |= EDIT_MINOR;
		}

		if ( $bot && ( $guser->isAllowedAny( 'markbotedits', 'bot' ) ) ) {
			$flags |= EDIT_FORCE_BOT;
		}

		// Actually store the edit
		$status = $this->doEditContent( $target->getContent(), $summary, $flags, $target->getId(), $guser );

		if ( !$status->isOK() ) {
			return $status->getErrorsArray();
		}

		if ( !empty( $status->value['revision'] ) ) {
			$revId = $status->value['revision']->getId();
		} else {
			$revId = false;
		}

		wfRunHooks( 'ArticleRollbackComplete', array( $this, $guser, $target, $current ) );

		$resultDetails = array(
			'summary' => $summary,
			'current' => $current,
			'target' => $target,
			'newid' => $revId
		);

		return array();
	}
 /**
  * @param string $timestamp
  * @param Title $title
  * @param User $user
  * @param string $actionComment
  * @param string $ip
  * @param string $type
  * @param string $action
  * @param Title $target
  * @param string $logComment
  * @param string $params
  * @param int $newId
  * @param string $actionCommentIRC
  * @return RecentChange
  */
 public static function newLogEntry($timestamp, &$title, &$user, $actionComment, $ip, $type, $action, $target, $logComment, $params, $newId = 0, $actionCommentIRC = '')
 {
     global $wgRequest;
     # # Get pageStatus for email notification
     switch ($type . '-' . $action) {
         case 'delete-delete':
             $pageStatus = 'deleted';
             break;
         case 'move-move':
         case 'move-move_redir':
             $pageStatus = 'moved';
             break;
         case 'delete-restore':
             $pageStatus = 'restored';
             break;
         case 'upload-upload':
             $pageStatus = 'created';
             break;
         case 'upload-overwrite':
         default:
             $pageStatus = 'changed';
             break;
     }
     $rc = new RecentChange();
     $rc->mTitle = $target;
     $rc->mPerformer = $user;
     $rc->mAttribs = array('rc_timestamp' => $timestamp, 'rc_namespace' => $target->getNamespace(), 'rc_title' => $target->getDBkey(), 'rc_type' => RC_LOG, 'rc_source' => self::SRC_LOG, 'rc_minor' => 0, 'rc_cur_id' => $target->getArticleID(), 'rc_user' => $user->getId(), 'rc_user_text' => $user->getName(), 'rc_comment' => $logComment, 'rc_this_oldid' => 0, 'rc_last_oldid' => 0, 'rc_bot' => $user->isAllowed('bot') ? $wgRequest->getBool('bot', true) : 0, 'rc_ip' => self::checkIPAddress($ip), 'rc_patrolled' => 1, 'rc_new' => 0, 'rc_old_len' => null, 'rc_new_len' => null, 'rc_deleted' => 0, 'rc_logid' => $newId, 'rc_log_type' => $type, 'rc_log_action' => $action, 'rc_params' => $params);
     $rc->mExtra = array('prefixedDBkey' => $title->getPrefixedDBkey(), 'lastTimestamp' => 0, 'actionComment' => $actionComment, 'pageStatus' => $pageStatus, 'actionCommentIRC' => $actionCommentIRC);
     return $rc;
 }
Example #30
0
 /**
  * Check whether a user is allowed to send email
  *
  * @param User $user
  * @param string $editToken Edit token
  * @param Config $config optional for backwards compatibility
  * @return string|null Null on success or string on error
  */
 public static function getPermissionsError($user, $editToken, Config $config = null)
 {
     if ($config === null) {
         wfDebug(__METHOD__ . ' called without a Config instance passed to it');
         $config = ConfigFactory::getDefaultInstance()->makeConfig('main');
     }
     if (!$config->get('EnableEmail') || !$config->get('EnableUserEmail')) {
         return 'usermaildisabled';
     }
     if (!$user->isAllowed('sendemail')) {
         return 'badaccess';
     }
     if (!$user->isEmailConfirmed()) {
         return 'mailnologin';
     }
     if ($user->isBlockedFromEmailuser()) {
         wfDebug("User is blocked from sending e-mail.\n");
         return "blockedemailuser";
     }
     if ($user->pingLimiter('emailuser')) {
         wfDebug("Ping limiter triggered.\n");
         return 'actionthrottledtext';
     }
     $hookErr = false;
     Hooks::run('UserCanSendEmail', array(&$user, &$hookErr));
     Hooks::run('EmailUserPermissionsErrors', array($user, $editToken, &$hookErr));
     if ($hookErr) {
         return $hookErr;
     }
     return null;
 }