more general solution addressing #554, kudos @rugk for the suggestions

This commit is contained in:
El RIDO 2020-01-04 11:34:16 +01:00
parent 8d0ac336d2
commit 4bf7f863dc
No known key found for this signature in database
GPG Key ID: 0F5C940A6BD81F92
15 changed files with 95 additions and 143 deletions

View File

@ -40,21 +40,6 @@ var a2zString = ['a','b','c','d','e','f','g','h','i','j','k','l','m',
supportedLanguages = ['de', 'es', 'fr', 'it', 'no', 'pl', 'pt', 'oc', 'ru', 'sl', 'zh'], supportedLanguages = ['de', 'es', 'fr', 'it', 'no', 'pl', 'pt', 'oc', 'ru', 'sl', 'zh'],
mimeTypes = ['image/png', 'application/octet-stream'], mimeTypes = ['image/png', 'application/octet-stream'],
formats = ['plaintext', 'markdown', 'syntaxhighlighting'], formats = ['plaintext', 'markdown', 'syntaxhighlighting'],
/**
* character to HTML entity lookup table
*
* @see {@link https://github.com/janl/mustache.js/blob/master/mustache.js#L60}
*/
entityMap = {
'&': '&',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
'/': '&#x2F;',
'`': '&#x60;',
'=': '&#x3D;'
},
mimeFile = fs.createReadStream('/etc/mime.types'), mimeFile = fs.createReadStream('/etc/mime.types'),
mimeLine = ''; mimeLine = '';
@ -97,22 +82,6 @@ function parseMime(line) {
exports.atob = atob; exports.atob = atob;
exports.btoa = btoa; exports.btoa = btoa;
/**
* convert all applicable characters to HTML entities
*
* @see {@link https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content}
* @name htmlEntities
* @function
* @param {string} str
* @return {string} escaped HTML
*/
exports.htmlEntities = function(str) {
return String(str).replace(
/[&<>"'`=\/]/g, function(s) {
return entityMap[s];
});
};
// provides random lowercase characters from a to z // provides random lowercase characters from a to z
exports.jscA2zString = function() { exports.jscA2zString = function() {
return jsc.elements(a2zString); return jsc.elements(a2zString);

View File

@ -440,7 +440,33 @@ jQuery.PrivateBin = (function($, RawDeflate) {
expirationDate = expirationDate.setUTCSeconds(expirationDate.getUTCSeconds() + secondsToExpiration); expirationDate = expirationDate.setUTCSeconds(expirationDate.getUTCSeconds() + secondsToExpiration);
return expirationDate; return expirationDate;
} };
/**
* encode all applicable characters to HTML entities
*
* @see {@link https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html}
*
* @name Helper.htmlEntities
* @function
* @param string str
* @return string escaped HTML
*/
me.htmlEntities = function(str) {
// using textarea, since other tags may allow and execute scripts, even when detached from DOM
let holder = document.createElement('textarea');
holder.textContent = str;
// as per OWASP recommendation, also encoding quotes and slash
return holder.innerHTML.replace(
/["'\/]/g,
function(s) {
return {
'"': '&quot;',
"'": '&#x27;',
'/': '&#x2F;'
}[s];
});
};
return me; return me;
})(); })();
@ -592,16 +618,31 @@ jQuery.PrivateBin = (function($, RawDeflate) {
args[0] = translations[messageId]; args[0] = translations[messageId];
} }
// messageID may contain links, but should be from a trusted source (code or translation JSON files)
let containsNoLinks = args[0].indexOf('<a') === -1;
for (let i = 0; i < args.length; ++i) {
// parameters (i > 0) may never contain HTML as they may come from untrusted parties
if (i > 0 || containsNoLinks) {
args[i] = Helper.htmlEntities(args[i]);
}
}
// format string // format string
let output = Helper.sprintf.apply(this, args); let output = Helper.sprintf.apply(this, args);
// if $element is given, apply text to element // if $element is given, apply text to element
if ($element !== null) { if ($element !== null) {
// avoid HTML entity encoding if translation contains link if (containsNoLinks) {
if (output.indexOf('<a') === -1) { // avoid HTML entity encoding if translation contains links
$element.text(output); $element.text(output);
} else { } else {
$element.html(output); // only allow tags/attributes we actually use in our translations
$element.html(
DOMPurify.sanitize(output, {
ALLOWED_TAGS: ['a', 'br', 'i', 'span'],
ALLOWED_ATTR: ['href', 'id']
})
);
} }
} }
@ -2362,7 +2403,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
// escape HTML entities, link URLs, sanitize // escape HTML entities, link URLs, sanitize
const escapedLinkedText = Helper.urls2links( const escapedLinkedText = Helper.urls2links(
$('<div />').text(text).html() Helper.htmlEntities(text)
), ),
sanitizedLinkedText = DOMPurify.sanitize(escapedLinkedText); sanitizedLinkedText = DOMPurify.sanitize(escapedLinkedText);
$plainText.html(sanitizedLinkedText); $plainText.html(sanitizedLinkedText);
@ -2796,11 +2837,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
$attachmentLink.appendTo($element); $attachmentLink.appendTo($element);
// update text - ensuring no HTML is inserted into the text node // update text - ensuring no HTML is inserted into the text node
I18n._( I18n._($attachmentLink, label, $attachmentLink.attr('download'));
$attachmentLink,
$('<div />').text(label).html(),
$('<div />').text($attachmentLink.attr('download')).html()
);
}; };
/** /**
@ -3498,7 +3535,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
for (let i = 0; i < $head.length; ++i) { for (let i = 0; i < $head.length; ++i) {
newDoc.write($head[i].outerHTML); newDoc.write($head[i].outerHTML);
} }
newDoc.write('</head><body><pre>' + DOMPurify.sanitize($('<div />').text(paste).html()) + '</pre></body></html>'); newDoc.write('</head><body><pre>' + DOMPurify.sanitize(Helper.htmlEntities(paste)) + '</pre></body></html>');
newDoc.close(); newDoc.close();
} }

View File

@ -67,10 +67,6 @@ describe('Alert', function () {
}); });
describe('showWarning', function () { describe('showWarning', function () {
before(function () {
cleanup();
});
jsc.property( jsc.property(
'shows a warning message (basic)', 'shows a warning message (basic)',
jsc.array(common.jscAlnumString()), jsc.array(common.jscAlnumString()),
@ -136,10 +132,6 @@ describe('Alert', function () {
}); });
describe('showError', function () { describe('showError', function () {
before(function () {
cleanup();
});
jsc.property( jsc.property(
'shows an error message (basic)', 'shows an error message (basic)',
jsc.array(common.jscAlnumString()), jsc.array(common.jscAlnumString()),
@ -205,10 +197,6 @@ describe('Alert', function () {
}); });
describe('showRemaining', function () { describe('showRemaining', function () {
before(function () {
cleanup();
});
jsc.property( jsc.property(
'shows remaining time (basic)', 'shows remaining time (basic)',
jsc.array(common.jscAlnumString()), jsc.array(common.jscAlnumString()),
@ -254,10 +242,6 @@ describe('Alert', function () {
}); });
describe('showLoading', function () { describe('showLoading', function () {
before(function () {
cleanup();
});
jsc.property( jsc.property(
'shows a loading message (basic)', 'shows a loading message (basic)',
jsc.array(common.jscAlnumString()), jsc.array(common.jscAlnumString()),
@ -310,10 +294,6 @@ describe('Alert', function () {
}); });
describe('hideLoading', function () { describe('hideLoading', function () {
before(function () {
cleanup();
});
it( it(
'hides the loading message', 'hides the loading message',
function() { function() {
@ -335,10 +315,6 @@ describe('Alert', function () {
}); });
describe('hideMessages', function () { describe('hideMessages', function () {
before(function () {
cleanup();
});
it( it(
'hides all messages', 'hides all messages',
function() { function() {
@ -361,10 +337,6 @@ describe('Alert', function () {
}); });
describe('setCustomHandler', function () { describe('setCustomHandler', function () {
before(function () {
cleanup();
});
jsc.property( jsc.property(
'calls a given handler function', 'calls a given handler function',
'nat 3', 'nat 3',

View File

@ -4,9 +4,6 @@ var common = require('../common');
describe('AttachmentViewer', function () { describe('AttachmentViewer', function () {
describe('setAttachment, showAttachment, removeAttachment, hideAttachment, hideAttachmentPreview, hasAttachment, getAttachment & moveAttachmentTo', function () { describe('setAttachment, showAttachment, removeAttachment, hideAttachment, hideAttachmentPreview, hasAttachment, getAttachment & moveAttachmentTo', function () {
this.timeout(30000); this.timeout(30000);
before(function () {
cleanup();
});
jsc.property( jsc.property(
'displays & hides data as requested', 'displays & hides data as requested',
@ -16,7 +13,7 @@ describe('AttachmentViewer', function () {
'string', 'string',
'string', 'string',
function (mimeType, rawdata, filename, prefix, postfix) { function (mimeType, rawdata, filename, prefix, postfix) {
var clean = jsdom(), let clean = jsdom(),
data = 'data:' + mimeType + ';base64,' + btoa(rawdata), data = 'data:' + mimeType + ';base64,' + btoa(rawdata),
previewSupported = ( previewSupported = (
mimeType.substring(0, 6) === 'image/' || mimeType.substring(0, 6) === 'image/' ||
@ -24,7 +21,8 @@ describe('AttachmentViewer', function () {
mimeType.substring(0, 6) === 'video/' || mimeType.substring(0, 6) === 'video/' ||
mimeType.match(/\/pdf/i) mimeType.match(/\/pdf/i)
), ),
results = []; results = [],
result = '';
prefix = prefix.replace(/%(s|d)/g, '%%'); prefix = prefix.replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%'); postfix = postfix.replace(/%(s|d)/g, '%%');
$('body').html( $('body').html(
@ -57,7 +55,7 @@ describe('AttachmentViewer', function () {
} }
// beyond this point we will get the blob URL instead of the data // beyond this point we will get the blob URL instead of the data
data = window.URL.createObjectURL(data); data = window.URL.createObjectURL(data);
var attachment = $.PrivateBin.AttachmentViewer.getAttachment(); const attachment = $.PrivateBin.AttachmentViewer.getAttachment();
results.push( results.push(
$.PrivateBin.AttachmentViewer.hasAttachment() && $.PrivateBin.AttachmentViewer.hasAttachment() &&
$('#attachment').hasClass('hidden') && $('#attachment').hasClass('hidden') &&
@ -84,13 +82,19 @@ describe('AttachmentViewer', function () {
!$('#attachment').hasClass('hidden') && !$('#attachment').hasClass('hidden') &&
(previewSupported ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden')) (previewSupported ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden'))
); );
var element = $('<div></div>'); let element = $('<div>');
$.PrivateBin.AttachmentViewer.moveAttachmentTo(element, prefix + '%s' + postfix); $.PrivateBin.AttachmentViewer.moveAttachmentTo(element, prefix + '%s' + postfix);
// messageIDs with links get a relaxed treatment
if (prefix.indexOf('<a') === -1 && postfix.indexOf('<a') === -1) {
result = $.PrivateBin.Helper.htmlEntities(prefix + filename + postfix);
} else {
result = $('<div>').html(prefix + $.PrivateBin.Helper.htmlEntities(filename) + postfix).html();
}
if (filename.length) { if (filename.length) {
results.push( results.push(
element.children()[0].href === data && element.children()[0].href === data &&
element.children()[0].getAttribute('download') === filename && element.children()[0].getAttribute('download') === filename &&
element.children()[0].text === $('<div />').text(prefix + filename + postfix).html() element.children()[0].text === result
); );
} else { } else {
results.push(element.children()[0].href === data); results.push(element.children()[0].href === data);

View File

@ -5,9 +5,6 @@ var common = require('../common');
describe('Check', function () { describe('Check', function () {
describe('init', function () { describe('init', function () {
this.timeout(30000); this.timeout(30000);
before(function () {
cleanup();
});
it('returns false and shows error, if a bot UA is detected', function () { it('returns false and shows error, if a bot UA is detected', function () {
jsc.assert(jsc.forall( jsc.assert(jsc.forall(

View File

@ -4,9 +4,6 @@ var common = require('../common');
describe('DiscussionViewer', function () { describe('DiscussionViewer', function () {
describe('handleNotification, prepareNewDiscussion, addComment, finishDiscussion, getReplyMessage, getReplyNickname, getReplyCommentId & highlightComment', function () { describe('handleNotification, prepareNewDiscussion, addComment, finishDiscussion, getReplyMessage, getReplyNickname, getReplyCommentId & highlightComment', function () {
this.timeout(30000); this.timeout(30000);
before(function () {
cleanup();
});
jsc.property( jsc.property(
'displays & hides comments as requested', 'displays & hides comments as requested',

View File

@ -4,9 +4,6 @@ require('../common');
describe('Editor', function () { describe('Editor', function () {
describe('show, hide, getText, setText & isPreview', function () { describe('show, hide, getText, setText & isPreview', function () {
this.timeout(30000); this.timeout(30000);
before(function () {
cleanup();
});
jsc.property( jsc.property(
'returns text fed into the textarea, handles editor tabs', 'returns text fed into the textarea, handles editor tabs',

View File

@ -3,10 +3,6 @@ var common = require('../common');
describe('Helper', function () { describe('Helper', function () {
describe('secondsToHuman', function () { describe('secondsToHuman', function () {
after(function () {
cleanup();
});
jsc.property('returns an array with a number and a word', 'integer', function (number) { jsc.property('returns an array with a number and a word', 'integer', function (number) {
var result = $.PrivateBin.Helper.secondsToHuman(number); var result = $.PrivateBin.Helper.secondsToHuman(number);
return Array.isArray(result) && return Array.isArray(result) &&
@ -57,11 +53,11 @@ describe('Helper', function () {
'nearray string', 'nearray string',
function (ids, contents) { function (ids, contents) {
var html = '', var html = '',
result = true; result = true,
clean = jsdom(html);
ids.forEach(function(item, i) { ids.forEach(function(item, i) {
html += '<div id="' + item.join('') + '">' + common.htmlEntities(contents[i] || contents[0]) + '</div>'; html += '<div id="' + item.join('') + '">' + $.PrivateBin.Helper.htmlEntities(contents[i] || contents[0]) + '</div>';
}); });
var clean = jsdom(html);
// TODO: As per https://github.com/tmpvar/jsdom/issues/321 there is no getSelection in jsdom, yet. // TODO: As per https://github.com/tmpvar/jsdom/issues/321 there is no getSelection in jsdom, yet.
// Once there is one, uncomment the block below to actually check the result. // Once there is one, uncomment the block below to actually check the result.
/* /*
@ -77,8 +73,8 @@ describe('Helper', function () {
}); });
describe('urls2links', function () { describe('urls2links', function () {
after(function () { before(function () {
cleanup(); cleanup = jsdom();
}); });
jsc.property( jsc.property(
@ -100,8 +96,8 @@ describe('Helper', function () {
var query = query.join(''), var query = query.join(''),
fragment = fragment.join(''), fragment = fragment.join(''),
url = schema + '://' + address.join('') + '/?' + query + '#' + fragment, url = schema + '://' + address.join('') + '/?' + query + '#' + fragment,
prefix = common.htmlEntities(prefix), prefix = $.PrivateBin.Helper.htmlEntities(prefix),
postfix = ' ' + common.htmlEntities(postfix); postfix = ' ' + $.PrivateBin.Helper.htmlEntities(postfix);
// special cases: When the query string and fragment imply the beginning of an HTML entity, eg. &#0 or &#x // special cases: When the query string and fragment imply the beginning of an HTML entity, eg. &#0 or &#x
if ( if (
@ -123,18 +119,14 @@ describe('Helper', function () {
'string', 'string',
function (prefix, query, postfix) { function (prefix, query, postfix) {
var url = 'magnet:?' + query.join('').replace(/^&+|&+$/gm,''), var url = 'magnet:?' + query.join('').replace(/^&+|&+$/gm,''),
prefix = common.htmlEntities(prefix), prefix = $.PrivateBin.Helper.htmlEntities(prefix),
postfix = common.htmlEntities(postfix); postfix = $.PrivateBin.Helper.htmlEntities(postfix);
return prefix + '<a href="' + url + '" rel="nofollow">' + url + '</a> ' + postfix === $.PrivateBin.Helper.urls2links(prefix + url + ' ' + postfix); return prefix + '<a href="' + url + '" rel="nofollow">' + url + '</a> ' + postfix === $.PrivateBin.Helper.urls2links(prefix + url + ' ' + postfix);
} }
); );
}); });
describe('sprintf', function () { describe('sprintf', function () {
after(function () {
cleanup();
});
jsc.property( jsc.property(
'replaces %s in strings with first given parameter', 'replaces %s in strings with first given parameter',
'string', 'string',
@ -211,7 +203,7 @@ describe('Helper', function () {
describe('getCookie', function () { describe('getCookie', function () {
this.timeout(30000); this.timeout(30000);
after(function () { before(function () {
cleanup(); cleanup();
}); });
@ -263,16 +255,16 @@ describe('Helper', function () {
}); });
describe('htmlEntities', function () { describe('htmlEntities', function () {
after(function () { before(function () {
cleanup(); cleanup = jsdom();
}); });
jsc.property( jsc.property(
'removes all HTML entities from any given string', 'removes all HTML entities from any given string',
'string', 'string',
function (string) { function (string) {
var result = common.htmlEntities(string); var result = $.PrivateBin.Helper.htmlEntities(string);
return !(/[<>"'`=\/]/.test(result)) && !(string.indexOf('&') > -1 && !(/&amp;/.test(result))); return !(/[<>]/.test(result)) && !(string.indexOf('&') > -1 && !(/&amp;/.test(result)));
} }
); );
}); });

View File

@ -32,6 +32,7 @@ describe('I18n', function () {
var fakeAlias = $.PrivateBin.I18n._(fake); var fakeAlias = $.PrivateBin.I18n._(fake);
$.PrivateBin.I18n.reset(); $.PrivateBin.I18n.reset();
messageId = $.PrivateBin.Helper.htmlEntities(messageId);
return messageId === result && messageId === alias && return messageId === result && messageId === alias &&
messageId === pluralResult && messageId === pluralAlias && messageId === pluralResult && messageId === pluralAlias &&
messageId === fakeResult && messageId === fakeAlias; messageId === fakeResult && messageId === fakeAlias;
@ -46,7 +47,7 @@ describe('I18n', function () {
prefix = prefix.replace(/%(s|d)/g, '%%'); prefix = prefix.replace(/%(s|d)/g, '%%');
params[0] = params[0].replace(/%(s|d)/g, '%%'); params[0] = params[0].replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%'); postfix = postfix.replace(/%(s|d)/g, '%%');
var translation = prefix + params[0] + postfix; var translation = $.PrivateBin.Helper.htmlEntities(prefix + params[0] + postfix);
params.unshift(prefix + '%s' + postfix); params.unshift(prefix + '%s' + postfix);
var result = $.PrivateBin.I18n.translate.apply(this, params); var result = $.PrivateBin.I18n.translate.apply(this, params);
$.PrivateBin.I18n.reset(); $.PrivateBin.I18n.reset();

View File

@ -5,18 +5,18 @@ describe('Model', function () {
describe('getExpirationDefault', function () { describe('getExpirationDefault', function () {
before(function () { before(function () {
$.PrivateBin.Model.reset(); $.PrivateBin.Model.reset();
cleanup(); cleanup = jsdom();
}); });
jsc.property( jsc.property(
'returns the contents of the element with id "pasteExpiration"', 'returns the contents of the element with id "pasteExpiration"',
'array asciinestring', 'nearray asciinestring',
'string', 'string',
'small nat', 'small nat',
function (keys, value, key) { function (keys, value, key) {
keys = keys.map(common.htmlEntities); keys = keys.map($.PrivateBin.Helper.htmlEntities);
value = common.htmlEntities(value); value = $.PrivateBin.Helper.htmlEntities(value);
var content = keys.length > key ? keys[key] : (keys.length > 0 ? keys[0] : 'null'), var content = keys.length > key ? keys[key] : keys[0],
contents = '<select id="pasteExpiration" name="pasteExpiration">'; contents = '<select id="pasteExpiration" name="pasteExpiration">';
keys.forEach(function(item) { keys.forEach(function(item) {
contents += '<option value="' + item + '"'; contents += '<option value="' + item + '"';
@ -27,7 +27,7 @@ describe('Model', function () {
}); });
contents += '</select>'; contents += '</select>';
$('body').html(contents); $('body').html(contents);
var result = common.htmlEntities( var result = $.PrivateBin.Helper.htmlEntities(
$.PrivateBin.Model.getExpirationDefault() $.PrivateBin.Model.getExpirationDefault()
); );
$.PrivateBin.Model.reset(); $.PrivateBin.Model.reset();
@ -39,18 +39,20 @@ describe('Model', function () {
describe('getFormatDefault', function () { describe('getFormatDefault', function () {
before(function () { before(function () {
$.PrivateBin.Model.reset(); $.PrivateBin.Model.reset();
});
after(function () {
cleanup(); cleanup();
}); });
jsc.property( jsc.property(
'returns the contents of the element with id "pasteFormatter"', 'returns the contents of the element with id "pasteFormatter"',
'array asciinestring', 'nearray asciinestring',
'string', 'string',
'small nat', 'small nat',
function (keys, value, key) { function (keys, value, key) {
keys = keys.map(common.htmlEntities); keys = keys.map($.PrivateBin.Helper.htmlEntities);
value = common.htmlEntities(value); value = $.PrivateBin.Helper.htmlEntities(value);
var content = keys.length > key ? keys[key] : (keys.length > 0 ? keys[0] : 'null'), var content = keys.length > key ? keys[key] : keys[0],
contents = '<select id="pasteFormatter" name="pasteFormatter">'; contents = '<select id="pasteFormatter" name="pasteFormatter">';
keys.forEach(function(item) { keys.forEach(function(item) {
contents += '<option value="' + item + '"'; contents += '<option value="' + item + '"';
@ -61,7 +63,7 @@ describe('Model', function () {
}); });
contents += '</select>'; contents += '</select>';
$('body').html(contents); $('body').html(contents);
var result = common.htmlEntities( var result = $.PrivateBin.Helper.htmlEntities(
$.PrivateBin.Model.getFormatDefault() $.PrivateBin.Model.getFormatDefault()
); );
$.PrivateBin.Model.reset(); $.PrivateBin.Model.reset();
@ -74,7 +76,6 @@ describe('Model', function () {
this.timeout(30000); this.timeout(30000);
beforeEach(function () { beforeEach(function () {
$.PrivateBin.Model.reset(); $.PrivateBin.Model.reset();
cleanup();
}); });
jsc.property( jsc.property(
@ -130,7 +131,6 @@ describe('Model', function () {
this.timeout(30000); this.timeout(30000);
beforeEach(function () { beforeEach(function () {
$.PrivateBin.Model.reset(); $.PrivateBin.Model.reset();
cleanup();
}); });
jsc.property( jsc.property(
@ -238,7 +238,6 @@ describe('Model', function () {
describe('getTemplate', function () { describe('getTemplate', function () {
beforeEach(function () { beforeEach(function () {
$.PrivateBin.Model.reset(); $.PrivateBin.Model.reset();
cleanup();
}); });
jsc.property( jsc.property(

View File

@ -36,9 +36,6 @@ describe('PasteStatus', function () {
describe('showRemainingTime', function () { describe('showRemainingTime', function () {
this.timeout(30000); this.timeout(30000);
before(function () {
cleanup();
});
jsc.property( jsc.property(
'shows burn after reading message or remaining time v1', 'shows burn after reading message or remaining time v1',
@ -121,10 +118,6 @@ describe('PasteStatus', function () {
}); });
describe('hideMessages', function () { describe('hideMessages', function () {
before(function () {
cleanup();
});
it( it(
'hides all messages', 'hides all messages',
function() { function() {

View File

@ -4,9 +4,6 @@ var common = require('../common');
describe('PasteViewer', function () { describe('PasteViewer', function () {
describe('run, hide, getText, setText, getFormat, setFormat & isPrettyPrinted', function () { describe('run, hide, getText, setText, getFormat, setFormat & isPrettyPrinted', function () {
this.timeout(30000); this.timeout(30000);
before(function () {
cleanup();
});
jsc.property( jsc.property(
'displays text according to format', 'displays text according to format',

View File

@ -6,10 +6,6 @@ describe('Prompt', function () {
// in nodejs -> replace the prompt in the "page" template with a modal // in nodejs -> replace the prompt in the "page" template with a modal
describe('requestPassword & getPassword', function () { describe('requestPassword & getPassword', function () {
this.timeout(30000); this.timeout(30000);
before(function () {
$.PrivateBin.Model.reset();
cleanup();
});
jsc.property( jsc.property(
'returns the password fed into the dialog', 'returns the password fed into the dialog',
@ -26,6 +22,7 @@ describe('Prompt', function () {
'password"></div><button type="submit">Decrypt</button>' + 'password"></div><button type="submit">Decrypt</button>' +
'</form></div></div></div></div>' '</form></div></div></div></div>'
); );
$.PrivateBin.Model.reset();
$.PrivateBin.Model.init(); $.PrivateBin.Model.init();
$.PrivateBin.Prompt.init(); $.PrivateBin.Prompt.init();
$.PrivateBin.Prompt.requestPassword(); $.PrivateBin.Prompt.requestPassword();

View File

@ -72,7 +72,7 @@ endif;
?> ?>
<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.7.js" integrity="sha512-XjNEK1xwh7SJ/7FouwV4VZcGW9cMySL3SwNpXgrURLBcXXQYtZdqhGoNdEwx9vwLvFjUGDQVNgpOrTsXlSTiQg==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/purify-2.0.7.js" integrity="sha512-XjNEK1xwh7SJ/7FouwV4VZcGW9cMySL3SwNpXgrURLBcXXQYtZdqhGoNdEwx9vwLvFjUGDQVNgpOrTsXlSTiQg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-HxU8g6MFviBCv6fEKEL+bn0fICxg9++ZUxxqySWXkX4iGgLodH/OVZDfr3dgKK5vZAv+0niWLuf+CWZ+/gUwWw==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-vV7gNbSUVUstR7GC+oZ050bVkHkjezDQW40KrIKWlhvZoJyuLMpH/jF9eN1Wd8/YJd4eovY4LTPJDHvwI3pwjg==" crossorigin="anonymous"></script>
<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" /> <link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" /> <link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
<link rel="icon" type="image/png" href="img/favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" /> <link rel="icon" type="image/png" href="img/favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />

View File

@ -50,7 +50,7 @@ endif;
?> ?>
<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.7.js" integrity="sha512-XjNEK1xwh7SJ/7FouwV4VZcGW9cMySL3SwNpXgrURLBcXXQYtZdqhGoNdEwx9vwLvFjUGDQVNgpOrTsXlSTiQg==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/purify-2.0.7.js" integrity="sha512-XjNEK1xwh7SJ/7FouwV4VZcGW9cMySL3SwNpXgrURLBcXXQYtZdqhGoNdEwx9vwLvFjUGDQVNgpOrTsXlSTiQg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-HxU8g6MFviBCv6fEKEL+bn0fICxg9++ZUxxqySWXkX4iGgLodH/OVZDfr3dgKK5vZAv+0niWLuf+CWZ+/gUwWw==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-vV7gNbSUVUstR7GC+oZ050bVkHkjezDQW40KrIKWlhvZoJyuLMpH/jF9eN1Wd8/YJd4eovY4LTPJDHvwI3pwjg==" crossorigin="anonymous"></script>
<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" /> <link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" /> <link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
<link rel="icon" type="image/png" href="img/favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" /> <link rel="icon" type="image/png" href="img/favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />