Browse Source

Escape user-generated input to avoid injection attacks

JC Brand 8 years ago
parent
commit
85f6a75fed
54 changed files with 203 additions and 164 deletions
  1. 3 2
      config.js
  2. 1 0
      docs/CHANGES.md
  3. 38 1
      spec/chatroom.js
  4. 7 7
      src/converse-muc.js
  5. 2 2
      src/templates/action.html
  6. 1 1
      src/templates/add_contact_dropdown.html
  7. 2 2
      src/templates/add_contact_form.html
  8. 5 5
      src/templates/bookmark.html
  9. 1 1
      src/templates/bookmarks_list.html
  10. 2 2
      src/templates/change_status_message.html
  11. 3 3
      src/templates/chat_status.html
  12. 2 2
      src/templates/chatarea.html
  13. 5 5
      src/templates/chatbox.html
  14. 1 1
      src/templates/chatbox_minimize.html
  15. 7 7
      src/templates/chatroom_bookmark_form.html
  16. 1 1
      src/templates/chatroom_bookmark_toggle.html
  17. 3 3
      src/templates/chatroom_head.html
  18. 4 4
      src/templates/chatroom_nickname_form.html
  19. 3 3
      src/templates/chatroom_password_form.html
  20. 2 2
      src/templates/chatroom_sidebar.html
  21. 4 4
      src/templates/chatroom_toolbar.html
  22. 5 5
      src/templates/contacts_panel.html
  23. 1 1
      src/templates/contacts_tab.html
  24. 1 1
      src/templates/controlbox_toggle.html
  25. 3 3
      src/templates/field.html
  26. 3 3
      src/templates/form_captcha.html
  27. 2 2
      src/templates/form_checkbox.html
  28. 3 3
      src/templates/form_input.html
  29. 2 2
      src/templates/form_select.html
  30. 2 2
      src/templates/form_textarea.html
  31. 4 4
      src/templates/form_username.html
  32. 1 1
      src/templates/group_header.html
  33. 1 1
      src/templates/info.html
  34. 6 6
      src/templates/login_panel.html
  35. 1 1
      src/templates/login_tab.html
  36. 2 2
      src/templates/message.html
  37. 1 1
      src/templates/new_day.html
  38. 5 5
      src/templates/occupant.html
  39. 3 3
      src/templates/pending_contact.html
  40. 4 4
      src/templates/register_panel.html
  41. 1 1
      src/templates/register_tab.html
  42. 5 5
      src/templates/registration_form.html
  43. 2 2
      src/templates/registration_request.html
  44. 4 4
      src/templates/requesting_contact.html
  45. 14 14
      src/templates/room_description.html
  46. 4 4
      src/templates/room_item.html
  47. 4 4
      src/templates/roster_item.html
  48. 2 2
      src/templates/search_contact.html
  49. 1 1
      src/templates/select_option.html
  50. 3 3
      src/templates/status_option.html
  51. 2 2
      src/templates/toggle_chats.html
  52. 3 3
      src/templates/toolbar.html
  53. 8 8
      src/templates/toolbar_otr.html
  54. 3 3
      src/templates/trimmed_chat.html

+ 3 - 2
config.js

@@ -205,8 +205,9 @@ require.config({
         // Configuration for requirejs-tpl
         // Use Mustache style syntax for variable interpolation
         templateSettings: {
-            evaluate : /\{\[([\s\S]+?)\]\}/g,
-            interpolate : /\{\{([\s\S]+?)\}\}/g
+            'escape': /\{\{\{([\s\S]+?)\}\}\}/g,
+            'evaluate': /\{\[([\s\S]+?)\]\}/g,
+            'interpolate': /\{\{([\s\S]+?)\}\}/g
         }
     },
 

+ 1 - 0
docs/CHANGES.md

@@ -8,6 +8,7 @@
   object as first parameter. [jcbrand]
 - Use lodash instead of underscore.js [jcbrand]
 - #486 Honor existing mam user configuration [throwaway42]
+- Escape user-generated input to prevent JS-injection attacks. (Thanks to SamWhited) [jcbrand]
 
 ## 2.0.5 (Unreleased)
 - #743, #751, #753 Update to Strophe 1.2.12. SASL-EXTERNAL now has reduced priority, so it won't

+ 38 - 1
spec/chatroom.js

@@ -512,10 +512,36 @@
                 }
             }));
 
