From 81d9e1bcf231d1fc729b3cf8c93bd5d6275b6985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Sun, 24 Jun 2018 19:53:09 +0200 Subject: [PATCH] Refactor software version code into own module --- gajim/common/connection.py | 30 +----- gajim/common/connection_handlers.py | 43 --------- gajim/common/connection_handlers_events.py | 30 ------ gajim/common/modules/software_version.py | 106 +++++++++++++++++++++ gajim/remote_control.py | 6 +- gajim/server_info.py | 3 +- gajim/vcard.py | 19 ++-- 7 files changed, 123 insertions(+), 114 deletions(-) create mode 100644 gajim/common/modules/software_version.py diff --git a/gajim/common/connection.py b/gajim/common/connection.py index c576006a9..0e4eee441 100644 --- a/gajim/common/connection.py +++ b/gajim/common/connection.py @@ -64,6 +64,7 @@ from gajim.common import passwords from gajim.common import i18n from gajim.common import idle from gajim.common.modules.entity_time import EntityTime +from gajim.common.modules.software_version import SoftwareVersion from gajim.common.connection_handlers import * from gajim.common.contacts import GC_Contact from gajim.gtkgui_helpers import get_action @@ -482,12 +483,6 @@ class CommonConnection: def account_changed(self, new_name): self.name = new_name - def request_os_info(self, jid, resource): - """ - To be implemented by derived classes - """ - raise NotImplementedError - def get_settings(self): """ To be implemented by derived classes @@ -665,6 +660,7 @@ class Connection(CommonConnection, ConnectionHandlers): self.sm = Smacks(self) # Stream Management self.register_module('EntityTime', EntityTime, self) + self.register_module('SoftwareVersion', SoftwareVersion, self) app.ged.register_event_handler('privacy-list-received', ged.CORE, self._nec_privacy_list_received) @@ -2245,28 +2241,6 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection = con nbxmpp.features_nb.getRegInfo(con, self._hostname) - def request_os_info(self, jid, resource, groupchat_jid=None): - """ - groupchat_jid is used when we want to send a request to a real jid and - act as if the answer comes from the groupchat_jid - """ - if not app.account_is_connected(self.name): - return - # If we are invisible, do not request - if self.connected == app.SHOW_LIST.index('invisible'): - self.dispatch('OS_INFO', (jid, resource, _('Not fetched because of invisible status'), _('Not fetched because of invisible status'))) - return - to_whom_jid = jid - if resource: - to_whom_jid += '/' + resource - iq = nbxmpp.Iq(to=to_whom_jid, typ='get', queryNS=nbxmpp.NS_VERSION) - id_ = self.connection.getAnID() - iq.setID(id_) - if groupchat_jid: - self.groupchat_jids[id_] = groupchat_jid - self.version_ids.append(id_) - self.connection.send(iq) - def request_gateway_prompt(self, jid, prompt=None): def _on_prompt_result(resp): app.nec.push_incoming_event(GatewayPromptReceivedEvent(None, diff --git a/gajim/common/connection_handlers.py b/gajim/common/connection_handlers.py index f0dfe6917..7e26380b5 100644 --- a/gajim/common/connection_handlers.py +++ b/gajim/common/connection_handlers.py @@ -1324,8 +1324,6 @@ ConnectionHTTPUpload): # keep the latest subscribed event for each jid to prevent loop when we # acknowledge presences self.subscribed_events = {} - # IDs of jabber:iq:version requests - self.version_ids = [] # IDs of disco#items requests self.disco_items_ids = [] # IDs of disco#info requests @@ -1351,8 +1349,6 @@ ConnectionHTTPUpload): app.ged.register_event_handler('http-auth-received', ged.CORE, self._nec_http_auth_received) - app.ged.register_event_handler('version-request-received', ged.CORE, - self._nec_version_request_received) app.ged.register_event_handler('last-request-received', ged.CORE, self._nec_last_request_received) app.ged.register_event_handler('time-request-received', ged.CORE, @@ -1394,8 +1390,6 @@ ConnectionHTTPUpload): ConnectionHTTPUpload.cleanup(self) app.ged.remove_event_handler('http-auth-received', ged.CORE, self._nec_http_auth_received) - app.ged.remove_event_handler('version-request-received', ged.CORE, - self._nec_version_request_received) app.ged.remove_event_handler('last-request-received', ged.CORE, self._nec_last_request_received) app.ged.remove_event_handler('time-request-received', ged.CORE, @@ -1579,10 +1573,6 @@ ConnectionHTTPUpload): def _nec_iq_error_received(self, obj): if obj.conn.name != self.name: return - if obj.id_ in self.version_ids: - app.nec.push_incoming_event(VersionResultReceivedEvent(None, - conn=self, stanza=obj.stanza)) - return True if obj.id_ in self.disco_items_ids: app.nec.push_incoming_event(AgentItemsErrorReceivedEvent(None, conn=self, stanza=obj.stanza)) @@ -1672,31 +1662,6 @@ ConnectionHTTPUpload): app.config.set_per('accounts', self.name, 'roster_version', obj.version) - def _VersionCB(self, con, iq_obj): - log.debug('VersionCB') - if not self.connection or self.connected < 2: - return - app.nec.push_incoming_event(VersionRequestEvent(None, conn=self, - stanza=iq_obj)) - raise nbxmpp.NodeProcessed - - def _nec_version_request_received(self, obj): - if obj.conn.name != self.name: - return - send_os = app.config.get_per('accounts', self.name, 'send_os_info') - if send_os: - iq_obj = obj.stanza.buildReply('result') - qp = iq_obj.getQuery() - qp.setTagData('name', 'Gajim') - qp.setTagData('version', app.version) - qp.setTagData('os', helpers.get_os_info()) - else: - iq_obj = obj.stanza.buildReply('error') - err = nbxmpp.ErrorNode(name=nbxmpp.NS_STANZAS + \ - ' service-unavailable') - iq_obj.addChild(node=err) - self.connection.send(iq_obj) - def _LastCB(self, con, iq_obj): log.debug('LastCB') if not self.connection or self.connected < 2: @@ -1720,11 +1685,6 @@ ConnectionHTTPUpload): iq_obj.addChild(node=err) self.connection.send(iq_obj) - def _VersionResultCB(self, con, iq_obj): - log.debug('VersionResultCB') - app.nec.push_incoming_event(VersionResultReceivedEvent(None, - conn=self, stanza=iq_obj)) - def _TimeCB(self, con, iq_obj): log.debug('TimeCB') if not self.connection or self.connected < 2: @@ -2220,11 +2180,8 @@ ConnectionHTTPUpload): nbxmpp.NS_DISCO_INFO) con.RegisterHandler('iq', self._DiscoverInfoErrorCB, 'error', nbxmpp.NS_DISCO_INFO) - con.RegisterHandler('iq', self._VersionCB, 'get', nbxmpp.NS_VERSION) con.RegisterHandler('iq', self._TimeCB, 'get', nbxmpp.NS_TIME) con.RegisterHandler('iq', self._LastCB, 'get', nbxmpp.NS_LAST) - con.RegisterHandler('iq', self._VersionResultCB, 'result', - nbxmpp.NS_VERSION) con.RegisterHandler('iq', self._MucOwnerCB, 'result', nbxmpp.NS_MUC_OWNER) con.RegisterHandler('iq', self._MucAdminCB, 'result', diff --git a/gajim/common/connection_handlers_events.py b/gajim/common/connection_handlers_events.py index ac0fb555e..554a7db1e 100644 --- a/gajim/common/connection_handlers_events.py +++ b/gajim/common/connection_handlers_events.py @@ -193,32 +193,6 @@ class HttpAuthReceivedEvent(nec.NetworkIncomingEvent): self.msg = self.stanza.getTagData('body') return True -class VersionResultReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): - name = 'version-result-received' - base_network_events = [] - - def generate(self): - self.get_id() - self.get_jid_resource(check_fake_jid=True) - if self.id_ in self.conn.version_ids: - self.conn.version_ids.remove(self.id_) - - self.client_info = '' - self.os_info = '' - - if self.stanza.getType() == 'error': - return True - - qp = self.stanza.getTag('query') - if qp.getTag('name'): - self.client_info += qp.getTag('name').getData() - if qp.getTag('version'): - self.client_info += ' ' + qp.getTag('version').getData() - if qp.getTag('os'): - self.os_info += qp.getTag('os').getData() - - return True - class RosterItemExchangeEvent(nec.NetworkIncomingEvent, HelperEvent): name = 'roster-item-exchange-received' base_network_events = [] @@ -264,10 +238,6 @@ class RosterItemExchangeEvent(nec.NetworkIncomingEvent, HelperEvent): if self.exchange_items_list: return True -class VersionRequestEvent(nec.NetworkIncomingEvent): - name = 'version-request-received' - base_network_events = [] - class LastRequestEvent(nec.NetworkIncomingEvent): name = 'last-request-received' base_network_events = [] diff --git a/gajim/common/modules/software_version.py b/gajim/common/modules/software_version.py new file mode 100644 index 000000000..6fc35f20a --- /dev/null +++ b/gajim/common/modules/software_version.py @@ -0,0 +1,106 @@ +# 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 . + +# XEP-0092: Software Version + +import logging + +import nbxmpp + +from gajim.common import app +from gajim.common.helpers import get_os_info +from gajim.common.nec import NetworkIncomingEvent + +log = logging.getLogger('gajim.c.m.software_version') + + +class SoftwareVersion: + def __init__(self, con): + self._con = con + self._account = con.name + + self.handlers = [ + ('iq', self._answer_request, 'get', nbxmpp.NS_VERSION), + ] + + def request_os_info(self, jid, resource): + if not app.account_is_connected(self._account): + return + # If we are invisible, do not request + if self._con.connected == app.SHOW_LIST.index('invisible'): + return + + if resource: + jid += '/' + resource + iq = nbxmpp.Iq(to=jid, typ='get', queryNS=nbxmpp.NS_VERSION) + + log.info('Requested: %s', jid) + + self._con.connection.SendAndCallForResponse(iq, self._result_received) + + def _result_received(self, stanza): + client_info, os_info = None, None + if not nbxmpp.isResultNode(stanza): + log.info('Error: %s', stanza.getError()) + else: + try: + client_info, os_info = self._extract_info(stanza) + except Exception: + log.exception('Error') + log.error(stanza) + + log.info('Received: %s %s %s', + stanza.getFrom(), client_info, os_info) + + app.nec.push_incoming_event( + VersionResultReceivedEvent(None, conn=self._con, + jid=stanza.getFrom(), + client_info=client_info, + os_info=os_info)) + + def _extract_info(self, stanza): + query = stanza.getTag('query') + name = query.getTag('name').getData() + version = query.getTag('version').getData() + client_info = '%s %s' % (name, version) + os_info = query.getTag('os') + if os_info is not None: + os_info = os_info.getData() + return client_info, os_info + + def _answer_request(self, con, stanza): + log.info('%s asked for the software version', stanza.getFrom()) + if app.config.get_per('accounts', self._account, 'send_os_info'): + os_info = get_os_info() + iq = stanza.buildReply('result') + query = iq.getQuery() + query.setTagData('name', 'Gajim') + query.setTagData('version', app.version) + query.setTagData('os', os_info) + log.info('Answer: Gajim %s %s', app.version, os_info) + else: + iq = stanza.buildReply('error') + err = nbxmpp.ErrorNode(nbxmpp.ERR_SERVICE_UNAVAILABLE) + iq.addChild(node=err) + log.info('Send service-unavailable') + self._con.connection.send(iq) + raise nbxmpp.NodeProcessed + + +class VersionResultReceivedEvent(NetworkIncomingEvent): + name = 'version-result-received' + base_network_events = [] + + def generate(self): + return True diff --git a/gajim/remote_control.py b/gajim/remote_control.py index dd2425c93..5c763e1bb 100644 --- a/gajim/remote_control.py +++ b/gajim/remote_control.py @@ -145,8 +145,10 @@ class Remote: obj.jid, obj.message, obj.keyID, chatstate])) def on_os_info(self, obj): - self.raise_signal('OsInfo', (obj.conn.name, [obj.jid, obj.resource, - obj.client_info, obj.os_info])) + self.raise_signal('OsInfo', (obj.conn.name, [obj.jid.getStripped(), + obj.getResource(), + obj.client_info, + obj.os_info])) def on_time(self, obj): self.raise_signal('EntityTime', (obj.conn.name, [obj.jid.getStripped(), diff --git a/gajim/server_info.py b/gajim/server_info.py index 922fc63a0..26fe5c284 100644 --- a/gajim/server_info.py +++ b/gajim/server_info.py @@ -74,7 +74,8 @@ class ServerInfoDialog(Gtk.Dialog): self.version = '' self.uptime = '' self.hostname = app.get_hostname_from_account(account) - app.connections[account].request_os_info(self.hostname, None) + con = app.connections[account] + con.get_module('SoftwareVersion').request_os_info(self.hostname, None) self.request_last_activity() for feature in self.get_features(): diff --git a/gajim/vcard.py b/gajim/vcard.py index af0729bc7..54b9286b8 100644 --- a/gajim/vcard.py +++ b/gajim/vcard.py @@ -276,15 +276,15 @@ class VcardWindow: if self.xml.get_object('information_notebook').get_n_pages() < 5: return if self.gc_contact: - if obj.fjid != self.contact.jid: + if obj.jid != self.contact.jid: return - elif app.get_jid_without_resource(obj.fjid) != self.contact.jid: + elif obj.jid.getStripped() != self.contact.jid: return i = 0 client = '' os = '' while i in self.os_info: - if self.os_info[i]['resource'] == obj.resource: + if self.os_info[i]['resource'] == obj.jid.getResource(): if obj.client_info: self.os_info[i]['client'] = obj.client_info else: @@ -425,11 +425,11 @@ class VcardWindow: else: # Request os info if contact is connected if self.gc_contact: j, r = app.get_room_and_nick_from_fjid(self.real_jid) - GLib.idle_add(app.connections[self.account].request_os_info, - j, r, self.contact.jid) + GLib.idle_add(con.get_module('SoftwareVersion').request_os_info, + j, r) else: - GLib.idle_add(app.connections[self.account].request_os_info, - self.contact.jid, self.contact.resource) + GLib.idle_add(con.get_module('SoftwareVersion').request_os_info, + self.contact.jid, self.contact.resource) # do not wait for entity_time if contact is not connected or has error # additional check for observer is needed, as show is offline for him @@ -458,8 +458,8 @@ class VcardWindow: uf_resources += '\n' + c.resource + \ _(' resource with priority ') + str(c.priority) if c.show not in ('offline', 'error'): - GLib.idle_add(app.connections[self.account].\ - request_os_info, c.jid, c.resource) + GLib.idle_add(con.get_module('SoftwareVersion').request_os_info, + c.jid, c.resource) GLib.idle_add(con.get_module('EntityTime').request_entity_time, c.jid, c.resource) self.os_info[i] = {'resource': c.resource, 'client': '', @@ -474,7 +474,6 @@ class VcardWindow: self.fill_status_label() - con = app.connections[self.account] if self.gc_contact: con.request_vcard(self._nec_vcard_received, self.gc_contact.get_full_jid(), room=True)