[Git][gajim/gajim][master] 10 commits: Remove unnecessary event classes

Philipp Hörist gitlab at dev.gajim.org
Fri Jan 4 00:14:06 CET 2019


Philipp Hörist pushed to branch master at gajim / gajim


Commits:
371756c2 by Philipp Hörist at 2019-01-03T08:06:44Z
Remove unnecessary event classes

- - - - -
1399c41d by Philipp Hörist at 2019-01-03T08:06:49Z
Remove old dbus module

We now use Gio DBus

- - - - -
f3d5babc by Philipp Hörist at 2019-01-03T09:19:25Z
Register handlers in CommonConnection class

- - - - -
0441ccd4 by Philipp Hörist at 2019-01-03T09:19:29Z
Move 'agent-removed' handler into Gateway module

- - - - -
b05f0e14 by Philipp Hörist at 2019-01-03T09:19:53Z
Move methods into Connection class

- - - - -
eb9f340a by Philipp Hörist at 2019-01-03T09:41:22Z
Remove star imports

- - - - -
4631f503 by Philipp Hörist at 2019-01-03T09:46:31Z
Remove unused code

- - - - -
c0fb6453 by Philipp Hörist at 2019-01-03T10:25:45Z
Move MUC message logging into message module

- - - - -
cdb37828 by Philipp Hörist at 2019-01-03T10:52:26Z
Move message error handler into message module

- - - - -
b6003286 by Philipp Hörist at 2019-01-03T23:11:28Z
Refactor message handlers

- Adapt to nbxmpp now unwraping MAM messages
- Use nbxmpp properties
- Save message-id to database

- - - - -


16 changed files:

- gajim/common/connection.py
- gajim/common/connection_handlers.py
- gajim/common/connection_handlers_events.py
- − gajim/common/dbus_support.py
- gajim/common/logger.py
- gajim/common/modules/gateway.py
- gajim/common/modules/mam.py
- gajim/common/modules/message.py
- gajim/common/modules/util.py
- gajim/common/zeroconf/client_zeroconf.py
- gajim/common/zeroconf/connection_handlers_zeroconf.py
- gajim/common/zeroconf/connection_zeroconf.py
- gajim/gtk/features.py
- gajim/gtk/themes.py
- gajim/gui_interface.py
- gajim/session.py


Changes:

=====================================
gajim/common/connection.py
=====================================
@@ -58,10 +58,22 @@ from gajim.common import app
 from gajim.common import gpg
 from gajim.common import passwords
 from gajim.common import idle
+from gajim.common import modules
+from gajim.common import ged
+from gajim.common.nec import NetworkEvent
 from gajim.common.i18n import _
-from gajim.common.connection_handlers import *
 from gajim.common.contacts import GC_Contact
-from gajim.common import modules
+from gajim.common.connection_handlers import ConnectionHandlers
+from gajim.common.connection_handlers_events import OurShowEvent
+from gajim.common.connection_handlers_events import BadGPGPassphraseEvent
+from gajim.common.connection_handlers_events import GPGPasswordRequiredEvent
+from gajim.common.connection_handlers_events import InformationEvent
+from gajim.common.connection_handlers_events import StanzaMessageOutgoingEvent
+from gajim.common.connection_handlers_events import GcStanzaMessageOutgoingEvent
+from gajim.common.connection_handlers_events import ConnectionLostEvent
+from gajim.common.connection_handlers_events import NewAccountConnectedEvent
+from gajim.common.connection_handlers_events import NewAccountNotConnectedEvent
+from gajim.common.connection_handlers_events import MessageSentEvent
 
 
 log = logging.getLogger('gajim.c.connection')
@@ -100,16 +112,15 @@ class CommonConnection:
         self.time_to_reconnect = None
         self._reconnect_timer_source = None
 
+        # If handlers have been registered
+        self.handlers_registered = False
+
         self.pep = {}
         # Do we continue connection when we get roster (send presence,get vcard..)
         self.continue_connect_info = None
 
         # Remember where we are in the register agent process
         self.agent_registrations = {}
-        # To know the groupchat jid associated with a stanza ID. Useful to
-        # request vcard or os info... to a real JID but act as if it comes from
-        # the fake jid
-        self.groupchat_jids = {} # {ID : groupchat_jid}
 
         self.roster_supported = True
         self.addressing_supported = False
@@ -123,6 +134,24 @@ class CommonConnection:
 
         self.get_config_values_or_default()
 
+    def _register_new_handlers(self, con):
+        for handler in modules.get_handlers(self):
+            if len(handler) == 5:
+                name, func, typ, ns, priority = handler
+                con.RegisterHandler(name, func, typ, ns, priority=priority)
+            else:
+                con.RegisterHandler(*handler)
+        self.handlers_registered = True
+
+    def _unregister_new_handlers(self, con):
+        if not con:
+            return
+        for handler in modules.get_handlers(self):
+            if len(handler) > 4:
+                handler = handler[:4]
+            con.UnregisterHandler(*handler)
+        self.handlers_registered = False
+
     def _compute_resource(self):
         resource = app.config.get_per('accounts', self.name, 'resource')
         # All valid resource substitution strings should be added to this hash.
@@ -421,11 +450,15 @@ class CommonConnection:
     def _event_dispatcher(self, realm, event, data):
         if realm == '':
             if event == 'STANZA RECEIVED':
-                app.nec.push_incoming_event(StanzaReceivedEvent(
-                    None, conn=self, stanza_str=str(data)))
+                app.nec.push_incoming_event(
+                    NetworkEvent('stanza-received',
+                                 conn=self,
+                                 stanza_str=str(data)))
             elif event == 'DATA SENT':
-                app.nec.push_incoming_event(StanzaSentEvent(
-                    None, conn=self, stanza_str=str(data)))
+                app.nec.push_incoming_event(
+                    NetworkEvent('stanza-sent',
+                                 conn=self,
+                                 stanza_str=str(data)))
 
     def change_status(self, show, msg, auto=False):
         if not msg:
@@ -479,6 +512,7 @@ class CommonConnection:
                 self._change_from_invisible()
             self._update_status(show, msg, idle_time=idle_time)
 
+
 class Connection(CommonConnection, ConnectionHandlers):
     def __init__(self, name):
         CommonConnection.__init__(self, name)
@@ -536,9 +570,7 @@ class Connection(CommonConnection, ConnectionHandlers):
     # END __init__
 
     def cleanup(self):
-        ConnectionHandlers.cleanup(self)
         modules.unregister(self)
-
         app.ged.remove_event_handler('message-outgoing', ged.OUT_CORE,
             self._nec_message_outgoing)
         app.ged.remove_event_handler('gc-message-outgoing', ged.OUT_CORE,
@@ -653,7 +685,7 @@ class Connection(CommonConnection, ConnectionHandlers):
         app.proxy65_manager.disconnect(self.connection)
         self.terminate_sessions()
         self.remove_all_transfers()
-        ConnectionHandlers._unregister_handlers(self)
+        self._unregister_new_handlers(self.connection)
         self.connection = None
 
     def _set_reconnect_timer(self):
@@ -732,8 +764,8 @@ class Connection(CommonConnection, ConnectionHandlers):
                         reason = _('Server %(name)s answered wrongly to '
                             'register request: %(error)s') % {'name': data[0],
                             'error': data[3]}
-                        app.nec.push_incoming_event(AccountNotCreatedEvent(
-                            None, conn=self, reason=reason))
+                        app.nec.push_incoming_event(NetworkEvent(
+                            'account-not-created', conn=self, reason=reason))
                         return
                     is_form = data[2]
                     conf = data[1]
@@ -743,15 +775,16 @@ class Connection(CommonConnection, ConnectionHandlers):
                         def _on_register_result(result):
                             if not nbxmpp.isResultNode(result):
                                 reason = result.getErrorMsg() or result.getError()
-                                app.nec.push_incoming_event(AccountNotCreatedEvent(
-                                    None, conn=self, reason=reason))
+                                app.nec.push_incoming_event(NetworkEvent(
+                                    'account-not-created', conn=self, reason=reason))
                                 return
                             if app.is_installed('GPG'):
                                 self.USE_GPG = True
                                 self.gpg = gpg.GnuPG()
                             app.nec.push_incoming_event(
-                                AccountCreatedEvent(None, conn=self,
-                                account_info=self.new_account_info))
+                                NetworkEvent('account-created',
+                                             conn=self,
+                                             account_info=self.new_account_info))
                             self.new_account_info = None
                             self.new_account_form = None
                             if self.connection:
@@ -773,8 +806,8 @@ class Connection(CommonConnection, ConnectionHandlers):
                                 # requested config has changed since first connection
                                 reason = _('Server %s provided a different '
                                     'registration form') % data[0]
-                                app.nec.push_incoming_event(AccountNotCreatedEvent(
-                                    None, conn=self, reason=reason))
+                                app.nec.push_incoming_event(NetworkEvent(
+                                    'account-not-created', conn=self, reason=reason))
                                 return
                             nbxmpp.features_nb.register(self.connection,
                                     self._hostname, self.new_account_form,
@@ -1039,9 +1072,12 @@ class Connection(CommonConnection, ConnectionHandlers):
 
         if self.client_cert and app.config.get_per('accounts', self.name,
         'client_cert_encrypted'):
-            app.nec.push_incoming_event(ClientCertPassphraseEvent(
-                None, conn=self, con=con, port=port,
-                secure_tuple=secure_tuple))
+            app.nec.push_incoming_event(
+                NetworkEvent('client-cert-passphrase',
+                             conn=self,
+                             con=con,
+                             port=port,
+                             secure_tuple=secure_tuple))
             return
         self.on_client_cert_passphrase('', con, port, secure_tuple)
 
@@ -1115,8 +1151,10 @@ class Connection(CommonConnection, ConnectionHandlers):
         con.RegisterDisconnectHandler(self.disconnect)
         if _con_type == 'plain' and app.config.get_per('accounts', self.name,
         'action_when_plaintext_connection') == 'warn':
-            app.nec.push_incoming_event(PlainConnectionEvent(None, conn=self,
-                xmpp_client=con))
+            app.nec.push_incoming_event(
+                NetworkEvent('plain-connection',
+                             conn=self,
+                             xmpp_client=con))
             return True
         if _con_type == 'plain' and app.config.get_per('accounts', self.name,
         'action_when_plaintext_connection') == 'disconnect':
@@ -1129,8 +1167,11 @@ class Connection(CommonConnection, ConnectionHandlers):
         'warn_when_insecure_ssl_connection') and \
         not self.connection_auto_accepted:
             # Pyopenssl is not used
-            app.nec.push_incoming_event(InsecureSSLConnectionEvent(None,
-                conn=self, xmpp_client=con, conn_type=_con_type))
+            app.nec.push_incoming_event(
+                NetworkEvent('insecure-ssl-connection',
+                             conn=self,
+                             xmpp_client=con,
+                             conn_type=_con_type))
             return True
         return self.connection_accepted(con, con_type)
 
@@ -1187,9 +1228,11 @@ class Connection(CommonConnection, ConnectionHandlers):
                 self.process_ssl_errors()
                 return
 
-        app.nec.push_incoming_event(SSLErrorEvent(None, conn=self,
-                                                  error_num=errnum,
-                                                  cert=cert))
+        app.nec.push_incoming_event(
+            NetworkEvent('ssl-error',
+                         conn=self,
+                         error_num=errnum,
+                         cert=cert))
 
     @staticmethod
     def _calculate_cert_sha256(cert):
@@ -1286,8 +1329,8 @@ class Connection(CommonConnection, ConnectionHandlers):
         if self.password is not None:
             on_password(self.password)
         else:
-            app.nec.push_incoming_event(PasswordRequiredEvent(
-                None, conn=self, on_password=on_password))
+            app.nec.push_incoming_event(NetworkEvent(
+                'password-required', conn=self, on_password=on_password))
 
     def _auth(self):
         self._register_handlers(self.connection, self._current_type)
@@ -1311,8 +1354,11 @@ class Connection(CommonConnection, ConnectionHandlers):
         app.con_types[self.name] = con_type
         # notify the gui about con_type
         app.nec.push_incoming_event(
-            ConnectionTypeEvent(None, conn=self, connection_type=con_type))
+            NetworkEvent('connection-type',
+                         conn=self,
+                         connection_type=con_type))
         ConnectionHandlers._register_handlers(self, con, con_type)
+        self._register_new_handlers(con)
 
     def _on_auth_successful(self):
         if self._unregister_account:
@@ -1365,8 +1411,11 @@ class Connection(CommonConnection, ConnectionHandlers):
             app.config.set_per('accounts', self.name,
                                'name', self.connection.User)
             new_jid = app.get_jid_from_account(self.name)
-            app.nec.push_incoming_event(AnonymousAuthEvent(
-                None, conn=self, old_jid=old_jid, new_jid=new_jid))
+            app.nec.push_incoming_event(
+                NetworkEvent('anonymous-auth',
+                             conn=self,
+                             old_jid=old_jid,
+                             new_jid=new_jid))
 
         self.connected = 2
         self.retrycount = 0
@@ -1447,7 +1496,7 @@ class Connection(CommonConnection, ConnectionHandlers):
             self.get_module('Blocking').get_blocking_list()
 
             # Inform GUI we just signed in
-            app.nec.push_incoming_event(SignedInEvent(None, conn=self))
+            app.nec.push_incoming_event(NetworkEvent('signed-in', conn=self))
 
     def get_signed_presence(self, msg, callback=None):
         if app.config.get_per('accounts', self.name, 'gpg_sign_presence'):
@@ -1494,6 +1543,86 @@ class Connection(CommonConnection, ConnectionHandlers):
             self.get_module('Roster').request_roster()
         elif self._connect_machine_calls == 4:
             self.send_first_presence()
+            self.discover_ft_proxies()
+
+    def discover_ft_proxies(self):
+        if not app.config.get_per('accounts', self.name, 'use_ft_proxies'):
+            return
+
+        cfg_proxies = app.config.get_per('accounts', self.name,
+            'file_transfer_proxies')
+        our_jid = helpers.parse_jid(app.get_jid_from_account(self.name) + \
+            '/' + self.server_resource)
+        testit = app.config.get_per('accounts', self.name,
+            'test_ft_proxies_on_startup')
+        if cfg_proxies:
+            proxies = [e.strip() for e in cfg_proxies.split(',')]
+            for proxy in proxies:
+                app.proxy65_manager.resolve(proxy, self.connection, our_jid,
+                    testit=testit)
+
+    def send_first_presence(self):
+        if self.connected > 1 and self.continue_connect_info:
+            msg = self.continue_connect_info[1]
+            sign_msg = self.continue_connect_info[2]
+            signed = ''
+            send_first_presence = True
+            if sign_msg:
+                signed = self.get_signed_presence(msg,
+                    self._send_first_presence)
+                if signed is None:
+                    app.nec.push_incoming_event(GPGPasswordRequiredEvent(None,
+                        conn=self, callback=self._send_first_presence))
+                    # _send_first_presence will be called when user enter
+                    # passphrase
+                    send_first_presence = False
+            if send_first_presence:
+                self._send_first_presence(signed)
+
+    def _send_first_presence(self, signed=''):
+        show = self.continue_connect_info[0]
+        msg = self.continue_connect_info[1]
+        sign_msg = self.continue_connect_info[2]
+        if sign_msg and not signed:
+            signed = self.get_signed_presence(msg)
+            if signed is None:
+                app.nec.push_incoming_event(BadGPGPassphraseEvent(None,
+                    conn=self))
+                self.USE_GPG = False
+                signed = ''
+        self.connected = app.SHOW_LIST.index(show)
+        sshow = helpers.get_xmpp_show(show)
+        # send our presence
+        if show == 'invisible':
+            self.send_invisible_presence(msg, signed, True)
+            return
+        if show not in ['offline', 'online', 'chat', 'away', 'xa', 'dnd']:
+            return
+        priority = app.get_priority(self.name, sshow)
+
+        self.get_module('Presence').send_presence(
+            priority=priority,
+            show=sshow,
+            status=msg,
+            sign=signed)
+
+        if self.connection:
+            self.priority = priority
+        app.nec.push_incoming_event(OurShowEvent(None, conn=self,
+            show=show))
+
+        if not self.avatar_conversion:
+            # ask our VCard
+            self.get_module('VCardTemp').request_vcard()
+
+        self.get_module('Bookmarks').get_bookmarks()
+        self.get_module('Annotations').get_annotations()
+        self.get_module('Blocking').get_blocking_list()
+
+        # Inform GUI we just signed in
+        app.nec.push_incoming_event(NetworkEvent('signed-in', conn=self))
+        self.get_module('PEP').send_stored_publish()
+        self.continue_connect_info = None
 
     def send_custom_status(self, show, msg, jid):
         if show not in app.SHOW_LIST:


=====================================
gajim/common/connection_handlers.py
=====================================
@@ -30,16 +30,15 @@ import operator
 import nbxmpp
 
 from gajim.common import app
-from gajim.common import ged
 from gajim.common import helpers
 from gajim.common import jingle_xtls
-from gajim.common import modules
-from gajim.common.caps_cache import muc_caps_cache
-from gajim.common.connection_handlers_events import *
-from gajim.common.const import KindConstant
 from gajim.common.jingle import ConnectionJingle
 from gajim.common.protocol.bytestream import ConnectionSocks5Bytestream
 from gajim.common.protocol.bytestream import ConnectionIBBytestream
+from gajim.common.connection_handlers_events import StreamReceivedEvent
+from gajim.common.connection_handlers_events import PresenceReceivedEvent
+from gajim.common.connection_handlers_events import StreamConflictReceivedEvent
+from gajim.common.connection_handlers_events import NotificationEvent
 
 
 log = logging.getLogger('gajim.c.connection_handlers')
@@ -53,69 +52,6 @@ class ConnectionHandlersBase:
         # IDs of sent messages (https://trac.gajim.org/ticket/8222)
         self.sent_message_ids = []
 
-        # We decrypt GPG messages one after the other. Keep queue in mem
-        self.gpg_messages_to_decrypt = []
-
-        app.ged.register_event_handler('gc-message-received', ged.CORE,
-            self._nec_gc_message_received)
-
-    def cleanup(self):
-        app.ged.remove_event_handler('gc-message-received', ged.CORE,
-            self._nec_gc_message_received)
-
-    def _check_for_mam_compliance(self, room_jid, stanza_id):
-        namespace = muc_caps_cache.get_mam_namespace(room_jid)
-        if stanza_id is None and namespace == nbxmpp.NS_MAM_2:
-            log.warning('%s announces mam:2 without stanza-id', room_jid)
-
-    def _nec_gc_message_received(self, obj):
-        if obj.conn.name != self.name:
-            return
-
-        if obj.stanza.getType() == 'error':
-            return
-
-        self._check_for_mam_compliance(obj.jid, obj.stanza_id)
-
-        if (app.config.should_log(obj.conn.name, obj.jid) and
-                obj.msgtxt and obj.nick):
-            # if not obj.nick, it means message comes from room itself
-            # usually it hold description and can be send at each connection
-            # so don't store it in logs
-            app.logger.insert_into_logs(self.name,
-                                        obj.jid,
-                                        obj.timestamp,
-                                        KindConstant.GC_MSG,
-                                        message=obj.msgtxt,
-                                        contact_name=obj.nick,
-                                        additional_data=obj.additional_data,
-                                        stanza_id=obj.stanza_id)
-            app.logger.set_room_last_message_time(obj.room_jid, obj.timestamp)
-            self.get_module('MAM').save_archive_id(
-                obj.room_jid, obj.stanza_id, obj.timestamp)
-
-    # process and dispatch an error message
-    def dispatch_error_message(self, msg, msgtxt, session, frm, tim):
-        error_msg = msg.getErrorMsg()
-
-        if not error_msg:
-            error_msg = msgtxt
-            msgtxt = None
-
-        subject = msg.getSubject()
-
-        if session.is_loggable():
-            app.logger.insert_into_logs(self.name,
-                                        nbxmpp.JID(frm).getStripped(),
-                                        tim,
-                                        KindConstant.ERROR,
-                                        message=error_msg,
-                                        subject=subject)
-
-        app.nec.push_incoming_event(MessageErrorEvent(None, conn=self,
-            fjid=frm, error_code=msg.getErrorCode(), error_msg=error_msg,
-            msg=msgtxt, time_=tim, session=session, stanza=msg))
-
     def get_sessions(self, jid):
         """
         Get all sessions for the given full jid
@@ -253,117 +189,13 @@ class ConnectionHandlers(ConnectionSocks5Bytestream,
     def __init__(self):
         ConnectionSocks5Bytestream.__init__(self)
         ConnectionIBBytestream.__init__(self)
-
-        # Handle presences BEFORE caps
-        app.nec.register_incoming_event(PresenceReceivedEvent)
-
         ConnectionJingle.__init__(self)
         ConnectionHandlersBase.__init__(self)
 
-        self.continue_connect_info = None
-
-        # If handlers have been registered
-        self.handlers_registered = False
-
+        app.nec.register_incoming_event(PresenceReceivedEvent)
         app.nec.register_incoming_event(StreamConflictReceivedEvent)
         app.nec.register_incoming_event(NotificationEvent)
 
-        app.ged.register_event_handler('agent-removed', ged.CORE,
-            self._nec_agent_removed)
-
-    def cleanup(self):
-        ConnectionHandlersBase.cleanup(self)
-        app.ged.remove_event_handler('agent-removed', ged.CORE,
-            self._nec_agent_removed)
-
-    def _nec_agent_removed(self, obj):
-        if obj.conn.name != self.name:
-            return
-        for jid in obj.jid_list:
-            log.debug('Removing contact %s due to unregistered transport %s',
-                      jid, obj.agent)
-            self.get_module('Presence').unsubscribe(jid)
-            # Transport contacts can't have 2 resources
-            if jid in app.to_be_removed[self.name]:
-                # This way we'll really remove it
-                app.to_be_removed[self.name].remove(jid)
-
-    def discover_ft_proxies(self):
-        cfg_proxies = app.config.get_per('accounts', self.name,
-            'file_transfer_proxies')
-        our_jid = helpers.parse_jid(app.get_jid_from_account(self.name) + \
-            '/' + self.server_resource)
-        testit = app.config.get_per('accounts', self.name,
-            'test_ft_proxies_on_startup')
-        if cfg_proxies:
-            proxies = [e.strip() for e in cfg_proxies.split(',')]
-            for proxy in proxies:
-                app.proxy65_manager.resolve(proxy, self.connection, our_jid,
-                    testit=testit)
-
-    def send_first_presence(self):
-        if self.connected > 1 and self.continue_connect_info:
-            msg = self.continue_connect_info[1]
-            sign_msg = self.continue_connect_info[2]
-            signed = ''
-            send_first_presence = True
-            if sign_msg:
-                signed = self.get_signed_presence(msg,
-                    self._send_first_presence)
-                if signed is None:
-                    app.nec.push_incoming_event(GPGPasswordRequiredEvent(None,
-                        conn=self, callback=self._send_first_presence))
-                    # _send_first_presence will be called when user enter
-                    # passphrase
-                    send_first_presence = False
-            if send_first_presence:
-                self._send_first_presence(signed)
-
-    def _send_first_presence(self, signed=''):
-        show = self.continue_connect_info[0]
-        msg = self.continue_connect_info[1]
-        sign_msg = self.continue_connect_info[2]
-        if sign_msg and not signed:
-            signed = self.get_signed_presence(msg)
-            if signed is None:
-                app.nec.push_incoming_event(BadGPGPassphraseEvent(None,
-                    conn=self))
-                self.USE_GPG = False
-                signed = ''
-        self.connected = app.SHOW_LIST.index(show)
-        sshow = helpers.get_xmpp_show(show)
-        # send our presence
-        if show == 'invisible':
-            self.send_invisible_presence(msg, signed, True)
-            return
-        if show not in ['offline', 'online', 'chat', 'away', 'xa', 'dnd']:
-            return
-        priority = app.get_priority(self.name, sshow)
-
-        self.get_module('Presence').send_presence(
-            priority=priority,
-            show=sshow,
-            status=msg,
-            sign=signed)
-
-        if self.connection:
-            self.priority = priority
-        app.nec.push_incoming_event(OurShowEvent(None, conn=self,
-            show=show))
-
-        if not self.avatar_conversion:
-            # ask our VCard
-            self.get_module('VCardTemp').request_vcard()
-
-        self.get_module('Bookmarks').get_bookmarks()
-        self.get_module('Annotations').get_annotations()
-        self.get_module('Blocking').get_blocking_list()
-
-        # Inform GUI we just signed in
-        app.nec.push_incoming_event(SignedInEvent(None, conn=self))
-        self.get_module('PEP').send_stored_publish()
-        self.continue_connect_info = None
-
     def _PubkeyGetCB(self, con, iq_obj):
         log.info('PubkeyGetCB')
         jid_from = helpers.get_full_jid_from_iq(iq_obj)
@@ -408,20 +240,3 @@ class ConnectionHandlers(ConnectionSocks5Bytestream,
             nbxmpp.NS_PUBKEY_PUBKEY)
         con.RegisterHandler('iq', self._PubkeyResultCB, 'result',
             nbxmpp.NS_PUBKEY_PUBKEY)
-
-        for handler in modules.get_handlers(self):
-            if len(handler) == 5:
-                name, func, typ, ns, priority = handler
-                con.RegisterHandler(name, func, typ, ns, priority=priority)
-            else:
-                con.RegisterHandler(*handler)
-        self.handlers_registered = True
-
-    def _unregister_handlers(self):
-        if not self.connection:
-            return
-        for handler in modules.get_handlers(self):
-            if len(handler) > 4:
-                handler = handler[:4]
-            self.connection.UnregisterHandler(*handler)
-        self.handlers_registered = False


=====================================
gajim/common/connection_handlers_events.py
=====================================
@@ -66,9 +66,6 @@ class MessageSentEvent(nec.NetworkIncomingEvent):
             self.conn.sent_message_ids = self.conn.sent_message_ids[-20000:]
         return True
 
-class MessageNotSentEvent(nec.NetworkIncomingEvent):
-    name = 'message-not-sent'
-
 class MessageErrorEvent(nec.NetworkIncomingEvent):
     name = 'message-error'
 
@@ -85,9 +82,6 @@ class MessageErrorEvent(nec.NetworkIncomingEvent):
             return True
         return False
 
-class AnonymousAuthEvent(nec.NetworkIncomingEvent):
-    name = 'anonymous-auth'
-
 class JingleRequestReceivedEvent(nec.NetworkIncomingEvent):
     name = 'jingle-request-received'
 
@@ -133,12 +127,6 @@ class JingleErrorReceivedEvent(nec.NetworkIncomingEvent):
         self.sid = self.jingle_session.sid
         return True
 
-class AccountCreatedEvent(nec.NetworkIncomingEvent):
-    name = 'account-created'
-
-class AccountNotCreatedEvent(nec.NetworkIncomingEvent):
-    name = 'account-not-created'
-
 class NewAccountConnectedEvent(nec.NetworkIncomingEvent):
     name = 'new-account-connected'
 
@@ -165,15 +153,6 @@ class NewAccountConnectedEvent(nec.NetworkIncomingEvent):
 class NewAccountNotConnectedEvent(nec.NetworkIncomingEvent):
     name = 'new-account-not-connected'
 
-class ConnectionTypeEvent(nec.NetworkIncomingEvent):
-    name = 'connection-type'
-
-class StanzaReceivedEvent(nec.NetworkIncomingEvent):
-    name = 'stanza-received'
-
-class StanzaSentEvent(nec.NetworkIncomingEvent):
-    name = 'stanza-sent'
-
 class BadGPGPassphraseEvent(nec.NetworkIncomingEvent):
     name = 'bad-gpg-passphrase'
 
@@ -191,9 +170,6 @@ class ConnectionLostEvent(nec.NetworkIncomingEvent):
             show='offline'))
         return True
 
-class GPGTrustKeyEvent(nec.NetworkIncomingEvent):
-    name = 'gpg-trust-key'
-
 class GPGPasswordRequiredEvent(nec.NetworkIncomingEvent):
     name = 'gpg-password-required'
 
@@ -201,42 +177,6 @@ class GPGPasswordRequiredEvent(nec.NetworkIncomingEvent):
         self.keyid = app.config.get_per('accounts', self.conn.name, 'keyid')
         return True
 
-class PlainConnectionEvent(nec.NetworkIncomingEvent):
-    name = 'plain-connection'
-
-class InsecureSSLConnectionEvent(nec.NetworkIncomingEvent):
-    name = 'insecure-ssl-connection'
-
-class SSLErrorEvent(nec.NetworkIncomingEvent):
-    name = 'ssl-error'
-
-class UpdateGCAvatarEvent(nec.NetworkIncomingEvent):
-    name = 'update-gc-avatar'
-
-    def generate(self):
-        return True
-
-class UpdateRosterAvatarEvent(nec.NetworkIncomingEvent):
-    name = 'update-roster-avatar'
-
-    def generate(self):
-        return True
-
-class UpdateRoomAvatarEvent(nec.NetworkIncomingEvent):
-    name = 'update-room-avatar'
-
-    def generate(self):
-        return True
-
-class ZeroconfNameConflictEvent(nec.NetworkIncomingEvent):
-    name = 'zeroconf-name-conflict'
-
-class PasswordRequiredEvent(nec.NetworkIncomingEvent):
-    name = 'password-required'
-
-class SignedInEvent(nec.NetworkIncomingEvent):
-    name = 'signed-in'
-
 class FileRequestReceivedEvent(nec.NetworkIncomingEvent):
     name = 'file-request-received'
 
@@ -737,10 +677,6 @@ class GcMessageOutgoingEvent(nec.NetworkOutgoingEvent):
     def generate(self):
         return True
 
-
-class ClientCertPassphraseEvent(nec.NetworkIncomingEvent):
-    name = 'client-cert-passphrase'
-
 class InformationEvent(nec.NetworkIncomingEvent):
     name = 'information'
 
@@ -756,10 +692,3 @@ class InformationEvent(nec.NetworkIncomingEvent):
         else:
             self.args = (self.args,)
         return True
-
-
-class StyleChanged(nec.NetworkIncomingEvent):
-    name = 'style-changed'
-
-    def generate(self):
-        return True


=====================================
gajim/common/dbus_support.py deleted
=====================================
@@ -1,165 +0,0 @@
-# Copyright (C) 2005 Andrew Sayman <lorien420 AT myrealbox.com>
-#                    Dimitur Kirov <dkirov AT gmail.com>
-# Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
-# Copyright (C) 2005-2014 Yann Leboulanger <asterix AT lagaule.org>
-# Copyright (C) 2006 Jean-Marie Traissard <jim AT lapin.org>
-#                    Stefan Bethge <stefan AT lanpartei.de>
-# Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
-#
-# This file is part of Gajim.
-#
-# Gajim is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published
-# by the Free Software Foundation; version 3 only.
-#
-# Gajim is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
-
-import sys
-import logging
-
-from gajim.common import exceptions
-from gajim.common.i18n import _
-
-_GAJIM_ERROR_IFACE = 'org.gajim.dbus.Error'
-
-log = logging.getLogger('gajim.c.dbus')
-
-try:
-    import dbus
-    from dbus.mainloop.glib import DBusGMainLoop
-    DBusGMainLoop(set_as_default=True)
-except ImportError:
-    supported = False
-    if sys.platform not in ('win32', 'darwin'):
-        print(_('D-Bus python bindings are missing in this computer'))
-        print(_('D-Bus capabilities of Gajim cannot be used'))
-else:
-    try:
-        # test if dbus-x11 is installed
-        _bus = dbus.SystemBus()
-        _bus = dbus.SessionBus()
-        supported = True # does user have D-Bus bindings?
-    except dbus.DBusException:
-        supported = False
-        if sys.platform not in ('win32', 'darwin'):
-            print(_('D-Bus does not run correctly on this machine'))
-            print(_('D-Bus capabilities of Gajim cannot be used'))
-    except exceptions.SystemBusNotPresent:
-        print(_('D-Bus does not run correctly on this machine: system bus not '
-            'present'))
-    except exceptions.SessionBusNotPresent:
-        print(_('D-Bus does not run correctly on this machine: session bus not '
-            'present'))
-
-class SystemBus:
-    """
-    A Singleton for the DBus SystemBus
-    """
-
-    def __init__(self):
-        self.system_bus = None
-
-    def SystemBus(self):
-        if not supported:
-            raise exceptions.DbusNotSupported
-
-        if not self.present():
-            raise exceptions.SystemBusNotPresent
-        return self.system_bus
-
-    def bus(self):
-        return self.SystemBus()
-
-    def present(self):
-        if not supported:
-            return False
-        if self.system_bus is None:
-            try:
-                self.system_bus = dbus.SystemBus()
-            except dbus.DBusException:
-                self.system_bus = None
-                return False
-            if self.system_bus is None:
-                return False
-            # Don't exit Gajim when dbus is stopped
-            self.system_bus.set_exit_on_disconnect(False)
-        return True
-
-system_bus = SystemBus()
-
-class SessionBus:
-    """
-    A Singleton for the D-Bus SessionBus
-    """
-
-    def __init__(self):
-        self.session_bus = None
-
-    def SessionBus(self):
-        if not supported:
-            raise exceptions.DbusNotSupported
-
-        if not self.present():
-            raise exceptions.SessionBusNotPresent
-        return self.session_bus
-
-    def bus(self):
-        return self.SessionBus()
-
-    def present(self):
-        if not supported:
-            return False
-        if self.session_bus is None:
-            try:
-                self.session_bus = dbus.SessionBus()
-            except dbus.DBusException:
-                self.session_bus = None
-                return False
-            if self.session_bus is None:
-                return False
-        return True
-
-session_bus = SessionBus()
-
-def get_interface(interface, path, start_service=True):
-    """
-    Get an interface on the current SessionBus. If the interface isn't running,
-    try to start it first
-    """
-    if not supported:
-        return None
-    if session_bus.present():
-        bus = session_bus.SessionBus()
-    else:
-        return None
-    try:
-        obj = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
-        dbus_iface = dbus.Interface(obj, 'org.freedesktop.DBus')
-        running_services = dbus_iface.ListNames()
-        started = True
-        if interface not in running_services:
-            # try to start the service
-            started = start_service and dbus_iface.StartServiceByName(
-                interface, dbus.UInt32(0)) == 1
-        if not started:
-            return None
-        obj = bus.get_object(interface, path)
-        return dbus.Interface(obj, interface)
-    except Exception as error:
-        log.debug(error)
-        return None
-
-
-if supported:
-    class MissingArgument(dbus.DBusException):
-        _dbus_error_name = _GAJIM_ERROR_IFACE + '.MissingArgument'
-
-    class InvalidArgument(dbus.DBusException):
-        '''Raised when one of the provided arguments is invalid.'''
-        _dbus_error_name = _GAJIM_ERROR_IFACE + '.InvalidArgument'


=====================================
gajim/common/logger.py
=====================================
@@ -72,6 +72,7 @@ LOGS_SQL_STATEMENT = '''
             subject TEXT,
             additional_data TEXT,
             stanza_id TEXT,
+            message_id TEXT,
             encryption TEXT,
             encryption_state TEXT,
             marker INTEGER
@@ -228,6 +229,13 @@ class Logger:
             ]
             self._execute_multiple(con, statements)
 
+        if self._get_user_version(con) < 3:
+            statements = [
+                'ALTER TABLE logs ADD COLUMN "message_id" TEXT',
+                'PRAGMA user_version=3'
+            ]
+            self._execute_multiple(con, statements)
+
     def _migrate_cache(self, con):
         if self._get_user_version(con) == 0:
             # All migrations from 0.16.9 until 1.0.0


=====================================
gajim/common/modules/gateway.py
=====================================
@@ -51,6 +51,13 @@ class Gateway:
         for jid in app.contacts.get_jid_list(self._account):
             if jid.endswith('@' + agent):
                 jid_list.append(jid)
+                log.info('Removing contact %s due to unregistered transport %s',
+                          jid, agent)
+                self._con.get_module('Presence').unsubscribe(jid)
+                # Transport contacts can't have 2 resources
+                if jid in app.to_be_removed[self._account]:
+                    # This way we'll really remove it
+                    app.to_be_removed[self._account].remove(jid)
 
         app.nec.push_incoming_event(
             NetworkEvent('agent-removed',


=====================================
gajim/common/modules/mam.py
=====================================
@@ -19,6 +19,7 @@ import time
 from datetime import datetime, timedelta
 
 import nbxmpp
+from nbxmpp.structs import StanzaHandler
 
 from gajim.common import app
 from gajim.common.nec import NetworkEvent
@@ -33,8 +34,6 @@ from gajim.common.modules.misc import parse_delay
 from gajim.common.modules.misc import parse_oob
 from gajim.common.modules.misc import parse_correction
 from gajim.common.modules.misc import parse_eme
-from gajim.common.modules.util import is_self_message
-from gajim.common.modules.util import is_muc_pm
 
 log = logging.getLogger('gajim.c.m.archiving')
 
@@ -45,8 +44,9 @@ class MAM:
         self._account = con.name
 
         self.handlers = [
-            ('message', self._mam_message_received, '', nbxmpp.NS_MAM_1),
-            ('message', self._mam_message_received, '', nbxmpp.NS_MAM_2),
+            StanzaHandler(name='message',
+                          callback=self._mam_message_received,
+                          priority=51),
         ]
 
         self.available = False
@@ -72,132 +72,91 @@ class MAM:
                          account=self._account,
                          feature=self.archiving_namespace))
 
-    def _from_valid_archive(self, stanza, message, groupchat):
-        if groupchat:
-            expected_archive = message.getFrom()
+    def _from_valid_archive(self, stanza, properties):
+        if properties.type.is_groupchat:
+            expected_archive = properties.jid
         else:
             expected_archive = self._con.get_own_jid()
 
-        archive_jid = stanza.getFrom()
-        if archive_jid is None:
-            if groupchat:
-                return
-            # Message from our own archive
-            return self._con.get_own_jid()
-
-        if archive_jid.bareMatch(expected_archive):
-            return archive_jid
+        return properties.mam.archive.bareMatch(expected_archive)
 
-    def _get_unique_id(self, result, message, groupchat, self_message, muc_pm):
-        stanza_id = result.getAttr('id')
-        if groupchat:
-            return stanza_id, None
+    def _get_unique_id(self, properties):
+        if properties.type.is_groupchat:
+            return properties.mam.id, None
 
-        origin_id = message.getOriginID()
-        if self_message:
-            return None, origin_id
+        if properties.is_self_message:
+            return None, properties.id
 
-        if muc_pm:
-            return stanza_id, origin_id
+        if properties.is_muc_pm:
+            return properties.mam.id, properties.id
 
-        if self._con.get_own_jid().bareMatch(message.getFrom()):
+        if self._con.get_own_jid().bareMatch(properties.jid):
             # message we sent
-            return stanza_id, origin_id
+            return properties.mam.id, properties.id
 
         # A message we received
-        return stanza_id, None
+        return properties.mam.id, None
+
+    def _mam_message_received(self, _con, stanza, properties):
+        if not properties.is_mam_message:
+            return
 
-    def _mam_message_received(self, _con, stanza):
         app.nec.push_incoming_event(
             NetworkIncomingEvent('raw-mam-message-received',
                                  conn=self._con,
                                  stanza=stanza))
 
-        result = stanza.getTag('result', protocol=True)
-        queryid = result.getAttr('queryid')
-        forwarded = result.getTag('forwarded',
-                                  namespace=nbxmpp.NS_FORWARD,
-                                  protocol=True)
-        message = forwarded.getTag('message', protocol=True)
-
-        groupchat = message.getType() == 'groupchat'
-
-        archive_jid = self._from_valid_archive(stanza, message, groupchat)
-        if archive_jid is None:
-            log.warning('Message from invalid archive %s', stanza)
+        if not self._from_valid_archive(stanza, properties):
+            log.warning('Message from invalid archive %s',
+                        properties.mam.archive)
             raise nbxmpp.NodeProcessed
 
-        log.info('Received message from archive: %s', archive_jid)
-        if not self._is_valid_request(archive_jid, queryid):
-            log.warning('Invalid MAM Message: unknown query id')
+        log.info('Received message from archive: %s', properties.mam.archive)
+        if not self._is_valid_request(properties):
+            log.warning('Invalid MAM Message: unknown query id %s',
+                        properties.mam.query_id)
             log.debug(stanza)
             raise nbxmpp.NodeProcessed
 
-        # Timestamp parsing
-        # Most servers dont set the 'from' attr, so we cant check for it
-        delay_timestamp = parse_delay(forwarded)
-        if delay_timestamp is None:
-            log.warning('No timestamp on MAM message')
-            log.warning(stanza)
-            raise nbxmpp.NodeProcessed
-
-        # Fix for self messaging
-        if not groupchat:
-            to = message.getTo()
-            if to is None:
-                # Some servers dont set the 'to' attribute when
-                # we send a message to ourself
-                message.setTo(self._con.get_own_jid())
-
         event_attrs = {}
 
+        groupchat = properties.type.is_groupchat
+
         if groupchat:
-            event_attrs.update(self._parse_gc_attrs(message))
+            event_attrs.update(self._parse_gc_attrs(properties))
         else:
-            event_attrs.update(self._parse_chat_attrs(message))
-
-        self_message = is_self_message(message, groupchat)
-        muc_pm = is_muc_pm(message, event_attrs['with_'], groupchat)
+            event_attrs.update(self._parse_chat_attrs(stanza, properties))
 
-        stanza_id, origin_id = self._get_unique_id(
-            result, message, groupchat, self_message, muc_pm)
-        message_id = message.getID()
+        stanza_id, message_id = self._get_unique_id(properties)
 
-        # Check for duplicates
-        namespace = self.archiving_namespace
-        if groupchat:
-            namespace = muc_caps_cache.get_mam_namespace(
-                archive_jid.getStripped())
-
-        if namespace == nbxmpp.NS_MAM_2:
+        if properties.mam.is_ver_2:
             # Search only with stanza-id for duplicates on mam:2
             if app.logger.find_stanza_id(self._account,
-                                         archive_jid.getStripped(),
+                                         str(properties.mam.archive),
                                          stanza_id,
-                                         origin_id,
+                                         message_id,
                                          groupchat=groupchat):
-                log.info('Found duplicate with stanza-id')
+                log.info('Found duplicate with stanza-id: %s, message-id: %s',
+                         stanza_id, message_id)
                 raise nbxmpp.NodeProcessed
 
-        msgtxt = message.getTagData('body')
-
         event_attrs.update(
             {'conn': self._con,
              'additional_data': AdditionalDataDict(),
              'encrypted': False,
-             'timestamp': delay_timestamp,
-             'self_message': self_message,
+             'timestamp': properties.mam.timestamp,
+             'self_message': properties.is_self_message,
              'groupchat': groupchat,
-             'muc_pm': muc_pm,
+             'muc_pm': properties.is_muc_pm,
              'stanza_id': stanza_id,
-             'origin_id': origin_id,
-             'message_id': message_id,
+             'origin_id': message_id,
+             'message_id': properties.id,
              'correct_id': None,
-             'archive_jid': archive_jid,
-             'msgtxt': msgtxt,
-             'message': message,
-             'stanza': message,
-             'namespace': namespace,
+             'archive_jid': properties.mam.archive,
+             'msgtxt': properties.body,
+             'message': stanza,
+             'stanza': stanza,
+             'namespace': properties.mam.namespace,
              })
 
         if groupchat:
@@ -217,26 +176,18 @@ class MAM:
         raise nbxmpp.NodeProcessed
 
     @staticmethod
-    def _parse_gc_attrs(message):
-        with_ = message.getFrom()
-        nick = message.getFrom().getResource()
-
-        # Get the real jid if we have it
+    def _parse_gc_attrs(properties):
         real_jid = None
-        muc_user = message.getTag('x', namespace=nbxmpp.NS_MUC_USER)
-        if muc_user is not None:
-            real_jid = muc_user.getTagAttr('item', 'jid')
-            if real_jid is not None:
-                real_jid = nbxmpp.JID(real_jid)
-
-        return {'with_': with_,
-                'nick': nick,
+        if properties.muc_user is not None:
+            real_jid = properties.muc_user.jid
+        return {'with_': properties.jid,
+                'nick': properties.muc_nickname,
                 'real_jid': real_jid,
                 'kind': KindConstant.GC_MSG}
 
-    def _parse_chat_attrs(self, message):
-        frm = message.getFrom()
-        to = message.getTo()
+    def _parse_chat_attrs(self, stanza, properties):
+        frm = properties.jid
+        to = stanza.getTo()
         if frm.bareMatch(self._con.get_own_jid()):
             with_ = to
             kind = KindConstant.CHAT_MSG_SENT
@@ -290,17 +241,15 @@ class MAM:
                                     message=event.msgtxt,
                                     contact_name=event.nick,
                                     additional_data=event.additional_data,
-                                    stanza_id=stanza_id)
+                                    stanza_id=stanza_id,
+                                    message_id=event.message_id)
 
         app.nec.push_incoming_event(
             MamDecryptedMessageReceived(None, **vars(event)))
 
-    def _is_valid_request(self, jid, query_id):
-        if query_id is None:
-            return False
-
-        valid_id = self._mam_query_ids.get(jid.getStripped(), None)
-        return valid_id == query_id
+    def _is_valid_request(self, properties):
+        valid_id = self._mam_query_ids.get(str(properties.mam.archive), None)
+        return valid_id == properties.mam.query_id
 
     def _get_query_id(self, jid):
         query_id = self._con.connection.getAnID()


=====================================
gajim/common/modules/message.py
=====================================
@@ -18,13 +18,16 @@ import time
 import logging
 
 import nbxmpp
+from nbxmpp.structs import StanzaHandler
+from nbxmpp.const import MessageType
 
 from gajim.common import app
-from gajim.common import helpers
+from gajim.common import caps_cache
 from gajim.common.i18n import _
 from gajim.common.nec import NetworkIncomingEvent
 from gajim.common.nec import NetworkEvent
 from gajim.common.helpers import AdditionalDataDict
+from gajim.common.const import KindConstant
 from gajim.common.modules.security_labels import parse_securitylabel
 from gajim.common.modules.user_nickname import parse_nickname
 from gajim.common.modules.misc import parse_delay
@@ -34,8 +37,7 @@ from gajim.common.modules.misc import parse_attention
 from gajim.common.modules.misc import parse_form
 from gajim.common.modules.misc import parse_oob
 from gajim.common.modules.misc import parse_xhtml
-from gajim.common.modules.util import is_self_message
-from gajim.common.modules.util import is_muc_pm
+from gajim.common.connection_handlers_events import MessageErrorEvent
 
 
 log = logging.getLogger('gajim.c.m.message')
@@ -46,30 +48,26 @@ class Message:
         self._con = con
         self._account = con.name
 
-        self.handlers = [('message', self._message_received)]
+        self.handlers = [
+            StanzaHandler(name='message',
+                          callback=self._message_received,
+                          priority=50),
+        ]
 
         # XEPs for which this message module should not be executed
         self._message_namespaces = set([nbxmpp.NS_PUBSUB_EVENT,
                                         nbxmpp.NS_ROSTERX,
-                                        nbxmpp.NS_MAM_1,
-                                        nbxmpp.NS_MAM_2,
-                                        nbxmpp.NS_CONFERENCE,
-                                        nbxmpp.NS_IBB,
-                                        nbxmpp.NS_CAPTCHA,])
+                                        nbxmpp.NS_IBB])
 
     def _message_received(self, _con, stanza, properties):
+        if properties.is_mam_message:
+            return
         # Check if a child of the message contains any
         # namespaces that we handle in other modules.
         # nbxmpp executes less common handlers last
         if self._message_namespaces & set(stanza.getProperties()):
             return
 
-        muc_user = stanza.getTag('x', namespace=nbxmpp.NS_MUC_USER)
-        if muc_user is not None and (stanza.getType() != 'error'):
-            if muc_user.getChildren():
-                # Not a PM, handled by MUC module
-                return
-
         log.info('Received from %s', stanza.getFrom())
 
         app.nec.push_incoming_event(NetworkEvent(
@@ -84,49 +82,36 @@ class Message:
             # Ugly, we treat the from attr as the remote jid,
             # to make that work with sent carbons we have to do this.
             # TODO: Check where in Gajim and plugins we depend on that behavior
-            stanza.setFrom(stanza.getTo().getBare())
+            stanza.setFrom(stanza.getTo())
 
         from_ = stanza.getFrom()
-        type_ = stanza.getType()
-        if type_ is None:
-            type_ = 'normal'
-
-        self_message = is_self_message(stanza, type_ == 'groupchat')
-        muc_pm = is_muc_pm(stanza, from_, type_ == 'groupchat')
-
-        id_ = stanza.getID()
-
-        fjid = None
-        if from_ is not None:
-            try:
-                fjid = helpers.parse_jid(str(from_))
-            except helpers.InvalidFormat:
-                log.warning('Invalid JID: %s, ignoring it',
-                            stanza.getFrom())
-                return
+        fjid = str(from_)
+        jid = from_.getBare()
+        resource = from_.getResource()
 
-        jid, resource = app.get_room_and_nick_from_fjid(fjid)
+        type_ = properties.type
 
         # Check for duplicates
-        stanza_id, origin_id = self._get_unique_id(
-            stanza, forwarded, sent, self_message, muc_pm)
+        stanza_id, message_id = self._get_unique_id(properties)
 
         # Check groupchat messages for duplicates,
         # We do this because of MUC History messages
-        if type_ == 'groupchat' or self_message or muc_pm:
-            if type_ == 'groupchat':
+        if (properties.type.is_groupchat or
+            properties.is_self_message or
+                properties.is_muc_pm):
+            if properties.type.is_groupchat:
                 archive_jid = stanza.getFrom().getStripped()
             else:
                 archive_jid = self._con.get_own_jid().getStripped()
             if app.logger.find_stanza_id(self._account,
                                          archive_jid,
                                          stanza_id,
-                                         origin_id,
-                                         type_ == 'groupchat'):
+                                         message_id,
+                                         properties.type.is_groupchat):
                 return
 
-        thread_id = stanza.getThread()
-        msgtxt = stanza.getBody()
+        thread_id = properties.thread
+        msgtxt = properties.body
 
         # TODO: remove all control UI stuff
         gc_control = app.interface.msg_win_mgr.get_gc_control(
@@ -136,7 +121,7 @@ class Message:
             gc_control = minimized.get(jid)
 
         if gc_control and jid == fjid:
-            if type_ == 'error':
+            if properties.type.is_error:
                 if msgtxt:
                     msgtxt = _('error while sending %(message)s ( %(error)s )') % {
                         'message': msgtxt, 'error': stanza.getErrorMsg()}
@@ -145,11 +130,11 @@ class Message:
                 # TODO: why is this here?
                 if stanza.getTag('html'):
                     stanza.delChild('html')
-            type_ = 'groupchat'
+            type_ = MessageType.GROUPCHAT
 
         session = None
-        if type_ != 'groupchat':
-            if muc_pm and type_ == 'error':
+        if not properties.type.is_groupchat:
+            if properties.is_muc_pm and properties.type.is_error:
                 session = self._con.find_session(fjid, thread_id)
                 if not session:
                     session = self._con.get_latest_session(fjid)
@@ -168,7 +153,7 @@ class Message:
             'conn': self._con,
             'stanza': stanza,
             'account': self._account,
-            'id_': id_,
+            'id_': properties.id,
             'encrypted': False,
             'additional_data': AdditionalDataDict(),
             'forwarded': forwarded,
@@ -177,13 +162,14 @@ class Message:
             'jid': jid,
             'resource': resource,
             'stanza_id': stanza_id,
-            'unique_id': stanza_id or origin_id,
-            'mtype': type_,
+            'unique_id': stanza_id or message_id,
+            'message_id': properties.id,
+            'mtype': type_.value,
             'msgtxt': msgtxt,
             'thread_id': thread_id,
             'session': session,
-            'self_message': self_message,
-            'muc_pm': muc_pm,
+            'self_message': properties.is_self_message,
+            'muc_pm': properties.is_muc_pm,
             'gc_control': gc_control
         }
 
@@ -248,9 +234,19 @@ class Message:
             if event.gc_control:
                 event.gc_control.print_conversation(event.msgtxt)
             else:
-                self._con.dispatch_error_message(
-                    event.stanza, event.msgtxt,
-                    event.session, event.fjid, timestamp)
+                self._log_error_message(event)
+                error_msg = event.stanza.getErrorMsg() or event.msgtxt
+                msgtxt = None if error_msg == event.msgtxt else event.msgtxt
+                app.nec.push_incoming_event(
+                    MessageErrorEvent(None,
+                                      conn=self._con,
+                                      fjid=event.fjid,
+                                      error_code=event.stanza.getErrorCode(),
+                                      error_msg=error_msg,
+                                      msg=msgtxt,
+                                      time_=event.timestamp,
+                                      session=event.session,
+                                      stanza=event.stanza))
             return
 
         if groupchat:
@@ -264,42 +260,77 @@ class Message:
 
             app.nec.push_incoming_event(NetworkEvent('gc-message-received',
                                                      **vars(event)))
+            # TODO: Some plugins modify msgtxt in the GUI event
+            self._log_muc_message(event)
             return
 
         app.nec.push_incoming_event(
             DecryptedMessageReceivedEvent(
                 None, **vars(event)))
 
-    def _get_unique_id(self, stanza, _forwarded, _sent, self_message, _muc_pm):
-        if stanza.getType() == 'groupchat':
-            # TODO: Disco the MUC check if 'urn:xmpp:mam:2' is announced
-            return self._get_stanza_id(stanza), None
+    def _log_error_message(self, event):
+        error_msg = event.stanza.getErrorMsg() or event.msgtxt
+        if app.config.should_log(self._account, event.jid):
+            app.logger.insert_into_logs(self._account,
+                                        event.jid,
+                                        event.timestamp,
+                                        KindConstant.ERROR,
+                                        message=error_msg,
+                                        subject=event.subject)
+
+    def _log_muc_message(self, event):
+        if event.mtype == 'error':
+            return
 
-        if stanza.getType() != 'chat':
+        self._check_for_mam_compliance(event.room_jid, event.stanza_id)
+
+        if (app.config.should_log(self._account, event.jid) and
+                event.msgtxt and event.nick):
+            # if not event.nick, it means message comes from room itself
+            # usually it hold description and can be send at each connection
+            # so don't store it in logs
+            app.logger.insert_into_logs(self._account,
+                                        event.jid,
+                                        event.timestamp,
+                                        KindConstant.GC_MSG,
+                                        message=event.msgtxt,
+                                        contact_name=event.nick,
+                                        additional_data=event.additional_data,
+                                        stanza_id=event.stanza_id,
+                                        message_id=event.message_id)
+            app.logger.set_room_last_message_time(event.room_jid, event.timestamp)
+            self._con.get_module('MAM').save_archive_id(
+                event.room_jid, event.stanza_id, event.timestamp)
+
+    @staticmethod
+    def _check_for_mam_compliance(room_jid, stanza_id):
+        namespace = caps_cache.muc_caps_cache.get_mam_namespace(room_jid)
+        if stanza_id is None and namespace == nbxmpp.NS_MAM_2:
+            log.warning('%s announces mam:2 without stanza-id', room_jid)
+
+    def _get_unique_id(self, properties):
+        if properties.is_self_message:
+            # Deduplicate self message with message-id
+            return None, properties.id
+
+        if properties.stanza_id.by is None:
+            # We can not verify who sent this stanza-id, ignore it.
             return None, None
 
-        # Messages we receive live
-        if self._con.get_module('MAM').archiving_namespace != nbxmpp.NS_MAM_2:
+        if properties.type.is_groupchat:
+            namespace = caps_cache.muc_caps_cache.get_mam_namespace(
+                properties.jid.getBare())
+            archive = properties.jid
+        else:
+            namespace = self._con.get_module('MAM').archiving_namespace
+            archive = self._con.get_own_jid()
+
+        if namespace != nbxmpp.NS_MAM_2:
             # Only mam:2 ensures valid stanza-id
             return None, None
 
-        if self_message:
-            return self._get_stanza_id(stanza), stanza.getOriginID()
-        return self._get_stanza_id(stanza), None
-
-    def _get_stanza_id(self, stanza):
-        stanza_id, by = stanza.getStanzaIDAttrs()
-        if by is None:
-            # We can not verify who set this stanza-id, ignore it.
-            return
-        if stanza.getType() == 'groupchat':
-            if stanza.getFrom().bareMatch(by):
-                # by attribute must match the server
-                return stanza_id
-        elif self._con.get_own_jid().bareMatch(by):
-            # by attribute must match the server
-            return stanza_id
-        return
+        if archive.bareMatch(properties.stanza_id.by):
+            return properties.stanza_id.id, None
 
 
 class MessageReceivedEvent(NetworkIncomingEvent):


=====================================
gajim/common/modules/util.py
=====================================
@@ -16,35 +16,6 @@
 
 from typing import Union
 
-import nbxmpp
-
-from gajim.common import app
-
-
-def is_self_message(message: nbxmpp.Node,
-                    groupchat: bool = False) -> bool:
-    if groupchat:
-        return False
-    frm = message.getFrom()
-    to = message.getTo()
-    return frm.bareMatch(to)
-
-
-def is_muc_pm(message: nbxmpp.Node,
-              jid: nbxmpp.JID,
-              groupchat: bool = False) -> bool:
-    if groupchat:
-        return False
-    muc_user = message.getTag('x', namespace=nbxmpp.NS_MUC_USER)
-    if muc_user is not None:
-        return muc_user.getChildren() == []
-
-    # muc#user namespace was added in MUC 1.28 so we need a fallback
-    # Check if we know the jid
-    if app.logger.jid_is_room_jid(jid.getStripped()):
-        return True
-    return False
-
 
 def from_xs_boolean(value: Union[str, bool]) -> bool:
     if isinstance(value, bool):


=====================================
gajim/common/zeroconf/client_zeroconf.py
=====================================
@@ -15,18 +15,6 @@
 # You should have received a copy of the GNU General Public License
 # along with Gajim.  If not, see <http://www.gnu.org/licenses/>.
 
-from unittest.mock import Mock
-
-from gajim.common import app
-import nbxmpp
-from nbxmpp.idlequeue import IdleObject
-from nbxmpp import dispatcher_nb, simplexml
-from nbxmpp.plugin import PlugIn
-from nbxmpp.plugin import *
-from nbxmpp.transports_nb import DATA_RECEIVED, DATA_SENT, DATA_ERROR
-from gajim.common.zeroconf import zeroconf
-
-from nbxmpp.protocol import *
 import socket
 import platform
 import ssl
@@ -34,13 +22,26 @@ import errno
 import sys
 import os
 import string
+import logging
 from random import Random
+from unittest.mock import Mock
 
-import logging
-log = logging.getLogger('gajim.c.z.client_zeroconf')
+import nbxmpp
+from nbxmpp import dispatcher_nb
+from nbxmpp import simplexml
+from nbxmpp.plugin import PlugIn
+from nbxmpp.idlequeue import IdleObject
+from nbxmpp.transports_nb import DATA_RECEIVED
+from nbxmpp.transports_nb import DATA_SENT
+from nbxmpp.transports_nb import DATA_ERROR
 
+from gajim.common import app
+from gajim.common.zeroconf import zeroconf
 from gajim.common.zeroconf import roster_zeroconf
 
+log = logging.getLogger('gajim.c.z.client_zeroconf')
+
+
 MAX_BUFF_LEN = 65536
 TYPE_SERVER, TYPE_CLIENT = range(2)
 
@@ -288,6 +289,7 @@ class P2PClient(IdleObject):
                 del self.conn_holder.ids_of_awaiting_messages[self.fd]
             self.conn_holder.remove_connection(self.sock_hash)
         if 'Dispatcher' in self.__dict__:
+            self._caller._unregister_new_handlers(self)
             self.Dispatcher.PlugOut()
         if 'P2PConnection' in self.__dict__:
             self.P2PConnection.PlugOut()
@@ -338,6 +340,8 @@ class P2PClient(IdleObject):
         self.RegisterHandler('iq', self._caller._JingleCB, 'error')
         self.RegisterHandler('iq', self._caller._JingleCB, 'set',
             nbxmpp.NS_JINGLE)
+        self._caller._register_new_handlers(self)
+
 
 class P2PConnection(IdleObject, PlugIn):
     def __init__(self, sock_hash, _sock, addresses=None, caller=None,


=====================================
gajim/common/zeroconf/connection_handlers_zeroconf.py
=====================================
@@ -32,12 +32,14 @@ from gajim.common import connection_handlers
 from gajim.common.i18n import _
 from gajim.common.helpers import AdditionalDataDict
 from gajim.common.nec import NetworkIncomingEvent, NetworkEvent
+from gajim.common.const import KindConstant
 from gajim.common.modules.user_nickname import parse_nickname
 from gajim.common.modules.misc import parse_eme
 from gajim.common.modules.misc import parse_correction
 from gajim.common.modules.misc import parse_attention
 from gajim.common.modules.misc import parse_oob
 from gajim.common.modules.misc import parse_xhtml
+from gajim.common.connection_handlers_events import MessageErrorEvent
 
 
 log = logging.getLogger('gajim.c.z.connection_handlers_zeroconf')
@@ -163,10 +165,31 @@ class ConnectionHandlersZeroconf(ConnectionSocks5BytestreamZeroconf,
         if event.mtype == 'error':
             if not event.msgtxt:
                 event.msgtxt = _('message')
-            self.dispatch_error_message(
-                event.stanza, event.msgtxt,
-                event.session, event.fjid, event.timestamp)
+            self._log_error_message(event)
+            error_msg = event.stanza.getErrorMsg() or event.msgtxt
+            msgtxt = None if error_msg == event.msgtxt else event.msgtxt
+            app.nec.push_incoming_event(
+                MessageErrorEvent(None,
+                                  conn=self,
+                                  fjid=event.fjid,
+                                  error_code=event.stanza.getErrorCode(),
+                                  error_msg=error_msg,
+                                  msg=msgtxt,
+                                  time_=event.timestamp,
+                                  session=event.session,
+                                  stanza=event.stanza))
+
             return
 
         app.nec.push_incoming_event(
             DecryptedMessageReceivedEvent(None, **vars(event)))
+
+    def _log_error_message(self, event):
+        error_msg = event.stanza.getErrorMsg() or event.msgtxt
+        if app.config.should_log(self.name, event.jid):
+            app.logger.insert_into_logs(self.name,
+                                        event.jid,
+                                        event.timestamp,
+                                        KindConstant.ERROR,
+                                        message=error_msg,
+                                        subject=event.subject)


=====================================
gajim/common/zeroconf/connection_zeroconf.py
=====================================
@@ -29,6 +29,8 @@
 
 import socket
 import getpass
+import logging
+import time
 
 import nbxmpp
 from gi.repository import GLib
@@ -36,12 +38,18 @@ from gi.repository import GLib
 from gajim.common import app
 from gajim.common import ged
 from gajim.common import modules
+from gajim.common.nec import NetworkEvent
 from gajim.common.i18n import _
 from gajim.common.connection import CommonConnection
 from gajim.common.zeroconf import client_zeroconf
 from gajim.common.zeroconf import zeroconf
-from gajim.common.zeroconf.connection_handlers_zeroconf import *
-from gajim.common.connection_handlers_events import *
+from gajim.common.zeroconf.connection_handlers_zeroconf import ConnectionHandlersZeroconf
+from gajim.common.zeroconf.connection_handlers_zeroconf import STATUS_LIST
+from gajim.common.connection_handlers_events import OurShowEvent
+from gajim.common.connection_handlers_events import InformationEvent
+from gajim.common.connection_handlers_events import ConnectionLostEvent
+from gajim.common.connection_handlers_events import MessageSentEvent
+from gajim.common.connection_handlers_events import MessageErrorEvent
 
 log = logging.getLogger('gajim.c.connection_zeroconf')
 
@@ -240,8 +248,10 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
         self.disconnect()
         app.nec.push_incoming_event(OurShowEvent(None, conn=self,
             show='offline'))
-        app.nec.push_incoming_event(ZeroconfNameConflictEvent(None, conn=self,
-            alt_name=alt_name))
+        app.nec.push_incoming_event(
+            NetworkEvent('zeroconf-name-conflict',
+                         conn=self,
+                         alt_name=alt_name))
 
     def _on_error(self, message):
         app.nec.push_incoming_event(InformationEvent(
@@ -362,7 +372,7 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
             check = self.connection.announce()
         else:
             self.connected = STATUS_LIST.index(show)
-        app.nec.push_incoming_event(SignedInEvent(None, conn=self))
+        app.nec.push_incoming_event(NetworkEvent('signed-in', conn=self))
 
         # stay offline when zeroconf does something wrong
         if check:


=====================================
gajim/gtk/features.py
=====================================
@@ -112,12 +112,6 @@ class FeaturesDialog(Gtk.Dialog):
                     _('Requires: pybonjour and bonjour SDK running (%(url)s)')
                     % {'url': 'https://developer.apple.com/opensource/)'},
                     None),
-            Feature(_('Command line Control'),
-                    self.dbus_available(),
-                    _('Enables you to control Gajim with via commandline'),
-                    _('Requires: python-dbus'),
-                    _('Feature not available under Windows'),
-                    None),
             Feature(_('OpenPGP Message Encryption'),
                     app.is_installed('GPG'),
                     _('Enables Gajim to encrypt chat messages with OpenPGP'),
@@ -159,10 +153,6 @@ class FeaturesDialog(Gtk.Dialog):
                     None)
         ]
 
-    def dbus_available(self):
-        from gajim.common import dbus_support
-        return dbus_support.supported
-
     def some_keyring_available(self):
         if os.name == 'nt':
             return True


=====================================
gajim/gtk/themes.py
=====================================
@@ -21,11 +21,11 @@ from gi.repository import Gtk
 from gi.repository import Gdk
 
 from gajim.common import app
+from gajim.common.nec import NetworkEvent
 from gajim.common.i18n import _
 from gajim.common.const import StyleAttr
 from gajim.common.const import DialogButton
 from gajim.common.const import ButtonAction
-from gajim.common.connection_handlers_events import StyleChanged
 
 from gajim.gtk.dialogs import ErrorDialog
 from gajim.gtk.dialogs import NewConfirmationDialog
@@ -388,18 +388,18 @@ class Option(Gtk.ListBoxRow):
         color_string = color.to_string()
         app.css_config.set_value(
             self._option.selector, self._option.attr, color_string, pre=True)
-        app.nec.push_incoming_event(StyleChanged(None))
+        app.nec.push_incoming_event(NetworkEvent('style-changed'))
 
     def _on_font_set(self, font_button):
         desc = font_button.get_font_desc()
         app.css_config.set_font(self._option.selector, desc, pre=True)
-        app.nec.push_incoming_event(StyleChanged(None,))
+        app.nec.push_incoming_event(NetworkEvent('style-changed'))
 
     def _on_remove(self, *args):
         self.get_parent().remove(self)
         app.css_config.remove_value(
             self._option.selector, self._option.attr, pre=True)
-        app.nec.push_incoming_event(StyleChanged(None))
+        app.nec.push_incoming_event(NetworkEvent('style-changed'))
         self.destroy()
 
     def __eq__(self, other):


=====================================
gajim/gui_interface.py
=====================================
@@ -85,10 +85,10 @@ from gajim.common import socks5
 from gajim.common import helpers
 from gajim.common import passwords
 from gajim.common import logging_helpers
+from gajim.common.nec import NetworkEvent
 from gajim.common.i18n import _
 from gajim.common.connection_handlers_events import (
-    OurShowEvent, FileTransferCompletedEvent,
-    UpdateRosterAvatarEvent, UpdateGCAvatarEvent, UpdateRoomAvatarEvent)
+    OurShowEvent, FileTransferCompletedEvent)
 
 from gajim.common.modules.httpupload import HTTPUploadProgressEvent
 from gajim.common.connection import Connection
@@ -614,22 +614,6 @@ class Interface:
             self.gpg_passphrase[obj.keyid] = request
         request.add_callback(obj.conn.name, obj.callback)
 
-    @staticmethod
-    def handle_event_gpg_trust_key(obj):
-        #('GPG_ALWAYS_TRUST', account, callback)
-        def on_yes(checked):
-            if checked:
-                obj.conn.gpg.always_trust.append(obj.keyID)
-            obj.callback(True)
-
-        def on_no():
-            obj.callback(False)
-
-        YesNoDialog(_('Untrusted OpenPGP key'), _('The OpenPGP key '
-            'used to encrypt this chat is not trusted. Do you really want to '
-            'encrypt this message?'), checktext=_('_Do not ask me again'),
-            on_response_yes=on_yes, on_response_no=on_no)
-
     def handle_event_password_required(self, obj):
         #('PASSWORD_REQUIRED', account, None)
         account = obj.conn.name
@@ -1359,7 +1343,6 @@ class Interface:
             'muc-invitation': [self.handle_event_gc_invitation],
             'muc-decline': [self.handle_event_gc_decline],
             'gpg-password-required': [self.handle_event_gpg_password_required],
-            'gpg-trust-key': [self.handle_event_gpg_trust_key],
             'http-auth-received': [self.handle_event_http_auth],
             'information': [self.handle_event_information],
             'insecure-ssl-connection': \
@@ -2116,13 +2099,13 @@ class Interface:
     def update_avatar(account=None, jid=None, contact=None, room_avatar=False):
         if room_avatar:
             app.nec.push_incoming_event(
-                UpdateRoomAvatarEvent(None, account=account, jid=jid))
+                NetworkEvent('update-room-avatar', account=account, jid=jid))
         elif contact is None:
             app.nec.push_incoming_event(
-                UpdateRosterAvatarEvent(None, account=account, jid=jid))
+                NetworkEvent('update-roster-avatar', account=account, jid=jid))
         else:
             app.nec.push_incoming_event(
-                UpdateGCAvatarEvent(None, contact=contact))
+                NetworkEvent('update-gc-avatar', contact=contact))
 
     def save_avatar(self, data, publish=False):
         """


=====================================
gajim/session.py
=====================================
@@ -134,7 +134,8 @@ class ChatControlSession:
                 message=msg_to_log,
                 subject=obj.subject,
                 additional_data=obj.additional_data,
-                stanza_id=obj.unique_id)
+                stanza_id=obj.unique_id,
+                message_id=obj.message_id)
 
         self.conn.get_module('MAM').save_archive_id(
             None, obj.stanza_id, obj.timestamp)



View it on GitLab: https://dev.gajim.org/gajim/gajim/compare/fcb33a10e711d15ccd0c1fd5fc5b3a12f8487f94...b600328639125320cf9738928c9f03fa9ee6a108

-- 
View it on GitLab: https://dev.gajim.org/gajim/gajim/compare/fcb33a10e711d15ccd0c1fd5fc5b3a12f8487f94...b600328639125320cf9738928c9f03fa9ee6a108
You're receiving this email because of your account on dev.gajim.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.gajim.org/pipermail/commits/attachments/20190104/a2d6e03b/attachment-0001.html>


More information about the Commits mailing list