Merge "Allow admins to delete user JS/CSS pages"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Mon, 27 Aug 2018 19:32:01 +0000 (19:32 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Mon, 27 Aug 2018 19:32:01 +0000 (19:32 +0000)
RELEASE-NOTES-1.32
docs/extension.schema.v1.json
docs/extension.schema.v2.json
includes/DefaultSettings.php
includes/Linker.php
includes/Storage/DerivedPageDataUpdater.php
includes/Title.php
includes/content/ContentHandler.php
includes/diff/TextSlotDiffRenderer.php
includes/page/WikiPage.php
includes/registration/ExtensionProcessor.php

index ec8c022..1deca12 100644 (file)
@@ -40,6 +40,8 @@ production.
 * The $wgPasswordSenderName setting, ignored since 1.23 by MediaWiki and almost
   all extensions, is no longer set at all. Instead, you can modify the system
   message `emailsender`.
+* A new configuration setting, $wgRawHtmlMessages, is added, for listing
+  messages which are displayed as raw HTML.
 
 === New features in 1.32 ===
 * (T112474) Generalized the ResourceLoader mechanism for overriding modules
index c9a887d..0ff169c 100644 (file)
                                "type": "string"
                        }
                },
+               "RawHtmlMessages": {
+                       "type": "array",
+                       "description": "Messages which are rendered as raw HTML",
+                       "items": {
+                               "type": "string"
+                       }
+               },
                "callback": {
                        "type": [
                                "array",
index 24212a9..7de5ed5 100644 (file)
                                "type": "string"
                        }
                },
+               "RawHtmlMessages": {
+                       "type": "array",
+                       "description": "Messages which are rendered as raw HTML",
+                       "items": {
+                               "type": "string"
+                       }
+               },
                "callback": {
                        "type": [
                                "array",
index 9b0899d..ea368bc 100644 (file)
@@ -8845,6 +8845,22 @@ $wgCSPHeader = false;
  */
 $wgCSPReportOnlyHeader = false;
 
+/**
+ * List of messages which might contain raw HTML.
+ * Extensions should add their messages here. The list is used for access control:
+ * changing messages listed here will require editsitecss and editsitejs rights.
+ *
+ * @since 1.32
+ * @var string[]
+ */
+$wgRawHtmlMessages = [
+       'copyright',
+       'history_copyright',
+       'googlesearch',
+       'feedback-terms',
+       'feedback-termsofuse',
+];
+
 /**
  * Mapping of event channels (or channel categories) to EventRelayer configuration.
  *
index 08a5724..7e56522 100644 (file)
@@ -431,7 +431,11 @@ class Linker {
                        $s = $thumb->toHtml( $params );
                }
                if ( $frameParams['align'] != '' ) {
-                       $s = "<div class=\"float{$frameParams['align']}\">{$s}</div>";
+                       $s = Html::rawElement(
+                               'div',
+                               [ 'class' => 'float' . $frameParams['align'] ],
+                               $s
+                       );
                }
                return str_replace( "\n", ' ', $prefix . $s . $postfix );
        }
index a00766f..dacec96 100644 (file)
@@ -1408,21 +1408,16 @@ class DerivedPageDataUpdater implements IDBAccessObject {
                $recursive = $this->options['changed']; // T52785
                $updates = $this->getSecondaryDataUpdates( $recursive );
 
+               $triggeringUser = $this->options['triggeringuser'] ?? $this->user;
+               if ( !$triggeringUser instanceof User ) {
+                       $triggeringUser = User::newFromIdentity( $triggeringUser );
+               }
                foreach ( $updates as $update ) {
                        // TODO: make an $option field for the cause
-                       $update->setCause( 'edit-page', $this->user->getName() );
+                       $update->setCause( 'edit-page', $triggeringUser->getName() );
                        if ( $update instanceof LinksUpdate ) {
                                $update->setRevision( $legacyRevision );
-
-                               if ( !empty( $this->options['triggeringuser'] ) ) {
-                                       /** @var UserIdentity|User $triggeringUser */
-                                       $triggeringUser = $this->options['triggeringuser'];
-                                       if ( !$triggeringUser instanceof User ) {
-                                               $triggeringUser = User::newFromIdentity( $triggeringUser );
-                                       }
-
-                                       $update->setTriggeringUser( $triggeringUser );
-                               }
+                               $update->setTriggeringUser( $triggeringUser );
                        }
                        DeferredUpdates::addUpdate( $update );
                }
index 1bff30f..895cc0e 100644 (file)
@@ -1480,6 +1480,22 @@ class Title implements LinkTarget {
                );
        }
 
+       /**
+        * Is this a message which can contain raw HTML?
+        *
+        * @return bool
+        * @since 1.32
+        */
+       public function isRawHtmlMessage() {
+               global $wgRawHtmlMessages;
+
+               if ( $this->inNamespace( NS_MEDIAWIKI ) ) {
+                       return false;
+               }
+               $message = lcfirst( $this->getRootText() );
+               return in_array( $message, $wgRawHtmlMessages, true );
+       }
+
        /**
         * Is this a talk page of some sort?
         *
@@ -2392,6 +2408,13 @@ class Title implements LinkTarget {
                                $error = [ 'sitejsonprotected', $action ];
                        } elseif ( $this->isSiteJsConfigPage() && !$user->isAllowed( 'editsitejs' ) ) {
                                $error = [ 'sitejsprotected', $action ];
+                       } elseif ( $this->isRawHtmlMessage() ) {
+                               // Raw HTML can be used to deploy CSS or JS so require rights for both.
+                               if ( !$user->isAllowed( 'editsitejs' ) ) {
+                                       $error = [ 'sitejsprotected', $action ];
+                               } elseif ( !$user->isAllowed( 'editsitecss' ) ) {
+                                       $error = [ 'sitecssprotected', $action ];
+                               }
                        }
 
                        if ( $error ) {
index 22fbe6f..344d040 100644 (file)
@@ -665,7 +665,7 @@ abstract class ContentHandler {
                        $differenceEngine = $this->createDifferenceEngine( $context );
                        if ( get_class( $differenceEngine ) !== DifferenceEngine::class ) {
                                // TODO turn this into a deprecation warning in a later release
-                               LoggerFactory::getInstance( 'diff' )->notice(
+                               LoggerFactory::getInstance( 'diff' )->info(
                                        'Falling back to DifferenceEngineSlotDiffRenderer', [
                                                'modelID' => $this->getModelID(),
                                                'DifferenceEngine' => get_class( $differenceEngine ),
index baedcf0..9c60705 100644 (file)
@@ -209,7 +209,8 @@ class TextSlotDiffRenderer extends SlotDiffRenderer {
                        $wikidiff2Version = phpversion( 'wikidiff2' );
                        if (
                                $wikidiff2Version !== false &&
-                               version_compare( $wikidiff2Version, '1.5.0', '>=' )
+                               version_compare( $wikidiff2Version, '1.5.0', '>=' ) &&
+                               version_compare( $wikidiff2Version, '1.8.0', '<' )
                        ) {
                                $text = wikidiff2_do_diff(
                                        $oldText,
@@ -218,7 +219,7 @@ class TextSlotDiffRenderer extends SlotDiffRenderer {
                                        $this->wikiDiff2MovedParagraphDetectionCutoff
                                );
                        } else {
-                               // Don't pass the 4th parameter for compatibility with older versions of wikidiff2
+                               // Don't pass the 4th parameter introduced in version 1.5.0 and removed in version 1.8.0
                                $text = wikidiff2_do_diff(
                                        $oldText,
                                        $newText,
index 147c9f3..ba2d511 100644 (file)
@@ -1961,7 +1961,7 @@ class WikiPage implements Page, IDBAccessObject {
         * Purges pages that include this page if the text was changed here.
         * Every 100th edit, prune the recent changes table.
         *
-        * @deprecated since 1.32, use PageUpdater::doEditUpdates instead.
+        * @deprecated since 1.32, use PageUpdater::doUpdates instead.
         *
         * @param Revision $revision
         * @param User $user User object that did the revision
index bf61779..eb56e13 100644 (file)
@@ -45,6 +45,7 @@ class ExtensionProcessor implements Processor {
                'MediaHandlers',
                'PasswordPolicy',
                'RateLimits',
+               'RawHtmlMessages',
                'RecentChangesFlags',
                'RemoveCredentialsBlacklist',
                'RemoveGroups',