diff --git a/README.md b/README.md index 2b29af421..dc72d1186 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ Repository | Reference | Recent Version [git-rev][git-revGHUrl] | [Documentation][git-revDOCUrl] | [![NPM version][git-revNPMVersionImage]][git-revNPMUrl] [github][githubGHUrl] | [Documentation][githubDOCUrl] | [![NPM version][githubNPMVersionImage]][githubNPMUrl] [highlight.js][highlight.jsGHUrl] | [Documentation][highlight.jsDOCUrl][ᴸᴬᴺᴳ][highlight.jsLANGUrl] | [![NPM version][highlight.jsNPMVersionImage]][highlight.jsNPMUrl] +[image-size][image-sizeGHUrl] | [Documentation][image-sizeDOCUrl] | [![NPM version][image-sizeNPMVersionImage]][image-sizeNPMUrl] [jquery][jQueryGHUrl] | [Documentation][jQueryDOCUrl] | [![NPM version][jQueryNPMVersionImage]][jQueryNPMUrl] [js-beautify][js-beautifyGHUrl] | [Documentation][js-beautifyDOCUrl] | [![NPM version][js-beautifyNPMVersionImage]][js-beautifyNPMUrl] [jsdom][jsdomGHUrl] | [Documentation][jsdomDOCUrl] | [![NPM version][jsdomNPMVersionImage]][jsdomNPMUrl] @@ -249,6 +250,11 @@ Outdated dependencies list can also be achieved with `$ npm --depth 0 outdated` [highlight.jsNPMVersionImage]: https://img.shields.io/npm/v/highlight.js.svg?style=flat [highlight.jsLANGUrl]: https://github.com/isagalaev/highlight.js/blob/master/docs/css-classes-reference.rst#language-names-and-aliases +[image-sizeNPMUrl]: https://www.npmjs.com/package/image-size +[image-sizeNPMVersionImage]: https://img.shields.io/npm/v/image-size?style=flat +[image-sizeGHUrl]: https://github.com/image-size/image-size +[image-sizeDOCUrl]: https://github.com/image-size/image-size/blob/master/Readme.md + [jQueryNPMUrl]: https://www.npmjs.com/package/jquery [jQueryNPMVersionImage]: https://img.shields.io/npm/v/jquery.svg?style=flat [jQueryGHUrl]: https://github.com/jquery/jquery diff --git a/controllers/scriptStorage.js b/controllers/scriptStorage.js index 6e6e942a2..276148d93 100644 --- a/controllers/scriptStorage.js +++ b/controllers/scriptStorage.js @@ -13,6 +13,8 @@ var fs = require('fs'); var util = require('util'); var _ = require('underscore'); var URL = require('url'); +var http = require('http'); +var https = require('https'); var crypto = require('crypto'); var stream = require('stream'); var peg = require('pegjs'); @@ -26,6 +28,7 @@ var moment = require('moment'); var Base62 = require('base62'); var SPDXOSI = require('spdx-osi'); // NOTE: Sub-dep of `spdx-is-osi` var SPDX = require('spdx-license-ids'); +var sizeOf = require('image-size'); var MongoClient = require('mongodb').MongoClient; var ExpressBrute = require('express-brute'); @@ -1381,6 +1384,14 @@ exports.storeScript = function (aUser, aMeta, aBuf, aUpdate, aCallback) { function (aInnerCallback) { // `@icon` validations var icon = null; + var maxX = 64; // px + var maxY = 64; // px + var buffer = null; + var fn = null; + var dimensions = null; + var matches = null; + var data = null; + var rDataURIbase64 = /^data:image\/.+;base64,(.*)$/; icon = findMeta(aMeta, 'UserScript.icon.0.value'); if (icon) { @@ -1393,9 +1404,71 @@ exports.storeScript = function (aUser, aMeta, aBuf, aUpdate, aCallback) { }), null); return; } - } - aInnerCallback(null); + // Test dimensions + if (/^data:/.test(icon)) { + matches = icon.match(rDataURIbase64); + if (matches) { + data = matches[1]; + buffer = new Buffer(data, 'base64'); + try { + dimensions = sizeOf(buffer); + } catch (aE) { + aInnerCallback(new statusError({ + message: '`@icon` ' + aE.message, + code: aE.code + })); + return; + } + + if (dimensions.width > maxX || dimensions.height > maxY) { + aInnerCallback(new statusError({ + message: '`@icon` dimensions are too large.', + code: 400 + }), null); + } else { + aInnerCallback(null); + } + } else { + aInnerCallback(new statusError({ + message: 'Invalid `@icon`', + code: 400 + }), null); + } + } else { + fn = /^http:/.test(icon) ? http : https; + fn.get(URL.parse(icon), function (aRes) { + var chunks = []; + aRes.on('data', function (aChunk) { + chunks.push(aChunk); + }).on('end', function () { + buffer = Buffer.concat(chunks); + try { + dimensions = sizeOf(buffer); + } catch (aE) { + aInnerCallback(new statusError({ + message: '`@icon` ' + aE.message, + code: aE.code + })); + return; + } + + if (dimensions.width > maxX || dimensions.height > maxY) { + aInnerCallback(new statusError({ + message: '`@icon` dimensions are too large.', + code: 400 + }), null); + } else { + aInnerCallback(null); + } + }).on('error', function (aErr) { + aInnerCallback(aErr); + }); + }); + } + } else { + aInnerCallback(null); + } }, function (aInnerCallback) { // `@supportURL` validations diff --git a/controllers/user.js b/controllers/user.js index 1b4d52c24..17646491f 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -1546,8 +1546,8 @@ exports.uploadScript = function (aReq, aRes, aNext) { scriptStorage.storeScript(aUser, aMeta, bufferConcat, false, function (aErr, aScript) { if (aErr || !aScript) { statusCodePage(aReq, aRes, aNext, { - statusCode: aErr.status.code, - statusMessage: aErr.status.message + statusCode: (aErr instanceof statusError ? aErr.status.code : aErr.code), + statusMessage: (aErr instanceof statusError ? aErr.status.message : aErr.code) }); return; } @@ -1603,8 +1603,8 @@ exports.submitSource = function (aReq, aRes, aNext) { if (aErr) { statusCodePage(aReq, aRes, aNext, { - statusCode: aErr.status.code, - statusMessage: aErr.status.message + statusCode: (aErr instanceof statusError ? aErr.status.code : aErr.code), + statusMessage: (aErr instanceof statusError ? aErr.status.message : aErr.message) }); return; } diff --git a/libs/helpers.js b/libs/helpers.js index 25709d44e..dbd64528d 100644 --- a/libs/helpers.js +++ b/libs/helpers.js @@ -163,7 +163,7 @@ exports.isFQUrl = function (aString, aMailto, aDataImg) { var source = encodeURIComponent(aString); var target = null; - if (protocol && /^https?/.test(protocol)) { + if (protocol && /^https?:$/.test(protocol)) { if (hostname) { target = encodeURIComponent(protocol) + encodeURIComponent('//') diff --git a/package.json b/package.json index e92d9e899..c0e5cbb92 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "git-rev": "0.2.1", "github": "0.2.4", "highlight.js": "9.12.0", + "image-size": "0.6.1", "jsdom": "11.5.1", "jquery": "3.2.1", "js-beautify": "1.7.4",