diff --git a/public/src/client/topic.js b/public/src/client/topic.js index c1c58f2862..1179bdb331 100644 --- a/public/src/client/topic.js +++ b/public/src/client/topic.js @@ -215,10 +215,11 @@ define('forum/topic', [ } function updateTopicTitle() { + var span = components.get('navbar/title').find('span'); if ($(window).scrollTop() > 50) { - components.get('navbar/title').find('span').text(ajaxify.data.title).show(); + span.html(ajaxify.data.titleEscaped).show(); } else { - components.get('navbar/title').find('span').text('').hide(); + span.html('').hide(); } app.removeAlert('bookmark'); } diff --git a/public/src/client/topic/postTools.js b/public/src/client/topic/postTools.js index cf594041b6..33199f7f0b 100644 --- a/public/src/client/topic/postTools.js +++ b/public/src/client/topic/postTools.js @@ -4,17 +4,14 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator'], function(share, navigator, components, translator) { - var PostTools = {}, - topicName; + var PostTools = {}; PostTools.init = function(tid) { - topicName = ajaxify.data.title; - renderMenu(); addPostHandlers(tid); - share.addShareHandlers(topicName); + share.addShareHandlers(ajaxify.data.title); addVoteHandler(); @@ -106,15 +103,15 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator var postContainer = components.get('topic'); postContainer.on('click', '[component="post/quote"]', function() { - onQuoteClicked($(this), tid, topicName); + onQuoteClicked($(this), tid); }); postContainer.on('click', '[component="post/reply"]', function() { - onReplyClicked($(this), tid, topicName); + onReplyClicked($(this), tid); }); $('.topic').on('click', '[component="topic/reply"]', function() { - onReplyClicked($(this), tid, topicName); + onReplyClicked($(this), tid); }); $('.topic').on('click', '[component="topic/reply-as-topic"]', function() { @@ -174,7 +171,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator }); } - function onReplyClicked(button, tid, topicName) { + function onReplyClicked(button, tid) { showStaleWarning(function(proceed) { if (!proceed) { var selectionText = '', @@ -197,7 +194,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator slug: ajaxify.data.slug, index: getData(button, 'data-index'), pid: toPid, - topicName: topicName, + topicName: ajaxify.data.title, username: username, text: selectionText }); @@ -205,7 +202,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator $(window).trigger('action:composer.post.new', { tid: tid, pid: toPid, - topicName: topicName, + topicName: ajaxify.data.title, text: username ? username + ' ' : '' }); } @@ -213,7 +210,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator }); } - function onQuoteClicked(button, tid, topicName) { + function onQuoteClicked(button, tid) { showStaleWarning(function(proceed) { if (!proceed) { var username = getUserName(button), @@ -230,7 +227,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator index: getData(button, 'data-index'), pid: pid, username: username, - topicName: topicName, + topicName: ajaxify.data.title, text: post }); }); @@ -368,7 +365,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator }); topicId.on('keyup change', function() { - moveBtn.attr('disabled', !topicId.val()) + moveBtn.attr('disabled', !topicId.val()); }); moveBtn.on('click', function() { diff --git a/public/src/client/topic/posts.js b/public/src/client/topic/posts.js index 6182b4c554..e05017c767 100644 --- a/public/src/client/topic/posts.js +++ b/public/src/client/topic/posts.js @@ -138,12 +138,6 @@ define('forum/topic/posts', [ before = repliesSelector.first(); } - data.title = $('<div></div>').text(ajaxify.data.title).html(); - data.slug = ajaxify.data.slug; - data.tags = ajaxify.data.tags; - data.viewcount = ajaxify.data.viewcount; - data.isFollowing = ajaxify.data.isFollowing; - $(window).trigger('action:posts.loading', {posts: data.posts, after: after, before: before}); app.parseAndTranslate('topic', 'posts', data, function(html) { diff --git a/src/controllers/topics.js b/src/controllers/topics.js index 018d1e83eb..2690943247 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -1,26 +1,29 @@ "use strict"; -var topicsController = {}, - async = require('async'), - S = require('string'), - nconf = require('nconf'), - - user = require('../user'), - meta = require('../meta'), - topics = require('../topics'), - posts = require('../posts'), - privileges = require('../privileges'), - plugins = require('../plugins'), - helpers = require('./helpers'), - pagination = require('../pagination'), - utils = require('../../public/src/utils'); + +var async = require('async'); +var S = require('string'); +var nconf = require('nconf'); +var validator = require('validator'); + +var user = require('../user'); +var meta = require('../meta'); +var topics = require('../topics'); +var posts = require('../posts'); +var privileges = require('../privileges'); +var plugins = require('../plugins'); +var helpers = require('./helpers'); +var pagination = require('../pagination'); +var utils = require('../../public/src/utils'); + +var topicsController = {}; topicsController.get = function(req, res, callback) { - var tid = req.params.topic_id, - sort = req.query.sort, - currentPage = parseInt(req.query.page, 10) || 1, - pageCount = 1, - userPrivileges; + var tid = req.params.topic_id; + var sort = req.query.sort; + var currentPage = parseInt(req.query.page, 10) || 1; + var pageCount = 1; + var userPrivileges; if ((req.params.post_index && !utils.isNumber(req.params.post_index)) || !utils.isNumber(tid)) { return callback(); @@ -128,7 +131,7 @@ topicsController.get = function(req, res, callback) { url: nconf.get('relative_path') + '/category/' + data.topicData.category.slug }, { - text: data.topicData.title + text: validator.escape(data.topicData.title) } ]; @@ -187,7 +190,7 @@ topicsController.get = function(req, res, callback) { }, { property: 'og:title', - content: topicData.title.replace(/&/g, '&') + content: topicData.title }, { property: 'og:description', diff --git a/src/notifications.js b/src/notifications.js index cb68e347ff..8d984f11c3 100644 --- a/src/notifications.js +++ b/src/notifications.js @@ -44,9 +44,6 @@ var async = require('async'), return next(null, null); } - if (notification.bodyShort) { - notification.bodyShort = S(notification.bodyShort).escapeHTML().s; - } if (notification.bodyLong) { notification.bodyLong = S(notification.bodyLong).escapeHTML().s; } @@ -388,9 +385,9 @@ var async = require('async'), var numUsers = usernames.length; if (numUsers === 2) { - notifications[modifyIndex].bodyShort = '[[' + mergeId + '_dual, ' + usernames.join(', ') + ', ' + notifications[modifyIndex].topicTitle + ']]' + notifications[modifyIndex].bodyShort = '[[' + mergeId + '_dual, ' + usernames.join(', ') + ', ' + notifications[modifyIndex].topicTitle + ']]'; } else if (numUsers > 2) { - notifications[modifyIndex].bodyShort = '[[' + mergeId + '_multiple, ' + usernames[0] + ', ' + (numUsers-1) + ', ' + notifications[modifyIndex].topicTitle + ']]' + notifications[modifyIndex].bodyShort = '[[' + mergeId + '_multiple, ' + usernames[0] + ', ' + (numUsers-1) + ', ' + notifications[modifyIndex].topicTitle + ']]'; } break; } diff --git a/src/topics/data.js b/src/topics/data.js index 458aac2894..92a4a89355 100644 --- a/src/topics/data.js +++ b/src/topics/data.js @@ -58,7 +58,7 @@ module.exports = function(Topics) { if (!topic) { return; } - topic.title = validator.escape(topic.title); + topic.titleEscaped = validator.escape(topic.title); topic.relativeTime = utils.toISOString(topic.timestamp); topic.lastposttimeISO = utils.toISOString(topic.lastposttime); } diff --git a/tests/topics.js b/tests/topics.js index bdc15643ba..ff12d84375 100644 --- a/tests/topics.js +++ b/tests/topics.js @@ -1,11 +1,12 @@ 'use strict'; /*global require, before, beforeEach, after*/ -var assert = require('assert'), - db = require('./mocks/databasemock'), - topics = require('../src/topics'), - categories = require('../src/categories'), - User = require('../src/user'); +var assert = require('assert'); +var validator = require('validator'); +var db = require('./mocks/databasemock'); +var topics = require('../src/topics'); +var categories = require('../src/categories'); +var User = require('../src/user'); describe('Topic\'s', function() { var topic, @@ -144,6 +145,22 @@ describe('Topic\'s', function() { }); }); + describe('Title escaping', function() { + + it('should properly escape topic title', function(done) { + var title = '"<script>alert(\'ok1\');</script> new topic test'; + var titleEscaped = validator.escape(title); + topics.post({uid: topic.userId, title: title, content: topic.content, cid: topic.categoryId}, function(err, result) { + assert.ifError(err); + topics.getTopicData(result.topicData.tid, function(err, topicData) { + assert.ifError(err); + assert.strictEqual(topicData.titleEscaped, titleEscaped); + assert.strictEqual(topicData.title, title); + }); + }); + }); + }); + after(function() { db.flushdb(); });