From 9307d0cb66c1b704605e3b5ac15dbd9a592f256e Mon Sep 17 00:00:00 2001 From: Andrew Green Date: Tue, 27 Feb 2018 12:54:32 -0600 Subject: [PATCH] [PATCH] Cleanup of output escaping None of these issues are exploitable, but will hopefully make the extension more robust against future changes. Co-authored-by: Brian Wolff Bug: T171987 Change-Id: I25ef0aadc52c5ff0b0313135eec44a66f3176a99 --- CentralNoticeBannerLogPager.php | 42 +++++++-------- CentralNoticeCampaignLogPager.php | 59 ++++++++++++---------- CentralNoticePageLogPager.php | 8 +-- includes/CNCampaignPager.php | 8 +-- includes/Campaign.php | 2 +- .../HtmlFormElements/HTMLCentralNoticeBanner.php | 2 +- resources/infrastructure/bannereditor.js | 12 ++--- resources/infrastructure/bannermanager.js | 6 +-- .../vendor/jquery.ui.multiselect/ui.multiselect.js | 8 +-- special/SpecialBannerAllocation.php | 26 +++++----- special/SpecialCentralNotice.php | 12 ++--- special/SpecialCentralNoticeBanners.php | 38 +++++++------- special/SpecialCentralNoticeLogs.php | 6 ++- special/SpecialGlobalAllocation.php | 38 +++++++------- special/SpecialNoticeTemplate.php | 6 +-- 15 files changed, 141 insertions(+), 132 deletions(-) diff --git a/CentralNoticeBannerLogPager.php b/CentralNoticeBannerLogPager.php index 15e90bf..9fbdf21 100644 --- a/CentralNoticeBannerLogPager.php +++ b/CentralNoticeBannerLogPager.php @@ -41,7 +41,7 @@ class CentralNoticeBannerLogPager extends CentralNoticeCampaignLogPager { // Create the user page link $userLink = Linker::linkKnown( $loggedUser->getUserPage(), - $loggedUser->getName() + htmlspecialchars( $loggedUser->getName() ) ); $userTalkLink = Linker::linkKnown( $loggedUser->getTalkPage(), @@ -63,26 +63,29 @@ class CentralNoticeBannerLogPager extends CentralNoticeCampaignLogPager { 'collapsed-rtl.png' : 'collapsed-ltr.png'; - $htmlOut .= '' . + $tmplogId = (int)$row->tmplog_id; + $htmlOut .= '' . '' . '' . ''; } $htmlOut .= Xml::closeElement( 'td' ); - $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top', 'class' => 'primary' ], + $htmlOut .= Xml::element( 'td', [ 'valign' => 'top', 'class' => 'primary' ], $lang->date( $row->tmplog_timestamp ) . ' ' . $lang->time( $row->tmplog_timestamp ) ); $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top', 'class' => 'primary' ], - $this->msg( 'centralnotice-user-links', $userLink, $userTalkLink )->text() + $this->msg( 'centralnotice-user-links' ) + ->rawParams( $userLink, $userTalkLink ) + ->parse() ); // Give grep a chance to find the usages: // centralnotice-action-created, centralnotice-action-modified, // centralnotice-action-removed - $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top', 'class' => 'primary' ], + $htmlOut .= Xml::element( 'td', [ 'valign' => 'top', 'class' => 'primary' ], $this->msg( 'centralnotice-action-'.$row->tmplog_action )->text() ); $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top', 'class' => 'primary' ], @@ -108,7 +111,7 @@ class CentralNoticeBannerLogPager extends CentralNoticeCampaignLogPager { if ( $row->tmplog_action !== 'removed' ) { // Begin log entry secondary row $htmlOut .= Xml::openElement( 'tr', - [ 'id' => 'cn-log-details-'.$row->tmplog_id, 'style' => 'display:none;' ] ); + [ 'id' => 'cn-log-details-'.$tmplogId, 'style' => 'display:none;' ] ); $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top' ], ' ' // force a table cell in older browsers @@ -169,17 +172,17 @@ class CentralNoticeBannerLogPager extends CentralNoticeCampaignLogPager { 'centralnotice-log-label', $this->msg( 'centralnotice-anon' )->text(), ( $row->tmplog_end_anon ? 'on' : 'off' ) - )->text() . "
"; + )->parse() . "
"; $details .= $this->msg( 'centralnotice-log-label', $this->msg( 'centralnotice-account' )->text(), ( $row->tmplog_end_account ? 'on' : 'off' ) - )->text() . "
"; + )->parse() . "
"; $details .= $this->msg( 'centralnotice-log-label', $this->msg( 'centralnotice-category' )->text(), - $row->tmplog_end_category - )->text() . "
"; + wfEscapeWikiText( $row->tmplog_end_category ) + )->parse() . "
"; // Autolink/landing pages feature has been removed, but we might as // well show any info about it in the logs. @@ -187,19 +190,19 @@ class CentralNoticeBannerLogPager extends CentralNoticeCampaignLogPager { 'centralnotice-log-label', $this->msg( 'centralnotice-autolink' )->text(), ( $row->tmplog_end_autolink ? 'on' : 'off' ) - )->text() . "
"; + )->parse() . "
"; if ( $row->tmplog_end_landingpages ) { $details .= $this->msg( 'centralnotice-log-label', $this->msg( 'centralnotice-landingpages' )->text(), - $row->tmplog_end_landingpages - )->text() . "
"; + wfEscapeWikiText( $row->tmplog_end_landingpages ) + )->parse() . "
"; } $details .= $this->msg( 'centralnotice-log-label', $this->msg( 'centralnotice-devices' )->text(), - $row->tmplog_end_devices - )->text() . "
"; + wfEscapeWikiText( $row->tmplog_end_devices ) + )->parse() . "
"; return $details; } @@ -231,7 +234,7 @@ class CentralNoticeBannerLogPager extends CentralNoticeCampaignLogPager { 'centralnotice-log-label', $this->msg( 'centralnotice-banner-content' )->text(), $this->msg( 'centralnotice-banner-content-changed' )->text() - )->text() . "
"; + )->parse() . "
"; } return $details; } @@ -241,7 +244,6 @@ class CentralNoticeBannerLogPager extends CentralNoticeCampaignLogPager { $endField = 'tmplog_end_'.$param; $oldval = ( $oldrow ) ? $oldrow->$endField : 0; - if ( $oldval !== $newrow->$endField ) { // Give grep a chance to find the usages: // centralnotice-anon, centralnotice-account, centralnotice-fundraising, @@ -258,7 +260,7 @@ class CentralNoticeBannerLogPager extends CentralNoticeCampaignLogPager { ? $this->msg( 'centralnotice-on' )->text() : $this->msg( 'centralnotice-off' )->text() ) )->text() - )->text() . "
"; + )->parse() . "
"; } return $result; } diff --git a/CentralNoticeCampaignLogPager.php b/CentralNoticeCampaignLogPager.php index 21e8e86..1f5ca95 100644 --- a/CentralNoticeCampaignLogPager.php +++ b/CentralNoticeCampaignLogPager.php @@ -89,7 +89,7 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { // Create the user page link $userLink = Linker::linkKnown( $loggedUser->getUserPage(), - $loggedUser->getName() + htmlspecialchars( $loggedUser->getName() ) ); $userTalkLink = Linker::linkKnown( $loggedUser->getTalkPage(), @@ -111,30 +111,33 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { $htmlOut = Xml::openElement( 'tr' ); $htmlOut .= Xml::openElement( 'td', [ 'valign' => 'top' ] ); + $notlogId = (int)$row->notlog_id; if ( $row->notlog_action !== 'removed' ) { $collapsedImg = $this->getLanguage()->isRtl() ? 'collapsed-rtl.png' : 'collapsed-ltr.png'; - $htmlOut .= '' . + $htmlOut .= '' . '' . + 'id="cn-collapsed-' . $notlogId . '" style="display:block;"/>' . '' . + 'id="cn-uncollapsed-' . $notlogId . '" style="display:none;"/>' . ''; } $htmlOut .= Xml::closeElement( 'td' ); - $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top', 'class' => 'primary' ], + $htmlOut .= Xml::element( 'td', [ 'valign' => 'top', 'class' => 'primary' ], $lang->date( $row->notlog_timestamp ) . $this->msg( 'word-separator' )->plain() . $lang->time( $row->notlog_timestamp ) ); $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top', 'class' => 'primary' ], - $this->msg( 'centralnotice-user-links', $userLink, $userTalkLink )->text() + $this->msg( 'centralnotice-user-links' ) + ->rawParams( $userLink, $userTalkLink ) + ->parse() ); // Give grep a chance to find the usages: // centralnotice-action-created, centralnotice-action-modified, // centralnotice-action-removed - $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top', 'class' => 'primary' ], + $htmlOut .= Xml::element( 'td', [ 'valign' => 'top', 'class' => 'primary' ], $this->msg( 'centralnotice-action-'.$row->notlog_action )->text() ); $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top', 'class' => 'primary' ], @@ -143,7 +146,7 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { // TODO temporary code for soft dependency on schema change $summary = property_exists( $row, 'notlog_comment' ) ? - $row->notlog_comment : ' '; + htmlspecialchars( $row->notlog_comment ) : ' '; $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top', 'class' => 'primary-summary' ], @@ -160,7 +163,7 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { if ( $row->notlog_action !== 'removed' ) { // Begin log entry secondary row $htmlOut .= Xml::openElement( 'tr', - [ 'id' => 'cn-log-details-'.$row->notlog_id, 'style' => 'display:none;' ] ); + [ 'id' => 'cn-log-details-'.$notlogId, 'style' => 'display:none;' ] ); $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top' ], ' ' // force a table cell in older browsers @@ -193,18 +196,18 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { $this->msg( 'centralnotice-start-timestamp' )->text(), $lang->date( $row->notlog_end_start ) . $wordSeparator . $lang->time( $row->notlog_end_start ) - )->text() . "
"; + )->parse() . "
"; $details .= $this->msg( 'centralnotice-log-label', $this->msg( 'centralnotice-end-timestamp' )->text(), $lang->date( $row->notlog_end_end ) . $wordSeparator . $lang->time( $row->notlog_end_end ) - )->text() . "
"; + )->parse() . "
"; $details .= $this->msg( 'centralnotice-log-label', $this->msg( 'centralnotice-projects' )->text(), - $row->notlog_end_projects - )->text() . "
"; + wfEscapeWikiText( $row->notlog_end_projects ) + )->parse() . "
"; $language_count = count( explode( ', ', $row->notlog_end_languages ) ); $languageList = ''; if ( $language_count > 15 ) { @@ -216,13 +219,13 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { $details .= $this->msg( 'centralnotice-log-label', $this->msg( 'centralnotice-languages' )->text(), - $languageList - )->text() . "
"; + wfEscapeWikiText( $languageList ) + )->parse() . "
"; $details .= $this->msg( 'centralnotice-log-label', $this->msg( 'centralnotice-geo' )->text(), ( $row->notlog_end_geo ? 'on' : 'off' ) - )->text() . "
"; + )->parse() . "
"; if ( $row->notlog_end_geo ) { $country_count = count( explode( ', ', $row->notlog_end_countries ) ); $countryList = ''; @@ -235,8 +238,8 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { $details .= $this->msg( 'centralnotice-log-label', $this->msg( 'centralnotice-countries' )->text(), - $countryList - )->text() . "
"; + wfEscapeWikiText( $countryList ) + )->parse() . "
"; } return $details; } @@ -260,7 +263,7 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { $lang->date( $row->notlog_end_start ) . $wordSeparator . $lang->time( $row->notlog_end_start ) )->text() - )->text() . "
"; + )->parse() . "
"; } if ( $row->notlog_begin_end !== $row->notlog_end_end ) { $details .= $this->msg( @@ -273,7 +276,7 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { $lang->date( $row->notlog_end_end ) . $wordSeparator . $lang->time( $row->notlog_end_end ) )->text() - )->text() . "
"; + )->parse() . "
"; } $details .= $this->testBooleanChange( 'enabled', $row ); $details .= $this->testPriorityChange( 'preferred', $row ); @@ -334,7 +337,7 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { 'centralnotice-log-label', $this->msg( 'centralnotice-templates' )->text(), $this->msg( 'centralnotice-changed', $before, $after )->text() - )->text() . "
"; + )->parse() . "
"; } return $details; } @@ -363,7 +366,7 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { ? $this->msg( 'centralnotice-on' )->text() : $this->msg( 'centralnotice-off' )->text() ) )->text() - )->text() . "
"; + )->parse() . "
"; } return $result; } @@ -403,7 +406,7 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { 'centralnotice-log-label', $this->msg( 'centralnotice-'.$param )->text(), $differences - )->text() . "
"; + )->parse() . "
"; } return $result; } @@ -456,7 +459,7 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { $beginMessage, $endMessage )->text() - )->text() . "
"; + )->parse() . "
"; } return $result; } @@ -483,7 +486,7 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { $beginMessage, $endMessage )->text() - )->text() . "
"; + )->parse() . "
"; } return $result; } @@ -498,10 +501,10 @@ class CentralNoticeCampaignLogPager extends ReverseChronologicalPager { $this->msg( 'centralnotice-' . $param )->text(), $this->msg( 'centralnotice-changed', - $oldval, - $newval + wfEscapeWikiText( $oldval ), + wfEscapeWikiText( $newval ) )->text() - )->text() . "
"; + )->parse() . "
"; } return $result; } diff --git a/CentralNoticePageLogPager.php b/CentralNoticePageLogPager.php index ae74928..31cbac5 100644 --- a/CentralNoticePageLogPager.php +++ b/CentralNoticePageLogPager.php @@ -87,7 +87,7 @@ class CentralNoticePageLogPager extends ReverseChronologicalPager { $loggedUser = User::newFromId( $row->rc_user ); // Create the user page link $userLink = Linker::linkKnown( $loggedUser->getUserPage(), - $loggedUser->getName() ); + htmlspecialchars( $loggedUser->getName() ) ); $userTalkLink = Linker::linkKnown( $loggedUser->getTalkPage(), $this->msg( 'centralnotice-talk-link' )->escaped() @@ -169,11 +169,13 @@ class CentralNoticePageLogPager extends ReverseChronologicalPager { $htmlOut .= Xml::openElement( 'td', [ 'valign' => 'top' ] ); $htmlOut .= Xml::closeElement( 'td' ); - $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top', 'class' => 'primary' ], + $htmlOut .= Xml::element( 'td', [ 'valign' => 'top', 'class' => 'primary' ], $lang->date( $row->rc_timestamp ) . ' ' . $lang->time( $row->rc_timestamp ) ); $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top', 'class' => 'primary' ], - $this->msg( 'centralnotice-user-links', $userLink, $userTalkLink )->text() + $this->msg( 'centralnotice-user-links' ) + ->rawParams( $userLink, $userTalkLink ) + ->parse() ); $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top', 'class' => 'primary' ], $bannerCell diff --git a/includes/CNCampaignPager.php b/includes/CNCampaignPager.php index d0fad22..667d33f 100644 --- a/includes/CNCampaignPager.php +++ b/includes/CNCampaignPager.php @@ -189,11 +189,11 @@ class CNCampaignPager extends TablePager { case 'projects': $p = explode( ',', $this->mCurrentRow->projects ); - return $this->onSpecialCN->listProjects( $p ); + return htmlspecialchars( $this->onSpecialCN->listProjects( $p ) ); case 'languages': $l = explode( ',', $this->mCurrentRow->languages ); - return $this->onSpecialCN->listLanguages( $l ); + return htmlspecialchars( $this->onSpecialCN->listLanguages( $l ) ); case 'countries': if ( $this->mCurrentRow->not_geo ) { @@ -203,7 +203,7 @@ class CNCampaignPager extends TablePager { $c = array_keys( GeoTarget::getCountriesList( 'en' ) ); } - return $this->onSpecialCN->listCountries( $c ); + return htmlspecialchars( $this->onSpecialCN->listCountries( $c ) ); case 'not_start': case 'not_end': @@ -236,7 +236,7 @@ class CNCampaignPager extends TablePager { case 'not_throttle': if ( $value < 100 ) { - return $value . "%"; + return htmlspecialchars( $value . "%" ); } else { return ''; } diff --git a/includes/Campaign.php b/includes/Campaign.php index aa9918c..42a5c2c 100644 --- a/includes/Campaign.php +++ b/includes/Campaign.php @@ -526,7 +526,7 @@ class Campaign { if ( $historical_banner === null ) { // FIXME: crazy hacks $historical_banner = Banner::getBannerSettings( $name ); - $historical_banner['label'] = wfMessage( 'centralnotice-damaged-log', $name ); + $historical_banner['label'] = wfMessage( 'centralnotice-damaged-log', $name )->text(); $historical_banner['display_anon'] = $historical_banner['anon']; $historical_banner['display_account'] = $historical_banner['account']; $historical_banner['devices'] = [ 'desktop' ]; diff --git a/includes/HtmlFormElements/HTMLCentralNoticeBanner.php b/includes/HtmlFormElements/HTMLCentralNoticeBanner.php index 4e30b27..fa12a3d 100644 --- a/includes/HtmlFormElements/HTMLCentralNoticeBanner.php +++ b/includes/HtmlFormElements/HTMLCentralNoticeBanner.php @@ -115,7 +115,7 @@ class HTMLCentralNoticeBanner extends HTMLInfoField { ); $html .= ' (' . Linker::link( SpecialPage::getTitleFor( 'Randompage' ), - $this->msg( 'centralnotice-live-preview' ), + $this->msg( 'centralnotice-live-preview' )->parse(), [ 'class' => 'cn-banner-list-element-label-text' ], [ 'banner' => $bannerName, diff --git a/resources/infrastructure/bannereditor.js b/resources/infrastructure/bannereditor.js index 1199c07..cacaab0 100644 --- a/resources/infrastructure/bannereditor.js +++ b/resources/infrastructure/bannereditor.js @@ -32,7 +32,7 @@ } $dialogEl.dialog( { - title: mw.message( 'centralnotice-banner-cdn-dialog-title' ).text(), + title: mw.message( 'centralnotice-banner-cdn-dialog-title' ).escaped(), autoOpen: false } ); @@ -119,7 +119,7 @@ dialogObj[ 0 ].name = 'addBannerDialog'; dialogObj.append( $( '#cn-formsection-clone-banner' ).children( 'div' ).clone().show() ) .dialog( { - title: mw.message( 'centralnotice-clone-notice' ).text(), + title: mw.message( 'centralnotice-clone-notice' ).escaped(), modal: true, buttons: buttons, width: 'auto' @@ -179,7 +179,7 @@ dialogObj.append( $( '#cn-formsection-delete-banner' ).children( 'div' ).clone().show() ) .dialog( { - title: mw.message( 'centralnotice-delete-banner-title', 1 ).text(), + title: mw.message( 'centralnotice-delete-banner-title', 1 ).escaped(), modal: true, buttons: buttons, width: '35em' @@ -206,7 +206,7 @@ dialogObj.text( mw.message( 'centralnotice-archive-banner-confirm' ).text() ); dialogObj.dialog( { - title: mw.message( 'centralnotice-archive-banner-title', 1 ).text(), + title: mw.message( 'centralnotice-archive-banner-title', 1 ).escaped(), resizable: false, modal: true, buttons: buttons @@ -237,9 +237,9 @@ endPos; if ( buttonType === 'close' ) { buttonValue = '' + - '
' + mw.msg( 'centralnotice-close-title' ) + + '
' + mw.message( 'centralnotice-close-title' ).escaped() + '
'; } if ( document.selection ) { diff --git a/resources/infrastructure/bannermanager.js b/resources/infrastructure/bannermanager.js index 90fda7e..c30c8e9 100644 --- a/resources/infrastructure/bannermanager.js +++ b/resources/infrastructure/bannermanager.js @@ -69,7 +69,7 @@ dialogObj[ 0 ].name = 'addBannerDialog'; dialogObj.append( $( '#cn-formsection-addBanner' ).children( 'div' ).clone().show() ) .dialog( { - title: mw.message( 'centralnotice-add-new-banner-title' ).text(), + title: mw.message( 'centralnotice-add-new-banner-title' ).escaped(), modal: true, buttons: buttons, width: 400 @@ -113,7 +113,7 @@ title: mw.message( 'centralnotice-delete-banner-title', bm.selectedItemCount - ).text(), + ).escaped(), width: '35em', modal: true, buttons: buttons @@ -143,7 +143,7 @@ title: mw.message( 'centralnotice-archive-banner-title', bm.selectedItemCount - ).text(), + ).escaped(), resizable: false, modal: true, buttons: buttons diff --git a/resources/vendor/jquery.ui.multiselect/ui.multiselect.js b/resources/vendor/jquery.ui.multiselect/ui.multiselect.js index cf1ec55..cdd3d5a 100644 --- a/resources/vendor/jquery.ui.multiselect/ui.multiselect.js +++ b/resources/vendor/jquery.ui.multiselect/ui.multiselect.js @@ -43,7 +43,7 @@ } }, _create: function() { - var countStr = mw.message('centralnotice-items-selected', 0), + var countStr = mw.message('centralnotice-items-selected', 0).escaped(), that; this.element.hide(); @@ -53,8 +53,8 @@ this.count = 0; // number of currently selected options this.selectedContainer = $('
').appendTo(this.container); this.availableContainer = $('
')[this.options.availableFirst?'prependTo': 'appendTo'](this.container); - this.selectedActions = $('').appendTo(this.selectedContainer); - this.availableActions = $('').appendTo(this.availableContainer); + this.selectedActions = $('').appendTo(this.selectedContainer); + this.availableActions = $('').appendTo(this.availableContainer); this.selectedList = $('
').bind('selectstart', function(){return false;}).appendTo(this.selectedContainer); this.availableList = $('
').bind('selectstart', function(){return false;}).appendTo(this.availableContainer); @@ -336,4 +336,4 @@ }); } }); -})(jQuery, mediaWiki); \ No newline at end of file +})(jQuery, mediaWiki); diff --git a/special/SpecialBannerAllocation.php b/special/SpecialBannerAllocation.php index 1f94f85..21dea3a 100644 --- a/special/SpecialBannerAllocation.php +++ b/special/SpecialBannerAllocation.php @@ -101,13 +101,13 @@ class SpecialBannerAllocation extends CentralNotice { $htmlOut .= Html::openElement( 'form', [ 'method' => 'get' ] ); $htmlOut .= Html::element( 'h2', [], $this->msg( 'centralnotice-view-allocation' )->text() ); - $htmlOut .= Xml::tags( 'p', null, $this->msg( 'centralnotice-allocation-instructions' )->text() ); + $htmlOut .= Xml::tags( 'p', null, $this->msg( 'centralnotice-allocation-instructions' )->parse() ); $htmlOut .= Html::openElement( 'table', [ 'id' => 'envpicker', 'cellpadding' => 7 ] ); $htmlOut .= Html::openElement( 'tr' ); $htmlOut .= Xml::tags( 'td', [ 'style' => 'width: 20%;' ], - $this->msg( 'centralnotice-project-name' )->text() ); + $this->msg( 'centralnotice-project-name' )->parse() ); $htmlOut .= Html::openElement( 'td' ); $htmlOut .= Html::openElement( 'select', [ 'name' => 'project' ] ); @@ -121,7 +121,7 @@ class SpecialBannerAllocation extends CentralNotice { $htmlOut .= Html::openElement( 'tr' ); $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top' ], - $this->msg( 'centralnotice-project-lang' )->text() ); + $this->msg( 'centralnotice-project-lang' )->parse() ); $htmlOut .= Html::openElement( 'td' ); // Retrieve the list of languages in user's language @@ -146,7 +146,7 @@ class SpecialBannerAllocation extends CentralNotice { $htmlOut .= Html::closeElement( 'td' ); $htmlOut .= Html::closeElement( 'tr' ); $htmlOut .= Html::openElement( 'tr' ); - $htmlOut .= Xml::tags( 'td', [], $this->msg( 'centralnotice-country' )->text() ); + $htmlOut .= Xml::tags( 'td', [], $this->msg( 'centralnotice-country' )->parse() ); $htmlOut .= Html::openElement( 'td' ); $userLanguageCode = $this->getLanguage()->getCode(); @@ -220,11 +220,11 @@ class SpecialBannerAllocation extends CentralNotice { 'h3', null, $this->msg( 'centralnotice-allocation-description', - htmlspecialchars( $language ), - htmlspecialchars( $project ), - htmlspecialchars( $country ), - $this->getOutput()->parseInline( $deviceData['label'] ) - )->text() + wfEscapeWikiText( $language ), + wfEscapeWikiText( $project ), + wfEscapeWikiText( $country ), + $deviceData['label'] + )->parse() ); // FIXME matrix is chosen dynamically based on more UI inputs @@ -279,11 +279,11 @@ class SpecialBannerAllocation extends CentralNotice { if ( count( $banners ) > 0 ) { $htmlOut .= Html::openElement( 'tr' ); $htmlOut .= Html::element( 'th', [ 'width' => '5%' ], - $this->msg( 'centralnotice-percentage' )->text() ); + $this->msg( 'centralnotice-percentage' )->parse() ); $htmlOut .= Html::element( 'th', [ 'width' => '30%' ], - $this->msg( 'centralnotice-banner' )->text() ); + $this->msg( 'centralnotice-banner' )->parse() ); $htmlOut .= Html::element( 'th', [ 'width' => '30%' ], - $this->msg( 'centralnotice-notice' )->text() ); + $this->msg( 'centralnotice-notice' )->parse() ); $htmlOut .= Html::closeElement( 'tr' ); } $htmlOut .= $this->createRows( $banners ); @@ -343,7 +343,7 @@ class SpecialBannerAllocation extends CentralNotice { } else { $htmlOut .= Html::openElement( 'tr' ); $htmlOut .= Html::openElement( 'td' ); - $htmlOut .= Xml::tags( 'p', null, $this->msg( 'centralnotice-no-allocation' )->text() ); + $htmlOut .= Xml::tags( 'p', null, $this->msg( 'centralnotice-no-allocation' )->parse() ); $htmlOut .= Html::closeElement( 'td' ); $htmlOut .= Html::closeElement( 'tr' ); } diff --git a/special/SpecialCentralNotice.php b/special/SpecialCentralNotice.php index 9da13d3..e6b19e2 100644 --- a/special/SpecialCentralNotice.php +++ b/special/SpecialCentralNotice.php @@ -227,7 +227,7 @@ class CentralNotice extends SpecialPage { ); return $out; } else { - return $this->getLanguage()->date( $timestamp ); + return htmlspecialchars( $this->getLanguage()->date( $timestamp ) ); } } @@ -257,7 +257,7 @@ class CentralNotice extends SpecialPage { return $this->createSelector( $prefix, $fields ); } else { - return $this->getLanguage()->time( $timestamp ); + return htmlspecialchars( $this->getLanguage()->time( $timestamp ) ); } } @@ -857,7 +857,7 @@ class CentralNotice extends SpecialPage { // Build Html $htmlOut = ''; $htmlOut .= Xml::tags( 'h2', null, - $this->msg( 'centralnotice-notice-heading', $notice )->text() ); + $this->msg( 'centralnotice-notice-heading', $notice )->parse() ); $htmlOut .= Xml::openElement( 'table', [ 'cellpadding' => 9 ] ); // Rows @@ -1450,11 +1450,11 @@ class CentralNotice extends SpecialPage { return Xml::element( 'label', [ 'class' => 'cn-change-summary-label' ], - $this->msg( 'centralnotice-change-summary-label' )->escaped() + $this->msg( 'centralnotice-change-summary-label' )->text() ) . Xml::element( 'input', [ 'class' => 'cn-change-summary-input', - 'placeholder' => $this->msg( $placeholderMsg )->escaped(), + 'placeholder' => $this->msg( $placeholderMsg )->text(), 'size' => 45, 'name' => 'changeSummary' ] @@ -1568,7 +1568,7 @@ class CentralNotice extends SpecialPage { // Now add our own foreach ( $wgNoticeTabifyPages as $page => $keys ) { $tabs[ $keys[ 'type' ] ][ $page ] = [ - 'text' => wfMessage( $keys[ 'message' ] ), + 'text' => wfMessage( $keys[ 'message' ] )->parse(), 'href' => SpecialPage::getTitleFor( $page )->getFullURL(), 'class' => ( $alias === $page ) ? 'selected' : '', ]; diff --git a/special/SpecialCentralNoticeBanners.php b/special/SpecialCentralNoticeBanners.php index 5706ab2..9d690f5 100644 --- a/special/SpecialCentralNoticeBanners.php +++ b/special/SpecialCentralNoticeBanners.php @@ -153,7 +153,7 @@ class SpecialCentralNoticeBanners extends CentralNotice { 'bannerNameFilter' => [ 'section' => 'header/banner-search', 'class' => 'HTMLTextField', - 'placeholder' => wfMessage( 'centralnotice-filter-template-prompt' ), + 'placeholder-message' => 'centralnotice-filter-template-prompt', 'filter-callback' => [ $this, 'sanitizeSearchTerms' ], 'default' => $filter, ], @@ -201,7 +201,7 @@ class SpecialCentralNoticeBanners extends CentralNotice { 'section' => 'addBanner', 'class' => 'HTMLTextField', 'label-message' => 'centralnotice-change-summary-label', - 'placeholder' => wfMessage( 'centralnotice-change-summary-action-prompt' ), + 'placeholder-message' => 'centralnotice-change-summary-action-prompt', 'disabled' => !$this->editable, 'filter-callback' => [ $this, 'truncateSummaryField' ] ], @@ -209,7 +209,7 @@ class SpecialCentralNoticeBanners extends CentralNotice { 'section' => 'removeBanner', 'class' => 'HTMLTextField', 'label-message' => 'centralnotice-change-summary-label', - 'placeholder' => wfMessage( 'centralnotice-change-summary-action-prompt' ), + 'placeholder-message' => 'centralnotice-change-summary-action-prompt', 'disabled' => !$this->editable, 'filter-callback' => [ $this, 'truncateSummaryField' ] ], @@ -257,13 +257,13 @@ class SpecialCentralNoticeBanners extends CentralNotice { // Attempt to create a new banner and redirect; we validate here because it's // a hidden field and that doesn't work so well with the form if ( !Banner::isValidBannerName( $formData[ 'newBannerName' ] ) ) { - return wfMessage( 'centralnotice-banner-name-error' ); + return wfMessage( 'centralnotice-banner-name-error' )->parse(); } else { $this->bannerName = $formData[ 'newBannerName' ]; } if ( Banner::fromName( $this->bannerName )->exists() ) { - return wfMessage( 'centralnotice-template-exists' )->text(); + return wfMessage( 'centralnotice-template-exists' )->parse(); } else { $retval = Banner::addTemplate( $this->bannerName, @@ -278,7 +278,7 @@ class SpecialCentralNoticeBanners extends CentralNotice { if ( $retval ) { // Something failed; display error to user - return wfMessage( $retval )->text(); + return wfMessage( $retval )->parse(); } else { $this->getOutput()->redirect( SpecialPage::getTitleFor( @@ -327,7 +327,7 @@ class SpecialCentralNoticeBanners extends CentralNotice { } } elseif ( $formData[ 'action' ] ) { // Oh noes! The l33t hakorz are here... - return wfMessage( 'centralnotice-generic-error' )->text(); + return wfMessage( 'centralnotice-generic-error' )->parse(); } return null; @@ -525,8 +525,8 @@ class SpecialCentralNoticeBanners extends CentralNotice { 'disabled' => !$this->editable, 'label-message' => 'centralnotice-banner-display', 'options' => [ - $this->msg( 'centralnotice-banner-logged-in' )->text() => 'registered', - $this->msg( 'centralnotice-banner-anonymous' )->text() => 'anonymous' + $this->msg( 'centralnotice-banner-logged-in' )->escaped() => 'registered', + $this->msg( 'centralnotice-banner-anonymous' )->escaped() => 'anonymous' ], 'default' => $selected, 'cssclass' => 'separate-form-element', @@ -537,7 +537,7 @@ class SpecialCentralNoticeBanners extends CentralNotice { ); $availableDevices = []; foreach ( CNDeviceTarget::getAvailableDevices() as $k => $value ) { - $header = $value[ 'header' ]; + $header = htmlspecialchars( $value[ 'header' ] ); $label = $this->getOutput()->parseInline( $value[ 'label' ] ); $availableDevices[ "($header) $label" ] = $header; } @@ -690,8 +690,8 @@ class SpecialCentralNoticeBanners extends CentralNotice { 'type' => 'info', 'default' => $this->msg( 'centralnotice-edit-template-magicwords', - $this->getLanguage()->listToText( $magicWords ) - )->text(), + wfEscapeWikiText( $this->getLanguage()->listToText( $magicWords ) ) + )->parse(), 'rawrow' => true, ]; @@ -699,7 +699,7 @@ class SpecialCentralNoticeBanners extends CentralNotice { // TODO: Fix this gawdawful method of inserting the close button $buttons[] = '' . $this->msg( 'centralnotice-close-button' )->text() . ''; + 'return false;">' . $this->msg( 'centralnotice-close-button' )->escaped() . ''; $formDescriptor[ 'banner-insert-button' ] = [ 'section' => 'edit-template', 'class' => 'HTMLInfoField', @@ -805,7 +805,7 @@ class SpecialCentralNoticeBanners extends CentralNotice { 'section' => 'delete-banner', 'class' => 'HTMLTextField', 'label-message' => 'centralnotice-change-summary-label', - 'placeholder' => wfMessage( 'centralnotice-change-summary-action-prompt' ), + 'placeholder-message' => 'centralnotice-change-summary-action-prompt', 'disabled' => !$this->editable, 'filter-callback' => [ $this, 'truncateSummaryField' ] ]; @@ -834,7 +834,7 @@ class SpecialCentralNoticeBanners extends CentralNotice { protected function generateCdnPurgeSection() { $purgeControls = Xml::element( 'h2', [ 'class' => 'cn-special-section' ], - $this->msg( 'centralnotice-banner-cdn-controls' )->escaped() ); + $this->msg( 'centralnotice-banner-cdn-controls' )->text() ); $purgeControls .= Html::openElement( 'fieldset', [ 'class' => 'prefsection' ] ); @@ -875,7 +875,7 @@ class SpecialCentralNoticeBanners extends CentralNotice { $purgeControls .= Html::element( 'div', [ 'class' => 'htmlform-help' ], - $this->msg( 'centralnotice-banner-cdn-help' )->escaped() + $this->msg( 'centralnotice-banner-cdn-help' )->text() ); $purgeControls .= Html::closeElement( 'fieldset' ); @@ -904,8 +904,8 @@ class SpecialCentralNoticeBanners extends CentralNotice { $this->getOutput()->redirect( $this->getPageTitle( '' )->getCanonicalURL() ); $this->bannerFormRedirectRequired = true; } catch ( Exception $ex ) { - return $ex->getMessage() . "
" . - $this->msg( 'centralnotice-template-still-bound', $this->bannerName ); + return htmlspecialchars( $ex->getMessage() ) . "
" . + $this->msg( 'centralnotice-template-still-bound', $this->bannerName )->parse(); } break; @@ -1014,7 +1014,7 @@ class SpecialCentralNoticeBanners extends CentralNotice { if ( !Banner::isValidBannerName( $this->bannerName ) ) { $out->addHTML( Xml::element( 'div', [ 'class' => 'error' ], - wfMessage( 'centralnotice-generic-error' ) ) + wfMessage( 'centralnotice-generic-error' )->text() ) ); return; } diff --git a/special/SpecialCentralNoticeLogs.php b/special/SpecialCentralNoticeLogs.php index 2f26cb0..10acfcb 100644 --- a/special/SpecialCentralNoticeLogs.php +++ b/special/SpecialCentralNoticeLogs.php @@ -178,7 +178,7 @@ class SpecialCentralNoticeLogs extends CentralNotice { 'id' => 'centralnoticelogreset', 'name' => 'centralnoticelogreset', 'class' => 'cn-filter-buttons', - 'onclick' => "location.href = '$link'; return false;", + 'onclick' => "location.href = " . Xml::encodeJsVar( $link ) . "; return false;", ] ); $htmlOut .= Xml::closeElement( 'td' ); @@ -284,12 +284,14 @@ class SpecialCentralNoticeLogs extends CentralNotice { * Build a radio button that switches the log type when you click it */ private function getLogSwitcher( $type, $id, $message, $fullUrl ) { + $fullUrlEnc = Xml::encodeJsVar( $fullUrl ); + $typeEnc = Xml::encodeJsVar( $type ); $htmlOut = ''; $htmlOut .= Xml::radio( 'log_type', $id, ( $this->logType == $type ? true : false ), - [ 'onclick' => "switchLogs( '".$fullUrl."', '".$type."' )" ] + [ 'onclick' => "switchLogs( " .$fullUrlEnc.", ".$typeEnc." )" ] ); $htmlOut .= Xml::label( $this->msg( $message )->text(), $id ); return $htmlOut; diff --git a/special/SpecialGlobalAllocation.php b/special/SpecialGlobalAllocation.php index e2cc4dc..995022a 100644 --- a/special/SpecialGlobalAllocation.php +++ b/special/SpecialGlobalAllocation.php @@ -129,13 +129,13 @@ class SpecialGlobalAllocation extends CentralNotice { $htmlOut .= Html::element( 'h2', [], $this->msg( 'centralnotice-view-allocation' )->text() ); $htmlOut .= Xml::tags( 'p', null, - $this->msg( 'centralnotice-allocation-instructions' )->text() ); + $this->msg( 'centralnotice-allocation-instructions' )->parse() ); $htmlOut .= Html::openElement( 'table', [ 'id' => 'envpicker', 'cellpadding' => 7 ] ); $htmlOut .= Html::openElement( 'tr' ); $htmlOut .= Xml::tags( 'td', [ 'style' => 'width: 20%;' ], - $this->msg( 'centralnotice-project-name' )->text() ); + $this->msg( 'centralnotice-project-name' )->parse() ); $htmlOut .= Html::openElement( 'td' ); $htmlOut .= Html::openElement( 'select', [ 'name' => 'project' ] ); @@ -151,7 +151,7 @@ class SpecialGlobalAllocation extends CentralNotice { $htmlOut .= Html::openElement( 'tr' ); $htmlOut .= Xml::tags( 'td', [ 'valign' => 'top' ], - $this->msg( 'centralnotice-project-lang' )->text() ); + $this->msg( 'centralnotice-project-lang' )->parse() ); $htmlOut .= Html::openElement( 'td' ); // Retrieve the list of languages in user's language @@ -178,7 +178,7 @@ class SpecialGlobalAllocation extends CentralNotice { $htmlOut .= Html::closeElement( 'td' ); $htmlOut .= Html::closeElement( 'tr' ); $htmlOut .= Html::openElement( 'tr' ); - $htmlOut .= Xml::tags( 'td', [], $this->msg( 'centralnotice-country' )->text() ); + $htmlOut .= Xml::tags( 'td', [], $this->msg( 'centralnotice-country' )->parse() ); $htmlOut .= Html::openElement( 'td' ); $userLanguageCode = $this->getLanguage()->getCode(); @@ -198,7 +198,7 @@ class SpecialGlobalAllocation extends CentralNotice { $htmlOut .= Html::openElement( 'tr' ); $htmlOut .= Html::openElement( 'td' ); - $htmlOut .= $this->msg( 'centralnotice-date' ); + $htmlOut .= $this->msg( 'centralnotice-date' )->parse(); $htmlOut .= Html::closeElement( 'td' ); $htmlOut .= Html::openElement( 'td' ); $htmlOut .= $this->dateSelector( 'filter', true, $this->timestamp ); @@ -236,13 +236,13 @@ class SpecialGlobalAllocation extends CentralNotice { $htmlOut .= Html::openElement( 'fieldset', [ 'class' => 'prefsection' ] ); $languageLabel = $this->language ? - htmlspecialchars( $this->language ) : $this->msg( 'centralnotice-all' )->text(); - $projectLabel = $this->language ? - htmlspecialchars( $this->project ) : $this->msg( 'centralnotice-all' )->text(); + $this->language : $this->msg( 'centralnotice-all' )->text(); + $projectLabel = $this->project ? + $this->project : $this->msg( 'centralnotice-all' )->text(); $countryLabel = $this->location ? - htmlspecialchars( $this->location ) : $this->msg( 'centralnotice-all' )->text(); + $this->location : $this->msg( 'centralnotice-all' )->text(); $deviceLabel = $this->device ? - htmlspecialchars( $this->device ) : $this->msg( 'centralnotice-all' )->text(); + $this->device : $this->msg( 'centralnotice-all' )->text(); $htmlOut .= Xml::tags( 'p', null, $this->msg( @@ -252,7 +252,7 @@ class SpecialGlobalAllocation extends CentralNotice { $countryLabel, $deviceLabel, wfTimestamp( TS_ISO_8601, $this->timestamp ) - )->text() + )->parse() ); $this->campaigns = Campaign::getHistoricalCampaigns( @@ -297,15 +297,15 @@ class SpecialGlobalAllocation extends CentralNotice { [ 'class' => 'mw-sp-centralnotice-allocationrow' ] ); $htmlOut .= Html::openElement( 'td' ); - $htmlOut .= $row['projects_label']; + $htmlOut .= htmlspecialchars( $row['projects_label'] ); $htmlOut .= Html::closeElement( 'td' ); $htmlOut .= Html::openElement( 'td' ); - $htmlOut .= $row['languages_label']; + $htmlOut .= htmlspecialchars( $row['languages_label'] ); $htmlOut .= Html::closeElement( 'td' ); $htmlOut .= Html::openElement( 'td' ); - $htmlOut .= $row['countries_label']; + $htmlOut .= htmlspecialchars( $row['countries_label'] ); $htmlOut .= Html::closeElement( 'td' ); $htmlOut .= Html::closeElement( 'tr' ); @@ -582,11 +582,11 @@ class SpecialGlobalAllocation extends CentralNotice { $htmlOut .= Html::openElement( 'tr', [ 'class' => 'mw-sp-centralnotice-allocationrow' ] ); if ( !$variesAnon ) { - $anonLabel = $this->msg( 'centralnotice-all' )->text(); + $anonLabel = $this->msg( 'centralnotice-all' )->parse(); } elseif ( $isAnon ) { - $anonLabel = $this->msg( 'centralnotice-user-role-anonymous' )->text(); + $anonLabel = $this->msg( 'centralnotice-user-role-anonymous' )->parse(); } else { - $anonLabel = $this->msg( 'centralnotice-user-role-logged-in' )->text(); + $anonLabel = $this->msg( 'centralnotice-user-role-logged-in' )->parse(); } $htmlOut .= Html::openElement( 'td' ); @@ -597,7 +597,7 @@ class SpecialGlobalAllocation extends CentralNotice { $bucketLabel = chr( $bucket + 65 ); $htmlOut .= Html::openElement( 'td' ); - $htmlOut .= $bucketLabel; + $htmlOut .= htmlspecialchars( $bucketLabel ); $htmlOut .= Html::closeElement( 'td' ); } @@ -634,7 +634,7 @@ class SpecialGlobalAllocation extends CentralNotice { ); } else { $htmlOut .= Html::openElement( 'td' ); - $htmlOut .= Xml::tags( 'p', null, $this->msg( 'centralnotice-no-allocation' )->text() ); + $htmlOut .= Xml::tags( 'p', null, $this->msg( 'centralnotice-no-allocation' )->parse() ); } // Row end diff --git a/special/SpecialNoticeTemplate.php b/special/SpecialNoticeTemplate.php index a95d102..0fca167 100644 --- a/special/SpecialNoticeTemplate.php +++ b/special/SpecialNoticeTemplate.php @@ -22,14 +22,14 @@ class SpecialNoticeTemplate extends CentralNotice { $banner = $this->getRequest()->getText( 'template' ); $this->getOutput()->redirect( - Title::makeTitle( NS_SPECIAL, "CentralNoticeBanners/edit/$banner" )-> - getCanonicalURL(), + Title::makeTitleSafe( NS_SPECIAL, "CentralNoticeBanners/edit/$banner" )-> + getFullUrlForRedirect(), 301 ); } else { // don't know where they were trying to go, redirect them to the new list form $this->getOutput()->redirect( - Title::makeTitle( NS_SPECIAL, 'CentralNoticeBanners' )->getCanonicalURL(), + Title::makeTitle( NS_SPECIAL, 'CentralNoticeBanners' )->getFullUrlForRedirect(), 301 ); } -- 2.15.1