EBernhardson has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/100604


Change subject: Filter the display of content via a hook
......................................................................

Filter the display of content via a hook

This new hook, FlowCheckHtmlContentXss, allows for a callback
to easily be added which allows or rejects the display of
stored html content.  When we find the next xss in parsoid this
will allow preventing that html for exploting the next viewer.

Change-Id: I6587113073993b12c12499f896bd27501697d486
Mingle: 401
---
M includes/Model/AbstractRevision.php
M includes/ParsoidUtils.php
M includes/Templating.php
3 files changed, 41 insertions(+), 18 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Flow 
refs/changes/04/100604/1

diff --git a/includes/Model/AbstractRevision.php 
b/includes/Model/AbstractRevision.php
index c721484..e9c4ea6 100644
--- a/includes/Model/AbstractRevision.php
+++ b/includes/Model/AbstractRevision.php
@@ -68,6 +68,10 @@
        protected $decompressedContent;
        // Converted (wikitext|html) content, based off of 
$this->decompressedContent
        protected $convertedContent = array();
+       // html content has been allowed by the xss check.  When we find the 
next xss
+       // in the parser this hook allows preventing any disply of hostile 
html. True
+       // means the content is allowed. False means not allowed. Null means 
unchecked
+       protected $xssCheck;
 
        // moderation states for the revision.  This is technically 
denormalized data
        // since it can be overwritten and does not provide a full history.
@@ -274,7 +278,7 @@
                return $this->moderationState === self::MODERATED_HIDDEN;
        }
 
-       public function getContentRaw() {
+       private function getContentRaw() {
                if ( $this->decompressedContent === null ) {
                        $this->decompressedContent = 
\Revision::decompressRevisionText( $this->content, $this->flags );
                }
@@ -291,13 +295,25 @@
         * @return string
         */
        public function getContent( $format = 'html' ) {
+               if ( $this->xssCheck === false ) {
+                       return '';
+               }
+               $raw = $this->getContentRaw();
+               $sourceFormat = in_array( 'html', $this->flags ) ? 'html' : 
'wikitext';
+               if ( $this->xssCheck === null && $sourceFormat === 'html' ) {
+                       // returns true if no handler aborted the hook
+                       $this->xssCheck = wfRunHooks( 
'FlowCheckHtmlContentXss', array( $raw ) );
+                       if ( !$this->xssCheck ) {
+                               return '';
+                       }
+               }
+
                if ( !$this->isFormatted() ) {
-                       return $this->getContentRaw();
+                       return $raw;
                }
                if ( !isset( $this->convertedContent[$format] ) ) {
-                       // check how content is stored & convert to requested 
format
-                       $sourceFormat = in_array( 'html', $this->flags ) ? 
'html' : 'wikitext';
-                       $this->convertedContent[$format] = 
ParsoidUtils::convert( $sourceFormat, $format, $this->getContentRaw() );
+                       // convert to requested format
+                       $this->convertedContent[$format] = 
ParsoidUtils::convert( $sourceFormat, $format, $raw );
                }
 
                return $this->convertedContent[$format];
diff --git a/includes/ParsoidUtils.php b/includes/ParsoidUtils.php
index 9e2bea9..031124b 100644
--- a/includes/ParsoidUtils.php
+++ b/includes/ParsoidUtils.php
@@ -92,7 +92,8 @@
                }
 
                // HTML is wrapped in <body> tag, undo that.
-               if ( $to == 'html' ) {
+               // unless $response is empty
+               if ( $to == 'html' && $response ) {
                        /*
                         * Workaround because DOMDocument can't guess charset.
                         * Parsoid provides utf-8. Alternative "workarounds" 
would be to
diff --git a/includes/Templating.php b/includes/Templating.php
index fe6d51d..ade53fa 100644
--- a/includes/Templating.php
+++ b/includes/Templating.php
@@ -378,6 +378,10 @@
         * @return string
         */
        protected function applyRedlinks( $content ) {
+               if ( !$content ) {
+                       return;
+               }
+
                /*
                 * In order to efficiently replace redlinks, multiple recursive
                 * functions (may) have been registered that fetch an array of 
linked-to
@@ -496,20 +500,22 @@
 
                // find links in DOM
                $content = $post->getContent( 'html' );
-               $dom = ParsoidUtils::createDOM( $content );
-               $xpath = new \DOMXPath( $dom );
-               $linkNodes = $xpath->query( 
'//a[@rel="mw:WikiLink"][@data-parsoid]' );
+               if ( $content ) {
+                       $dom = ParsoidUtils::createDOM( $content );
+                       $xpath = new \DOMXPath( $dom );
+                       $linkNodes = $xpath->query( 
'//a[@rel="mw:WikiLink"][@data-parsoid]' );
 
-               foreach ( $linkNodes as $linkNode ) {
-                       $parsoid = $linkNode->getAttribute( 'data-parsoid' );
-                       $parsoid = json_decode( $parsoid, true );
+                       foreach ( $linkNodes as $linkNode ) {
+                               $parsoid = $linkNode->getAttribute( 
'data-parsoid' );
+                               $parsoid = json_decode( $parsoid, true );
 
-                       if ( isset( $parsoid['sa']['href'] ) ) {
-                               // real results will be stored in 
Templating::parsoidLinks
-                               $link = $parsoid['sa']['href'];
-                               $title = Title::newFromText( $link );
-                               if ( $title !== null ) {
-                                       $this->parsoidLinks[$link] = $title;
+                               if ( isset( $parsoid['sa']['href'] ) ) {
+                                       // real results will be stored in 
Templating::parsoidLinks
+                                       $link = $parsoid['sa']['href'];
+                                       $title = Title::newFromText( $link );
+                                       if ( $title !== null ) {
+                                               $this->parsoidLinks[$link] = 
$title;
+                                       }
                                }
                        }
                }

-- 
To view, visit https://gerrit.wikimedia.org/r/100604
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6587113073993b12c12499f896bd27501697d486
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: EBernhardson <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to