-            it("indicates moderators by means of a special css class and tooltip", mock.initConverse(function (_converse) {
+            it("escapes occupant nicknames when rendering them, to avoid JS-injection attacks", mock.initConverse(function (_converse) {
                 test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
+                /* <presence xmlns="jabber:client" to="jc@chat.example.org/converse.js-17184538"
+                 *      from="oo@conference.chat.example.org/&lt;img src=&quot;x&quot; onerror=&quot;alert(123)&quot;/&gt;">
+                 *   <x xmlns="http://jabber.org/protocol/muc#user">
+                 *    <item jid="jc@chat.example.org/converse.js-17184538" affiliation="owner" role="moderator"/>
+                 *    <status code="110"/>
+                 *   </x>
+                 * </presence>"
+                 */
+                var presence = $pres({
+                        to:'dummy@localhost/pda',
+                        from:"lounge@localhost/&lt;img src=&quot;x&quot; onerror=&quot;alert(123)&quot;/&gt;"
+                }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
+                .c('item').attrs({
+                    jid: 'someone@localhost',
+                    role: 'moderator',
+                }).up()
+                .c('status').attrs({code:'110'}).nodeTree;
+
+                _converse.connection._dataRecv(test_utils.createRequest(presence));
                 var view = _converse.chatboxviews.get('lounge@localhost');
+                var occupant = view.$el.find('.occupant-list').find('li');
+                expect(occupant.length).toBe(2);
+                expect($(occupant).last().text()).toBe("&lt;img src=&quot;x&quot; onerror=&quot;alert(123)&quot;/&gt;");
+            }));
 
+            it("indicates moderators by means of a special css class and tooltip", mock.initConverse(function (_converse) {
+                test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
+                var view = _converse.chatboxviews.get('lounge@localhost');
                 var presence = $pres({
                         to:'dummy@localhost/pda',
                         from:'lounge@localhost/moderatorman'
@@ -787,6 +813,17 @@
                 expect($chat_content.find('.chat-info').text()).toBe('Topic set by ralphm to: '+text);
             }));
 
+            it("escapes the subject before rendering it, to avoid JS-injection attacks", mock.initConverse(function (_converse) {
+                test_utils.openAndEnterChatRoom(_converse, 'jdev', 'conference.jabber.org', 'jc');
+                spyOn(window, 'alert');
+                var subject = '<img src="x" onerror="alert(\'XSS\');"/>';
+                var view = _converse.chatboxviews.get('jdev@conference.jabber.org');
+                view.setChatRoomSubject('ralphm', subject);
+                var $chat_content = view.$el.find('.chat-content');
+                expect($chat_content.find('.chat-info').length).toBe(1);
+                expect($chat_content.find('.chat-info').text()).toBe('Topic set by ralphm to: '+subject);
+            }));
+
             it("informs users if their nicknames has been changed.", mock.initConverse(function (_converse) {
                 /* The service then sends two presence stanzas to the full JID
                  * of each occupant (including the occupant who is changing his

+ 7 - 7
src/converse-muc.js

@@ -268,16 +268,16 @@
                     * can then at least tell gettext to scan for it so that these
                     * strings are picked up by the translation machinery.
                     */
-                    301: ___("<strong>%1$s</strong> has been banned"),
-                    303: ___("<strong>%1$s</strong>'s nickname has changed"),
-                    307: ___("<strong>%1$s</strong> has been kicked out"),
-                    321: ___("<strong>%1$s</strong> has been removed because of an affiliation change"),
-                    322: ___("<strong>%1$s</strong> has been removed for not being a member")
+                    301: ___("%1$s has been banned"),
+                    303: ___("%1$s's nickname has changed"),
+                    307: ___("%1$s has been kicked out"),
+                    321: ___("%1$s has been removed because of an affiliation change"),
+                    322: ___("%1$s has been removed for not being a member")
                 },
 
                 new_nickname_messages: {
-                    210: ___('Your nickname has been automatically set to: <strong>%1$s</strong>'),
-                    303: ___('Your nickname has been changed to: <strong>%1$s</strong>')
+                    210: ___('Your nickname has been automatically set to: %1$s'),
+                    303: ___('Your nickname has been changed to: %1$s')
                 }
             };
 

+ 2 - 2
src/templates/action.html

@@ -1,4 +1,4 @@
-<div class="chat-message {{extra_classes}}" data-isodate="{{isodate}}">
-    <span class="chat-msg-author chat-msg-{{sender}}">{{time}} **{{username}} </span>
+<div class="chat-message {{{extra_classes}}}" data-isodate="{{{isodate}}}">
+    <span class="chat-msg-author chat-msg-{{{sender}}}">{{{time}}} **{{{username}}}&nbsp;</span>
     <span class="chat-msg-content"><!-- message gets added here via renderMessage --></span>
 </div>

+ 1 - 1
src/templates/add_contact_dropdown.html

@@ -1,6 +1,6 @@
 <dl class="add-converse-contact dropdown">
     <dt id="xmpp-contact-search" class="fancy-dropdown">
-        <a class="toggle-xmpp-contact-form icon-plus" href="#" title="{{label_click_to_chat}}"> {{label_add_contact}}</a>
+        <a class="toggle-xmpp-contact-form icon-plus" href="#" title="{{{label_click_to_chat}}}"> {{{label_add_contact}}}</a>
     </dt>
     <dd class="search-xmpp"><ul></ul></dd>
 </dl>

+ 2 - 2
src/templates/add_contact_form.html

@@ -3,7 +3,7 @@
         <input type="text"
             name="identifier"
             class="username"
-            placeholder="{{label_contact_username}}"/>
-        <button class="pure-button button-primary" type="submit">{{label_add}}</button>
+            placeholder="{{{label_contact_username}}}"/>
+        <button class="pure-button button-primary" type="submit">{{{label_add}}}</button>
     </form>
 </li>

+ 5 - 5
src/templates/bookmark.html

@@ -1,7 +1,7 @@
 <dd class="available-chatroom">
-    <a class="open-room" data-room-jid="{{jid}}" title="{{open_title}}" href="#">{{name}}</a>
-    <a class="remove-bookmark icon-close" data-room-jid="{{jid}}" data-bookmark-name="{{name}}"
-       title="{{info_remove}}" href="#">&nbsp;</a>
-    <a class="room-info icon-room-info" data-room-jid="{{jid}}"
-       title="{{info_title}}" href="#">&nbsp;</a>
+    <a class="open-room" data-room-jid="{{{jid}}}" title="{{{open_title}}}" href="#">{{{name}}}</a>
+    <a class="remove-bookmark icon-close" data-room-jid="{{{jid}}}" data-bookmark-name="{{{name}}}"
+       title="{{{info_remove}}}" href="#">&nbsp;</a>
+    <a class="room-info icon-room-info" data-room-jid="{{{jid}}}"
+       title="{{{info_title}}}" href="#">&nbsp;</a>
 </dd>

+ 1 - 1
src/templates/bookmarks_list.html

@@ -1,2 +1,2 @@
-<a href="#" class="bookmarks-toggle icon-{{toggle_state}}" title="{{desc_bookmarks}}">{{label_bookmarks}}</a>
+<a href="#" class="bookmarks-toggle icon-{{{toggle_state}}}" title="{{{desc_bookmarks}}}">{{{label_bookmarks}}}</a>
 <dl class="bookmarks rooms-list"></dl>

+ 2 - 2
src/templates/change_status_message.html

@@ -1,8 +1,8 @@
 <form id="set-custom-xmpp-status" class="pure-form">
 <fieldset>
     <span class="input-button-group">
-        <input type="text" class="custom-xmpp-status" value="{{status_message}}" placeholder="{{label_custom_status}}"/>
-        <input type="submit" class="pure-button button-primary" value="{{label_save}}"/>
+        <input type="text" class="custom-xmpp-status" value="{{{status_message}}}" placeholder="{{{label_custom_status}}}"/>
+        <input type="submit" class="pure-button button-primary" value="{{{label_save}}}"/>
     </span>
 </fieldset>
 </form>

+ 3 - 3
src/templates/chat_status.html

@@ -1,6 +1,6 @@
 <div class="xmpp-status">
-    <a class="choose-xmpp-status {{chat_status}} icon-{{chat_status}}" data-value="{{status_message}}" href="#" title="{{desc_change_status}}">
-        {{status_message}}
+    <a class="choose-xmpp-status {{{chat_status}}} icon-{{{chat_status}}}" data-value="{{{status_message}}}" href="#" title="{{{desc_change_status}}}">
+        {{{status_message}}}
     </a>
-    <a class="change-xmpp-status-message icon-pencil" href="#" title="{{desc_custom_status}}"></a>
+    <a class="change-xmpp-status-message icon-pencil" href="#" title="{{{desc_custom_status}}}"></a>
 </div>

+ 2 - 2
src/templates/chatarea.html

@@ -1,11 +1,11 @@
 <div class="chat-area">
     <div class="chat-content"></div>
-    <div class="new-msgs-indicator hidden">▼ {{ unread_msgs }} ▼</div>
+    <div class="new-msgs-indicator hidden">▼ {{{ unread_msgs }}} ▼</div>
     <form class="sendXMPPMessage" action="" method="post">
         {[ if (show_toolbar) { ]}
             <ul class="chat-toolbar no-text-select"></ul>
         {[ } ]}
         <textarea type="text" class="chat-textarea" 
-            placeholder="{{label_message}}"/>
+            placeholder="{{{label_message}}}"/>
     </form>
 </div>

+ 5 - 5
src/templates/chatbox.html

@@ -3,12 +3,12 @@
     <div class="dragresize dragresize-topleft"></div>
     <div class="dragresize dragresize-left"></div>
     <div class="chat-head chat-head-chatbox">
-        <a class="chatbox-btn close-chatbox-button icon-close" title="{{info_close}}"></a>
+        <a class="chatbox-btn close-chatbox-button icon-close" title="{{{info_close}}}"></a>
         <div class="chat-title">
             {[ if (url) { ]}
-                <a href="{{url}}" target="_blank" rel="noopener" class="user">
+                <a href="{{{url}}}" target="_blank" rel="noopener" class="user">
             {[ } ]}
-                    {{ title }}
+                    {{{ title }}}
             {[ if (url) { ]}
                 </a>
             {[ } ]}
@@ -17,7 +17,7 @@
     </div>
     <div class="chat-body">
         <div class="chat-content"></div>
-        <div class="new-msgs-indicator hidden">▼ {{ unread_msgs }} ▼</div>
+        <div class="new-msgs-indicator hidden">▼ {{{ unread_msgs }}} ▼</div>
         {[ if (show_textarea) { ]}
         <form class="sendXMPPMessage" action="" method="post">
             {[ if (show_toolbar) { ]}
@@ -26,7 +26,7 @@
         <textarea
             type="text"
             class="chat-textarea"
-            placeholder="{{label_personal_message}}"/>
+            placeholder="{{{label_personal_message}}}"/>
         </form>
         {[ } ]}
     </div>

+ 1 - 1
src/templates/chatbox_minimize.html

@@ -1 +1 @@
-<a class="chatbox-btn toggle-chatbox-button icon-minus" title="{{info_minimize}}"></a>
+<a class="chatbox-btn toggle-chatbox-button icon-minus" title="{{{info_minimize}}}"></a>

+ 7 - 7
src/templates/chatroom_bookmark_form.html

@@ -1,17 +1,17 @@
 <div class="chatroom-form-container">
     <form class="pure-form converse-form chatroom-form">
         <fieldset>
-            <legend>{{heading}}</legend>
-            <label>{{label_name}}</label>
+            <legend>{{{heading}}}</legend>
+            <label>{{{label_name}}}</label>
             <input type="text" name="name" required="required"/>
-            <label>{{label_autojoin}}</label>
+            <label>{{{label_autojoin}}}</label>
             <input type="checkbox" name="autojoin"/>
-            <label>{{label_nick}}</label>
-            <input type="text" name="nick" value="{{default_nick}}"/>
+            <label>{{{label_nick}}}</label>
+            <input type="text" name="nick" value="{{{default_nick}}}"/>
         </fieldset>
         <fieldset>
-            <input class="pure-button button-primary" type="submit" value="{{label_submit}}"/>
-            <input class="pure-button button-cancel" type="button" value="{{label_cancel}}"/>
+            <input class="pure-button button-primary" type="submit" value="{{{label_submit}}}"/>
+            <input class="pure-button button-cancel" type="button" value="{{{label_cancel}}}"/>
         </fieldset>
     </form>
 </div>

+ 1 - 1
src/templates/chatroom_bookmark_toggle.html

@@ -1,4 +1,4 @@
 <a class="chatbox-btn toggle-bookmark icon-pushpin
    {[ if (bookmarked) {]}
     button-on
-   {[ } ]}" title="{{info_toggle_bookmark}}"></a>
+   {[ } ]}" title="{{{info_toggle_bookmark}}}"></a>

+ 3 - 3
src/templates/chatroom_head.html

@@ -1,8 +1,8 @@
-<a class="chatbox-btn close-chatbox-button icon-close" title="{{info_close}}"></a>
+<a class="chatbox-btn close-chatbox-button icon-close" title="{{{info_close}}}"></a>
 {[ if (affiliation == 'owner') { ]}
-    <a class="chatbox-btn configure-chatroom-button icon-wrench" title="{{info_configure}} "></a>
+    <a class="chatbox-btn configure-chatroom-button icon-wrench" title="{{{info_configure}}} "></a>
 {[ } ]}
 <div class="chat-title">
-    {{ _.escape(name) }}
+    {{{ name }}}
     <p class="chatroom-topic"><p/>
 </div>

+ 4 - 4
src/templates/chatroom_nickname_form.html

@@ -1,12 +1,12 @@
 <div class="chatroom-form-container">
     <form class="pure-form converse-form chatroom-form converse-centered-form">
         <fieldset>
-            <label>{{heading}}</label>
-            <p class="validation-message">{{validation_message}}</p>
-            <input type="text" required="required" name="nick" class="new-chatroom-nick" placeholder="{{label_nickname}}"/>
+            <label>{{{heading}}}</label>
+            <p class="validation-message">{{{validation_message}}}</p>
+            <input type="text" required="required" name="nick" class="new-chatroom-nick" placeholder="{{{label_nickname}}}"/>
         </fieldset>
         <fieldset>
-            <input type="submit" class="pure-button button-primary" name="join" value="{{label_join}}"/>
+            <input type="submit" class="pure-button button-primary" name="join" value="{{{label_join}}}"/>
         </fieldset>
     </form>
 </div>

+ 3 - 3
src/templates/chatroom_password_form.html

@@ -1,12 +1,12 @@
 <div class="chatroom-form-container">
     <form class="pure-form converse-form chatroom-form">
         <fieldset>
-            <legend>{{heading}}</legend>
-            <label>{{label_password}}</label>
+            <legend>{{{heading}}}</legend>
+            <label>{{{label_password}}}</label>
             <input type="password" name="password"/>
         </fieldset>
         <fieldset>
-            <input class="pure-button button-primary" type="submit" value="{{label_submit}}"/>
+            <input class="pure-button button-primary" type="submit" value="{{{label_submit}}}"/>
         </fieldset>
     </form>
 </div>

+ 2 - 2
src/templates/chatroom_sidebar.html

@@ -1,9 +1,9 @@
 <!-- <div class="occupants"> -->
 {[ if (allow_muc_invitations) { ]}
 <form class="pure-form room-invite">
-    <input class="invited-contact" placeholder="{{label_invitation}}" type="text"/>
+    <input class="invited-contact" placeholder="{{{label_invitation}}}" type="text"/>
 </form>
 {[ } ]}
-<p class="occupants-heading">{{label_occupants}}:</p>
+<p class="occupants-heading">{{{label_occupants}}}:</p>
 <ul class="occupant-list"></ul>
 <!-- </div> -->

+ 4 - 4
src/templates/chatroom_toolbar.html

@@ -1,5 +1,5 @@
 {[ if (show_emoticons)  { ]}
-    <li class="toggle-smiley icon-happy" title="{{label_insert_smiley}}">
+    <li class="toggle-smiley icon-happy" title="{{{label_insert_smiley}}}">
         <ul>
             <li><a class="icon-smiley" href="#" data-emoticon=":)"></a></li>
             <li><a class="icon-wink" href="#" data-emoticon=";)"></a></li>
@@ -18,12 +18,12 @@
     </li>
 {[ } ]}
 {[ if (show_call_button)  { ]}
-<li class="toggle-call"><a class="icon-phone" title="{{label_start_call}}"></a></li>
+<li class="toggle-call"><a class="icon-phone" title="{{{label_start_call}}}"></a></li>
 {[ } ]}
 {[ if (show_occupants_toggle)  { ]}
-<li class="toggle-occupants"><a class="icon-hide-users" title="{{label_hide_occupants}}"></a></li>
+<li class="toggle-occupants"><a class="icon-hide-users" title="{{{label_hide_occupants}}}"></a></li>
 {[ } ]}
 {[ if (show_clear_button)  { ]}
-<li class="toggle-clear"><a class="icon-remove" title="{{label_clear}}"></a></li>
+<li class="toggle-clear"><a class="icon-remove" title="{{{label_clear}}}"></a></li>
 {[ } ]}
 

+ 5 - 5
src/templates/contacts_panel.html

@@ -1,14 +1,14 @@
 <form class="pure-form set-xmpp-status" action="" method="post">
     <span id="xmpp-status-holder">
         <select id="select-xmpp-status" style="display:none">
-            <option value="online">{{label_online}}</option>
-            <option value="dnd">{{label_busy}}</option>
-            <option value="away">{{label_away}}</option>
+            <option value="online">{{{label_online}}}</option>
+            <option value="dnd">{{{label_busy}}}</option>
+            <option value="away">{{{label_away}}}</option>
             {[ if (include_offline_state)  { ]}
-            <option value="offline">{{label_offline}}</option>
+            <option value="offline">{{{label_offline}}}</option>
             {[ } ]}
             {[ if (allow_logout)  { ]}
-            <option value="logout">{{label_logout}}</option>
+            <option value="logout">{{{label_logout}}}</option>
             {[ } ]}
         </select>
     </span>

+ 1 - 1
src/templates/contacts_tab.html

@@ -1,4 +1,4 @@
 <li><a class="s {[ if (is_current) { ]} current {[ } ]}"
        data-id="users" href="#users">
-    {{label_contacts}}
+    {{{label_contacts}}}
 </a></li>

+ 1 - 1
src/templates/controlbox_toggle.html

@@ -1 +1 @@
-<span class="conn-feedback">{{label_toggle}}</span>
+<span class="conn-feedback">{{{label_toggle}}}</span>

+ 3 - 3
src/templates/field.html

@@ -1,5 +1,5 @@
-<field var="{{name}}">{[ if (_.isArray(value)) { ]}
-    {[ _.each(value,function(arrayValue) { ]}<value>{{arrayValue}}</value>{[ }); ]}
+<field var="{{{name}}}">{[ if (_.isArray(value)) { ]}
+    {[ _.each(value,function(arrayValue) { ]}<value>{{{arrayValue}}}</value>{[ }); ]}
 {[ } else { ]}
-    <value>{{value}}</value>
+    <value>{{{value}}}</value>
 {[ } ]}</field>

+ 3 - 3
src/templates/form_captcha.html

@@ -1,9 +1,9 @@
 {[ if (label) { ]}
 <label>
-    {{label}}
+    {{{label}}}
 </label>
 {[ } ]}
-<img src="data:{{type}};base64,{{data}}">
-<input name="{{name}}" type="text" {[ if (required) { ]} class="required" {[ } ]} >
+<img src="data:{{{type}}};base64,{{{data}}}">
+<input name="{{{name}}}" type="text" {[ if (required) { ]} class="required" {[ } ]} >
 
 

+ 2 - 2
src/templates/form_checkbox.html

@@ -1,2 +1,2 @@
-<label>{{label}}</label>
-<input name="{{name}}" type="{{type}}" {{checked}}>
+<label>{{{label}}}</label>
+<input name="{{{name}}}" type="{{{type}}}" {{{checked}}}>

+ 3 - 3
src/templates/form_input.html

@@ -1,8 +1,8 @@
 {[ if (label) { ]}
 <label>
-    {{label}}
+    {{{label}}}
 </label>
 {[ } ]}
-<input name="{{name}}" type="{{type}}" 
-    {[ if (value) { ]} value="{{value}}" {[ } ]}
+<input name="{{{name}}}" type="{{{type}}}" 
+    {[ if (value) { ]} value="{{{value}}}" {[ } ]}
     {[ if (required) { ]} class="required" {[ } ]} >

+ 2 - 2
src/templates/form_select.html

@@ -1,2 +1,2 @@
-<label>{{label}}</label>
-<select name="{{name}}"  {[ if (multiple) { ]} multiple="multiple" {[ } ]}>{{options}}</select>
+<label>{{{label}}}</label>
+<select name="{{{name}}}"  {[ if (multiple) { ]} multiple="multiple" {[ } ]}>{{options}}</select>

+ 2 - 2
src/templates/form_textarea.html

@@ -1,2 +1,2 @@
-<label class="label-ta">{{label}}</label>
-<textarea name="{{name}}">{{value}}</textarea>
+<label class="label-ta">{{{label}}}</label>
+<textarea name="{{{name}}}">{{{value}}}</textarea>

+ 4 - 4
src/templates/form_username.html

@@ -1,11 +1,11 @@
 {[ if (label) { ]}
 <label>
-    {{label}}
+    {{{label}}}
 </label>
 {[ } ]}
 <div class="input-group">
-    <input name="{{name}}" type="{{type}}"
-        {[ if (value) { ]} value="{{value}}" {[ } ]}
+    <input name="{{{name}}}" type="{{{type}}}"
+        {[ if (value) { ]} value="{{{value}}}" {[ } ]}
         {[ if (required) { ]} class="required" {[ } ]} />
-    <span title="{{domain}}">{{domain}}</span>
+    <span title="{{{domain}}}">{{{domain}}}</span>
 </div>

+ 1 - 1
src/templates/group_header.html

@@ -1 +1 @@
-<a href="#" class="group-toggle icon-{{toggle_state}}" title="{{desc_group_toggle}}">{{label_group}}</a>
+<a href="#" class="group-toggle icon-{{{toggle_state}}}" title="{{{desc_group_toggle}}}">{{{label_group}}}</a>

+ 1 - 1
src/templates/info.html

@@ -1 +1 @@
-<div class="chat-info">{{message}}</div>
+<div class="chat-info">{{{message}}}</div>

+ 6 - 6
src/templates/login_panel.html

@@ -4,17 +4,17 @@
     {[ } ]}
     {[ if (!auto_login) { ]}
         {[ if (authentication == LOGIN || authentication == EXTERNAL) { ]}
-            <label>{{label_username}}</label>
-            <input type="text" name="jid" placeholder="{{placeholder_username}}">
+            <label>{{{label_username}}}</label>
+            <input type="text" name="jid" placeholder="{{{placeholder_username}}}">
             {[ if (authentication !== EXTERNAL) { ]}
-                <label>{{label_password}}</label>
-                <input type="password" name="password" placeholder="{{placeholder_password}}">
+                <label>{{{label_password}}}</label>
+                <input type="password" name="password" placeholder="{{{placeholder_password}}}">
             {[ } ]}
-            <input class="pure-button button-primary" type="submit" value="{{label_login}}">
+            <input class="pure-button button-primary" type="submit" value="{{{label_login}}}">
             <span class="conn-feedback"></span>
         {[ } ]}
         {[ if (authentication == ANONYMOUS) { ]}
-            <input type="pure-button button-primary" class="submit login-anon" value="{{label_anon_login}}"/>
+            <input type="pure-button button-primary" class="submit login-anon" value="{{{label_anon_login}}}"/>
         {[ } ]}
         {[ if (authentication == PREBIND) { ]}
             <p>Disconnected.</p>

+ 1 - 1
src/templates/login_tab.html

@@ -1 +1 @@
-<li><a class="current" href="#login-dialog">{{label_sign_in}}</a></li>
+<li><a class="current" href="#login-dialog">{{{label_sign_in}}}</a></li>

+ 2 - 2
src/templates/message.html

@@ -1,4 +1,4 @@
-<div class="chat-message {{extra_classes}}" data-isodate="{{isodate}}" data-msgid="{{msgid}}">
-    <span class="chat-msg-author chat-msg-{{sender}}">{{time}} {{username}}:&nbsp;</span>
+<div class="chat-message {{{extra_classes}}}" data-isodate="{{{isodate}}}" data-msgid="{{{msgid}}}">
+    <span class="chat-msg-author chat-msg-{{{sender}}}">{{{time}}} {{{username}}}:&nbsp;</span>
     <span class="chat-msg-content"><!-- message gets added here via renderMessage --></span>
 </div>

+ 1 - 1
src/templates/new_day.html

@@ -1 +1 @@
-<time class="chat-info chat-date" data-isodate="{{isodate}}">{{datestring}}</time>
+<time class="chat-info chat-date" data-isodate="{{{isodate}}}">{{{datestring}}}</time>

+ 5 - 5
src/templates/occupant.html

@@ -1,10 +1,10 @@
-<li class="{{role}} occupant" id="{{id}}"
+<li class="{{{role}}} occupant" id="{{{id}}}"
     {[ if (role === "moderator") { ]}
-       title="{{desc_moderator}} {{hint_occupant}}"
+       title="{{{desc_moderator}}} {{{hint_occupant}}}"
     {[ } ]}
     {[ if (role === "occupant") { ]}
-       title="{{desc_occupant}} {{hint_occupant}}"
+       title="{{{desc_occupant}}} {{{hint_occupant}}}"
     {[ } ]}
     {[ if (role === "visitor") { ]}
-       title="{{desc_visitor}} {{hint_occupant}}"
-    {[ } ]}>{{nick}}</li>
+       title="{{{desc_visitor}}} {{{hint_occupant}}}"
+    {[ } ]}>{{{nick}}}</li>

+ 3 - 3
src/templates/pending_contact.html

@@ -1,9 +1,9 @@
 {[ if (allow_chat_pending_contacts)  { ]}
 <a class="open-chat"href="#">
 {[ } ]}
-<span class="pending-contact-name" title="Name: {{fullname}}
-JID: {{jid}}">{{fullname}}</span> 
+<span class="pending-contact-name" title="Name: {{{fullname}}}
+JID: {{{jid}}}">{{{fullname}}}</span> 
 {[ if (allow_chat_pending_contacts)  { ]}
 </a>
 {[ } ]}
-<a class="remove-xmpp-contact icon-remove" title="{{desc_remove}}" href="#"></a>
+<a class="remove-xmpp-contact icon-remove" title="{{{desc_remove}}}" href="#"></a>

+ 4 - 4
src/templates/register_panel.html

@@ -1,7 +1,7 @@
 <form id="converse-register" class="pure-form converse-form">
     <span class="reg-feedback"></span>
-    <label>{{label_domain}}</label>
-    <input type="text" name="domain" placeholder="{{domain_placeholder}}">
-    <p class="form-help">{{help_providers}} <a href="{{href_providers}}" class="url" target="_blank" rel="noopener">{{help_providers_link}}</a>.</p>
-    <input class="pure-button button-primary" type="submit" value="{{label_register}}">
+    <label>{{{label_domain}}}</label>
+    <input type="text" name="domain" placeholder="{{{domain_placeholder}}}">
+    <p class="form-help">{{{help_providers}}} <a href="{{{href_providers}}}" class="url" target="_blank" rel="noopener">{{{help_providers_link}}}</a>.</p>
+    <input class="pure-button button-primary" type="submit" value="{{{label_register}}}">
 </form>

+ 1 - 1
src/templates/register_tab.html

@@ -1 +1 @@
-<li><a class="s" href="#register">{{label_register}}</a></li>
+<li><a class="s" href="#register">{{{label_register}}}</a></li>

+ 5 - 5
src/templates/registration_form.html

@@ -1,6 +1,6 @@
-<p class="provider-title">{{domain}}</p>
-<a href='https://xmpp.net/result.php?domain={{domain}}&amp;type=client'>
-    <img class="provider-score" src='https://xmpp.net/badge.php?domain={{domain}}' alt='xmpp.net score' />
+<p class="provider-title">{{{domain}}}</p>
+<a href='https://xmpp.net/result.php?domain={{{domain}}}&amp;type=client'>
+    <img class="provider-score" src='https://xmpp.net/badge.php?domain={{{domain}}}' alt='xmpp.net score' />
 </a>
-<p class="title">{{title}}</p>
-<p class="instructions">{{instructions}}</p>
+<p class="title">{{{title}}}</p>
+<p class="instructions">{{{instructions}}}</p>

+ 2 - 2
src/templates/registration_request.html

@@ -1,3 +1,3 @@
 <span class="spinner login-submit"/>
-<p class="info">{{info_message}}</p>
-<button class="pure-button button-cancel hor_centered">{{cancel}}</button>
+<p class="info">{{{info_message}}}</p>
+<button class="pure-button button-cancel hor_centered">{{{cancel}}}</button>

+ 4 - 4
src/templates/requesting_contact.html

@@ -1,12 +1,12 @@
 {[ if (allow_chat_pending_contacts)  { ]}
 <a class="open-chat"href="#">
 {[ } ]}
-<span class="req-contact-name" title="Name: {{fullname}}
-JID: {{jid}}">{{fullname}}</span>
+<span class="req-contact-name" title="Name: {{{fullname}}}
+JID: {{{jid}}}">{{{fullname}}}</span>
 {[ if (allow_chat_pending_contacts)  { ]}
 </a>
 {[ } ]}
 <span class="request-actions">
-    <a class="accept-xmpp-request icon-checkmark" title="{{desc_accept}}" href="#"></a>
-    <a class="decline-xmpp-request icon-close" title="{{desc_decline}}" href="#"></a>
+    <a class="accept-xmpp-request icon-checkmark" title="{{{desc_accept}}}" href="#"></a>
+    <a class="decline-xmpp-request icon-close" title="{{{desc_decline}}}" href="#"></a>
 </span>

+ 14 - 14
src/templates/room_description.html

@@ -1,41 +1,41 @@
 <!-- FIXME: check markup in mockup -->
 <div class="room-info">
-<p class="room-info"><strong>{{label_desc}}</strong> {{desc}}</p>
-<p class="room-info"><strong>{{label_occ}}</strong> {{occ}}</p>
-<p class="room-info"><strong>{{label_features}}</strong>
+<p class="room-info"><strong>{{{label_desc}}}</strong> {{{desc}}}</p>
+<p class="room-info"><strong>{{{label_occ}}}</strong> {{{occ}}}</p>
+<p class="room-info"><strong>{{{label_features}}}</strong>
     <ul>
         {[ if (passwordprotected) { ]}
-        <li class="room-info locked">{{label_requires_auth}}</li>
+        <li class="room-info locked">{{{label_requires_auth}}}</li>
         {[ } ]}
         {[ if (hidden) { ]}
-        <li class="room-info">{{label_hidden}}</li>
+        <li class="room-info">{{{label_hidden}}}</li>
         {[ } ]}
         {[ if (membersonly) { ]}
-        <li class="room-info">{{label_requires_invite}}</li>
+        <li class="room-info">{{{label_requires_invite}}}</li>
         {[ } ]}
         {[ if (moderated) { ]}
-        <li class="room-info">{{label_moderated}}</li>
+        <li class="room-info">{{{label_moderated}}}</li>
         {[ } ]}
         {[ if (nonanonymous) { ]}
-        <li class="room-info">{{label_non_anon}}</li>
+        <li class="room-info">{{{label_non_anon}}}</li>
         {[ } ]}
         {[ if (open) { ]}
-        <li class="room-info">{{label_open_room}}</li>
+        <li class="room-info">{{{label_open_room}}}</li>
         {[ } ]}
         {[ if (persistent) { ]}
-        <li class="room-info">{{label_permanent_room}}</li>
+        <li class="room-info">{{{label_permanent_room}}}</li>
         {[ } ]}
         {[ if (publicroom) { ]}
-        <li class="room-info">{{label_public}}</li>
+        <li class="room-info">{{{label_public}}}</li>
         {[ } ]}
         {[ if (semianonymous) { ]}
-        <li class="room-info">{{label_semi_anon}}</li>
+        <li class="room-info">{{{label_semi_anon}}}</li>
         {[ } ]}
         {[ if (temporary) { ]}
-        <li class="room-info">{{label_temp_room}}</li>
+        <li class="room-info">{{{label_temp_room}}}</li>
         {[ } ]}
         {[ if (unmoderated) { ]}
-        <li class="room-info">{{label_unmoderated}}</li>
+        <li class="room-info">{{{label_unmoderated}}}</li>
         {[ } ]}
     </ul>
 </p>

+ 4 - 4
src/templates/room_item.html

@@ -1,6 +1,6 @@
 <dd class="available-chatroom">
-<a class="open-room" data-room-jid="{{jid}}"
-   title="{{open_title}}" href="#">{{_.escape(name)}}</a>
-<a class="room-info icon-room-info" data-room-jid="{{jid}}"
-   title="{{info_title}}" href="#">&nbsp;</a>
+<a class="open-room" data-room-jid="{{{jid}}}"
+   title="{{{open_title}}}" href="#">{{{_.escape(name)}}}</a>
+<a class="room-info icon-room-info" data-room-jid="{{{jid}}}"
+   title="{{{info_title}}}" href="#">&nbsp;</a>
 </dd>

+ 4 - 4
src/templates/roster_item.html

@@ -1,6 +1,6 @@
-<a class="open-chat" title="{{title_fullname}}: {{fullname}}
-JID: {{jid}}
-{{desc_chat}}" href="#"><span class="icon-{{chat_status}}" title="{{desc_status}}"></span>{{fullname}}</a>
+<a class="open-chat" title="{{{title_fullname}}}: {{{fullname}}}
+JID: {{{jid}}}
+{{{desc_chat}}}" href="#"><span class="icon-{{{chat_status}}}" title="{{{desc_status}}}"></span>{{{fullname}}}</a>
 {[ if (allow_contact_removal) { ]}
-<a class="remove-xmpp-contact icon-remove" title="{{desc_remove}}" href="#"></a>
+<a class="remove-xmpp-contact icon-remove" title="{{{desc_remove}}}" href="#"></a>
 {[ } ]}

+ 2 - 2
src/templates/search_contact.html

@@ -3,7 +3,7 @@
         <input type="text"
             name="identifier"
             class="username"
-            placeholder="{{label_contact_name}}"/>
-        <button type="submit">{{label_search}}</button>
+            placeholder="{{{label_contact_name}}}"/>
+        <button type="submit">{{{label_search}}}</button>
     </form>
 </li>

+ 1 - 1
src/templates/select_option.html

@@ -1 +1 @@
-<option value="{{value}}" {[ if (selected) { ]} selected="selected" {[ } ]} >{{label}}</option>
+<option value="{{{value}}}" {[ if (selected) { ]} selected="selected" {[ } ]} >{{{label}}}</option>

+ 3 - 3
src/templates/status_option.html

@@ -1,6 +1,6 @@
 <li>
-    <a href="#" class="{{ value }}" data-value="{{ value }}">
-        <span class="icon-{{ value }}"></span>
-        {{ text }}
+    <a href="#" class="{{{ value }}}" data-value="{{{ value }}}">
+        <span class="icon-{{{ value }}}"></span>
+        {{{ text }}}
     </a>
 </li>

+ 2 - 2
src/templates/toggle_chats.html

@@ -1,4 +1,4 @@
-{{Minimized}} <span id="minimized-count">({{num_minimized}})</span>
+{{{Minimized}}} <span id="minimized-count">({{{num_minimized}}})</span>
 <span class="unread-message-count"
     {[ if (!num_unread) { ]} style="display: none" {[ } ]}
-    href="#">{{num_unread}}</span>
+    href="#">{{{num_unread}}}</span>

+ 3 - 3
src/templates/toolbar.html

@@ -1,5 +1,5 @@
 {[ if (show_emoticons)  { ]}
-    <li class="toggle-smiley icon-happy" title="{{label_insert_smiley}}">
+    <li class="toggle-smiley icon-happy" title="{{{label_insert_smiley}}}">
         <ul>
             <li><a class="icon-smiley" href="#" data-emoticon=":)"></a></li>
             <li><a class="icon-wink" href="#" data-emoticon=";)"></a></li>
@@ -18,8 +18,8 @@
     </li>
 {[ } ]}
 {[ if (show_call_button)  { ]}
-<li class="toggle-call"><a class="icon-phone" title="{{label_start_call}}"></a></li>
+<li class="toggle-call"><a class="icon-phone" title="{{{label_start_call}}}"></a></li>
 {[ } ]}
 {[ if (show_clear_button)  { ]}
-<li class="toggle-clear"><a class="icon-remove" title="{{label_clear}}"></a></li>
+<li class="toggle-clear"><a class="icon-remove" title="{{{label_clear}}}"></a></li>
 {[ } ]}

+ 8 - 8
src/templates/toolbar_otr.html

@@ -1,6 +1,6 @@
 {[ if (allow_otr)  { ]}
-    <li class="toggle-otr {{otr_status_class}}" title="{{otr_tooltip}}">
-        <span class="chat-toolbar-text">{{otr_translated_status}}</span>
+    <li class="toggle-otr {{{otr_status_class}}}" title="{{{otr_tooltip}}}">
+        <span class="chat-toolbar-text">{{{otr_translated_status}}}</span>
         {[ if (otr_status == UNENCRYPTED) { ]}
             <span class="icon-unlocked"></span>
         {[ } ]}
@@ -15,17 +15,17 @@
         {[ } ]}
         <ul>
             {[ if (otr_status == UNENCRYPTED) { ]}
-               <li><a class="start-otr" href="#">{{label_start_encrypted_conversation}}</a></li>
+               <li><a class="start-otr" href="#">{{{label_start_encrypted_conversation}}}</a></li>
             {[ } ]}
             {[ if (otr_status != UNENCRYPTED) { ]}
-               <li><a class="start-otr" href="#">{{label_refresh_encrypted_conversation}}</a></li>
-               <li><a class="end-otr" href="#">{{label_end_encrypted_conversation}}</a></li>
-               <li><a class="auth-otr" data-scheme="smp" href="#">{{label_verify_with_smp}}</a></li>
+               <li><a class="start-otr" href="#">{{{label_refresh_encrypted_conversation}}}</a></li>
+               <li><a class="end-otr" href="#">{{{label_end_encrypted_conversation}}}</a></li>
+               <li><a class="auth-otr" data-scheme="smp" href="#">{{{label_verify_with_smp}}}</a></li>
             {[ } ]}
             {[ if (otr_status == UNVERIFIED) { ]}
-               <li><a class="auth-otr" data-scheme="fingerprint" href="#">{{label_verify_with_fingerprints}}</a></li>
+               <li><a class="auth-otr" data-scheme="fingerprint" href="#">{{{label_verify_with_fingerprints}}}</a></li>
             {[ } ]}
-            <li><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank" rel="noopener">{{label_whats_this}}</a></li>
+            <li><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank" rel="noopener">{{{label_whats_this}}}</a></li>
         </ul>
     </li>
 {[ } ]}

+ 3 - 3
src/templates/trimmed_chat.html

@@ -1,7 +1,7 @@
 <a class="chatbox-btn close-chatbox-button icon-close"></a>
 <a class="chat-head-message-count" 
     {[ if (!num_unread) { ]} style="display: none" {[ } ]}
-    href="#">{{num_unread}}</a>
-<a href="#" class="restore-chat" title="{{tooltip}}">
-    {{ title }}
+    href="#">{{{num_unread}}}</a>
+<a href="#" class="restore-chat" title="{{{tooltip}}}">
+    {{{ title }}}
 </a>