/**
* Does the title correspond to a protected article?
* @param string $what the action the page is protected from,
- * by default checks move and edit
+ * by default checks move and edit
* @return boolean
*/
public function isProtected( $action = '' ) {
return $this->mWatched;
}
- /**
+ /**
* Can $wgUser perform $action on this page?
* This skips potentially expensive cascading permission checks.
*
/**
* Determines if $wgUser is unable to edit this page because it has been protected
* by $wgNamespaceProtection.
- *
+ *
* @return boolean
*/
public function isNamespaceProtected() {
return false;
}
- /**
+ /**
* Can $wgUser perform $action on this page?
* @param string $action action that permission needs to be checked for
* @param bool $doExpensiveQueries Set this to false to avoid doing unnecessary queries.
return ( $this->getUserPermissionsErrorsInternal( $action, $wgUser, $doExpensiveQueries ) === array());
}
- /**
+ /**
* Can $user perform $action on this page?
* @param string $action action that permission needs to be checked for
* @param bool $doExpensiveQueries Set this to false to avoid doing unnecessary queries.
$id = $user->blockedBy();
$reason = $user->blockedFor();
+ if( $reason == '' ) {
+ $reason = wfMsg( 'blockednoreason' );
+ }
$ip = wfGetIP();
if ( is_numeric( $id ) ) {
}
}
+ if ($action == 'protect') {
+ if ($this->getUserPermissionsErrors('edit', $user) != array()) {
+ $errors[] = array( 'protect-cantedit' ); // If they can't edit, they shouldn't protect.
+ }
+ }
+
+
+ if ($action == 'create') {
+ $title_protection = $this->getTitleProtection();
+
+ if (is_array($title_protection)) {
+ extract($title_protection);
+
+ if ($pt_create_perm == 'sysop')
+ $pt_create_perm = 'protect';
+
+ if ($pt_create_perm == '' || !$user->isAllowed($pt_create_perm)) {
+ $errors[] = array ( 'titleprotected', User::whoIs($pt_user), $pt_reason );
+ }
+ }
+ }
+
if( $action == 'create' ) {
if( ( $this->isTalkPage() && !$user->isAllowed( 'createtalk' ) ) ||
( !$this->isTalkPage() && !$user->isAllowed( 'createpage' ) ) ) {
}
} elseif( $action == 'move' && !( $this->isMovable() && $user->isAllowed( 'move' ) ) ) {
$errors[] = $user->isAnon() ? array ( 'movenologintext' ) : array ('movenotallowed');
- } else if ( !$user->isAllowed( $action ) ) {
+ } else if ( !$user->isAllowed( $action ) ) {
$return = null;
- $groups = array();
+ $groups = array();
global $wgGroupPermissions;
- foreach( $wgGroupPermissions as $key => $value ) {
- if( isset( $value[$action] ) && $value[$action] == true ) {
- $groupName = User::getGroupName( $key );
- $groupPage = User::getGroupPage( $key );
- if( $groupPage ) {
- $groups[] = '[['.$groupPage->getPrefixedText().'|'.$groupName.']]';
- } else {
- $groups[] = $groupName;
- }
- }
- }
- $n = count( $groups );
- $groups = implode( ', ', $groups );
- switch( $n ) {
- case 0:
- case 1:
- case 2:
- $return = array( "badaccess-group$n", $groups );
- break;
- default:
- $return = array( 'badaccess-groups', $groups );
- }
+ foreach( $wgGroupPermissions as $key => $value ) {
+ if( isset( $value[$action] ) && $value[$action] == true ) {
+ $groupName = User::getGroupName( $key );
+ $groupPage = User::getGroupPage( $key );
+ if( $groupPage ) {
+ $groups[] = '[['.$groupPage->getPrefixedText().'|'.$groupName.']]';
+ } else {
+ $groups[] = $groupName;
+ }
+ }
+ }
+ $n = count( $groups );
+ $groups = implode( ', ', $groups );
+ switch( $n ) {
+ case 0:
+ case 1:
+ case 2:
+ $return = array( "badaccess-group$n", $groups );
+ break;
+ default:
+ $return = array( 'badaccess-groups', $groups );
+ }
$errors[] = $return;
}
return $errors;
}
+ /**
+ * Is this title subject to title protection?
+ * @return mixed An associative array representing any existent title
+ * protection, or false if there's none.
+ */
+ public function getTitleProtection() {
+ $dbr = wfGetDB( DB_SLAVE );
+
+ $res = $dbr->select( 'protected_titles', '*',
+ array ('pt_namespace' => $this->getNamespace(), 'pt_title' => $this->getDBKey()) );
+
+ if ($row = $dbr->fetchRow( $res )) {
+ return $row;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateTitleProtection( $create_perm, $reason, $expiry ) {
+ global $wgGroupPermissions,$wgUser,$wgContLang;
+
+ if ($create_perm == implode(',',$this->getRestrictions('create'))
+ && $expiry == $this->mRestrictionsExpiry) {
+ // No change
+ return true;
+ }
+
+ list ($namespace, $title) = array( $this->getNamespace(), $this->getDBKey() );
+
+ $dbw = wfGetDB( DB_MASTER );
+
+ $encodedExpiry = Block::encodeExpiry($expiry, $dbw );
+
+ $expiry_description = '';
+ if ( $encodedExpiry != 'infinity' ) {
+ $expiry_description = ' (' . wfMsgForContent( 'protect-expiring', $wgContLang->timeanddate( $expiry ) ).')';
+ }
+
+ # Update protection table
+ if ($create_perm != '' ) {
+ $dbw->replace( 'protected_titles', array(array('pt_namespace', 'pt_title')),
+ array( 'pt_namespace' => $namespace, 'pt_title' => $title
+ , 'pt_create_perm' => $create_perm
+ , 'pt_timestamp' => Block::encodeExpiry(wfTimestampNow(), $dbw)
+ , 'pt_expiry' => $encodedExpiry
+ , 'pt_user' => $wgUser->getId(), 'pt_reason' => $reason ), __METHOD__ );
+ } else {
+ $dbw->delete( 'protected_titles', array( 'pt_namespace' => $namespace,
+ 'pt_title' => $title ), __METHOD__ );
+ }
+ # Update the protection log
+ $log = new LogPage( 'protect' );
+
+ if( $create_perm ) {
+ $log->addEntry( $this->mRestrictions['create'] ? 'modify' : 'protect', $this, trim( $reason . " [create=$create_perm] $expiry_description" ) );
+ } else {
+ $log->addEntry( 'unprotect', $this, $reason );
+ }
+
+ return true;
+ }
+
+ /**
+ * Remove any title protection (due to page existing
+ */
+ public function deleteTitleProtection() {
+ $dbw = wfGetDB( DB_MASTER );
+
+ $dbw->delete( 'protected_titles',
+ array ('pt_namespace' => $this->getNamespace(), 'pt_title' => $this->getDBKey()), __METHOD__ );
+ }
+
/**
* Can $wgUser edit this page?
* @return boolean
* and check again
*/
if( $this->getNamespace() == NS_SPECIAL ) {
- $name = $this->getText();
+ $name = $this->getDBKey();
list( $name, /* $subpage */) = SpecialPage::resolveAliasWithSubpage( $name );
+ if ( $name === false ) {
+ # Invalid special page, but we show standard login required message
+ return false;
+ }
+
$pure = SpecialPage::getTitleFor( $name )->getPrefixedText();
if( in_array( $pure, $wgWhitelistRead, true ) )
return true;
public function loadRestrictions( $oldFashionedRestrictions = NULL ) {
if( !$this->mRestrictionsLoaded ) {
- $dbr = wfGetDB( DB_SLAVE );
+ if ($this->exists()) {
+ $dbr = wfGetDB( DB_SLAVE );
- $res = $dbr->select( 'page_restrictions', '*',
- array ( 'pr_page' => $this->getArticleId() ), __METHOD__ );
+ $res = $dbr->select( 'page_restrictions', '*',
+ array ( 'pr_page' => $this->getArticleId() ), __METHOD__ );
- $this->loadRestrictionsFromRow( $res, $oldFashionedRestrictions );
+ $this->loadRestrictionsFromRow( $res, $oldFashionedRestrictions );
+ } else {
+ $title_protection = $this->getTitleProtection();
+
+ if (is_array($title_protection)) {
+ extract($title_protection);
+
+ $now = wfTimestampNow();
+ $expiry = Block::decodeExpiry($pt_expiry);
+
+ if (!$expiry || $expiry > $now) {
+ // Apply the restrictions
+ $this->mRestrictionsExpiry = $expiry;
+ $this->mRestrictions['create'] = explode(',', trim($pt_create_perm) );
+ } else { // Get rid of the old restrictions
+ Title::purgeExpiredRestrictions();
+ }
+ }
+ $this->mRestrictionsLoaded = true;
+ }
}
}
$dbw->delete( 'page_restrictions',
array( 'pr_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ),
__METHOD__ );
+
+ $dbw->delete( 'protected_titles',
+ array( 'pt_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ),
+ __METHOD__ );
}
/**
* @return array the array of groups allowed to edit this article
*/
public function getRestrictions( $action ) {
- if( $this->exists() ) {
- if( !$this->mRestrictionsLoaded ) {
- $this->loadRestrictions();
- }
- return isset( $this->mRestrictions[$action] )
- ? $this->mRestrictions[$action]
- : array();
- } else {
- return array();
+ if( !$this->mRestrictionsLoaded ) {
+ $this->loadRestrictions();
}
+ return isset( $this->mRestrictions[$action] )
+ ? $this->mRestrictions[$action]
+ : array();
}
/**
# Initialisation
static $rxTc = false;
if( !$rxTc ) {
- # % is needed as well
- $rxTc = '/[^' . Title::legalChars() . ']|%[0-9A-Fa-f]{2}/S';
+ # Matching titles will be held as illegal.
+ $rxTc = '/' .
+ # Any character not allowed is forbidden...
+ '[^' . Title::legalChars() . ']' .
+ # URL percent encoding sequences interfere with the ability
+ # to round-trip titles -- you can't link to them consistently.
+ '|%[0-9A-Fa-f]{2}' .
+ # XML/HTML character references produce similar issues.
+ '|&[A-Za-z0-9\x80-\xff]+;' .
+ '|&#[0-9]+;' .
+ '|&#x[0-9A-Fa-f]+;' .
+ '/S';
}
$this->mInterwiki = $this->mFragment = '';
return 'protectedpage';
}
+ global $wgUser;
+ $err = null;
+ if( !wfRunHooks( 'AbortMove', array( $this, $nt, $wgUser, &$err ) ) ) {
+ return 'hookaborted';
+ }
+
# The move is allowed only if (1) the target doesn't exist, or
# (2) the target is a redirect to the source, and has no history
# (so we can undo bad moves right after they're done).
if ( ! $this->isValidMoveTarget( $nt ) ) {
return 'articleexists';
}
+ } else {
+ $tp = $nt->getTitleProtection();
+ if ( $tp and !$wgUser->isAllowed( $tp['pt_create_perm'] ) ) {
+ return 'cantmove-titleprotected';
+ }
}
return true;
}
* @param bool $auth indicates whether $wgUser's permissions
* should be checked
* @param string $reason The reason for the move
- * @param bool $createRedirect Whether to create a redirect from the old title to the new title
+ * @param bool $createRedirect Whether to create a redirect from the old title to the new title.
+ * Ignored if the user doesn't have the suppressredirect right.
* @return mixed true on success, message name on failure
*/
public function moveTo( &$nt, $auth = true, $reason = '', $createRedirect = true ) {
}
if( $u )
$u->doUpdate();
+ # Update message cache for interface messages
+ if( $nt->getNamespace() == NS_MEDIAWIKI ) {
+ global $wgMessageCache;
+ $newarticle = new Article( $nt );
+ $wgMessageCache->replace( $nt->getDBkey(), $newarticle->getContent() );
+ }
global $wgUser;
wfRunHooks( 'TitleMoveComplete', array( &$this, &$nt, &$wgUser, $pageid, $redirid ) );
* @param Title &$nt the page to move to, which should currently
* be a redirect
* @param string $reason The reason for the move
- * @param bool $createRedirect Whether to leave a redirect at the old title
+ * @param bool $createRedirect Whether to leave a redirect at the old title.
+ * Ignored if the user doesn't have the suppressredirect right
*/
private function moveOverExistingRedirect( &$nt, $reason = '', $createRedirect = true ) {
- global $wgUseSquid;
+ global $wgUseSquid, $wgUser;
$fname = 'Title::moveOverExistingRedirect';
$comment = wfMsgForContent( '1movedto2_redir', $this->getPrefixedText(), $nt->getPrefixedText() );
$linkCache->clearLink( $nt->getPrefixedDBkey() );
# Recreate the redirect, this time in the other direction.
- if($createRedirect)
+ if($createRedirect || !$wgUser->isAllowed('suppressredirect'))
{
$mwRedir = MagicWord::get( 'redirect' );
$redirectText = $mwRedir->getSynonym( 0 ) . ' [[' . $nt->getPrefixedText() . "]]\n";
* @param Title &$nt the new Title
* @param string $reason The reason for the move
* @param bool $createRedirect Whether to create a redirect from the old title to the new title
+ * Ignored if the user doesn't have the suppressredirect right
*/
private function moveToNewTitle( &$nt, $reason = '', $createRedirect = true ) {
- global $wgUseSquid;
+ global $wgUseSquid, $wgUser;
$fname = 'MovePageForm::moveToNewTitle';
$comment = wfMsgForContent( '1movedto2', $this->getPrefixedText(), $nt->getPrefixedText() );
if ( $reason ) {
$linkCache->clearLink( $nt->getPrefixedDBkey() );
- if($createRedirect)
+ if($createRedirect || !$wgUser->isAllowed('suppressredirect'))
{
# Insert redirect
$mwRedir = MagicWord::get( 'redirect' );
* @return bool
*/
public function isAlwaysKnown() {
+ // If the page is form Mediawiki:message/lang, calling wfMsgWeirdKey causes
+ // the full l10n of that language to be loaded. That takes much memory and
+ // isn't needed. So we strip the language part away.
+ // Also, extension messages which are not loaded, are shown as red, because
+ // we don't call MessageCache::loadAllMessages.
+ list( $basename, /* rest */ ) = explode( '/', $this->mDbkeyform, 2 );
return $this->isExternal()
|| ( $this->mNamespace == NS_MAIN && $this->mDbkeyform == '' )
- || ( $this->mNamespace == NS_MEDIAWIKI && wfMsgWeirdKey( $this->mDbkeyform ) );
+ || ( $this->mNamespace == NS_MEDIAWIKI && wfMsgWeirdKey( $basename ) );
}
/**
}
}
-
-