code for ApiBase::parseMsg() will no longer work.
* ApiBase::$messageMap is no longer public. Code attempting to access it will
result in a PHP fatal error.
-* $wgUserEmailUseReplyTo is now false by default to work around restrictive DMARC policies.
+* $wgUserEmailUseReplyTo is now true by default to work around restrictive DMARC policies.
=== New features in 1.29 ===
* (T5233) A cookie can now be set when a user is autoblocked, to track that user if
'Collation' => __DIR__ . '/includes/collation/Collation.php',
'CollationCkb' => __DIR__ . '/includes/collation/CollationCkb.php',
'CollationEt' => __DIR__ . '/includes/collation/CollationEt.php',
+ 'CollationFa' => __DIR__ . '/includes/collation/CollationFa.php',
'CommandLineInc' => __DIR__ . '/maintenance/commandLine.inc',
'CommandLineInstaller' => __DIR__ . '/maintenance/install.php',
'CompareParserCache' => __DIR__ . '/maintenance/compareParserCache.php',
'VFormHTMLForm' => __DIR__ . '/includes/htmlform/VFormHTMLForm.php',
'ValidateRegistrationFile' => __DIR__ . '/maintenance/validateRegistrationFile.php',
'ViewAction' => __DIR__ . '/includes/actions/ViewAction.php',
+ 'ViewCLI' => __DIR__ . '/maintenance/view.php',
'VirtualRESTService' => __DIR__ . '/includes/libs/virtualrest/VirtualRESTService.php',
'VirtualRESTServiceClient' => __DIR__ . '/includes/libs/virtualrest/VirtualRESTServiceClient.php',
'WANObjectCache' => __DIR__ . '/includes/libs/objectcache/WANObjectCache.php',
$pageLang = $title->getPageLanguage()->getCode();
if ( $config->get( 'PageLanguageUseDB' )
- && $this->getTitle()->userCan( 'pagelang', $this->getUser() )
+ && $title->userCan( 'pagelang', $user )
) {
// Link to Special:PageLanguage with pre-filled page title if user has permissions
$titleObj = SpecialPage::getTitleFor( 'PageLanguage', $title->getPrefixedText() );
// Content model of the page
$modelHtml = htmlspecialchars( ContentHandler::getLocalizedName( $title->getContentModel() ) );
// If the user can change it, add a link to Special:ChangeContentModel
- if ( $title->quickUserCan( 'editcontentmodel' ) ) {
+ if ( $config->get( 'ContentHandlerUseDB' )
+ && $title->userCan( 'editcontentmodel', $user )
+ ) {
$modelHtml .= ' ' . $this->msg( 'parentheses' )->rawParams( $linkRenderer->makeLink(
SpecialPage::getTitleValueFor( 'ChangeContentModel', $title->getPrefixedText() ),
$this->msg( 'pageinfo-content-model-change' )->text()
}
$expiry = $title->getRestrictionExpiry( $restrictionType );
$formattedexpiry = $this->msg( 'parentheses',
- $this->getLanguage()->formatExpiry( $expiry ) )->escaped();
+ $lang->formatExpiry( $expiry ) )->escaped();
$message .= $this->msg( 'word-separator' )->escaped() . $formattedexpiry;
// Messages: restriction-edit, restriction-move, restriction-create,
return new CollationCkb;
case 'xx-uca-et':
return new CollationEt;
+ case 'xx-uca-fa':
+ return new CollationFa;
default:
$match = [];
if ( preg_match( '/^uca-([a-z@=-]+)$/', $collationName, $match ) ) {
--- /dev/null
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Temporary workaround for incorrect collation of Persian language ('fa') in ICU (bug T139110).
+ *
+ * 'ا' and 'و' should not be considered the same letter for the purposes of collation in Persian.
+ *
+ * @since 1.29
+ */
+class CollationFa extends IcuCollation {
+ private $tertiaryCollator;
+
+ public function __construct() {
+ parent::__construct( 'fa' );
+ $this->tertiaryCollator = Collator::create( 'fa' );
+ }
+
+ public function getPrimarySortKey( $string ) {
+ $firstLetter = mb_substr( $string, 0, 1 );
+ if ( $firstLetter === 'و' || $firstLetter === 'ا' ) {
+ return $this->tertiaryCollator->getSortKey( $string );
+ }
+
+ return parent::getPrimarySortKey( $string );
+ }
+}
*/
public static function getHTML( $e ) {
if ( self::showBackTrace( $e ) ) {
- $html = "<div class=\"errorbox\"><p>" .
+ $html = "<div class=\"errorbox mw-content-ltr\"><p>" .
nl2br( htmlspecialchars( MWExceptionHandler::getLogMessage( $e ) ) ) .
'</p><p>Backtrace:</p><p>' .
nl2br( htmlspecialchars( MWExceptionHandler::getRedactedTraceAsString( $e ) ) ) .
"</p></div>\n";
} else {
$logId = WebRequest::getRequestId();
- $html = "<div class=\"errorbox\">" .
+ $html = "<div class=\"errorbox mw-content-ltr\">" .
'[' . $logId . '] ' .
gmdate( 'Y-m-d H:i:s' ) . ": " .
self::msg( "internalerror-fatal-exception",
const MAX_ALLOWED_LAG = 3; // abort if more than this much DB lag is present
const LAG_CHECK_PERIOD = 1.0; // check replica DB lag this many seconds
const ERROR_BACKOFF_TTL = 1; // seconds to back off a queue due to errors
+ const READONLY_BACKOFF_TTL = 30; // seconds to back off a queue due to read-only errors
/**
* @param callable $debug Optional debug output handler
// Back off of certain jobs for a while (for throttling and for errors)
if ( $info['status'] === false && mt_rand( 0, 49 ) == 0 ) {
- $ttw = max( $ttw, self::ERROR_BACKOFF_TTL ); // too many errors
+ $ttw = max( $ttw, $this->getErrorBackoffTTL( $info['error'] ) );
$backoffDeltas[$jType] = isset( $backoffDeltas[$jType] )
? $backoffDeltas[$jType] + $ttw
: $ttw;
return $response;
}
+ /**
+ * @param string $error
+ * @return int TTL in seconds
+ */
+ private function getErrorBackoffTTL( $error ) {
+ return strpos( $error, 'DBReadOnlyError' ) !== false
+ ? self::READONLY_BACKOFF_TTL
+ : self::ERROR_BACKOFF_TTL;
+ }
+
/**
* @param Job $job
* @param LBFactory $lbFactory
// Add the envelope sender address using the -f command line option when PHP mail() is used.
// Will default to the $from->address when the UserMailerChangeReturnPath hook fails and the
// generated VERP address when the hook runs effectively.
- $extraParams .= ' -f ' . $returnPath;
+
+ // PHP runs this through escapeshellcmd(). However that's not sufficient
+ // escaping (e.g. due to spaces). MediaWiki's email sanitizer should generally
+ // be good enough, but just in case, put in double quotes, and remove any
+ // double quotes present (" is not allowed in emails, so should have no
+ // effect, although this might cause apostrophees to be double escaped)
+ $returnPathCLI = '"' . str_replace( '"', '', $returnPath ) . '"';
+ $extraParams .= ' -f ' . $returnPathCLI;
$headers['Return-Path'] = $returnPath;
public function execute( $par = '' ) {
$this->getOutput()->disable();
if ( wfReadOnly() ) {
- // HTTP 423 Locked
- HttpStatus::header( 423 );
- print 'Wiki is in read-only mode';
-
+ wfHttpError( 423, 'Locked', 'Wiki is in read-only mode.' );
return;
} elseif ( !$this->getRequest()->wasPosted() ) {
- HttpStatus::header( 400 );
- print 'Request must be POSTed';
+ wfHttpError( 400, 'Bad Request', 'Request must be POSTed.' );
return;
}
$params = array_intersect_key( $this->getRequest()->getValues(), $required + $optional );
$missing = array_diff_key( $required, $params );
if ( count( $missing ) ) {
- HttpStatus::header( 400 );
- print 'Missing parameters: ' . implode( ', ', array_keys( $missing ) );
+ wfHttpError( 400, 'Bad Request',
+ 'Missing parameters: ' . implode( ', ', array_keys( $missing ) )
+ );
return;
}
$verified = is_string( $providedSignature )
&& hash_equals( $correctSignature, $providedSignature );
if ( !$verified || $params['sigexpiry'] < time() ) {
- HttpStatus::header( 400 );
- print 'Invalid or stale signature provided';
+ wfHttpError( 400, 'Bad Request', 'Invalid or stale signature provided.' );
return;
}
public function execute( $par ) {
$user = $this->getUser();
$request = $this->getRequest();
+ $session = $request->getSession();
$out = $this->getOutput();
if ( $par !== null ) {
}
// show a successbox, if the user rights was saved successfully
- if ( $request->getCheck( 'success' ) && $this->mFetchedUser !== null ) {
+ if (
+ $session->get( 'specialUserrightsSaveSuccess' ) &&
+ $this->mFetchedUser !== null
+ ) {
+ // Remove session data for the success message
+ $session->remove( 'specialUserrightsSaveSuccess' );
+
$out->addModules( [ 'mediawiki.special.userrights' ] );
$out->addModuleStyles( 'mediawiki.notification.convertmessagebox.styles' );
$out->addHTML(
$targetUser
);
+ // Set session data for the success message
+ $session->set( 'specialUserrightsSaveSuccess', 1 );
+
$out->redirect( $this->getSuccessURL() );
return;
}
function getSuccessURL() {
- return $this->getPageTitle( $this->mTarget )->getFullURL( [ 'success' => 1 ] );
+ return $this->getPageTitle( $this->mTarget )->getFullURL();
}
/**
"restrictionsfield-badip": "Invalid IP address or range: $1",
"restrictionsfield-label": "Allowed IP ranges:",
"restrictionsfield-help": "One IP address or CIDR range per line. To enable everything, use<br><code>0.0.0.0/0</code><br><code>::/0</code>",
- "revid": "r$1",
+ "revid": "revision $1",
"pageid": "page ID $1"
}
--- /dev/null
+<?php
+/**
+ * Show page contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+require_once __DIR__ . '/Maintenance.php';
+
+/**
+ * Maintenance script to show page contents.
+ *
+ * @ingroup Maintenance
+ */
+class ViewCLI extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->addDescription( 'Show article contents on the command line' );
+ $this->addArg( 'title', 'Title of article to view' );
+ }
+
+ public function execute() {
+ $title = Title::newFromText( $this->getArg() );
+ if ( !$title ) {
+ $this->error( "Invalid title", true );
+ }
+
+ $page = WikiPage::factory( $title );
+
+ $content = $page->getContent( Revision::RAW );
+ if ( !$content ) {
+ $this->error( "Page has no content", true );
+ }
+ if ( !$content instanceof TextContent ) {
+ $this->error( "Non-text content models not supported", true );
+ }
+
+ $this->output( $content->getNativeData() );
+ }
+}
+
+$maintClass = "ViewCLI";
+require_once RUN_MAINTENANCE_IF_MAIN;