diff --git a/js/common.js b/js/common.js index 08a4907f..f0482ae6 100644 --- a/js/common.js +++ b/js/common.js @@ -21,11 +21,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(); @@ -118,6 +120,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 f4bb3caf..766e6124 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -1026,13 +1026,44 @@ jQuery.PrivateBin = (function($, 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 f9acc5c3..d5a92b38 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 310c4240..94abaabf 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( '