diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index d805a2a8399ecdce9ed5f5557b08a72feb48ab14..dd15220fd8817c4b2af2e40c3b73a8634cf66632 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -1973,12 +1973,13 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): 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) + for child in file_tag.getChildren(): + name = child.getName() + if name in ('name', 'size', 'hash', 'date'): + val = child.getData() if val is None: continue - self.file_props[attribute] = val + self.file_props[name] = val file_desc_tag = file_tag.getTag('desc') if file_desc_tag is not None: self.file_props['desc'] = file_desc_tag.getData() diff --git a/src/common/jingle.py b/src/common/jingle.py index 4c2598487b66463dae081794336b75619da78e97..60a1bcd178ffe03ee61afbe6a9ef241d2f84dbc3 100644 --- a/src/common/jingle.py +++ b/src/common/jingle.py @@ -101,7 +101,7 @@ class ConnectionJingle(object): # do we need to create a new jingle object if sid not in self._sessions: #TODO: tie-breaking and other things... - newjingle = JingleSession(con=self, weinitiate=False, jid=jid, + newjingle = JingleSession(con=self, werequest=False, weinitiate=False, jid=jid, iq_id=id_, sid=sid) self._sessions[sid] = newjingle @@ -141,14 +141,14 @@ class ConnectionJingle(object): jingle.start_session() return jingle.sid - def start_file_transfer(self, jid, file_props): + def start_file_transfer(self, jid, file_props, request=False): logger.info("start file transfer with file: %s" % file_props) contact = gajim.contacts.get_contact_with_highest_priority(self.name, gajim.get_jid_without_resource(jid)) if contact is None: return use_security = contact.supports(xmpp.NS_JINGLE_XTLS) - jingle = JingleSession(self, weinitiate=True, jid=jid) + jingle = JingleSession(self, request, weinitiate=True, jid=jid) # this is a file transfer jingle.session_type_FT = True self._sessions[jingle.sid] = jingle diff --git a/src/common/jingle_content.py b/src/common/jingle_content.py index 079000f8599880bf1442eaa61a7fd00932ebe214..dcafbf39e412986cf3e2b537bb2ecbfb239a1a72 100644 --- a/src/common/jingle_content.py +++ b/src/common/jingle_content.py @@ -162,6 +162,46 @@ class JingleContent(object): self.sent = True content.addChild(node=self.transport.make_transport()) + def _fill_content(self, content, action): + description_node = xmpp.simplexml.Node( + tag=xmpp.NS_JINGLE_FILE_TRANSFER + ' description') + + if self.session.werequest: + simode = xmpp.simplexml.Node(tag='request') + else: + simode = xmpp.simplexml.Node(tag='offer') + + file_tag = simode.setTag('file', namespace=xmpp.NS_FILE) + if 'name' in self.file_props: + node = xmpp.simplexml.Node(tag='name') + node.addData(self.file_props['name']) + file_tag.addChild(node=node) + if 'size' in self.file_props: + node = xmpp.simplexml.Node(tag='size') + node.addData(self.file_props['size']) + file_tag.addChild(node=node) + if 'hash' in self.file_props: + # TODO: use xep-300 for this bit + pass + desc = file_tag.setTag('desc') + if 'desc' in self.file_props: + desc.setData(self.file_props['desc']) + + description_node.addChild(node=simode) + + if self.use_security: + security = xmpp.simplexml.Node( + tag=xmpp.NS_JINGLE_XTLS + ' security') + # TODO: add fingerprint element + for m in ('x509', ): # supported authentication methods + method = xmpp.simplexml.Node(tag='method') + method.setAttr('name', m) + security.addChild(node=method) + content.addChild(node=security) + + content.addChild(node=description_node) + + def destroy(self): self.callbacks = None del self.session.contents[(self.creator, self.name)] diff --git a/src/common/jingle_ft.py b/src/common/jingle_ft.py index 9763ffb76c56693d742ce0270fac903bb9e3ef67..17b431c06c4f54cd8a325b8a8c0300f1066d9494 100644 --- a/src/common/jingle_ft.py +++ b/src/common/jingle_ft.py @@ -132,6 +132,8 @@ class JingleFileTransfer(JingleContent): return h = xmpp.Hashes() hash_ = h.calculateHash(self.session.hash_algo, file_) + # DEBUG + #hash_ = '1294809248109223' if not hash_: # Hash alogrithm not supported return @@ -294,32 +296,6 @@ class JingleFileTransfer(JingleContent): else: self.__state_changed(STATE_CAND_SENT, args) - def _fill_content(self, content): - description_node = xmpp.simplexml.Node( - tag=xmpp.NS_JINGLE_FILE_TRANSFER + ' description') - - sioffer = xmpp.simplexml.Node(tag='offer') - file_tag = sioffer.setTag('file', namespace=xmpp.NS_FILE) - file_tag.setAttr('name', self.file_props['name']) - file_tag.setAttr('size', self.file_props['size']) - desc = file_tag.setTag('desc') - if 'desc' in self.file_props: - desc.setData(self.file_props['desc']) - - description_node.addChild(node=sioffer) - - if self.use_security: - security = xmpp.simplexml.Node( - tag=xmpp.NS_JINGLE_XTLS + ' security') - # TODO: add fingerprint element - for m in ('x509', ): # supported authentication methods - method = xmpp.simplexml.Node(tag='method') - method.setAttr('name', m) - security.addChild(node=method) - content.addChild(node=security) - - content.addChild(node=description_node) - def _store_socks5_sid(self, sid, hash_id): # callback from socsk5queue.start_listener self.file_props['hash'] = hash_id diff --git a/src/common/jingle_session.py b/src/common/jingle_session.py index b3faafe2d8e23495091f04e52db05cf0443bae5c..adcd11636a610d3210b8fca515cf6abe0bb105e9 100644 --- a/src/common/jingle_session.py +++ b/src/common/jingle_session.py @@ -63,7 +63,7 @@ class JingleSession(object): negotiated between an initiator and a responder. """ - def __init__(self, con, weinitiate, jid, iq_id=None, sid=None): + def __init__(self, con, werequest, weinitiate, jid, iq_id=None, sid=None): """ con -- connection object, weinitiate -- boolean, are we the initiator? @@ -83,6 +83,8 @@ class JingleSession(object): self.responder = weinitiate and self.peerjid or self.ourjid # are we an initiator? self.weinitiate = weinitiate + # Are we requesting or offering a file? + self.werequest = werequest # what state is session in? (one from JingleStates) self.state = JingleStates.ended if not sid: diff --git a/src/filetransfers_window.py b/src/filetransfers_window.py index 4537c5141bde49daf118c4eb8e6a6a8697091eea..ac4d3eb5b11ef757f6364d3585c7f52fe3afaab1 100644 --- a/src/filetransfers_window.py +++ b/src/filetransfers_window.py @@ -37,7 +37,6 @@ from common.protocol.bytestream import (is_transfer_active, is_transfer_paused, is_transfer_stopped) from common.xmpp.protocol import NS_JINGLE_FILE_TRANSFER import logging - log = logging.getLogger('gajim.filetransfer_window') C_IMAGE = 0 @@ -249,10 +248,14 @@ class FileTransfersWindow: dialogs.ErrorDialog(_('File transfer stopped'), sectext) self.tree.get_selection().unselect_all() - def show_hash_error(self, jid, file_props): + def show_hash_error(self, jid, file_props, account): def on_yes(dummy): - # TODO: Request the file to the sender - pass + # Request the file to the sender + sid = gajim.connections[account].start_file_transfer(jid, + file_props, + True) + file_props['sid'] = sid + if file_props['type'] == 'r': file_name = os.path.basename(file_props['file-name']) diff --git a/src/gui_interface.py b/src/gui_interface.py index dff02d25c84adfc70c63bb793675b11e27624a8f..587dd8206f8e20c6de05105a49b0e26dc0d60890 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -989,7 +989,7 @@ class Interface: ft.show_stopped(jid, file_props, error_msg=_('Error opening file')) elif file_props['error'] == -10: - ft.show_hash_error(jid, file_props) + ft.show_hash_error(jid, file_props, account) return msg_type = '' diff --git a/src/roster_window.py b/src/roster_window.py index 58070d1b814f01c67835fa4cb6596571b7a1326b..c8e32b52122f430ef83a15a315401bcecb1ba674 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -1978,7 +1978,7 @@ class RosterWindow: gajim.events.remove_events(account, jid, event) return True elif event.type_ == 'file-hash-error': - ft.show_hash_error(jid, data) + ft.show_hash_error(jid, data, account) gajim.events.remove_events(account, jid, event) elif event.type_ == 'file-completed': ft.show_completed(jid, data)