jenkins-bot has submitted this change and it was merged.

Change subject: Add custom wiki protocols for data access
......................................................................


Add custom wiki protocols for data access

* wikiapi:///?action=query&list=allpages
  Call to api.php - ignores the path parameter, and only uses the query

* wikirest:///api/rest_v1/page/...
  Call to RESTbase api - requires the path to start with "/api/"

* wikiraw:///MyPage/data
  Get raw content of a wiki page, where the path is the title
  of the page with an additional leading '/' which gets removed.
  Uses mediawiki api, and extract the content after the request

* 
wikirawupload://upload.wikimedia.org/wikipedia/commons/3/3e/Einstein_1921_by_F_Schmutzer_-_restoration.jpg
  Get an image for the graph, e.g. from commons
  This tag specifies any content from the uploads.* domain, without query params

Change-Id: I6be3f3f30a725d7a4c8ce9cf349f341f2bc19dd6
---
M Graph.body.php
M extension.json
M modules/graph1.js
M modules/graph2.js
4 files changed, 106 insertions(+), 48 deletions(-)

Approvals:
  Yurik: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/Graph.body.php b/Graph.body.php
index 8b25f36..07b5c4a 100644
--- a/Graph.body.php
+++ b/Graph.body.php
@@ -75,9 +75,8 @@
 
                        if ( $liveSpecs || $interact ) {
                                // TODO: these 3 js vars should be per domain 
if 'ext.graph' is added, not per page
-                               global $wgGraphDataDomains, 
$wgGraphUrlBlacklist, $wgGraphIsTrusted;
+                               global $wgGraphDataDomains, $wgGraphIsTrusted;
                                $output->addJsConfigVars( 'wgGraphDataDomains', 
$wgGraphDataDomains );
-                               $output->addJsConfigVars( 
'wgGraphUrlBlacklist', $wgGraphUrlBlacklist );
                                $output->addJsConfigVars( 'wgGraphIsTrusted', 
$wgGraphIsTrusted );
 
                                $output->addModuleStyles( 'ext.graph' );
diff --git a/extension.json b/extension.json
index 453f1ef..f79eba4 100644
--- a/extension.json
+++ b/extension.json
@@ -117,7 +117,6 @@
                "GraphDataDomains": [],
                "GraphDefaultVegaVer": 1,
                "GraphEnableGZip": false,
-               "GraphUrlBlacklist": false,
                "GraphIsTrusted": false,
                "GraphImgServiceUrl": false
        },
