From e6c7fa26e938d06fb1eb274e90f7ab22667c7cd8 Mon Sep 17 00:00:00 2001 From: Reedy Date: Sun, 10 May 2020 02:14:35 +0100 Subject: [PATCH 01/16] Fixup some SELECT * usages in sqlite schema patches Bug: T252311 Change-Id: I7abdb7db89873c20f3a79df9452ab45c59ca6395 --- maintenance/sqlite/archives/patch-categorylinks-fix-pk.sql | 6 +++--- maintenance/sqlite/archives/patch-iwlinks-fix-pk.sql | 6 +++--- maintenance/sqlite/archives/patch-langlinks-fix-pk.sql | 6 +++--- maintenance/sqlite/archives/patch-log_search-fix-pk.sql | 6 +++--- maintenance/sqlite/archives/patch-module_deps-fix-pk.sql | 6 +++--- maintenance/sqlite/archives/patch-objectcache-fix-pk.sql | 6 +++--- .../sqlite/archives/patch-querycache_info-fix-pk.sql | 6 +++--- maintenance/sqlite/archives/patch-site_stats-fix-pk.sql | 6 +++--- maintenance/sqlite/archives/patch-text-fix-pk.sql | 6 +++--- .../sqlite/archives/patch-user_former_groups-fix-pk.sql | 6 +++--- .../sqlite/archives/patch-user_properties-fix-pk.sql | 6 +++--- 11 files changed, 33 insertions(+), 33 deletions(-) diff --git a/maintenance/sqlite/archives/patch-categorylinks-fix-pk.sql b/maintenance/sqlite/archives/patch-categorylinks-fix-pk.sql index 13a75a36f9..6bf2295510 100644 --- a/maintenance/sqlite/archives/patch-categorylinks-fix-pk.sql +++ b/maintenance/sqlite/archives/patch-categorylinks-fix-pk.sql @@ -40,8 +40,8 @@ CREATE TABLE /*_*/categorylinks_tmp ( PRIMARY KEY (cl_from,cl_to) ) /*$wgDBTableOptions*/; -INSERT INTO /*_*/categorylinks_tmp - SELECT * +INSERT INTO /*_*/categorylinks_tmp(cl_from, cl_to, cl_sortkey, cl_sortkey_prefix, cl_timestamp, cl_collation, cl_type) + SELECT cl_from, cl_to, cl_sortkey, cl_sortkey_prefix, cl_timestamp, cl_collation, cl_type FROM /*_*/categorylinks; DROP TABLE /*_*/categorylinks; @@ -57,4 +57,4 @@ CREATE INDEX /*i*/cl_sortkey ON /*_*/categorylinks (cl_to,cl_type,cl_sortkey,cl_ CREATE INDEX /*i*/cl_timestamp ON /*_*/categorylinks (cl_to,cl_timestamp); -- Used when updating collation (e.g. updateCollation.php) -CREATE INDEX /*i*/cl_collation_ext ON /*_*/categorylinks (cl_collation, cl_to, cl_type, cl_from); \ No newline at end of file +CREATE INDEX /*i*/cl_collation_ext ON /*_*/categorylinks (cl_collation, cl_to, cl_type, cl_from); diff --git a/maintenance/sqlite/archives/patch-iwlinks-fix-pk.sql b/maintenance/sqlite/archives/patch-iwlinks-fix-pk.sql index 91ce25196d..e973c9d750 100644 --- a/maintenance/sqlite/archives/patch-iwlinks-fix-pk.sql +++ b/maintenance/sqlite/archives/patch-iwlinks-fix-pk.sql @@ -10,8 +10,8 @@ CREATE TABLE /*_*/iwlinks_tmp ( PRIMARY KEY (iwl_from,iwl_prefix,iwl_title) ) /*$wgDBTableOptions*/; -INSERT INTO /*_*/iwlinks_tmp - SELECT * FROM /*_*/iwlinks; +INSERT INTO /*_*/iwlinks_tmp(iwl_from, iwl_prefix, iwl_title) + SELECT iwl_from, iwl_prefix, iwl_title FROM /*_*/iwlinks; DROP TABLE /*_*/iwlinks; @@ -21,4 +21,4 @@ ALTER TABLE /*_*/iwlinks_tmp RENAME TO /*_*/iwlinks; CREATE INDEX /*i*/iwl_prefix_title_from ON /*_*/iwlinks (iwl_prefix, iwl_title, iwl_from); -- Index for ApiQueryIWLinks -CREATE INDEX /*i*/iwl_prefix_from_title ON /*_*/iwlinks (iwl_prefix, iwl_from, iwl_title); \ No newline at end of file +CREATE INDEX /*i*/iwl_prefix_from_title ON /*_*/iwlinks (iwl_prefix, iwl_from, iwl_title); diff --git a/maintenance/sqlite/archives/patch-langlinks-fix-pk.sql b/maintenance/sqlite/archives/patch-langlinks-fix-pk.sql index da096aceb0..ee164cc103 100644 --- a/maintenance/sqlite/archives/patch-langlinks-fix-pk.sql +++ b/maintenance/sqlite/archives/patch-langlinks-fix-pk.sql @@ -10,12 +10,12 @@ CREATE TABLE /*_*/langlinks_tmp ( PRIMARY KEY (ll_from,ll_lang) ) /*$wgDBTableOptions*/; -INSERT INTO /*_*/langlinks_tmp - SELECT * FROM /*_*/langlinks; +INSERT INTO /*_*/langlinks_tmp(ll_from, ll_lang, ll_title) + SELECT ll_from, ll_lang, ll_title FROM /*_*/langlinks; DROP TABLE /*_*/langlinks; ALTER TABLE /*_*/langlinks_tmp RENAME TO /*_*/langlinks; -- Index for ApiQueryLangbacklinks -CREATE INDEX /*i*/ll_lang ON /*_*/langlinks (ll_lang, ll_title); \ No newline at end of file +CREATE INDEX /*i*/ll_lang ON /*_*/langlinks (ll_lang, ll_title); diff --git a/maintenance/sqlite/archives/patch-log_search-fix-pk.sql b/maintenance/sqlite/archives/patch-log_search-fix-pk.sql index 153e415014..7c559930f0 100644 --- a/maintenance/sqlite/archives/patch-log_search-fix-pk.sql +++ b/maintenance/sqlite/archives/patch-log_search-fix-pk.sql @@ -8,11 +8,11 @@ CREATE TABLE /*_*/log_search_tmp ( PRIMARY KEY (ls_field,ls_value,ls_log_id) ) /*$wgDBTableOptions*/; -INSERT INTO /*_*/log_search_tmp - SELECT * FROM /*_*/log_search; +INSERT INTO /*_*/log_search_tmp(ls_field, ls_value, ls_log_id) + SELECT ls_field, ls_value, ls_log_id FROM /*_*/log_search; DROP TABLE /*_*/log_search; ALTER TABLE /*_*/log_search_tmp RENAME TO /*_*/log_search; -CREATE INDEX /*i*/ls_log_id ON /*_*/log_search (ls_log_id); \ No newline at end of file +CREATE INDEX /*i*/ls_log_id ON /*_*/log_search (ls_log_id); diff --git a/maintenance/sqlite/archives/patch-module_deps-fix-pk.sql b/maintenance/sqlite/archives/patch-module_deps-fix-pk.sql index 73bcbe23f4..bf5153fd4b 100644 --- a/maintenance/sqlite/archives/patch-module_deps-fix-pk.sql +++ b/maintenance/sqlite/archives/patch-module_deps-fix-pk.sql @@ -8,9 +8,9 @@ CREATE TABLE /*_*/module_deps_tmp ( PRIMARY KEY (md_module,md_skin) ) /*$wgDBTableOptions*/; -INSERT INTO /*_*/module_deps_tmp - SELECT * FROM /*_*/module_deps; +INSERT INTO /*_*/module_deps_tmp(md_module, md_skin, md_deps) + SELECT md_module, md_skin, md_deps FROM /*_*/module_deps; DROP TABLE /*_*/module_deps; -ALTER TABLE /*_*/module_deps_tmp RENAME TO /*_*/module_deps; \ No newline at end of file +ALTER TABLE /*_*/module_deps_tmp RENAME TO /*_*/module_deps; diff --git a/maintenance/sqlite/archives/patch-objectcache-fix-pk.sql b/maintenance/sqlite/archives/patch-objectcache-fix-pk.sql index f2bef5838d..c3228a9b65 100644 --- a/maintenance/sqlite/archives/patch-objectcache-fix-pk.sql +++ b/maintenance/sqlite/archives/patch-objectcache-fix-pk.sql @@ -4,11 +4,11 @@ CREATE TABLE /*_*/objectcache_tmp ( exptime datetime ) /*$wgDBTableOptions*/; -INSERT INTO /*_*/objectcache_tmp - SELECT * FROM /*_*/objectcache; +INSERT INTO /*_*/objectcache_tmp(keyname, "value", exptime) + SELECT keyname, "value", exptime FROM /*_*/objectcache; DROP TABLE /*_*/objectcache; ALTER TABLE /*_*/objectcache_tmp RENAME TO /*_*/objectcache; -CREATE INDEX /*i*/exptime ON /*_*/objectcache (exptime); \ No newline at end of file +CREATE INDEX /*i*/exptime ON /*_*/objectcache (exptime); diff --git a/maintenance/sqlite/archives/patch-querycache_info-fix-pk.sql b/maintenance/sqlite/archives/patch-querycache_info-fix-pk.sql index d9483be4e9..6960667fa1 100644 --- a/maintenance/sqlite/archives/patch-querycache_info-fix-pk.sql +++ b/maintenance/sqlite/archives/patch-querycache_info-fix-pk.sql @@ -7,9 +7,9 @@ CREATE TABLE /*_*/querycache_info_tmp ( qci_timestamp binary(14) NOT NULL default '19700101000000' ) /*$wgDBTableOptions*/; -INSERT INTO /*_*/querycache_info_tmp - SELECT * FROM /*_*/querycache_info; +INSERT INTO /*_*/querycache_info_tmp(qci_type, qci_timestamp) + SELECT qci_type, qci_timestamp FROM /*_*/querycache_info; DROP TABLE /*_*/querycache_info; -ALTER TABLE /*_*/querycache_info_tmp RENAME TO /*_*/querycache_info; \ No newline at end of file +ALTER TABLE /*_*/querycache_info_tmp RENAME TO /*_*/querycache_info; diff --git a/maintenance/sqlite/archives/patch-site_stats-fix-pk.sql b/maintenance/sqlite/archives/patch-site_stats-fix-pk.sql index d785e9841c..b5b60f1534 100644 --- a/maintenance/sqlite/archives/patch-site_stats-fix-pk.sql +++ b/maintenance/sqlite/archives/patch-site_stats-fix-pk.sql @@ -25,9 +25,9 @@ CREATE TABLE /*_*/site_stats_tmp ( ss_images int default 0 ) /*$wgDBTableOptions*/; -INSERT INTO /*_*/site_stats_tmp - SELECT * FROM /*_*/site_stats; +INSERT INTO /*_*/site_stats_tmp(ss_row_id, ss_total_edits, ss_good_articles, ss_total_pages, ss_users, ss_active_users, ss_images) + SELECT ss_row_id, ss_total_edits, ss_good_articles, ss_total_pages, ss_users, ss_active_users, ss_images FROM /*_*/site_stats; DROP TABLE /*_*/site_stats; -ALTER TABLE /*_*/site_stats_tmp RENAME TO /*_*/site_stats; \ No newline at end of file +ALTER TABLE /*_*/site_stats_tmp RENAME TO /*_*/site_stats; diff --git a/maintenance/sqlite/archives/patch-text-fix-pk.sql b/maintenance/sqlite/archives/patch-text-fix-pk.sql index 380887b179..623bdb3c02 100644 --- a/maintenance/sqlite/archives/patch-text-fix-pk.sql +++ b/maintenance/sqlite/archives/patch-text-fix-pk.sql @@ -29,9 +29,9 @@ CREATE TABLE /*_*/text_tmp ( old_flags tinyblob NOT NULL ) /*$wgDBTableOptions*/ MAX_ROWS=10000000 AVG_ROW_LENGTH=10240; -INSERT INTO /*_*/text_tmp - SELECT * FROM /*_*/text; +INSERT INTO /*_*/text_tmp(old_id, old_text, old_flags) + SELECT old_id, old_text, old_flags FROM /*_*/text; DROP TABLE /*_*/text; -ALTER TABLE /*_*/text_tmp RENAME TO /*_*/text; \ No newline at end of file +ALTER TABLE /*_*/text_tmp RENAME TO /*_*/text; diff --git a/maintenance/sqlite/archives/patch-user_former_groups-fix-pk.sql b/maintenance/sqlite/archives/patch-user_former_groups-fix-pk.sql index 4f5d62253a..969c24b5d1 100644 --- a/maintenance/sqlite/archives/patch-user_former_groups-fix-pk.sql +++ b/maintenance/sqlite/archives/patch-user_former_groups-fix-pk.sql @@ -5,9 +5,9 @@ CREATE TABLE /*_*/user_former_groups_tmp ( PRIMARY KEY (ufg_user,ufg_group) ) /*$wgDBTableOptions*/; -INSERT INTO /*_*/user_former_groups_tmp - SELECT * FROM /*_*/user_former_groups; +INSERT INTO /*_*/user_former_groups_tmp(ufg_user, ufg_group) + SELECT ufg_user, ufg_group FROM /*_*/user_former_groups; DROP TABLE /*_*/user_former_groups; -ALTER TABLE /*_*/user_former_groups_tmp RENAME TO /*_*/user_former_groups; \ No newline at end of file +ALTER TABLE /*_*/user_former_groups_tmp RENAME TO /*_*/user_former_groups; diff --git a/maintenance/sqlite/archives/patch-user_properties-fix-pk.sql b/maintenance/sqlite/archives/patch-user_properties-fix-pk.sql index 8362d23365..682f568137 100644 --- a/maintenance/sqlite/archives/patch-user_properties-fix-pk.sql +++ b/maintenance/sqlite/archives/patch-user_properties-fix-pk.sql @@ -10,11 +10,11 @@ CREATE TABLE /*_*/user_properties_tmp ( PRIMARY KEY (up_user,up_property) ) /*$wgDBTableOptions*/; -INSERT INTO /*_*/user_properties_tmp - SELECT * FROM /*_*/user_properties; +INSERT INTO /*_*/user_properties_tmp(up_user, up_property, up_value) + SELECT up_user, up_property, up_value FROM /*_*/user_properties; DROP TABLE /*_*/user_properties; ALTER TABLE /*_*/user_properties_tmp RENAME TO /*_*/user_properties; -CREATE INDEX /*i*/user_properties_property ON /*_*/user_properties (up_property); \ No newline at end of file +CREATE INDEX /*i*/user_properties_property ON /*_*/user_properties (up_property); -- 2.20.1 From 0c9325129a49014376d5772290dd49411e432795 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Mon, 18 May 2020 14:18:14 +1000 Subject: [PATCH 02/16] Backport docs/extension.schema.v2.json fixes * Fix the type of "Hooks" to not accept string (it never would've worked) Bug: T240307 Change-Id: I1a8657ff9fd14618c6709dbab62c3b4ee9f659a5 --- docs/extension.schema.v2.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/extension.schema.v2.json b/docs/extension.schema.v2.json index e13129bb56..9c7290a119 100644 --- a/docs/extension.schema.v2.json +++ b/docs/extension.schema.v2.json @@ -596,7 +596,7 @@ "type": "object" }, "Hooks": { - "type": [ "string", "object" ], + "type": "object", "description": "Hooks this extension uses (mapping of hook name to callback)" }, "JobClasses": { -- 2.20.1 From 198a866e79cdaad94f01ef2ae9cc8d5d4d2b8111 Mon Sep 17 00:00:00 2001 From: Reedy Date: Tue, 26 May 2020 01:28:46 +0100 Subject: [PATCH 03/16] [registration] Remove type of string from Hooks in extension.schema.v1.json Same as it will be or v2 when that patch merges Change-Id: I64c3bbcda0f353fe9c14b0d5bea241e0304c0e2e Follows-Up: I1a8657ff9fd14618c6709dbab62c3b4ee9f659a5 --- docs/extension.schema.v1.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/extension.schema.v1.json b/docs/extension.schema.v1.json index 0763e7de63..4e489cc5ec 100644 --- a/docs/extension.schema.v1.json +++ b/docs/extension.schema.v1.json @@ -575,7 +575,7 @@ "type": "object" }, "Hooks": { - "type": [ "string", "object" ], + "type": "object", "description": "Hooks this extension uses (mapping of hook name to callback)" }, "JobClasses": { -- 2.20.1 From 6517428fbe91d29e854fdb455bd1d3ae35a5d332 Mon Sep 17 00:00:00 2001 From: GeoffreyT2000 Date: Tue, 5 Mar 2019 17:55:49 -0800 Subject: [PATCH 04/16] Set rc_patrolled to 2 for autopatrolled changes in rebuildrecentchanges.php This fixes what rc_patrolled should be for autopatrolled changes. Also, non-upload log entries will have rc_patrolled = 2 for now until T217388 decides what rc_patrolled should be for such entries. In contrast, upload entries can be patrolled unlike other log entries, so they will have rc_patrolled = 0. Bug: T199474 Change-Id: Ib7d1f5f7dd3541768305debee703fd342844714b (cherry picked from commit 87aaf7a1664a1a031f5872ffaf5fd9730db39444) --- maintenance/rebuildrecentchanges.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/maintenance/rebuildrecentchanges.php b/maintenance/rebuildrecentchanges.php index dc8bf290b0..9c2549fc38 100644 --- a/maintenance/rebuildrecentchanges.php +++ b/maintenance/rebuildrecentchanges.php @@ -321,7 +321,7 @@ class RebuildRecentchanges extends Maintenance { 'rc_title' => $row->log_title, 'rc_minor' => 0, 'rc_bot' => 0, - 'rc_patrolled' => 1, + 'rc_patrolled' => $row->log_type == 'upload' ? 0 : 2, 'rc_new' => 0, 'rc_this_oldid' => 0, 'rc_last_oldid' => 0, @@ -439,11 +439,12 @@ class RebuildRecentchanges extends Maintenance { foreach ( $actorQuery['orconds'] as $cond ) { $dbw->update( 'recentchanges', - [ 'rc_patrolled' => 1 ], + [ 'rc_patrolled' => 2 ], [ $cond, 'rc_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $this->cutoffFrom ) ), 'rc_timestamp < ' . $dbw->addQuotes( $dbw->timestamp( $this->cutoffTo ) ), + 'rc_patrolled' => 0 ], __METHOD__ ); -- 2.20.1 From a9beb409f957bec65b8fced623e9aa3d7b7c65a9 Mon Sep 17 00:00:00 2001 From: GeoffreyT2000 Date: Thu, 28 Feb 2019 19:47:38 -0800 Subject: [PATCH 05/16] Update the change_tag table in rebuildrecentchanges.php Without updating the change_tag table, tags will not correctly appear on Special:RecentChanges after running the script. Bug: T229461 Change-Id: Iff12588df1ad8d658091832e38d870dd8b75a32f (cherry picked from commit 4c69162b95afc3dd3d7a1fa51cee207e6fe0171b) --- maintenance/rebuildrecentchanges.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/maintenance/rebuildrecentchanges.php b/maintenance/rebuildrecentchanges.php index 9c2549fc38..03ab64e313 100644 --- a/maintenance/rebuildrecentchanges.php +++ b/maintenance/rebuildrecentchanges.php @@ -168,6 +168,15 @@ class RebuildRecentchanges extends Maintenance { + $actorMigration->getInsertValues( $dbw, 'rc_user', $user ), __METHOD__ ); + + $rcid = $dbw->insertId(); + $dbw->update( + 'change_tag', + [ 'ct_rc_id' => $rcid ], + [ 'ct_rev_id' => $row->rev_id ], + __METHOD__ + ); + if ( ( ++$inserted % $this->getBatchSize() ) == 0 ) { $lbFactory->waitForReplication(); } @@ -340,6 +349,14 @@ class RebuildRecentchanges extends Maintenance { __METHOD__ ); + $rcid = $dbw->insertId(); + $dbw->update( + 'change_tag', + [ 'ct_rc_id' => $rcid ], + [ 'ct_log_id' => $row->log_id ], + __METHOD__ + ); + if ( ( ++$inserted % $this->getBatchSize() ) == 0 ) { $lbFactory->waitForReplication(); } -- 2.20.1 From af0e7338dd24ed7e7e15cc7c47b5a6ba0e376bc0 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Mon, 25 May 2020 13:48:42 +1000 Subject: [PATCH 06/16] Call ob_start() before running tests The policy introduced for T206476 creates a subtle failure mode: any test writing to stdout will cause headers to be sent, causing later tests to fail when they try to call header(). Instead, call ob_start() to intercept test output. Any buffered output is still seen when PHPUnit exits. Bug: T206476 Change-Id: Id085efeab67d1e700ffcbf37868b5107e3a7e5d5 --- tests/phpunit/phpunit.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/phpunit/phpunit.php b/tests/phpunit/phpunit.php index 650cfcfa3a..6036e3fb82 100755 --- a/tests/phpunit/phpunit.php +++ b/tests/phpunit/phpunit.php @@ -124,6 +124,10 @@ class PHPUnitMaintClass extends Maintenance { exit( 1 ); } + // Start an output buffer to avoid headers being sent by constructors, + // data providers, etc. (T206476) + ob_start(); + fwrite( STDERR, defined( 'HHVM_VERSION' ) ? 'Using HHVM ' . HHVM_VERSION . ' (' . PHP_VERSION . ")\n" : 'Using PHP ' . PHP_VERSION . "\n" ); -- 2.20.1 From 4d081c8cd944f54117ec8bd12191d48d75f4d83e Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Tue, 19 Nov 2019 14:36:35 -0500 Subject: [PATCH 07/16] SpecialContributions: Use PoolCounter to limit concurrency Allow using PoolCounter to limit the number of times a user or IP can concurrently load Special:Contributions. By default no limitation is applied. Key 'SpecialContributions' in $wgPoolCounterConf must be set to configure the concurrency. Bug: T234450 Change-Id: Ie769fa170093bfb6d281c651d3857545d139e009 --- RELEASE-NOTES-1.31 | 2 + includes/specials/SpecialContributions.php | 45 +++++++++++++++------- languages/i18n/en.json | 2 + languages/i18n/qqq.json | 2 + 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/RELEASE-NOTES-1.31 b/RELEASE-NOTES-1.31 index bde7d57d8a..88f43aa3d5 100644 --- a/RELEASE-NOTES-1.31 +++ b/RELEASE-NOTES-1.31 @@ -3,6 +3,8 @@ THIS IS NOT A RELEASE YET === Changes since MediaWiki 1.31.7 === +* Per-user concurrency in SpecialContributions can now be limited by setting + $wgPoolCounterConf['SpecialContributions'] appropriately. == MediaWiki 1.31.7 == diff --git a/includes/specials/SpecialContributions.php b/includes/specials/SpecialContributions.php index 6fc8306a52..2812541c16 100644 --- a/includes/specials/SpecialContributions.php +++ b/includes/specials/SpecialContributions.php @@ -230,20 +230,39 @@ class SpecialContributions extends IncludableSpecialPage { } elseif ( !$pager->getNumRows() ) { $out->addWikiMsg( 'nocontribs', $target ); } else { - # Show a message about replica DB lag, if applicable - $lb = MediaWikiServices::getInstance()->getDBLoadBalancer(); - $lag = $lb->safeGetLag( $pager->getDatabase() ); - if ( $lag > 0 ) { - $out->showLagWarning( $lag ); - } - - $output = $pager->getBody(); - if ( !$this->including() ) { - $output = '

