Merge branch 'master' into 0.8

Conflicts:
	bower.json
	converse.js
	docs/CHANGES.rst
	spec/chatbox.js
	tests/utils.js
	tests_main.js
This commit is contained in:
JC Brand 2014-03-09 06:02:38 +02:00
commit 9849daacf9
19 changed files with 124 additions and 50 deletions

View File

@ -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",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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({

View File

@ -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)
------------------

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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ÎÁ
à à{Ÿ"°³ƒ]÷;

View File

@ -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>

File diff suppressed because one or more lines are too long

View File

@ -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.

View File

@ -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>

View File

@ -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": {

View File

@ -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

View File

@ -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",

View File

@ -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">

View File

@ -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;
}));