changeset 530:1735aaeac652

plugin OTR: forces FINISHED state if we are in ENCRYPTED state on contact disconnection
author souliane <souliane@mailoo.org>
date Fri, 05 Sep 2014 11:53:55 +0200
parents 9bfd71e2b35c
children 793f12d1f970
files src/browser/libervia_main.py src/browser/sat_browser/otrjs_wrapper.py src/browser/sat_browser/plugin_sec_otr.py
diffstat 3 files changed, 57 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/browser/libervia_main.py	Fri Sep 05 11:41:40 2014 +0200
+++ b/src/browser/libervia_main.py	Fri Sep 05 11:53:55 2014 +0200
@@ -747,6 +747,10 @@
                 self.status_panel.setStatus(statuses.values()[0])  # pylint: disable=E1103
         else:
             self.contact_panel.setConnected(entity_jid.bare, entity_jid.resource, show, priority, statuses)
+            if show == 'unavailable':  # XXX: save some resources as for now we only need 'unavailable'
+                for plugin in self.plugins.values():
+                    if hasattr(plugin, 'presenceReceivedTrigger'):
+                        plugin.presenceReceivedTrigger(entity_jid, show, priority, statuses)
 
     def _roomJoinedCb(self, room_jid, room_nicks, user_nick):
         _target = jid.JID(room_jid)
--- a/src/browser/sat_browser/otrjs_wrapper.py	Fri Sep 05 11:41:40 2014 +0200
+++ b/src/browser/sat_browser/otrjs_wrapper.py	Fri Sep 05 11:53:55 2014 +0200
@@ -130,6 +130,10 @@
         def disconnect(self):
             self.otr.endOtr()
 
+        def finish(self):
+            """Finish the session - avoid to send any message and the user has to manually disconnect"""
+            self.otr.handleTLVs('\x00\x00\x01\x00\x00')
+
         def receiveMessage(self, msg):
             """Received a message, ask otr.js to (try to) decrypt it"""
             self.otr.receiveMsg(msg)
--- a/src/browser/sat_browser/plugin_sec_otr.py	Fri Sep 05 11:41:40 2014 +0200
+++ b/src/browser/sat_browser/plugin_sec_otr.py	Fri Sep 05 11:53:55 2014 +0200
@@ -42,7 +42,7 @@
 AUTH_QUEST_DEF = D_("<i>To authenticate using a question, pick a question whose answer is known only to you and your correspondent. Enter this question and this answer, then wait for your correspondent to enter the answer too. If the answers don't match, then you may be talking to an imposter.</i>{eol}{eol}").format(eol=DIALOG_EOL)
 AUTH_QUEST_ASK = D_("<i>Your correspondent is attempting to determine if he or she is really talking to you, or if it's someone pretending to be you. Your correspondent has asked a question, indicated below. To authenticate to your correspondent, enter the answer and click OK.</i>{eol}{eol}").format(eol=DIALOG_EOL)
 AUTH_SECRET_TXT = D_("{eol}{eol}Enter secret answer here: (case sensitive){eol}").format(eol=DIALOG_EOL)
-FEEDBACK_NOT_PRIVATE = D_("You haven't started any private conversation with %s yet.")
+FEEDBACK_NOT_PRIVATE = D_("Your conversation with %s is not encrypted.")
 
 DROP_TXT = D_("You private key is used to encrypt messages for your correspondent, nobody except you must know it, if you are in doubt, you should drop it!{eol}{eol}Are you sure you want to drop your private key?").format(eol=DIALOG_EOL)
 
@@ -225,6 +225,11 @@
         if self.state != otr.context.STATE_PLAINTEXT:
             super(Context, self).disconnect()
 
+    def finish(self):
+        """Finish the session - avoid to send any message but the user still has to end the session himself."""
+        if self.state == otr.context.STATE_ENCRYPTED:
+            super(Context, self).finish()
+
 
 class Account(otr.context.Account):
 
@@ -266,9 +271,15 @@
             self.contexts[other_jid] = Context(self.host, self.account, other_jid)
         return self.contexts[other_jid]
 
-    def getContextForUser(self, other, create=True):
-        log.debug(u"getContextForUser [%s]" % other)
-        if not other.resource:
+    def getContextForUser(self, other_jid, start=True):
+        """Get the context for the given JID
+
+        @param other_jid (JID): your correspondent
+        @param start (bool): start non-existing context if True
+        @return: Context
+        """
+        log.debug(u"getContextForUser [%s]" % other_jid)
+        if not other_jid.resource:
             log.error("getContextForUser called with a bare jid")
         if start:
             return self.startContext(other_jid)
@@ -351,6 +362,39 @@
             cb(to_jid)
         return False  # interrupt the main process
 
+    def presenceReceivedTrigger(self, entity, show, priority, statuses):
+        if show == "unavailable":
+            self.endSession(entity, finish=True)
+        return True
+
+    def endSession(self, other_jid, profile, finish=False):
+        """Finish or disconnect an OTR session
+
+        @param other_jid (JID): str
+        @param finish: if True, finish the session but do not disconnect it
+        @return: True if the session has been finished or disconnected, False if there was nothing to do
+        """
+        def cb(other_jid):
+            def not_available():
+                if not finish:
+                    self.host.newMessageCb(other_jid, FEEDBACK_NOT_PRIVATE % other_jid.full(), "headline", self.host.whoami, {})
+
+            priv_key = self.context_manager.account.privkey
+            if priv_key is None:
+                not_available()
+                return
+
+            otrctx = self.context_manager.getContextForUser(other_jid, start=False)
+            if otrctx is None:
+                not_available()
+                return
+            if finish:
+                otrctx.finish()
+            else:
+                otrctx.disconnect()
+
+        self.fixResource(other_jid, cb)
+
     # Menu callbacks
 
     def _startRefresh(self, menu_data):
@@ -374,26 +418,12 @@
 
         @param menu_data: %(menu_data)s
         """
-        def cb(other_jid):
-            def not_available():
-                self.host.newMessageCb(other_jid, FEEDBACK_NOT_PRIVATE % other_jid.full(), "headline", self.host.whoami, {})
-
-            priv_key = self.context_manager.account.privkey
-            if priv_key is None:
-                not_available()
-                return
-
-            otrctx = self.context_manager.getContextForUser(other_jid, create=False)
-            if otrctx is None:
-                not_available()
-                return
-            otrctx.disconnect()
         try:
             other_jid = menu_data['jid']
-            self.fixResource(other_jid, cb)
         except KeyError:
             log.error(_("jid key is not present !"))
             return None
+        self.endSession(other_jid)
 
     def _authenticate(self, menu_data, profile):
         """Authenticate other user and see our own fingerprint
@@ -461,4 +491,3 @@
         except KeyError:
             log.error(_("jid key is not present !"))
             return None
-