* Fix #5592
Escape translation tokens in topic titles, descriptions, profile about, and post contents

* Fix tests
v1.18.x
Peter Jaszkowiak 8 years ago committed by psychobunny
parent c3febca9c8
commit 1fb48ef7a7

@ -207,7 +207,7 @@
// if there are arguments to the token // if there are arguments to the token
var backup = ''; var backup = '';
if (args && args.length) { if (args && args.length) {
backup = this.translate('[[' + currentSlice + '[['); backup = this.translate(currentSlice);
} }
// add the translation promise to the array // add the translation promise to the array
toTranslate.push(this.translateKey(name, args, backup)); toTranslate.push(this.translateKey(name, args, backup));
@ -239,7 +239,7 @@
// if we were mid-token, treat it as invalid // if we were mid-token, treat it as invalid
if (inToken) { if (inToken) {
last = this.translate('[[' + last); last = this.translate(last);
} }
// add the remaining text after the last translation string // add the remaining text after the last translation string
@ -414,7 +414,7 @@
* @returns {string} * @returns {string}
*/ */
Translator.escape = function escape(text) { Translator.escape = function escape(text) {
return typeof text === 'string' ? text.replace(/\[\[([\S]*?)\]\]/g, '\\[\\[$1\\]\\]') : text; return typeof text === 'string' ? text.replace(/\[/g, '[').replace(/\]/g, ']') : text;
}; };
/** /**
@ -423,7 +423,7 @@
* @returns {string} * @returns {string}
*/ */
Translator.unescape = function unescape(text) { Translator.unescape = function unescape(text) {
return typeof text === 'string' ? text.replace(/\\\[\\\[([\S]*?)\\\]\\\]/g, '[[$1]]') : text; return typeof text === 'string' ? text.replace(/[|\\\[/g, '[').replace(/]|\\\]/g, ']') : text;
}; };
/** /**

@ -11,7 +11,7 @@ var posts = require('../posts');
var topics = require('../topics'); var topics = require('../topics');
var privileges = require('../privileges'); var privileges = require('../privileges');
var batch = require('../batch'); var batch = require('../batch');
var translator = require('../translator');
module.exports = function (Categories) { module.exports = function (Categories) {
Categories.getRecentReplies = function (cid, uid, count, callback) { Categories.getRecentReplies = function (cid, uid, count, callback) {
@ -136,7 +136,7 @@ module.exports = function (Categories) {
teaser.user.uid = undefined; teaser.user.uid = undefined;
teaser.topic = { teaser.topic = {
slug: topicData[index].slug, slug: topicData[index].slug,
title: validator.escape(String(topicData[index].title)), title: translator.escape(validator.escape(String(topicData[index].title))),
}; };
} }
}); });

@ -12,6 +12,7 @@ var accountHelpers = require('./helpers');
var helpers = require('../helpers'); var helpers = require('../helpers');
var pagination = require('../../pagination'); var pagination = require('../../pagination');
var messaging = require('../../messaging'); var messaging = require('../../messaging');
var translator = require('../../translator');
var profileController = {}; var profileController = {};
@ -74,7 +75,7 @@ profileController.get = function (req, res, callback) {
return p && parseInt(p.deleted, 10) !== 1; return p && parseInt(p.deleted, 10) !== 1;
}); });
userData.hasPrivateChat = results.hasPrivateChat; userData.hasPrivateChat = results.hasPrivateChat;
userData.aboutme = results.aboutme; userData.aboutme = translator.escape(results.aboutme);
userData.nextStart = results.posts.nextStart; userData.nextStart = results.posts.nextStart;
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username }]); userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username }]);
userData.title = userData.username; userData.title = userData.username;

@ -12,6 +12,7 @@ var meta = require('../meta');
var pagination = require('../pagination'); var pagination = require('../pagination');
var helpers = require('./helpers'); var helpers = require('./helpers');
var utils = require('../utils'); var utils = require('../utils');
var translator = require('../translator');
var categoryController = {}; var categoryController = {};
@ -160,6 +161,10 @@ categoryController.get = function (req, res, callback) {
return callback(err); return callback(err);
} }
categoryData.topics.forEach(function (topic) {
topic.title = translator.escape(topic.title);
});
categoryData.description = translator.escape(categoryData.description);
categoryData.privileges = userPrivileges; categoryData.privileges = userPrivileges;
categoryData.showSelect = categoryData.privileges.editable; categoryData.showSelect = categoryData.privileges.editable;
@ -207,7 +212,7 @@ categoryController.get = function (req, res, callback) {
categoryData['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1; categoryData['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1;
categoryData.rssFeedUrl = nconf.get('relative_path') + '/category/' + categoryData.cid + '.rss'; categoryData.rssFeedUrl = nconf.get('relative_path') + '/category/' + categoryData.cid + '.rss';
categoryData.title = categoryData.name; categoryData.title = translator.escape(categoryData.name);
pageCount = Math.max(1, Math.ceil(categoryData.topic_count / settings.topicsPerPage)); pageCount = Math.max(1, Math.ceil(categoryData.topic_count / settings.topicsPerPage));
categoryData.pagination = pagination.create(currentPage, pageCount, req.query); categoryData.pagination = pagination.create(currentPage, pageCount, req.query);
categoryData.pagination.rel.forEach(function (rel) { categoryData.pagination.rel.forEach(function (rel) {

@ -14,6 +14,7 @@ var plugins = require('../plugins');
var helpers = require('./helpers'); var helpers = require('./helpers');
var pagination = require('../pagination'); var pagination = require('../pagination');
var utils = require('../utils'); var utils = require('../utils');
var translator = require('../translator');
var topicsController = {}; var topicsController = {};
@ -129,13 +130,14 @@ topicsController.get = function (req, res, callback) {
plugins.fireHook('filter:controllers.topic.get', { topicData: topicData, uid: req.uid }, next); plugins.fireHook('filter:controllers.topic.get', { topicData: topicData, uid: req.uid }, next);
}, },
function (data, next) { function (data, next) {
data.topicData.title = translator.escape(data.topicData.title);
var breadcrumbs = [ var breadcrumbs = [
{ {
text: data.topicData.category.name, text: data.topicData.category.name,
url: nconf.get('relative_path') + '/category/' + data.topicData.category.slug, url: nconf.get('relative_path') + '/category/' + data.topicData.category.slug,
}, },
{ {
text: data.topicData.title, text: translator.escape(data.topicData.title),
}, },
]; ];

@ -73,6 +73,7 @@ module.exports = function (Posts) {
}; };
function sanitizeSignature(signature) { function sanitizeSignature(signature) {
signature = translator.escape(signature);
var string = S(signature); var string = S(signature);
var tagsToStrip = []; var tagsToStrip = [];

@ -10,7 +10,7 @@ var user = require('../user');
var plugins = require('../plugins'); var plugins = require('../plugins');
var categories = require('../categories'); var categories = require('../categories');
var utils = require('../utils'); var utils = require('../utils');
var translator = require('../translator');
module.exports = function (Posts) { module.exports = function (Posts) {
Posts.getPostSummaryByPids = function (pids, uid, options, callback) { Posts.getPostSummaryByPids = function (pids, uid, options, callback) {
@ -119,7 +119,7 @@ module.exports = function (Posts) {
var cids = topics.map(function (topic) { var cids = topics.map(function (topic) {
if (topic) { if (topic) {
topic.title = validator.escape(String(topic.title)); topic.title = translator.escape(validator.escape(String(topic.title)));
topic.deleted = parseInt(topic.deleted, 10) === 1; topic.deleted = parseInt(topic.deleted, 10) === 1;
} }
return topic && topic.cid; return topic && topic.cid;

@ -10,7 +10,7 @@ var categories = require('../src/categories');
var topics = require('../src/topics'); var topics = require('../src/topics');
var user = require('../src/user'); var user = require('../src/user');
var meta = require('../src/meta'); var meta = require('../src/meta');
var translator = require('../src/translator');
describe('Controllers', function () { describe('Controllers', function () {
var tid; var tid;
@ -1031,9 +1031,9 @@ describe('Controllers', function () {
} }
assert.ok(parsed.cookies); assert.ok(parsed.cookies);
assert.equal('\\\\[\\\\[global:cookies.message\\\\]\\\\]', parsed.cookies.message); assert.equal(translator.escape('[[global:cookies.message]]'), parsed.cookies.message);
assert.equal('\\\\[\\\\[global:cookies.accept\\\\]\\\\]', parsed.cookies.dismiss); assert.equal(translator.escape('[[global:cookies.accept]]'), parsed.cookies.dismiss);
assert.equal('\\\\[\\\\[global:cookies.learn_more\\\\]\\\\]', parsed.cookies.link); assert.equal(translator.escape('[[global:cookies.learn_more]]'), parsed.cookies.link);
done(); done();
}); });

@ -156,14 +156,14 @@ describe('new Translator(language)', function () {
it('should use backup for unknown keys with arguments', function () { it('should use backup for unknown keys with arguments', function () {
var translator = Translator.create('en-GB'); var translator = Translator.create('en-GB');
return translator.translate('[[unknown:key.with.args, arguments are here, derpity, derp]]').then(function (translated) { return translator.translate('[[unknown:key.with.args, arguments are here, derpity, derp]]').then(function (translated) {
assert.strictEqual(translated, '[[unknown:key.with.args, arguments are here, derpity, derp[['); assert.strictEqual(translated, 'unknown:key.with.args, arguments are here, derpity, derp');
}); });
}); });
it('should ignore unclosed tokens', function () { it('should ignore unclosed tokens', function () {
var translator = Translator.create('en-GB'); var translator = Translator.create('en-GB');
return translator.translate('here is some stuff and other things [[abc:xyz, other random stuff should be fine here [[global:home]] and more things [[pages:users/latest]]').then(function (translated) { return translator.translate('here is some stuff and other things [[abc:xyz, other random stuff should be fine here [[global:home]] and more things [[pages:users/latest]]').then(function (translated) {
assert.strictEqual(translated, 'here is some stuff and other things [[abc:xyz, other random stuff should be fine here Home and more things Latest Users'); assert.strictEqual(translated, 'here is some stuff and other things abc:xyz, other random stuff should be fine here Home and more things Latest Users');
}); });
}); });
}); });
@ -248,7 +248,7 @@ describe('Translator static methods', function () {
it('should escape translation patterns within text', function (done) { it('should escape translation patterns within text', function (done) {
assert.strictEqual( assert.strictEqual(
Translator.escape('some nice text [[global:home]] here'), Translator.escape('some nice text [[global:home]] here'),
'some nice text \\[\\[global:home\\]\\] here' 'some nice text [[global:home]] here'
); );
done(); done();
}); });
@ -260,6 +260,10 @@ describe('Translator static methods', function () {
Translator.unescape('some nice text \\[\\[global:home\\]\\] here'), Translator.unescape('some nice text \\[\\[global:home\\]\\] here'),
'some nice text [[global:home]] here' 'some nice text [[global:home]] here'
); );
assert.strictEqual(
Translator.unescape('some nice text [[global:home]] here'),
'some nice text [[global:home]] here'
);
done(); done();
}); });
}); });

Loading…
Cancel
Save