diff --git a/js/common.js b/js/common.js index bc3bd39..be1cf37 100644 --- a/js/common.js +++ b/js/common.js @@ -22,11 +22,13 @@ require('./bootstrap-3.3.7'); require('./privatebin'); // internal variables -var a2zString = ['a','b','c','d','e','f','g','h','i','j','k','l','m', - 'n','o','p','q','r','s','t','u','v','w','x','y','z'], - alnumString = a2zString.concat(['0','1','2','3','4','5','6','7','8','9']), - queryString = alnumString.concat(['+','%','&','.','*','-','_']), - hashString = queryString.concat(['!']), +var a2zString = ['a','b','c','d','e','f','g','h','i','j','k','l','m', + 'n','o','p','q','r','s','t','u','v','w','x','y','z'], + digitString = ['0','1','2','3','4','5','6','7','8','9'], + alnumString = a2zString.concat(digitString), + hexString = digitString.concat(['a','b','c','d','e','f']), + queryString = alnumString.concat(['+','%','&','.','*','-','_']), + hashString = queryString.concat(['!']), base64String = alnumString.concat(['+','/','=']).concat( a2zString.map(function(c) { return c.toUpperCase(); @@ -123,6 +125,11 @@ exports.jscAlnumString = function() { return jsc.elements(alnumString); }; +//provides random characters allowed in hexadecimal notation +exports.jscHexString = function() { + return jsc.elements(hexString); +}; + // provides random characters allowed in GET queries exports.jscQueryString = function() { return jsc.elements(queryString); diff --git a/js/privatebin.js b/js/privatebin.js index 57eb273..cf74733 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -743,13 +743,44 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) { */ me.getPasteId = function() { - if (id === null) { - // Attention: This also returns the delete token inside of the ID, if it is specified - id = window.location.search.substring(1); + const idRegEx = /^[a-z0-9]{16}$/; + const idRegExFind = /[a-z0-9]{16}/; - if (id === '') { - throw 'no paste id given'; + // return cached value + if (id !== null) { + return id; + } + + // do use URL interface, if possible + if (window.URL && window.URL.prototype && ('searchParams' in window.URL.prototype)) { + try { + const url = new URL(window.location); + + for (const param of url.searchParams) { + const key = param[0]; + const value = param[1]; + + if (value === '' && idRegEx.test(key)) { + // safe, as the whole regex is matched + id = key; + return id; + } + } + } catch (e) { + // fallback below + console.error('URL interface not properly supported, error:', e); } + } else { + console.warn('URL interface appears not to be supported in this browser.'); + } + + // fallback to simple RegEx + console.warn('fallback to simple RegEx search'); + // Attention: This also returns the delete token inside of the ID, if it is specified + id = (window.location.search.match(idRegExFind) || [''])[0]; + + if (id === '') { + throw 'no paste id given'; } return id; diff --git a/js/test/Model.js b/js/test/Model.js index 18ec8a8..1ed8812 100644 --- a/js/test/Model.js +++ b/js/test/Model.js @@ -81,18 +81,23 @@ describe('Model', function () { 'returns the query string without separator, if any', jsc.nearray(common.jscA2zString()), jsc.nearray(common.jscA2zString()), - jsc.nearray(common.jscHashString()), + jsc.tuple(new Array(16).fill(common.jscHexString)), + jsc.array(common.jscQueryString()), + jsc.array(common.jscQueryString()), 'string', - function (schema, address, query, fragment) { - var queryString = query.join(''), - clean = jsdom('', { + function (schema, address, pasteId, queryStart, queryEnd, fragment) { + var pasteIdString = pasteId.join(''), + queryStartString = queryStart.join('') + (queryStart.length > 0 ? '&' : ''), + queryEndString = (queryEnd.length > 0 ? '&' : '') + queryEnd.join(''), + queryString = queryStartString + pasteIdString + queryEndString, + clean = jsdom('', { url: schema.join('') + '://' + address.join('') + '/?' + queryString + '#' + fragment }), result = $.PrivateBin.Model.getPasteId(); $.PrivateBin.Model.reset(); clean(); - return queryString === result; + return pasteIdString === result; } ); jsc.property( diff --git a/js/test/Prompt.js b/js/test/Prompt.js index 0e65b25..038f7a0 100644 --- a/js/test/Prompt.js +++ b/js/test/Prompt.js @@ -16,7 +16,7 @@ describe('Prompt', function () { 'string', function (password) { password = password.replace(/\r+/g, ''); - var clean = jsdom('', {url: 'ftp://example.com/?0'}); + var clean = jsdom('', {url: 'ftp://example.com/?0000000000000000'}); $('body').html( '