diff --git a/client/js/libs/handlebars/parse.js b/client/js/libs/handlebars/parse.js index a6d26df8..6303d895 100644 --- a/client/js/libs/handlebars/parse.js +++ b/client/js/libs/handlebars/parse.js @@ -1,8 +1,9 @@ Handlebars.registerHelper( "parse", function(text) { var wrap = wraplong(text); - text = escape(text); + text = Handlebars.Utils.escapeExpression(text); text = colors(text); + text = channels(text); text = uri(text); if (wrap) { return "" + text + ""; @@ -23,17 +24,6 @@ function wraplong(text) { return wrap; } -function escape(text) { - var e = { - "<": "<", - ">": ">", - "'": "'" - }; - return text.replace(/[<>']/g, function (c) { - return e[c]; - }); -} - function uri(text) { return URI.withinString(text, function(url, start, end, source) { if (url.indexOf("javascript:") === 0) { @@ -48,6 +38,19 @@ function uri(text) { }); } +/** + * Channels names are strings of length up to fifty (50) characters. + * The only restriction on a channel name is that it SHALL NOT contain + * any spaces (' '), a control G (^G or ASCII 7), a comma (','). + * Channel prefix '&' is handled as '&' because this parser is executed + * after entities in the message have been escaped. This prevents a couple of bugs. + */ +function channels(text) { + return text.replace( + /(^|\s|\x07|,)((?:#|&)[^\x07\s\,]{1,49})/g, + '$1$2' + ); +} /** * MIRC compliant colour and style parser diff --git a/client/js/lounge.js b/client/js/lounge.js index 413e5b21..b41ef1e1 100644 --- a/client/js/lounge.js +++ b/client/js/lounge.js @@ -234,26 +234,6 @@ $(function() { if (text.find("i").size() === 1) { text = text.find("i"); } - // Channels names are strings (beginning with a '&' or '#' character) - // of length up to 200 characters. - // See https://tools.ietf.org/html/rfc1459#section-1.3 - text.html(text.html().replace(/(^|\s)([#&][^\x07\x2C\s]{0,199})/ig, - '$1$2')); - text.find("span.inline-channel") - .on("click", function() { - var chan = $(".network") - .find(".chan.active") - .parent(".network") - .find(".chan[data-title='" + $(this).data("chan") + "']"); - if (chan.size() === 1) { - chan.click(); - } else { - socket.emit("input", { - target: chat.data("id"), - text: "/join " + $(this).data("chan") - }); - } - }); if ((type === "message" || type === "action") && chan.hasClass("channel")) { var nicks = chan.find(".users").data("nicks"); @@ -529,6 +509,21 @@ $(function() { }); }); + chat.on("click", ".inline-channel", function() { + var chan = $(".network") + .find(".chan.active") + .parent(".network") + .find(".chan[data-title='" + $(this).data("chan") + "']"); + if (chan.size() === 1) { + chan.click(); + } else { + socket.emit("input", { + target: chat.data("id"), + text: "/join " + $(this).data("chan") + }); + } + }); + chat.on("click", ".messages", function() { setTimeout(function() { var text = "";