diff --git a/src/common/jingle.py b/src/common/jingle.py index f4de9eb7a..d4e5b6ada 100644 --- a/src/common/jingle.py +++ b/src/common/jingle.py @@ -157,7 +157,7 @@ class ConnectionJingle(object): transport = JingleTransportIBB() c = JingleFileTransfer(jingle, transport=transport, file_props=file_props, use_security=use_security) - c.hash_algo = self.__hash_support(contact) + jingle.hash_algo = self.__hash_support(contact) jingle.add_content('file' + helpers.get_random_string_16(), c) jingle.start_session() return c.transport.sid diff --git a/src/common/jingle_ft.py b/src/common/jingle_ft.py index 59ea6d256..c5c7c8af6 100644 --- a/src/common/jingle_ft.py +++ b/src/common/jingle_ft.py @@ -103,9 +103,7 @@ class JingleFileTransfer(JingleContent): self.media = 'file' self.nominated_cand = {} - # Hash algorithm that we are using to calculate the integrity of the - # file. Could be 'md5', 'sha-1', etc... - self.hash_algo = None + def __on_session_initiate(self, stanza, content, error, action): gajim.nec.push_incoming_event(FileRequestReceivedEvent(None, @@ -117,14 +115,16 @@ class JingleFileTransfer(JingleContent): self.hashThread.start() def __calcHash(self): - if self.hash_algo == None: + if self.session.hash_algo == None: return try: file = open(self.file_props['file-name'], 'r') except: return h = xmpp.Hashes() - h.calculateHash(self.hash_algo, file) + hash = h.calculateHash(self.session.hash_algo, file) + self.file_props['hash'] = hash + h.addHash(hash, self.session.hash_algo) checksum = xmpp.Node(tag='checksum', payload=[xmpp.Node(tag='file', payload=[h])]) checksum.setNamespace(xmpp.NS_JINGLE_FILE_TRANSFER) diff --git a/src/common/jingle_session.py b/src/common/jingle_session.py index 4d5a184b3..14c9080fd 100644 --- a/src/common/jingle_session.py +++ b/src/common/jingle_session.py @@ -98,6 +98,9 @@ class JingleSession(object): self.accepted = True # is this session accepted by user + # Hash algorithm that we are using to calculate the integrity of the + # file. Could be 'md5', 'sha-1', etc... + self.hash_algo = None self.file_hash = None # callbacks to call on proper contents # use .prepend() to add new callbacks, especially when you're going @@ -424,9 +427,11 @@ class JingleSession(object): for hash in hashes.getChildren(): algo = hash.getAttr('algo') if algo in xmpp.Hashes.supported: + self.hash_algo = algo data = hash.getData() + # This only works because there is only one session + # per file in jingleFT self.file_hash = data - print data raise xmpp.NodeProcessed self.__send_error(stanza, 'feature-not-implemented', 'unsupported-info', type_='modify') raise xmpp.NodeProcessed diff --git a/src/common/xmpp/protocol.py b/src/common/xmpp/protocol.py index 82b16a9c0..c2c00f9d4 100644 --- a/src/common/xmpp/protocol.py +++ b/src/common/xmpp/protocol.py @@ -1067,7 +1067,6 @@ class Hashes(Node): """ hl = None hash = None - # file_string can be a string or a file if type(file_string) == str: # if it is a string if algo == 'md5': @@ -1104,7 +1103,7 @@ class Hashes(Node): hl.update(line) hash = hl.hexdigest() - self.addHash(hash, algo) + return hash def addHash(self, hash, algo): """ diff --git a/src/gui_interface.py b/src/gui_interface.py index 3879cceaf..3fe7b5f30 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -71,6 +71,7 @@ from session import ChatControlSession import common.sleepy from common.xmpp import idlequeue +from common.xmpp import Hashes from common.zeroconf import connection_zeroconf from common import resolver from common import caps_cache @@ -908,6 +909,22 @@ class Interface: self.last_ftwindow_update = time.time() self.instances['file_transfers'].set_progress(file_props['type'], file_props['sid'], file_props['received-len']) + def __compare_hashes(self, account, file_props): + session = gajim.connections[account].get_jingle_session(jid=None, + sid=file_props['session-sid']) + h = Hashes() + try: + file = open(file_props['file-name'], 'r') + except: + return + hash = h.calculateHash(session.hash_algo, file) + # If the hash we received and the hash of the file are the same, + # then the file is not corrupt + if session.file_hash == hash: + print "they are te same" + # End jingle session + if session: + session.end_session() def handle_event_file_rcv_completed(self, account, file_props): ft = self.instances['file_transfers'] @@ -919,18 +936,17 @@ class Interface: if 'stalled' in file_props and file_props['stalled'] or \ 'paused' in file_props and file_props['paused']: return - + if file_props['type'] == 'r': # we receive a file jid = unicode(file_props['sender']) + # Compare hashes in a new thread + self.hashThread = Thread(target=self.__compare_hashes, + args=(account, file_props)) + self.hashThread.start() gajim.socks5queue.remove_receiver(file_props['sid'], True, True) else: # we send a file jid = unicode(file_props['receiver']) gajim.socks5queue.remove_sender(file_props['sid'], True, True) - # End jingle session - session = gajim.connections[account].get_jingle_session(jid, - sid=file_props['session-sid']) - if session: - session.end_session() if helpers.allow_popup_window(account): if file_props['error'] == 0: