diff --git a/gajim/common/connection.py b/gajim/common/connection.py
index d06bd7aaa..08777d8c8 100644
--- a/gajim/common/connection.py
+++ b/gajim/common/connection.py
@@ -367,12 +367,6 @@ class CommonConnection:
additional_data=obj.additional_data,
stanza_id=obj.stanza_id)
- def unsubscribe_agent(self, agent):
- """
- To be implemented by derived classes
- """
- raise NotImplementedError
-
def update_contact(self, jid, name, groups):
if self.connection:
self.getRoster().set_item(jid=jid, name=name, groups=groups)
@@ -1602,17 +1596,6 @@ class Connection(CommonConnection, ConnectionHandlers):
return
self.connection.send(stanza)
- def unsubscribe_agent(self, agent):
- if not app.account_is_connected(self.name):
- return
- iq = nbxmpp.Iq('set', nbxmpp.NS_REGISTER, to=agent)
- iq.setQuery().setTag('remove')
- id_ = self.connection.getAnID()
- iq.setID(id_)
- self.awaiting_answers[id_] = (AGENT_REMOVED, agent)
- self.connection.send(iq)
- self.getRoster().del_item(agent)
-
def send_new_account_infos(self, form, is_form):
if is_form:
# Get username and password and put them in new_account_info
@@ -1656,20 +1639,6 @@ class Connection(CommonConnection, ConnectionHandlers):
self.connection = con
nbxmpp.features_nb.getRegInfo(con, self._hostname)
- def request_gateway_prompt(self, jid, prompt=None):
- def _on_prompt_result(resp):
- app.nec.push_incoming_event(GatewayPromptReceivedEvent(None,
- conn=self, stanza=resp))
- if prompt:
- typ_ = 'set'
- else:
- typ_ = 'get'
- iq = nbxmpp.Iq(typ=typ_, to=jid)
- query = iq.addChild(name='query', namespace=nbxmpp.NS_GATEWAY)
- if prompt:
- query.setTagData('prompt', prompt)
- self.connection.SendAndCallForResponse(iq, _on_prompt_result)
-
def getRoster(self):
return self.get_module('Roster')
diff --git a/gajim/common/connection_handlers.py b/gajim/common/connection_handlers.py
index 77234ef86..486c62c3b 100644
--- a/gajim/common/connection_handlers.py
+++ b/gajim/common/connection_handlers.py
@@ -38,25 +38,15 @@ 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.nec import NetworkEvent
from gajim.common.protocol.bytestream import ConnectionSocks5Bytestream
from gajim.common.protocol.bytestream import ConnectionIBBytestream
log = logging.getLogger('gajim.c.connection_handlers')
-# kind of events we can wait for an answer
-AGENT_REMOVED = 'agent_removed'
-
# basic connection handlers used here and in zeroconf
class ConnectionHandlersBase:
def __init__(self):
- # List of IDs we are waiting answers for {id: (type_of_request, data), }
- self.awaiting_answers = {}
- # List of IDs that will produce a timeout is answer doesn't arrive
- # {time_of_the_timeout: (id, message to send to gui), }
- self.awaiting_timeouts = {}
-
# keep track of sessions this connection has with other JIDs
self.sessions = {}
@@ -291,35 +281,6 @@ class ConnectionHandlers(ConnectionSocks5Bytestream,
app.ged.remove_event_handler('agent-removed', ged.CORE,
self._nec_agent_removed)
- def _ErrorCB(self, con, iq_obj):
- log.debug('ErrorCB')
- app.nec.push_incoming_event(IqErrorReceivedEvent(None, conn=self,
- stanza=iq_obj))
-
- def _IqCB(self, con, iq_obj, properties):
- id_ = iq_obj.getID()
-
- app.nec.push_incoming_event(NetworkEvent('raw-iq-received',
- conn=self, stanza=iq_obj))
-
- # Check if we were waiting a timeout for this id
- found_tim = None
- for tim in self.awaiting_timeouts:
- if id_ == self.awaiting_timeouts[tim][0]:
- found_tim = tim
- break
- if found_tim:
- del self.awaiting_timeouts[found_tim]
-
- if id_ not in self.awaiting_answers:
- return
-
- if self.awaiting_answers[id_][0] == AGENT_REMOVED:
- jid = self.awaiting_answers[id_][1]
- app.nec.push_incoming_event(AgentRemovedEvent(None, conn=self,
- agent=jid))
- del self.awaiting_answers[id_]
-
def _nec_agent_removed(self, obj):
if obj.conn.name != self.name:
return
@@ -445,8 +406,6 @@ class ConnectionHandlers(ConnectionSocks5Bytestream,
con.RegisterHandler('iq', self._JingleCB, 'result')
con.RegisterHandler('iq', self._JingleCB, 'error')
con.RegisterHandler('iq', self._JingleCB, 'set', nbxmpp.NS_JINGLE)
- con.RegisterHandler('iq', self._ErrorCB, 'error')
- con.RegisterHandler('iq', self._IqCB)
con.RegisterHandler('iq', self._ResultCB, 'result')
con.RegisterHandler('unknown', self._StreamCB,
nbxmpp.NS_XMPP_STREAMS, xmlns=nbxmpp.NS_STREAMS)
diff --git a/gajim/common/connection_handlers_events.py b/gajim/common/connection_handlers_events.py
index 7f9db35a8..da8ddcedb 100644
--- a/gajim/common/connection_handlers_events.py
+++ b/gajim/common/connection_handlers_events.py
@@ -119,16 +119,6 @@ class HelperEvent:
self.muc_pm = muc_user.getChildren() == []
return self.muc_pm
-class IqErrorReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
- name = 'iq-error-received'
-
- def generate(self):
- self.get_id()
- self.get_jid_resource(check_fake_jid=True)
- self.errmsg = self.stanza.getErrorMsg()
- self.errcode = self.stanza.getErrorCode()
- return True
-
class StreamReceivedEvent(nec.NetworkIncomingEvent):
name = 'stream-received'
@@ -266,16 +256,6 @@ class StanzaReceivedEvent(nec.NetworkIncomingEvent):
class StanzaSentEvent(nec.NetworkIncomingEvent):
name = 'stanza-sent'
-class AgentRemovedEvent(nec.NetworkIncomingEvent):
- name = 'agent-removed'
-
- def generate(self):
- self.jid_list = []
- for jid in app.contacts.get_jid_list(self.conn.name):
- if jid.endswith('@' + self.agent):
- self.jid_list.append(jid)
- return True
-
class BadGPGPassphraseEvent(nec.NetworkIncomingEvent):
name = 'bad-gpg-passphrase'
@@ -479,22 +459,6 @@ class FileTransferCompletedEvent(nec.NetworkIncomingEvent):
self.jid = app.get_jid_without_resource(jid)
return True
-class GatewayPromptReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
- name = 'gateway-prompt-received'
-
- def generate(self):
- self.get_jid_resource()
- query = self.stanza.getTag('query')
- if query:
- self.desc = query.getTagData('desc')
- self.prompt = query.getTagData('prompt')
- self.prompt_jid = query.getTagData('jid')
- else:
- self.desc = None
- self.prompt = None
- self.prompt_jid = None
- return True
-
class NotificationEvent(nec.NetworkIncomingEvent):
name = 'notification'
base_network_events = ['decrypted-message-received',
diff --git a/gajim/common/modules/__init__.py b/gajim/common/modules/__init__.py
index c5aea976d..77403cb9d 100644
--- a/gajim/common/modules/__init__.py
+++ b/gajim/common/modules/__init__.py
@@ -26,7 +26,8 @@ from gajim.common.types import ConnectionT
log = logging.getLogger('gajim.c.m')
-ZEROCONF_MODULES = ['adhoc_commands',
+ZEROCONF_MODULES = ['iq',
+ 'adhoc_commands',
'receipts',
'discovery',
'chatstates']
diff --git a/gajim/common/modules/gateway.py b/gajim/common/modules/gateway.py
new file mode 100644
index 000000000..57a1d7ada
--- /dev/null
+++ b/gajim/common/modules/gateway.py
@@ -0,0 +1,95 @@
+# 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-0100: Gateway Interaction
+
+import logging
+
+import nbxmpp
+
+from gajim.common import app
+from gajim.common.nec import NetworkEvent
+
+log = logging.getLogger('gajim.c.m.gateway')
+
+
+class Gateway:
+ def __init__(self, con):
+ self._con = con
+ self._account = con.name
+
+ self.handlers = []
+
+ def unsubscribe(self, agent):
+ if not app.account_is_connected(self._account):
+ return
+ iq = nbxmpp.Iq('set', nbxmpp.NS_REGISTER, to=agent)
+ iq.setQuery().setTag('remove')
+
+ self._con.connection.SendAndCallForResponse(
+ iq, self._on_unsubscribe_result)
+ self._con.getRoster().del_item(agent)
+
+ def _on_unsubscribe_result(self, stanza):
+ if not nbxmpp.isResultNode(stanza):
+ log.info('Error: %s', stanza.getError())
+ return
+
+ agent = stanza.getFrom().getBare()
+ jid_list = []
+ for jid in app.contacts.get_jid_list(self._account):
+ if jid.endswith('@' + agent):
+ jid_list.append(jid)
+
+ app.nec.push_incoming_event(
+ NetworkEvent('agent-removed',
+ conn=self._con,
+ agent=agent,
+ jid_list=jid_list))
+
+ def request_gateway_prompt(self, jid, prompt=None):
+ typ_ = 'get'
+ if prompt:
+ typ_ = 'set'
+ iq = nbxmpp.Iq(typ=typ_, to=jid)
+ query = iq.addChild(name='query', namespace=nbxmpp.NS_GATEWAY)
+ if prompt:
+ query.setTagData('prompt', prompt)
+ self._con.connection.SendAndCallForResponse(iq, self._on_prompt_result)
+
+ def _on_prompt_result(self, stanza):
+ jid = str(stanza.getFrom())
+ fjid = stanza.getFrom().getBare()
+ resource = stanza.getFrom().getResource()
+
+ query = stanza.getTag('query')
+ if query is not None:
+ desc = query.getTagData('desc')
+ prompt = query.getTagData('prompt')
+ prompt_jid = query.getTagData('jid')
+ else:
+ desc = None
+ prompt = None
+ prompt_jid = None
+
+ app.nec.push_incoming_event(
+ NetworkEvent('gateway-prompt-received',
+ conn=self._con,
+ fjid=fjid,
+ jid=jid,
+ resource=resource,
+ desc=desc,
+ prompt=prompt,
+ prompt_jid=prompt_jid,
+ stanza=stanza))
diff --git a/gajim/common/modules/iq.py b/gajim/common/modules/iq.py
new file mode 100644
index 000000000..c8e743e4d
--- /dev/null
+++ b/gajim/common/modules/iq.py
@@ -0,0 +1,87 @@
+# 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 .
+
+# Iq handler
+
+import logging
+
+import nbxmpp
+from nbxmpp.const import Error
+from nbxmpp.structs import StanzaHandler
+
+from gajim.common import app
+from gajim.common.nec import NetworkEvent
+from gajim.common.file_props import FilesProp
+
+
+log = logging.getLogger('gajim.c.m.iq')
+
+
+class Iq:
+ def __init__(self, con):
+ self._con = con
+ self._account = con.name
+
+ self.handlers = [
+ StanzaHandler(name='iq',
+ callback=self._iq_error_received,
+ typ='error',
+ priority=51),
+ ]
+
+ def _iq_error_received(self, _con, _stanza, properties):
+ log.info('Error: %s', properties.error)
+ if properties.error.type in (Error.JID_MALFORMED,
+ Error.FORBIDDEN,
+ Error.NOT_ACCEPTABLE):
+ sid = self._get_sid(properties.id)
+ file_props = FilesProp.getFileProp(self._account, sid)
+ if file_props:
+ if properties.error.type == Error.JID_MALFORMED:
+ file_props.error = -3
+ else:
+ file_props.error = -4
+ app.nec.push_incoming_event(
+ NetworkEvent('file-request-error',
+ conn=self._con,
+ jid=properties.jid.getBare(),
+ file_props=file_props,
+ error_msg=properties.error.message))
+ self._con.disconnect_transfer(file_props)
+ raise nbxmpp.NodeProcessed
+
+ if properties.error.type == Error.ITEM_NOT_FOUND:
+ sid = self._get_sid(properties.id)
+ file_props = FilesProp.getFileProp(self._account, sid)
+ if file_props:
+ app.nec.push_incoming_event(
+ NetworkEvent('file-send-error',
+ account=self._account,
+ jid=str(properties.jid),
+ file_props=file_props))
+ self._con.disconnect_transfer(file_props)
+ raise nbxmpp.NodeProcessed
+
+ app.nec.push_incoming_event(
+ NetworkEvent('iq-error-received',
+ account=self._account,
+ properties=properties))
+ raise nbxmpp.NodeProcessed
+
+ @staticmethod
+ def _get_sid(id_):
+ sid = id_
+ if len(id_) > 3 and id_[2] == '_':
+ sid = id_[3:]
+ return sid
diff --git a/gajim/common/zeroconf/connection_handlers_zeroconf.py b/gajim/common/zeroconf/connection_handlers_zeroconf.py
index 8d3f0259b..dba3e8e94 100644
--- a/gajim/common/zeroconf/connection_handlers_zeroconf.py
+++ b/gajim/common/zeroconf/connection_handlers_zeroconf.py
@@ -44,8 +44,6 @@ log = logging.getLogger('gajim.c.z.connection_handlers_zeroconf')
STATUS_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd',
'invisible']
-# kind of events we can wait for an answer
-AGENT_REMOVED = 'agent_removed'
class ZeroconfMessageReceivedEvent(NetworkIncomingEvent):
diff --git a/gajim/gtk/add_contact.py b/gajim/gtk/add_contact.py
index 5928b2a4a..f1f486089 100644
--- a/gajim/gtk/add_contact.py
+++ b/gajim/gtk/add_contact.py
@@ -115,7 +115,8 @@ class AddNewContactWindow(Gtk.ApplicationWindow):
if account:
for service in self.agents[type_]:
- app.connections[account].request_gateway_prompt(service)
+ con = app.connections[account]
+ con.get_module('Gateway').request_gateway_prompt(service)
self.protocol_combobox.set_active(0)
self.auto_authorize_checkbutton.show()
@@ -246,8 +247,8 @@ class AddNewContactWindow(Gtk.ApplicationWindow):
transport = model[row][0]
if self.account and not self.jid_escaped:
self.adding_jid = (jid, transport, type_)
- app.connections[self.account].request_gateway_prompt(
- transport, jid)
+ con = app.connections[self.account]
+ con.get_module('Gateway').request_gateway_prompt(transport, jid)
else:
jid = jid.replace('@', '%') + '@' + transport
self._add_jid(jid, type_)
diff --git a/gajim/gui_interface.py b/gajim/gui_interface.py
index 360432ea2..2d33c0fce 100644
--- a/gajim/gui_interface.py
+++ b/gajim/gui_interface.py
@@ -87,7 +87,7 @@ from gajim.common import passwords
from gajim.common import logging_helpers
from gajim.common.i18n import _
from gajim.common.connection_handlers_events import (
- OurShowEvent, FileRequestErrorEvent, FileTransferCompletedEvent,
+ OurShowEvent, FileTransferCompletedEvent,
UpdateRosterAvatarEvent, UpdateGCAvatarEvent, UpdateRoomAvatarEvent)
from gajim.common.modules.httpupload import HTTPUploadProgressEvent
@@ -199,38 +199,11 @@ class Interface:
'id': obj.iq_id}, sec_msg, on_response_yes=(on_yes, obj),
on_response_no=(response, obj, 'no'))
- def handle_event_iq_error(self, obj):
- #('ERROR_ANSWER', account, (id_, fjid, errmsg, errcode))
- if str(obj.errcode) in ('400', '403', '406') and obj.id_:
- # show the error dialog
- sid = obj.id_
- if len(obj.id_) > 3 and obj.id_[2] == '_':
- sid = obj.id_[3:]
- file_props = FilesProp.getFileProp(obj.conn.name, sid)
- if file_props:
- if str(obj.errcode) == '400':
- file_props.error = -3
- else:
- file_props.error = -4
- app.nec.push_incoming_event(FileRequestErrorEvent(None,
- conn=obj.conn, jid=obj.jid, file_props=file_props,
- error_msg=obj.errmsg))
- obj.conn.disconnect_transfer(file_props)
- return
- elif str(obj.errcode) == '404':
- sid = obj.id_
- if len(obj.id_) > 3 and obj.id_[2] == '_':
- sid = obj.id_[3:]
- file_props = FilesProp.getFileProp(obj.conn.name, sid)
- if file_props:
- self.handle_event_file_send_error(obj.conn.name, (obj.fjid,
- file_props))
- obj.conn.disconnect_transfer(file_props)
- return
-
- ctrl = self.msg_win_mgr.get_control(obj.fjid, obj.conn.name)
+ def handle_event_iq_error(self, event):
+ ctrl = self.msg_win_mgr.get_control(event.properties.jid.getBare(),
+ event.account)
if ctrl and ctrl.type_id == message_control.TYPE_GC:
- ctrl.print_conversation('Error %s: %s' % (obj.errcode, obj.errmsg))
+ ctrl.print_conversation('Error: %s' % event.properties.error)
@staticmethod
def handle_event_connection_lost(obj):
@@ -739,25 +712,23 @@ class Interface:
def handle_event_bookmarks(self, obj):
gui_menu_builder.build_bookmark_menu(obj.account)
- def handle_event_file_send_error(self, account, array):
- jid = array[0]
- file_props = array[1]
+ def handle_event_file_send_error(self, event):
ft = self.instances['file_transfers']
- ft.set_status(file_props, 'stop')
+ ft.set_status(event.file_props, 'stop')
- if helpers.allow_popup_window(account):
- ft.show_send_error(file_props)
+ if helpers.allow_popup_window(event.account):
+ ft.show_send_error(event.file_props)
return
- event = events.FileSendErrorEvent(file_props)
- self.add_event(account, jid, event)
+ event = events.FileSendErrorEvent(event.file_props)
+ self.add_event(event.account, event.jid, event)
- if helpers.allow_showing_notification(account):
+ if helpers.allow_showing_notification(event.account):
event_type = _('File Transfer Error')
app.notification.popup(
- event_type, jid, account,
+ event_type, event.jid, event.account,
'file-send-error', 'gajim-ft_error',
- event_type, file_props.name)
+ event_type, event.file_props.name)
def handle_event_file_request_error(self, obj):
# ('FILE_REQUEST_ERROR', account, (jid, file_props, error_msg))
@@ -1383,7 +1354,7 @@ class Interface:
def create_core_handlers_list(self):
self.handlers = {
'DB_ERROR': [self.handle_event_db_error],
- 'FILE_SEND_ERROR': [self.handle_event_file_send_error],
+ 'file-send-error': [self.handle_event_file_send_error],
'pep-received': [self.handle_atom_entry],
'bad-gpg-passphrase': [self.handle_event_bad_gpg_passphrase],
'bookmarks-received': [self.handle_event_bookmarks],
diff --git a/gajim/roster_window.py b/gajim/roster_window.py
index c4b02d43d..b09628cff 100644
--- a/gajim/roster_window.py
+++ b/gajim/roster_window.py
@@ -2774,7 +2774,7 @@ class RosterWindow:
def remove(list_):
for (contact, account) in list_:
full_jid = contact.get_full_jid()
- app.connections[account].unsubscribe_agent(full_jid)
+ app.connections[account].get_module('Gateway').unsubscribe(full_jid)
# remove transport from treeview
self.remove_contact(contact.jid, account, backend=True)