diff --git a/public/src/modules/translator.js b/public/src/modules/translator.js index eea3f7495b..b0d1ad5cb8 100644 --- a/public/src/modules/translator.js +++ b/public/src/modules/translator.js @@ -207,7 +207,7 @@ // if there are arguments to the token var backup = ''; if (args && args.length) { - backup = this.translate('[[' + currentSlice + '[['); + backup = this.translate(currentSlice); } // add the translation promise to the array toTranslate.push(this.translateKey(name, args, backup)); @@ -239,7 +239,7 @@ // if we were mid-token, treat it as invalid if (inToken) { - last = this.translate('[[' + last); + last = this.translate(last); } // add the remaining text after the last translation string @@ -414,7 +414,7 @@ * @returns {string} */ 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} */ 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; }; /** diff --git a/src/categories/recentreplies.js b/src/categories/recentreplies.js index 564d05d673..1908db45e6 100644 --- a/src/categories/recentreplies.js +++ b/src/categories/recentreplies.js @@ -11,7 +11,7 @@ var posts = require('../posts'); var topics = require('../topics'); var privileges = require('../privileges'); var batch = require('../batch'); - +var translator = require('../translator'); module.exports = function (Categories) { Categories.getRecentReplies = function (cid, uid, count, callback) { @@ -136,7 +136,7 @@ module.exports = function (Categories) { teaser.user.uid = undefined; teaser.topic = { slug: topicData[index].slug, - title: validator.escape(String(topicData[index].title)), + title: translator.escape(validator.escape(String(topicData[index].title))), }; } }); diff --git a/src/controllers/accounts/profile.js b/src/controllers/accounts/profile.js index 1fc092a5f4..d22e3256bf 100644 --- a/src/controllers/accounts/profile.js +++ b/src/controllers/accounts/profile.js @@ -12,6 +12,7 @@ var accountHelpers = require('./helpers'); var helpers = require('../helpers'); var pagination = require('../../pagination'); var messaging = require('../../messaging'); +var translator = require('../../translator'); var profileController = {}; @@ -74,7 +75,7 @@ profileController.get = function (req, res, callback) { return p && parseInt(p.deleted, 10) !== 1; }); userData.hasPrivateChat = results.hasPrivateChat; - userData.aboutme = results.aboutme; + userData.aboutme = translator.escape(results.aboutme); userData.nextStart = results.posts.nextStart; userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username }]); userData.title = userData.username; diff --git a/src/controllers/category.js b/src/controllers/category.js index 88b49c0b24..602f158eeb 100644 --- a/src/controllers/category.js +++ b/src/controllers/category.js @@ -12,6 +12,7 @@ var meta = require('../meta'); var pagination = require('../pagination'); var helpers = require('./helpers'); var utils = require('../utils'); +var translator = require('../translator'); var categoryController = {}; @@ -160,6 +161,10 @@ categoryController.get = function (req, res, callback) { return callback(err); } + categoryData.topics.forEach(function (topic) { + topic.title = translator.escape(topic.title); + }); + categoryData.description = translator.escape(categoryData.description); categoryData.privileges = userPrivileges; 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.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)); categoryData.pagination = pagination.create(currentPage, pageCount, req.query); categoryData.pagination.rel.forEach(function (rel) { diff --git a/src/controllers/topics.js b/src/controllers/topics.js index 4fe1bf96d5..8f767ad36c 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -14,6 +14,7 @@ var plugins = require('../plugins'); var helpers = require('./helpers'); var pagination = require('../pagination'); var utils = require('../utils'); +var translator = require('../translator'); var topicsController = {}; @@ -129,13 +130,14 @@ topicsController.get = function (req, res, callback) { plugins.fireHook('filter:controllers.topic.get', { topicData: topicData, uid: req.uid }, next); }, function (data, next) { + data.topicData.title = translator.escape(data.topicData.title); var breadcrumbs = [ { text: data.topicData.category.name, url: nconf.get('relative_path') + '/category/' + data.topicData.category.slug, }, { - text: data.topicData.title, + text: translator.escape(data.topicData.title), }, ]; diff --git a/src/posts/parse.js b/src/posts/parse.js index e5ce10e1ac..3e33226b8d 100644 --- a/src/posts/parse.js +++ b/src/posts/parse.js @@ -73,6 +73,7 @@ module.exports = function (Posts) { }; function sanitizeSignature(signature) { + signature = translator.escape(signature); var string = S(signature); var tagsToStrip = []; diff --git a/src/posts/summary.js b/src/posts/summary.js index a05718b95c..0eaadaca94 100644 --- a/src/posts/summary.js +++ b/src/posts/summary.js @@ -10,7 +10,7 @@ var user = require('../user'); var plugins = require('../plugins'); var categories = require('../categories'); var utils = require('../utils'); - +var translator = require('../translator'); module.exports = function (Posts) { Posts.getPostSummaryByPids = function (pids, uid, options, callback) { @@ -119,7 +119,7 @@ module.exports = function (Posts) { var cids = topics.map(function (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; } return topic && topic.cid; diff --git a/test/controllers.js b/test/controllers.js index e1a3537994..e1568f6802 100644 --- a/test/controllers.js +++ b/test/controllers.js @@ -10,7 +10,7 @@ var categories = require('../src/categories'); var topics = require('../src/topics'); var user = require('../src/user'); var meta = require('../src/meta'); - +var translator = require('../src/translator'); describe('Controllers', function () { var tid; @@ -1031,9 +1031,9 @@ describe('Controllers', function () { } assert.ok(parsed.cookies); - assert.equal('\\\\[\\\\[global:cookies.message\\\\]\\\\]', parsed.cookies.message); - assert.equal('\\\\[\\\\[global:cookies.accept\\\\]\\\\]', parsed.cookies.dismiss); - assert.equal('\\\\[\\\\[global:cookies.learn_more\\\\]\\\\]', parsed.cookies.link); + assert.equal(translator.escape('[[global:cookies.message]]'), parsed.cookies.message); + assert.equal(translator.escape('[[global:cookies.accept]]'), parsed.cookies.dismiss); + assert.equal(translator.escape('[[global:cookies.learn_more]]'), parsed.cookies.link); done(); }); diff --git a/test/translator.js b/test/translator.js index e7f69ccdf0..c6cac36ecc 100644 --- a/test/translator.js +++ b/test/translator.js @@ -156,14 +156,14 @@ describe('new Translator(language)', function () { it('should use backup for unknown keys with arguments', function () { var translator = Translator.create('en-GB'); 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 () { 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) { - 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) { assert.strictEqual( Translator.escape('some nice text [[global:home]] here'), - 'some nice text \\[\\[global:home\\]\\] here' + 'some nice text [[global:home]] here' ); done(); }); @@ -260,6 +260,10 @@ describe('Translator static methods', function () { Translator.unescape('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(); }); });