Merge "rdbms: Fix incomplete doc for DatabaseMssql::tableName()"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 26 Mar 2019 18:41:05 +0000 (18:41 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 26 Mar 2019 18:41:05 +0000 (18:41 +0000)
66 files changed:
.gitignore
.phpcs.xml
HISTORY
RELEASE-NOTES-1.33
autoload.php
includes/Block.php
includes/DefaultSettings.php
includes/ForeignResourceManager.php
includes/GlobalFunctions.php
includes/Linker.php
includes/OutputPage.php
includes/Title.php
includes/actions/pagers/HistoryPager.php
includes/api/ApiQueryRevisionsBase.php
includes/api/i18n/he.json
includes/api/i18n/ja.json
includes/block/BlockRestriction.php
includes/changetags/ChangeTags.php
includes/context/RequestContext.php
includes/db/DatabaseOracle.php
includes/db/MWLBFactory.php
includes/htmlform/HTMLForm.php
includes/htmlform/HTMLFormField.php
includes/htmlform/OOUIHTMLForm.php
includes/installer/i18n/pms.json
includes/libs/rdbms/lbfactory/LBFactory.php
includes/libs/rdbms/lbfactory/LBFactoryMulti.php
includes/logging/LogEntry.php
includes/objectcache/ObjectCache.php
includes/poolcounter/PoolCounter.php
includes/poolcounter/PoolCounterNull.php [new file with mode: 0644]
includes/rcfeed/RedisPubSubFeedEngine.php
includes/registration/ExtensionProcessor.php
includes/registration/Processor.php
includes/specialpage/QueryPage.php
languages/i18n/az.json
languages/i18n/be-tarask.json
languages/i18n/bg.json
languages/i18n/bn.json
languages/i18n/diq.json
languages/i18n/et.json
languages/i18n/fa.json
languages/i18n/fr.json
languages/i18n/fy.json
languages/i18n/ga.json
languages/i18n/gcr.json
languages/i18n/he.json
languages/i18n/hr.json
languages/i18n/hu.json
languages/i18n/io.json
languages/i18n/mk.json
languages/i18n/ms.json
languages/i18n/nan.json
maintenance/dictionary/mediawiki.dic
maintenance/dumpTextPass.php
maintenance/manageForeignResources.php [new file with mode: 0644]
maintenance/resources/foreign-resources.yaml [deleted file]
maintenance/resources/manageForeignResources.php [deleted file]
resources/Resources.php
resources/lib/foreign-resources.yaml [new file with mode: 0644]
resources/src/mediawiki.feedback/feedback.css
resources/src/mediawiki.feedback/feedback.js
resources/src/mediawiki.feedback/images/spinner.gif [deleted file]
resources/src/mediawiki.widgets.visibleLengthLimit/mediawiki.widgets.visibleLengthLimit.js
tests/phpunit/includes/cache/MessageCacheTest.php
tests/selenium/specs/page.js

index def5a08..8cacb1e 100644 (file)
@@ -50,6 +50,7 @@ sftp-config.json
 # Building & testing
 npm-debug.log
 node_modules/
+/resources/lib/.foreign
 /tests/phpunit/phpunit.phar
 /tests/selenium/log
 .eslintcache
index 6934648..d1e54a7 100644 (file)
                <exclude-pattern>*/includes/parser/Preprocessor_Hash\.php</exclude-pattern>
                <exclude-pattern>*/includes/parser/Preprocessor\.php</exclude-pattern>
                <exclude-pattern>*/includes/PathRouter\.php</exclude-pattern>
-               <exclude-pattern>*/includes/poolcounter/PoolCounter\.php</exclude-pattern>
                <exclude-pattern>*/includes/PrefixSearch\.php</exclude-pattern>
                <exclude-pattern>*/includes/profiler/SectionProfiler\.php</exclude-pattern>
                <exclude-pattern>*/includes/search/SearchEngine\.php</exclude-pattern>
diff --git a/HISTORY b/HISTORY
index a926069..d00da92 100644 (file)
--- a/HISTORY
+++ b/HISTORY
@@ -2,6 +2,25 @@ Change notes from older releases. For current info see RELEASE-NOTES-1.33.
 
 = MediaWiki 1.32 =
 
+== MediaWiki 1.32.1 ==
+
+=== Changes since MediaWiki 1.32.0 ===
+* (T213577) rdbms: avoid transaction status errors from ping() in rollback().
+* rdbms: Pass required parameter.
+* rdbms: do not treat SAVEPOINT and RELEASE SAVEPOINT as write queries.
+* (T204531) rdbms: reduce LoadBalancer replication log spam.
+* (T213489) Avoid session double-start in Setup.php.
+* (T213717) Correct namespace 'Template' for gom-deva
+* (T198054) Fix login page crash caused by unknown language via ?uselang
+* (T215324) (T210937) list=users mistakenly reports user as missing.
+* (T209483) Add ILBFactory::redefineLocalDomain method. This is intended for
+use with scripts like addWiki.php to avoid mismatched domain errors.
+* (T208871) The hard-coded Google search form on the database error page was
+removed.
+* (T204800) Fix Title::getFragmentForURL for bad interwiki prefix
+* (T215566) Fix installer being unable to determine if the database exists
+during a fresh installation.
+
 == MediaWiki 1.32.0 ==
 
 === Changes since MediaWiki 1.32.0-rc.2 ===
@@ -4785,6 +4804,11 @@ of files that are no longer available follows.
 
 = MediaWiki 1.23 =
 
+== MediaWiki 1.23.17 ==
+
+=== Changes since 1.23.16 === <!--T:69-->
+* Fix syntax errors introduced in 1.23.16 when running PHP 5.3.
+
 == MediaWiki 1.23.16 ==
 This is a security and maintenance release of the MediaWiki 1.23 branch.
 
@@ -7044,6 +7068,52 @@ changes to languages because of Bugzilla reports.
 
 == MediaWiki 1.19 ==
 
+== MediaWiki 1.19.24 ==
+
+This is a security and maintenance release of the MediaWiki 1.19 branch.
+
+=== Changes since 1.19.23 ===
+
+* ({{bug|T85848}}, {{bug|T71210}}) SECURITY: Don't parse XMP blocks that
+contain XML entities, to prevent various DoS attacks.
+* ({{bug|T88310}}) SECURITY: Always expand xml entities when checking SVG's.
+* ({{bug|T73394}}) SECURITY: Escape > in Html::expandAttributes to prevent XSS.
+* ({{bug|T85855}}) SECURITY: Don't execute another user's CSS or JS on preview.
+* ({{bug|T85349}}, {{bug|T85850}}, {{bug|T86711}}) SECURITY: Multiple issues
+fixed in SVG filtering to prevent XSS and protect viewer's privacy.
+
+== MediaWiki 1.19.23 ==
+
+This is a security and maintenance release of the MediaWiki 1.19 branch.
+
+=== Changes since 1.19.22 ===
+
+* (bug T76686) [SECURITY] thumb.php outputs wikitext message as raw HTML, which
+could lead to xss. Permission to edit MediaWiki namespace is required to
+exploit this.
+* (bug T74222) The original patch for T74222 was reverted as unnecessary.
+* Add missing $ in front of variable in OutputPage.php
+
+== MediaWiki 1.19.22 ==
+
+This is a security and maintenance release of the MediaWiki 1.19 branch.
+
+=== Changes since 1.19.21 ===
+
+* ({{bug|66776}}, {{bug|71478}}) SECURITY:  User PleaseStand reported a way to
+inject code into API clients that used format=php to process pages that
+underwent flash policy mangling. This was fixed along with improving how the
+mangling was done for format=json, and allowing sites to disable the mangling
+using $wgMangleFlashPolicy.
+* ({{bug|72222}}) SECURITY: Do not show log action when the entry is revdeleted
+with DELETED_ACTION. NOTICE: this may be reverted in a future release pending a
+public RFC about the desired functionality. This issue was reported by user
+Bawolff.
+* ({{bug|71621}}) Make allowing site-wide styles on restricted special pages a
+config option.
+* $wgMangleFlashPolicy was added to make MediaWiki's mangling of anything that
+might be a flash policy directive configurable.
+
 == MediaWiki 1.19.21 ==
 This is a maintenance release of the MediaWiki 1.19 branch.
 
@@ -7618,6 +7688,20 @@ changes to languages because of Bugzilla reports.
 
 == MediaWiki 1.18 ==
 
+== MediaWiki 1.18.6 ==
+2012-11-29
+
+This is a maintenance and security release of the MediaWiki 1.18 branch
+
+=== Changes since 1.18.5 ===
+* ([[bugzilla:40995|bug 40995]]) Prevent session fixation in Special:UserLogin
+(CVE-2012-5391)
+* ([[bugzilla:41400|bug 41400]]) Prevent linker regex from exceeding PCRE
+backtrack limit
+* Localisation updates
+* Increase permitted runtime for testParserTest
+* ([[bugzilla:36179|bug 36179]]) Unquote 'null' for PostgreSQL.
+
 == MediaWiki 1.18.5 ==
 2012-08-30
 
@@ -11341,6 +11425,43 @@ regularly. Below only new and removed languages are listed.
 
 == MediaWiki 1.13 ==
 
+== MediaWiki 1.13.5 ==
+
+February 22, 2009
+
+This is a maintenance update to the Summer 2008 snapshot release of MediaWiki.
+
+MediaWiki is now using a "continuous integration" development model with
+quarterly snapshot releases. The latest development code is always kept
+"ready to run", and in fact runs our own sites on Wikipedia.
+
+Release branches will continue to receive security updates for about a year
+from first release, but nonessential bugfixes and feature developments
+will be made on the development trunk and appear in the next quarterly release.
+
+Those wishing to use the latest code instead of a branch release can obtain
+it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
+
+== Changes since 1.13.4 ==
+
+* (bug 17449) Fixed PostgreSQL installation
+* (bug 17527) Fixed missing MySQL-specific options in installer
+
+== Changes since 1.13.3 ==
+
+A number of cross-site scripting (XSS) security vulnerabilities were discovered
+in the web-based installer (config/index.php). These vulnerabilities all
+require a live installer -- once the installer has been used to install a wiki,
+it is deactivated.
+
+Note that cross-site scripting vulnerabilities can be used to attack any website
+in the same cookie domain. So if you have an uninstalled copy of MediaWiki on
+the same site as an active web service, MediaWiki could be used to attack the
+active service.
+
+If you are hosting an old copy of MediaWiki that you have never installed, you
+are advised to remove it from the web.
+
 == Changes since 1.13.2 ==
 
 David Remahl of Apple's Product Security team has identified a number of
@@ -11983,9 +12104,143 @@ Other changes in this release:
   the page
 * list=exturlusage in "list all links" mode can now filter by protocol
 
+== MediaWiki 1.12 ==
 
+== MediaWiki 1.12.4 ==
 
-== MediaWiki 1.12 ==
+February 7, 2009
+
+A number of cross-site scripting (XSS) security vulnerabilities were discovered
+in the web-based installer (config/index.php). These vulnerabilities all
+require a live installer -- once the installer has been used to install a wiki,
+it is deactivated.
+
+Note that cross-site scripting vulnerabilities can be used to attack any
+website in the same cookie domain. So if you have an uninstalled copy of
+MediaWiki on the same site as an active web service, MediaWiki could be used to
+attack the active service.
+
+If you are hosting an old copy of MediaWiki that you have never installed, you
+are advised to remove it from the web.
+
+== MediaWiki 1.12.3 ==
+
+* Fixed packaging/distribution error. Many files were missing from the
+distributed tarball.
+
+== MediaWiki 1.12.2 ==
+
+David Remahl of Apple's Product Security team has identified a number of
+security issues in previous releases of MediaWiki. Subsequent analysis by the
+MediaWiki development team expanded the scope of these vulnerabilities. The
+issues with a significant impact are as follows:
+
+* A local script injection vulnerability affecting Internet Explorer clients
+for all MediaWiki installations with uploads enabled. [CVE-2008-5250]
+* A local script injection vulnerability affecting clients with SVG scripting
+capability (such as Firefox 1.5+), for all MediaWiki installations with SVG
+uploads enabled. [CVE-2008-5250]
+* A CSRF vulnerability affecting the Special:Import feature, for all MediaWiki
+installations since the feature was introduced in 1.3.0. [CVE-2008-5252]
+
+A local script injection vulnerability allows an attacker with a wiki account
+to steal another user's login session, and to act as that user on the wiki. The
+attacker uploads a malicious script file, and tricks the victim into executing
+it.
+
+CSRF vulnerabilities allow an attacker to act as an authorised user on the
+wiki, but unlike an XSS vulnerability, the attacker can only act as the user in
+a specific and restricted way. The present CSRF vulnerability allows pages to
+be edited, with forged revision histories. Like an XSS vulnerability, the
+authorised user must visit the malicious web page to activate the attack.
+
+These three vulnerabilities are all fixed in this release.
+
+David Remahl also reminded us of some security-related configuration issues:
+
+* By default, MediaWiki stores a backup of deleted images in the images/deleted
+directory. If you do not want these images to be publically accessible, make
+sure this directory is not accessible from the web. MediaWiki takes some steps
+to avoid leaking these images, but these measures are not perfect.
+* Set display_errors=off in your php.ini to avoid path disclosure via PHP fatal
+errors. This is the default on most shared web hosts.
+* Enabling MediaWiki's debugging features, such as $wgShowExceptionDetails, may
+lead to path disclosure.
+
+Other changes in this release:
+
+* Avoid fatal error in profileinfo.php when not configured.
+* Add a .htaccess to deleted images directory for additional protection against
+exposure of deleted files with known SHA-1 hashes on default installations.
+* Avoid streaming uploaded files to the user via index.php. This allows
+security-conscious users to serve uploaded files via a different domain, and
+thus client-side scripts executed from that domain cannot access the login
+cookies. Affects Special:Undelete, img_auth.php and thumb.php.
+* When streaming files via index.php, use the MIME type detected from the file
+extension, not from the data. This reduces the XSS attack surface.
+* Blacklist redirects via Special:Filepath. Such redirects exacerbate any XSS
+vulnerabilities involving uploads of files containing scripts.
+* Internationalisation updates.
+
+== MediaWiki 1.12.1 ==
+
+Changes since 1.12.0:
+* (bug [[bugzilla:13522|13522]]) Fix fatal error in Parser::extractTagsAndParams
+* (bug [[bugzilla:12077|12077]]) Fix HTML nesting for TOC
+* (bug [[bugzilla:13532|13532]]) Use proper timestamp call when reverting images
+* (bug [[bugzilla:13649|13649]], [[bugzilla:14084|14084]]) Bad call to
+wfTimestamp()
+* (bug [[bugzilla:13770|13770]]) Use Preprocessor_Hash by default to avoid
+missing DOM module errors
+* (bug [[bugzilla:13442|13442]]) API: Missing pages in prop=langlinks and
+prop=extlinks are now handled properly.
+* (bug [[bugzilla:13482|13482]]) API: Disabled search types handled properly
+* (bug [[bugzilla:13836|13836]]) API: Fixed fatal errors resulting from
+combining iiprop=metadata  with format=xml
+* (bug [[bugzilla:11633|11633]]) API: Explicitly convert redirect titles to
+strings due to PHP's very weak typing on array keys.
+* API: Fixing main page display in meta=siteinfo
+* (bug [[bugzilla:11719|11719]]) API: Remove trailing blanks in YAML output.
+* (bug [[bugzilla:13718|13718]]) API: Return the proper continue parameter for
+cmsort=timestamp
+* Security: Work around misconfiguration by requiring strict comparisons for
+in_array in User::isAllowed().
+* Security: Fixed XSS vulnerability in useskin parameter.
+
+== MediaWiki 1.12.0 ==
+
+This is the quarterly branch release of [[MediaWiki]] for Winter 2008.
+
+MediaWiki is now using a "continuous integration" development model with
+quarterly snapshot releases. The latest development code is always kept "ready
+to run", and in fact runs our own sites on [[wikipedia:|Wikipedia]].
+
+Release branches will continue to receive security updates for about a year
+from first release, but nonessential bugfixes and feature developments will be
+made on the development trunk and appear in the next quarterly release.
+
+Those wishing to use the latest code instead of a branch release can obtain it
+from source control: [[Download from SVN]].
+
+Changes since 1.12.0rc1:
+*(bug [[bugzilla:13359|13359]]) Double-escaping in [[Special:Allpages]].
+*Localization updates.
+
+== MediaWiki 1.12.0rc1 ==
+
+This is a release candidate of the Winter 2008 quarterly snapshot release of
+[[MediaWiki]].
+
+MediaWiki is now using a "continuous integration" development model with
+quarterly snapshot releases. The latest development code is always kept "ready
+to run", and in fact runs our own sites on [[wikipedia:|Wikipedia]].
+
+Release branches will continue to receive security updates for about a year
+from first release, but nonessential bugfixes and feature developments will be
+made on the development trunk and appear in the next quarterly release.
+
+Those wishing to use the latest code instead of a branch release can obtain it
+from source control: [[Download from SVN]].
 
 This is the Winter 2007 quarterly release.
 
@@ -12539,6 +12794,76 @@ Full API documentation is available at https://www.mediawiki.org/wiki/API
 
 == MediaWiki 1.11 ==
 
+== MediaWiki 1.11.2 ==
+
+March 2, 2008
+
+This is a security release of the Fall 2007 snapshot release of MediaWiki.
+Possible cross-site information leaks using the callback parameter for
+JSON-formatted results in the API are prevented by dropping user credentials.
+
+MediaWiki release versions prior to 1.11 are not vulnerable, as they do not
+include the callback feature which allows client-side JavaScript on other sites
+to reach API data.
+
+Changes in this release:
+
+* User credentials are dropped for API JSON requests using a callback
+* Edit tokens are not reported for API JSON requests using a callback
+
+== MediaWiki 1.11.1 ==
+
+January 23, 2008
+
+This is a security and bugfix release of the Fall 2007 snapshot release of
+ MediaWiki. A potential XSS injection vector affecting api.php only for
+ Microsoft Internet Explorer users has been closed.
+
+Changes in this release:
+* (bug [[bugzilla:11450|11450]]) Fix creation of objectcache table on upgrade
+* (bug [[bugzilla:11462|11462]]) Fix typo in LanguageGetSpecialPageAliases hook
+name
+* Fix regression in LinkBatch.php breaking PHP 5.0
+* Security fix for API on MSIE
+
+To work around the vulnerability without upgrading, you may disable the API if
+you don't need it:
+:[[Manual:$wgEnableAPI|$wgEnableAPI]] = false;
+
+Not vulnerable versions:
+* 1.12 or later
+* 1.11 >= 1.11.1
+* 1.10 >= 1.10.3
+* 1.9 >= 1.9.5
+* 1.8 any version (if $wgEnableAPI has been left off)
+
+Vulnerable versions:
+* 1.11 <= 1.11.0rc1
+* 1.10 <= 1.10.2
+* 1.9 <= 1.9.4
+* 1.8 any version (if $wgEnableAPI has been switched on)
+
+MediaWiki 1.7 and below are not affected as they do not include the API
+functionality, however the BotQuery extension is similarly vulnerable unless
+updated to the latest SVN version.
+
+== MediaWiki 1.11.0 ==
+
+September 10, 2007
+
+This is the Fall 2007 snapshot release of MediaWiki.
+
+MediaWiki is now using a "continuous integration" development model with
+quarterly snapshot releases. The latest development code is always kept "ready
+to run", and in fact runs our own sites on Wikipedia.
+
+Release branches will continue to receive security updates for about a year
+from first release, but nonessential bugfixes and feature developments will be
+made on the development trunk and appear in the next quarterly release.
+
+Those wishing to use the latest code instead of a branch release can obtain it
+from source control: [[Download from SVN]]
+
 This is the Summer 2007 branch release of MediaWiki.
 
 MediaWiki is now using a "continuous integration" development model with
@@ -12552,6 +12877,33 @@ will be made on the development trunk and appear in the next quarterly release.
 Those wishing to use the latest code instead of a branch release can obtain
 it from source control: https://www.mediawiki.org/wiki/Download_from_SVN
 
+== Changes since 1.11.0rc1 ==
+
+A possible HTML/XSS injection vector in the API pretty-printing mode has been
+found and fixed.
+
+The vulnerability may be worked around in an unfixed version by simply
+disabling the API interface if it is not in use, by adding this to
+[[Manual:LocalSettings.php|LocalSettings.php]]:<br />
+<code>[[Manual:$wgEnableAPI|$wgEnableAPI]] = false;</code> <br />
+(This is the default setting in 1.8.x.)
+
+Not vulnerable versions:
+* 1.11 >= 1.11.0
+* 1.10 >= 1.10.2
+* 1.9 >= 1.9.4
+* 1.8 >= 1.8.5
+
+Vulnerable versions:
+* 1.11 <= 1.11.0rc1
+* 1.10 <= 1.10.1
+* 1.9 <= 1.9.3
+* 1.8 <= 1.8.4 (if [[Manual:$wgEnableAPI|$wgEnableAPI]] has been switched on)
+
+MediaWiki 1.7 and below are not affected as they do not include the faulty
+function, however the [[Extension:BotQuery|BotQuery extension]] is similarly
+vulnerable unless updated to the latest SVN version.
+
 == Configuration changes since 1.10 ==
 
 * $wgThumbUpright - Adjust width of upright images when parameter 'upright' is
@@ -12560,7 +12912,8 @@ it from source control: https://www.mediawiki.org/wiki/Download_from_SVN
   usergroups
 * $wgEnotifImpersonal, $wgEnotifUseJobQ - Bulk mail options for large sites
 * $wgShowHostnames - Expose server host names through the API and HTML comments
-* $wgSaveDeletedFiles has been removed, the feature is now enabled unconditionally
+* $wgSaveDeletedFiles has been removed, the feature is now enabled
+unconditionally
 
 == New features since 1.10 ==
 
@@ -13127,6 +13480,121 @@ Full API documentation is available at https://www.mediawiki.org/wiki/API
 
 == MediaWiki 1.10 ==
 
+== MediaWiki 1.10.4 ==
+
+March 2, 2008
+
+* Correction for API path fix, broken in 1.10.3
+
+== MediaWiki 1.10.3 ==
+
+January 23, 2008
+
+This is a security update to the Winter 2007 quarterly release. A potential
+XSS injection vector affecting api.php only for Microsoft Internet Explorer
+users has been closed.
+
+
+To work around the vulnerability without upgrading, you may disable the API if
+you don't need it:
+
+:[[Manual:$wgEnableAPI|$wgEnableAPI]] = false;
+
+Not vulnerable versions:
+* 1.12 or later
+* 1.11 >= 1.11.1
+* 1.10 >= 1.10.3
+* 1.9 >= 1.9.5
+* 1.8 any version (if $wgEnableAPI has been left off)
+
+Vulnerable versions:
+* 1.11 <= 1.11.0rc1
+* 1.10 <= 1.10.2
+* 1.9 <= 1.9.4
+* 1.8 any version (if $wgEnableAPI has been switched on)
+
+MediaWiki 1.7 and below are not affected as they do not include the API
+functionality, however the BotQuery extension is similarly vulnerable unless
+updated to the latest SVN version.
+
+== MediaWiki 1.10.2 ==
+September 10, 2007
+
+This is a security fix update to the Spring 2007 quarterly release snapshot. A
+possible HTML/XSS injection vector in the API pretty-printing mode has been
+found and fixed.
+
+The vulnerability may be worked around in an unfixed version by simply
+disabling the API interface if it is not in use, by adding this to
+LocalSettings.php:
+:[[Manual:$wgEnableAPI|$wgEnableAPI]] = false;
+
+Not vulnerable versions:
+* 1.11 >= 1.11.0
+* 1.10 >= 1.10.2
+* 1.9 >= 1.9.4
+* 1.8 >= 1.8.5
+
+Vulnerable versions:
+* 1.11 <= 1.11.0rc1
+* 1.10 <= 1.10.1
+* 1.9 <= 1.9.3
+* 1.8 <= 1.8.4 (if $wgEnableAPI has been switched on)
+
+MediaWiki 1.7 and below are not affected as they do not include the faulty
+function, however the BotQuery extension is similarly vulnerable unless updated
+to the latest SVN version.
+
+== MediaWiki 1.10.1 ==
+July 13, 2007
+
+This is a bugfix update to the Spring 2007 quarterly release snapshot. A number
+of fixes to improve compatibility with PostgreSQL, some versions of MySQL, and
+some PHP configurations are included.
+
+Changes since 1.10.0:
+
+* (bug [[bugzilla:9417|9417]]) Uploading new versions of images when using
+Postgres no longer  throws warnings.
+* (bug [[bugzilla:9908|9908]]) Using tsearch2 with Postgres 8.1 no longer gives
+an error.
+* (bug [[bugzilla:9973|9973]]) Changed size was shown in advanced recentchanges
+collapsible items with $wgRCShowChangedSized = false.
+* Fixed installation on MyISAM or old InnoDB with charset=utf8, was giving
+overlong key errors.
+* Fixed zero-padding issues with MySQL 5 binary schema
+* (bug [[bugzilla:9820|9820]]) session.save_path check no longer halts
+installation, but warns of possible bad values
+* (bug [[bugzilla:9978|9978]]) Fixed session.save_path validation when using
+extended configuration format, e.g. "5;/tmp"
+
+== MediaWiki 1.10.0 ==
+May 9, 2007
+
+This is the quarterly release snapshot for Spring 2007. See below for a full
+list of changes since the 1.9.x series.
+
+Changes since 1.10.0rc2:
+
+* (bug [[bugzilla:9808|9808]]) Fix regression that ignored user 'rclimit'
+option for Special:Contributions
+
+== MediaWiki 1.10.0rc2 ==
+May 4, 2007
+
+THIS IS A RELEASE CANDIDATE MADE AVAILABLE FOR TESTING!
+A FINAL 1.10.0 RELEASE WILL APPEAR WITHIN A FEW DAYS.
+
+Changes since 1.10.0rc1:
+* Various l10n fixes and updates
+* Fix for upgrade of page_restrictions table
+* (bug [[bugzilla:9780|9780]]) Fix normalization of titles with initial colon
+followed by whitespace
+* Fix for regression in upload: wrong size info saved into image table
+* Avoid cyclic stub problems when authorization hooks do funny things with the
+user and the database at load time
+
+== MediaWiki 1.10.0rc1 ==
 This is the Spring 2007 branch release of MediaWiki.
 
 MediaWiki is now using a "continuous integration" development model with
@@ -13616,10 +14084,159 @@ break. Don't forget to always back up your database before upgrading!
 See the file UPGRADE for more detailed upgrade instructions.
 
 = MediaWiki release notes =
-
 Security reminder: MediaWiki does not require PHP's register_globals
 setting since version 1.2.0. If you have it on, turn it *off* if you can.
 
+= MediaWiki 1.9 =
+
+== MediaWiki 1.9.6 ==
+
+March 2, 2008
+
+* Correction for API path fix, broken in 1.9.5
+
+== MediaWiki 1.9.5 ==
+
+January 23, 2008
+
+This is a security update to the Winter 2007 quarterly release. A potential XSS
+injection vector affecting api.php only for Microsoft Internet Explorer users
+has been closed.
+
+
+To work around the vulnerability without upgrading, you may disable the API if
+you don't need it:
+
+:[[Manual:$wgEnableAPI|$wgEnableAPI]] = false;
+
+Not vulnerable versions:
+* 1.12 or later
+* 1.11 >= 1.11.1
+* 1.10 >= 1.10.3
+* 1.9 >= 1.9.5
+* 1.8 any version (if $wgEnableAPI has been left off)
+
+Vulnerable versions:
+* 1.11 <= 1.11.0rc1
+* 1.10 <= 1.10.2
+* 1.9 <= 1.9.4
+* 1.8 any version (if $wgEnableAPI has been switched on)
+
+MediaWiki 1.7 and below are not affected as they do not include the API
+functionality, however the BotQuery extension is similarly vulnerable unless
+updated to the latest SVN version.
+
+== MediaWiki 1.9.4 ==
+
+September 10, 2007
+
+This is a security and bug fix update to the Winter 2007 quarterly release.
+Minor compatibility fixes for IIS 5 are included.
+
+* (bug [[bugzilla:8847|8847]]) Strip spurious #fragments from request URI to
+fix redirect loops on some server configurations
+* A possible HTML/XSS injection vector in the API pretty-printing mode has been
+found and fixed.
+
+The vulnerability may be worked around in an unfixed version by simply
+disabling the API interface if it is not in use, by adding this to
+LocalSettings.php:
+
+:[[Manual:$wgEnableAPI|$wgEnableAPI]] = false;
+
+Not vulnerable versions:
+* 1.11 >= 1.11.0
+* 1.10 >= 1.10.2
+* 1.9 >= 1.9.4
+* 1.8 >= 1.8.5
+
+Vulnerable versions:
+* 1.11 <= 1.11.0rc1
+* 1.10 <= 1.10.1
+* 1.9 <= 1.9.3
+* 1.8 <= 1.8.4 (if $wgEnableAPI has been switched on)
+
+MediaWiki 1.7 and below are not affected as they do not include the faulty
+function, however the BotQuery extension is similarly vulnerable unless updated
+to the latest SVN version.
+
+== MediaWiki 1.9.3 ==
+
+February 20, 2007
+
+This is a security and bug-fix update to the Winter 2007 quarterly release.
+Minor compatibility fixes for IIS and PostgreSQL are included.
+
+An XSS injection vulnerability based on Microsoft Internet Explorer's UTF-7
+charset autodetection was located in the AJAX support module, affecting MSIE
+users on MediaWiki 1.6.x and up when the optional setting $wgUseAjax is enabled.
+
+If you are using an extension based on the optional Ajax module, either disable
+it or upgrade to a version containing the fix:
+
+* 1.9: fixed in 1.9.3
+* 1.8: fixed in 1.8.4
+* 1.7: fixed in 1.7.3
+* 1.6: fixed in 1.6.10
+
+There is no known danger in the default configuration, with ''$wgUseAjax'' off.
+
+* ([[mediazilla:8992|8992]]) Fix a remaining raw use of REQUEST_URI in history
+* ([[mediazilla:8984|8984]]) Fix a database error in
+Special:Recentchangeslinked when using the PostgreSQL database.
+* Add ''charset'' to Content-Type headers on various HTTP error responses to
+forestall additional UTF-7-autodetect XSS issues. PHP sends only ''text/html''
+by default when the script didn't specify more details, which some
+inconsiderate browsers consider a license to autodetect the deadly,
+hard-to-escape UTF-7. This fixes an issue with the Ajax interface error message
+on MSIE when ''$wgUseAjax'' is enabled (not default configuration); this UTF-7
+variant on a previously fixed attack vector was discovered by Moshe BA from
+BugSec: [http://www.bugsec.com/articles.php?Security=24
+http://www.bugsec.com/articles.php?Security=24]
+* Trackback responses now specify XML content type
+
+== MediaWiki 1.9.2 ==
+
+February 4, 2007
+
+This is a bug-fix update that fixes some installation and other minor issues
+with the 1.9.1 release as well as a security issue which was introduced in the
+1.9 branch.
+
+JavaScript code which regenerated the "sortable tables" feature did not
+properly sanitize input, leading to an HTML injection vulnerability.
+
+* ([[mediazilla:8774|8774]]) Fix path for GNU FDL rights icon on new installs
+* ([[mediazilla:8819|8819]]) Fix full path disclosure with skins dependencies
+* ([[mediazilla:8819|8819]]) Fixed data-loss bug in compressOld batch text
+compression affecting pages which had null edits (move, protect, etc) as second
+edit in a batch group. Isolated and patched by Travis Derouin.
+* Security fix for sortable tables JavaScript
+
+== MediaWiki 1.9.1 ==
+
+January 24, 2007
+
+This is a bug-fix update that fixes some installation and upgrade issues with
+the original 1.9.0 release.
+
+* ([[mediazilla:3000|3000]]) Fall back to SCRIPT_NAME plus QUERY_STRING when
+REQUEST_URI is not available, as on IIS with PHP-CGI
+* Security fix for DjVu images. (Only affects servers where .djvu file  uploads
+are enabled and ''$wgDjvuToXML'' is set.)
+* ([[mediazilla:8638|8638]]) Fix update from 1.4 and earlier
+* ([[mediazilla:8641|8641]]) Fix order of updates to ipblocks table for updates
+from <=1.7
+* ([[mediazilla:8673|8673]]) Minor fix for web service API content-type header
+* Fix API revision list on PHP 5.2.1; bad reference assignment
+* Fixed up the AjaxSearch
+* Exclude settings files when generating documentation. That could expose the
+database user and password to remote users.
+* ar: fix the 'create a new page' on search page when no exact match found
+* Correct tooltip accesskey hint for Opera on the Macintosh (uses Shift-Esc-,
+not Ctrl-).
+* ([[mediazilla:8719|8719]]) Firefox release notes lie! Fix tooltips for
+Firefox 2 on x11; accesskeys default settings appear to be same as Windows.
 
 == Changes since 1.8 ==
 
index 93d3253..72a468b 100644 (file)
@@ -84,6 +84,8 @@ For notes on 1.32.x and older releases, see HISTORY.
   is no longer a problem, because the code now ensures the timestamp is always
   higher than the previous one. The writes are guarded with CAS logic (check
   and set), which prevents updates that would overlap.
+* $wgDBmysql5 (T196185) - This experimental setting, deprecated in 1.31, has
+  been removed.
 
 === New user-facing features in 1.33 ===
 * (T96041) __EXPECTUNUSEDCATEGORY__ on a category page causes the category
index bbfe251..528b7fe 100644 (file)
@@ -851,7 +851,7 @@ $wgAutoloadLocalClasses = [
        'Maintenance' => __DIR__ . '/maintenance/Maintenance.php',
        'MakeTestEdits' => __DIR__ . '/maintenance/makeTestEdits.php',
        'MalformedTitleException' => __DIR__ . '/includes/title/MalformedTitleException.php',
-       'ManageForeignResources' => __DIR__ . '/maintenance/resources/manageForeignResources.php',
+       'ManageForeignResources' => __DIR__ . '/maintenance/manageForeignResources.php',
        'ManageJobs' => __DIR__ . '/maintenance/manageJobs.php',
        'ManualLogEntry' => __DIR__ . '/includes/logging/LogEntry.php',
        'MapCacheLRU' => __DIR__ . '/includes/libs/MapCacheLRU.php',
@@ -1108,10 +1108,10 @@ $wgAutoloadLocalClasses = [
        'PhpXmlBugTester' => __DIR__ . '/includes/installer/PhpBugTests.php',
        'Pingback' => __DIR__ . '/includes/Pingback.php',
        'PoolCounter' => __DIR__ . '/includes/poolcounter/PoolCounter.php',
+       'PoolCounterNull' => __DIR__ . '/includes/poolcounter/PoolCounterNull.php',
        'PoolCounterRedis' => __DIR__ . '/includes/poolcounter/PoolCounterRedis.php',
        'PoolCounterWork' => __DIR__ . '/includes/poolcounter/PoolCounterWork.php',
        'PoolCounterWorkViaCallback' => __DIR__ . '/includes/poolcounter/PoolCounterWorkViaCallback.php',
-       'PoolCounter_Stub' => __DIR__ . '/includes/poolcounter/PoolCounter.php',
        'PoolWorkArticleView' => __DIR__ . '/includes/poolcounter/PoolWorkArticleView.php',
        'PopulateArchiveRevId' => __DIR__ . '/maintenance/populateArchiveRevId.php',
        'PopulateBacklinkNamespace' => __DIR__ . '/maintenance/populateBacklinkNamespace.php',
index 7e32f7e..060eebd 100644 (file)
@@ -166,7 +166,7 @@ class Block {
                }
 
                $this->setReason( $options['reason'] );
-               $this->mTimestamp = wfTimestamp( TS_MW, $options['timestamp'] );
+               $this->setTimestamp( wfTimestamp( TS_MW, $options['timestamp'] ) );
                $this->setExpiry( wfGetDB( DB_REPLICA )->decodeExpiry( $options['expiry'] ) );
 
                # Boolean settings
@@ -471,7 +471,7 @@ class Block {
                        $row->ipb_by, $row->ipb_by_text, $row->ipb_by_actor ?? null
                ) );
 
-               $this->mTimestamp = wfTimestamp( TS_MW, $row->ipb_timestamp );
+               $this->setTimestamp( wfTimestamp( TS_MW, $row->ipb_timestamp ) );
                $this->mAuto = $row->ipb_auto;
                $this->setHideName( $row->ipb_deleted );
                $this->mId = (int)$row->ipb_id;
@@ -904,7 +904,7 @@ class Block {
                                ->inContentLanguage()->plain()
                );
                $timestamp = wfTimestampNow();
-               $autoblock->mTimestamp = $timestamp;
+               $autoblock->setTimestamp( $timestamp );
                $autoblock->mAuto = 1;
                $autoblock->isCreateAccountBlocked( $this->isCreateAccountBlocked() );
                # Continue suppressing the name if needed
@@ -975,7 +975,7 @@ class Block {
         */
        public function updateTimestamp() {
                if ( $this->mAuto ) {
-                       $this->mTimestamp = wfTimestamp();
+                       $this->setTimestamp( wfTimestamp() );
                        $this->setExpiry( self::getAutoblockExpiry( $this->getTimestamp() ) );
 
                        $dbw = wfGetDB( DB_MASTER );
@@ -1036,10 +1036,7 @@ class Block {
         * @return int (0 for foreign users)
         */
        public function getBy() {
-               $blocker = $this->getBlocker();
-               return ( $blocker instanceof User )
-                       ? $blocker->getId()
-                       : 0;
+               return $this->getBlocker()->getId();
        }
 
        /**
@@ -1048,10 +1045,7 @@ class Block {
         * @return string
         */
        public function getByName() {
-               $blocker = $this->getBlocker();
-               return ( $blocker instanceof User )
-                       ? $blocker->getName()
-                       : (string)$blocker; // username
+               return $this->getBlocker()->getName();
        }
 
        /**
index 3afa593..7a645a6 100644 (file)
@@ -2114,26 +2114,6 @@ $wgDBerrorLog = false;
  */
 $wgDBerrorLogTZ = false;
 
-/**
- * Set to true to engage MySQL 4.1/5.0 charset-related features;
- * for now will just cause sending of 'SET NAMES=utf8' on connect.
- *
- * @warning THIS IS EXPERIMENTAL!
- *
- * May break if you're not using the table defs from mysql5/tables.sql.
- * May break if you're upgrading an existing wiki if set differently.
- * Broken symptoms likely to include incorrect behavior with page titles,
- * usernames, comments etc containing non-ASCII characters.
- * Might also cause failures on the object cache and other things.
- *
- * Even correct usage may cause failures with Unicode supplementary
- * characters (those not in the Basic Multilingual Plane) unless MySQL
- * has enhanced their Unicode support.
- *
- * @deprecated since 1.31
- */
-$wgDBmysql5 = false;
-
 /**
  * Set true to enable Oracle DCRP (supported from 11gR1 onward)
  *
index e0d088a..9fd1e4f 100644 (file)
@@ -30,10 +30,12 @@ class ForeignResourceManager {
        private $registryFile;
        private $libDir;
        private $tmpParentDir;
+       private $cacheDir;
        private $infoPrinter;
        private $errorPrinter;
        private $verbosePrinter;
        private $action;
+       private $registry;
 
        /**
         * @param string $registryFile Path to YAML file
@@ -60,8 +62,11 @@ class ForeignResourceManager {
 
                // Use a temporary directory under the destination directory instead
                // of wfTempDir() because PHP's rename() does not work across file
-               // systems, as the user's /tmp and $IP may be on different filesystems.
-               $this->tmpParentDir = "{$this->libDir}/.tmp";
+               // systems, and the user's /tmp and $IP may be on different filesystems.
+               $this->tmpParentDir = "{$this->libDir}/.foreign/tmp";
+
+               $cacheHome = getenv( 'XDG_CACHE_HOME' ) ? realpath( getenv( 'XDG_CACHE_HOME' ) ) : false;
+               $this->cacheDir = $cacheHome ? "$cacheHome/mw-foreign" : "{$this->libDir}/.foreign/cache";
        }
 
        /**
@@ -69,18 +74,24 @@ class ForeignResourceManager {
         * @throws Exception
         */
        public function run( $action, $module ) {
-               if ( !in_array( $action, [ 'update', 'verify', 'make-sri' ] ) ) {
-                       throw new Exception( 'Invalid action parameter.' );
+               $actions = [ 'update', 'verify', 'make-sri' ];
+               if ( !in_array( $action, $actions ) ) {
+                       $this->error( "Invalid action.\n\nMust be one of " . implode( ', ', $actions ) . '.' );
+                       return false;
                }
                $this->action = $action;
 
-               $registry = $this->parseBasicYaml( file_get_contents( $this->registryFile ) );
+               $this->registry = $this->parseBasicYaml( file_get_contents( $this->registryFile ) );
                if ( $module === 'all' ) {
-                       $modules = $registry;
-               } elseif ( isset( $registry[ $module ] ) ) {
-                       $modules = [ $module => $registry[ $module ] ];
+                       $modules = $this->registry;
+               } elseif ( isset( $this->registry[ $module ] ) ) {
+                       $modules = [ $module => $this->registry[ $module ] ];
                } else {
-                       throw new Exception( 'Unknown module name.' );
+                       $this->error( "Unknown module name.\n\nMust be one of:\n" .
+                               wordwrap( implode( ', ', array_keys( $this->registry ) ), 80 ) .
+                               '.'
+                       );
+                       return false;
                }
 
                foreach ( $modules as $moduleName => $info ) {
@@ -121,8 +132,8 @@ class ForeignResourceManager {
                        }
                }
 
-               $this->cleanUp();
                $this->output( "\nDone!\n" );
+               $this->cleanUp();
                if ( $this->hasErrors ) {
                        // The verify mode should check all modules/files and fail after, not during.
                        return false;
@@ -131,7 +142,29 @@ class ForeignResourceManager {
                return true;
        }
 
+       private function cacheKey( $src, $integrity ) {
+               $key = basename( $src ) . '_' . substr( $integrity, -12 );
+               $key = preg_replace( '/[.\/+?=_-]+/', '_', $key );
+               return rtrim( $key, '_' );
+       }
+
+       /** @return string|false */
+       private function cacheGet( $key ) {
+               return Wikimedia\quietCall( 'file_get_contents', "{$this->cacheDir}/$key.data" );
+       }
+
+       private function cacheSet( $key, $data ) {
+               wfMkdirParents( $this->cacheDir );
+               file_put_contents( "{$this->cacheDir}/$key.data", $data, LOCK_EX );
+       }
+
        private function fetch( $src, $integrity ) {
+               $key = $this->cacheKey( $src, $integrity );
+               $data = $this->cacheGet( $key );
+               if ( $data ) {
+                       return $data;
+               }
+
                $req = MWHttpRequest::factory( $src, [ 'method' => 'GET', 'followRedirects' => false ] );
                if ( !$req->execute()->isOK() ) {
                        throw new Exception( "Failed to download resource at {$src}" );
@@ -144,6 +177,7 @@ class ForeignResourceManager {
                $actualIntegrity = $algo . '-' . base64_encode( hash( $algo, $data, true ) );
                if ( $integrity === $actualIntegrity ) {
                        $this->verbose( "... passed integrity check for {$src}\n" );
+                       $this->cacheSet( $key, $data );
                } else {
                        if ( $this->action === 'make-sri' ) {
                                $this->output( "Integrity for {$src}\n\tintegrity: ${actualIntegrity}\n" );
@@ -271,6 +305,23 @@ class ForeignResourceManager {
 
        private function cleanUp() {
                wfRecursiveRemoveDir( $this->tmpParentDir );
+
+               // Prune the cache of files we don't recognise.
+               $knownKeys = [];
+               foreach ( $this->registry as $info ) {
+                       if ( $info['type'] === 'file' || $info['type'] === 'tar' ) {
+                               $knownKeys[] = $this->cacheKey( $info['src'], $info['integrity'] );
+                       } elseif ( $info['type'] === 'multi-file' ) {
+                               foreach ( $info['files'] as $file ) {
+                                       $knownKeys[] = $this->cacheKey( $file['src'], $file['integrity'] );
+                               }
+                       }
+               }
+               foreach ( glob( "{$this->cacheDir}/*" ) as $cacheFile ) {
+                       if ( !in_array( basename( $cacheFile, '.data' ), $knownKeys ) ) {
+                               unlink( $cacheFile );
+                       }
+               }
        }
 
        /**
index 319bf63..55b78ac 100644 (file)
@@ -334,6 +334,7 @@ function wfUrlencode( $s ) {
        static $needle;
 
        if ( is_null( $s ) ) {
+               // Reset $needle for testing.
                $needle = null;
                return '';
        }
index decc13c..ec3b245 100644 (file)
@@ -1077,16 +1077,18 @@ class Linker {
         * @since 1.16.3
         * @param Revision $rev
         * @param bool $isPublic Show only if all users can see it
+        * @param bool $useParentheses (optional) Wrap comments in parentheses where needed
         * @return string HTML
         */
-       public static function revUserTools( $rev, $isPublic = false ) {
+       public static function revUserTools( $rev, $isPublic = false, $useParentheses = true ) {
                if ( $rev->isDeleted( Revision::DELETED_USER ) && $isPublic ) {
                        $link = wfMessage( 'rev-deleted-user' )->escaped();
                } elseif ( $rev->userCan( Revision::DELETED_USER ) ) {
                        $userId = $rev->getUser( Revision::FOR_THIS_USER );
                        $userText = $rev->getUserText( Revision::FOR_THIS_USER );
                        $link = self::userLink( $userId, $userText )
-                               . self::userToolLinks( $userId, $userText );
+                               . self::userToolLinks( $userId, $userText, false, 0, null,
+                                       $useParentheses );
                } else {
                        $link = wfMessage( 'rev-deleted-user' )->escaped();
                }
@@ -1532,9 +1534,8 @@ class Linker {
                        $stxt = wfMessage( 'historyempty' )->escaped();
                } else {
                        $stxt = wfMessage( 'nbytes' )->numParams( $size )->escaped();
-                       $stxt = wfMessage( 'parentheses' )->rawParams( $stxt )->escaped();
                }
-               return "<span class=\"history-size\">$stxt</span>";
+               return "<span class=\"history-size mw-diff-bytes\">$stxt</span>";
        }
 
        /**
index cb90ccf..8a19c51 100644 (file)
@@ -2984,7 +2984,7 @@ class OutputPage extends ContextSource {
         */
        public function showFileRenameError( $old, $new ) {
                wfDeprecated( __METHOD__, '1.32' );
-               $this->showFatalError( $this->msg( 'filerenameerror', $old, $new )->escpaed() );
+               $this->showFatalError( $this->msg( 'filerenameerror', $old, $new )->escaped() );
        }
 
        /**
index d8aeb62..0f45839 100644 (file)
@@ -3727,6 +3727,7 @@ class Title implements LinkTarget, IDBAccessObject {
                // @todo: get rid of secureAndSplit, refactor parsing code.
                // @note: getTitleParser() returns a TitleParser implementation which does not have a
                //        splitTitleString method, but the only implementation (MediaWikiTitleCodec) does
+               /** @var MediaWikiTitleCodec $titleCodec */
                $titleCodec = MediaWikiServices::getInstance()->getTitleParser();
                // MalformedTitleException can be thrown here
                $parts = $titleCodec->splitTitleString( $this->mDbkeyform, $this->mDefaultNamespace );
index d3a32d0..9e4080d 100644 (file)
@@ -310,11 +310,12 @@ class HistoryPager extends ReverseChronologicalPager {
 
                $curlink = $this->curLink( $rev, $latest );
                $lastlink = $this->lastLink( $rev, $next );
-               $curLastlinks = $curlink . $this->historyPage->message['pipe-separator'] . $lastlink;
+               $curLastlinks = Html::rawElement( 'span', [], $curlink ) .
+                       Html::rawElement( 'span', [], $lastlink );
                $histLinks = Html::rawElement(
                        'span',
-                       [ 'class' => 'mw-history-histlinks' ],
-                       $this->msg( 'parentheses' )->rawParams( $curLastlinks )->escaped()
+                       [ 'class' => 'mw-history-histlinks mw-changeslist-links' ],
+                       $curLastlinks
                );
 
                $diffButtons = $this->diffButtons( $rev, $firstInList );
@@ -362,7 +363,7 @@ class HistoryPager extends ReverseChronologicalPager {
                $s .= " $link";
                $s .= $dirmark;
                $s .= " <span class='history-user'>" .
-                       Linker::revUserTools( $rev, true ) . "</span>";
+                       Linker::revUserTools( $rev, true, false ) . "</span>";
                $s .= $dirmark;
 
                if ( $rev->isMinor() ) {
@@ -374,12 +375,12 @@ class HistoryPager extends ReverseChronologicalPager {
                        # Size is always public data
                        $prevSize = $this->parentLens[$row->rev_parent_id] ?? 0;
                        $sDiff = ChangesList::showCharacterDifference( $prevSize, $rev->getSize() );
-                       $fSize = Linker::formatRevisionSize( $rev->getSize() );
-                       $s .= ' <span class="mw-changeslist-separator">. .</span> ' . "$fSize $sDiff";
+                       $fSize = Linker::formatRevisionSize( $rev->getSize(), false );
+                       $s .= ' <span class="mw-changeslist-separator"></span> ' . "$fSize $sDiff";
                }
 
                # Text following the character difference is added just before running hooks
-               $s2 = Linker::revComment( $rev, false, true );
+               $s2 = Linker::revComment( $rev, false, true, false );
 
                if ( $notificationtimestamp && ( $row->rev_timestamp >= $notificationtimestamp ) ) {
                        $s2 .= ' <span class="updatedmarker">' . $this->msg( 'updatedmarker' )->escaped() . '</span>';
@@ -427,7 +428,11 @@ class HistoryPager extends ReverseChronologicalPager {
                Hooks::run( 'HistoryRevisionTools', [ $rev, &$tools, $prevRev, $user ] );
 
                if ( $tools ) {
-                       $s2 .= ' ' . $this->msg( 'parentheses' )->rawParams( $lang->pipeList( $tools ) )->escaped();
+                       $s2 .= ' ' . Html::openElement( 'span', [ 'class' => 'mw-changeslist-links' ] );
+                       foreach ( $tools as $tool ) {
+                               $s2 .= Html::rawElement( 'span', [], $tool );
+                       }
+                       $s2 .= Html::closeElement( 'span' );
                }
 
                # Tags
@@ -443,7 +448,7 @@ class HistoryPager extends ReverseChronologicalPager {
 
                # Include separator between character difference and following text
                if ( $s2 !== '' ) {
-                       $s .= ' <span class="mw-changeslist-separator">. .</span> ' . $s2;
+                       $s .= ' <span class="mw-changeslist-separator"></span> ' . $s2;
                }
 
                $attribs = [ 'data-mw-revid' => $rev->getId() ];
index 51f4d41..565e615 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  */
 
+use MediaWiki\Logger\LoggerFactory;
 use MediaWiki\Revision\RevisionAccessException;
 use MediaWiki\Revision\RevisionRecord;
 use MediaWiki\Revision\SlotRecord;
@@ -292,69 +293,27 @@ abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
                        }
                }
 
-               if ( $this->fld_roles ) {
-                       $vals['roles'] = $revision->getSlotRoles();
-               }
-
-               if ( $this->needSlots ) {
-                       $revDel = $this->checkRevDel( $revision, RevisionRecord::DELETED_TEXT );
-                       if ( ( $this->fld_slotsha1 || $this->fetchContent ) && ( $revDel & self::IS_DELETED ) ) {
-                               $anyHidden = true;
+               try {
+                       if ( $this->fld_roles ) {
+                               $vals['roles'] = $revision->getSlotRoles();
                        }
-                       if ( $this->slotRoles === null ) {
-                               try {
-                                       $slot = $revision->getSlot( SlotRecord::MAIN, RevisionRecord::RAW );
-                               } catch ( RevisionAccessException $e ) {
-                                       // Back compat: If there's no slot, there's no content, so set 'textmissing'
-                                       // @todo: Gergő says to mention T198099 as a "todo" here.
-                                       $vals['textmissing'] = true;
-                                       $slot = null;
-                               }
 
-                               if ( $slot ) {
-                                       $content = null;
-                                       $vals += $this->extractSlotInfo( $slot, $revDel, $content );
-                                       if ( !empty( $vals['nosuchsection'] ) ) {
-                                               $this->dieWithError(
-                                                       [
-                                                               'apierror-nosuchsection-what',
-                                                               wfEscapeWikiText( $this->section ),
-                                                               $this->msg( 'revid', $revision->getId() )
-                                                       ],
-                                                       'nosuchsection'
-                                               );
-                                       }
-                                       if ( $content ) {
-                                               $vals += $this->extractDeprecatedContent( $content, $revision );
-                                       }
-                               }
-                       } else {
-                               $roles = array_intersect( $this->slotRoles, $revision->getSlotRoles() );
-                               $vals['slots'] = [
-                                       ApiResult::META_KVP_MERGE => true,
-                               ];
-                               foreach ( $roles as $role ) {
-                                       try {
-                                               $slot = $revision->getSlot( $role, RevisionRecord::RAW );
-                                       } catch ( RevisionAccessException $e ) {
-                                               // Don't error out here so the client can still process other slots/revisions.
-                                               // @todo: Gergő says to mention T198099 as a "todo" here.
-                                               $vals['slots'][$role]['missing'] = true;
-                                               continue;
-                                       }
-                                       $content = null;
-                                       $vals['slots'][$role] = $this->extractSlotInfo( $slot, $revDel, $content );
-                                       // @todo Move this into extractSlotInfo() (and remove its $content parameter)
-                                       // when extractDeprecatedContent() is no more.
-                                       if ( $content ) {
-                                               $vals['slots'][$role]['contentmodel'] = $content->getModel();
-                                               $vals['slots'][$role]['contentformat'] = $content->getDefaultFormat();
-                                               ApiResult::setContentValue( $vals['slots'][$role], 'content', $content->serialize() );
-                                       }
+                       if ( $this->needSlots ) {
+                               $revDel = $this->checkRevDel( $revision, RevisionRecord::DELETED_TEXT );
+                               if ( ( $this->fld_slotsha1 || $this->fetchContent ) && ( $revDel & self::IS_DELETED ) ) {
+                                       $anyHidden = true;
                                }
-                               ApiResult::setArrayType( $vals['slots'], 'kvp', 'role' );
-                               ApiResult::setIndexedTagName( $vals['slots'], 'slot' );
+                               $vals = array_merge( $vals, $this->extractAllSlotInfo( $revision, $revDel ) );
                        }
+               } catch ( RevisionAccessException $ex ) {
+                       // This is here so T212428 doesn't spam the log.
+                       // TODO: find out why T212428 happens in the first place!
+                       $vals['slotsmissing'] = true;
+
+                       LoggerFactory::getInstance( 'api-warning' )->error(
+                               'Failed to access revision slots',
+                               [ 'revision' => $revision->getId(), 'exception' => $ex, ]
+                       );
                }
 
                if ( $this->fld_comment || $this->fld_parsedcomment ) {
@@ -396,6 +355,79 @@ abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
                return $vals;
        }
 
+       /**
+        * Extracts information about all relevant slots.
+        *
+        * @param RevisionRecord $revision
+        * @param int $revDel
+        *
+        * @return array
+        * @throws ApiUsageException
+        */
+       private function extractAllSlotInfo( RevisionRecord $revision, $revDel ): array {
+               $vals = [];
+
+               if ( $this->slotRoles === null ) {
+                       try {
+                               $slot = $revision->getSlot( SlotRecord::MAIN, RevisionRecord::RAW );
+                       } catch ( RevisionAccessException $e ) {
+                               // Back compat: If there's no slot, there's no content, so set 'textmissing'
+                               // @todo: Gergő says to mention T198099 as a "todo" here.
+                               $vals['textmissing'] = true;
+                               $slot = null;
+                       }
+
+                       if ( $slot ) {
+                               $content = null;
+                               $vals += $this->extractSlotInfo( $slot, $revDel, $content );
+                               if ( !empty( $vals['nosuchsection'] ) ) {
+                                       $this->dieWithError(
+                                               [
+                                                       'apierror-nosuchsection-what',
+                                                       wfEscapeWikiText( $this->section ),
+                                                       $this->msg( 'revid', $revision->getId() )
+                                               ],
+                                               'nosuchsection'
+                                       );
+                               }
+                               if ( $content ) {
+                                       $vals += $this->extractDeprecatedContent( $content, $revision );
+                               }
+                       }
+               } else {
+                       $roles = array_intersect( $this->slotRoles, $revision->getSlotRoles() );
+                       $vals['slots'] = [
+                               ApiResult::META_KVP_MERGE => true,
+                       ];
+                       foreach ( $roles as $role ) {
+                               try {
+                                       $slot = $revision->getSlot( $role, RevisionRecord::RAW );
+                               } catch ( RevisionAccessException $e ) {
+                                       // Don't error out here so the client can still process other slots/revisions.
+                                       // @todo: Gergő says to mention T198099 as a "todo" here.
+                                       $vals['slots'][$role]['missing'] = true;
+                                       continue;
+                               }
+                               $content = null;
+                               $vals['slots'][$role] = $this->extractSlotInfo( $slot, $revDel, $content );
+                               // @todo Move this into extractSlotInfo() (and remove its $content parameter)
+                               // when extractDeprecatedContent() is no more.
+                               if ( $content ) {
+                                       $vals['slots'][$role]['contentmodel'] = $content->getModel();
+                                       $vals['slots'][$role]['contentformat'] = $content->getDefaultFormat();
+                                       ApiResult::setContentValue(
+                                               $vals['slots'][$role],
+                                               'content',
+                                               $content->serialize()
+                                       );
+                               }
+                       }
+                       ApiResult::setArrayType( $vals['slots'], 'kvp', 'role' );
+                       ApiResult::setIndexedTagName( $vals['slots'], 'slot' );
+               }
+               return $vals;
+       }
+
        /**
         * Extract information from the SlotRecord
         *
index 04efe36..3b13904 100644 (file)
        "apihelp-parse-paramvalue-prop-revid": "הוספת מזהה הגרסה של הדף המפוענח.",
        "apihelp-parse-paramvalue-prop-displaytitle": "הוספת הכותרת של קוד הוויקי המפוענח.",
        "apihelp-parse-paramvalue-prop-headitems": "נותן פריטים לשים ב־<code>&lt;head&gt;</code> של הדף.",
-       "apihelp-parse-paramvalue-prop-headhtml": "נותן את ה־<code>&lt;head&gt;</code> המפוענח של הדף.",
+       "apihelp-parse-paramvalue-prop-headhtml": "נותן doctype מפוענח, תג <code>&lt;html&gt;</code> פותח, רכיב <code>&lt;head&gt;</code>, ותג <code>&lt;body&gt;</code> פותח של הדף.",
        "apihelp-parse-paramvalue-prop-modules": "מתן יחידות ResourceLoader שמשמשות בדף. כדי לטעון, יש להשתמש ב<code dir=\"ltr\">mw.loader.using()</code>. יש לבקש את <kbd>jsconfigvars</kbd> או את <kbd>encodedjsconfigvars</kbd> יחד עם <kbd>modules</kbd>.",
        "apihelp-parse-paramvalue-prop-jsconfigvars": "נותן משתני הגדרות של JavaScript שייחודיים לדף הזה. כדי להחיל, יש להשתמש ב<code dir=\"ltr\">mw.config.set()</code>.",
        "apihelp-parse-paramvalue-prop-encodedjsconfigvars": "נותן משתני הגדרות של JavaScript שייחודיים לדף הזה בתור מחרוזת JSON.",
index 6629309..9e28c39 100644 (file)
        "apierror-mustbeloggedin": "$1にログインしている必要があります。",
        "apierror-noimageredirect": "画像のリダイレクトを作成する権限がありません。",
        "apierror-nosuchpageid": "ID $1のページはありません。",
+       "apierror-pagelang-disabled": "このウィキではページの言語は変更できません。",
        "apierror-permissiondenied": "$1に必要な権限がありません。",
        "apierror-permissiondenied-generic": "アクセスが拒否されました。",
        "apierror-readonly": "ウィキは現在読み取り専用モードです。",
index b92cda8..cbd30c2 100644 (file)
@@ -51,7 +51,7 @@ class BlockRestriction {
                        return [];
                }
 
-               $db = $db ?: wfGetDb( DB_REPLICA );
+               $db = $db ?: wfGetDB( DB_REPLICA );
 
                $result = $db->select(
                        [ 'ipblocks_restrictions', 'page' ],
@@ -182,7 +182,7 @@ class BlockRestriction {
 
                $parentBlockId = (int)$parentBlockId;
 
-               $db = wfGetDb( DB_MASTER );
+               $db = wfGetDB( DB_MASTER );
 
                $db->startAtomic( __METHOD__ );
 
index 00eed14..3a93e57 100644 (file)
@@ -766,7 +766,7 @@ class ChangeTags {
                                        // Return nothing.
                                        $conds[] = '0';
                                        break;
-                               };
+                               }
                        }
 
                        if ( $filterTagIds !== [] ) {
index 2cbe67c..a4225a1 100644 (file)
@@ -345,12 +345,8 @@ class RequestContext implements IContextSource, MutableContext {
                                        $obj = Language::factory( $code );
                                        $this->lang = $obj;
                                }
-
-                               unset( $this->recursion );
-                       }
-                       catch ( Exception $ex ) {
+                       } finally {
                                unset( $this->recursion );
-                               throw $ex;
                        }
                }
 
index 16bde4b..5effb32 100644 (file)
@@ -700,14 +700,6 @@ class DatabaseOracle extends Database {
                return new Blob( $b );
        }
 
-       function decodeBlob( $b ) {
-               if ( $b instanceof Blob ) {
-                       $b = $b->fetch();
-               }
-
-               return $b;
-       }
-
        function unionQueries( $sqls, $all ) {
                $glue = ' UNION ALL ';
 
@@ -969,7 +961,7 @@ class DatabaseOracle extends Database {
                // Defines must comply with ^define\s*([^\s=]*)\s*=\s?'\{\$([^\}]*)\}';
                while ( !feof( $fp ) ) {
                        if ( $lineCallback ) {
-                               call_user_func( $lineCallback );
+                               $lineCallback();
                        }
                        $line = trim( fgets( $fp, 1024 ) );
                        $sl = strlen( $line ) - 1;
@@ -1015,7 +1007,7 @@ class DatabaseOracle extends Database {
 
                                        $cmd = $this->replaceVars( $cmd );
                                        if ( $inputCallback ) {
-                                               call_user_func( $inputCallback, $cmd );
+                                               $inputCallback( $cmd );
                                        }
                                        $res = $this->doQuery( $cmd );
                                        if ( $resultCallback ) {
@@ -1350,10 +1342,6 @@ class DatabaseOracle extends Database {
                return 'BITOR(' . $fieldLeft . ', ' . $fieldRight . ')';
        }
 
-       function getServer() {
-               return $this->server;
-       }
-
        public function buildGroupConcatField(
                $delim, $table, $field, $conds = '', $join_conds = []
        ) {
index 6ed693e..9851460 100644 (file)
@@ -122,7 +122,6 @@ abstract class MWLBFactory {
                                                'tablePrefix' => $mainConfig->get( 'DBprefix' ),
                                                'flags' => DBO_DEFAULT,
                                                'sqlMode' => $mainConfig->get( 'SQLMode' ),
-                                               'utf8Mode' => $mainConfig->get( 'DBmysql5' )
                                        ];
 
                                        $lbConf['servers'][$i] = $server;
@@ -142,7 +141,6 @@ abstract class MWLBFactory {
                                        'load' => 1,
                                        'flags' => $flags,
                                        'sqlMode' => $mainConfig->get( 'SQLMode' ),
-                                       'utf8Mode' => $mainConfig->get( 'DBmysql5' )
                                ];
                                if ( in_array( $server['type'], $typesWithSchema, true ) ) {
                                        $server += [ 'schema' => $mainConfig->get( 'DBmwschema' ) ];
@@ -168,7 +166,6 @@ abstract class MWLBFactory {
                                        $lbConf['serverTemplate']['schema'] = $mainConfig->get( 'DBmwschema' );
                                }
                                $lbConf['serverTemplate']['sqlMode'] = $mainConfig->get( 'SQLMode' );
-                               $lbConf['serverTemplate']['utf8Mode'] = $mainConfig->get( 'DBmysql5' );
                        }
                }
 
index 82cbb40..ee0da7b 100644 (file)
@@ -605,7 +605,7 @@ class HTMLForm extends ContextSource {
                $valid = true;
                $hoistedErrors = Status::newGood();
                if ( $this->mValidationErrorMessage ) {
-                       foreach ( (array)$this->mValidationErrorMessage as $error ) {
+                       foreach ( $this->mValidationErrorMessage as $error ) {
                                $hoistedErrors->fatal( ...$error );
                        }
                } else {
@@ -700,8 +700,8 @@ class HTMLForm extends ContextSource {
        /**
         * Set a message to display on a validation error.
         *
-        * @param string|array $msg String or Array of valid inputs to wfMessage()
-        *     (so each entry can be either a String or Array)
+        * @param array $msg Array of valid inputs to wfMessage()
+        *     (so each entry must itself be an array of arguments)
         *
         * @return HTMLForm $this for chaining calls (since 1.20)
         */
index 818474d..16dc465 100644 (file)
@@ -586,7 +586,7 @@ abstract class HTMLFormField {
                        // It might look weird, but it'll work OK.
                        return $this->getFieldLayoutOOUI(
                                new OOUI\Widget( [ 'content' => new OOUI\HtmlSnippet( $this->getDiv( $value ) ) ] ),
-                               [ 'infusable' => false, 'align' => 'top' ]
+                               [ 'align' => 'top' ]
                        );
                }
 
index 49cbdee..e7e3ff6 100644 (file)
@@ -151,13 +151,11 @@ class OOUIHTMLForm extends HTMLForm {
                        'expanded' => false,
                        'padded' => true,
                        'framed' => true,
-                       'infusable' => false,
                ] );
 
                $layout->appendContent(
                        new OOUI\FieldsetLayout( [
                                'label' => $legend,
-                               'infusable' => false,
                                'items' => [
                                        new OOUI\Widget( [
                                                'content' => new OOUI\HtmlSnippet( $section )
index f928e20..9d41768 100644 (file)
@@ -77,7 +77,7 @@
        "config-uploads-not-safe": "'''Avis:''' Sò dossié stàndard për carié <code>$1</code> a l'é vulneràbil a l'esecussion ëd qualsëssìa senari.\nBele che MediaWiki a contròla j'aspet ëd sicurëssa ëd tùit j'archivi carià, a l'é motobin arcomandà ëd [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security saré ës përtus ëd sicurëssa] prima d'abilité ij cariament.",
        "config-no-cli-uploads-check": "'''Avis:''' Toa cartela predefinìa për j-amportassion (<code>$1</code>) a l'é nen controlà a propòsit ëd la vulnerabilità\nd'esecussion ëd senari arbitrari durant l'istalassion CLI.",
        "config-brokenlibxml": "Sò sistema a l'ha na combinassion ëd version PHP e libxml2 che a l'ha dij bigat e a peul provoché la corussion ëd dat ëstërmà an MediaWiki e d'àutre aplicassion për l'aragnà.\nCh'a agiorna a PHP 5.2.9 o pi neuv e libxml2 2.7.3 o pi neuv ([https://bugs.php.net/bug.php?id=45996 bigat archivià con PHP]).\nAnstalassion abortìa.",
-       "config-suhosin-max-value-length": "Suhosin a l'é instalà e a lìmita la longheur dël paràmetr GET a $1 byte. Ël component ResourceLoader ëd MediaWiki a travajerà an rispetand ës lìmit, ma sòn a degraderà le prestassion. Se possìbil, a dovrìa amposté suhosin.get.max_value_length a 1024 o pi àut an <code>php.ini</code>, e amposté <code>$wgResourceLoaderMaxQueryLength</code> al midem valor an LocalSettings.php .",
+       "config-suhosin-max-value-length": "Suhosin a l'é instalà e a lìmita la <code>longheur</code> dël paràmetr GET a $1 byte. Ël component ResourceLoader ëd MediaWiki a travajerà an rispetand ës lìmit, ma sòn a degraderà le prestassion. Se possìbil, a dovrìa amposté <code>suhosin.get.max_value_length</code> a 1024 o pi àut an <code>php.ini</code>, e amposté <code>$wgResourceLoaderMaxQueryLength</code> al midem valor an <code>LocalSettings.php</code>.",
        "config-db-type": "Sòrt ëd base ëd dàit:",
        "config-db-host": "Ospitant ëd la base ëd dàit:",
        "config-db-host-help": "Se sò servent ëd base ëd dàit a l'é su un servent diferent, ch'a anserissa ambelessì ël nòm dl'ospitant o l'adrëssa IP.\n\nS'a deuvra n'ospitalità partagià, sò fornidor d'ospitalità a dovrìa deje ël nòm dl'ospitant giust ant soa documentassion.\n\nSe a anstala su un servent Windows e a deuvra MySQL, dovré «localhost» a podrìa funsioné nen com nòm dël servent. S'a marcia nen, ch'a preuva «127.0.0.1» com adrëssa IP local.\n\nS'a deuvra PostgresSQL, ch'a lassa sto camp bianch për coleghesse a travers un socket UNIX.",
index 007ac20..3a8f2e1 100644 (file)
@@ -654,7 +654,7 @@ abstract class LBFactory implements ILBFactory {
        }
 
        public function closeAll() {
-               $this->forEachLBCallMethod( 'closeAll', [] );
+               $this->forEachLBCallMethod( 'closeAll' );
        }
 
        public function setAgentName( $agent ) {
index 189ceee..aec99f4 100644 (file)
@@ -89,9 +89,6 @@ class LBFactoryMulti extends LBFactory {
         */
        private $readOnlyBySection = [];
 
-       /** @var array Load balancer factory configuration */
-       private $conf;
-
        /** @var LoadBalancer[] */
        private $mainLBs = [];
 
@@ -166,7 +163,6 @@ class LBFactoryMulti extends LBFactory {
        public function __construct( array $conf ) {
                parent::__construct( $conf );
 
-               $this->conf = $conf;
                $required = [ 'sectionsByDB', 'sectionLoads', 'serverTemplate' ];
                $optional = [ 'groupLoadsBySection', 'groupLoadsByDB', 'hostsByName',
                        'externalLoads', 'externalTemplateOverrides', 'templateOverridesByServer',
index 33dd69b..5cad31f 100644 (file)
@@ -793,8 +793,24 @@ class ManualLogEntry extends LogEntryBase implements Taggable {
         * @param string $to One of: rcandudp (default), rc, udp
         */
        public function publish( $newId, $to = 'rcandudp' ) {
+               $canAddTags = true;
+               // FIXME: this code should be removed once all callers properly call publish()
+               if ( $to === 'udp' && !$newId && !$this->getAssociatedRevId() ) {
+                       \MediaWiki\Logger\LoggerFactory::getInstance( 'logging' )->warning(
+                               'newId and/or revId must be set when calling ManualLogEntry::publish()',
+                               [
+                                       'newId' => $newId,
+                                       'to' => $to,
+                                       'revId' => $this->getAssociatedRevId(),
+                                       // pass a new exception to register the stack trace
+                                       'exception' => new RuntimeException()
+                               ]
+                       );
+                       $canAddTags = false;
+               }
+
                DeferredUpdates::addCallableUpdate(
-                       function () use ( $newId, $to ) {
+                       function () use ( $newId, $to, $canAddTags ) {
                                $log = new LogPage( $this->getType() );
                                if ( !$log->isRestricted() ) {
                                        Hooks::runWithoutAbort( 'ManualLogEntryBeforePublish', [ $this ] );
@@ -806,9 +822,14 @@ class ManualLogEntry extends LogEntryBase implements Taggable {
                                                $rc->save( $rc::SEND_NONE );
                                        } else {
                                                $tags = $this->getTags();
-                                               if ( $tags ) {
-                                                       $revId = $this->getAssociatedRevId(); // Use null if $revId is 0
-                                                       ChangeTags::addTags( $tags, null, $revId > 0 ? $revId : null, $newId );
+                                               if ( $tags && $canAddTags ) {
+                                                       $revId = $this->getAssociatedRevId();
+                                                       ChangeTags::addTags(
+                                                               $tags,
+                                                               null,
+                                                               $revId > 0 ? $revId : null,
+                                                               $newId > 0 ? $newId : null
+                                                       );
                                                }
                                        }
 
index dc8b146..fed0854 100644 (file)
@@ -238,7 +238,6 @@ class ObjectCache {
                global $wgMainCacheType, $wgMessageCacheType, $wgParserCacheType;
                $candidates = [ $wgMainCacheType, $wgMessageCacheType, $wgParserCacheType ];
                foreach ( $candidates as $candidate ) {
-                       $cache = false;
                        if ( $candidate !== CACHE_NONE && $candidate !== CACHE_ANYTHING ) {
                                $cache = self::getInstance( $candidate );
                                // CACHE_ACCEL might default to nothing if no APCu
index ba0b4cb..060faec 100644 (file)
@@ -39,7 +39,7 @@
  * that start with "nowait:". However, only 0 timeouts (non-blocking requests)
  * can be used with "nowait:" keys.
  *
- * By default PoolCounter_Stub is used, which provides no locking. You
+ * By default PoolCounterNull is used, which provides no locking. You
  * can get a useful one in the PoolCounter extension.
  */
 abstract class PoolCounter {
@@ -111,7 +111,7 @@ abstract class PoolCounter {
        public static function factory( $type, $key ) {
                global $wgPoolCounterConf;
                if ( !isset( $wgPoolCounterConf[$type] ) ) {
-                       return new PoolCounter_Stub;
+                       return new PoolCounterNull;
                }
                $conf = $wgPoolCounterConf[$type];
                $class = $conf['class'];
@@ -208,23 +208,3 @@ abstract class PoolCounter {
                return $type . ':' . ( hexdec( substr( sha1( $key ), 0, 4 ) ) % $slots );
        }
 }
-
-// phpcs:ignore Squiz.Classes.ValidClassName.NotCamelCaps
-class PoolCounter_Stub extends PoolCounter {
-
-       public function __construct() {
-               /* No parameters needed */
-       }
-
-       public function acquireForMe() {
-               return Status::newGood( PoolCounter::LOCKED );
-       }
-
-       public function acquireForAnyone() {
-               return Status::newGood( PoolCounter::LOCKED );
-       }
-
-       public function release() {
-               return Status::newGood( PoolCounter::RELEASED );
-       }
-}
diff --git a/includes/poolcounter/PoolCounterNull.php b/includes/poolcounter/PoolCounterNull.php
new file mode 100644 (file)
index 0000000..95a5057
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Provides of semaphore semantics for restricting the number
+ * of workers that may be concurrently performing the same task.
+ *
+ * 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
+ */
+
+/**
+ * A default PoolCounter, which provides no locking.
+ */
+class PoolCounterNull extends PoolCounter {
+
+       public function __construct() {
+               /* No parameters needed */
+       }
+
+       public function acquireForMe() {
+               return Status::newGood( PoolCounter::LOCKED );
+       }
+
+       public function acquireForAnyone() {
+               return Status::newGood( PoolCounter::LOCKED );
+       }
+
+       public function release() {
+               return Status::newGood( PoolCounter::RELEASED );
+       }
+}
index 8a3aa0c..c954df1 100644 (file)
@@ -37,7 +37,7 @@
  *
  * @since 1.22
  */
-class RedisPubSubFeedEngine extends RCFeedEngine {
+class RedisPubSubFeedEngine extends FormattedRCFeed {
 
        /**
         * @see FormattedRCFeed::send
@@ -68,8 +68,8 @@ class RedisPubSubFeedEngine extends RCFeedEngine {
                if ( $conn !== false ) {
                        $conn->publish( $channel, $line );
                        return true;
-               } else {
-                       return false;
                }
+
+               return false;
        }
 }
index 1d3fd86..b474ddc 100644 (file)
@@ -189,7 +189,6 @@ class ExtensionProcessor implements Processor {
         * @param string $path
         * @param array $info
         * @param int $version manifest_version for info
-        * @return array
         */
        public function extractInfo( $path, array $info, $version ) {
                $dir = dirname( $path );
index 636d3b3..68ba413 100644 (file)
@@ -17,7 +17,6 @@ interface Processor {
         * @param string $path Absolute path of JSON file
         * @param array $info
         * @param int $version manifest_version for info
-        * @return array "credits" information to store
         */
        public function extractInfo( $path, array $info, $version );
 
index 579ca19..b88479a 100644 (file)
@@ -46,13 +46,18 @@ abstract class QueryPage extends SpecialPage {
         * The number of rows returned by the query. Reading this variable
         * only makes sense in functions that are run after the query has been
         * done, such as preprocessResults() and formatRow().
+        *
+        * @var int
         */
        protected $numRows;
 
+       /**
+        * @var string|null
+        */
        protected $cachedTimestamp = null;
 
        /**
-        * Whether to show prev/next links
+        * @var bool Whether to show prev/next links
         */
        protected $shownavigation = true;
 
@@ -62,7 +67,8 @@ abstract class QueryPage extends SpecialPage {
         *
         * DO NOT CHANGE THIS LIST without testing that
         * maintenance/updateSpecialPages.php still works.
-        * @return array
+        *
+        * @return string[][]
         */
        public static function getPages() {
                static $qp = null;
@@ -166,7 +172,7 @@ abstract class QueryPage extends SpecialPage {
         * Subclasses return an array of fields to order by here. Don't append
         * DESC to the field names, that'll be done automatically if
         * sortDescending() returns true.
-        * @return array
+        * @return string[]
         * @since 1.18
         */
        function getOrderFields() {
@@ -378,7 +384,7 @@ abstract class QueryPage extends SpecialPage {
 
        /**
         * Get a DB connection to be used for slow recache queries
-        * @return IDatabase
+        * @return \Wikimedia\Rdbms\Database
         */
        function getRecacheDB() {
                return wfGetDB( DB_REPLICA, [ $this->getName(), 'QueryPage::recache', 'vslow' ] );
@@ -500,6 +506,9 @@ abstract class QueryPage extends SpecialPage {
                return [ 'value' ];
        }
 
+       /**
+        * @return string
+        */
        public function getCachedTimestamp() {
                if ( is_null( $this->cachedTimestamp ) ) {
                        $dbr = wfGetDB( DB_REPLICA );
@@ -754,98 +763,6 @@ abstract class QueryPage extends SpecialPage {
        function preprocessResults( $db, $res ) {
        }
 
-       /**
-        * Similar to above, but packaging in a syndicated feed instead of a web page
-        * @param string $class
-        * @param int $limit
-        * @return bool
-        */
-       function doFeed( $class = '', $limit = 50 ) {
-               if ( !$this->getConfig()->get( 'Feed' ) ) {
-                       $this->getOutput()->addWikiMsg( 'feed-unavailable' );
-                       return false;
-               }
-
-               $limit = min( $limit, $this->getConfig()->get( 'FeedLimit' ) );
-
-               $feedClasses = $this->getConfig()->get( 'FeedClasses' );
-               if ( isset( $feedClasses[$class] ) ) {
-                       /** @var RSSFeed|AtomFeed $feed */
-                       $feed = new $feedClasses[$class](
-                               $this->feedTitle(),
-                               $this->feedDesc(),
-                               $this->feedUrl() );
-                       $feed->outHeader();
-
-                       $res = $this->reallyDoQuery( $limit, 0 );
-                       foreach ( $res as $obj ) {
-                               $item = $this->feedResult( $obj );
-                               if ( $item ) {
-                                       $feed->outItem( $item );
-                               }
-                       }
-
-                       $feed->outFooter();
-                       return true;
-               } else {
-                       return false;
-               }
-       }
-
-       /**
-        * Override for custom handling. If the titles/links are ok, just do
-        * feedItemDesc()
-        * @param object $row
-        * @return FeedItem|null
-        */
-       function feedResult( $row ) {
-               if ( !isset( $row->title ) ) {
-                       return null;
-               }
-               $title = Title::makeTitle( intval( $row->namespace ), $row->title );
-               if ( $title ) {
-                       $date = $row->timestamp ?? '';
-                       $comments = '';
-                       if ( $title ) {
-                               $talkpage = $title->getTalkPage();
-                               $comments = $talkpage->getFullURL();
-                       }
-
-                       return new FeedItem(
-                               $title->getPrefixedText(),
-                               $this->feedItemDesc( $row ),
-                               $title->getFullURL(),
-                               $date,
-                               $this->feedItemAuthor( $row ),
-                               $comments );
-               } else {
-                       return null;
-               }
-       }
-
-       function feedItemDesc( $row ) {
-               return isset( $row->comment ) ? htmlspecialchars( $row->comment ) : '';
-       }
-
-       function feedItemAuthor( $row ) {
-               return $row->user_text ?? '';
-       }
-
-       function feedTitle() {
-               $desc = $this->getDescription();
-               $code = $this->getConfig()->get( 'LanguageCode' );
-               $sitename = $this->getConfig()->get( 'Sitename' );
-               return "$sitename - $desc [$code]";
-       }
-
-       function feedDesc() {
-               return $this->msg( 'tagline' )->text();
-       }
-
-       function feedUrl() {
-               return $this->getPageTitle()->getFullURL();
-       }
-
        /**
         * Creates a new LinkBatch object, adds all pages from the passed ResultWrapper (MUST include
         * title and optional the namespace field) and executes the batch. This operation will pre-cache
index b917b9d..cb005a9 100644 (file)
@@ -33,7 +33,8 @@
                        "Neriman2003",
                        "Fitoschido",
                        "Toghrul Rahimli",
-                       "Vlad5250"
+                       "Vlad5250",
+                       "Hüseynzadə"
                ]
        },
        "tog-underline": "Keçidlərin altını xətlə:",
        "userlogin-signwithsecure": "Etibarlı bağlantıdan istifadə edin",
        "cannotlogin-title": "Daxil olmaq mümkün olmadı",
        "cannotlogin-text": "Daxil olmaq mümkün deyil.",
-       "cannotloginnow-title": "Daxil olmaq indi mümkün deyil",
+       "cannotloginnow-title": "İndi daxil olmaq mümkün deyil",
        "cannotloginnow-text": "$1 istifadə edərkən daxil olmaq mümkün deyil.",
        "cannotcreateaccount-title": "Hesablar yaradıla bilmədi",
        "cannotcreateaccount-text": "Bu vikidə birbaşa hesab yaratma aktiv deyil.",
index ec4d676..6a17cc9 100644 (file)
        "pager-newer-n": "$1 {{PLURAL:$1|навейшая|навейшыя|навейшых}}",
        "pager-older-n": "$1 {{PLURAL:$1|старэйшая|старэйшыя|старэйшых}}",
        "suppress": "Падавіць вэрсію",
-       "querypage-disabled": "Гэта спэцыяльная старонка адключаная для падвышэньня прадукцыйнасьці",
+       "querypage-disabled": "Гэтая спэцыяльная старонка адключаная для падвышэньня прадукцыйнасьці.",
        "apihelp": "Даведка API",
        "apihelp-no-such-module": "Модуль «$1» ня знойдзены.",
        "apisandbox": "Пясочніца API",
        "deleting-backlinks-warning": "<strong>Увага:</strong> [[Special:WhatLinksHere/{{FULLPAGENAME}}|іншыя старонкі]] ўключаюць або спасылаюцца на старонку, якую вы зьбіраецеся выдаліць.",
        "deleting-subpages-warning": "<strong>Папярэджаньне:</strong> старонка, якую вы зьбіраецеся выдаліць, мае [[Special:PrefixIndex/{{FULLPAGENAME}}/|{{PLURAL:$1|$1 падстаронку|$1 падстаронкі|$1 падстаронак|51=болей за 50 падстаронак}}]].",
        "rollback": "Адкаціць рэдагаваньні",
+       "rollback-confirmation-confirm": "Калі ласка, пацьвердзіце:",
+       "rollback-confirmation-yes": "Адкаціць",
        "rollbacklink": "адкат",
        "rollbacklinkcount": "адкаціць $1 {{PLURAL:$1|рэдагаваньне|рэдагаваньні|рэдагаваньняў}}",
        "rollbacklinkcount-morethan": "адкаціць больш за $1 {{PLURAL:$1|рэдагаваньне|рэдагаваньні|рэдагаваньняў}}",
index 12ce570..5df588d 100644 (file)
        "pagelang-reason": "Причина",
        "pagelang-submit": "Изпращане",
        "pagelang-nonexistent-page": "Страницата $1 не съществува.",
+       "pagelang-unchanged-language": "Страницата $1 вече е със зададен език $2.",
+       "pagelang-unchanged-language-default": "Страницата $1 вече е със зададен език, съвпадащ с езика по подразбиране за това уики.",
+       "pagelang-db-failed": "Базата данни не успя да смени езика на страницата.",
        "right-pagelang": "Промяна езика на страница",
        "action-pagelang": "промяна езика на страницата",
        "log-name-pagelang": "Дневник на езиковите промени",
        "mediastatistics-header-multimedia": "Мултимедия",
        "mediastatistics-header-office": "Офис",
        "mediastatistics-header-total": "Всички файлове",
+       "json-error-state-mismatch": "Невалиден или грешно структуриран JSON",
+       "json-error-ctrl-char": "Грешка в контролния знак. Вероятно е неправилно кодиран",
        "json-error-syntax": "Синтактична грешка",
        "headline-anchor-title": "Препратка към този раздел",
        "special-characters-group-latin": "Латиница",
        "log-action-filter-protect-move_prot": "Преместване на защитата",
        "log-action-filter-rights-rights": "Ръчна промяна",
        "log-action-filter-rights-autopromote": "Автоматична промяна",
+       "log-action-filter-suppress-event": "Потискане на дневника",
+       "log-action-filter-suppress-revision": "Потискане на версията",
+       "log-action-filter-suppress-delete": "Потискане на страницата",
+       "log-action-filter-suppress-block": "Потискане на потребителя чрез блокиране",
+       "log-action-filter-suppress-reblock": "Потискане на потребителя чрез повторно блокиране",
        "log-action-filter-upload-upload": "Ново качване",
        "log-action-filter-upload-overwrite": "Повторно качване",
        "log-action-filter-upload-revert": "Връщане",
index f2c6016..7ba93cc 100644 (file)
        "deleting-backlinks-warning": "<strong>সতর্কীকরণ:</strong> আপনি যেটি মুছে ফেলতে যাচ্ছেন তা [[Special:WhatLinksHere/{{FULLPAGENAME}}|অন্যান্য পাতাসমূহে]] সংযুক্ত অথবা অন্তর্ভুক্ত রয়েছে।",
        "deleting-subpages-warning": "<strong>সতর্কীকরণ:</strong> আপনি যে পাতাটি মুছে ফেলতে যাচ্ছেন তাঁর [[Special:PrefixIndex/{{FULLPAGENAME}}/|{{PLURAL:$1|একটি উপপাতা|$1টি উপপাতা|51=৫০টির বেশী}}]] রয়েছে।",
        "rollback": "সম্পাদনা ফিরিয়ে নিন",
+       "rollback-confirmation-confirm": "দয়া করে নিশ্চিত করুন:",
+       "rollback-confirmation-yes": "পুনর্বহাল করুন",
+       "rollback-confirmation-no": "বাতিল করুন",
        "rollbacklink": "পুনর্বহাল",
        "rollbacklinkcount": "$1টি {{PLURAL:$1|সম্পাদনা}} রোলব্যাক করুন",
        "rollbacklinkcount-morethan": "$1টির বেশি {{PLURAL:$1|সম্পাদনা}} রোলব্যাক করুন",
index c17a6bb..366a783 100644 (file)
        "delete-warning-toobig": "no pel wayirê tarixê vurnayiş ê derg o, $1 {{PLURAL:$1|revizyonê|revizyonê}} seri de.\nhewn a kerdışê ıney {{SITENAME}} şuxul bıne gırano;\nbı diqqet dewam kerê.",
        "deleteprotected": "Şıma nêşenê ena perer esternê,  çıkı per starya ya.",
        "rollback": "vurnayişan tepiya bıger",
+       "rollback-confirmation-no": "Bıtexelne",
        "rollbacklink": "ageyrayış",
        "rollbacklinkcount": "$1 {{PLURAL:$1|vurnayış|vurnayışi}} peyd gıroti",
        "rollbacklinkcount-morethan": "$1 {{PLURAL:$1|vurnayış|vuranyışi}} tewr peyd gırot",
index 6f32bc0..a8515a9 100644 (file)
@@ -78,6 +78,7 @@
        "tog-norollbackdiff": "Ära näita erinevusi pärast tühistamist",
        "tog-useeditwarning": "Hoiata mind, kui lahkun redigeerimisleheküljelt muudatusi salvestamata",
        "tog-prefershttps": "Kasuta sisselogimisel alati turvalist ühendust",
+       "tog-showrollbackconfirmation": "Küsi tühistamislingile klõpsamise järel kinnitust",
        "underline-always": "Alati",
        "underline-never": "Mitte kunagi",
        "underline-default": "Kujunduse või brauseri vaikeväärtus",
        "badretype": "Sisestatud paroolid ei lange kokku.",
        "usernameinprogress": "Selle kasutajanimega konto loomine on juba pooleli.\nPalun oota.",
        "userexists": "Sisestatud kasutajanimi on juba kasutusel.\nPalun valige uus nimi.",
+       "createacct-normalization": "Tehniliste piirangute tõttu kohandatakse sinu kasutajanimi kujule \"$2\".",
        "loginerror": "Viga sisselogimisel",
        "createacct-error": "Tõrge konto loomisel",
        "createaccounterror": "Kasutajakonto loomine ebaõnnestus: $1",
        "deleting-backlinks-warning": "<strong>Hoiatus:</strong> [[Special:WhatLinksHere/{{FULLPAGENAME}}|Teised leheküljed]] viitavad leheküljele, mida oled kustutamas, või see lehekülg on kasutuses mallina.",
        "deleting-subpages-warning": "<strong>Hoiatus:</strong> Oled kustutamas lehekülge, millel on [[Special:PrefixIndex/{{FULLPAGENAME}}/|{{PLURAL:$1|alamlehekülg|$1 alamlehekülge|51=üle 50 alamlehekülje}}]].",
        "rollback": "Tühista muudatused",
+       "rollback-confirmation-confirm": "Palun kinnita:",
+       "rollback-confirmation-yes": "Tühista",
+       "rollback-confirmation-no": "Loobu",
        "rollbacklink": "tühista",
        "rollbacklinkcount": "tühista {{PLURAL:$1|üks muudatus|$1 muudatust}}",
        "rollbacklinkcount-morethan": "tühista üle {{PLURAL:$1|ühe muudatuse|10 muudatuse}}",
        "ipb-confirm": "Kinnita blokeering",
        "ipb-sitewide": "Saidiülene",
        "ipb-partial": "Osaline",
+       "ipb-sitewide-help": "Viki kõigi lehekülgede muutmine ja kogu ülejäänud kaastöö.",
+       "ipb-partial-help": "Teatud lehekülgede või nimeruumide muutmine.",
        "ipb-pages-label": "Leheküljed",
        "ipb-namespaces-label": "Nimeruumid",
        "badipaddress": "Vigane IP-aadress",
        "confirm-unwatch-top": "Kas eemaldad selle lehekülje oma jälgimisloendist?",
        "confirm-rollback-button": "Sobib",
        "confirm-rollback-top": "Kas tühistad sellel leheküljel tehtud muudatused?",
+       "confirm-rollback-bottom": "See toiming tühistab koheselt valitud muudatused sellel leheküljel.",
        "confirm-mcrrestore-title": "Redaktsiooni taastamine",
        "confirm-mcrundo-title": "Muudatuse eemaldamine",
        "mcrundofailed": "Eemaldamine ebaõnnestus",
        "logentry-rights-autopromote": "$1 {{GENDER:$2|viidi}} automaatselt üle teise rühma; enne oli $4, nüüd on $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|laadis üles}} faili $3",
        "logentry-upload-overwrite": "$1 {{GENDER:$2|laadis üles}} uue versiooni failist $3",
-       "logentry-upload-revert": "$1 {{GENDER:$2|laadis üles}} faili $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|taastas}} faili $3 vanema versiooni",
        "log-name-managetags": "Märgiste haldamise logi",
        "log-description-managetags": "Sellel leheküljel on toodud [[Special:Tags|märgiste]] haldamisega seotud tegevused. Logis on ainult toimingud, mida administraatorid on teinud käsitsi. Siin puuduvad logisissekanded viki tarkvaras koostatud või sealt kustutatud märgiste kohta.",
        "logentry-managetags-create": "$1 {{GENDER:$2|koostas}} märgise \"$4\"",
        "log-action-filter-suppress-reblock": "Kasutaja varjamine taasblokeerimise teel",
        "log-action-filter-upload-upload": "Uus üleslaadimine",
        "log-action-filter-upload-overwrite": "Uuesti üleslaadimine",
+       "log-action-filter-upload-revert": "Taastamine",
        "authmanager-authn-not-in-progress": "Autentimine pole teoksil või seansiandmed läksid kaduma. Palun alusta uuesti.",
        "authmanager-authn-no-primary": "Ette antud autentimisandmeid ei õnnestunud autentida.",
        "authmanager-authn-no-local-user": "Ette antud autentimisandmed pole selles vikis seotud ühegi kasutajaga.",
        "passwordpolicies-policy-maximalpasswordlength": "Parool peab olema $1 {{PLURAL:$1|märgist}} lühem.",
        "passwordpolicies-policy-passwordcannotbepopular": "Parool ei tohi olla {{PLURAL:$1|populaarne parool|$1 populaarse parooli loendis}}.",
        "passwordpolicies-policy-passwordnotinlargeblacklist": "Parool ei saa olla 100&nbsp;000 kõige levinuma parooli loendis.",
+       "passwordpolicies-policyflag-forcechange": "peab muutma sisselogimisel",
+       "passwordpolicies-policyflag-suggestchangeonlogin": "soovita muutmist sisselogimisel",
        "easydeflate-invaliddeflate": "Ette antud sisu ei ole õigesti vähendatud",
        "unprotected-js": "Turvalisuse huvides ei saa JavaScripti laadida kaitsmata lehekülgedelt. Palun koosta JavaScripti ainult nimeruumis MediaWiki või kasutajate nimeruumi alamleheküljel."
 }
index 76decac..f7fd250 100644 (file)
@@ -72,7 +72,8 @@
                        "Physicsch",
                        "Nbi",
                        "Amjad Khan",
-                       "Ahmad252"
+                       "Ahmad252",
+                       "FarsiNevis"
                ]
        },
        "tog-underline": "خط کشیدن زیر پیوندها:",
        "subject-preview": "پیش‌نمایش موضوع:",
        "previewerrortext": "در زمان تلاش برای نمایش دادن تغییرات شما، خطایی رخ داد.",
        "blockedtitle": "کاربر بسته شده‌است",
-       "blockedtext-partial": "<strong>حساب کاربری یا آدرس آی‌پی شما از انجام تغییرات در این صفحه منع شده‌است. شما همچنان می‌توانید در دیگر صفحه‌های این ویکی ویرایش کنید.</strong> برای مشاهده جزئیات کامل قطع دسترسی به [[ویژه:مشارکت‌های من|مشارکت‌های حساب]] مراجعه کنید.\n\nاین قطع دسترسی توسط $1 انجام گرفته‌است.\n\nدلیل قطع دسترسی <em>$2</em> است.\n\n* زمان آغاز قطع دسترسی: $8\n* زمان پایان قطع دسترسی: $6\n* موارد مورد نظر: $7\n* شناسه قطع دسترسی: #$5",
+       "blocked-email-user": "<strong>دسترسی حساب کاربری شما از ارسال ایمیل قطع شده است. شما همچنان می‌توانید سایر صفحات این ویکی را ویرایش کنید.</strong>می‌توانید جزئیات کامل قطع دسترسی را در [[Special:MyContributions|مشارکت‌های حساب]] ببینید.\n\nقطع دسترسی توسط $1 انجام شده است.\n\nدلیل داده‌شده <em>$2</em> بوده است.\n\n* شروع قطع دسترسی: $8\n* اتمام قطع دسترسی: $6\n* هدف قطع دسترسی: $7\n* شناسه قطع دسترسی #$5",
+       "blockedtext-partial": "<strong>حساب کاربری یا آدرس آی‌پی شما از انجام تغییرات در این صفحه منع شده‌است. شما همچنان می‌توانید در دیگر صفحه‌های این ویکی ویرایش کنید.</strong> برای مشاهده جزئیات کامل قطع دسترسی به [[Special:MyContributions|مشارکت‌های حساب]] مراجعه کنید.\n\nاین قطع دسترسی توسط $1 انجام گرفته‌است.\n\nدلیل قطع دسترسی <em>$2</em> است.\n\n* زمان آغاز قطع دسترسی: $8\n* زمان پایان قطع دسترسی: $6\n* موارد مورد نظر: $7\n* شناسه قطع دسترسی: #$5",
        "blockedtext": "<strong>دسترسی حساب کاربری یا نشانی آی‌پی شما بسته شده‌است.</strong>\n\nاین قطع دسترسی توسط $1 انجام شده است.\nدلیل ارائه‌شده چنین است: <em>$2</em>\n\n* شروع قطع دسترسی: $8\n* پایان قطع دسترسی: $6\n* کاربری هدف قطع دسترسی: $7\n\nشما می‌توانید با $1 یا [[{{MediaWiki:Grouppage-sysop}}|مدیری]] دیگر تماس بگیرید و در این باره صحبت کنید.\nتوجه کنید که شما نمی‌توانید از قابلیت «{{int:emailuser}}» استفاده کنید مگر آنکه آدرس ایمیل معتبری در [[Special:Preferences|ترجیحات کاربری]] خودتان ثبت کرده باشید و نیز باید امکان استفاده از این قابلیت برای شما قطع نشده باشد.\nنشانی آی‌پی فعلی شما $3 و شمارهٔ قطع دسترسی شما $5 است.\nلطفاً تمامی جزئیات فوق را در کلیهٔ درخواست‌هایی که در این باره مطرح می‌کنید ذکر کنید.",
        "autoblockedtext": "دسترسی نشانی آی‌پی شما قطع شده‌است، زیرا این نشانی آی‌پی توسط کاربر دیگری استفاده شده که دسترسی او توسط $1 قطع شده‌است.\nدلیل ارائه‌شده چنین است:\n\n:''$2''\n\n* شروع قطع دسترسی: $8\n* پایان قطع دسترسی: $6\n* کاربری هدف قطع دسترسی: $7\n\nشما می‌توانید با $1 یا [[{{MediaWiki:Grouppage-sysop}}|مدیری]] دیگر تماس بگیرید و در این باره صحبت کنید.\nتوجه کنید که شما نمی‌توانید از قابلیت «{{int:emailuser}}» استفاده کنید مگر آنکه نشانی ایمیل معتبری در [[Special:Preferences|ترجیحات کاربری]] خودتان ثبت کرده باشید و نیز باید امکان استفاده از این قابلیت برای شما قطع نشده باشد.\nنشانی آی‌پی فعلی شما $3 و شمارهٔ قطع دسترسی شما $5 است.\nلطفاً تمامی جزئیات فوق را در کلیهٔ درخواست‌هایی که در این باره مطرح می‌کنید ذکر کنید.",
        "systemblockedtext": "نام کاربری یا نشانی آی‌پی شما خودکار توسط مدیاویکی مسدود شده‌است.\nدلیل ارائه‌شده:\n\n:<em>$2</em>\n\n* آغاز بلاک: $8\n* پایان بلاک: $6\n* قطع دسترسی‌شده مورد نظر: $7\n\nنشانی آی‌پی کنونی شما $3 است.\nخواهشمند است تمام جزئیات بالا را در هر پرس‌وجویی که انجام می‌دهید قرار دهید.",
        "edit-gone-missing": "امکان به‌روز کردن صفحه وجود ندارد.\nبه نظرمی‌رسد که صفحه حذف شده باشد.",
        "edit-conflict": "تعارض ویرایشی.",
        "edit-no-change": "ویرایش شما نادیده گرفته شد، زیرا تغییری در متن داده نشده بود.",
+       "edit-slots-cannot-add": "این {{PLURAL:$1|اسلات|اسلات‌ها}} پشتیبانی نمی‌شود: $2.",
+       "edit-slots-cannot-remove": "امکان حذف این {{PLURAL:$1|اسلات|اسلات‌ها}} وجود ندارد: $2.",
+       "edit-slots-missing": "این {{PLURAL:$1|اسلات|اسلات‌ها}} ناموجود است: $2.",
        "postedit-confirmation-created": "صفحه ایجاد شده است.",
        "postedit-confirmation-restored": "صفحه بازیابی شده است.",
        "postedit-confirmation-saved": "ویرایش شما ذخیره شد.",
        "defaultmessagetext": "متن پیش‌فرض پیغام",
        "content-failed-to-parse": "عدم موفقیت در تجزیه محتوای $2 برای مدل $1: $3",
        "invalid-content-data": "داده محتوای نامعتبر",
-       "content-not-allowed-here": "محتوای «$1» در صفحهٔ [[:$2]] مجاز نیست",
+       "content-not-allowed-here": "محتوای «$1» در صفحهٔ [[:$2]] بخش «$3» مجاز نیست",
        "editwarning-warning": "خروج از این صفحه ممکن است باعث شود که شما هر شانسی که به وجود آورده‌اید را از دست بدهید.\nاگر شما وارد سامانه شده‌اید، می‌توانید این هشدار را در بخش «{{int:prefs-editing}}» ترجیحاتتان غیرفعال کنید.",
        "editpage-invalidcontentmodel-title": "مدل محتوای پشتیبانی نشده",
        "editpage-invalidcontentmodel-text": "مدل محتوای «$1» پشتیبای نمی‌شود.",
        "move": "انتقال",
        "movethispage": "انتقال این صفحه",
        "unusedimagestext": "پرونده‌های زیر موجودند اما در هیچ صفحه‌ای به کار نرفته‌اند.\nلطفاً توجه داشته باشید که دیگر وبگاه‌ها ممکن است با یک نشانی اینترنتی مستقیم به یک پرونده پیوند دهند، و با وجود این که در استفادهٔ فعال هستند در این جا فهرست شوند.",
+       "unusedimagestext-categorizedimgisused": "فایل موردنظر موجود است اما در هیچ صفحه‌ای استفاده نشده است. تصاویر رده‌بندی‌شده حتی اگر در هیچ صفحه‌ای درج نشده باشند، به عنوان تصاویر مورداستفاده محسوب می‌شوند.\nلطفا توجه داشته باشید که دیگر وب‌سایت‌ها ممکن است به صورت مستقیم به یک فایل پیوند داده باشند و با وجود اینکه آن فایل فعال محسوب می‌شود در اینجا لیست شده باشد.",
        "unusedcategoriestext": "این رده‌ها وجود دارند ولی هیچ مقاله یا ردهٔ دیگری از آنها استفاده نمی‌کند.",
        "notargettitle": "مقصدی نیست",
        "notargettext": "شما صفحهٔ یا کاربر مقصدی برای انجام این عمل روی آن مشخص نکرده‌اید.",
        "deleting-backlinks-warning": "<strong>هشدار:</strong> [[Special:WhatLinksHere/{{FULLPAGENAME}}|صفحه‌های دیگری]] هستند که به صفحه‌ای که شما در حال حذف آن هستید پیوند دارند یا آن را تراگنجانیده‌اند.",
        "deleting-subpages-warning": "<strong>هشدار:</strong> صفحه‌ای که شما می‌خواهید حذف کنید [[Special:PrefixIndex/{{FULLPAGENAME}}/|{{PLURAL:$1|یک زیرصفحه|$1 زیرصفحه|51=بیش از پنجاه زیرصفحه}}]] دارد.",
        "rollback": "واگردانی ویرایش‌ها",
-       "rollback-confirmation-confirm": "لطفا تایید کنید:",
+       "rollback-confirmation-confirm": "لطفاً تأیید کنید:",
        "rollback-confirmation-yes": "واگردانی",
        "rollback-confirmation-no": "انصراف",
        "rollbacklink": "واگردانی",
        "movepage-moved": "'''«$1» به «$2» منتقل شد'''",
        "movepage-moved-redirect": "یک تغییرمسیر ایجاد شد.",
        "movepage-moved-noredirect": "از ایجاد تغییرمسیر ممانعت شد.",
+       "movepage-delete-first": "صفحه مقصد تعداد زیادی نسخه برای حذف دارد. لطفا ابتدا صفحه را دستی حذف کنید و سپس دوباره سعی کنید.",
        "articleexists": "صفحه‌ای با این نام از قبل وجود دارد، یا نامی که انتخاب کرده‌اید معتبر نیست.\nلطفاً نام دیگری انتخاب کنید.",
        "cantmove-titleprotected": "شما نمی‌توانید صفحه را به این نشانی انتقال دهید، چرا که عنوان جدید در برابر ایجاد محافظت شده‌است",
        "movetalk": "صفحهٔ بحث هم منتقل شود",
        "mcrundofailed": "واگردانی ناموفق بود",
        "mcrundo-missingparam": "فقدان پارامترهای ضروری در درخواست",
        "mcrundo-changed": "این صفحه از زمانی که شما تفاوت را دیده‌اید تغییر کرده است. تغییر جدید را مشاهده کنید.",
+       "mcrundo-parse-failed": "قادر به تجزیه نسخه جدید نیست: $1",
        "semicolon-separator": "؛&#32;",
        "comma-separator": "،&#32;",
        "percent": "$1٪",
        "logentry-block-reblock": "$1 {{GENDER:$2|تنظیمات}} بستن {{GENDER:$4|$3}} را به پایان قطع دسترسی $5 $6 تغییر داد.",
        "logentry-partialblock-block-page": "{{PLURAL:$1|صفحه|صفحات}} $2",
        "logentry-partialblock-block-ns": "{{PLURAL:$1|فضای نام|فضاهای نام}} $2",
-       "logentry-partialblock-block": "$1 {{GENDER:$4|$3}} را از ویرایش $7 با انقضای $5 $6 قطع دسترسی کرد",
-       "logentry-partialblock-reblock": "$1 {{GENDER:$2|تنظیمات}} بستن {{GENDER:$4|$3}} را به جلوگیری از ویرایش $7 و پایان قطع دسترسی $5 $6 تغییر داد.",
+       "logentry-partialblock-block": "$1 {{GENDER:$4|$3}} را از ویرایش $7 با انقضای $5 $6 {{GENDER:$2|قطع دسترسی کرد}}",
+       "logentry-partialblock-reblock": "$1 {{GENDER:$2|تنظیمات}} بستن {{GENDER:$4|$3}} را به جلوگیری از ویرایش $7 و پایان قطع دسترسی $5 $6 تغییر داد",
+       "logentry-non-editing-block-block": "$1 {{GENDER:$4|$3}} را از اعمال مشخص‌شده غیرویرایشی با انقضای $5 $6 {{GENDER:$2|قطع دسترسی کرد}}",
+       "logentry-non-editing-block-reblock": "$1 {{GENDER:$2|تنظیمات}} بستن {{GENDER:$4|$3}} را به جلوگیری از اعمال مشخص‌شده غیرویرایشی و پایان قطع دسترسی $5 $6 تغییر داد.",
        "logentry-suppress-block": "$1 {{GENDER:$2|بسته شد}} {{GENDER:$4|$3}} با پایان قطع دسترسی در زمان $5 $6",
        "logentry-suppress-reblock": "$1 {{GENDER:$2|تنظیمات}} بستن برای  {{GENDER:$4|$3}} به پایان قطع دسترسی  $5 $6 تغییر یافت",
        "logentry-import-upload": "$1 $3 را توسط بارگذار پرونده {{GENDER:$2|درون‌ریزی کرد}}",
        "passwordpolicies-policy-maximalpasswordlength": "گذرواژه باید کمتر از $1 {{PLURAL:$1|نویسه|نویسه}} طول داشته باشد",
        "passwordpolicies-policy-passwordcannotbepopular": "گذرواژه نمی‌تواند {{PLURAL:$1|گذرواژه پراستفاده باشد|در فهرست $1 گذرواژه‌های پراستفاده باشد}}",
        "passwordpolicies-policy-passwordnotinlargeblacklist": "گذرواژه نمی‌تواند یکی از ۱۰۰٬۰۰۰ گذرواژه پراستفاده باشد.",
-       "passwordpolicies-policyflag-forcechange": "در هنگام ورود باید تغییر کند",
-       "passwordpolicies-policyflag-suggestchangeonlogin": "در هنگام ورود پیشنهاد تغییر داده می‌شود",
+       "passwordpolicies-policyflag-forcechange": "در هنگام ورود باید تغییر دهید",
+       "passwordpolicies-policyflag-suggestchangeonlogin": "در هنگام ورود، پیشنهاد تغییر بده",
        "easydeflate-invaliddeflate": "محتوی تهیه‌شده به صورت درست خالی نشده‌است",
        "unprotected-js": "به دلایل امنیتی، جاوااسکریپت نمی‌تواند از صفحات محافظت‌نشده بارگیری شود. لطفا جاوااسکریپت را تنها در فضای نام مدیاویکی: و یا در زیرصفحهٔ کاربری خودتان ایجاد کنید."
 }
index 6afa75e..cd60511 100644 (file)
        "tog-useeditwarning": "M’avertir quand je quitte une page en cours de modification sans avoir sauvegardé",
        "tog-prefershttps": "Toujours utiliser une connexion sécurisée lorsque je suis connecté",
        "tog-showrollbackconfirmation": "Afficher une demande de confirmation en cliquant sur un lien d’annulation",
+       "tog-showrollbackconfirmation-prerelease-warning": "Veuillez prendre note : Cette fonctionnalité n’est pas encore disponible. Si vous définissez cette préférence maintenant, votre choix sera pris en compte [https://meta.wikimedia.org/wiki/WMDE_Technical_Wishes/Rollback#Status quand la fonctionnalité sera livrée].",
        "underline-always": "Toujours",
        "underline-never": "Jamais",
        "underline-default": "Valeur par défaut du thème ou du navigateur",
        "confirm-unwatch-top": "Supprimer cette page de votre liste de suivi ?",
        "confirm-rollback-button": "OK",
        "confirm-rollback-top": "Révoquer les modifications de cette page ?",
+       "confirm-rollback-bottom": "Cette action annulera immédiatement les modifications sélectionnées sur cette page.",
        "confirm-mcrrestore-title": "Restaurer une version",
        "confirm-mcrundo-title": "Annuler une modification",
        "mcrundofailed": "L’annulation a échoué",
index 4830ea0..a3903bb 100644 (file)
        "blankpage": "Side is leech",
        "intentionallyblankpage": "Dizze side is bewust leech lizzen en wurdt brûkt foar benchmarks, ensfh.",
        "tag-list-wrapper": "[[Special:Tags|{{PLURAL:$1|Lebel|Lebels}}]]: $2",
+       "tag-mw-new-redirect": "Nije trochferwizing",
+       "tag-mw-undo": "Ungedien meitsjen",
        "tags-source-header": "Boarne",
        "tags-active-header": "Aktyf?",
        "tags-actions-header": "Aksjes",
        "logentry-delete-delete": "$1 {{GENDER:$2|hat}} de side $3 wiske",
        "revdelete-restricted": "hat beheinings oplein oan behearders",
        "revdelete-unrestricted": "hat beheinings foar behearders goedmakke",
+       "logentry-move-move": "$1 {{GENDER:$2|hat}} de side $3 omneamd ta $4",
+       "logentry-move-move-noredirect": "$1 {{GENDER:$2|hat}} de side $3 omneamd ta $4 sûnder in trochferwizing efter te litten",
+       "logentry-move-move_redir": "$1 {{GENDER:$2|hat}} de side $3 omneamd ta $4 fan de trochferwizing",
+       "logentry-move-move_redir-noredirect": "$1 {{GENDER:$2|hat}} de side $3 omneamd ta $4 fan de trochferwizing, sûnder in trochferwizing efter te litten",
        "logentry-newusers-create": "It meidochakkount $1 is {{GENDER:$2|oanmakke}}",
        "logentry-newusers-autocreate": "It meidochakkount $1 is automatysk {{GENDER:$2|oanmakke}}",
        "logentry-upload-upload": "$1 hat $3 {{GENDER:$2|opladen}}",
index c0c3832..fc566aa 100644 (file)
@@ -22,7 +22,8 @@
                        "Macofe",
                        "Tem",
                        "Nmacu",
-                       "ديفيد"
+                       "ديفيد",
+                       "Xqt"
                ]
        },
        "tog-underline": "Folínte faoi naisc:",
        "ilsubmit": "Cuardaigh",
        "bydate": "de réir dáta",
        "sp-newimages-showfrom": "Taispeáin íomhánna nua as $2, $1",
-       "days": "{{PLURAL:$1|$1 lá}}",
+       "days": "$1 lá",
        "bad_image_list": "Is é seo a leanas an formáid:\n\nNíl ach míreanna liosta amháin (línte ag tosú le *) san áireamh.\nIs riachtanach gur nasc do dhrochchomhad é an chéad nasc ar líne.\nIs eisceachtaí iad na naisc eile ar an líne céanna, .i. leathanaigh gur féidir an comhad a bheith orthu go hinlíne.",
        "metadata": "Meiteasonraí",
        "metadata-help": "Tá breis eolais sa comhad seo, curtha, is dócha, as ceamara digiteach ná scanóir a chruthaigh ná a digitigh é.\nMá tá an comhad mionathraithe as an bunleagan, b'fhéidir nach mbeidh ceann de na sonraí fágtha sa comhad atá athruithe.",
index c033735..c6c810e 100644 (file)
        "print": "Enprimé",
        "view": "Lir",
        "view-foreign": "Wè asou $1",
-       "edit": "Modifyé",
-       "edit-local": "Modifyé dèskripsyon lokal",
+       "edit": "Chanjé",
+       "edit-local": "Chanjé dèskripsyon lokal-a",
        "create": "Kréyé",
        "create-local": "Ajouté roun dèskripsyon lokal",
        "delete": "Siprimen",
        "undelete_short": "Rèstoré {{PLURAL:$1|roun modifikasyon|$1 modifikasyon}}",
        "viewdeleted_short": "Wè {{PLURAL:$1|roun modifikasyon ki siprimen|$1 modifikasyon ki siprimen}}",
        "protect": "Protéjé",
-       "protect_change": "modifyé",
+       "protect_change": "chanjé",
        "unprotect": "Chanjé protègsyon-an",
        "newpage": "Nouvèl paj",
        "talkpagelinktext": "diskisyon",
        "newmessageslinkplural": "{{PLURAL:$1|oun nouvèl mésaj|dé nouvèl mésaj}}",
        "newmessagesdifflinkplural": "{{PLURAL:$1|dannyé modifikasyon}}",
        "youhavenewmessagesmulti": "Zòt gen dé nouvèl mésaj asou $1.",
-       "editsection": "Modifyé",
-       "editold": "modifyé",
+       "editsection": "chanjé",
+       "editold": "chanjé",
        "viewsourceold": "wè sours-a",
-       "editlink": "modifyé",
+       "editlink": "chanjé",
        "viewsourcelink": "wè sours-a",
        "editsectionhint": "Modifyé ségsyon-an : $1",
        "toc": "Baydivan",
        "yourpasswordagain": "Konfirmen modipas-a :",
        "createacct-yourpasswordagain": "Konfirmen modipas-a",
        "createacct-yourpasswordagain-ph": "Rantré òkò menm modipas-a",
-       "userlogin-remembermypassword": "Gardé mo sésyon aktiv",
+       "userlogin-remembermypassword": "Gadé mo sésyon agtiv",
        "userlogin-signwithsecure": "Itilizé roun konnègsyon sékirizé",
        "cannotlogin-title": "Enposib di konnègté so kò",
        "cannotlogin-text": "Konnègsyon-an pa posib",
        "cannotcreateaccount-title": "Kréyasyon di kont enposib",
        "cannotcreateaccount-text": "Kréyasyon-an dirèk di kont itilizatò pa fika agtivé asou sa wiki.",
        "yourdomainname": "Zòt domenn :",
-       "password-change-forbidden": "Zòt pa pouvé modifyé mo di pas asou sa wiki.",
+       "password-change-forbidden": "Zòt pa pouvé chanjé modipas-ya asou sa wiki.",
        "externaldberror": "Swé roun lérò prodjwi so kò asou baz-a di data d'otantifikasyon, swé zòt pa otorizé à mété à jou zòt kont ègstèrn.",
        "login": "Konnègsyon",
        "login-security": "Vérifyé zòt idantité",
        "createacct-benefit-body1": "modifikasyon{{PLURAL:$1|}}",
        "createacct-benefit-body2": "paj{{PLURAL:$1|}}",
        "createacct-benefit-body3": "{{PLURAL:$1|kontribitò résan}}",
-       "badretype": "Mo di pas ki zòt sézi pa ka korèsponn.",
+       "badretype": "Modipas-ya ki zòt sézi pa ka korèsponn.",
        "usernameinprogress": "Oun kréyasyon di kont pou sa non d'itilizatò ja an kour.\nSouplé, pasyanté.",
        "userexists": "Non d'itilizatò sézi ja itilizé.\nSouplé, chwézi roun non diféran.",
        "loginerror": "Lérò di konnègsyon",
        "nosuchusershort": "I pa gen kontribitò ké non-an « $1 ».\nSouplé, vérifyé lòrtograf.",
        "nouserspecified": "Zòt divèt sézi roun non d'itilizatò.",
        "login-userblocked": "{{GENDER:$1|Sa itilizatò}} bloké. Konnègsyon-an pa otorizé.",
-       "wrongpassword": "Non d'itilizatò oben mo di pas enkorèk.\nSouplé, éséyé òkò.",
+       "wrongpassword": "Non-an di itilizatò oben modipas enkorèk.\nSouplé, éséyé òkò.",
        "wrongpasswordempty": "Zòt pa rantré pyès modipas.\nSouplé, éséyé òkò.",
        "passwordtooshort": "Zòt mo di pas divèt kontni omwen $1 karaktèr{{PLURAL:$1|}}.",
-       "passwordtoolong": "Mo di pas pa pouvé dépasé $1 karaktèr{{PLURAL:$1|}}.",
-       "passwordtoopopular": "Mo di pas ki tròp kouran pa pouvé fika itilizé. Souplé, chwézi roun mo di pas pli difisil à douviné.",
+       "passwordtoolong": "Modipas-ya pa pouvé dépasé $1 karagtèr{{PLURAL:$1|}}.",
+       "passwordtoopopular": "Modipas ki tròp kouran pa pouvé fika itilizé. Souplé, chwézi roun modipas ki pi difisil pou sonjé.",
        "password-name-match": "Zòt mo di pas divèt fika diféran di zòt non d'itilizatò.",
        "password-login-forbidden": "Litilizasyon-an di sa non d'itilizatò oben di sa modipas sa entèrdi.",
        "mailmypassword": "Réynisyalizé modipas-a",
        "newpassword": "Nouvèl modipas :",
        "retypenew": "Konfirmen modipas nòv-a :",
        "resetpass_submit": "Chanjé modipas-a é konnègté so kò.",
-       "changepassword-success": "Zòt modipas modifyé !",
+       "changepassword-success": "Zòt modipas chanjé !",
        "changepassword-throttled": "Zòt fè tròp di tantativ di konnègsyon résaman. \nSouplé, antann $1 anvan di réyéséyé.",
        "botpasswords": "Modipas di robo",
        "botpasswords-summary": "<em>Modipas-ya di robo</em> ka pèrmèt di agsédé à roun kont itilizatò vya API-a san itilizé idantifyan-yan di konnègsyon prensipal. Drwè itilizatò-ya ki disponnib lò to konnègté ké roun modipas robo pouvé fika rédjwi.\n\nSi zòt pa ka wè poukisa zòt ké lé fè sa, a ki zòt pa benzwen di fè sa. Pésonn divèt janmen doumandé zòt di an jénéré roun é di bay li.",
        "botpasswords-disabled": "Modipas-ya di robo dézagtivé.",
        "botpasswords-no-central-id": "Pou itilizé modipas-ya di robo, zòt divèt fika konnègté à roun kont ki santralizé.",
        "botpasswords-existing": "Modipas di robo ki ka ègzisté",
-       "botpasswords-createnew": "Kréyé roun mo di pas nòv di robo",
+       "botpasswords-createnew": "Kréyé roun nouvèl modipas di robo",
        "botpasswords-editexisting": "Modifyé roun modipas di robo ki ka ègzisté",
        "botpasswords-label-needsreset": "(Modipas-a divèt fika réynisyalizé)",
        "botpasswords-label-appid": "Non di robo :",
        "botpasswords-newpassword": "Nouvèl modipas-a pou konnègté so kò à<strong>$1</strong> sa <strong>$2</strong>. <em>Souplé, anréjistré li pou fè référans asou li iltèryòrman.</em><br> (Pou ansyen robo-ya ki ka nésésité ki non-an ki fourni pou konnègsyon-an ka fika menm-an ki non-an di itilizatò évantchwèl, zòt pouvé osi itilizé <strong>$3</strong> kou non di itilizatò é <strong>$4</strong> kou modipas).",
        "botpasswords-no-provider": "BotPasswordsSessionProvider pa disponnib.",
        "botpasswords-restriction-failed": "Rèstrigsyon-yan di modipas di robo ka anpéché sa konnègsyon.",
-       "botpasswords-invalid-name": "Non-an d'itilizatò spésifyé pa ka kontni di séparatò di mo di pas di robo (« $1 »).",
+       "botpasswords-invalid-name": "Non-an d'itilizatò ki èspésifyé pa ka kontni di séparatò di modipas di robo (« $1 »).",
        "botpasswords-not-exist": "{{GENDER:$1|Itilizatò|Itilizatris}}-a « $1 » pa gen di mo di pas di robo nonmen « $2 ».",
        "botpasswords-needs-reset": "Modipas-a di robo di non « $2 » di itilizatò-a « $1 » divèt fika réynisyalizé.",
        "resetpass_forbidden": "Modipas-ya pa pouvé fika chanjé.",
-       "resetpass_forbidden-reason": "Mo di pas pa pouvé fika modifyé : $1",
+       "resetpass_forbidden-reason": "Modipas-ya pa pouvé fika chanjé : $1",
        "resetpass-no-info": "Zòt divèt fika konnègté pou agsédé dirèkman à sa paj.",
        "resetpass-submit-loggedin": "Chanjé di modipas",
        "resetpass-submit-cancel": "Annilé",
        "resetpass-expired-soft": "Zòt modipas èspiré, é divèt fika modifyé. Souplé, chwézi roun nouvèl atchwèlman oben kliké asou « {{int:authprovider-resetpass-skip-label}} » pou fè li plita.",
        "resetpass-validity-soft": "Zòt modipas pa valid : $1\n\nSouplé, chwézi roun nouvèl modipas atchwèlman, oben kliké asou « {{int:authprovider-resetpass-skip-label}} » pou modifyé li plita.",
        "passwordreset": "Réynisyalizasyon di modipas",
-       "passwordreset-text-one": "Ranplisé sa fòrmilèr pou zòt mo di pas.",
+       "passwordreset-text-one": "Ranpli sa fòrmilèr pou réynisyalizé zòt modipas.",
        "passwordreset-emaildisabled": "Fongsyonnalité-ya di kourilèt fika dézagtivé asou sa wiki.",
        "passwordreset-username": "Non di itilizatò :",
        "passwordreset-domain": "Domenn :",
        "protectedarticle": "protéjé « [[$1]] »",
        "modifiedarticleprotection": "modifyé nivo-a di protègsyon di « [[$1]] »",
        "protect-default": "Otorizé tout itilizatò-ya",
-       "restriction-edit": "Modifyé",
+       "restriction-edit": "Chanjé",
        "restriction-move": "Rounonmen",
        "namespace": "Lèspas di non",
        "invert": "Envèrsé sélègsyon-an",
        "pageinfo-magic-words": "{{PLURAL:$1|Mo majik}} ($1)",
        "pageinfo-hidden-categories": "{{PLURAL:$1|Katégori kaché|}} ($1)",
        "pageinfo-templates": "{{PLURAL:$1|Modèl enkli}} ($1)",
-       "pageinfo-toolboxlink": "Lenfòrmasyon asou paj-a",
+       "pageinfo-toolboxlink": "Lenfòrmasyon asou paj",
        "pageinfo-contentpage": "Konté kou paj di kontni",
        "pageinfo-contentpage-yes": "Enren",
        "patrol-log-page": "Journal dé roulèktir",
index 01162a4..1716310 100644 (file)
@@ -86,7 +86,7 @@
        "tog-useeditwarning": "הצגת אזהרה בעת עזיבת דף עריכה עם שינויים שטרם נשמרו",
        "tog-prefershttps": "תמיד להשתמש בתקשורת מאובטחת לאחר הכניסה לחשבון",
        "tog-showrollbackconfirmation": "הצגת הודעת אישור לאחר לחיצה על קישור \"שחזור\"",
-       "tog-showrollbackconfirmation-prerelease-warning": "×\9cתש×\95×\9eת ×\9c×\91×\9a: ×\94×\90פשר×\95ת ×\94×\96×\90ת ×¢×\93×\99×\99×\9f ×\90×\99× ×\94 ×\96×\9e×\99× ×\94. ×\90×\9d {{GENDER:|ת×\92×\93×\99ר|ת×\92×\93×\99ר×\99}} ×\94×\94×¢×\93פ×\94 ×\94×\96×\90ת ×¢×\9bש×\99×\95, ×\94×\91×\97×\99ר×\94 ×©×\9c×\9a ×ª×\99×\96×\9bר [https://meta.wikimedia.org/wiki/WMDE_Technical_Wishes/Rollback#Status ×\9c×\96×\9e×\9f ×©×\94×\90פשר×\95ת ×\94×\96×\90ת ×ª×¦×\90 ×\9c×\90×\95ר].",
+       "tog-showrollbackconfirmation-prerelease-warning": "×\9cתש×\95×\9eת ×\9c×\91×\9a: ×ª×\9b×\95× ×\94 ×\96×\95 ×¢×\93×\99×\99×\9f ×\90×\99× ×\94 ×\96×\9e×\99× ×\94. ×\90×\9d {{GENDER:|תפע×\99×\9c|תפע×\99×\9c×\99}} ×\90ת ×\94×\94×¢×\93פ×\94 ×\94×\96×\90ת ×¢×\9bש×\99×\95, ×\91×\97×\99רת×\9a ×ª×\99ש×\9eר ×\95ת×\99×\9bנס ×\9cת×\95קף [https://meta.wikimedia.org/wiki/WMDE_Technical_Wishes/Rollback#Status ×\9bש×\94ת×\9b×\95× ×\94 ×ª×\94פ×\95×\9a ×\9c×\96×\9e×\99× ×\94].",
        "underline-always": "תמיד",
        "underline-never": "לעולם לא",
        "underline-default": "ברירת המחדל של העיצוב או של הדפדפן",
        "deleting-backlinks-warning": "<strong>אזהרה:</strong> [[Special:WhatLinksHere/{{FULLPAGENAME}}|דפים אחרים]] מקשרים לדף זה (שעומד להימחק) או מכלילים אותו.",
        "deleting-subpages-warning": "<strong>אזהרה:</strong> לדף שעומד להימחק יש [[Special:PrefixIndex/{{FULLPAGENAME}}/|{{PLURAL:$1|דף משנה|$1 דפי משנה|51=יותר מ־50 דפי משנה}}]].",
        "rollback": "שחזור עריכות",
-       "rollback-confirmation-confirm": "× ×\90 ×\9c×\90שר:",
+       "rollback-confirmation-confirm": "×\9c×\90×\99ש×\95ר×\9a:",
        "rollback-confirmation-yes": "שחזור",
        "rollback-confirmation-no": "ביטול",
        "rollbacklink": "שחזור",
        "confirm-unwatch-top": "להסיר את הדף הזה מרשימת המעקב שלך?",
        "confirm-rollback-button": "אישור",
        "confirm-rollback-top": "לשחזר את העריכות בדף זה?",
-       "confirm-rollback-bottom": "×\94פע×\95×\9c×\94 ×\94×\96×\90ת ×ª×©×\97×\96ר ×\91×\90×\95פ×\9f ×\9e×\99×\99×\93×\99 ×\90ת ×\94ש×\99× ×\95×\99×\99×\9d ×©× ×\91×\97ר×\95 ×\91×\93×£ ×\94זה.",
+       "confirm-rollback-bottom": "פע×\95×\9c×\94 ×\96×\95 ×ª×©×\97×\96ר ×\91×\90×\95פ×\9f ×\9e×\99×\99×\93×\99 ×\90ת ×\94ש×\99× ×\95×\99×\99×\9d ×©×\91×\97רת ×\91×\93×£ זה.",
        "confirm-mcrrestore-title": "שחזור גרסה",
        "confirm-mcrundo-title": "ביטול שינוי",
        "mcrundofailed": "הביטול נכשל",
index 2383108..9aeb97d 100644 (file)
                        "Zeljko.filipin"
                ]
        },
-       "tog-underline": "Podcrtavanje poveznica",
-       "tog-hideminor": "Sakrij manje izmjene u nedavnim promjenama",
-       "tog-hidepatrolled": "Sakrij pregledane izmjene u nedavnim promjenama",
-       "tog-newpageshidepatrolled": "Sakrij pregledane stranice iz popisa novih stranica",
-       "tog-hidecategorization": "Sakrij kategorizaciju stranica",
+       "tog-underline": "Podcrtavanje veza:",
+       "tog-hideminor": "Sakrivaj manje izmjene sa popisa nedavnih promjena",
+       "tog-hidepatrolled": "Sakrivaj patrolirane izmjene sa popisa nedavnih promjena",
+       "tog-newpageshidepatrolled": "Sakrivaj patrolirane stranice sa popisa novih stranica",
+       "tog-hidecategorization": "Sakrivaj kategorizaciju stranica",
        "tog-extendwatchlist": "Proširi popis praćenih stranica tako da prikaže sve promjene, ne samo najnovije",
        "tog-usenewrc": "Grupne promjene po stranici u popisu nedavnih izmjena i popisu praćenih stranica (zahtijeva JavaScript)",
        "tog-numberheadings": "Automatski označi naslove brojevima",
        "youhavenewmessagesmulti": "Imate nove poruke na $1",
        "editsection": "uredi",
        "editold": "uredi",
-       "viewsourceold": "vidi izvor",
+       "viewsourceold": "prikaži izvor",
        "editlink": "uredi",
-       "viewsourcelink": "vidi izvornik",
+       "viewsourcelink": "prikaži izvor",
        "editsectionhint": "Uredi odlomak: $1",
        "toc": "Sadržaj",
        "showtoc": "prikaži",
        "perfcached": "Sljedeći podaci su iz međuspremnika i možda nisu najsvježiji. Međuspremnik sadrži $1 {{PLURAL:$1|rezultat|rezultata}} pretraživanja.",
        "perfcachedts": "Sljedeći podaci su iz međuspremnika i posljednji puta su ažurirani u $1. Međuspremnik sadrži $4 {{PLURAL:$4|rezultat|rezultata}} pretraživanja.",
        "querypage-no-updates": "Osvježavanje ove stranice je trenutačno onemogućeno. Nove promjene neće biti vidljive.",
-       "viewsource": "Vidi izvornik",
+       "viewsource": "Prikaži izvor",
        "viewsource-title": "Vidi kôd stranice $1",
        "actionthrottled": "Uređivanje je usporeno",
        "actionthrottledtext": "Kao mjera protiv spama, ograničeni vam je broj ovih radnji u određenom vremenu, i trenutačno ste dostigli to ograničenje. Pokušajte opet za par minuta.",
index 929235c..41135bc 100644 (file)
@@ -98,6 +98,7 @@
        "tog-norollbackdiff": "Ne jelenjenek meg az eltérések visszaállítás után",
        "tog-useeditwarning": "Figyelmeztessen, ha szerkesztéskor a módosítások mentése nélkül akarom elhagyni a lapot",
        "tog-prefershttps": "Mindig biztonságos kapcsolatot használjon, amikor be vagyok jelentkezve",
+       "tog-showrollbackconfirmation": "Megerősítés kérése, amikor a visszaállítás linkre kattintasz",
        "underline-always": "mindig",
        "underline-never": "soha",
        "underline-default": "Felület és böngésző alapértelmezése szerint",
        "deleting-backlinks-warning": "<strong>Figyelem:</strong> [[Special:WhatLinksHere/{{FULLPAGENAME}}|Más lapok]] hivatkoznak a törlendő oldalra (vagy beillesztik azt).",
        "deleting-subpages-warning": "<strong>Figyelem:</strong> A törlésre jelölt lapnak [[Special:PrefixIndex/{{FULLPAGENAME}}/|{{PLURAL:$1|van egy allapja|$1 allapja van|51=több mint 50 allapja van}}]].",
        "rollback": "Szerkesztések visszaállítása",
+       "rollback-confirmation-confirm": "Kérlek erősítsd meg:",
+       "rollback-confirmation-yes": "Visszaállítás",
+       "rollback-confirmation-no": "Mégse",
        "rollbacklink": "visszaállítás",
        "rollbacklinkcount": "$1 szerkesztés visszaállítása",
        "rollbacklinkcount-morethan": "több mint $1 szerkesztés visszaállítása",
        "ipb-confirm": "Blokk megerősítése",
        "ipb-sitewide": "Teljes körű",
        "ipb-partial": "Részleges",
+       "ipb-sitewide-help": "A wiki összes lapja és minden egyéb közreműködési művelet.",
+       "ipb-partial-help": "Meghatározott lapok vagy névterek.",
        "ipb-pages-label": "Lapok",
        "ipb-namespaces-label": "Névterek",
        "badipaddress": "Érvénytelen IP-cím",
        "ipb_expiry_old": "A lejárati idő a múltban van.",
        "ipb_expiry_temp": "A láthatatlan felhasználóinév-blokkok lehetnek állandóak.",
        "ipb_hide_invalid": "A felhasználói fiókot nem lehet elrejteni; több mint $1 szerkesztése van.",
+       "ipb_hide_partial": "Felhasználói nevek elrejtésekor és blokkolásakor a blokknak az egész wikire ki kell terjednie.",
        "ipb_already_blocked": "\"$1\" már blokkolva",
        "ipb-needreblock": "$1 már blokkolva van. Meg szeretnéd változtatni a beállításokat?",
        "ipb-otherblocks-header": "További {{PLURAL:$1|blokk|blokkok}}",
        "confirm-unwatch-top": "El szeretnéd távolítani a lapot a figyelőlistádról?",
        "confirm-rollback-button": "OK",
        "confirm-rollback-top": "Visszavonod a változtatásokat?",
+       "confirm-rollback-bottom": "Ez a művelet azonnal visszaállítja a lap kiválasztott változtatásait.",
        "confirm-mcrrestore-title": "Egy változat visszaállítása",
        "confirm-mcrundo-title": "Egy változtatás visszavonva",
        "mcrundofailed": "A visszavonás nem sikerült",
        "passwordpolicies-policy-maximalpasswordlength": "A jelszó legfeljebb $1 karakter hosszú lehet",
        "passwordpolicies-policy-passwordcannotbepopular": "A jelszó nem {{PLURAL:$1|lehet a gyakran használt jelszó|szerepelhet a(z) $1 leggyakrabban használt jelszó listáján}}",
        "passwordpolicies-policy-passwordnotinlargeblacklist": "A jelszó nem szerepelhet a 100 000 leggyakrabban használt jelszó listáján .",
+       "passwordpolicies-policyflag-forcechange": "lecserélés követelése bejelentkezéskor",
+       "passwordpolicies-policyflag-suggestchangeonlogin": "lecserélés ajánlása bejelentkezéskor",
        "unprotected-js": "Biztonsági okokból JavaScript nem tölthető be védtelen lapokról. Kérlek egyedül a MediaWiki névtérben készíts JavaScriptet, vagy szerkesztői allapként."
 }
index edeeb8a..d7eb2bb 100644 (file)
        "help": "Helpo",
        "help-mediawiki": "Helpo pri MediaWiki",
        "search": "Sercho",
-       "search-ignored-headings": " #<!-- mantenez ica lineo sen modifiki --> <pre>\n# Tituli qui ignoresos per la sistemo di serchado.\n# Modifiki en ca parto efikeskos balde pos la titulo di la pagino adicionesos a l'indexo.\n# Tu povas acelerar la riindexigo di la pagino facante nihila editado.\n# La sintaxo esas quale infre:\n#   * Omna texti qui finas kun la signo \"#\" fine de la lineo, esas komentaro.\n#   * Omna lineo ne blanka - to esas: skriptata -, esas l'exakta titulo por ignorar la diferi inter mayuskula e minuskula literi, ed altra.\nReferi\nExtera ligili\nVidez anke\n #</pre> <!-- mantenez ica lineo sen modifiki -->",
+       "search-ignored-headings": " #<!-- mantenez ica lineo sen modifiki --> <pre>\n# Tituli qui ignoresos dal sistemo di serchado.\n# Modifiki en ca parto efikeskos balde pos la titulo di la pagino adicionesos a l'indexo.\n# Tu povas acelerar la riindexigo di la pagino facante nihila editado.\n# La sintaxo esas quale infre:\n#   * Omna texti qui finas kun la signo \"#\" fine de la lineo, esas komentaro.\n#   * Omna lineo ne blanka - to esas: skriptata -, esas l'exakta titulo por ignorar la diferi inter mayuskula e minuskula literi, ed altra.\nReferi\nExtera ligili\nVidez anke\n #</pre> <!-- mantenez ica lineo sen modifiki -->",
        "searchbutton": "Serchez",
        "go": "Irar",
        "searcharticle": "Irez",
index 2d3e88b..20ebf2a 100644 (file)
@@ -71,6 +71,7 @@
        "tog-useeditwarning": "Предупреди ме кога сакам да напуштам страница за уредување без да ги имам зачувано промените",
        "tog-prefershttps": "Секогаш најавувај ме преку безбедна врска",
        "tog-showrollbackconfirmation": "Прикажи потврдница при стискање на врската за отповикување",
+       "tog-showrollbackconfirmation-prerelease-warning": "Имајте предвид: Оваа можност сè уште не е достапна. Ако ја зададете поставката сега, изборот ќе ви се зачува [https://meta.wikimedia.org/wiki/WMDE_Technical_Wishes/Rollback#Status кога ќе излезе алатката].",
        "underline-always": "Секогаш",
        "underline-never": "Никогаш",
        "underline-default": "Според рувото или прелистувачот",
        "deleting-backlinks-warning": "<strong>Предупредување:</strong>  До страницата што сакате да ја избришете водат [[Special:WhatLinksHere/{{FULLPAGENAME}}|други страници]] или пак се превметнуваат во неа.",
        "deleting-subpages-warning": "<strong>Предупредување:</strong> Страницата што сакате да ја избришете има [[Special:PrefixIndex/{{FULLPAGENAME}}/|{{PLURAL:$1|потстраница|$1 потстраници|51=преку 50 потстраници}}]].",
        "rollback": "Отповикај промени",
-       "rollback-confirmation-confirm": "Ð\94а {{PLURAL:$1|0=ги Ð¾Ñ\82повикам Ð¾Ð²Ð¸Ðµ Ñ\83Ñ\80едÑ\83ваÑ\9aа|оÑ\82повикам ÐµÐ´Ð½Ð¾ Ñ\83Ñ\80едÑ\83ваÑ\9aе|оÑ\82повикам $1 Ñ\83Ñ\80едÑ\83ваÑ\9aа}}?",
+       "rollback-confirmation-confirm": "Ð\9fоÑ\82вÑ\80деÑ\82е:",
        "rollback-confirmation-yes": "Отповикај",
        "rollback-confirmation-no": "Откажи",
        "rollbacklink": "отповикај",
index 62e2047..61d40cb 100644 (file)
        "rightslogtext": "Ini ialah log perubahan terhadap hak pengguna.",
        "action-read": "membaca laman ini",
        "action-edit": "menyunting laman ini",
-       "action-createpage": "mencipta laman",
-       "action-createtalk": "mencipta laman perbincangan",
+       "action-createpage": "ciptakan laman ini",
+       "action-createtalk": "ciptakan laman perbincangan ini",
        "action-createaccount": "mencipta akaun pengguna ini",
        "action-history": "melihat sejarah halaman ini",
        "action-minoredit": "menanda suntingan ini sebagai suntingan kecil",
index 89ea2a3..ff71467 100644 (file)
        "cantrollback": "Bô-hoat-tō· kā siu-kái ká-tńg--khì; téng ūi kòng-hiàn-chiá sī chit ia̍h î-it ê chok-chiá.",
        "alreadyrolled": "Bô-hoat-tō· kā [[User:$2|$2]] ([[User talk:$2|Thó-lūn]]) tùi [[:$1]] ê siu-kái ká-tńg-khì; í-keng ū lâng siu-kái a̍h-sī ká-tńg chit ia̍h. Téng 1 ūi siu-kái-chiá sī [[User:$3|$3]] ([[User talk:$3|Thó-lūn]]).",
        "editcomment": "Siu-kái phêng-lūn sī: <em>$1</em>.",
-       "protectedarticle": "pó-hō͘ \"[[$1]]\"",
+       "protectedarticle": "pó-hō͘ liáu \"[[$1]]\"",
        "protect-title": "Kái-piàn \"$1\" ê pó-hō͘ chân-kip",
        "prot_1movedto2": "[[$1]] sóa khì tī [[$2]]",
        "protect-legend": "Khak-tēng beh pó-hō·",
        "protectcomment": "Lí-iû:",
-       "protect-level-autoconfirmed": "Chí ín-chún chū-tōng khak-jīn iōng-chiá",
-       "protect-level-sysop": "Chí ín-chún koán-lí jîn-oân",
+       "protect-level-autoconfirmed": "Ta ín-chún chū-tōng khak-jīn iōng-chiá",
+       "protect-level-sysop": "Ta ín-chún koán-lí jîn-oân",
+       "protect-expiring": "chì $1 (UTC) kòe-kî",
+       "protect-expiring-local": "chì $1 kòe-kî",
        "protect-cascade": "Cascading protection - pó-hō͘ jīm-hô pau-hâm tī chit ia̍h ê ia̍h.",
        "restriction-edit": "Siu-kái",
        "restriction-move": "Sóa khì",
index fc17a3d..45457f5 100644 (file)
@@ -2425,7 +2425,6 @@ mkdir
 mms
 mobile
 mobileformat
-mobilelanding
 mobileview
 modified
 modifiedarticleprotection
index f515df7..61c63e9 100644 (file)
@@ -839,6 +839,7 @@ TEXT
                if ( $newAddress === false ) {
                        return false;
                }
+               $newAddress = trim( $newAddress );
                if ( strpos( $newAddress, ':' ) === false ) {
                        $newAddress = SqlBlobStore::makeAddressFromTextId( intval( $newAddress ) );
                }
diff --git a/maintenance/manageForeignResources.php b/maintenance/manageForeignResources.php
new file mode 100644 (file)
index 0000000..54554b8
--- /dev/null
@@ -0,0 +1,86 @@
+<?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
+ * @ingroup Maintenance
+ */
+
+require_once __DIR__ . '/Maintenance.php';
+
+/**
+ * Manage foreign resources registered with ResourceLoader.
+ *
+ * @ingroup Maintenance
+ * @since 1.32
+ */
+class ManageForeignResources extends Maintenance {
+       public function __construct() {
+               parent::__construct();
+               $this->addDescription( <<<TEXT
+Manage foreign resources registered with ResourceLoader.
+
+This helps developers with downloading, verifying, and updating local copies of upstream
+libraries registered as ResourceLoader modules. See resources/lib/foreign-resources.yaml.
+
+Use the "update" action to download urls specified in foreign-resources.yaml, and unpack
+them to the resources directory. This will also verify them against the integrity hashes.
+
+Use the "verify" action to verify the files currently in the resources directory match
+what "update" would replace them with. This is effectively a dry-run and will not change
+any module resources on disk.
+
+Use the "make-sri" action to compute an integrity hash for upstreams that do not publish
+one themselves. Add or update the urls foreign-resources.yaml as needed, but omit (or
+leave empty) the "integrity" key. Then, run the "make-sri" action for the module and
+copy the integrity into the file. Then, you can use "verify" or "update" normally.
+TEXT
+               );
+               $this->addArg( 'action', 'One of "update", "verify" or "make-sri"', true );
+               $this->addArg( 'module', 'Name of a single module (Default: all)', false );
+               $this->addOption( 'verbose', 'Be verbose', false, false, 'v' );
+       }
+
+       /**
+        * @return bool
+        * @throws Exception
+        */
+       public function execute() {
+               global $IP;
+               $frm = new ForeignResourceManager(
+                        "{$IP}/resources/lib/foreign-resources.yaml",
+                        "{$IP}/resources/lib",
+                       function ( $text ) {
+                               $this->output( $text );
+                       },
+                       function ( $text ) {
+                               $this->error( $text );
+                       },
+                       function ( $text ) {
+                               if ( $this->hasOption( 'verbose' ) ) {
+                                       $this->output( $text );
+                               }
+                       }
+               );
+
+               $action = $this->getArg( 0 );
+               $module = $this->getArg( 1, 'all' );
+               return $frm->run( $action, $module );
+       }
+}
+
+$maintClass = ManageForeignResources::class;
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/resources/foreign-resources.yaml b/maintenance/resources/foreign-resources.yaml
deleted file mode 100644 (file)
index d4458aa..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-### Format of this file
-#
-# The top-level keys are directory names (under resources/lib/).
-# They should match module names (as registered in Resources.php), but there are exceptions.
-# Each top-level key holds a resource descriptor that must have one of
-# the following `type` values:
-#
-# - `tar`: For tarball archive (may be gzip-compressed).
-# - `file: For a plain file.
-# - `multi-file`: For multiple plain files.
-#
-### Type tar
-#
-# The `src` and `integrity` keys are required.
-#
-# * `src`: Full URL to the remote resource.
-# * `integrity`: Cryptographic hash (integrity metadata format per <https://www.w3.org/TR/SRI/>).
-# * `dest`: An object mapping paths to files or directory from the remote resource to a destination
-#    in the module directory. The value of key in dest may be omitted, which will extract the key
-#    directly to the module directory.
-#
-### Type file
-#
-# The `src` and `integrity` keys are required.
-#
-# * `src`: Full URL to the remote resource.
-# * `integrity`: Cryptographic hash (integrity metadata format per <https://www.w3.org/TR/SRI/>).
-# * `dest`: The name of the file in the module directory. Default: Basename of URL.
-#
-### Type multi-file
-#
-# The `files` key is required.
-#
-# * `files`: An object mapping destination paths to an object containing `src` and `integrity`
-#    keys.
-
-CLDRPluralRuleParser:
-  type: file
-  src: https://raw.githubusercontent.com/santhoshtr/CLDRPluralRuleParser/0dda851/src/CLDRPluralRuleParser.js
-  integrity: sha384-M4taeYYG2+9Ob1/La16iO+zlRRmBV5lBR3xUKkQT6kfkJ0aLbCi6yc0RYI1BDzdh
-
-easy-deflate:
-  type: multi-file
-  files:
-    deflate.js:
-      src: https://raw.githubusercontent.com/edg2s/Easy-Deflate/7a6056e5302f6f385ff2efa60afda45b4ad81e51/deflate.js
-      integrity: sha384-sHnZLDSWMUhA2w9ygkzCK8YFvoh/fQKY6lXMbvmrYzjuNURiLB0DZFCDNMpGyZ77
-    easydeflate.js:
-      src: https://raw.githubusercontent.com/edg2s/Easy-Deflate/7a6056e5302f6f385ff2efa60afda45b4ad81e51/easydeflate.js
-      integrity: sha384-EwPfP2RMkDPa1HkzQsXgzTsy1KEjcIzQPA1HDS/JPHjvEMvVUsCxWwm1oXql/jk2
-    inflate.js:
-      src: https://raw.githubusercontent.com/edg2s/Easy-Deflate/7a6056e5302f6f385ff2efa60afda45b4ad81e51/inflate.js
-      integrity: sha384-hMg44Hw424mUYvmzKl0JT4J8UU/1YYhTiGRtR0YX/MXNLK9qWTK0d62FBCDGxmxw
-    README.md:
-      src: https://raw.githubusercontent.com/edg2s/Easy-Deflate/7a6056e5302f6f385ff2efa60afda45b4ad81e51/README.md
-      integrity: sha384-6kwcfCLivvqXBZy2ATyya+mTVWLk3eaQyBdC6tbpBtkygnBrM2SNkq3jz/l7IkvP
-
-html5shiv:
-  type: file
-  src: https://raw.githubusercontent.com/aFarkas/html5shiv/3.7.3/src/html5shiv.js
-  integrity: sha384-RPXhaTf22QktT8KTwZ6bUz/C+7CnccaIw5W/y/t0FW5WSDGj3wc3YtRIJC0w47in
-
-jquery:
-  type: file
-  src: https://code.jquery.com/jquery-3.3.1.js
-  # Integrity from link modals https://code.jquery.com/jquery/
-  integrity: sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=
-  dest: jquery.js
-
-jquery.client:
-  type: tar
-  src: https://registry.npmjs.org/jquery-client/-/jquery-client-2.0.2.tgz
-  integrity: sha256-8c8nBbBykHEMc4I7ksdKJvvw/P7WkaC2X46RTPdz/pw=
-  dest:
-    package/AUTHORS.txt:
-    package/jquery.client.js:
-    package/LICENSE-MIT:
-    package/README.md:
-
-jquery.cookie:
-  type: multi-file
-  files:
-    jquery.cookie.js:
-      src: https://raw.githubusercontent.com/carhartl/jquery-cookie/v1.3.1/jquery.cookie.js
-      integrity: sha384-Xxq63E9KDgzUJ6WPNPqVeOtRIwZyx6y9DzEwY2u6LYKSnWrjSoGtWSKmTindYBf2
-    MIT-LICENSE.txt:
-      src: https://raw.githubusercontent.com/carhartl/jquery-cookie/v1.3.1/MIT-LICENSE.txt
-      integrity: sha384-zYsGf3KJ7S0AhOICjcoh0kkn7aGZlzYUXXX5xz8dwR9KjLMM+/JPR2g/jVOGGeId
-    CHANGELOG.md:
-      src: https://raw.githubusercontent.com/carhartl/jquery-cookie/v1.3.1/CHANGELOG.md
-      integrity: sha384-SQOHhLc7PHxHDQpGE/zv9XfXKL0A7OBu8kuyVDnHVp+zSoWyRw4xUJ+LSm5ql4kS
-
-jquery.form:
-  type: file
-  src: https://raw.githubusercontent.com/jquery-form/form/ff80d9ddf4/jquery.form.js
-  integrity: sha384-h4G2CrcSbixzMvrrK259cNBYaL/vS1D4+KdUN9NJDzQnTU1bQ6Avluget+Id13M7
-  dest: jquery.form.js
-
-jquery.fullscreen:
-  type: file
-  src: https://raw.githubusercontent.com/theopolisme/jquery-fullscreen/v2.1.0/jquery.fullscreen.js
-  integrity: sha384-G4KPs2d99tgcsyUnJ3eeZ1r2hEKDwZfc4+/xowL/LIemq2VVwEE8HpVAWt4WYNLR
-  dest: jquery.fullscreen.js
-
-jquery.hoverIntent:
-  type: file
-  src: https://raw.githubusercontent.com/briancherne/jquery-hoverIntent/823603fdac/jquery.hoverIntent.js
-  integrity: sha384-lca0haN0hqFGGh2aYUhtAgX9dhVHfQnTADH4svDeM6gcXnL7aFGeAi1NYwipDMyS
-  dest: jquery.hoverIntent.js
-
-jquery.jStorage:
-  type: file
-  src: https://raw.githubusercontent.com/andris9/jStorage/v0.4.12/jstorage.js
-  integrity: sha384-geMeN8k803kPp6cqRL4VNfuSM1L8DcbKRk0St/KHJzxgpX9S0y9FA6HxA/JgucrJ
-  dest: jstorage.js
-
-jquery.throttle-debounce:
-  type: file
-  src: https://raw.githubusercontent.com/cowboy/jquery-throttle-debounce/v1.1/jquery.ba-throttle-debounce.js
-  integrity: sha384-ULOy4DbAghrCqRcrTJLXOY9e4gDpWh0BeEf6xMSL0VtNudXWggcb6AmrVrl4KDAP
-  dest: jquery.ba-throttle-debounce.js
-
-moment:
-  type: tar
-  src: https://codeload.github.com/moment/moment/tar.gz/2.24.0
-  integrity: sha384-2/I9rfqkN8AAgh5wOXXphuo827uV7lMmOodrCfIvqC6W6JKKiDGOwd+lE3e8R0yz
-  dest:
-    moment-2.24.0/moment.js:
-    moment-2.24.0/CHANGELOG.md:
-    moment-2.24.0/README.md:
-    moment-2.24.0/LICENSE:
-    moment-2.24.0/locale/*.js: locale
-
-mustache:
-  type: multi-file
-  files:
-    mustache.js:
-      src: https://raw.githubusercontent.com/janl/mustache.js/v1.0.0/mustache.js
-      integrity: sha384-k2UYqmzoiq/qgIzZvcYBxbXQW4YdPAsXDOTkHTGb9TCZ9sjCkyT4TlaUN0wQRkql
-    LICENSE:
-      src: https://raw.githubusercontent.com/janl/mustache.js/v1.0.0/LICENSE
-      integrity: sha384-MYVwXwula9+YkyXexOJVZ0v0DaVvG22uX57mNq5Di+7u8OH9EG9q3yuXkp1Iehiq
-
-oojs:
-  type: tar
-  src: https://registry.npmjs.org/oojs/-/oojs-2.2.2.tgz
-  integrity: sha256-ebgQW2EGrSkBCnDJBGqDpsBDjA3PMN/M8U5DyLHt9mw=
-  dest:
-    package/dist/oojs.jquery.js:
-    package/AUTHORS.txt:
-    package/LICENSE-MIT:
-    package/README.md:
-
-oojs-router:
-  type: tar
-  src: https://registry.npmjs.org/oojs-router/-/oojs-router-0.2.0.tgz
-  integrity: sha384-VngYqdQ3vTDMXbm4e4FUZCCGos7fB0Jkr9V+kBL5MElprK1h0yQZOzBNnMHtSJS/
-  dest:
-    package/dist/oojs-router.js:
-    package/LICENSE:
-    package/AUTHORS.txt:
-    package/History.md:
-
-ooui:
-  type: tar
-  src: https://registry.npmjs.org/oojs-ui/-/oojs-ui-0.31.1.tgz
-  integrity: sha384-M9KdU6u02zSKCVczcw6YJmSvFLhdeagNg9CPhizYVqrybL8bamrF5u6YfrFGEyiv
-  dest:
-    # Main stuff
-    package/dist/oojs-ui-core.js{,.map.json}:
-    package/dist/oojs-ui-core-{wikimediaui,apex}.css:
-    package/dist/oojs-ui-widgets.js{,.map.json}:
-    package/dist/oojs-ui-widgets-{wikimediaui,apex}.css:
-    package/dist/oojs-ui-toolbars.js{,.map.json}:
-    package/dist/oojs-ui-toolbars-{wikimediaui,apex}.css:
-    package/dist/oojs-ui-windows.js{,.map.json}:
-    package/dist/oojs-ui-windows-{wikimediaui,apex}.css:
-    package/dist/oojs-ui-{wikimediaui,apex}.js{,.map.json}:
-    package/dist/i18n:
-    package/dist/images:
-    # WikimediaUI theme
-    package/dist/themes/wikimediaui/images/icons/*.{svg,png}: themes/wikimediaui/images/icons
-    package/dist/themes/wikimediaui/images/indicators/*.{svg,png}: themes/wikimediaui/images/indicators
-    package/dist/themes/wikimediaui/images/textures/*.{gif,svg}: themes/wikimediaui/images/textures
-    package/src/themes/wikimediaui/*.json: themes/wikimediaui
-    package/dist/wikimedia-ui-base.less:
-    # Apex theme (icons, indicators, and textures)
-    package/src/themes/apex/*.json: themes/apex
-    # Misc stuff
-    package/dist/AUTHORS.txt:
-    package/dist/History.md:
-    package/dist/LICENSE-MIT:
-    package/dist/README.md:
-
-qunitjs:
-  type: multi-file
-  # Integrity from link modals at https://code.jquery.com/qunit/
-  files:
-    qunit.js:
-      src: http://code.jquery.com/qunit/qunit-2.9.1.js
-      integrity: sha256-eNccBdxd8zReziWcVjEsPeyJDi3LKMYnzMXyDv8bzsU=
-    qunit.css:
-      src: https://code.jquery.com/qunit/qunit-2.9.1.css
-      integrity: sha256-SSS7o92V7wzcIFg3qnJL9mc4msePaT4klbxtuSGvVVo=
-
-sinonjs:
-  type: file
-  src: https://sinonjs.org/releases/sinon-1.17.7.js
-  integrity: sha384-wR63Jwy75KqwBfzCmXd6gYws6uj3qV/XMAybzXrkEYGYG3AQ58ZWwr1fVpkHa5e8
-  dest: sinon.js
diff --git a/maintenance/resources/manageForeignResources.php b/maintenance/resources/manageForeignResources.php
deleted file mode 100644 (file)
index 6de82c0..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-<?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
- * @ingroup Maintenance
- */
-
-require_once __DIR__ . '/../Maintenance.php';
-
-/**
- * Manage foreign resources registered with ResourceLoader.
- *
- * @ingroup Maintenance
- * @since 1.32
- */
-class ManageForeignResources extends Maintenance {
-       public function __construct() {
-               parent::__construct();
-               $this->addDescription( <<<TEXT
-Manage foreign resources registered with ResourceLoader.
-
-This helps developers to download, verify and update local copies of upstream
-libraries registered as ResourceLoader modules. See also foreign-resources.yaml.
-
-For sources that don't publish an integrity hash, omit "integrity" (or leave empty)
-and run the "make-sri" action to compute the missing hashes.
-
-This script runs in dry-run mode by default. Use --update to actually change,
-remove, or add files to resources/lib/.
-TEXT
-               );
-               $this->addArg( 'action', 'One of "update", "verify" or "make-sri"', true );
-               $this->addArg( 'module', 'Name of a single module (Default: all)', false );
-               $this->addOption( 'verbose', 'Be verbose', false, false, 'v' );
-       }
-
-       /**
-        * @return bool
-        * @throws Exception
-        */
-       public function execute() {
-               global $IP;
-               $frm = new ForeignResourceManager(
-                        __DIR__ . '/foreign-resources.yaml',
-                        "{$IP}/resources/lib",
-                       function ( $text ) {
-                               $this->output( $text );
-                       },
-                       function ( $text ) {
-                               $this->error( $text );
-                       },
-                       function ( $text ) {
-                               if ( $this->hasOption( 'verbose' ) ) {
-                                       $this->output( $text );
-                               }
-                       }
-               );
-
-               $action = $this->getArg( 0 );
-               $module = $this->getArg( 1, 'all' );
-               return $frm->run( $action, $module );
-       }
-}
-
-$maintClass = ManageForeignResources::class;
-require_once RUN_MAINTENANCE_IF_MAIN;
index 5e5f308..b2d0ad2 100644 (file)
@@ -592,6 +592,7 @@ return [
                'group' => 'jquery.ui',
        ],
        'jquery.ui.spinner' => [
+               'deprecated' => 'Please use "jquery.spinner" instead.',
                'scripts' => 'resources/lib/jquery.ui/jquery.ui.spinner.js',
                'dependencies' => [
                        'jquery.ui.core',
diff --git a/resources/lib/foreign-resources.yaml b/resources/lib/foreign-resources.yaml
new file mode 100644 (file)
index 0000000..f862850
--- /dev/null
@@ -0,0 +1,259 @@
+# ## Format of this file
+#
+# The top-level keys in this file correspond with directories under resources/lib/.
+# These in turn are registered as module bundles in Resources.php.
+#
+# ## How to install an foreign resource
+#
+# 1. Add or update the url(s) for the upstream module to this YAML file.
+#
+#    Look at other modules for examples. To install a module from npm,
+#    we use the tarball distribution from npmjs.org. This is the same as what
+#    the npm CLI uses. For example, to install jquery-client@9.2.0, use:
+#    <https://registry.npmjs.org/jquery-client/-/jquery-client-9.2.0.tgz>.
+#
+# 2. If the upstream maintainers publish an integrity hash, set that as well.
+#    Otherwise, use manageForeignResources.php to compute the integrity hash.
+#
+#    Run `php manageForeignResources.php make-sri "my module name"`
+#
+#    This will download the specified file(s) and print their integrity hashes,
+#    already formatted in YAML, ready for copying to this file.
+#
+# 3. Last but not least, decide where files go.
+#
+#    If you specified a direct url to JavaScript or CSS file, this step is
+#    optional. See the corresponding documentation section below for more
+#    information and examples for "dest" keys. Once you've set any "dest" keys,
+#    run `php manageForeignResources.php update "my module name"`.
+#
+# ## Package formats
+#
+# Each top-level key must use one of these types:
+#
+# - `file`: For a plain file.
+# - `multi-file`: For multiple plain files.
+# - `tar`: For a tarball archive (may be compressed).
+#
+# ### The "file" type
+#
+# * `src`: Full URL to the remote resource.
+# * `integrity`: Cryptographic hash (integrity metadata format per <https://www.w3.org/TR/SRI/>).
+# * `dest`: [optional] The file name to use in the module directory. Default: Basename of URL.
+#
+# For example, the following would produce resources/lib/mymodule/x.js:
+#
+#     mymodule:
+#       type: file
+#       src: https://mymodule.example/1.2.3/x.js
+#       integrity: sha384-Je+NE+saisQuoi
+#
+# ### The "multi-file" type
+#
+# * `files`: An object mapping destination paths to `src` and `integrity` keys.
+#
+# For example:
+#
+#     mymodule:
+#       type: multi-file
+#       files:
+#         x.js:
+#           src: https://mymodule.example/1.2.3/x.js
+#           integrity: sha384-Je+NE+saisQuoi
+#         x.css:
+#           src: https://mymodule.example/1.2.3/x.css
+#           integrity: sha384-Je+NE+saisQuoi
+#
+# ### The "tar" type
+#
+# * `src`: Full URL to the remote resource.
+# * `integrity`: Cryptographic hash (integrity metadata format per <https://www.w3.org/TR/SRI/>).
+# * `dest`: [optional] The default is to extract all files from the package.
+#    To only extract some of the files or directories, use "dest" to specify
+#    files, directories, and/or glob patterns. You can use a site like https://unpkg.com/
+#    to easily inspect an npm package, like <https://unpkg.com/jquery-client@2.0.2/>.
+#
+# For example:
+#
+#     mymodule:
+#       type: tar
+#       src: https://registry.npmjs.org/jquery-client/-/jquery-client-9.2.0.tgz
+#       integrity: sha384-Je+NE+saisQuoi
+#       dest:
+#         package/dist/x.js:
+#         package/dist/i18n:
+#         package/dist/style/*.css:
+#
+# The would extract the "x.js" file, the "i18n" directory (recursive),
+# and any "*.css" files from the "style" directory.
+#
+
+CLDRPluralRuleParser:
+  type: file
+  src: https://raw.githubusercontent.com/santhoshtr/CLDRPluralRuleParser/0dda851/src/CLDRPluralRuleParser.js
+  integrity: sha384-M4taeYYG2+9Ob1/La16iO+zlRRmBV5lBR3xUKkQT6kfkJ0aLbCi6yc0RYI1BDzdh
+
+easy-deflate:
+  type: multi-file
+  files:
+    deflate.js:
+      src: https://raw.githubusercontent.com/edg2s/Easy-Deflate/7a6056e5302f6f385ff2efa60afda45b4ad81e51/deflate.js
+      integrity: sha384-sHnZLDSWMUhA2w9ygkzCK8YFvoh/fQKY6lXMbvmrYzjuNURiLB0DZFCDNMpGyZ77
+    easydeflate.js:
+      src: https://raw.githubusercontent.com/edg2s/Easy-Deflate/7a6056e5302f6f385ff2efa60afda45b4ad81e51/easydeflate.js
+      integrity: sha384-EwPfP2RMkDPa1HkzQsXgzTsy1KEjcIzQPA1HDS/JPHjvEMvVUsCxWwm1oXql/jk2
+    inflate.js:
+      src: https://raw.githubusercontent.com/edg2s/Easy-Deflate/7a6056e5302f6f385ff2efa60afda45b4ad81e51/inflate.js
+      integrity: sha384-hMg44Hw424mUYvmzKl0JT4J8UU/1YYhTiGRtR0YX/MXNLK9qWTK0d62FBCDGxmxw
+    README.md:
+      src: https://raw.githubusercontent.com/edg2s/Easy-Deflate/7a6056e5302f6f385ff2efa60afda45b4ad81e51/README.md
+      integrity: sha384-6kwcfCLivvqXBZy2ATyya+mTVWLk3eaQyBdC6tbpBtkygnBrM2SNkq3jz/l7IkvP
+
+html5shiv:
+  type: file
+  src: https://raw.githubusercontent.com/aFarkas/html5shiv/3.7.3/src/html5shiv.js
+  integrity: sha384-RPXhaTf22QktT8KTwZ6bUz/C+7CnccaIw5W/y/t0FW5WSDGj3wc3YtRIJC0w47in
+
+jquery:
+  type: file
+  src: https://code.jquery.com/jquery-3.3.1.js
+  # Integrity from link modals https://code.jquery.com/jquery/
+  integrity: sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=
+  dest: jquery.js
+
+jquery.client:
+  type: tar
+  src: https://registry.npmjs.org/jquery-client/-/jquery-client-2.0.2.tgz
+  integrity: sha256-8c8nBbBykHEMc4I7ksdKJvvw/P7WkaC2X46RTPdz/pw=
+  dest:
+    package/AUTHORS.txt:
+    package/jquery.client.js:
+    package/LICENSE-MIT:
+    package/README.md:
+
+jquery.cookie:
+  type: multi-file
+  files:
+    jquery.cookie.js:
+      src: https://raw.githubusercontent.com/carhartl/jquery-cookie/v1.3.1/jquery.cookie.js
+      integrity: sha384-Xxq63E9KDgzUJ6WPNPqVeOtRIwZyx6y9DzEwY2u6LYKSnWrjSoGtWSKmTindYBf2
+    MIT-LICENSE.txt:
+      src: https://raw.githubusercontent.com/carhartl/jquery-cookie/v1.3.1/MIT-LICENSE.txt
+      integrity: sha384-zYsGf3KJ7S0AhOICjcoh0kkn7aGZlzYUXXX5xz8dwR9KjLMM+/JPR2g/jVOGGeId
+    CHANGELOG.md:
+      src: https://raw.githubusercontent.com/carhartl/jquery-cookie/v1.3.1/CHANGELOG.md
+      integrity: sha384-SQOHhLc7PHxHDQpGE/zv9XfXKL0A7OBu8kuyVDnHVp+zSoWyRw4xUJ+LSm5ql4kS
+
+jquery.form:
+  type: file
+  src: https://raw.githubusercontent.com/jquery-form/form/ff80d9ddf4/jquery.form.js
+  integrity: sha384-h4G2CrcSbixzMvrrK259cNBYaL/vS1D4+KdUN9NJDzQnTU1bQ6Avluget+Id13M7
+
+jquery.fullscreen:
+  type: file
+  src: https://raw.githubusercontent.com/theopolisme/jquery-fullscreen/v2.1.0/jquery.fullscreen.js
+  integrity: sha384-G4KPs2d99tgcsyUnJ3eeZ1r2hEKDwZfc4+/xowL/LIemq2VVwEE8HpVAWt4WYNLR
+
+jquery.hoverIntent:
+  type: file
+  src: https://raw.githubusercontent.com/briancherne/jquery-hoverIntent/823603fdac/jquery.hoverIntent.js
+  integrity: sha384-lca0haN0hqFGGh2aYUhtAgX9dhVHfQnTADH4svDeM6gcXnL7aFGeAi1NYwipDMyS
+
+jquery.jStorage:
+  type: file
+  src: https://raw.githubusercontent.com/andris9/jStorage/v0.4.12/jstorage.js
+  integrity: sha384-geMeN8k803kPp6cqRL4VNfuSM1L8DcbKRk0St/KHJzxgpX9S0y9FA6HxA/JgucrJ
+
+jquery.throttle-debounce:
+  type: file
+  src: https://raw.githubusercontent.com/cowboy/jquery-throttle-debounce/v1.1/jquery.ba-throttle-debounce.js
+  integrity: sha384-ULOy4DbAghrCqRcrTJLXOY9e4gDpWh0BeEf6xMSL0VtNudXWggcb6AmrVrl4KDAP
+
+moment:
+  type: tar
+  src: https://codeload.github.com/moment/moment/tar.gz/2.24.0
+  integrity: sha384-2/I9rfqkN8AAgh5wOXXphuo827uV7lMmOodrCfIvqC6W6JKKiDGOwd+lE3e8R0yz
+  dest:
+    moment-2.24.0/moment.js:
+    moment-2.24.0/CHANGELOG.md:
+    moment-2.24.0/README.md:
+    moment-2.24.0/LICENSE:
+    moment-2.24.0/locale/*.js: locale
+
+mustache:
+  type: multi-file
+  files:
+    mustache.js:
+      src: https://raw.githubusercontent.com/janl/mustache.js/v1.0.0/mustache.js
+      integrity: sha384-k2UYqmzoiq/qgIzZvcYBxbXQW4YdPAsXDOTkHTGb9TCZ9sjCkyT4TlaUN0wQRkql
+    LICENSE:
+      src: https://raw.githubusercontent.com/janl/mustache.js/v1.0.0/LICENSE
+      integrity: sha384-MYVwXwula9+YkyXexOJVZ0v0DaVvG22uX57mNq5Di+7u8OH9EG9q3yuXkp1Iehiq
+
+oojs:
+  type: tar
+  src: https://registry.npmjs.org/oojs/-/oojs-2.2.2.tgz
+  integrity: sha256-ebgQW2EGrSkBCnDJBGqDpsBDjA3PMN/M8U5DyLHt9mw=
+  dest:
+    package/dist/oojs.jquery.js:
+    package/AUTHORS.txt:
+    package/LICENSE-MIT:
+    package/README.md:
+
+oojs-router:
+  type: tar
+  src: https://registry.npmjs.org/oojs-router/-/oojs-router-0.2.0.tgz
+  integrity: sha384-VngYqdQ3vTDMXbm4e4FUZCCGos7fB0Jkr9V+kBL5MElprK1h0yQZOzBNnMHtSJS/
+  dest:
+    package/dist/oojs-router.js:
+    package/LICENSE:
+    package/AUTHORS.txt:
+    package/History.md:
+
+ooui:
+  type: tar
+  src: https://registry.npmjs.org/oojs-ui/-/oojs-ui-0.31.1.tgz
+  integrity: sha384-M9KdU6u02zSKCVczcw6YJmSvFLhdeagNg9CPhizYVqrybL8bamrF5u6YfrFGEyiv
+  dest:
+    # Main stuff
+    package/dist/oojs-ui-core.js{,.map.json}:
+    package/dist/oojs-ui-core-{wikimediaui,apex}.css:
+    package/dist/oojs-ui-widgets.js{,.map.json}:
+    package/dist/oojs-ui-widgets-{wikimediaui,apex}.css:
+    package/dist/oojs-ui-toolbars.js{,.map.json}:
+    package/dist/oojs-ui-toolbars-{wikimediaui,apex}.css:
+    package/dist/oojs-ui-windows.js{,.map.json}:
+    package/dist/oojs-ui-windows-{wikimediaui,apex}.css:
+    package/dist/oojs-ui-{wikimediaui,apex}.js{,.map.json}:
+    package/dist/i18n:
+    package/dist/images:
+    # WikimediaUI theme
+    package/dist/themes/wikimediaui/images/icons/*.{svg,png}: themes/wikimediaui/images/icons
+    package/dist/themes/wikimediaui/images/indicators/*.{svg,png}: themes/wikimediaui/images/indicators
+    package/dist/themes/wikimediaui/images/textures/*.{gif,svg}: themes/wikimediaui/images/textures
+    package/src/themes/wikimediaui/*.json: themes/wikimediaui
+    package/dist/wikimedia-ui-base.less:
+    # Apex theme (icons, indicators, and textures)
+    package/src/themes/apex/*.json: themes/apex
+    # Misc stuff
+    package/dist/AUTHORS.txt:
+    package/dist/History.md:
+    package/dist/LICENSE-MIT:
+    package/dist/README.md:
+
+qunitjs:
+  type: multi-file
+  # Integrity from link modals at https://code.jquery.com/qunit/
+  files:
+    qunit.js:
+      src: http://code.jquery.com/qunit/qunit-2.9.1.js
+      integrity: sha256-eNccBdxd8zReziWcVjEsPeyJDi3LKMYnzMXyDv8bzsU=
+    qunit.css:
+      src: https://code.jquery.com/qunit/qunit-2.9.1.css
+      integrity: sha256-SSS7o92V7wzcIFg3qnJL9mc4msePaT4klbxtuSGvVVo=
+
+sinonjs:
+  type: file
+  src: https://sinonjs.org/releases/sinon-1.17.7.js
+  integrity: sha384-wR63Jwy75KqwBfzCmXd6gYws6uj3qV/XMAybzXrkEYGYG3AQ58ZWwr1fVpkHa5e8
+  dest: sinon.js
index 92e1d04..c2d4835 100644 (file)
@@ -1,13 +1,3 @@
-.feedback-spinner {
-       display: inline-block;
-       zoom: 1;
-       *display: inline; /* IE7 and below */ /* stylelint-disable declaration-block-no-duplicate-properties */
-       /* @embed */
-       background: url( images/spinner.gif );
-       width: 18px;
-       height: 18px;
-}
-
 .mw-feedbackDialog-welcome-message,
 .mw-feedbackDialog-feedback-terms {
        line-height: 1.4;
index 5b73e7c..3ffc496 100644 (file)
                        padded: true
                } );
 
-               this.$spinner = $( '<div>' )
-                       .addClass( 'feedback-spinner' );
-
                // Feedback form
                this.feedbackMessageLabel = new OO.ui.LabelWidget( {
                        classes: [ 'mw-feedbackDialog-welcome-message' ]
diff --git a/resources/src/mediawiki.feedback/images/spinner.gif b/resources/src/mediawiki.feedback/images/spinner.gif
deleted file mode 100644 (file)
index aed0ea4..0000000
Binary files a/resources/src/mediawiki.feedback/images/spinner.gif and /dev/null differ
index 63da95a..453bf03 100644 (file)
         *
         * @param {OO.ui.TextInputWidget} textInputWidget Text input widget
         * @param {number} [limit] Byte limit, defaults to $input's maxlength
+        * @param {Function} [filterFunction] Function to call on the string before assessing the length.
         */
-       mw.widgets.visibleByteLimit = function ( textInputWidget, limit ) {
+       mw.widgets.visibleByteLimit = function ( textInputWidget, limit, filterFunction ) {
                limit = limit || +textInputWidget.$input.attr( 'maxlength' );
+               if ( !filterFunction || typeof filterFunction !== 'function' ) {
+                       filterFunction = undefined;
+               }
 
                function updateCount() {
-                       var remaining = limit - byteLength( textInputWidget.getValue() );
+                       var value = textInputWidget.getValue(),
+                               remaining;
+                       if ( filterFunction ) {
+                               value = filterFunction( value );
+                       }
+                       remaining = limit - byteLength( value );
                        if ( remaining > 99 ) {
                                remaining = '';
                        } else {
@@ -32,7 +41,7 @@
                updateCount();
 
                // Actually enforce limit
-               textInputWidget.$input.byteLimit( limit );
+               textInputWidget.$input.byteLimit( limit, filterFunction );
        };
 
        /**
         * Uses jQuery#codePointLimit to enforce the limit.
         *
         * @param {OO.ui.TextInputWidget} textInputWidget Text input widget
-        * @param {number} [limit] Byte limit, defaults to $input's maxlength
+        * @param {number} [limit] Code point limit, defaults to $input's maxlength
+        * @param {Function} [filterFunction] Function to call on the string before assessing the length.
         */
-       mw.widgets.visibleCodePointLimit = function ( textInputWidget, limit ) {
+       mw.widgets.visibleCodePointLimit = function ( textInputWidget, limit, filterFunction ) {
                limit = limit || +textInputWidget.$input.attr( 'maxlength' );
+               if ( !filterFunction || typeof filterFunction !== 'function' ) {
+                       filterFunction = undefined;
+               }
 
                function updateCount() {
-                       var remaining = limit - codePointLength( textInputWidget.getValue() );
+                       var value = textInputWidget.getValue(),
+                               remaining;
+                       if ( filterFunction ) {
+                               value = filterFunction( value );
+                       }
+                       remaining = limit - codePointLength( value );
                        if ( remaining > 99 ) {
                                remaining = '';
                        } else {
@@ -60,7 +78,7 @@
                updateCount();
 
                // Actually enforce limit
-               textInputWidget.$input.codePointLimit( limit );
+               textInputWidget.$input.codePointLimit( limit, filterFunction );
        };
 
 }() );
index d8330ef..b03a309 100644 (file)
@@ -223,8 +223,6 @@ class MessageCacheTest extends MediaWikiLangTestCase {
 
        /**
         * Regression test for T218918
-        * @group Broken
-        * @fixme Disabled per https://phabricator.wikimedia.org/T219042
         */
        public function testLoadFromDB_fetchLatestRevision() {
                // Create three revisions of the same message page.
@@ -239,7 +237,7 @@ class MessageCacheTest extends MediaWikiLangTestCase {
                $importRevision = new WikiRevision( new HashConfig() );
                $importRevision->setTitle( $r3->getTitle() );
                $importRevision->setComment( 'Imported edit' );
-               $importRevision->setTimestamp( '19991122334455' );
+               $importRevision->setTimestamp( '19991122001122' );
                $importRevision->setText( 'IMPORTED OLD TEST' );
                $importRevision->setUsername( 'Alan Smithee' );
 
index d35843b..80e12cd 100644 (file)
@@ -91,7 +91,7 @@ describe( 'Page', function () {
 
                // check
                HistoryPage.open( name );
-               assert.strictEqual( HistoryPage.comment.getText(), `(Created or updated page with "${content}")` );
+               assert.strictEqual( HistoryPage.comment.getText(), `Created or updated page with "${content}"` );
        } );
 
        it( 'should be deletable', function () {