backporting double encoding fixes from #560

This commit is contained in:
El RIDO
2020-02-16 08:37:33 +01:00
parent 2a5f622580
commit 6ccbad612d
9 changed files with 249 additions and 125 deletions

View File

@@ -3,6 +3,7 @@ var common = require('../common');
describe('I18n', function () {
describe('translate', function () {
this.timeout(30000);
before(function () {
$.PrivateBin.I18n.reset();
});
@@ -32,14 +33,41 @@ describe('I18n', function () {
var fakeAlias = $.PrivateBin.I18n._(fake);
$.PrivateBin.I18n.reset();
messageId = $.PrivateBin.Helper.htmlEntities(messageId);
if (messageId.indexOf('<a') === -1) {
messageId = $.PrivateBin.Helper.htmlEntities(messageId);
} else {
messageId = DOMPurify.sanitize(
messageId, {
ALLOWED_TAGS: ['a', 'i', 'span'],
ALLOWED_ATTR: ['href', 'id']
}
);
}
return messageId === result && messageId === alias &&
messageId === pluralResult && messageId === pluralAlias &&
messageId === fakeResult && messageId === fakeAlias;
}
);
jsc.property(
'replaces %s in strings with first given parameter',
'replaces %s in strings with first given parameter, encoding all, when no link is in the messageID',
'string',
'(small nearray) string',
'string',
function (prefix, params, postfix) {
prefix = prefix.replace(/%(s|d)/g, '%%').replace(/<a/g, '');
params[0] = params[0].replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%').replace(/<a/g, '');
const translation = $.PrivateBin.Helper.htmlEntities(prefix + params[0] + postfix);
params.unshift(prefix + '%s' + postfix);
const result = $.PrivateBin.I18n.translate.apply(this, params);
$.PrivateBin.I18n.reset();
const alias = $.PrivateBin.I18n._.apply(this, params);
$.PrivateBin.I18n.reset();
return translation === result && translation === alias;
}
);
jsc.property(
'replaces %s in strings with first given parameter, encoding params only, when a link is part of the messageID',
'string',
'(small nearray) string',
'string',
@@ -47,15 +75,83 @@ describe('I18n', function () {
prefix = prefix.replace(/%(s|d)/g, '%%');
params[0] = params[0].replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%');
var translation = $.PrivateBin.Helper.htmlEntities(prefix + params[0] + postfix);
params.unshift(prefix + '%s' + postfix);
var result = $.PrivateBin.I18n.translate.apply(this, params);
const translation = DOMPurify.sanitize(
prefix + '<a href="' + params[0] + '"></a>' + postfix, {
ALLOWED_TAGS: ['a', 'i', 'span'],
ALLOWED_ATTR: ['href', 'id']
}
);
params.unshift(prefix + '<a href="%s"></a>' + postfix);
const result = $.PrivateBin.I18n.translate.apply(this, params);
$.PrivateBin.I18n.reset();
var alias = $.PrivateBin.I18n._.apply(this, params);
const alias = $.PrivateBin.I18n._.apply(this, params);
$.PrivateBin.I18n.reset();
return translation === result && translation === alias;
}
);
jsc.property(
'replaces %s in strings with first given parameter into an element, encoding all, when no link is in the messageID',
'string',
'(small nearray) string',
'string',
function (prefix, params, postfix) {
prefix = prefix.replace(/%(s|d)/g, '%%').replace(/<a/g, '');
params[0] = params[0].replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%').replace(/<a/g, '');
const translation = $('<textarea>').text((prefix + params[0] + postfix)).text();
let args = Array.prototype.slice.call(params);
args.unshift(prefix + '%s' + postfix);
let clean = jsdom();
$('body').html('<div id="i18n"></div>');
args.unshift($('#i18n'));
$.PrivateBin.I18n.translate.apply(this, args);
const result = $('#i18n').text();
$.PrivateBin.I18n.reset();
clean();
clean = jsdom();
$('body').html('<div id="i18n"></div>');
args[0] = $('#i18n');
$.PrivateBin.I18n._.apply(this, args);
const alias = $('#i18n').text();
$.PrivateBin.I18n.reset();
clean();
return translation === result && translation === alias;
}
);
jsc.property(
'replaces %s in strings with first given parameter into an element, encoding params only, when a link is part of the messageID inserted',
'string',
'(small nearray) string',
'string',
function (prefix, params, postfix) {
prefix = prefix.replace(/%(s|d)/g, '%%').trim();
params[0] = params[0].replace(/%(s|d)/g, '%%').trim();
postfix = postfix.replace(/%(s|d)/g, '%%').trim();
const translation = DOMPurify.sanitize(
prefix + '<a href="' + params[0] + '"></a>' + postfix, {
ALLOWED_TAGS: ['a', 'i', 'span'],
ALLOWED_ATTR: ['href', 'id']
}
);
let args = Array.prototype.slice.call(params);
args.unshift(prefix + '<a href="%s"></a>' + postfix);
let clean = jsdom();
$('body').html('<div id="i18n"></div>');
args.unshift($('#i18n'));
$.PrivateBin.I18n.translate.apply(this, args);
const result = $('#i18n').html();
$.PrivateBin.I18n.reset();
clean();
clean = jsdom();
$('body').html('<div id="i18n"></div>');
args[0] = $('#i18n');
$.PrivateBin.I18n._.apply(this, args);
const alias = $('#i18n').html();
$.PrivateBin.I18n.reset();
clean();
return translation === result && translation === alias;
}
);
});
describe('getPluralForm', function () {
@@ -88,14 +184,17 @@ describe('I18n', function () {
'downloads and handles any supported language',
common.jscSupportedLanguages(),
function(language) {
var clean = jsdom('', {url: 'https://privatebin.net/', cookie: ['lang=' + language]});
// cleanup
var clean = jsdom('', {cookie: ['lang=en']});
$.PrivateBin.I18n.reset('en');
$.PrivateBin.I18n.loadTranslations();
clean();
// mock
clean = jsdom('', {cookie: ['lang=' + language]});
$.PrivateBin.I18n.reset(language, require('../../i18n/' + language + '.json'));
var result = $.PrivateBin.I18n.translate('en'),
alias = $.PrivateBin.I18n._('en');
clean();
return language === result && language === alias;
}