Quellcode durchsuchen

Merge branch 'master' into 0.8

Conflicts:
	bower.json
	converse.js
	docs/CHANGES.rst
	spec/chatbox.js
	tests/utils.js
	tests_main.js
JC Brand vor 11 Jahren
Ursprung
Commit
9849daacf9

+ 1 - 1
bower.json

@@ -1,6 +1,6 @@
 {
   "name": "converse",
-  "version": "0.7.3",
+  "version": "0.7.4",
   "devDependencies": {
     "jasmine": "https://github.com/jcbrand/jasmine.git#1_3_x",
     "otr": "0.2.7",

Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 1
builds/converse-no-locales-no-otr.min.js


Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 1
builds/converse-no-otr.min.js


Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 1
builds/converse.min.js


+ 5 - 3
converse.js

@@ -43,7 +43,8 @@
                 if (list) {
                     for (i=0; i<list.length; i++) {
                         var prot = list[i].indexOf('http://') === 0 || list[i].indexOf('https://') === 0 ? '' : 'http://';
-                        x = x.replace(list[i], "<a target='_blank' href='" + prot + list[i] + "'>"+ list[i] + "</a>" );
+                        var escaped_url = encodeURI(decodeURI(list[i])).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
+                        x = x.replace(list[i], "<a target='_blank' href='" + prot + escaped_url + "'>"+ list[i] + "</a>" );
                     }
                 }
                 $(obj).html(x);
@@ -942,15 +943,16 @@
                     msg_date = msg_dict.time ? converse.parseISO8601(msg_dict.time) : new Date(),
                     text = msg_dict.message,
                     match = text.match(/^\/(.*?)(?: (.*))?$/),
+                    fullname = msg_dict.fullname || this.model.get('fullname'),
                     template, username;
 
                 if ((match) && (match[1] === 'me')) {
                     text = text.replace(/^\/me/, '');
                     template = converse.templates.action_template;
-                    username = msg_dict.fullname;
+                    username = fullname;
                 } else  {
                     template = converse.templates.message;
-                    username = msg_dict.sender === 'me' && __('me') || msg_dict.fullname || this.model.get('fullname');
+                    username = msg_dict.sender === 'me' && __('me') || fullname;
                 }
                 $el.find('div.chat-event').remove();
                 var message = template({

+ 12 - 1
docs/CHANGES.rst

@@ -7,6 +7,16 @@ Changelog
 * Chat boxes and rooms can now be resized vertically. [jcbrand]
 * Chat boxes and rooms can be minimized. [jcbrand]
 
+0.7.4 (2014-03-05)
+------------------
+
+.. note:: This release contains an important security fix.
+   Thanks to Renaud Dubourguais from `Synacktiv http://synacktiv.com`_ for reporting the vulnerability.
+
+* #125 Bugfix: crypto dependencies loaded in wrong order [jcbrand]
+* Bugfix: action messages (i.e. /me) didn't work in OTR mode. [jcbrand]
+* Security fix: Ensure that message URLs are properly encoded. [jcbrand]
+
 0.7.3 (2014-02-23)
 ------------------
 
@@ -22,11 +32,12 @@ Changelog
 ------------------
 
 .. note:: This release contains an important security fix.
+   Thanks to hejsan for reporting the vulnerability.
 
 * #48 Add event emitter support and emit events. [jcbrand]
 * #97 Wrong number of online contacts shown with config option ``show_only_online_users``. [jcbrand]
 * #100 Make the fetching of vCards optional (enabled by default). [jcbrand]
-* Sanitize message text to avoid Javascript injection attacks. Thanks to hejsan for reporting. [jcbrand]
+* Sanitize message text to avoid Javascript injection attacks.  [jcbrand]
 
 0.7.1 (2013-11-17)
 ------------------

+ 1 - 1
docs/html/.buildinfo

@@ -1,4 +1,4 @@
 # Sphinx build info version 1
 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
-config: 738ca7b60aed811ee1668ad08d26eabb
+config: 0660e50cf30718622673fcf0e779dfd4
 tags: fbb0d17656682115ca4d033fb2f83ba1

+ 5 - 5
docs/html/genindex.html

@@ -9,7 +9,7 @@
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     
-    <title>Index &mdash; Converse.js 0.7.3 documentation</title>
+    <title>Index &mdash; Converse.js 0.7.4 documentation</title>
     
     <link rel="stylesheet" href="_static/stylesheet.css" type="text/css" />
     <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -17,7 +17,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    '',
-        VERSION:     '0.7.3',
+        VERSION:     '0.7.4',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -26,7 +26,7 @@
     <script type="text/javascript" src="_static/jquery.js"></script>
     <script type="text/javascript" src="_static/underscore.js"></script>
     <script type="text/javascript" src="_static/doctools.js"></script>
-    <link rel="top" title="Converse.js 0.7.3 documentation" href="index.html" /> 
+    <link rel="top" title="Converse.js 0.7.4 documentation" href="index.html" /> 
   </head>
   <body>
     <div id="header_wrap" class="outer">
@@ -51,7 +51,7 @@
         <li class="right" style="margin-right: 10px">
           <a href="#" title="General Index"
              accesskey="I">index</a></li>
-        <li><a href="index.html">Converse.js 0.7.3 documentation</a> &raquo;</li> 
+        <li><a href="index.html">Converse.js 0.7.4 documentation</a> &raquo;</li> 
       </ul>
     </div>
 <section id="main_content" class="inner">  
@@ -80,7 +80,7 @@
         <li class="right" style="margin-right: 10px">
           <a href="#" title="General Index"
              >index</a></li>
-        <li><a href="index.html">Converse.js 0.7.3 documentation</a> &raquo;</li> 
+        <li><a href="index.html">Converse.js 0.7.4 documentation</a> &raquo;</li> 
       </ul>
     </div>
 </div>

+ 5 - 5
docs/html/index.html

@@ -7,7 +7,7 @@
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     
-    <title>Quickstart (to get a demo up and running) &mdash; Converse.js 0.7.3 documentation</title>
+    <title>Quickstart (to get a demo up and running) &mdash; Converse.js 0.7.4 documentation</title>
     
     <link rel="stylesheet" href="_static/stylesheet.css" type="text/css" />
     <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -15,7 +15,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    '',
-        VERSION:     '0.7.3',
+        VERSION:     '0.7.4',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -24,7 +24,7 @@
     <script type="text/javascript" src="_static/jquery.js"></script>
     <script type="text/javascript" src="_static/underscore.js"></script>
     <script type="text/javascript" src="_static/doctools.js"></script>
-    <link rel="top" title="Converse.js 0.7.3 documentation" href="#" /> 
+    <link rel="top" title="Converse.js 0.7.4 documentation" href="#" /> 
   </head>
   <body>
     <div id="header_wrap" class="outer">
@@ -49,7 +49,7 @@
         <li class="right" style="margin-right: 10px">
           <a href="genindex.html" title="General Index"
              accesskey="I">index</a></li>
-        <li><a href="#">Converse.js 0.7.3 documentation</a> &raquo;</li> 
+        <li><a href="#">Converse.js 0.7.4 documentation</a> &raquo;</li> 
       </ul>
     </div>
 <section id="main_content" class="inner">  
@@ -1045,7 +1045,7 @@ The query string will be included in the request with <tt class="docutils litera
         <li class="right" style="margin-right: 10px">
           <a href="genindex.html" title="General Index"
              >index</a></li>
-        <li><a href="#">Converse.js 0.7.3 documentation</a> &raquo;</li> 
+        <li><a href="#">Converse.js 0.7.4 documentation</a> &raquo;</li> 
       </ul>
     </div>
 </div>

+ 1 - 1
docs/html/objects.inv

@@ -1,6 +1,6 @@
 # Sphinx inventory version 2
 # Project: Converse.js
-# Version: 0.7.3
+# Version: 0.7.4
 # The remainder of this file is compressed using zlib.
 xÚmÎÁ
 à à{Ÿ"°³ƒ]÷;

+ 5 - 5
docs/html/search.html

@@ -7,7 +7,7 @@
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     
-    <title>Search &mdash; Converse.js 0.7.3 documentation</title>
+    <title>Search &mdash; Converse.js 0.7.4 documentation</title>
     
     <link rel="stylesheet" href="_static/stylesheet.css" type="text/css" />
     <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -15,7 +15,7 @@
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
         URL_ROOT:    '',
-        VERSION:     '0.7.3',
+        VERSION:     '0.7.4',
         COLLAPSE_INDEX: false,
         FILE_SUFFIX: '.html',
         HAS_SOURCE:  true
@@ -25,7 +25,7 @@
     <script type="text/javascript" src="_static/underscore.js"></script>
     <script type="text/javascript" src="_static/doctools.js"></script>
     <script type="text/javascript" src="_static/searchtools.js"></script>
-    <link rel="top" title="Converse.js 0.7.3 documentation" href="index.html" />
+    <link rel="top" title="Converse.js 0.7.4 documentation" href="index.html" />
   <script type="text/javascript">
     jQuery(function() { Search.loadIndex("searchindex.js"); });
   </script>
@@ -55,7 +55,7 @@
         <li class="right" style="margin-right: 10px">
           <a href="genindex.html" title="General Index"
              accesskey="I">index</a></li>
-        <li><a href="index.html">Converse.js 0.7.3 documentation</a> &raquo;</li> 
+        <li><a href="index.html">Converse.js 0.7.4 documentation</a> &raquo;</li> 
       </ul>
     </div>
 <section id="main_content" class="inner">  
@@ -100,7 +100,7 @@
         <li class="right" style="margin-right: 10px">
           <a href="genindex.html" title="General Index"
              >index</a></li>
-        <li><a href="index.html">Converse.js 0.7.3 documentation</a> &raquo;</li> 
+        <li><a href="index.html">Converse.js 0.7.4 documentation</a> &raquo;</li> 
       </ul>
     </div>
 </div>

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
docs/html/searchindex.js


+ 2 - 2
docs/source/conf.py

@@ -48,9 +48,9 @@ copyright = u'2013, JC Brand'
 # built documents.
 #
 # The short X.Y version.
-version = '0.7.3'
+version = '0.7.4'
 # The full version, including alpha/beta/rc tags.
-release = '0.7.3'
+release = '0.7.4'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.

+ 1 - 1
index.html

@@ -4,7 +4,7 @@
     <meta charset='utf-8' />
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
-    <meta name="description" content="Converse.js: Open Source Browser-Based Instant Messaging" />
+    <meta name="description" content="Converse.js: A chat client for your website" />
     <link rel="stylesheet" type="text/css" media="screen" href="stylesheets/stylesheet.css">
     <link rel="stylesheet" type="text/css" media="screen" href="converse.css">
     <script data-main="main" src="components/requirejs/require.js"></script>

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "converse.js",
-  "version": "0.7.3",
+  "version": "0.7.4",
   "description": "Browser based XMPP instant messaging client",
   "main": "main.js",
   "directories": {

+ 70 - 14
spec/chatbox.js

@@ -465,42 +465,99 @@
                         var view = this.chatboxviews.get(contact_jid);
                         var message = 'This message is sent from this chatbox';
                         spyOn(view, 'sendMessage').andCallThrough();
-                        view.$el.find('.chat-textarea').text(message);
-                        view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+                        utils.sendMessage(view, message);
                         expect(view.sendMessage).toHaveBeenCalled();
                         expect(view.model.messages.length, 2);
+                        expect(converse.emit.callCount).toEqual(3);
                         expect(converse.emit.mostRecentCall.args, ['onMessageSend', message]);
-                        var txt = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content').text();
-                        expect(txt).toEqual(message);
+                        expect(view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content').text()).toEqual(message);
                     }.bind(converse));
                 }, converse));
 
-                it("are sanitized to prevent Javascript injection attacks", $.proxy(function () {
+                it("is sanitized to prevent Javascript injection attacks", $.proxy(function () {
                     var contact_jid = mock.cur_names[0].replace(' ','.').toLowerCase() + '@localhost';
                     utils.openChatBoxFor(contact_jid);
                     var view = this.chatboxviews.get(contact_jid);
-                    var message = 'This message contains <b>markup</b>';
+                    var message = '<p>This message contains <em>some</em> <b>markup</b></p>';
                     spyOn(view, 'sendMessage').andCallThrough();
-                    view.$el.find('.chat-textarea').text(message);
-                    view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+                    utils.sendMessage(view, message);
                     expect(view.sendMessage).toHaveBeenCalled();
-                    var txt = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content').text();
-                    expect(txt).toEqual(message);
+                    var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content');
+                    expect(msg.text()).toEqual(message);
+                    expect(msg.html()).toEqual('&lt;p&gt;This message contains &lt;em&gt;some&lt;/em&gt; &lt;b&gt;markup&lt;/b&gt;&lt;/p&gt;');
+                }, converse));
+
+                it("can contain hyperlinks, which will be clickable", $.proxy(function () {
+                    var contact_jid = mock.cur_names[0].replace(' ','.').toLowerCase() + '@localhost';
+                    utils.openChatBoxFor(contact_jid);
+                    var view = this.chatboxviews.get(contact_jid);
+                    var message = 'This message contains a hyperlink: www.opkode.com';
+                    spyOn(view, 'sendMessage').andCallThrough();
+                    utils.sendMessage(view, message);
+                    expect(view.sendMessage).toHaveBeenCalled();
+                    var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content');
+                    expect(msg.text()).toEqual(message);
+                    expect(msg.html()).toEqual('This message contains a hyperlink: <a target="_blank" href="http://www.opkode.com">www.opkode.com</a>');
+                }, converse));
+
+                it("will have properly escaped URLs", $.proxy(function () {
+                    var contact_jid = mock.cur_names[0].replace(' ','.').toLowerCase() + '@localhost';
+                    utils.openChatBoxFor(contact_jid);
+                    var view = this.chatboxviews.get(contact_jid);
+                    spyOn(view, 'sendMessage').andCallThrough();
+
+                    var message = "http://www.opkode.com/'onmouseover='alert(1)'whatever";
+                    utils.sendMessage(view, message);
+                    expect(view.sendMessage).toHaveBeenCalled();
+                    var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content');
+                    expect(msg.text()).toEqual(message);
+                    expect(msg.html()).toEqual('<a target="_blank" href="http://www.opkode.com/%27onmouseover=%27alert%281%29%27whatever">http://www.opkode.com/\'onmouseover=\'alert(1)\'whatever</a>');
+
+                    message = 'http://www.opkode.com/"onmouseover="alert(1)"whatever';
+                    utils.sendMessage(view, message);
+                    expect(view.sendMessage).toHaveBeenCalled();
+                    msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content');
+                    expect(msg.text()).toEqual(message);
+                    expect(msg.html()).toEqual('<a target="_blank" href="http://www.opkode.com/%22onmouseover=%22alert%281%29%22whatever">http://www.opkode.com/"onmouseover="alert(1)"whatever</a>');
+
+                    message = "https://en.wikipedia.org/wiki/Ender's_Game";
+                    utils.sendMessage(view, message);
+                    expect(view.sendMessage).toHaveBeenCalled();
+                    msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content');
+                    expect(msg.text()).toEqual(message);
+                    expect(msg.html()).toEqual('<a target="_blank" href="https://en.wikipedia.org/wiki/Ender%27s_Game">https://en.wikipedia.org/wiki/Ender\'s_Game</a>');
+
+                    message = "https://en.wikipedia.org/wiki/Ender%27s_Game";
+                    utils.sendMessage(view, message);
+                    expect(view.sendMessage).toHaveBeenCalled();
+                    msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content');
+                    expect(msg.text()).toEqual(message);
+                    expect(msg.html()).toEqual('<a target="_blank" href="https://en.wikipedia.org/wiki/Ender%27s_Game">https://en.wikipedia.org/wiki/Ender%27s_Game</a>');
                 }, converse));
 
             }, converse));
         }, converse));
 
         describe("Special Messages", $.proxy(function () {
+            beforeEach(function () {
+                utils.closeAllChatBoxes();
+                utils.removeControlBox();
+                converse.roster.localStorage._clear();
+                utils.initConverse();
+                utils.createCurrentContacts();
+                utils.openControlBox();
+                utils.openContactsPanel();
+            });
+
             it("'/clear' can be used to clear messages in a conversation", $.proxy(function () {
                 spyOn(converse, 'emit');
                 var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
+                utils.openChatBoxFor(contact_jid);
                 var view = this.chatboxviews.get(contact_jid);
                 var message = 'This message is another sent from this chatbox';
                 // Lets make sure there is at least one message already
                 // (e.g for when this test is run on its own).
-                view.$el.find('.chat-textarea').val(message).text(message);
-                view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+                utils.sendMessage(view, message);
                 expect(view.model.messages.length > 0).toBeTruthy();
                 expect(view.model.messages.localStorage.records.length > 0).toBeTruthy();
                 expect(converse.emit).toHaveBeenCalledWith('onMessageSend', message);
@@ -508,8 +565,7 @@
                 message = '/clear';
                 var old_length = view.model.messages.length;
                 spyOn(view, 'sendMessage').andCallThrough();
-                view.$el.find('.chat-textarea').val(message).text(message);
-                view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+                utils.sendMessage(view, message);
                 expect(view.sendMessage).toHaveBeenCalled();
                 expect(view.model.messages.length, 0); // The messages must be removed from the modal
                 expect(view.model.messages.localStorage.records.length, 0); // And also from localStorage

+ 2 - 2
src/build.js

@@ -33,8 +33,8 @@
         "bigint": "src/bigint",
         "crypto.core": "components/otr/vendor/cryptojs/core",
         "crypto.enc-base64": "components/otr/vendor/cryptojs/enc-base64",
-        "crypto.md5": "components/crypto-js/src/md5",
-        "crypto.evpkdf": "components/crypto-js/src/evpkdf",
+        "crypto.md5": "components/crypto-js-evanvosberg/src/md5",
+        "crypto.evpkdf": "components/crypto-js-evanvosberg/src/evpkdf",
         "crypto.cipher-core": "components/otr/vendor/cryptojs/cipher-core",
         "crypto.aes": "components/otr/vendor/cryptojs/aes",
         "crypto.sha1": "components/otr/vendor/cryptojs/sha1",

+ 1 - 1
tests.html

@@ -3,7 +3,7 @@
 <html>
 <head>
     <title>Converse.js Tests</title>
-    <meta name="description" content="Converse.js: Open Source Browser-Based Instant Messaging" />
+    <meta name="description" content="Converse.js: A chat client for your website" />
     <link rel="shortcut icon" type="image/png" href="components/jasmine/images/jasmine_favicon.png">
     <link rel="stylesheet" type="text/css" href="components/jasmine/src/html/jasmine.css">
     <link rel="stylesheet" type="text/css" media="screen" href="stylesheets/stylesheet.css">

+ 5 - 0
tests/utils.js

@@ -110,5 +110,10 @@
         }
         return this;
     };
+
+    utils.sendMessage = function (chatboxview, message) {
+        chatboxview.$el.find('.chat-textarea').val(message);
+        chatboxview.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
+    };
     return utils;
 }));

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.