diff --git a/modules/graph1.js b/modules/graph1.js
index 090ba3c..3a9f425 100644
--- a/modules/graph1.js
+++ b/modules/graph1.js
@@ -8,7 +8,6 @@
                if ( originalSanitize === false ) {
                        // Make sure we only initialize graphs once
                        vg.config.domainWhiteList = mw.config.get( 
'wgGraphDataDomains' );
-                       vg.config.urlBlackList = mw.config.get( 
'wgGraphUrlBlacklist' );
                        if ( !mw.config.get( 'wgGraphIsTrusted' ) ) {
                                vg.config.dataHeaders = { 'Treat-as-Untrusted': 
1 };
                        }
@@ -25,21 +24,6 @@
                                url.path = decodeURIComponent( url.path );
                                url = url.toString();
                                if ( !url ) {
-                                       return false;
-                               }
-                               if ( !vg.config.urlBlackListRe ) {
-                                       // Lazy initialize urlBlackListRe
-                                       if ( vg.config.urlBlackList ) {
-                                               vg.config.urlBlackListRe = 
vg.config.urlBlackList.map( function ( s ) {
-                                                       return new RegExp( s );
-                                               } );
-                                       } else {
-                                               vg.config.urlBlackListRe = [];
-                                       }
-                               }
-                               if ( vg.config.urlBlackListRe.some( function ( 
re ) {
-                                       return re.test( url );
-                               } ) ) {
                                        return false;
                                }
                                return url;
diff --git a/modules/graph2.js b/modules/graph2.js
index ce23332..39eb075 100644
--- a/modules/graph2.js
+++ b/modules/graph2.js
@@ -1,18 +1,114 @@
 ( function ( $, mw ) {
-       var originalSanitize;
+       var originalSanitize, originalLoader;
 
-       // Make sure we only initialize graphs once
        vg.config.load.domainWhiteList = mw.config.get( 'wgGraphDataDomains' );
-       vg.config.load.urlBlackList = mw.config.get( 'wgGraphUrlBlacklist' );
 
+       vg.util.load.file = vg.util.load.http = function ( url, opt, callback ) 
{
+               callback( new Error( 'Loading of ' + url + ' is not allowed' ) 
);
+       };
+
+       // Override loader so that we can do post-loader data processing
+       originalLoader = vg.util.load.loader.bind( vg.util.load );
+       vg.util.load.loader = function ( opt, callback ) {
+               return originalLoader.call( vg.util.load, opt, function ( 
error, data ) {
+                       var json;
+
+                       if ( error ) {
+                               callback( error );
+                               return;
+                       }
+                       if ( opt.isApiCall ) {
+                               // This was an API call - check for errors
+                               json = JSON.parse( data ) ;
+                               if ( json.error ) {
+                                       error = new Error( 'API error: ' + 
JSON.stringify( json.error ) );
+                                       data = undefined;
+                               } else {
+                                       if ( json.warnings ) {
+                                               mw.log( 'API warnings: ' + 
JSON.stringify( json.warnings ) );
+                                       }
+                                       if ( opt.extractApiContent ) {
+                                               try {
+                                                       data = 
json.query.pages[ 0 ].revisions[ 0 ].content;
+                                               } catch ( e ) {
+                                                       data = undefined;
+                                                       error = new Error( 
'Page content not available ' + opt.url );
+                                               }
+                                       }
+                               }
+                       }
+                       callback( error, data );
+               } );
+       };
+
+       // Override sanitizer to implement custom protocols and extra validation
        originalSanitize = vg.util.load.sanitizeUrl.bind( vg.util.load );
        vg.util.load.sanitizeUrl = function ( opt ) {
-               var url = originalSanitize.apply( vg.util.load, arguments );
-               if ( !url ) {
-                       return false;
+               var path, query,
+                       url = new mw.Uri( opt.url );
+
+               switch ( url.protocol ) {
+                       case 'http':
+                       case 'https':
+                               // Will disable this as soon as all graphs have 
been switched to custom protocols
+                               url.path = decodeURIComponent( url.path );
+                               opt.url = url.toString();
+                               return originalSanitize.call( vg.util.load, opt 
);
+
+                       case 'wikiapi':
+                               // wikiapi:///?action=query&list=allpages
+                               // Call to api.php - ignores the path 
parameter, and only uses the query
+                               path = '/w/api.php';
+                               query = $.extend( url.query, { format: 'json', 
formatversion: 'latest' } );
+                               opt.isApiCall = true;
+                               break;
+
+                       case 'wikirest':
+                               // wikirest:///api/rest_v1/page/...
+                               // Call to RESTbase api - requires the path to 
start with "/api/"
+                               if ( !/^\/api\//.test( url.path ) ) {
+                                       return false;
+                               }
+                               path = url.path;
+                               query = url.query;
+                               break;
+
+                       case 'wikiraw':
+                               // wikiraw:///MyPage/data
+                               // Get raw content of a wiki page, where the 
path is the title
+                               // of the page with an additional leading '/' 
which gets removed.
+                               // Uses mediawiki api, and extract the content 
after the request
+                               path = '/w/api.php';
+                               query = {
+                                       format: 'json',
+                                       formatversion: 'latest',
+                                       action: 'query',
+                                       prop: 'revisions',
+                                       rvprop: 'content',
+                                       titles: url.path.substring( 1 )
+                               };
+                               opt.isApiCall = true;
+                               opt.extractApiContent = true;
+                               break;
+
+                       case 'wikirawupload':
+                               // 
wikirawupload://upload.wikimedia.org/wikipedia/commons/3/3e/Einstein_1921_by_F_Schmutzer_-_restoration.jpg
+                               // Get an image for the graph, e.g. from commons
+                               // This tag specifies any content from the 
uploads.* domain, without query params
+                               if ( !/^upload\./.test( url.host ) ) {
+                                       return false;
+                               }
+                               path = url.path;
+                               break;
                }
-               // Normalize url by parsing and re-encoding it
-               url = new mw.Uri( url );
+
+               opt.url = new mw.Uri( {
+                       host: url.host,
+                       port: url.port,
+                       path: path,
+                       query: query
+               } ).toString();
+
                if ( !mw.config.get( 'wgGraphIsTrusted' ) &&
                        window.location.hostname.toLowerCase() === 
url.host.toLowerCase()
                ) {
@@ -21,27 +117,7 @@
                        opt.headers = { 'Treat-as-Untrusted': 1 };
                }
 
-               url.path = decodeURIComponent( url.path );
-               url = url.toString();
-               if ( !url ) {
-                       return false;
-               }
-               if ( !vg.config.load.urlBlackListRe ) {
-                       // Lazy initialize urlBlackListRe
-                       if ( vg.config.load.urlBlackList ) {
-                               vg.config.load.urlBlackListRe = 
vg.config.load.urlBlackList.map( function ( s ) {
-                                       return new RegExp( s );
-                               } );
-                       } else {
-                               vg.config.load.urlBlackListRe = [];
-                       }
-               }
-               if ( vg.config.load.urlBlackListRe.some( function ( re ) {
-                                       return re.test( url );
-                               } ) ) {
-                       return false;
-               }
-               return url;
+               return originalSanitize.call( vg.util.load, opt );
        };
 
        /**

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I6be3f3f30a725d7a4c8ce9cf349f341f2bc19dd6
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Graph
Gerrit-Branch: wmf/1.27.0-wmf.9
Gerrit-Owner: Yurik <yu...@wikimedia.org>
Gerrit-Reviewer: Yurik <yu...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to