From 0bcbd105e392c2628f8cf214bdc89f8cff6cd7f0 Mon Sep 17 00:00:00 2001 From: isymchych Date: Fri, 12 Feb 2016 14:48:57 +0200 Subject: [PATCH 1/2] escape nicknames before displaying them --- modules/UI/UI.js | 22 ++++++++++------- modules/UI/side_pannels/SidePanelToggler.js | 5 ++-- modules/UI/side_pannels/chat/Chat.js | 2 +- .../side_pannels/contactlist/ContactList.js | 2 +- .../UI/side_pannels/settings/SettingsMenu.js | 2 +- modules/UI/util/MessageHandler.js | 6 ++--- modules/UI/util/UIUtil.js | 10 ++++++++ modules/UI/videolayout/LocalVideo.js | 12 ++++------ modules/UI/videolayout/RemoteVideo.js | 8 +++---- modules/UI/videolayout/VideoLayout.js | 5 ---- modules/settings/Settings.js | 24 +++++++++++-------- 11 files changed, 54 insertions(+), 44 deletions(-) diff --git a/modules/UI/UI.js b/modules/UI/UI.js index 9515dec656f7..fc58504d02fa 100644 --- a/modules/UI/UI.js +++ b/modules/UI/UI.js @@ -223,12 +223,13 @@ UI.changeDisplayName = function (id, displayName) { * Intitialize conference UI. */ UI.initConference = function () { - var id = APP.conference.localId; + let id = APP.conference.localId; Toolbar.updateRoomUrl(window.location.href); - var meHTML = APP.translation.generateTranslationHTML("me"); - var settings = Settings.getSettings(); + let meHTML = APP.translation.generateTranslationHTML("me"); - $("#localNick").html(settings.email || settings.uid + " (" + meHTML + ")"); + let email = Settings.getEmail(); + let uid = Settings.getUserId(); + $("#localNick").html(email || `${uid} (${meHTML})`); // Add myself to the contact list. ContactList.addContact(id); @@ -236,14 +237,14 @@ UI.initConference = function () { // Once we've joined the muc show the toolbar ToolbarToggler.showToolbar(); - var displayName = config.displayJids ? id : settings.displayName; + let displayName = config.displayJids ? id : Settings.getDisplayName(); if (displayName) { UI.changeDisplayName('localVideoContainer', displayName); } // Make sure we configure our avatar id, before creating avatar for us - UI.setUserAvatar(id, settings.email); + UI.setUserAvatar(id, email); Toolbar.checkAutoEnableDesktopSharing(); if(!interfaceConfig.filmStripOnly) { @@ -607,8 +608,11 @@ UI.toggleContactList = function () { PanelToggler.toggleContactList(); }; -UI.inputDisplayNameHandler = function (value) { - VideoLayout.inputDisplayNameHandler(value); +/** + * Handle new user display name. + */ +UI.inputDisplayNameHandler = function (newDisplayName) { + eventEmitter.emit(UIEvents.NICKNAME_CHANGED, newDisplayName); }; /** @@ -888,7 +892,7 @@ UI.inviteParticipants = function (roomUrl, conferenceName, key, nick) { body = body.replace(/\n/g, "%0D%0A"); if (nick) { - body += "%0D%0A%0D%0A" + nick; + body += "%0D%0A%0D%0A" + UIUtil.escapeHtml(nick); } if (interfaceConfig.INVITATION_POWERED_BY) { diff --git a/modules/UI/side_pannels/SidePanelToggler.js b/modules/UI/side_pannels/SidePanelToggler.js index f3742a2cd534..55836556cd9b 100644 --- a/modules/UI/side_pannels/SidePanelToggler.js +++ b/modules/UI/side_pannels/SidePanelToggler.js @@ -148,9 +148,8 @@ var PanelToggler = { '#settingsmenu', null, function() { - var settings = Settings.getSettings(); - $('#setDisplayName').get(0).value = settings.displayName; - $('#setEmail').get(0).value = settings.email; + $('#setDisplayName').val(Settings.getDisplayName()); + $('#setEmail').val(Settings.getEmail()); }, null); }, diff --git a/modules/UI/side_pannels/chat/Chat.js b/modules/UI/side_pannels/chat/Chat.js index 743daea612e8..3c2fadac7c2e 100644 --- a/modules/UI/side_pannels/chat/Chat.js +++ b/modules/UI/side_pannels/chat/Chat.js @@ -179,7 +179,7 @@ var Chat = { $('#nickinput').keydown(function (event) { if (event.keyCode === 13) { event.preventDefault(); - var val = UIUtil.escapeHtml(this.value); + let val = this.value; this.value = ''; eventEmitter.emit(UIEvents.NICKNAME_CHANGED, val); } diff --git a/modules/UI/side_pannels/contactlist/ContactList.js b/modules/UI/side_pannels/contactlist/ContactList.js index 05236a849836..aa743afa9c40 100644 --- a/modules/UI/side_pannels/contactlist/ContactList.js +++ b/modules/UI/side_pannels/contactlist/ContactList.js @@ -158,7 +158,7 @@ var ContactList = { let contactName = $(`#contacts #${id}>p`); if (displayName) { - contactName.html(displayName); + contactName.text(displayName); } }, diff --git a/modules/UI/side_pannels/settings/SettingsMenu.js b/modules/UI/side_pannels/settings/SettingsMenu.js index 950ee09687dd..d44be09bbb76 100644 --- a/modules/UI/side_pannels/settings/SettingsMenu.js +++ b/modules/UI/side_pannels/settings/SettingsMenu.js @@ -40,7 +40,7 @@ function generateDevicesOptions(items, selectedId) { export default { init (emitter) { function update() { - let displayName = UIUtil.escapeHtml($('#setDisplayName').val()); + let displayName = $('#setDisplayName').val(); if (displayName && Settings.getDisplayName() !== displayName) { emitter.emit(UIEvents.NICKNAME_CHANGED, displayName); diff --git a/modules/UI/util/MessageHandler.js b/modules/UI/util/MessageHandler.js index 80c781472753..0130b10c0f4a 100644 --- a/modules/UI/util/MessageHandler.js +++ b/modules/UI/util/MessageHandler.js @@ -1,6 +1,8 @@ /* global $, APP, jQuery, toastr, Impromptu */ /* jshint -W101 */ +import UIUtil from './UIUtil'; + /** * Flag for enable/disable of the notifications. * @type {boolean} @@ -204,7 +206,7 @@ var messageHandler = (function(my) { return; var displayNameSpan = '" + APP.translation.translateString(displayNameKey); @@ -247,5 +249,3 @@ var messageHandler = (function(my) { }(messageHandler || {})); module.exports = messageHandler; - - diff --git a/modules/UI/util/UIUtil.js b/modules/UI/util/UIUtil.js index 519d66f30dbd..50d9f85fa3ac 100644 --- a/modules/UI/util/UIUtil.js +++ b/modules/UI/util/UIUtil.js @@ -72,6 +72,16 @@ return $('
').text(unsafeText).html(); }, + /** + * Unescapes the given text. + * + * @param {string} safe string which contains escaped html + * @returns {string} unescaped html string. + */ + unescapeHtml: function (safe) { + return $('
').html(safe).text(); + }, + imageToGrayScale: function (canvas) { var context = canvas.getContext('2d'); var imgData = context.getImageData(0, 0, canvas.width, canvas.height); diff --git a/modules/UI/videolayout/LocalVideo.js b/modules/UI/videolayout/LocalVideo.js index e631e6a43c9f..e339be4e2002 100644 --- a/modules/UI/videolayout/LocalVideo.js +++ b/modules/UI/videolayout/LocalVideo.js @@ -65,7 +65,9 @@ LocalVideo.prototype.setDisplayName = function(displayName, key) { if (nameSpan.text() !== displayName) { if (displayName && displayName.length > 0) { meHTML = APP.translation.generateTranslationHTML("me"); - $('#localDisplayName').html(displayName + ' (' + meHTML + ')'); + $('#localDisplayName').html( + UIUtil.escapeHtml(displayName) + ' (' + meHTML + ')' + ); } else { $('#localDisplayName').html(defaultLocalDisplayName); } @@ -81,7 +83,7 @@ LocalVideo.prototype.setDisplayName = function(displayName, key) { if (displayName && displayName.length > 0) { meHTML = APP.translation.generateTranslationHTML("me"); - nameSpan.innerHTML = displayName + meHTML; + nameSpan.innerHTML = UIUtil.escapeHtml(displayName) + meHTML; } else { nameSpan.innerHTML = defaultLocalDisplayName; @@ -126,7 +128,7 @@ LocalVideo.prototype.setDisplayName = function(displayName, key) { editDisplayName.select(); editDisplayName.one("focusout", function (e) { - self.VideoLayout.inputDisplayNameHandler(this.value); + self.emitter.emit(UIEvents.NICKNAME_CHANGED, this.value); $('#editDisplayName').hide(); }); @@ -141,10 +143,6 @@ LocalVideo.prototype.setDisplayName = function(displayName, key) { } }; -LocalVideo.prototype.inputDisplayNameHandler = function (name) { - this.emitter.emit(UIEvents.NICKNAME_CHANGED, UIUtil.escapeHtml(name)); -}; - LocalVideo.prototype.createConnectionIndicator = function() { if(this.connectionIndicator) return; diff --git a/modules/UI/videolayout/RemoteVideo.js b/modules/UI/videolayout/RemoteVideo.js index 92462e8d58e3..7683c671fda0 100644 --- a/modules/UI/videolayout/RemoteVideo.js +++ b/modules/UI/videolayout/RemoteVideo.js @@ -359,7 +359,7 @@ RemoteVideo.prototype.setDisplayName = function(displayName, key) { // If we already have a display name for this video. if (nameSpan.length > 0) { if (displayName && displayName.length > 0) { - $('#' + this.videoSpanId + '_name').html(displayName); + $('#' + this.videoSpanId + '_name').text(displayName); } else if (key && key.length > 0) { var nameHtml = APP.translation.generateTranslationHTML(key); @@ -374,10 +374,10 @@ RemoteVideo.prototype.setDisplayName = function(displayName, key) { $('#' + this.videoSpanId)[0].appendChild(nameSpan); if (displayName && displayName.length > 0) { - nameSpan.innerHTML = displayName; - } - else + $(nameSpan).text(displayName); + } else { nameSpan.innerHTML = interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME; + } nameSpan.id = this.videoSpanId + '_name'; } }; diff --git a/modules/UI/videolayout/VideoLayout.js b/modules/UI/videolayout/VideoLayout.js index 53143fd20e8d..15502b3eecf7 100644 --- a/modules/UI/videolayout/VideoLayout.js +++ b/modules/UI/videolayout/VideoLayout.js @@ -347,11 +347,6 @@ var VideoLayout = { } }, - - inputDisplayNameHandler (name) { - localVideoThumbnail.inputDisplayNameHandler(name); - }, - videoactive (videoelem, resourceJid) { console.info(resourceJid + " video is now active", videoelem); diff --git a/modules/settings/Settings.js b/modules/settings/Settings.js index ced1aeeb0801..7ffe4a667d12 100644 --- a/modules/settings/Settings.js +++ b/modules/settings/Settings.js @@ -1,4 +1,5 @@ import {generateUsername} from '../util/UsernameGenerator'; +import UIUtil from '../UI/util/UIUtil'; let email = ''; let displayName = ''; @@ -32,7 +33,7 @@ if (supportsLocalStorage()) { userId = window.localStorage.jitsiMeetId || ''; email = window.localStorage.email || ''; - displayName = window.localStorage.displayname || ''; + displayName = UIUtil.unescapeHtml(window.localStorage.displayname || ''); language = window.localStorage.language; cameraDeviceId = window.localStorage.cameraDeviceId || ''; micDeviceId = window.localStorage.micDeviceId || ''; @@ -46,26 +47,29 @@ export default { /** * Sets the local user display name and saves it to local storage * - * @param newDisplayName the new display name for the local user - * @returns {string} the display name we just set + * @param {string} newDisplayName unescaped display name for the local user */ - setDisplayName: function (newDisplayName) { - if (displayName === newDisplayName) { - return displayName; - } + setDisplayName (newDisplayName) { displayName = newDisplayName; - window.localStorage.displayname = displayName; - return displayName; + window.localStorage.displayname = UIUtil.escapeHtml(displayName); }, /** - * Returns the currently used by the user + * Returns the escaped display name currently used by the user * @returns {string} currently valid user display name. */ getDisplayName: function () { return displayName; }, + /** + * Returns id of the user. + * @returns {string} user id + */ + getUserId () { + return userId; + }, + setEmail: function (newEmail) { email = newEmail; window.localStorage.email = newEmail; From ebf57923ae891564ed4432c4f45c5dc5478e33c9 Mon Sep 17 00:00:00 2001 From: isymchych Date: Fri, 12 Feb 2016 16:15:34 +0200 Subject: [PATCH 2/2] hide chat if local display name is empty --- conference.js | 8 +++++++- css/chat.css | 15 +++++++++++++++ modules/UI/UI.js | 2 +- modules/UI/side_pannels/chat/Chat.js | 7 +++---- modules/UI/side_pannels/settings/SettingsMenu.js | 4 +--- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/conference.js b/conference.js index 305be4923d4b..192a65a6b592 100644 --- a/conference.js +++ b/conference.js @@ -860,7 +860,13 @@ export default { APP.UI.setUserAvatar(data.attributes.id, data.value); }); - APP.UI.addListener(UIEvents.NICKNAME_CHANGED, (nickname) => { + APP.UI.addListener(UIEvents.NICKNAME_CHANGED, (nickname = '') => { + nickname = nickname.trim(); + + if (nickname === APP.settings.getDisplayName()) { + return; + } + APP.settings.setDisplayName(nickname); room.setDisplayName(nickname); APP.UI.changeDisplayName(APP.conference.localId, nickname); diff --git a/css/chat.css b/css/chat.css index f817691ecf0c..1cf801c0ebdc 100644 --- a/css/chat.css +++ b/css/chat.css @@ -22,6 +22,9 @@ overflow-x: hidden; word-wrap: break-word; } +#chatspace.is-conversation-mode #chatconversation { + visibility: visible; +} .localuser { color: #087dba; @@ -61,6 +64,10 @@ box-shadow: none; } +#chatspace.is-conversation-mode #usermsg { + visibility: visible; +} + #nickname { position: absolute; text-align: center; @@ -72,6 +79,10 @@ width: 95%; } +#chatspace.is-conversation-mode #nickname { + visibility: hidden; +} + #nickinput { margin-top: 20px; font-size: 14px; @@ -168,6 +179,10 @@ visibility: hidden; } +#chatspace.is-conversation-mode #smileysarea { + visibility: visible; +} + #smileysContainer { display: none; position: absolute; diff --git a/modules/UI/UI.js b/modules/UI/UI.js index fc58504d02fa..e1b77e2f2a35 100644 --- a/modules/UI/UI.js +++ b/modules/UI/UI.js @@ -560,7 +560,7 @@ UI.updateUserRole = function (user) { messageHandler.notify( displayName, 'notify.somebody', 'connected', 'notify.grantedTo', { - to: displayName + to: UIUtil.escapeHtml(displayName) } ); } else { diff --git a/modules/UI/side_pannels/chat/Chat.js b/modules/UI/side_pannels/chat/Chat.js index 3c2fadac7c2e..0264350f3883 100644 --- a/modules/UI/side_pannels/chat/Chat.js +++ b/modules/UI/side_pannels/chat/Chat.js @@ -292,13 +292,12 @@ var Chat = { /** * Sets the chat conversation mode. + * @param {boolean} isConversationMode if chat should be in + * conversation mode or not. */ setChatConversationMode (isConversationMode) { + $('#chatspace').toggleClass('is-conversation-mode', isConversationMode); if (isConversationMode) { - $('#nickname').css({visibility: 'hidden'}); - $('#chatconversation').css({visibility: 'visible'}); - $('#usermsg').css({visibility: 'visible'}); - $('#smileysarea').css({visibility: 'visible'}); $('#usermsg').focus(); } }, diff --git a/modules/UI/side_pannels/settings/SettingsMenu.js b/modules/UI/side_pannels/settings/SettingsMenu.js index d44be09bbb76..35a6dac140c4 100644 --- a/modules/UI/side_pannels/settings/SettingsMenu.js +++ b/modules/UI/side_pannels/settings/SettingsMenu.js @@ -42,9 +42,7 @@ export default { function update() { let displayName = $('#setDisplayName').val(); - if (displayName && Settings.getDisplayName() !== displayName) { - emitter.emit(UIEvents.NICKNAME_CHANGED, displayName); - } + emitter.emit(UIEvents.NICKNAME_CHANGED, displayName); let language = $("#languages_selectbox").val(); if (language !== Settings.getLanguage()) {