Merge branch 'master' into sanitizeMarkdown, changing test to use new library
This commit is contained in:
commit
233bd65b00
10 changed files with 856 additions and 49 deletions
2
.gitattributes
vendored
2
.gitattributes
vendored
|
@ -2,8 +2,6 @@ doc/ export-ignore
|
||||||
tst/ export-ignore
|
tst/ export-ignore
|
||||||
js/.istanbul.yml export-ignore
|
js/.istanbul.yml export-ignore
|
||||||
js/test.js export-ignore
|
js/test.js export-ignore
|
||||||
js/mocha-3.2.0.js export-ignore
|
|
||||||
css/mocha-3.2.0.css export-ignore
|
|
||||||
.codeclimate.yml export-ignore
|
.codeclimate.yml export-ignore
|
||||||
.csslintrc export-ignore
|
.csslintrc export-ignore
|
||||||
.dockerignore export-ignore
|
.dockerignore export-ignore
|
||||||
|
|
|
@ -3,10 +3,11 @@ preset: recommended
|
||||||
risky: false
|
risky: false
|
||||||
|
|
||||||
enabled:
|
enabled:
|
||||||
- no_empty_comment
|
|
||||||
- align_equals
|
- align_equals
|
||||||
- long_array_syntax
|
|
||||||
- concat_with_spaces
|
- concat_with_spaces
|
||||||
|
- long_array_syntax
|
||||||
|
- no_empty_comment
|
||||||
|
- pre_increment
|
||||||
|
|
||||||
disabled:
|
disabled:
|
||||||
- blank_line_after_opening_tag
|
- blank_line_after_opening_tag
|
||||||
|
@ -23,6 +24,7 @@ disabled:
|
||||||
- phpdoc_separation
|
- phpdoc_separation
|
||||||
- phpdoc_single_line_var_spacing
|
- phpdoc_single_line_var_spacing
|
||||||
- phpdoc_summary
|
- phpdoc_summary
|
||||||
|
- post_increment
|
||||||
- short_array_syntax
|
- short_array_syntax
|
||||||
- single_line_after_imports
|
- single_line_after_imports
|
||||||
- unalign_equals
|
- unalign_equals
|
||||||
|
|
|
@ -124,7 +124,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
range = document.body.createTextRange();
|
range = document.body.createTextRange();
|
||||||
range.moveToElementText(element);
|
range.moveToElementText(element);
|
||||||
range.select();
|
range.select();
|
||||||
} else if (window.getSelection){
|
} else if (window.getSelection) {
|
||||||
selection = window.getSelection();
|
selection = window.getSelection();
|
||||||
range = document.createRange();
|
range = document.createRange();
|
||||||
range.selectNodeContents(element);
|
range.selectNodeContents(element);
|
||||||
|
@ -302,8 +302,6 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
* internationalization module
|
* internationalization module
|
||||||
*
|
*
|
||||||
* @name I18n
|
* @name I18n
|
||||||
* @param {object} window
|
|
||||||
* @param {object} document
|
|
||||||
* @class
|
* @class
|
||||||
*/
|
*/
|
||||||
var I18n = (function () {
|
var I18n = (function () {
|
||||||
|
@ -414,7 +412,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
var orgArguments = arguments;
|
var orgArguments = arguments;
|
||||||
$(document).on(languageLoadedEvent, function () {
|
$(document).on(languageLoadedEvent, function () {
|
||||||
// log to show that the previous error could be mitigated
|
// log to show that the previous error could be mitigated
|
||||||
console.log('Fix missing translation of \'' + messageId + '\' with now loaded language ' + language);
|
console.warn('Fix missing translation of \'' + messageId + '\' with now loaded language ' + language);
|
||||||
// re-execute this function
|
// re-execute this function
|
||||||
me.translate.apply(this, orgArguments);
|
me.translate.apply(this, orgArguments);
|
||||||
});
|
});
|
||||||
|
@ -845,11 +843,9 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
* everything directly UI-related, which fits nowhere else
|
* everything directly UI-related, which fits nowhere else
|
||||||
*
|
*
|
||||||
* @name UiHelper
|
* @name UiHelper
|
||||||
* @param {object} window
|
|
||||||
* @param {object} document
|
|
||||||
* @class
|
* @class
|
||||||
*/
|
*/
|
||||||
var UiHelper = (function (window, document) {
|
var UiHelper = (function () {
|
||||||
var me = {};
|
var me = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -866,7 +862,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
{
|
{
|
||||||
var currentLocation = Helper.baseUri();
|
var currentLocation = Helper.baseUri();
|
||||||
if (event.originalEvent.state === null && // no state object passed
|
if (event.originalEvent.state === null && // no state object passed
|
||||||
event.originalEvent.target.location.href === currentLocation && // target location is home page
|
event.target.location.href === currentLocation && // target location is home page
|
||||||
window.location.href === currentLocation // and we are not already on the home page
|
window.location.href === currentLocation // and we are not already on the home page
|
||||||
) {
|
) {
|
||||||
// redirect to home page
|
// redirect to home page
|
||||||
|
@ -958,6 +954,23 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* trigger a history (pop) state change
|
||||||
|
*
|
||||||
|
* used to test the UiHelper.historyChange private function
|
||||||
|
*
|
||||||
|
* @name UiHelper.mockHistoryChange
|
||||||
|
* @function
|
||||||
|
* @param {string} state (optional) state to mock
|
||||||
|
*/
|
||||||
|
me.mockHistoryChange = function(state)
|
||||||
|
{
|
||||||
|
if (typeof state === 'undefined') {
|
||||||
|
state = null;
|
||||||
|
}
|
||||||
|
historyChange($.Event('popstate', {originalEvent: new PopStateEvent('popstate', {state: state}), target: window}));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initialize
|
* initialize
|
||||||
*
|
*
|
||||||
|
@ -973,7 +986,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return me;
|
return me;
|
||||||
})(window, document);
|
})();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alert/error manager
|
* Alert/error manager
|
||||||
|
@ -989,12 +1002,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
$statusMessage,
|
$statusMessage,
|
||||||
$remainingTime;
|
$remainingTime;
|
||||||
|
|
||||||
var currentIcon = [
|
var currentIcon;
|
||||||
'glyphicon-time', // loading icon
|
|
||||||
'glyphicon-info-sign', // status icon
|
|
||||||
'', // resevered for warning, not used yet
|
|
||||||
'glyphicon-alert' // error icon
|
|
||||||
];
|
|
||||||
|
|
||||||
var alertType = [
|
var alertType = [
|
||||||
'loading', // not in bootstrap, but using a good value here
|
'loading', // not in bootstrap, but using a good value here
|
||||||
|
@ -1090,7 +1098,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
*/
|
*/
|
||||||
me.showStatus = function(message, icon, dismissable, autoclose)
|
me.showStatus = function(message, icon, dismissable, autoclose)
|
||||||
{
|
{
|
||||||
console.log('status shown: ', message);
|
console.info('status shown: ', message);
|
||||||
// @TODO: implement dismissable
|
// @TODO: implement dismissable
|
||||||
// @TODO: implement autoclose
|
// @TODO: implement autoclose
|
||||||
|
|
||||||
|
@ -1133,7 +1141,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
*/
|
*/
|
||||||
me.showRemaining = function(message)
|
me.showRemaining = function(message)
|
||||||
{
|
{
|
||||||
console.log('remaining message shown: ', message);
|
console.info('remaining message shown: ', message);
|
||||||
handleNotification(1, $remainingTime, message);
|
handleNotification(1, $remainingTime, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1151,7 +1159,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
me.showLoading = function(message, percentage, icon)
|
me.showLoading = function(message, percentage, icon)
|
||||||
{
|
{
|
||||||
if (typeof message !== 'undefined' && message !== null) {
|
if (typeof message !== 'undefined' && message !== null) {
|
||||||
console.log('status changed: ', message);
|
console.info('status changed: ', message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// default message text
|
// default message text
|
||||||
|
@ -1238,6 +1246,13 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
$loadingIndicator = $('#loadingindicator');
|
$loadingIndicator = $('#loadingindicator');
|
||||||
$statusMessage = $('#status');
|
$statusMessage = $('#status');
|
||||||
$remainingTime = $('#remainingtime');
|
$remainingTime = $('#remainingtime');
|
||||||
|
|
||||||
|
currentIcon = [
|
||||||
|
'glyphicon-time', // loading icon
|
||||||
|
'glyphicon-info-sign', // status icon
|
||||||
|
'', // reserved for warning, not used yet
|
||||||
|
'glyphicon-alert' // error icon
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return me;
|
return me;
|
||||||
|
@ -1247,10 +1262,9 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
* handles paste status/result
|
* handles paste status/result
|
||||||
*
|
*
|
||||||
* @name PasteStatus
|
* @name PasteStatus
|
||||||
* @param {object} window
|
|
||||||
* @class
|
* @class
|
||||||
*/
|
*/
|
||||||
var PasteStatus = (function (window) {
|
var PasteStatus = (function () {
|
||||||
var me = {};
|
var me = {};
|
||||||
|
|
||||||
var $pasteSuccess,
|
var $pasteSuccess,
|
||||||
|
@ -1351,7 +1365,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
];
|
];
|
||||||
|
|
||||||
Alert.showRemaining([expirationLabel, expiration[0]]);
|
Alert.showRemaining([expirationLabel, expiration[0]]);
|
||||||
$remainingTime.removeClass('foryoureyesonly')
|
$remainingTime.removeClass('foryoureyesonly');
|
||||||
} else {
|
} else {
|
||||||
// never expires
|
// never expires
|
||||||
return;
|
return;
|
||||||
|
@ -1383,7 +1397,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
*/
|
*/
|
||||||
me.init = function()
|
me.init = function()
|
||||||
{
|
{
|
||||||
$pasteSuccess = $('#pasteSuccess');
|
$pasteSuccess = $('#pastesuccess');
|
||||||
// $pasteUrl is saved in me.createPasteNotification() after creation
|
// $pasteUrl is saved in me.createPasteNotification() after creation
|
||||||
$remainingTime = $('#remainingtime');
|
$remainingTime = $('#remainingtime');
|
||||||
$shortenButton = $('#shortenbutton');
|
$shortenButton = $('#shortenbutton');
|
||||||
|
@ -1393,7 +1407,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return me;
|
return me;
|
||||||
})(window);
|
})();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* password prompt
|
* password prompt
|
||||||
|
@ -1454,7 +1468,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
throw 'password prompt canceled';
|
throw 'password prompt canceled';
|
||||||
}
|
}
|
||||||
if (password.length === 0) {
|
if (password.length === 0) {
|
||||||
// recursive…
|
// recurse…
|
||||||
return me.requestPassword();
|
return me.requestPassword();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1462,7 +1476,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getthe cached password
|
* get the cached password
|
||||||
*
|
*
|
||||||
* If you do not get a password with this function
|
* If you do not get a password with this function
|
||||||
* (returns an empty string), use requestPassword.
|
* (returns an empty string), use requestPassword.
|
||||||
|
@ -1827,7 +1841,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
*
|
*
|
||||||
* @name PasteViewer.setFormat
|
* @name PasteViewer.setFormat
|
||||||
* @function
|
* @function
|
||||||
* @param {string} newFormat the the new format
|
* @param {string} newFormat the new format
|
||||||
*/
|
*/
|
||||||
me.setFormat = function(newFormat)
|
me.setFormat = function(newFormat)
|
||||||
{
|
{
|
||||||
|
@ -1836,7 +1850,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// needs to update display too, if from or to Markdown is switched
|
// needs to update display too, if we switch from or to Markdown
|
||||||
if (format === 'markdown' || newFormat === 'markdown') {
|
if (format === 'markdown' || newFormat === 'markdown') {
|
||||||
isDisplayed = false;
|
isDisplayed = false;
|
||||||
}
|
}
|
||||||
|
@ -1965,6 +1979,9 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
|
|
||||||
// get default option from template/HTML or fall back to set value
|
// get default option from template/HTML or fall back to set value
|
||||||
format = Model.getFormatDefault() || format;
|
format = Model.getFormatDefault() || format;
|
||||||
|
text = '';
|
||||||
|
isDisplayed = false;
|
||||||
|
isChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return me;
|
return me;
|
||||||
|
@ -2641,7 +2658,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
me.showViewButtons = function()
|
me.showViewButtons = function()
|
||||||
{
|
{
|
||||||
if (viewButtonsDisplayed) {
|
if (viewButtonsDisplayed) {
|
||||||
console.log('showViewButtons: view buttons are already displayed');
|
console.warn('showViewButtons: view buttons are already displayed');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2661,7 +2678,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
me.hideViewButtons = function()
|
me.hideViewButtons = function()
|
||||||
{
|
{
|
||||||
if (!viewButtonsDisplayed) {
|
if (!viewButtonsDisplayed) {
|
||||||
console.log('hideViewButtons: view buttons are already hidden');
|
console.warn('hideViewButtons: view buttons are already hidden');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2693,7 +2710,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
me.showCreateButtons = function()
|
me.showCreateButtons = function()
|
||||||
{
|
{
|
||||||
if (createButtonsDisplayed) {
|
if (createButtonsDisplayed) {
|
||||||
console.log('showCreateButtons: create buttons are already displayed');
|
console.warn('showCreateButtons: create buttons are already displayed');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2718,7 +2735,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
me.hideCreateButtons = function()
|
me.hideCreateButtons = function()
|
||||||
{
|
{
|
||||||
if (!createButtonsDisplayed) {
|
if (!createButtonsDisplayed) {
|
||||||
console.log('hideCreateButtons: create buttons are already hidden');
|
console.warn('hideCreateButtons: create buttons are already hidden');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3970,7 +3987,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
||||||
Uploader.setUnencryptedData('deletetoken', deleteToken);
|
Uploader.setUnencryptedData('deletetoken', deleteToken);
|
||||||
|
|
||||||
Uploader.setFailure(function () {
|
Uploader.setFailure(function () {
|
||||||
Controller.showError(I18n._('Could not delete the paste, it was not stored in burn after reading mode.'));
|
Alert.showError(I18n._('Could not delete the paste, it was not stored in burn after reading mode.'));
|
||||||
})
|
})
|
||||||
Uploader.run();
|
Uploader.run();
|
||||||
}
|
}
|
||||||
|
|
785
js/test.js
785
js/test.js
|
@ -22,11 +22,17 @@ global.sjcl = require('./sjcl-1.0.6');
|
||||||
global.Base64 = require('./base64-2.1.9').Base64;
|
global.Base64 = require('./base64-2.1.9').Base64;
|
||||||
global.RawDeflate = require('./rawdeflate-0.5').RawDeflate;
|
global.RawDeflate = require('./rawdeflate-0.5').RawDeflate;
|
||||||
global.RawDeflate.inflate = require('./rawinflate-0.3').RawDeflate.inflate;
|
global.RawDeflate.inflate = require('./rawinflate-0.3').RawDeflate.inflate;
|
||||||
|
require('./prettify');
|
||||||
|
global.prettyPrint = window.PR.prettyPrint;
|
||||||
|
global.prettyPrintOne = window.PR.prettyPrintOne;
|
||||||
|
global.showdown = require('./showdown-1.6.1');
|
||||||
|
global.DOMPurify = require('./purify.min');
|
||||||
|
require('./bootstrap-3.3.7');
|
||||||
require('./privatebin');
|
require('./privatebin');
|
||||||
|
|
||||||
// redirect console messages to log file
|
// redirect console messages to log file
|
||||||
console.warn = console.error = function (msg) {
|
console.info = console.warn = console.error = function () {
|
||||||
logFile.write(msg + '\n');
|
logFile.write(Array.prototype.slice.call(arguments).join('') + '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Helper', function () {
|
describe('Helper', function () {
|
||||||
|
@ -182,7 +188,7 @@ describe('Helper', function () {
|
||||||
jsc.array(jsc.elements(queryString)),
|
jsc.array(jsc.elements(queryString)),
|
||||||
'string',
|
'string',
|
||||||
function (prefix, query, postfix) {
|
function (prefix, query, postfix) {
|
||||||
var url = 'magnet:?' + query.join(''),
|
var url = 'magnet:?' + query.join('').replace(/^&+|&+$/gm,''),
|
||||||
prefix = $.PrivateBin.Helper.htmlEntities(prefix),
|
prefix = $.PrivateBin.Helper.htmlEntities(prefix),
|
||||||
postfix = $.PrivateBin.Helper.htmlEntities(postfix),
|
postfix = $.PrivateBin.Helper.htmlEntities(postfix),
|
||||||
element = $('<div>' + prefix + url + ' ' + postfix + '</div>');
|
element = $('<div>' + prefix + url + ' ' + postfix + '</div>');
|
||||||
|
@ -599,6 +605,82 @@ describe('Model', function () {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getFormatDefault', function () {
|
||||||
|
before(function () {
|
||||||
|
$.PrivateBin.Model.reset();
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'returns the contents of the element with id "pasteFormatter"',
|
||||||
|
'array asciinestring',
|
||||||
|
'string',
|
||||||
|
'small nat',
|
||||||
|
function (keys, value, key) {
|
||||||
|
keys = keys.map($.PrivateBin.Helper.htmlEntities);
|
||||||
|
value = $.PrivateBin.Helper.htmlEntities(value);
|
||||||
|
var content = keys.length > key ? keys[key] : (keys.length > 0 ? keys[0] : 'null'),
|
||||||
|
contents = '<select id="pasteFormatter" name="pasteFormatter">';
|
||||||
|
keys.forEach(function(item) {
|
||||||
|
contents += '<option value="' + item + '"';
|
||||||
|
if (item === content) {
|
||||||
|
contents += ' selected="selected"';
|
||||||
|
}
|
||||||
|
contents += '>' + value + '</option>';
|
||||||
|
});
|
||||||
|
contents += '</select>';
|
||||||
|
$('body').html(contents);
|
||||||
|
var result = $.PrivateBin.Helper.htmlEntities(
|
||||||
|
$.PrivateBin.Model.getFormatDefault()
|
||||||
|
);
|
||||||
|
$.PrivateBin.Model.reset();
|
||||||
|
return content === result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('hasCipherData', function () {
|
||||||
|
before(function () {
|
||||||
|
$.PrivateBin.Model.reset();
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'checks if the element with id "cipherdata" contains any data',
|
||||||
|
'asciistring',
|
||||||
|
function (value) {
|
||||||
|
value = $.PrivateBin.Helper.htmlEntities(value).trim();
|
||||||
|
$('body').html('<div id="cipherdata">' + value + '</div>');
|
||||||
|
$.PrivateBin.Model.init();
|
||||||
|
var result = $.PrivateBin.Model.hasCipherData();
|
||||||
|
$.PrivateBin.Model.reset();
|
||||||
|
return (value.length > 0) === result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getCipherData', function () {
|
||||||
|
before(function () {
|
||||||
|
$.PrivateBin.Model.reset();
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'returns the contents of the element with id "cipherdata"',
|
||||||
|
'asciistring',
|
||||||
|
function (value) {
|
||||||
|
value = $.PrivateBin.Helper.htmlEntities(value).trim();
|
||||||
|
$('body').html('<div id="cipherdata">' + value + '</div>');
|
||||||
|
$.PrivateBin.Model.init();
|
||||||
|
var result = $.PrivateBin.Helper.htmlEntities(
|
||||||
|
$.PrivateBin.Model.getCipherData()
|
||||||
|
);
|
||||||
|
$.PrivateBin.Model.reset();
|
||||||
|
return value === result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
describe('getPasteId', function () {
|
describe('getPasteId', function () {
|
||||||
this.timeout(30000);
|
this.timeout(30000);
|
||||||
before(function () {
|
before(function () {
|
||||||
|
@ -710,4 +792,701 @@ describe('Model', function () {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getTemplate', function () {
|
||||||
|
before(function () {
|
||||||
|
$.PrivateBin.Model.reset();
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'returns the contents of the element with id "[name]template"',
|
||||||
|
jsc.nearray(jsc.elements(alnumString)),
|
||||||
|
jsc.nearray(jsc.elements(a2zString)),
|
||||||
|
jsc.nearray(jsc.elements(alnumString)),
|
||||||
|
function (id, element, value) {
|
||||||
|
id = id.join('');
|
||||||
|
element = element.join('');
|
||||||
|
value = value.join('').trim();
|
||||||
|
|
||||||
|
// <br>, <hr>, <img> and <wbr> tags can't contain strings,
|
||||||
|
// table tags can't be alone, so test with a <p> instead
|
||||||
|
if (['br', 'col', 'hr', 'img', 'tr', 'td', 'th', 'wbr'].indexOf(element) >= 0) {
|
||||||
|
element = 'p';
|
||||||
|
}
|
||||||
|
|
||||||
|
$('body').html(
|
||||||
|
'<div id="templates"><' + element + ' id="' + id +
|
||||||
|
'template">' + value + '</' + element + '></div>'
|
||||||
|
);
|
||||||
|
$.PrivateBin.Model.init();
|
||||||
|
var template = '<' + element + ' id="' + id + '">' + value +
|
||||||
|
'</' + element + '>',
|
||||||
|
result = $.PrivateBin.Model.getTemplate(id).wrap('<p/>').parent().html();
|
||||||
|
$.PrivateBin.Model.reset();
|
||||||
|
return template === result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('UiHelper', function () {
|
||||||
|
// TODO: As per https://github.com/tmpvar/jsdom/issues/1565 there is no navigation support in jsdom, yet.
|
||||||
|
// for now we use a mock function to trigger the event
|
||||||
|
describe('historyChange', function () {
|
||||||
|
this.timeout(30000);
|
||||||
|
before(function () {
|
||||||
|
$.PrivateBin.Helper.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'redirects to home, when the state is null',
|
||||||
|
jsc.elements(schemas),
|
||||||
|
jsc.nearray(jsc.elements(a2zString)),
|
||||||
|
function (schema, address) {
|
||||||
|
var expected = schema + '://' + address.join('') + '/',
|
||||||
|
clean = jsdom('', {url: expected});
|
||||||
|
|
||||||
|
// make window.location.href writable
|
||||||
|
Object.defineProperty(window.location, 'href', {
|
||||||
|
writable: true,
|
||||||
|
value: window.location.href
|
||||||
|
});
|
||||||
|
$.PrivateBin.UiHelper.mockHistoryChange();
|
||||||
|
$.PrivateBin.Helper.reset();
|
||||||
|
var result = window.location.href;
|
||||||
|
clean();
|
||||||
|
return expected === result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'does not redirect to home, when a new paste is created',
|
||||||
|
jsc.elements(schemas),
|
||||||
|
jsc.nearray(jsc.elements(a2zString)),
|
||||||
|
jsc.array(jsc.elements(queryString)),
|
||||||
|
jsc.nearray(jsc.elements(base64String)),
|
||||||
|
function (schema, address, query, fragment) {
|
||||||
|
var expected = schema + '://' + address.join('') + '/' + '?' +
|
||||||
|
query.join('') + '#' + fragment.join(''),
|
||||||
|
clean = jsdom('', {url: expected});
|
||||||
|
|
||||||
|
// make window.location.href writable
|
||||||
|
Object.defineProperty(window.location, 'href', {
|
||||||
|
writable: true,
|
||||||
|
value: window.location.href
|
||||||
|
});
|
||||||
|
$.PrivateBin.UiHelper.mockHistoryChange([
|
||||||
|
{type: 'newpaste'}, '', expected
|
||||||
|
]);
|
||||||
|
$.PrivateBin.Helper.reset();
|
||||||
|
var result = window.location.href;
|
||||||
|
clean();
|
||||||
|
return expected === result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('reloadHome', function () {
|
||||||
|
this.timeout(30000);
|
||||||
|
before(function () {
|
||||||
|
$.PrivateBin.Helper.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'redirects to home',
|
||||||
|
jsc.elements(schemas),
|
||||||
|
jsc.nearray(jsc.elements(a2zString)),
|
||||||
|
jsc.array(jsc.elements(queryString)),
|
||||||
|
jsc.nearray(jsc.elements(base64String)),
|
||||||
|
function (schema, address, query, fragment) {
|
||||||
|
var expected = schema + '://' + address.join('') + '/',
|
||||||
|
clean = jsdom('', {
|
||||||
|
url: expected + '?' + query.join('') + '#' + fragment.join('')
|
||||||
|
});
|
||||||
|
|
||||||
|
// make window.location.href writable
|
||||||
|
Object.defineProperty(window.location, 'href', {
|
||||||
|
writable: true,
|
||||||
|
value: window.location.href
|
||||||
|
});
|
||||||
|
$.PrivateBin.UiHelper.reloadHome();
|
||||||
|
$.PrivateBin.Helper.reset();
|
||||||
|
var result = window.location.href;
|
||||||
|
clean();
|
||||||
|
return expected === result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isVisible', function () {
|
||||||
|
// TODO As per https://github.com/tmpvar/jsdom/issues/1048 there is no layout support in jsdom, yet.
|
||||||
|
// once it is supported or a workaround is found, uncomment the section below
|
||||||
|
/*
|
||||||
|
before(function () {
|
||||||
|
$.PrivateBin.Helper.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'detect visible elements',
|
||||||
|
jsc.nearray(jsc.elements(alnumString)),
|
||||||
|
jsc.nearray(jsc.elements(a2zString)),
|
||||||
|
function (id, element) {
|
||||||
|
id = id.join('');
|
||||||
|
element = element.join('');
|
||||||
|
var clean = jsdom(
|
||||||
|
'<' + element + ' id="' + id + '"></' + element + '>'
|
||||||
|
);
|
||||||
|
var result = $.PrivateBin.UiHelper.isVisible($('#' + id));
|
||||||
|
clean();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('scrollTo', function () {
|
||||||
|
// TODO Did not find a way to test that, see isVisible test above
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Alert', function () {
|
||||||
|
describe('showStatus', function () {
|
||||||
|
before(function () {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'shows a status message',
|
||||||
|
jsc.array(jsc.elements(alnumString)),
|
||||||
|
jsc.array(jsc.elements(alnumString)),
|
||||||
|
function (icon, message) {
|
||||||
|
icon = icon.join('');
|
||||||
|
message = message.join('');
|
||||||
|
var expected = '<div id="status" role="alert" ' +
|
||||||
|
'class="statusmessage alert alert-info"><span ' +
|
||||||
|
'class="glyphicon glyphicon-' + icon +
|
||||||
|
'" aria-hidden="true"></span> ' + message + '</div>';
|
||||||
|
$('body').html(
|
||||||
|
'<div id="status" role="alert" class="statusmessage ' +
|
||||||
|
'alert alert-info hidden"><span class="glyphicon ' +
|
||||||
|
'glyphicon-info-sign" aria-hidden="true"></span> </div>'
|
||||||
|
);
|
||||||
|
$.PrivateBin.Alert.init();
|
||||||
|
$.PrivateBin.Alert.showStatus(message, icon);
|
||||||
|
var result = $('body').html();
|
||||||
|
return expected === result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('showError', function () {
|
||||||
|
before(function () {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'shows an error message',
|
||||||
|
jsc.array(jsc.elements(alnumString)),
|
||||||
|
jsc.array(jsc.elements(alnumString)),
|
||||||
|
function (icon, message) {
|
||||||
|
icon = icon.join('');
|
||||||
|
message = message.join('');
|
||||||
|
var expected = '<div id="errormessage" role="alert" ' +
|
||||||
|
'class="statusmessage alert alert-danger"><span ' +
|
||||||
|
'class="glyphicon glyphicon-' + icon +
|
||||||
|
'" aria-hidden="true"></span> ' + message + '</div>';
|
||||||
|
$('body').html(
|
||||||
|
'<div id="errormessage" role="alert" class="statusmessage ' +
|
||||||
|
'alert alert-danger hidden"><span class="glyphicon ' +
|
||||||
|
'glyphicon-alert" aria-hidden="true"></span> </div>'
|
||||||
|
);
|
||||||
|
$.PrivateBin.Alert.init();
|
||||||
|
$.PrivateBin.Alert.showError(message, icon);
|
||||||
|
var result = $('body').html();
|
||||||
|
return expected === result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('showRemaining', function () {
|
||||||
|
before(function () {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'shows remaining time',
|
||||||
|
jsc.array(jsc.elements(alnumString)),
|
||||||
|
jsc.array(jsc.elements(alnumString)),
|
||||||
|
'integer',
|
||||||
|
function (message, string, number) {
|
||||||
|
message = message.join('');
|
||||||
|
string = string.join('');
|
||||||
|
var expected = '<div id="remainingtime" role="alert" ' +
|
||||||
|
'class="alert alert-info"><span ' +
|
||||||
|
'class="glyphicon glyphicon-fire" aria-hidden="true">' +
|
||||||
|
'</span> ' + string + message + number + '</div>';
|
||||||
|
$('body').html(
|
||||||
|
'<div id="remainingtime" role="alert" class="hidden ' +
|
||||||
|
'alert alert-info"><span class="glyphicon ' +
|
||||||
|
'glyphicon-fire" aria-hidden="true"></span> </div>'
|
||||||
|
);
|
||||||
|
$.PrivateBin.Alert.init();
|
||||||
|
$.PrivateBin.Alert.showRemaining(['%s' + message + '%d', string, number]);
|
||||||
|
var result = $('body').html();
|
||||||
|
return expected === result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('showLoading', function () {
|
||||||
|
before(function () {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'shows a loading message',
|
||||||
|
jsc.array(jsc.elements(alnumString)),
|
||||||
|
jsc.array(jsc.elements(alnumString)),
|
||||||
|
'integer',
|
||||||
|
function (icon, message, number) {
|
||||||
|
icon = icon.join('');
|
||||||
|
message = message.join('');
|
||||||
|
var default_message = 'Loading…';
|
||||||
|
if (message.length == 0) {
|
||||||
|
message = default_message;
|
||||||
|
}
|
||||||
|
var expected = '<ul class="nav navbar-nav"><li ' +
|
||||||
|
'id="loadingindicator" class="navbar-text"><span ' +
|
||||||
|
'class="glyphicon glyphicon-' + icon +
|
||||||
|
'" aria-hidden="true"></span> ' + message + '</li></ul>';
|
||||||
|
$('body').html(
|
||||||
|
'<ul class="nav navbar-nav"><li id="loadingindicator" ' +
|
||||||
|
'class="navbar-text hidden"><span class="glyphicon ' +
|
||||||
|
'glyphicon-time" aria-hidden="true"></span> ' +
|
||||||
|
default_message + '</li></ul>'
|
||||||
|
);
|
||||||
|
$.PrivateBin.Alert.init();
|
||||||
|
$.PrivateBin.Alert.showLoading(message, number, icon);
|
||||||
|
var result = $('body').html();
|
||||||
|
return expected === result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('hideLoading', function () {
|
||||||
|
before(function () {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(
|
||||||
|
'hides the loading message',
|
||||||
|
function() {
|
||||||
|
$('body').html(
|
||||||
|
'<ul class="nav navbar-nav"><li id="loadingindicator" ' +
|
||||||
|
'class="navbar-text"><span class="glyphicon ' +
|
||||||
|
'glyphicon-time" aria-hidden="true"></span> ' +
|
||||||
|
'Loading…</li></ul>'
|
||||||
|
);
|
||||||
|
$('body').addClass('loading');
|
||||||
|
$.PrivateBin.Alert.init();
|
||||||
|
$.PrivateBin.Alert.hideLoading();
|
||||||
|
return !$('body').hasClass('loading') &&
|
||||||
|
$('#loadingindicator').hasClass('hidden');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('hideMessages', function () {
|
||||||
|
before(function () {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(
|
||||||
|
'hides all messages',
|
||||||
|
function() {
|
||||||
|
$('body').html(
|
||||||
|
'<div id="status" role="alert" class="statusmessage ' +
|
||||||
|
'alert alert-info"><span class="glyphicon ' +
|
||||||
|
'glyphicon-info-sign" aria-hidden="true"></span> </div>' +
|
||||||
|
'<div id="errormessage" role="alert" class="statusmessage ' +
|
||||||
|
'alert alert-danger"><span class="glyphicon ' +
|
||||||
|
'glyphicon-alert" aria-hidden="true"></span> </div>'
|
||||||
|
);
|
||||||
|
$.PrivateBin.Alert.init();
|
||||||
|
$.PrivateBin.Alert.hideMessages();
|
||||||
|
return $('#statusmessage').hasClass('hidden') &&
|
||||||
|
$('#errormessage').hasClass('hidden');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setCustomHandler', function () {
|
||||||
|
before(function () {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'calls a given handler function',
|
||||||
|
'nat 3',
|
||||||
|
jsc.array(jsc.elements(alnumString)),
|
||||||
|
function (trigger, message) {
|
||||||
|
message = message.join('');
|
||||||
|
var handlerCalled = false,
|
||||||
|
default_message = 'Loading…',
|
||||||
|
functions = [
|
||||||
|
$.PrivateBin.Alert.showStatus,
|
||||||
|
$.PrivateBin.Alert.showError,
|
||||||
|
$.PrivateBin.Alert.showRemaining,
|
||||||
|
$.PrivateBin.Alert.showLoading
|
||||||
|
];
|
||||||
|
if (message.length == 0) {
|
||||||
|
message = default_message;
|
||||||
|
}
|
||||||
|
$('body').html(
|
||||||
|
'<ul class="nav navbar-nav"><li id="loadingindicator" ' +
|
||||||
|
'class="navbar-text hidden"><span class="glyphicon ' +
|
||||||
|
'glyphicon-time" aria-hidden="true"></span> ' +
|
||||||
|
default_message + '</li></ul>' +
|
||||||
|
'<div id="remainingtime" role="alert" class="hidden ' +
|
||||||
|
'alert alert-info"><span class="glyphicon ' +
|
||||||
|
'glyphicon-fire" aria-hidden="true"></span> </div>' +
|
||||||
|
'<div id="status" role="alert" class="statusmessage ' +
|
||||||
|
'alert alert-info"><span class="glyphicon ' +
|
||||||
|
'glyphicon-info-sign" aria-hidden="true"></span> </div>' +
|
||||||
|
'<div id="errormessage" role="alert" class="statusmessage ' +
|
||||||
|
'alert alert-danger"><span class="glyphicon ' +
|
||||||
|
'glyphicon-alert" aria-hidden="true"></span> </div>'
|
||||||
|
);
|
||||||
|
$.PrivateBin.Alert.init();
|
||||||
|
$.PrivateBin.Alert.setCustomHandler(function(id, $element) {
|
||||||
|
handlerCalled = true;
|
||||||
|
return jsc.random(0, 1) ? true : $element;
|
||||||
|
});
|
||||||
|
functions[trigger](message);
|
||||||
|
return handlerCalled;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('PasteStatus', function () {
|
||||||
|
describe('createPasteNotification', function () {
|
||||||
|
this.timeout(30000);
|
||||||
|
before(function () {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'creates a notification after a successfull paste upload',
|
||||||
|
jsc.elements(schemas),
|
||||||
|
jsc.nearray(jsc.elements(a2zString)),
|
||||||
|
jsc.array(jsc.elements(queryString)),
|
||||||
|
'string',
|
||||||
|
jsc.elements(schemas),
|
||||||
|
jsc.nearray(jsc.elements(a2zString)),
|
||||||
|
jsc.array(jsc.elements(queryString)),
|
||||||
|
function (
|
||||||
|
schema1, address1, query1, fragment1,
|
||||||
|
schema2, address2, query2
|
||||||
|
) {
|
||||||
|
var expected1 = schema1 + '://' + address1.join('') + '/?' +
|
||||||
|
encodeURI(query1.join('').replace(/^&+|&+$/gm,'') + '#' + fragment1),
|
||||||
|
expected2 = schema2 + '://' + address2.join('') + '/?' +
|
||||||
|
encodeURI(query2.join('')),
|
||||||
|
clean = jsdom();
|
||||||
|
$('body').html('<div><div id="deletelink"></div><div id="pastelink"></div></div>');
|
||||||
|
$.PrivateBin.PasteStatus.init();
|
||||||
|
$.PrivateBin.PasteStatus.createPasteNotification(expected1, expected2);
|
||||||
|
var result1 = $('#pasteurl')[0].href,
|
||||||
|
result2 = $('#deletelink a')[0].href;
|
||||||
|
clean();
|
||||||
|
return result1 == expected1 && result2 == expected2;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('showRemainingTime', function () {
|
||||||
|
this.timeout(30000);
|
||||||
|
before(function () {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'shows burn after reading message or remaining time',
|
||||||
|
'bool',
|
||||||
|
'nat',
|
||||||
|
jsc.nearray(jsc.elements(a2zString)),
|
||||||
|
jsc.nearray(jsc.elements(a2zString)),
|
||||||
|
jsc.array(jsc.elements(queryString)),
|
||||||
|
'string',
|
||||||
|
function (
|
||||||
|
burnafterreading, remaining_time,
|
||||||
|
schema, address, query, fragment
|
||||||
|
) {
|
||||||
|
var clean = jsdom('', {
|
||||||
|
url: schema.join('') + '://' + address.join('') +
|
||||||
|
'/?' + queryString + '#' + fragment
|
||||||
|
});
|
||||||
|
$('body').html('<div id="remainingtime" class="hidden"></div>');
|
||||||
|
$.PrivateBin.PasteStatus.init();
|
||||||
|
$.PrivateBin.PasteStatus.showRemainingTime({
|
||||||
|
'burnafterreading': burnafterreading,
|
||||||
|
'remaining_time': remaining_time,
|
||||||
|
'expire_date': remaining_time ? ((new Date()).getTime() / 1000) + remaining_time : 0
|
||||||
|
});
|
||||||
|
if (burnafterreading) {
|
||||||
|
var result = $('#remainingtime').hasClass('foryoureyesonly') &&
|
||||||
|
!$('#remainingtime').hasClass('hidden');
|
||||||
|
} else if (remaining_time) {
|
||||||
|
var result =!$('#remainingtime').hasClass('foryoureyesonly') &&
|
||||||
|
!$('#remainingtime').hasClass('hidden');
|
||||||
|
} else {
|
||||||
|
var result = $('#remainingtime').hasClass('hidden') &&
|
||||||
|
!$('#remainingtime').hasClass('foryoureyesonly');
|
||||||
|
}
|
||||||
|
clean();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('hideMessages', function () {
|
||||||
|
before(function () {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(
|
||||||
|
'hides all messages',
|
||||||
|
function() {
|
||||||
|
$('body').html(
|
||||||
|
'<div id="remainingtime"></div><div id="pastesuccess"></div>'
|
||||||
|
);
|
||||||
|
$.PrivateBin.PasteStatus.init();
|
||||||
|
$.PrivateBin.PasteStatus.hideMessages();
|
||||||
|
return $('#remainingtime').hasClass('hidden') &&
|
||||||
|
$('#pastesuccess').hasClass('hidden');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Prompt', function () {
|
||||||
|
// TODO: this does not test the prompt() fallback, since that isn't available
|
||||||
|
// in nodejs -> replace the prompt in the "page" template with a modal
|
||||||
|
describe('requestPassword & getPassword', function () {
|
||||||
|
this.timeout(30000);
|
||||||
|
before(function () {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'returns the password fed into the dialog',
|
||||||
|
'string',
|
||||||
|
function (password) {
|
||||||
|
password = password.replace(/\r+/g, '');
|
||||||
|
var clean = jsdom('', {url: 'ftp://example.com/#0'});
|
||||||
|
$('body').html(
|
||||||
|
'<div id="passwordmodal" class="modal fade" role="dialog">' +
|
||||||
|
'<div class="modal-dialog"><div class="modal-content">' +
|
||||||
|
'<div class="modal-body"><form id="passwordform" role="form">' +
|
||||||
|
'<div class="form-group"><input id="passworddecrypt" ' +
|
||||||
|
'type="password" class="form-control" placeholder="Enter ' +
|
||||||
|
'password"></div><button type="submit">Decrypt</button>' +
|
||||||
|
'</form></div></div></div></div><div id="cipherdata">{}</div>'
|
||||||
|
);
|
||||||
|
$.PrivateBin.Model.init();
|
||||||
|
$.PrivateBin.Prompt.init();
|
||||||
|
$.PrivateBin.Prompt.requestPassword();
|
||||||
|
$('#passworddecrypt').val(password);
|
||||||
|
$('#passwordform').submit();
|
||||||
|
var result = $.PrivateBin.Prompt.getPassword();
|
||||||
|
clean();
|
||||||
|
return result == password;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Editor', function () {
|
||||||
|
describe('show, hide, getText, setText & isPreview', function () {
|
||||||
|
this.timeout(30000);
|
||||||
|
before(function () {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'returns text fed into the textarea, handles editor tabs',
|
||||||
|
'string',
|
||||||
|
function (text) {
|
||||||
|
var clean = jsdom(),
|
||||||
|
results = [];
|
||||||
|
$('body').html(
|
||||||
|
'<ul id="editorTabs" class="nav nav-tabs hidden"><li ' +
|
||||||
|
'role="presentation" class="active"><a id="messageedit" ' +
|
||||||
|
'href="#">Editor</a></li><li role="presentation"><a ' +
|
||||||
|
'id="messagepreview" href="#">Preview</a></li></ul><div ' +
|
||||||
|
'id="placeholder" class="hidden">+++ no paste text +++</div>' +
|
||||||
|
'<div id="prettymessage" class="hidden"><pre id="prettyprint" ' +
|
||||||
|
'class="prettyprint linenums:1"></pre></div><div ' +
|
||||||
|
'id="plaintext" class="hidden"></div><p><textarea ' +
|
||||||
|
'id="message" name="message" cols="80" rows="25" ' +
|
||||||
|
'class="form-control hidden"></textarea></p>'
|
||||||
|
);
|
||||||
|
$.PrivateBin.Editor.init();
|
||||||
|
results.push(
|
||||||
|
$('#editorTabs').hasClass('hidden') &&
|
||||||
|
$('#message').hasClass('hidden')
|
||||||
|
);
|
||||||
|
$.PrivateBin.Editor.show();
|
||||||
|
results.push(
|
||||||
|
!$('#editorTabs').hasClass('hidden') &&
|
||||||
|
!$('#message').hasClass('hidden')
|
||||||
|
);
|
||||||
|
$.PrivateBin.Editor.hide();
|
||||||
|
results.push(
|
||||||
|
$('#editorTabs').hasClass('hidden') &&
|
||||||
|
$('#message').hasClass('hidden')
|
||||||
|
);
|
||||||
|
$.PrivateBin.Editor.show();
|
||||||
|
$.PrivateBin.Editor.focusInput();
|
||||||
|
results.push(
|
||||||
|
$.PrivateBin.Editor.getText().length == 0
|
||||||
|
);
|
||||||
|
$.PrivateBin.Editor.setText(text);
|
||||||
|
results.push(
|
||||||
|
$.PrivateBin.Editor.getText() == $('#message').val()
|
||||||
|
);
|
||||||
|
$.PrivateBin.Editor.setText();
|
||||||
|
results.push(
|
||||||
|
!$.PrivateBin.Editor.isPreview() &&
|
||||||
|
!$('#message').hasClass('hidden')
|
||||||
|
);
|
||||||
|
$('#messagepreview').click();
|
||||||
|
results.push(
|
||||||
|
$.PrivateBin.Editor.isPreview() &&
|
||||||
|
$('#message').hasClass('hidden')
|
||||||
|
);
|
||||||
|
$('#messageedit').click();
|
||||||
|
results.push(
|
||||||
|
!$.PrivateBin.Editor.isPreview() &&
|
||||||
|
!$('#message').hasClass('hidden')
|
||||||
|
);
|
||||||
|
clean();
|
||||||
|
return results.every(element => element);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('PasteViewer', function () {
|
||||||
|
describe('run, hide, getText, setText, getFormat, setFormat & isPrettyPrinted', function () {
|
||||||
|
this.timeout(30000);
|
||||||
|
before(function () {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'displays text according to format',
|
||||||
|
jsc.elements(['plaintext', 'markdown', 'syntaxhighlighting']),
|
||||||
|
'nestring',
|
||||||
|
function (format, text) {
|
||||||
|
var clean = jsdom(),
|
||||||
|
results = [];
|
||||||
|
$('body').html(
|
||||||
|
'<div id="placeholder" class="hidden">+++ no paste text ' +
|
||||||
|
'+++</div><div id="prettymessage" class="hidden"><pre ' +
|
||||||
|
'id="prettyprint" class="prettyprint linenums:1"></pre>' +
|
||||||
|
'</div><div id="plaintext" class="hidden"></div>'
|
||||||
|
);
|
||||||
|
$.PrivateBin.PasteViewer.init();
|
||||||
|
$.PrivateBin.PasteViewer.setFormat(format);
|
||||||
|
$.PrivateBin.PasteViewer.setText('');
|
||||||
|
results.push(
|
||||||
|
$('#placeholder').hasClass('hidden') &&
|
||||||
|
$('#prettymessage').hasClass('hidden') &&
|
||||||
|
$('#plaintext').hasClass('hidden') &&
|
||||||
|
$.PrivateBin.PasteViewer.getFormat() == format &&
|
||||||
|
$.PrivateBin.PasteViewer.getText() == ''
|
||||||
|
);
|
||||||
|
$.PrivateBin.PasteViewer.run();
|
||||||
|
results.push(
|
||||||
|
!$('#placeholder').hasClass('hidden') &&
|
||||||
|
$('#prettymessage').hasClass('hidden') &&
|
||||||
|
$('#plaintext').hasClass('hidden')
|
||||||
|
);
|
||||||
|
$.PrivateBin.PasteViewer.hide();
|
||||||
|
results.push(
|
||||||
|
$('#placeholder').hasClass('hidden') &&
|
||||||
|
$('#prettymessage').hasClass('hidden') &&
|
||||||
|
$('#plaintext').hasClass('hidden')
|
||||||
|
);
|
||||||
|
$.PrivateBin.PasteViewer.setText(text);
|
||||||
|
$.PrivateBin.PasteViewer.run();
|
||||||
|
results.push(
|
||||||
|
$('#placeholder').hasClass('hidden') &&
|
||||||
|
!$.PrivateBin.PasteViewer.isPrettyPrinted() &&
|
||||||
|
$.PrivateBin.PasteViewer.getText() == text
|
||||||
|
);
|
||||||
|
if (format == 'markdown') {
|
||||||
|
results.push(
|
||||||
|
$('#prettymessage').hasClass('hidden') &&
|
||||||
|
!$('#plaintext').hasClass('hidden')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
results.push(
|
||||||
|
!$('#prettymessage').hasClass('hidden') &&
|
||||||
|
$('#plaintext').hasClass('hidden')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
clean();
|
||||||
|
return results.every(element => element);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
jsc.property(
|
||||||
|
'sanitizes XSS',
|
||||||
|
jsc.elements(['plaintext', 'markdown', 'syntaxhighlighting']),
|
||||||
|
'string',
|
||||||
|
// https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
|
||||||
|
jsc.elements([
|
||||||
|
'<PLAINTEXT>',
|
||||||
|
'\';alert(String.fromCharCode(88,83,83))//\';alert(String.fromCharCode(88,83,83))//";',
|
||||||
|
'alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//--',
|
||||||
|
'></SCRIPT>">\'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>',
|
||||||
|
'\'\';!--"<XSS>=&{()}',
|
||||||
|
'<SCRIPT SRC=http://example.com/xss.js></SCRIPT>',
|
||||||
|
'\'">><marquee><img src=x onerror=confirm(1)></marquee>"></plaintext\\></|\\><plaintext/onmouseover=prompt(1)><script>prompt(1)</script>@gmail.com<isindex formaction=javascript:alert(/XSS/) type=submit>\'-->"></script><script>alert(document.cookie)</script>"><img/id="confirm(1)"/alt="/"src="/"onerror=eval(id)>\'">',
|
||||||
|
'<IMG SRC="javascript:alert(\'XSS\');">',
|
||||||
|
'<IMG SRC=javascript:alert(\'XSS\')>',
|
||||||
|
'<IMG SRC=JaVaScRiPt:alert(\'XSS\')>',
|
||||||
|
'<IMG SRC=javascript:alert("XSS")>',
|
||||||
|
'<IMG SRC=`javascript:alert("RSnake says, \'XSS\'")`>',
|
||||||
|
'<a onmouseover="alert(document.cookie)">xxs link</a>',
|
||||||
|
'<a onmouseover=alert(document.cookie)>xxs link</a>',
|
||||||
|
'<IMG """><SCRIPT>alert("XSS")</SCRIPT>">',
|
||||||
|
'<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>'
|
||||||
|
// the list goes on…
|
||||||
|
]),
|
||||||
|
'string',
|
||||||
|
function (format, prefix, xss, suffix) {
|
||||||
|
var clean = jsdom(),
|
||||||
|
text = prefix + xss + suffix;
|
||||||
|
$('body').html(
|
||||||
|
'<div id="placeholder" class="hidden">+++ no paste text ' +
|
||||||
|
'+++</div><div id="prettymessage" class="hidden"><pre ' +
|
||||||
|
'id="prettyprint" class="prettyprint linenums:1"></pre>' +
|
||||||
|
'</div><div id="plaintext" class="hidden"></div>'
|
||||||
|
);
|
||||||
|
$.PrivateBin.PasteViewer.init();
|
||||||
|
$.PrivateBin.PasteViewer.setFormat(format);
|
||||||
|
$.PrivateBin.PasteViewer.setText(text);
|
||||||
|
$.PrivateBin.PasteViewer.run();
|
||||||
|
var result = $('body').html().indexOf(xss) !== -1;
|
||||||
|
clean();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ class Filter
|
||||||
$i = 0;
|
$i = 0;
|
||||||
while (($size / 1024) >= 1) {
|
while (($size / 1024) >= 1) {
|
||||||
$size = $size / 1024;
|
$size = $size / 1024;
|
||||||
$i++;
|
++$i;
|
||||||
}
|
}
|
||||||
return number_format($size, ($i ? 2 : 0), '.', ' ') . ' ' . I18n::_($iec[$i]);
|
return number_format($size, ($i ? 2 : 0), '.', ' ') . ' ' . I18n::_($iec[$i]);
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ class Filter
|
||||||
public static function slowEquals($a, $b)
|
public static function slowEquals($a, $b)
|
||||||
{
|
{
|
||||||
$diff = strlen($a) ^ strlen($b);
|
$diff = strlen($a) ^ strlen($b);
|
||||||
for ($i = 0; $i < strlen($a) && $i < strlen($b); $i++) {
|
for ($i = 0; $i < strlen($a) && $i < strlen($b); ++$i) {
|
||||||
$diff |= ord($a[$i]) ^ ord($b[$i]);
|
$diff |= ord($a[$i]) ^ ord($b[$i]);
|
||||||
}
|
}
|
||||||
return $diff === 0;
|
return $diff === 0;
|
||||||
|
|
|
@ -70,7 +70,7 @@ if ($MARKDOWN):
|
||||||
<?php
|
<?php
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-CbxrV468ako77cl5jNqoqohA9EphJI54ha7/3Zv0K7lXW/0fC7l1L+SXpTq94FpQP4vSIZFmQnOkrmPxkgNbag==" crossorigin="anonymous"></script>
|
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-zbiQgBDsSGOdieFoYhNqu7fnj+GpeuQRXQcUSg1U9lP3HlHUY6Lp1w/Hl/LK2y/RGjkoV3MRcjU/BQVGoZxKlw==" crossorigin="anonymous"></script>
|
||||||
<!--[if lt IE 10]>
|
<!--[if lt IE 10]>
|
||||||
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
|
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
|
@ -231,6 +231,17 @@ if ($isCpct):
|
||||||
?>
|
?>
|
||||||
</ul>
|
</ul>
|
||||||
<select id="pasteFormatter" name="pasteFormatter" class="hidden">
|
<select id="pasteFormatter" name="pasteFormatter" class="hidden">
|
||||||
|
<?php
|
||||||
|
foreach ($FORMATTER as $key => $value):
|
||||||
|
?>
|
||||||
|
<option value="<?php echo $key; ?>"<?php
|
||||||
|
if ($key == $FORMATTERDEFAULT):
|
||||||
|
?> selected="selected"<?php
|
||||||
|
endif;
|
||||||
|
?>><?php echo $value; ?></option>
|
||||||
|
<?php
|
||||||
|
endforeach;
|
||||||
|
?>
|
||||||
</select>
|
</select>
|
||||||
</li>
|
</li>
|
||||||
<?php
|
<?php
|
||||||
|
@ -424,7 +435,7 @@ endif;
|
||||||
<a href="https://www.opera.com/">Opera</a>,
|
<a href="https://www.opera.com/">Opera</a>,
|
||||||
<a href="https://www.google.com/chrome">Chrome</a>…
|
<a href="https://www.google.com/chrome">Chrome</a>…
|
||||||
</div>
|
</div>
|
||||||
<div id="pasteSuccess" role="alert" class="hidden alert alert-success">
|
<div id="pastesuccess" role="alert" class="hidden alert alert-success">
|
||||||
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
|
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
|
||||||
<div id="deletelink"></div>
|
<div id="deletelink"></div>
|
||||||
<div id="pastelink">
|
<div id="pastelink">
|
||||||
|
|
|
@ -48,7 +48,7 @@ if ($MARKDOWN):
|
||||||
<?php
|
<?php
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-CbxrV468ako77cl5jNqoqohA9EphJI54ha7/3Zv0K7lXW/0fC7l1L+SXpTq94FpQP4vSIZFmQnOkrmPxkgNbag==" crossorigin="anonymous"></script>
|
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-zbiQgBDsSGOdieFoYhNqu7fnj+GpeuQRXQcUSg1U9lP3HlHUY6Lp1w/Hl/LK2y/RGjkoV3MRcjU/BQVGoZxKlw==" crossorigin="anonymous"></script>
|
||||||
<!--[if lt IE 10]>
|
<!--[if lt IE 10]>
|
||||||
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
|
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
|
@ -185,7 +185,7 @@ if (strlen($LANGUAGESELECTION)):
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
</div>
|
</div>
|
||||||
<div id="pasteresult" class="hidden">
|
<div id="pastesuccess" class="hidden">
|
||||||
<div id="deletelink"></div>
|
<div id="deletelink"></div>
|
||||||
<div id="pastelink">
|
<div id="pastelink">
|
||||||
<?php
|
<?php
|
||||||
|
|
Loading…
Reference in a new issue