Yurik has uploaded a new change for review.
https://gerrit.wikimedia.org/r/259613
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(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Graph
refs/changes/13/259613/1
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: newchange
Gerrit-Change-Id: I6be3f3f30a725d7a4c8ce9cf349f341f2bc19dd6
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Graph
Gerrit-Branch: wmf/1.27.0-wmf.9
Gerrit-Owner: Yurik <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits