diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index 1105a47bb..85734fd8d 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -1691,3 +1691,64 @@ class AgentInfoErrorReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.get_jid_resource() self.get_id() return True + +class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): + name = 'file-request-received' + base_network_events = [] + + def generate(self): + self.get_id() + self.fjid = self.conn._ft_get_from(self.stanza) + self.jid = gajim.get_jid_without_resource(self.fjid) + self.file_props = {'type': 'r'} + self.file_props['sender'] = self.fjid + self.file_props['request-id'] = self.id_ + si = self.stanza.getTag('si') + profile = si.getAttr('profile') + if profile != xmpp.NS_FILE: + self.conn.send_file_rejection(self.file_props, code='400', typ='profile') + raise xmpp.NodeProcessed + feature_tag = si.getTag('feature', namespace=xmpp.NS_FEATURE) + if not feature_tag: + return + form_tag = feature_tag.getTag('x', namespace=xmpp.NS_DATA) + if not form_tag: + return + self.dataform = dataforms.ExtendForm(node=form_tag) + for f in self.dataform.iter_fields(): + if f.var == 'stream-method' and f.type == 'list-single': + values = [o[1] for o in f.options] + self.file_props['stream-methods'] = ' '.join(values) + if xmpp.NS_BYTESTREAM in values or xmpp.NS_IBB in values: + break + else: + self.conn.send_file_rejection(self.file_props, code='400', typ='stream') + raise xmpp.NodeProcessed + file_tag = si.getTag('file') + for attribute in file_tag.getAttrs(): + if attribute in ('name', 'size', 'hash', 'date'): + val = file_tag.getAttr(attribute) + if val is None: + continue + self.file_props[attribute] = val + file_desc_tag = file_tag.getTag('desc') + if file_desc_tag is not None: + self.file_props['desc'] = file_desc_tag.getData() + + mime_type = si.getAttr('mime-type') + if mime_type is not None: + self.file_props['mime-type'] = mime_type + + self.file_props['receiver'] = self.conn._ft_get_our_jid() + self.file_props['sid'] = unicode(si.getAttr('id')) + self.file_props['transfered_size'] = [] + return True + +class FileRequestErrorEvent(nec.NetworkIncomingEvent): + name = 'file-request-error' + base_network_events = [] + + def generate(self): + self.jid = gajim.get_jid_without_resource(self.jid) + return True + diff --git a/src/common/protocol/bytestream.py b/src/common/protocol/bytestream.py index d88d2e35d..ad8a40e3b 100644 --- a/src/common/protocol/bytestream.py +++ b/src/common/protocol/bytestream.py @@ -37,6 +37,8 @@ from common import xmpp from common import gajim from common import helpers from common import dataforms +from common.connection_handlers_events import FileRequestReceivedEvent +from common import ged from common.socks5 import Socks5Receiver @@ -79,6 +81,8 @@ class ConnectionBytestream: def __init__(self): self.files_props = {} + gajim.ged.register_event_handler('file-request-received', ged.GUI1, + self._nec_file_request_received) def _ft_get_our_jid(self): our_jid = gajim.get_jid_from_account(self.name) @@ -212,52 +216,15 @@ class ConnectionBytestream: raise xmpp.NodeProcessed def _siSetCB(self, con, iq_obj): - jid = self._ft_get_from(iq_obj) - file_props = {'type': 'r'} - file_props['sender'] = jid - file_props['request-id'] = unicode(iq_obj.getAttr('id')) - si = iq_obj.getTag('si') - profile = si.getAttr('profile') - mime_type = si.getAttr('mime-type') - if profile != xmpp.NS_FILE: - self.send_file_rejection(file_props, code='400', typ='profile') - raise xmpp.NodeProcessed - feature_tag = si.getTag('feature', namespace=xmpp.NS_FEATURE) - if not feature_tag: - return - form_tag = feature_tag.getTag('x', namespace=xmpp.NS_DATA) - if not form_tag: - return - form = dataforms.ExtendForm(node=form_tag) - for f in form.iter_fields(): - if f.var == 'stream-method' and f.type == 'list-single': - values = [o[1] for o in f.options] - file_props['stream-methods'] = ' '.join(values) - if xmpp.NS_BYTESTREAM in values or xmpp.NS_IBB in values: - break - else: - self.send_file_rejection(file_props, code='400', typ='stream') - raise xmpp.NodeProcessed - file_tag = si.getTag('file') - for attribute in file_tag.getAttrs(): - if attribute in ('name', 'size', 'hash', 'date'): - val = file_tag.getAttr(attribute) - if val is None: - continue - file_props[attribute] = val - file_desc_tag = file_tag.getTag('desc') - if file_desc_tag is not None: - file_props['desc'] = file_desc_tag.getData() - - if mime_type is not None: - file_props['mime-type'] = mime_type - file_props['receiver'] = self._ft_get_our_jid() - file_props['sid'] = unicode(si.getAttr('id')) - file_props['transfered_size'] = [] - gajim.socks5queue.add_file_props(self.name, file_props) - self.dispatch('FILE_REQUEST', (jid, file_props)) + gajim.nec.push_incoming_event(FileRequestReceivedEvent(None, conn=self, + stanza=iq_obj)) raise xmpp.NodeProcessed + def _nec_file_request_received(self, obj): + if obj.conn.name != self.name: + return + gajim.socks5queue.add_file_props(self.name, obj.file_props) + def _siErrorCB(self, con, iq_obj): si = iq_obj.getTag('si') profile = si.getAttr('profile') @@ -268,7 +235,8 @@ class ConnectionBytestream: return jid = self._ft_get_from(iq_obj) file_props['error'] = -3 - self.dispatch('FILE_REQUEST_ERROR', (jid, file_props, '')) + gajim.nec.push_incoming_event(FileRequestErrorEvent(None, conn=self, + jid=jid, file_props=file_props, error_msg='')) raise xmpp.NodeProcessed class ConnectionSocks5Bytestream(ConnectionBytestream): @@ -300,7 +268,9 @@ class ConnectionSocks5Bytestream(ConnectionBytestream): if contact.get_full_jid() == receiver_jid: file_props['error'] = -5 self.remove_transfer(file_props) - self.dispatch('FILE_REQUEST_ERROR', (contact.jid, file_props, '')) + gajim.nec.push_incoming_event(FileRequestErrorEvent(None, + conn=self, jid=contact.jid, file_props=file_props, + error_msg='')) sender_jid = unicode(file_props['sender']) if contact.get_full_jid() == sender_jid: file_props['error'] = -3 @@ -336,7 +306,7 @@ class ConnectionSocks5Bytestream(ConnectionBytestream): if 'idx' in host and host['idx'] > 0: gajim.socks5queue.remove_receiver(host['idx']) gajim.socks5queue.remove_sender(host['idx']) - + if 'direction' in file_props: # it's a IBB sid = file_props['sid'] @@ -360,7 +330,8 @@ class ConnectionSocks5Bytestream(ConnectionBytestream): self._result_socks5_sid, file_props['sid']) if not listener: file_props['error'] = -5 - self.dispatch('FILE_REQUEST_ERROR', (unicode(receiver), file_props, '')) + gajim.nec.push_incoming_event(FileRequestErrorEvent(None, conn=self, + jid=unicode(receiver), file_props=file_props, error_msg='')) self._connect_error(unicode(receiver), file_props['sid'], file_props['sid'], code=406) else: @@ -490,7 +461,8 @@ class ConnectionSocks5Bytestream(ConnectionBytestream): if file_props is not None: self.disconnect_transfer(file_props) file_props['error'] = -3 - self.dispatch('FILE_REQUEST_ERROR', (to, file_props, msg)) + gajim.nec.push_incoming_event(FileRequestErrorEvent(None, + conn=self, jid=to, file_props=file_props, error_msg=msg)) def _proxy_auth_ok(self, proxy): """ @@ -521,7 +493,8 @@ class ConnectionSocks5Bytestream(ConnectionBytestream): return file_props = self.files_props[id_] file_props['error'] = -4 - self.dispatch('FILE_REQUEST_ERROR', (jid, file_props, '')) + gajim.nec.push_incoming_event(FileRequestErrorEvent(None, conn=self, + jid=jid, file_props=file_props, error_msg='')) raise xmpp.NodeProcessed def _bytestreamSetCB(self, con, iq_obj): @@ -799,7 +772,7 @@ class ConnectionIBBytestream(ConnectionBytestream): {'sid':sid})])) file_props['completed'] = True del self.files_props[sid] - + def IBBMessageHandler(self, conn, stanza): """ Receive next portion of incoming datastream and store it write diff --git a/src/gui_interface.py b/src/gui_interface.py index 0775012ea..813cdb596 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -166,8 +166,9 @@ class Interface: file_props['error'] = -3 else: file_props['error'] = -4 - self.handle_event_file_request_error(obj.conn.name, (obj.fjid, - file_props, obj.errmsg)) + gajim.nec.push_incoming_event(FileRequestErrorEvent(None, + conn=self, jid=obj.jid, file_props=file_props, + error_msg=obj.errmsg)) obj.conn.disconnect_transfer(file_props) return elif unicode(obj.errcode) == '404': @@ -819,19 +820,17 @@ class Interface: notify.popup(_('New E-mail'), jid, obj.conn.name, 'gmail', path_to_image=path, title=title, text=text) - def handle_event_file_request_error(self, account, array): + def handle_event_file_request_error(self, obj): # ('FILE_REQUEST_ERROR', account, (jid, file_props, error_msg)) - jid, file_props, errmsg = array - jid = gajim.get_jid_without_resource(jid) ft = self.instances['file_transfers'] - ft.set_status(file_props['type'], file_props['sid'], 'stop') - errno = file_props['error'] + ft.set_status(obj.file_props['type'], obj.file_props['sid'], 'stop') + errno = obj.file_props['error'] - if helpers.allow_popup_window(account): + if helpers.allow_popup_window(obj.conn.name): if errno in (-4, -5): - ft.show_stopped(jid, file_props, errmsg) + ft.show_stopped(obj.jid, obj.file_props, obj.error_msg) else: - ft.show_request_error(file_props) + ft.show_request_error(obj.file_props) return if errno in (-4, -5): @@ -839,45 +838,43 @@ class Interface: else: msg_type = 'file-request-error' - self.add_event(account, jid, msg_type, file_props) + self.add_event(obj.conn.name, obj.jid, msg_type, obj.file_props) - if helpers.allow_showing_notification(account): + if helpers.allow_showing_notification(obj.conn.name): # check if we should be notified path = gtkgui_helpers.get_icon_path('gajim-ft_error', 48) event_type = _('File Transfer Error') - notify.popup(event_type, jid, account, msg_type, path, - title = event_type, text = file_props['name']) + notify.popup(event_type, obj.jid, obj.conn.name, msg_type, path, + title=event_type, text=obj.file_props['name']) - def handle_event_file_request(self, account, array): - jid = array[0] - jid = gajim.get_jid_without_resource(jid) - if jid not in gajim.contacts.get_jid_list(account): + def handle_event_file_request(self, obj): + account = obj.conn.name + if obj.jid not in gajim.contacts.get_jid_list(account): keyID = '' attached_keys = gajim.config.get_per('accounts', account, - 'attached_gpg_keys').split() - if jid in attached_keys: - keyID = attached_keys[attached_keys.index(jid) + 1] - contact = gajim.contacts.create_not_in_roster_contact(jid=jid, - account=account, keyID=keyID) + 'attached_gpg_keys').split() + if obj.jid in attached_keys: + keyID = attached_keys[attached_keys.index(obj.jid) + 1] + contact = gajim.contacts.create_not_in_roster_contact(jid=obj.jid, + account=account, keyID=keyID) gajim.contacts.add_contact(account, contact) - self.roster.add_contact(contact.jid, account) - file_props = array[1] - contact = gajim.contacts.get_first_contact_from_jid(account, jid) + self.roster.add_contact(obj.jid, account) + contact = gajim.contacts.get_first_contact_from_jid(account, obj.jid) if helpers.allow_popup_window(account): self.instances['file_transfers'].show_file_request(account, contact, - file_props) + obj.file_props) return - self.add_event(account, jid, 'file-request', file_props) + self.add_event(account, obj.jid, 'file-request', obj.file_props) if helpers.allow_showing_notification(account): path = gtkgui_helpers.get_icon_path('gajim-ft_request', 48) txt = _('%s wants to send you a file.') % gajim.get_name_from_jid( - account, jid) + account, obj.jid) event_type = _('File Transfer Request') - notify.popup(event_type, jid, account, 'file-request', - path_to_image = path, title = event_type, text = txt) + notify.popup(event_type, obj.jid, account, 'file-request', + path_to_image=path, title=event_type, text=txt) def handle_event_file_error(self, title, message): dialogs.ErrorDialog(title, message) @@ -1376,14 +1373,14 @@ class Interface: 'ERROR': [self.handle_event_error], 'DB_ERROR': [self.handle_event_db_error], 'INFORMATION': [self.handle_event_information], - 'FILE_REQUEST': [self.handle_event_file_request], - 'FILE_REQUEST_ERROR': [self.handle_event_file_request_error], 'FILE_SEND_ERROR': [self.handle_event_file_send_error], 'atom-entry-received': [self.handle_atom_entry], 'bad-gpg-passphrase': [self.handle_event_bad_gpg_passphrase], 'bookmarks-received': [self.handle_event_bookmarks], 'connection-lost': [self.handle_event_connection_lost], 'failed-decrypt': [(self.handle_event_failed_decrypt, ged.GUI2)], + 'file-request-error': [self.handle_event_file_request_error], + 'file-request-received': [self.handle_event_file_request], 'fingerprint-error': [self.handle_event_fingerprint_error], 'gc-invitation-received': [self.handle_event_gc_invitation], 'gc-presence-received': [self.handle_event_gc_presence],