support for xep-300
This commit is contained in:
		
							parent
							
								
									76bc866a98
								
							
						
					
					
						commit
						376777091e
					
				
					 5 changed files with 161 additions and 14 deletions
				
			
		| 
						 | 
					@ -208,7 +208,9 @@ gajim_common_features = [xmpp.NS_BYTESTREAM, xmpp.NS_SI, xmpp.NS_FILE,
 | 
				
			||||||
        'jabber:iq:gateway', xmpp.NS_LAST, xmpp.NS_PRIVACY, xmpp.NS_PRIVATE,
 | 
					        'jabber:iq:gateway', xmpp.NS_LAST, xmpp.NS_PRIVACY, xmpp.NS_PRIVATE,
 | 
				
			||||||
        xmpp.NS_REGISTER, xmpp.NS_VERSION, xmpp.NS_DATA, xmpp.NS_ENCRYPTED, 'msglog',
 | 
					        xmpp.NS_REGISTER, xmpp.NS_VERSION, xmpp.NS_DATA, xmpp.NS_ENCRYPTED, 'msglog',
 | 
				
			||||||
        'sslc2s', 'stringprep', xmpp.NS_PING, xmpp.NS_TIME_REVISED, xmpp.NS_SSN,
 | 
					        'sslc2s', 'stringprep', xmpp.NS_PING, xmpp.NS_TIME_REVISED, xmpp.NS_SSN,
 | 
				
			||||||
        xmpp.NS_MOOD, xmpp.NS_ACTIVITY, xmpp.NS_NICK, xmpp.NS_ROSTERX, xmpp.NS_SECLABEL]
 | 
					        xmpp.NS_MOOD, xmpp.NS_ACTIVITY, xmpp.NS_NICK, xmpp.NS_ROSTERX, xmpp.NS_SECLABEL,
 | 
				
			||||||
 | 
					        xmpp.NS_HASHES, xmpp.NS_HASHES_MD5, xmpp.NS_HASHES_SHA1,
 | 
				
			||||||
 | 
					        xmpp.NS_HASHES_SHA256, xmpp.NS_HASHES_SHA512]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Optional features gajim supports per account
 | 
					# Optional features gajim supports per account
 | 
				
			||||||
gajim_optional_features = {}
 | 
					gajim_optional_features = {}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -151,10 +151,24 @@ class ConnectionJingle(object):
 | 
				
			||||||
        file_props['sid'] = jingle.sid
 | 
					        file_props['sid'] = jingle.sid
 | 
				
			||||||
        c = JingleFileTransfer(jingle, file_props=file_props,
 | 
					        c = JingleFileTransfer(jingle, file_props=file_props,
 | 
				
			||||||
                               use_security=use_security)
 | 
					                               use_security=use_security)
 | 
				
			||||||
 | 
					        c.hash_algo = self.__hash_support(contact) 
 | 
				
			||||||
        jingle.add_content('file' + helpers.get_random_string_16(), c)
 | 
					        jingle.add_content('file' + helpers.get_random_string_16(), c)
 | 
				
			||||||
        jingle.start_session()
 | 
					        jingle.start_session()
 | 
				
			||||||
        return c.transport.sid
 | 
					        return c.transport.sid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __hash_support(self, contact):
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if contact.supports(xmpp.NS_HASHES):
 | 
				
			||||||
 | 
					            if contact.supports(xmpp.NS_HASHES_MD5):
 | 
				
			||||||
 | 
					                return 'md5'
 | 
				
			||||||
 | 
					            elif contact.supports(xmpp.NS_HASHES_SHA1):
 | 
				
			||||||
 | 
					                return 'sha-1'
 | 
				
			||||||
 | 
					            elif contact.supports(xmpp.NS_HASHES_SHA256):
 | 
				
			||||||
 | 
					                return 'sha-256'
 | 
				
			||||||
 | 
					            elif contact.supports(xmpp.NS_HASHES_SHA512):
 | 
				
			||||||
 | 
					                return 'sha-512'
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def iter_jingle_sessions(self, jid, sid=None, media=None):
 | 
					    def iter_jingle_sessions(self, jid, sid=None, media=None):
 | 
				
			||||||
        if sid:
 | 
					        if sid:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,7 @@ from jingle_transport import JingleTransportICEUDP, JingleTransportSocks5, Jingl
 | 
				
			||||||
from common import helpers
 | 
					from common import helpers
 | 
				
			||||||
from common.socks5 import Socks5ReceiverClient, Socks5SenderClient
 | 
					from common.socks5 import Socks5ReceiverClient, Socks5SenderClient
 | 
				
			||||||
from common.connection_handlers_events import FileRequestReceivedEvent
 | 
					from common.connection_handlers_events import FileRequestReceivedEvent
 | 
				
			||||||
 | 
					import threading
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
log = logging.getLogger('gajim.c.jingle_ft')
 | 
					log = logging.getLogger('gajim.c.jingle_ft')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,9 +56,11 @@ class JingleFileTransfer(JingleContent):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # events we might be interested in
 | 
					        # events we might be interested in
 | 
				
			||||||
        self.callbacks['session-initiate'] += [self.__on_session_initiate]
 | 
					        self.callbacks['session-initiate'] += [self.__on_session_initiate]
 | 
				
			||||||
 | 
					        self.callbacks['session-initiate-sent'] += [self.__on_session_initiate_sent]
 | 
				
			||||||
        self.callbacks['content-add'] += [self.__on_session_initiate]
 | 
					        self.callbacks['content-add'] += [self.__on_session_initiate]
 | 
				
			||||||
        self.callbacks['session-accept'] += [self.__on_session_accept]
 | 
					        self.callbacks['session-accept'] += [self.__on_session_accept]
 | 
				
			||||||
        self.callbacks['session-terminate'] += [self.__on_session_terminate]
 | 
					        self.callbacks['session-terminate'] += [self.__on_session_terminate]        
 | 
				
			||||||
 | 
					        self.callbacks['session-info'] += [self.__on_session_info]
 | 
				
			||||||
        self.callbacks['transport-accept'] += [self.__on_transport_accept]
 | 
					        self.callbacks['transport-accept'] += [self.__on_transport_accept]
 | 
				
			||||||
        self.callbacks['transport-replace'] += [self.__on_transport_replace]
 | 
					        self.callbacks['transport-replace'] += [self.__on_transport_replace]
 | 
				
			||||||
        self.callbacks['session-accept-sent'] += [self.__transport_setup]
 | 
					        self.callbacks['session-accept-sent'] += [self.__transport_setup]
 | 
				
			||||||
| 
						 | 
					@ -99,12 +101,36 @@ class JingleFileTransfer(JingleContent):
 | 
				
			||||||
        self.session = session
 | 
					        self.session = session
 | 
				
			||||||
        self.media = 'file'
 | 
					        self.media = 'file'
 | 
				
			||||||
        self.nominated_cand = {}
 | 
					        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):
 | 
					    def __on_session_initiate(self, stanza, content, error, action):
 | 
				
			||||||
        gajim.nec.push_incoming_event(FileRequestReceivedEvent(None,
 | 
					        gajim.nec.push_incoming_event(FileRequestReceivedEvent(None,
 | 
				
			||||||
            conn=self.session.connection, stanza=stanza, jingle_content=content,
 | 
					            conn=self.session.connection, stanza=stanza, jingle_content=content,
 | 
				
			||||||
            FT_content=self))
 | 
					            FT_content=self))
 | 
				
			||||||
 | 
					    def __on_session_initiate_sent(self, stanza, content, error, action):
 | 
				
			||||||
 | 
					        # Calculate file_hash in a new thread
 | 
				
			||||||
 | 
					        self.hashThread = threading.Thread(target=self.__calcHash)
 | 
				
			||||||
 | 
					        self.hashThread.start()
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    def __calcHash(self):
 | 
				
			||||||
 | 
					        if self.hash_algo == None:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            file = open(self.file_props['file-name'], 'r')
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        h = xmpp.Hashes()
 | 
				
			||||||
 | 
					        h.calculateHash(self.hash_algo, file)
 | 
				
			||||||
 | 
					        checksum = xmpp.Node(tag='checksum',  
 | 
				
			||||||
 | 
					                             payload=[xmpp.Node(tag='file', payload=[h])])
 | 
				
			||||||
 | 
					        checksum.setNamespace(xmpp.NS_JINGLE_FILE_TRANSFER)
 | 
				
			||||||
 | 
					        # Send hash in a session info
 | 
				
			||||||
 | 
					        self.session.__session_info(checksum )
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
    def __on_session_accept(self, stanza, content, error, action):
 | 
					    def __on_session_accept(self, stanza, content, error, action):
 | 
				
			||||||
        log.info("__on_session_accept")
 | 
					        log.info("__on_session_accept")
 | 
				
			||||||
        con = self.session.connection
 | 
					        con = self.session.connection
 | 
				
			||||||
| 
						 | 
					@ -152,6 +178,9 @@ class JingleFileTransfer(JingleContent):
 | 
				
			||||||
    def __on_session_terminate(self, stanza, content, error, action):
 | 
					    def __on_session_terminate(self, stanza, content, error, action):
 | 
				
			||||||
        log.info("__on_session_terminate")
 | 
					        log.info("__on_session_terminate")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __on_session_info(self, stanza, content, error, action):
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
    def __on_transport_accept(self, stanza, content, error, action):
 | 
					    def __on_transport_accept(self, stanza, content, error, action):
 | 
				
			||||||
        log.info("__on_transport_accept")
 | 
					        log.info("__on_transport_accept")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -164,8 +193,6 @@ class JingleFileTransfer(JingleContent):
 | 
				
			||||||
    def __on_transport_info(self, stanza, content, error, action):
 | 
					    def __on_transport_info(self, stanza, content, error, action):
 | 
				
			||||||
        log.info("__on_transport_info")
 | 
					        log.info("__on_transport_info")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #if not self.weinitiate: # proxy activated from initiator
 | 
					 | 
				
			||||||
        #    return
 | 
					 | 
				
			||||||
        if content.getTag('transport').getTag('candidate-error'):
 | 
					        if content.getTag('transport').getTag('candidate-error'):
 | 
				
			||||||
            self.nominated_cand['peer-cand'] = False
 | 
					            self.nominated_cand['peer-cand'] = False
 | 
				
			||||||
            if self.state == STATE_CAND_SENT_PENDING_REPLY:
 | 
					            if self.state == STATE_CAND_SENT_PENDING_REPLY:
 | 
				
			||||||
| 
						 | 
					@ -392,7 +419,7 @@ class JingleFileTransfer(JingleContent):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def start_transfer(self):
 | 
					    def start_transfer(self):
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        self.state = STATE_TRANSFERING
 | 
					        self.state = STATE_TRANSFERING
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # It tells wether we start the transfer as client or server
 | 
					        # It tells wether we start the transfer as client or server
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,7 +98,7 @@ class JingleSession(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.accepted = True # is this session accepted by user
 | 
					        self.accepted = True # is this session accepted by user
 | 
				
			||||||
 | 
					        self.file_hash = None
 | 
				
			||||||
        # callbacks to call on proper contents
 | 
					        # callbacks to call on proper contents
 | 
				
			||||||
        # use .prepend() to add new callbacks, especially when you're going
 | 
					        # use .prepend() to add new callbacks, especially when you're going
 | 
				
			||||||
        # to send error instead of ack
 | 
					        # to send error instead of ack
 | 
				
			||||||
| 
						 | 
					@ -126,6 +126,7 @@ class JingleSession(object):
 | 
				
			||||||
                'iq-result':            [self.__broadcast],
 | 
					                'iq-result':            [self.__broadcast],
 | 
				
			||||||
                'iq-error':             [self.__on_error],
 | 
					                'iq-error':             [self.__on_error],
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def collect_iq_id(self, iq_id):
 | 
					    def collect_iq_id(self, iq_id):
 | 
				
			||||||
        if iq_id is not None:
 | 
					        if iq_id is not None:
 | 
				
			||||||
| 
						 | 
					@ -416,9 +417,20 @@ class JingleSession(object):
 | 
				
			||||||
    def __on_session_info(self, stanza, jingle, error, action):
 | 
					    def __on_session_info(self, stanza, jingle, error, action):
 | 
				
			||||||
        # TODO: ringing, active, (un)hold, (un)mute
 | 
					        # TODO: ringing, active, (un)hold, (un)mute
 | 
				
			||||||
        payload = jingle.getPayload()
 | 
					        payload = jingle.getPayload()
 | 
				
			||||||
        if payload:
 | 
					        for p in payload:
 | 
				
			||||||
            self.__send_error(stanza, 'feature-not-implemented', 'unsupported-info', type_='modify')
 | 
					            if p.getName() == 'checksum':
 | 
				
			||||||
            raise xmpp.NodeProcessed
 | 
					                hashes = p.getTag('file').getTag(name='hashes', 
 | 
				
			||||||
 | 
					                                        namespace=xmpp.NS_HASHES)
 | 
				
			||||||
 | 
					                for hash in hashes.getChildren():
 | 
				
			||||||
 | 
					                    algo = hash.getAttr('algo')
 | 
				
			||||||
 | 
					                    if algo in xmpp.Hashes.supported:
 | 
				
			||||||
 | 
					                        data = hash.getData()
 | 
				
			||||||
 | 
					                        self.file_hash = data
 | 
				
			||||||
 | 
					                        print data
 | 
				
			||||||
 | 
					                        raise xmpp.NodeProcessed
 | 
				
			||||||
 | 
					        self.__send_error(stanza, 'feature-not-implemented', 'unsupported-info', type_='modify')
 | 
				
			||||||
 | 
					        raise xmpp.NodeProcessed
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __on_content_remove(self, stanza, jingle, error, action):
 | 
					    def __on_content_remove(self, stanza, jingle, error, action):
 | 
				
			||||||
        for content in jingle.iterTags('content'):
 | 
					        for content in jingle.iterTags('content'):
 | 
				
			||||||
| 
						 | 
					@ -704,6 +716,13 @@ class JingleSession(object):
 | 
				
			||||||
        if payload:
 | 
					        if payload:
 | 
				
			||||||
            jingle.addChild(node=payload)
 | 
					            jingle.addChild(node=payload)
 | 
				
			||||||
        self.connection.connection.send(stanza)
 | 
					        self.connection.connection.send(stanza)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    def _JingleFileTransfer__session_info(self, p):
 | 
				
			||||||
 | 
					        # For some strange reason when I call
 | 
				
			||||||
 | 
					        # self.session.__session_info(h) from the jingleFileTransfer object
 | 
				
			||||||
 | 
					        # within a thread, this method gets called instead. Even though, it
 | 
				
			||||||
 | 
					        # isn't being called explicitly.
 | 
				
			||||||
 | 
					        self.__session_info(p)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _session_terminate(self, reason=None):
 | 
					    def _session_terminate(self, reason=None):
 | 
				
			||||||
        assert self.state != JingleStates.ended
 | 
					        assert self.state != JingleStates.ended
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ sub- stanzas) handling routines
 | 
				
			||||||