' . $pager->getNavigationBar() . '

' . - $output . - '

' . $pager->getNavigationBar() . '

'; + // @todo We just want a wiki ID here, not a "DB domain", but + // current status of MediaWiki conflates the two. See T235955. + $poolKey = WikiMap::getCurrentWikiDbDomain() . ':SpecialContributions:'; + if ( $this->getUser()->isAnon() ) { + $poolKey .= 'a:' . $this->getUser()->getName(); + } else { + $poolKey .= 'u:' . $this->getUser()->getId(); } - $out->addHTML( $output ); + $work = new PoolCounterWorkViaCallback( 'SpecialContributions', $poolKey, [ + 'doWork' => function () use ( $pager, $out ) { + # Show a message about replica DB lag, if applicable + $lb = MediaWikiServices::getInstance()->getDBLoadBalancer(); + $lag = $lb->safeGetLag( $pager->getDatabase() ); + if ( $lag > 0 ) { + $out->showLagWarning( $lag ); + } + + $output = $pager->getBody(); + if ( !$this->including() ) { + $output = '

' . $pager->getNavigationBar() . '

' . + $output . + '

' . $pager->getNavigationBar() . '

'; + } + $out->addHTML( $output ); + }, + 'error' => function () use ( $out ) { + $msg = $this->getUser()->isAnon() + ? 'sp-contributions-concurrency-ip' + : 'sp-contributions-concurrency-user'; + $out->wrapWikiMsg( "
\n$1\n
", $msg ); + } + ] ); + $work->execute(); } $out->preventClickjacking( $pager->getPreventClickjacking() ); diff --git a/languages/i18n/en.json b/languages/i18n/en.json index 86762384a8..13920c0b15 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -2521,6 +2521,8 @@ "sp-contributions-footer-anon-range": "-", "sp-contributions-footer-newbies": "-", "sp-contributions-outofrange": "Unable to show any results. The requested IP range is larger than the CIDR limit of /$1.", + "sp-contributions-concurrency-user": "Sorry, too many requests are being made from your user account. Please try again later.", + "sp-contributions-concurrency-ip": "Sorry, too many requests are being made from your IP address. Please try again later.", "whatlinkshere": "What links here", "whatlinkshere-title": "Pages that link to \"$1\"", "whatlinkshere-summary": "", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index 576c2bf241..e745375132 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -2718,6 +2718,8 @@ "sp-contributions-footer-anon-range": "{{ignored}}This is the footer for IP ranges on [[Special:Contributions]].", "sp-contributions-footer-newbies": "{{ignored}}This is the footer for newbie users on [[Special:Contributions]].", "sp-contributions-outofrange": "Message shown when a user tries to view contributions of an IP range that's too large. $1 is the numerical limit imposed on the CIDR range.", + "sp-contributions-concurrency-user": "Message shown when a logged-in user tries to load [[Special:Contributions]] too many times at once.", + "sp-contributions-concurrency-ip": "Message shown when a logged-out user tries to load [[Special:Contributions]] too many times at once.", "whatlinkshere": "The text of the link in the toolbox (on the left, below the search menu) going to [[Special:WhatLinksHere]].\n\nSee also:\n* {{msg-mw|Whatlinkshere}}\n* {{msg-mw|Accesskey-t-whatlinkshere}}\n* {{msg-mw|Tooltip-t-whatlinkshere}}", "whatlinkshere-title": "Title of the special page [[Special:WhatLinksHere]]. This page appears when you click on the 'What links here' button in the toolbox. $1 is the name of the page concerned.", "whatlinkshere-summary": "{{doc-specialpagesummary|whatlinkshere}}", -- 2.20.1 From 07f9cbf59223f2994a9aab6861d25cf7da886bcd Mon Sep 17 00:00:00 2001 From: Reedy Date: Tue, 23 Jun 2020 00:48:25 +0100 Subject: [PATCH 08/16] Bring RELEASE-NOTES up to date Change-Id: I359ebf5a6f2aec785674080e9ae4724b31b6a0c2 --- RELEASE-NOTES-1.31 | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/RELEASE-NOTES-1.31 b/RELEASE-NOTES-1.31 index 88f43aa3d5..edd827e8ef 100644 --- a/RELEASE-NOTES-1.31 +++ b/RELEASE-NOTES-1.31 @@ -3,8 +3,18 @@ THIS IS NOT A RELEASE YET === Changes since MediaWiki 1.31.7 === -* Per-user concurrency in SpecialContributions can now be limited by setting - $wgPoolCounterConf['SpecialContributions'] appropriately. +* (T199809) Don't invalidate BotPasswords if a password reset email is sent. +* (T247017) PasswordReset performance improvements. +* (T250568) Work around change in SimpleXMLElement behavior introduced in PHP + 7.3.17. +* Remove some rotten and out of date documentation. +* (T252311) Improvements to some older SQLite update patches. +* (T240307) Minor fixes to extension.schema.v2.json and extension.schema.v1.json. +* (T199474) Set rc_patrolled to 2 for autopatrolled changes in + rebuildrecentchanges.php. +* (T206476) Call ob_start() before running tests. +* (T234450) Per-user concurrency in SpecialContributions can now be limited by + setting $wgPoolCounterConf['SpecialContributions'] appropriately. == MediaWiki 1.31.7 == -- 2.20.1 From 2e150e00139b500db741c8fa7a0d7e453ccc25bd Mon Sep 17 00:00:00 2001 From: Reedy Date: Tue, 23 Jun 2020 00:59:02 +0100 Subject: [PATCH 09/16] One more RELEASE-NOTES Change-Id: I5d8518a2c6ba2f4bb4963a21c1101cab17685868 --- RELEASE-NOTES-1.31 | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES-1.31 b/RELEASE-NOTES-1.31 index edd827e8ef..5d7f0c52e8 100644 --- a/RELEASE-NOTES-1.31 +++ b/RELEASE-NOTES-1.31 @@ -12,6 +12,7 @@ THIS IS NOT A RELEASE YET * (T240307) Minor fixes to extension.schema.v2.json and extension.schema.v1.json. * (T199474) Set rc_patrolled to 2 for autopatrolled changes in rebuildrecentchanges.php. +* (T229461) Update the change_tag table in rebuildrecentchanges.php. * (T206476) Call ob_start() before running tests. * (T234450) Per-user concurrency in SpecialContributions can now be limited by setting $wgPoolCounterConf['SpecialContributions'] appropriately. -- 2.20.1 From d5aeff51afd8a451c9185f0f754f86408185c876 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Tue, 31 Mar 2020 17:02:49 +1100 Subject: [PATCH 10/16] SECURITY: Fix accidental public CC headers in img_auth.php Incorrect parameters to FileBackend::streamFile() caused Cache-Control:private and Vary:Cookie response headers to be omitted when requesting a file in a path configured by $wgImgAuthUrlPathMap. Typically this is used to deliver images generated by extensions. CVE-2020-15005 Bug: T248947 Change-Id: I404d9462e4b35d3d832bfab21954ff87e46e3eb2 --- RELEASE-NOTES-1.31 | 2 ++ img_auth.php | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/RELEASE-NOTES-1.31 b/RELEASE-NOTES-1.31 index 5d7f0c52e8..2b48c93dab 100644 --- a/RELEASE-NOTES-1.31 +++ b/RELEASE-NOTES-1.31 @@ -16,6 +16,8 @@ THIS IS NOT A RELEASE YET * (T206476) Call ob_start() before running tests. * (T234450) Per-user concurrency in SpecialContributions can now be limited by setting $wgPoolCounterConf['SpecialContributions'] appropriately. +* (T248947) SECURITY: img_auth.php may leak private extension images into the + public cache. == MediaWiki 1.31.7 == diff --git a/img_auth.php b/img_auth.php index 70570d8649..2caf57ad58 100644 --- a/img_auth.php +++ b/img_auth.php @@ -92,8 +92,10 @@ function wfImageAuthMain() { } if ( $be->fileExists( [ 'src' => $filename ] ) ) { wfDebugLog( 'img_auth', "Streaming `" . $filename . "`." ); - $be->streamFile( [ 'src' => $filename ], - [ 'Cache-Control: private', 'Vary: Cookie' ] ); + $be->streamFile( [ + 'src' => $filename, + 'headers' => [ 'Cache-Control: private', 'Vary: Cookie' ] + ] ); } else { wfForbidden( 'img-auth-accessdenied', 'img-auth-nofile', $path ); } -- 2.20.1 From c759d64146ad3d48c316b0052b7e240def4634da Mon Sep 17 00:00:00 2001 From: Reedy Date: Tue, 23 Jun 2020 01:26:58 +0100 Subject: [PATCH 11/16] Bump and prep 1.31.8 Change-Id: I5d51e01b55235c3303b721cb58e56487acb7a9e4 --- RELEASE-NOTES-1.31 | 2 +- includes/Defines.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASE-NOTES-1.31 b/RELEASE-NOTES-1.31 index 2b48c93dab..6144e690d6 100644 --- a/RELEASE-NOTES-1.31 +++ b/RELEASE-NOTES-1.31 @@ -1,6 +1,6 @@ == MediaWiki 1.31.8 == -THIS IS NOT A RELEASE YET +This is a security and maintenance release of the MediaWiki 1.31 branch. === Changes since MediaWiki 1.31.7 === * (T199809) Don't invalidate BotPasswords if a password reset email is sent. diff --git a/includes/Defines.php b/includes/Defines.php index 214eba5571..9c76fec6b0 100644 --- a/includes/Defines.php +++ b/includes/Defines.php @@ -37,7 +37,7 @@ use Wikimedia\Rdbms\IDatabase; * * @since 1.31.7 */ -define( 'MW_VERSION', '1.31.7' ); +define( 'MW_VERSION', '1.31.8' ); # Obsolete aliases /** -- 2.20.1 From b5f555a3c1b52b6f7387651eb5a04807124f7b39 Mon Sep 17 00:00:00 2001 From: Reedy Date: Tue, 23 Jun 2020 01:30:57 +0100 Subject: [PATCH 12/16] Start 1.31.9 Change-Id: I268d185fa606b7905664ad10d8f8f2c58e05d4d3 --- RELEASE-NOTES-1.31 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RELEASE-NOTES-1.31 b/RELEASE-NOTES-1.31 index 6144e690d6..4351598d90 100644 --- a/RELEASE-NOTES-1.31 +++ b/RELEASE-NOTES-1.31 @@ -1,3 +1,9 @@ +== MediaWiki 1.31.9 == + +THIS IS NOT A RELEASE YET + +=== Changes since MediaWiki 1.31.8 === + == MediaWiki 1.31.8 == This is a security and maintenance release of the MediaWiki 1.31 branch. -- 2.20.1 From b10c41a2947eea81a1b323952c928cda5263f837 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Thu, 25 Jun 2020 16:03:35 +1000 Subject: [PATCH 13/16] In the web installer, use secure session cookies When starting a session when the detected protocol is HTTPS, use cookie_secure=1 so that the session cookie has the secure attribute. Without the secure attribute, a CSRF attack could be used to send cookies over an insecure channel, leaking the session ID to an attacker with network access. Change-Id: I1a4b612425a16da1a7a8fd855f376a377b0b48d7 (cherry picked from commit 9ba8f8d12475a37848eaadae0effae8d956e3342) --- includes/installer/WebInstaller.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/includes/installer/WebInstaller.php b/includes/installer/WebInstaller.php index 8fb980791e..545cc06cae 100644 --- a/includes/installer/WebInstaller.php +++ b/includes/installer/WebInstaller.php @@ -341,11 +341,17 @@ class WebInstaller extends Installer { return true; } + // Use secure cookies if we are on HTTPS + $options = []; + if ( $this->request->getProtocol() === 'https' ) { + $options['cookie_secure'] = '1'; + } + $this->phpErrors = []; set_error_handler( [ $this, 'errorHandler' ] ); try { session_name( 'mw_installer_session' ); - session_start(); + session_start( $options ); } catch ( Exception $e ) { restore_error_handler(); throw $e; -- 2.20.1 From 7fff372a26ea413813ea3037fbc8f51efcdd5a90 Mon Sep 17 00:00:00 2001 From: Kunal Mehta Date: Mon, 6 Jul 2020 12:58:16 -0700 Subject: [PATCH 14/16] shell: Expand documentation in firejail.profile Explain what content should go in the profile and what the two inclusions are for. Bug: T257207 Change-Id: I7a0fbc558a85baa91624414f67f84d2dc23a41bb --- includes/shell/firejail.profile | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/includes/shell/firejail.profile b/includes/shell/firejail.profile index 07f059bad0..d87d3ee9be 100644 --- a/includes/shell/firejail.profile +++ b/includes/shell/firejail.profile @@ -1,7 +1,16 @@ # Firejail profile used by MediaWiki when shelling out +# Most rules are applied via command-line flags controlled by the +# Shell::RESTRICTION_* constants. +# Rules added to this file must be compatible with every command that could +# be invoked. If something might need to be disabled, then it should be added +# as a Shell:RESTRICTION_* constant instead so that commands can opt-in/out. + # See for -# syntax documentation -# Persistent local customizations +# syntax documentation. + +# Optionally allow sysadmins to set extra restrictions that apply to their +# MediaWiki setup, e.g. disallowing access to extra private directories. include /etc/firejail/mediawiki.local -# Persistent global definitions + +# Include any global firejail customizations. include /etc/firejail/globals.local -- 2.20.1 From 32bfea6c4e5a4a1dbf56a9f5a144d434adf63b3a Mon Sep 17 00:00:00 2001 From: Ludovic CHEVALIER Date: Wed, 22 Jul 2020 17:19:05 +0200 Subject: [PATCH 15/16] Init Wiklou repository --- .gitmodules | 19 +++++++++++++++++-- extensions/DismissableSiteNotice | 1 + extensions/Matomo | 1 + extensions/UploadWizard | 1 + extensions/WikimediaMessages | 1 + extensions/intersection | 1 + 6 files changed, 22 insertions(+), 2 deletions(-) create mode 160000 extensions/DismissableSiteNotice create mode 160000 extensions/Matomo create mode 160000 extensions/UploadWizard create mode 160000 extensions/WikimediaMessages create mode 160000 extensions/intersection diff --git a/.gitmodules b/.gitmodules index e722de674f..05dc77a3e5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,7 +16,7 @@ branch = REL1_31 [submodule "extensions/ConfirmEdit"] path = extensions/ConfirmEdit - url = https://gerrit.wikimedia.org/r/mediawiki/extensions/ConfirmEdit + url = https://github.com/wikimedia/mediawiki-extensions-ConfirmEdit/archive/master.tar.gz branch = REL1_31 [submodule "extensions/Gadgets"] path = extensions/Gadgets @@ -101,4 +101,19 @@ [submodule "vendor"] path = vendor url = https://gerrit.wikimedia.org/r/mediawiki/vendor - branch = REL1_31 \ No newline at end of file + branch = REL1_31 +[submodule "extensions/Matomo"] + path = extensions/Matomo + url = https://github.com/DaSchTour/matomo-mediawiki-extension.git +[submodule "extensions/intersection"] + path = extensions/intersection + url = https://github.com/wikimedia/mediawiki-extensions-intersection.git +[submodule "extensions/DismissableSiteNotice"] + path = extensions/DismissableSiteNotice + url = https://github.com/wikimedia/mediawiki-extensions-DismissableSiteNotice +[submodule "extensions/WikimediaMessages"] + path = extensions/WikimediaMessages + url = https://github.com/wikimedia/mediawiki-extensions-WikimediaMessages +[submodule "extensions/UploadWizard"] + path = extensions/UploadWizard + url = https://github.com/wikimedia/mediawiki-extensions-UploadWizard diff --git a/extensions/DismissableSiteNotice b/extensions/DismissableSiteNotice new file mode 160000 index 0000000000..73a6b7220b --- /dev/null +++ b/extensions/DismissableSiteNotice @@ -0,0 +1 @@ +Subproject commit 73a6b7220b85ead337df741cd1ecfe5268dfb1c6 diff --git a/extensions/Matomo b/extensions/Matomo new file mode 160000 index 0000000000..c722fab5ce --- /dev/null +++ b/extensions/Matomo @@ -0,0 +1 @@ +Subproject commit c722fab5ce7d9e35da7de1ce2344b537e36fa73e diff --git a/extensions/UploadWizard b/extensions/UploadWizard new file mode 160000 index 0000000000..1ba0e4e94c --- /dev/null +++ b/extensions/UploadWizard @@ -0,0 +1 @@ +Subproject commit 1ba0e4e94cccda217e38b7853ad947709f00e303 diff --git a/extensions/WikimediaMessages b/extensions/WikimediaMessages new file mode 160000 index 0000000000..a600cfd1d5 --- /dev/null +++ b/extensions/WikimediaMessages @@ -0,0 +1 @@ +Subproject commit a600cfd1d59e3f9336713aee04bbc4e9792af360 diff --git a/extensions/intersection b/extensions/intersection new file mode 160000 index 0000000000..e4419d7f2e --- /dev/null +++ b/extensions/intersection @@ -0,0 +1 @@ +Subproject commit e4419d7f2eda38640978982f67d150cb19ebba55 -- 2.20.1 From 08a0bec2c20f5a40459a51a1254912b78321c3c1 Mon Sep 17 00:00:00 2001 From: Ludovic CHEVALIER Date: Thu, 23 Jul 2020 10:30:29 +0200 Subject: [PATCH 16/16] +extension/Scribunto --- .gitmodules | 10 +++++++++- extensions/Scribunto | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) create mode 160000 extensions/Scribunto diff --git a/.gitmodules b/.gitmodules index 05dc77a3e5..8917c0d8a7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,7 +16,7 @@ branch = REL1_31 [submodule "extensions/ConfirmEdit"] path = extensions/ConfirmEdit - url = https://github.com/wikimedia/mediawiki-extensions-ConfirmEdit/archive/master.tar.gz + url = https://gerrit.wikimedia.org/r/mediawiki/extensions/ConfirmEdit branch = REL1_31 [submodule "extensions/Gadgets"] path = extensions/Gadgets @@ -108,12 +108,20 @@ [submodule "extensions/intersection"] path = extensions/intersection url = https://github.com/wikimedia/mediawiki-extensions-intersection.git + branch = REL1_31 [submodule "extensions/DismissableSiteNotice"] path = extensions/DismissableSiteNotice url = https://github.com/wikimedia/mediawiki-extensions-DismissableSiteNotice + branch = REL1_31 [submodule "extensions/WikimediaMessages"] path = extensions/WikimediaMessages url = https://github.com/wikimedia/mediawiki-extensions-WikimediaMessages + branch = REL1_31 [submodule "extensions/UploadWizard"] path = extensions/UploadWizard url = https://github.com/wikimedia/mediawiki-extensions-UploadWizard + branch = REL1_31 +[submodule "extensions/Scribunto"] + path = extensions/Scribunto + url = https://github.com/wikimedia/mediawiki-extensions-Scribunto + branch = REL1_31 diff --git a/extensions/Scribunto b/extensions/Scribunto new file mode 160000 index 0000000000..106fbf4df8 --- /dev/null +++ b/extensions/Scribunto @@ -0,0 +1 @@ +Subproject commit 106fbf4df8f759e4e2eaa7b753fb38978f9780b4 -- 2.20.1