diff --git a/docs/CHANGES.md b/docs/CHANGES.md index fdedbe6d8..3323e96d2 100755 --- a/docs/CHANGES.md +++ b/docs/CHANGES.md @@ -8,6 +8,7 @@ - Chat bot messages don't appear when they have the same ids as their commands. [jcbrand] - Updated onDisconnected method to fire disconnected event even if auto_reconnect is false. [kamranzafar] +- #553 Add processing hints to OTR messages [jcbrand] ## 1.0.2 (2016-05-24) diff --git a/spec/chatbox.js b/spec/chatbox.js index ddf7091f7..3eee773b1 100644 --- a/spec/chatbox.js +++ b/spec/chatbox.js @@ -934,24 +934,6 @@ }.bind(converse)); - describe("An OTR Chat Message", function () { - - it("will not be carbon copied when it's sent out", function () { - var msgtext = "?OTR,1,3,?OTR:AAIDAAAAAAEAAAABAAAAwCQ8HKsag0y0DGKsneo0kzKu1ua5L93M4UKTkCf1I2kbm2RgS5kIxDTxrTj3wVRB+H5Si86E1fKtuBgsDf/bKkGTM0h/49vh5lOD9HkE8cnSrFEn5GN,"; - var sender_jid = mock.cur_names[3].replace(/ /g,'.').toLowerCase() + '@localhost'; - converse_api.chats.open(sender_jid); - var chatbox = converse.chatboxes.get(sender_jid); - spyOn(converse.connection, 'send'); - chatbox.set('otr_status', 1); // Set OTR status to UNVERIFIED, to mock an encrypted session - chatbox.trigger('sendMessage', new converse.Message({ message: msgtext })); - var $sent = $(converse.connection.send.argsForCall[0][0].tree()); - expect($sent.find('body').siblings('private').length).toBe(1); - expect($sent.find('private').length).toBe(1); - expect($sent.find('private').attr('xmlns')).toBe('urn:xmpp:carbons:2'); - chatbox.set('otr_status', 0); // Reset again to UNENCRYPTED - }); - }); - describe("A Chat Status Notification", function () { it("does not open automatically if a chat state notification is received", function () { diff --git a/spec/otr.js b/spec/otr.js index ada2c7a3e..ae7c40f3a 100644 --- a/spec/otr.js +++ b/spec/otr.js @@ -9,9 +9,15 @@ } ); } (this, function ($, mock, test_utils) { + var Strophe = converse_api.env.Strophe; var b64_sha1 = converse_api.env.b64_sha1; return describe("The OTR module", function() { + beforeEach(function () { + test_utils.openControlBox(); + test_utils.openContactsPanel(); + test_utils.createContacts('current'); + }); it("can store a session passphrase in session storage", function () { // With no prebind, the user's XMPP password is used and nothing is @@ -33,5 +39,39 @@ converse.authentication = auth; converse.connection.pass = pass; }); + + it("will add processing hints to sent out encrypted stanzas", function () { + var UNVERIFIED = 1, UNENCRYPTED = 0; + var contact_name = mock.cur_names[0]; + var contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost'; + test_utils.openChatBoxFor(contact_jid); + var chatview = converse.chatboxviews.get(contact_jid); + chatview.model.set('otr_status', UNVERIFIED); + var stanza = chatview.createMessageStanza(new converse.Message({ message: 'hello world'})); + var $hints = $(stanza.nodeTree).find('[xmlns="'+Strophe.NS.HINTS+'"]'); + expect($hints.length).toBe(3); + expect($hints.get(0).tagName).toBe('no-store'); + expect($hints.get(1).tagName).toBe('no-permanent-store'); + expect($hints.get(2).tagName).toBe('no-copy'); + chatview.model.set('otr_status', UNENCRYPTED); // Reset again to UNENCRYPTED + }); + + describe("An OTR Chat Message", function () { + + it("will not be carbon copied when it's sent out", function () { + var msgtext = "?OTR,1,3,?OTR:AAIDAAAAAAEAAAABAAAAwCQ8HKsag0y0DGKsneo0kzKu1ua5L93M4UKTkCf1I2kbm2RgS5kIxDTxrTj3wVRB+H5Si86E1fKtuBgsDf/bKkGTM0h/49vh5lOD9HkE8cnSrFEn5GN,"; + var sender_jid = mock.cur_names[3].replace(/ /g,'.').toLowerCase() + '@localhost'; + converse_api.chats.open(sender_jid); + var chatbox = converse.chatboxes.get(sender_jid); + spyOn(converse.connection, 'send'); + chatbox.set('otr_status', 1); // Set OTR status to UNVERIFIED, to mock an encrypted session + chatbox.trigger('sendMessage', new converse.Message({ message: msgtext })); + var $sent = $(converse.connection.send.argsForCall[0][0].tree()); + expect($sent.find('body').siblings('private').length).toBe(1); + expect($sent.find('private').length).toBe(1); + expect($sent.find('private').attr('xmlns')).toBe('urn:xmpp:carbons:2'); + chatbox.set('otr_status', 0); // Reset again to UNENCRYPTED + }); + }); }); })); diff --git a/src/converse-core.js b/src/converse-core.js index 91aadb005..3c2629549 100755 --- a/src/converse-core.js +++ b/src/converse-core.js @@ -151,6 +151,7 @@ Strophe.addNamespace('ROSTERX', 'http://jabber.org/protocol/rosterx'); Strophe.addNamespace('XFORM', 'jabber:x:data'); Strophe.addNamespace('NICK', 'http://jabber.org/protocol/nick'); + Strophe.addNamespace('HINTS', 'urn:xmpp:hints'); // Instance level constants this.TIMEOUTS = { // Set as module attr so that we can override in tests. diff --git a/src/converse-otr.js b/src/converse-otr.js index c48d87b33..675ce9315 100644 --- a/src/converse-otr.js +++ b/src/converse-otr.js @@ -298,7 +298,10 @@ var stanza = this._super.createMessageStanza.apply(this, arguments); if (this.model.get('otr_status') !== UNENCRYPTED) { // OTR messages aren't carbon copied - stanza.c('private', {'xmlns': Strophe.NS.CARBONS}); + stanza.c('private', {'xmlns': Strophe.NS.CARBONS}).up() + .c('no-store', {'xmlns': Strophe.NS.HINTS}).up() + .c('no-permanent-store', {'xmlns': Strophe.NS.HINTS}).up() + .c('no-copy', {'xmlns': Strophe.NS.HINTS}); } return stanza; }, diff --git a/tests/utils.js b/tests/utils.js index 90b0cd863..2ca4a47a2 100644 --- a/tests/utils.js +++ b/tests/utils.js @@ -140,7 +140,7 @@ * * These contacts are not grouped. See below. */ - var names; + var names, jid; if (type === 'requesting') { names = mock.req_names; subscription = 'none'; @@ -167,13 +167,16 @@ length = names.length; } for (i=0; i