from simplexml import Node, NodeBuilder
 | 
					from simplexml import Node, NodeBuilder
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
import string
 | 
					import string
 | 
				
			||||||
 | 
					import hashlib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def ascii_upper(s):
 | 
					def ascii_upper(s):
 | 
				
			||||||
    trans_table = string.maketrans(string.ascii_lowercase,
 | 
					    trans_table = string.maketrans(string.ascii_lowercase,
 | 
				
			||||||
| 
						 | 
					@ -89,7 +90,7 @@ NS_JINGLE_ERRORS  = 'urn:xmpp:jingle:errors:1'                        # XEP-0166
 | 
				
			||||||
NS_JINGLE_RTP     = 'urn:xmpp:jingle:apps:rtp:1'                      # XEP-0167
 | 
					NS_JINGLE_RTP     = 'urn:xmpp:jingle:apps:rtp:1'                      # XEP-0167
 | 
				
			||||||
NS_JINGLE_RTP_AUDIO = 'urn:xmpp:jingle:apps:rtp:audio'                # XEP-0167
 | 
					NS_JINGLE_RTP_AUDIO = 'urn:xmpp:jingle:apps:rtp:audio'                # XEP-0167
 | 
				
			||||||
NS_JINGLE_RTP_VIDEO = 'urn:xmpp:jingle:apps:rtp:video'                # XEP-0167
 | 
					NS_JINGLE_RTP_VIDEO = 'urn:xmpp:jingle:apps:rtp:video'                # XEP-0167
 | 
				
			||||||
NS_JINGLE_FILE_TRANSFER='urn:xmpp:jingle:apps:file-transfer:1'        # XEP-0234
 | 
					NS_JINGLE_FILE_TRANSFER ='urn:xmpp:jingle:apps:file-transfer:1'        # XEP-0234
 | 
				
			||||||
NS_JINGLE_XTLS='urn:xmpp:jingle:security:xtls:0'                      # XTLS: EXPERIMENTAL security layer of jingle
 | 
					NS_JINGLE_XTLS='urn:xmpp:jingle:security:xtls:0'                      # XTLS: EXPERIMENTAL security layer of jingle
 | 
				
			||||||
NS_JINGLE_RAW_UDP = 'urn:xmpp:jingle:transports:raw-udp:1'            # XEP-0177
 | 
					NS_JINGLE_RAW_UDP = 'urn:xmpp:jingle:transports:raw-udp:1'            # XEP-0177
 | 
				
			||||||
NS_JINGLE_ICE_UDP = 'urn:xmpp:jingle:transports:ice-udp:1'            # XEP-0176
 | 
					NS_JINGLE_ICE_UDP = 'urn:xmpp:jingle:transports:ice-udp:1'            # XEP-0176
 | 
				
			||||||
| 
						 | 
					@ -160,7 +161,12 @@ NS_PUBKEY_PUBKEY  = 'urn:xmpp:pubkey:2'
 | 
				
			||||||
NS_PUBKEY_REVOKE  = 'urn:xmpp:revoke:2'
 | 
					NS_PUBKEY_REVOKE  = 'urn:xmpp:revoke:2'
 | 
				
			||||||
NS_PUBKEY_ATTEST  = 'urn:xmpp:attest:2'
 | 
					NS_PUBKEY_ATTEST  = 'urn:xmpp:attest:2'
 | 
				
			||||||
NS_STREAM_MGMT    = 'urn:xmpp:sm:2'                                   # XEP-198
 | 
					NS_STREAM_MGMT    = 'urn:xmpp:sm:2'                                   # XEP-198
 | 
				
			||||||
 | 
					NS_HASHES         = 'urn:xmpp:hashes:0'                               # XEP-300
 | 
				
			||||||
 | 
					NS_HASHES_MD5     = 'urn:xmpp:hash-function-textual-names:md5'
 | 
				
			||||||
 | 
					NS_HASHES_SHA1    = 'urn:xmpp:hash-function-textual-names:sha-1'
 | 
				
			||||||
 | 
					NS_HASHES_SHA256  = 'urn:xmpp:hash-function-textual-names:sha-256'
 | 
				
			||||||
 | 
					NS_HASHES_SHA512  = 'urn:xmpp:hash-function-textual-names:sha-512'
 | 
				
			||||||
 | 
					                 
 | 
				
			||||||
xmpp_stream_error_conditions = '''
 | 
					xmpp_stream_error_conditions = '''
 | 
				
			||||||
bad-format --  --  -- The entity has sent XML that cannot be processed.
 | 
					bad-format --  --  -- The entity has sent XML that cannot be processed.
 | 
				
			||||||
bad-namespace-prefix --  --  -- The entity has sent a namespace prefix that is unsupported, or has sent no namespace prefix on an element that requires such a prefix.
 | 
					bad-namespace-prefix --  --  -- The entity has sent a namespace prefix that is unsupported, or has sent no namespace prefix on an element that requires such a prefix.
 | 
				
			||||||
| 
						 | 
					@ -1030,7 +1036,85 @@ class Iq(Protocol):
 | 
				
			||||||
            attrs={'id': self.getID()})
 | 
					            attrs={'id': self.getID()})
 | 
				
			||||||
        iq.setQuery(self.getQuery().getName()).setNamespace(self.getQueryNS())
 | 
					        iq.setQuery(self.getQuery().getName()).setNamespace(self.getQueryNS())
 | 
				
			||||||
        return iq
 | 
					        return iq
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					class Hashes(Node): 
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Hash elements for various XEPs as defined in XEP-300
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    RECOMENDED HASH USE:
 | 
				
			||||||
 | 
					    Algorithm     Support
 | 
				
			||||||
 | 
					    MD2           MUST NOT
 | 
				
			||||||
 | 
					    MD4           MUST NOT
 | 
				
			||||||
 | 
					    MD5           MAY
 | 
				
			||||||
 | 
					    SHA-1         MUST
 | 
				
			||||||
 | 
					    SHA-256       MUST
 | 
				
			||||||
 | 
					    SHA-512       SHOULD
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    supported = ('md5', 'sha-1', 'sha-256', 'sha-512')
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    def __init__(self, nsp=NS_HASHES):
 | 
				
			||||||
 | 
					        Node.__init__(self, None, {}, [], None, None,False, None)
 | 
				
			||||||
 | 
					        self.setNamespace(nsp)
 | 
				
			||||||
 | 
					        self.setName('hashes')
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    def calculateHash(self, algo, file_string):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Calculate the hash and add it. It is preferable doing it here
 | 
				
			||||||
 | 
					        instead of doing it all over the place in Gajim.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        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':
 | 
				
			||||||
 | 
					                hl = hashlib.md5()
 | 
				
			||||||
 | 
					            elif algo == 'sha-1':
 | 
				
			||||||
 | 
					                hl = hashlib.sha1()
 | 
				
			||||||
 | 
					            elif algo == 'sha-256':
 | 
				
			||||||
 | 
					                hl = hashlib.sha256()
 | 
				
			||||||
 | 
					            elif algo == 'sha-512':
 | 
				
			||||||
 | 
					                hl = hashlib.sha512()
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            if hl == None:
 | 
				
			||||||
 | 
					                # Raise exception
 | 
				
			||||||
 | 
					                raise Exception('Hash algorithm not supported')
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                hl.update(file_string)
 | 
				
			||||||
 | 
					                hash = hl.hexdigest()
 | 
				
			||||||
 | 
					        else: # if it is a file
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            if algo == 'md5':
 | 
				
			||||||
 | 
					                hl = hashlib.md5()
 | 
				
			||||||
 | 
					            elif algo == 'sha-1':
 | 
				
			||||||
 | 
					                hl = hashlib.sha1()
 | 
				
			||||||
 | 
					            elif algo == 'sha-256':
 | 
				
			||||||
 | 
					                hl = hashlib.sha256()
 | 
				
			||||||
 | 
					            elif algo == 'sha-512':
 | 
				
			||||||
 | 
					                hl = hashlib.sha512()
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            if hl == None:
 | 
				
			||||||
 | 
					                # Raise exception
 | 
				
			||||||
 | 
					                raise Exception('Hash algorithm not supported')
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                for line in file_string:
 | 
				
			||||||
 | 
					                    hl.update(line)
 | 
				
			||||||
 | 
					                hash = hl.hexdigest()
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					        self.addHash(hash, algo)
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					    def addHash(self, hash, algo):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        More than one hash can be added. Although it is permitted, it should
 | 
				
			||||||
 | 
					        not be done for big files because it could slow down Gajim.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        attrs = {}
 | 
				
			||||||
 | 
					        attrs['algo'] = algo 
 | 
				
			||||||
 | 
					        self.addChild('hash', attrs, [hash])
 | 
				
			||||||
 | 
					     
 | 
				
			||||||
class Acks(Node):
 | 
					class Acks(Node):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Acknowledgement elements for Stream Management
 | 
					    Acknowledgement elements for Stream Management
 | 
				
			||||||
| 
						 | 
					@ -1413,3 +1497,4 @@ class DataForm(Node):
 | 
				
			||||||
        Simple dictionary interface for setting datafields values by their names
 | 
					        Simple dictionary interface for setting datafields values by their names
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return self.setField(name).setValue(val)
 | 
					        return self.setField(name).setValue(val)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue