diff --git a/gajim/common/connection.py b/gajim/common/connection.py index 6a0f2c63a..f004520cd 100644 --- a/gajim/common/connection.py +++ b/gajim/common/connection.py @@ -1486,6 +1486,9 @@ class Connection(CommonConnection, ConnectionHandlers): # Get bookmarks self.get_module('Bookmarks').request_bookmarks() + # Enable Software Version + self.get_module('SoftwareVersion').set_enabled(True) + # Get annotations self.get_module('Annotations').request_annotations() diff --git a/gajim/common/modules/software_version.py b/gajim/common/modules/software_version.py index 56f891b8a..86f5cb0fa 100644 --- a/gajim/common/modules/software_version.py +++ b/gajim/common/modules/software_version.py @@ -6,101 +6,39 @@ # # 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 +# 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/>. +# along with Gajim. If not, see <http://www.gnu.org/licenses/>. # XEP-0092: Software Version -import nbxmpp -from nbxmpp.structs import StanzaHandler - from gajim.common import app from gajim.common.helpers import get_os_info -from gajim.common.nec import NetworkIncomingEvent from gajim.common.modules.base import BaseModule class SoftwareVersion(BaseModule): + + _nbxmpp_extends = 'SoftwareVersion' + _nbxmpp_methods = [ + 'set_software_version', + 'request_software_version', + 'disable', + ] + def __init__(self, con): BaseModule.__init__(self, con) - self.handlers = [ - StanzaHandler(name='iq', - callback=self._answer_request, - typ='get', - ns=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) - - self._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): - self._log.info('Error: %s', stanza.getError()) + def set_enabled(self, enabled): + if enabled: + if not app.config.get_per('accounts', self._account, 'send_os_info'): + return + self._nbxmpp('SoftwareVersion').set_software_version( + 'Gajim', app.version, get_os_info()) else: - try: - client_info, os_info = self._extract_info(stanza) - except Exception: - self._log.exception('Error') - self._log.error(stanza) - - self._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)) - - @staticmethod - def _extract_info(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, _properties): - self._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) - self._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) - self._log.info('Send service-unavailable') - self._con.connection.send(iq) - raise nbxmpp.NodeProcessed - - -class VersionResultReceivedEvent(NetworkIncomingEvent): - name = 'version-result-received' + self._nbxmpp('SoftwareVersion').disable() def get_instance(*args, **kwargs): diff --git a/gajim/gtk/preferences.py b/gajim/gtk/preferences.py index 2b542c5ab..f0b4bf776 100644 --- a/gajim/gtk/preferences.py +++ b/gajim/gtk/preferences.py @@ -879,6 +879,8 @@ class Preferences(Gtk.ApplicationWindow): def on_send_os_info_checkbutton_toggled(self, widget): widget.set_inconsistent(False) self.on_per_account_checkbutton_toggled(widget, 'send_os_info') + for con in app.connections.values(): + con.get_module('SoftwareVersion').set_enabled(widget.get_active()) def on_ignore_events_from_unknown_contacts_checkbutton_toggled(self, widget): widget.set_inconsistent(False) diff --git a/gajim/gtk/server_info.py b/gajim/gtk/server_info.py index 7aa4e2b4a..670d7b54a 100644 --- a/gajim/gtk/server_info.py +++ b/gajim/gtk/server_info.py @@ -17,6 +17,7 @@ from collections import namedtuple from datetime import timedelta import nbxmpp +from nbxmpp.util import is_error_result from gi.repository import Gtk from gi.repository import Gdk @@ -24,6 +25,8 @@ from gajim.common import app from gajim.common import ged from gajim.common.i18n import _ +from gajim.gtk.util import ensure_not_destroyed + log = logging.getLogger('gajim.gtk.serverinfo') @@ -34,6 +37,7 @@ class ServerInfoDialog(Gtk.Dialog): destroy_with_parent=True) self.account = account + self._destroyed = False self.set_transient_for(app.interface.roster.window) self.set_resizable(False) @@ -69,10 +73,6 @@ class ServerInfoDialog(Gtk.Dialog): self.connect('response', self.on_response) self.connect('destroy', self.on_destroy) - app.ged.register_event_handler('version-result-received', - ged.CORE, - self._nec_version_result_received) - app.ged.register_event_handler('server-disco-received', ged.GUI1, self._server_disco_received) @@ -81,7 +81,8 @@ class ServerInfoDialog(Gtk.Dialog): self.uptime = '' self.hostname = app.get_hostname_from_account(account) con = app.connections[account] - con.get_module('SoftwareVersion').request_os_info(self.hostname, None) + con.get_module('SoftwareVersion').request_software_version( + self.hostname, callback=self._software_version_received) self.request_last_activity() for feature in self.get_features(): @@ -138,10 +139,12 @@ class ServerInfoDialog(Gtk.Dialog): 'days': delta.days, 'hours': hours} self.update(self.get_infos, self.info_listbox) - def _nec_version_result_received(self, obj): - if obj.jid != self.hostname: - return - self.version = obj.client_info or _('Unknown') + @ensure_not_destroyed + def _software_version_received(self, result): + if is_error_result(result): + self.version = _('Unknown') + else: + self.version = '%s %s' % (result.name, result.version) self.update(self.get_infos, self.info_listbox) def _server_disco_received(self, obj): @@ -229,11 +232,8 @@ class ServerInfoDialog(Gtk.Dialog): self.destroy() def on_destroy(self, *args): + self._destroyed = True del app.interface.instances[self.account]['server_info'] - app.ged.remove_event_handler('version-result-received', - ged.CORE, - self._nec_version_result_received) - app.ged.remove_event_handler('server-disco-received', ged.GUI1, self._server_disco_received) diff --git a/gajim/remote_control.py b/gajim/remote_control.py index 45364b1d6..ca1ee742a 100644 --- a/gajim/remote_control.py +++ b/gajim/remote_control.py @@ -267,9 +267,6 @@ class GajimRemote(Server): <signal name='NewMessage'> <arg type='av' /> </signal> - <signal name='OsInfo'> - <arg type='av' /> - </signal> <signal name='Roster'> <arg type='av' /> </signal> @@ -299,8 +296,6 @@ class GajimRemote(Server): super().__init__(self.con, '/org/gajim/dbus/RemoteObject') self.first_show = True - app.ged.register_event_handler('version-result-received', ged.POSTGUI, - self.on_os_info) app.ged.register_event_handler('time-result-received', ged.POSTGUI, self.on_time) app.ged.register_event_handler('roster-info', ged.POSTGUI, @@ -346,12 +341,6 @@ class GajimRemote(Server): self.raise_signal('MessageSent', (obj.conn.name, [ obj.jid, obj.message, obj.keyID, chatstate])) - def on_os_info(self, obj): - self.raise_signal('OsInfo', (obj.conn.name, [obj.jid.getStripped(), - obj.jid.getResource(), - obj.client_info, - obj.os_info])) - def on_time(self, obj): self.raise_signal('EntityTime', (obj.conn.name, [obj.jid.getStripped(), obj.jid.getResource(), diff --git a/gajim/vcard.py b/gajim/vcard.py index 9dae488e6..ca3550e8e 100644 --- a/gajim/vcard.py +++ b/gajim/vcard.py @@ -33,6 +33,8 @@ from gi.repository import Gtk from gi.repository import GLib from gi.repository import Gdk from nbxmpp.structs import AnnotationNote +from nbxmpp.util import is_error_result +from nbxmpp.protocol import JID from gajim import gtkgui_helpers from gajim.gui_menu_builder import show_save_as_menu @@ -102,8 +104,6 @@ class VcardWindow: self.update_progressbar_timeout_id = GLib.timeout_add(self.update_intervall, self.update_progressbar) - app.ged.register_event_handler('version-result-received', ged.GUI1, - self.set_os_info) app.ged.register_event_handler('time-result-received', ged.GUI1, self.set_entity_time) @@ -148,8 +148,6 @@ class VcardWindow: if note is None or new_annotation != note.data: new_note = AnnotationNote(jid=self.contact.jid, data=new_annotation) con.get_module('Annotations').set_note(new_note) - app.ged.remove_event_handler('version-result-received', ged.GUI1, - self.set_os_info) app.ged.remove_event_handler('time-result-received', ged.GUI1, self.set_entity_time) @@ -263,34 +261,27 @@ class VcardWindow: self.clear_values() self._set_values(vcard, jid) - def set_os_info(self, obj): - if obj.conn.name != self.account: - return + def set_os_info(self, result, jid): if self.xml.get_object('information_notebook').get_n_pages() < 5: return - if self.gc_contact: - if obj.jid != self.contact.jid: - return - elif obj.jid.getStripped() != self.contact.jid: - return + + error = is_error_result(result) i = 0 client = '' os_info = '' while i in self.os_info: - if self.os_info[i]['resource'] == obj.jid.getResource(): - if obj.client_info: - self.os_info[i]['client'] = obj.client_info + if self.os_info[i]['resource'] == JID(jid).getResource(): + if not error: + self.os_info[i]['client'] = '%s %s' % (result.name, + result.version) else: self.os_info[i]['client'] = Q_('?Client:Unknown') - if obj.os_info: - self.os_info[i]['os'] = obj.os_info + + if not error and result.os is not None: + self.os_info[i]['os'] = result.os else: self.os_info[i]['os'] = Q_('?OS:Unknown') - else: - if not self.os_info[i]['client']: - self.os_info[i]['client'] = Q_('?Client:Unknown') - if not self.os_info[i]['os']: - self.os_info[i]['os'] = Q_('?OS:Unknown') + if i > 0: client += '\n' os_info += '\n' @@ -417,12 +408,16 @@ class VcardWindow: self.os_info_arrived = True 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(con.get_module('SoftwareVersion').request_os_info, - j, r) + con.get_module('SoftwareVersion').request_software_version( + self.real_jid, + callback=self.set_os_info, + user_data=self.real_jid) else: - GLib.idle_add(con.get_module('SoftwareVersion').request_os_info, - self.contact.jid, self.contact.resource) + jid = self.contact.get_full_jid() + con.get_module('SoftwareVersion').request_software_version( + jid, + callback=self.set_os_info, + user_data=jid) # 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 @@ -451,8 +446,9 @@ class VcardWindow: uf_resources += '\n' + c.resource + \ _(' resource with priority ') + str(c.priority) if c.show not in ('offline', 'error'): - GLib.idle_add(con.get_module('SoftwareVersion').request_os_info, - c.jid, c.resource) + jid = c.get_full_jid() + con.get_module('SoftwareVersion').request_software_version( + jid, callback=self.set_os_info, user_data=jid) GLib.idle_add(con.get_module('EntityTime').request_entity_time, c.jid, c.resource) self.os_info[i] = {'resource': c.resource, 'client': '',