Commit 2af1af20 authored by zimio's avatar zimio

file_props refactoring

parent b6b44cb3
......@@ -3203,11 +3203,11 @@ class ChatControl(ChatControlBase):
"""
Show an InfoBar on top of control
"""
markup = '<b>%s:</b> %s' % (_('File transfer'), file_props['name'])
if 'desc' in file_props and file_props['desc']:
markup += ' (%s)' % file_props['desc']
markup = '<b>%s:</b> %s' % (_('File transfer'), file_props.name)
if file_props.desc:
markup += ' (%s)' % file_props.desc
markup += '\n%s: %s' % (_('Size'), helpers.convert_bytes(
file_props['size']))
file_props.size))
b1 = gtk.Button(_('_Accept'))
b1.connect('clicked', self._on_accept_file_request, file_props)
b2 = gtk.Button(stock=gtk.STOCK_CANCEL)
......@@ -3216,9 +3216,7 @@ class ChatControl(ChatControlBase):
gtk.MESSAGE_QUESTION)
def _on_open_ft_folder(self, widget, file_props):
if 'file-name' not in file_props:
return
path = os.path.split(file_props['file-name'])[0]
path = os.path.split(file_props.file_name)[0]
if os.path.exists(path) and os.path.isdir(path):
helpers.launch_file_manager(path)
ev = self._get_file_props_event(file_props, 'file-completed')
......@@ -3232,9 +3230,9 @@ class ChatControl(ChatControlBase):
def _got_file_completed(self, file_props):
markup = '<b>%s:</b> %s' % (_('File transfer completed'),
file_props['name'])
if 'desc' in file_props and file_props['desc']:
markup += ' (%s)' % file_props['desc']
file_props.name)
if file_props.desc:
markup += ' (%s)' % file_props.desc
b1 = gtk.Button(_('_Open Containing Folder'))
b1.connect('clicked', self._on_open_ft_folder, file_props)
b2 = gtk.Button(stock=gtk.STOCK_OK)
......
......@@ -37,6 +37,7 @@ from common.logger import LOG_DB_PATH
from common.pep import SUPPORTED_PERSONAL_USER_EVENTS
from common.xmpp.protocol import NS_CHATSTATES
from common.jingle_transport import JingleTransportSocks5
from common.file_props import FilesProp
import gtkgui_helpers
......@@ -1940,16 +1941,44 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
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_
if self.jingle_content:
self.file_props['session-type'] = 'jingle'
self.file_props['stream-methods'] = xmpp.NS_BYTESTREAM
self.FT_content.use_security = bool(self.jingle_content.getTag(
'security'))
if not self.FT_content.transport:
self.FT_content.transport = JingleTransportSocks5()
self.FT_content.transport.set_our_jid(
self.FT_content.session.ourjid)
self.FT_content.transport.set_connection(
self.FT_content.session.connection)
sid = self.FT_content.transport.sid
self.file_props = FilesProp.getNewFileProp(self.conn.name, sid)
self.file_props.session_sid = unicode(
self.stanza.getTag('jingle').getAttr('sid')
)
self.FT_content.file_props = self.file_props
self.FT_content.transport.set_file_props(self.file_props)
if self.file_props.streamhosts:
self.file_props.streamhosts.extend(
self.FT_content.transport.remote_candidates)
else:
self.file_props.streamhosts = \
self.FT_content.transport.remote_candidates
for host in self.file_props.streamhosts:
host['initiator'] = self.FT_content.session.initiator
host['target'] = self.FT_content.session.responder
else:
si = self.stanza.getTag('si')
self.file_props = FilesProp.getNewFileProp(self.conn.name,
unicode(si.getAttr('id'))
)
self.file_props.sender = self.fjid
self.file_props.request_id = self.id_
if self.jingle_content:
self.file_props.session_type = 'jingle'
self.file_props.stream_methods = xmpp.NS_BYTESTREAM
file_tag = self.jingle_content.getTag('description').getTag(
'offer').getTag('file')
else:
si = self.stanza.getTag('si')
profile = si.getAttr('profile')
if profile != xmpp.NS_FILE:
self.conn.send_file_rejection(self.file_props, code='400',
......@@ -1965,7 +1994,7 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
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)
self.file_props.stream_methods = ' '.join(values)
if xmpp.NS_BYTESTREAM in values or xmpp.NS_IBB in values:
break
else:
......@@ -1975,54 +2004,30 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
file_tag = si.getTag('file')
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[name] = val
# Delete this, it shouldn't be necesary after file_props gets
# refactored.
if name == 'hash':
self.file_props['algo'] = child.getAttr('algo')
val = child.getData()
if val is None:
continue
if name == 'name':
self.file_props.name = val
if name == 'size':
self.file_props.size = val
if name == 'hash':
self.file_props.algo = child.getAttr('algo')
self.file_props.hash_ = val
if name == 'date':
self.file_props.date = val
file_desc_tag = file_tag.getTag('desc')
if file_desc_tag is not None:
self.file_props['desc'] = file_desc_tag.getData()
self.file_props.desc = file_desc_tag.getData()
if not self.jingle_content:
mime_type = si.getAttr('mime-type')
if mime_type is not None:
self.file_props['mime-type'] = mime_type
self.file_props.mime_type = mime_type
self.file_props['receiver'] = self.conn._ft_get_our_jid()
self.file_props['transfered_size'] = []
if self.jingle_content:
self.FT_content.use_security = bool(self.jingle_content.getTag(
'security'))
self.file_props['session-sid'] = unicode(self.stanza.getTag(
'jingle').getAttr('sid'))
self.file_props.receiver = self.conn._ft_get_our_jid()
self.file_props.transfered_size = []
self.FT_content.file_props = self.file_props
if not self.FT_content.transport:
self.FT_content.transport = JingleTransportSocks5()
self.FT_content.transport.set_our_jid(
self.FT_content.session.ourjid)
self.FT_content.transport.set_connection(
self.FT_content.session.connection)
self.file_props['sid'] = self.FT_content.transport.sid
self.FT_content.session.connection.files_props[
self.file_props['sid']] = self.file_props
self.FT_content.transport.set_file_props(self.file_props)
if self.file_props.has_key('streamhosts'):
self.file_props['streamhosts'].extend(
self.FT_content.transport.remote_candidates)
else:
self.file_props['streamhosts'] = \
self.FT_content.transport.remote_candidates
for host in self.file_props['streamhosts']:
host['initiator'] = self.FT_content.session.initiator
host['target'] = self.FT_content.session.responder
else:
self.file_props['sid'] = unicode(si.getAttr('id'))
return True
class FileRequestErrorEvent(nec.NetworkIncomingEvent):
......
"""
This module is in charge of taking care of all the infomation related to
individual files. Files are identified by the account name and its sid.
>>> print FilesProp.getFileProp('jabberid', '10')
None
>>> fp = FilesProp()
Traceback (most recent call last):
...
Exception: this class should not be instatiated
>>> print FilesProp.getAllFileProp()
[]
>>> fp = FilesProp.getNewFileProp('jabberid', '10')
>>> fp2 = FilesProp.getFileProp('jabberid', '10')
>>> fp == fp2
True
"""
class FilesProp:
_files_props = {}
def __init__(self):
raise Exception('this class should not be instatiated')
@classmethod
def getNewFileProp(cls, account, sid):
fp = FileProp(account, sid)
cls.setFileProp(fp, account, sid)
return fp
@classmethod
def getFileProp(cls, account, sid):
if (account, sid) in cls._files_props.keys():
return cls._files_props[account, sid]
@classmethod
def getFilePropByAccount(cls, account):
# Returns a list of file_props in one account
file_props = []
for account, sid in cls._files_props:
if account == account:
file_props.append(cls._files_props[account, sid])
return file_props
@classmethod
def getFilePropByType(cls, type_, sid):
# This method should be deleted. Getting fileprop by type and sid is not
# unique enough. More than one fileprop might have the same type and sid
files_prop = cls.getAllFileProp()
for fp in files_prop:
if fp.type_ == type_ and fp.sid == sid:
return fp
@classmethod
def getFilePropBySid(cls, sid):
# This method should be deleted. It is kept to make things compatible
# This method should be replaced and instead get the file_props by
# account and sid
files_prop = cls.getAllFileProp()
for fp in files_prop:
if fp.sid == sid:
return fp
@classmethod
def getAllFileProp(cls):
return cls._files_props.values()
@classmethod
def setFileProp(cls, fp, account, sid):
cls._files_props[account, sid] = fp
@classmethod
def deleteFileProp(cls, file_prop):
files_props = cls._files_props
a = s = None
for account, sid in files_props:
fp = files_props[account, sid]
if fp is file_prop:
a = account
s = sid
if a != None and s != None:
del files_props[a, s]
class FileProp(object):
def __init__(self, account, sid):
# Do not instatiate this class directly. Call FilesProp.getNeFileProp
# instead
self.streamhosts = []
self.transfered_size = []
self.started = False
self.completed = False
self.paused = False
self.stalled = False
self.connected = False
self.stopped = False
self.is_a_proxy = False
self.proxyhost = None
self.proxy_sender = None
self.proxy_receiver = None
self.streamhost_used = None
# method callback called in case of transfer failure
self.failure_cb = None
# method callback called when disconnecting
self.disconnect_cb = None
self.continue_cb = None
self.sha_str = None
# transfer type: 's' for sending and 'r' for receiving
self.type_ = None
self.error = None
self.elapsed_time = None
self.last_time = None
self.received_len = None
# full file path
self.file_name = None
self.name = None
self.file_desc = None
self.offset = None
self.sender = None
self.receiver = None
self.tt_account = None
self.size = None
self._sid = sid
self.account = account
self.mime_type = None
self.algo = None
self.direction = None
self.syn_id = None
self.seq = None
self.hash_ = None
self.session_sid = None
self.fd = None
self.startexmpp = None
self.session_type = None
def getsid(self):
# Getter of the property sid
return self._sid
def setsid(self, value):
# The sid value will change
# we need to change the in _files_props key as well
del FilesProp._files_props[self.account, self._sid]
self._sid = value
FilesProp._files_props[self.account, self._sid] = self
sid = property(getsid, setsid)
if __name__ == "__main__":
import doctest
doctest.testmod()
......@@ -152,7 +152,7 @@ class ConnectionJingle(object):
# this is a file transfer
jingle.session_type_FT = True
self._sessions[jingle.sid] = jingle
file_props['sid'] = jingle.sid
file_props.sid = jingle.sid
if contact.supports(xmpp.NS_JINGLE_BYTESTREAM):
transport = JingleTransportSocks5()
elif contact.supports(xmpp.NS_JINGLE_IBB):
......
......@@ -172,25 +172,25 @@ class JingleContent(object):
simode = xmpp.simplexml.Node(tag='offer')
file_tag = simode.setTag('file', namespace=xmpp.NS_FILE)
if 'name' in self.file_props:
if self.file_props.name:
node = xmpp.simplexml.Node(tag='name')
node.addData(self.file_props['name'])
node.addData(self.file_props.name)
file_tag.addChild(node=node)
if 'size' in self.file_props:
if self.file_props.size:
node = xmpp.simplexml.Node(tag='size')
node.addData(self.file_props['size'])
node.addData(self.file_props.size)
file_tag.addChild(node=node)
if 'hash' in self.file_props:
if self.file_props.hash_:
# TODO: use xep-300 for this bit
pass
# if the file is less than 10 mb, then it is small
# lets calculate it right away
if int(self.file_props['size']) < 10000000:
if int(self.file_props.size) < 10000000:
h = self._calcHash()
file_tag.addChild(node=h)
desc = file_tag.setTag('desc')
if 'desc' in self.file_props:
desc.setData(self.file_props['desc'])
if self.file_props.desc:
desc.setData(self.file_props.desc)
description_node.addChild(node=simode)
......
......@@ -76,11 +76,11 @@ class JingleFileTransfer(JingleContent):
self.weinitiate = True
if self.file_props is not None:
self.file_props['sender'] = session.ourjid
self.file_props['receiver'] = session.peerjid
self.file_props['session-type'] = 'jingle'
self.file_props['session-sid'] = session.sid
self.file_props['transfered_size'] = []
self.file_props.sender = session.ourjid
self.file_props.receiver = session.peerjid
self.file_props.session_type = 'jingle'
self.file_props.session_sid = session.sid
self.file_props.transfered_size = []
log.info("FT request: %s" % file_props)
......@@ -92,7 +92,7 @@ class JingleFileTransfer(JingleContent):
log.info('ourjid: %s' % session.ourjid)
if self.file_props is not None:
self.file_props['sid'] = self.transport.sid
self.file_props.sid = self.transport.sid
self.session = session
self.media = 'file'
......@@ -119,13 +119,12 @@ class JingleFileTransfer(JingleContent):
FT_content=self))
self._listen_host()
# Delete this after file_props refactoring this shouldn't be necesary
self.session.file_hash = self.file_props['hash']
self.session.hash_algo = self.file_props['algo']
self.session.file_hash = self.file_props.hash_
self.session.hash_algo = self.file_props.algo
def __on_session_initiate_sent(self, stanza, content, error, action):
# Calculate file_hash in a new thread
# if we haven't sent the hash already.
if 'hash' not in self.file_props:
if self.file_props.hash_ is None:
self.hashThread = threading.Thread(target=self.__send_hash)
self.hashThread.start()
......@@ -143,7 +142,7 @@ class JingleFileTransfer(JingleContent):
if self.session.hash_algo == None:
return
try:
file_ = open(self.file_props['file-name'], 'r')
file_ = open(self.file_props.file_name, 'r')
except:
# can't open file
return
......@@ -154,7 +153,7 @@ class JingleFileTransfer(JingleContent):
if not hash_:
# Hash alogrithm not supported
return
self.file_props['hash'] = hash_
self.file_props.hash_ = hash_
h.addHash(hash_, self.session.hash_algo)
return h
......@@ -175,26 +174,21 @@ class JingleFileTransfer(JingleContent):
self.__state_changed(STATE_TRANSFERING)
raise xmpp.NodeProcessed
self.file_props['streamhosts'] = self.transport.remote_candidates
for host in self.file_props['streamhosts']:
self.file_props.streamhosts = self.transport.remote_candidates
for host in self.file_props.streamhosts:
host['initiator'] = self.session.initiator
host['target'] = self.session.responder
host['sid'] = self.file_props['sid']
host['sid'] = self.file_props.sid
response = stanza.buildReply('result')
response.delChild(response.getQuery())
con.connection.send(response)
if not gajim.socks5queue.get_file_props(
self.session.connection.name, self.file_props['sid']):
gajim.socks5queue.add_file_props(self.session.connection.name,
self.file_props)
fingerprint = None
if self.use_security:
fingerprint = 'client'
if self.transport.type == TransportType.SOCKS5:
gajim.socks5queue.connect_to_hosts(self.session.connection.name,
self.file_props['sid'], self.on_connect,
self.file_props.sid, self.on_connect,
self._on_connect_error, fingerprint=fingerprint,
receiving=False)
return
......@@ -310,15 +304,15 @@ class JingleFileTransfer(JingleContent):
def _store_socks5_sid(self, sid, hash_id):
# callback from socsk5queue.start_listener
self.file_props['hash'] = hash_id
self.file_props.hash_ = hash_id
def _listen_host(self):
receiver = self.file_props['receiver']
sender = self.file_props['sender']
sha_str = helpers.get_auth_sha(self.file_props['sid'], sender,
receiver = self.file_props.receiver
sender = self.file_props.sender
sha_str = helpers.get_auth_sha(self.file_props.sid, sender,
receiver)
self.file_props['sha_str'] = sha_str
self.file_props.sha_str = sha_str
port = gajim.config.get('file_transfers_port')
......
......@@ -14,6 +14,7 @@
import gajim
import xmpp
from jingle_transport import *
from common.socks5 import Socks5ReceiverClient, Socks5SenderClient
class JingleFileTransferStates:
......@@ -37,26 +38,18 @@ class StateInitialized(JingleFileTransferStates):
'''
def action(self, args=None):
self.jft._listen_host()
if self.jft.weinitiate:
# update connection's fileprops
self.jft.session.connection.files_props[self.jft.file_props['sid']] = \
self.jft.file_props
self.jft._listen_host()
# Listen on configured port for file transfer
else:
# Add file_props to the queue
if not gajim.socks5queue.get_file_props(
self.jft.session.connection.name, self.jft.file_props['sid']):
gajim.socks5queue.add_file_props(
self.jft.session.connection.name,
self.jft.file_props)
fingerprint = None
if self.jft.use_security:
fingerprint = 'client'
# Connect to the candidate host, on success call on_connect method
gajim.socks5queue.connect_to_hosts(
self.jft.session.connection.name,
self.jft.file_props['sid'], self.jft.on_connect,
self.jft.file_props.sid, self.jft.on_connect,
self.jft._on_connect_error, fingerprint=fingerprint)
......@@ -156,9 +149,7 @@ class StateTransfering(JingleFileTransferStates):
'''
def __start_IBB_transfer(self, con):
con.files_props[self.jft.file_props['sid']] = \
self.jft.file_props
fp = open(self.jft.file_props['file-name'], 'r')
fp = open(self.jft.file_props.file_name, 'r')
con.OpenStream( self.jft.transport.sid,
self.jft.session.peerjid, fp, blocksize=4096)
......@@ -174,14 +165,14 @@ class StateTransfering(JingleFileTransferStates):
streamhost_used = self.jft.nominated_cand['peer-cand']
if streamhost_used['type'] == 'proxy':
self.jft.file_props['is_a_proxy'] = True
self.jft.file_props.is_a_proxy = True
# This needs to be changed when requesting
if self.jft.weinitiate:
self.jft.file_props['proxy_sender'] = streamhost_used['initiator']
self.jft.file_props['proxy_receiver'] = streamhost_used['target']
self.jft.file_props.proxy_sender = streamhost_used['initiator']
self.jft.file_props.proxy_receiver = streamhost_used['target']
else:
self.jft.file_props['proxy_sender'] = streamhost_used['target']
self.jft.file_props['proxy_receiver'] = streamhost_used['initiator']
self.jft.file_props.proxy_sender = streamhost_used['target']
self.jft.file_props.proxy_receiver = streamhost_used['initiator']
# This needs to be changed when requesting
if not self.jft.weinitiate and streamhost_used['type'] == 'proxy':
......@@ -200,12 +191,12 @@ class StateTransfering(JingleFileTransferStates):
return
if streamhost_used['type'] == 'proxy':
self.jft.file_props['streamhost-used'] = True
streamhost_used['sid'] = self.jft.file_props['sid']
self.jft.file_props['streamhosts'] = []
self.jft.file_props['streamhosts'].append(streamhost_used)
self.jft.file_props['proxyhosts'] = []
self.jft.file_props['proxyhosts'].append(streamhost_used)
self.jft.file_props.streamhost_used = True
streamhost_used['sid'] = self.jft.file_props.sid
self.jft.file_props.streamhosts = []
self.jft.file_props.streamhosts.append(streamhost_used)
self.jft.file_props.proxyhosts = []
self.jft.file_props.proxyhosts.append(streamhost_used)
# This needs to be changed when requesting
if self.jft.weinitiate:
......@@ -218,7 +209,7 @@ class StateTransfering(JingleFileTransferStates):
connected=False, file_props=self.jft.file_props)
else:
sockobj = Socks5ReceiverClient(gajim.idlequeue, streamhost_used,
sid=self.jft.file_props['sid'],
sid=self.jft.file_props.sid,
file_props=self.jft.file_props, fingerprint=None)
sockobj.proxy = True
sockobj.streamhost = streamhost_used
......@@ -228,7 +219,7 @@ class StateTransfering(JingleFileTransferStates):
# If we offered the nominated candidate used, we activate
# the proxy
if not self.jft.isOurCandUsed():
gajim.socks5queue.on_success[self.jft.file_props['sid']] = \
gajim.socks5queue.on_success[self.jft.file_props.sid] = \
self.jft.transport._on_proxy_auth_ok
# TODO: add on failure
else:
......
......@@ -190,8 +190,8 @@ class JingleTransportSocks5(JingleTransport):
c['type'] = 'direct'
c['jid'] = self.ourjid
c['priority'] = (2**16) * type_preference
c['initiator'] = self.file_props['sender']
c['target'] = self.file_props['receiver']
c['initiator'] = self.file_props.sender
c['target'] = self.file_props.receiver
local_ip_cand.append(c)
self._add_candidates(local_ip_cand)
......@@ -213,8 +213,8 @@ class JingleTransportSocks5(JingleTransport):
c['type'] = 'direct'
c['jid'] = self.ourjid
c['priority'] = (2**16) * type_preference
c['initiator'] = self.file_props['sender']
c['target'] = self.file_props['receiver']
c['initiator'] = self.file_props.sender
c['target'] = self.file_props.receiver
additional_ip_cand.append(c)
self._add_candidates(additional_ip_cand)
......@@ -228,7 +228,7 @@ class JingleTransportSocks5(JingleTransport):
proxyhosts = socks5conn._get_file_transfer_proxies_from_config(self.file_props)
if proxyhosts:
self.file_props['proxyhosts'] = proxyhosts
self.file_props.proxyhosts = proxyhosts
for proxyhost in proxyhosts:
c = {'host': proxyhost['host']}
......@@ -237,15 +237,15 @@ class JingleTransportSocks5(JingleTransport):
c['type'] = 'proxy'
c['jid'] = proxyhost['jid']
c['priority'] = (2**16) * type_preference
c['initiator'] = self.file_props['sender']
c['target'] = self.file_props['receiver']
c['initiator'] = self.file_props.sender
c['target'] = self.file_props.receiver
proxy_cand.append(c)
self._add_candidates(proxy_cand)
def get_content(self):
sesn = self.connection.get_jingle_session(self.ourjid,
self.file_props['session-sid'])
self.file_props.session_sid)
for content in sesn.contents.values():
if content.transport == self:
return content
......@@ -256,7 +256,7 @@ class JingleTransportSocks5(JingleTransport):
if not self.connection:
return
sesn = self.connection.get_jingle_session(self.ourjid,
self.file_props['session-sid'])
self.file_props.session_sid)
if sesn is None:
return
......
This diff is collapsed.
......@@ -31,6 +31,7 @@ from common import gajim
from common import helpers
from socks5 import Socks5
from common.xmpp.idlequeue import IdleObject
from common.file_props import FilesProp
S_INITIAL = 0
S_STARTED = 1
......@@ -248,9 +249,10 @@ class HostTester(Socks5, IdleObject):
self.on_success = on_success
self.on_failure = on_failure
self._sock = None
self.file_props = {'is_a_proxy': True,
'proxy_sender': sender_jid,
'proxy_receiver': 'test@gajim.org/test2'}
self.file_props = FilesProp.getNewFileProp(jid, sid)
self.file_props.is_a_proxy = True
self.file_props.proxy_sender = sender_jid
self.file_props.proxy_receiver = 'test@gajim.org/test2'
Socks5.__init__(self, gajim.idlequeue, host, port, None, None, None)
self.sid = sid
......@@ -367,9 +369,10 @@ class ReceiverTester(Socks5, IdleObject):
self.on_success = on_success
self.on_failure = on_failure
self._sock = None
self.file_props = {'is_a_proxy': True,
'proxy_sender': sender_jid,
'proxy_receiver': 'test@gajim.org/test2'}
self.file_props = FilesProp.getNewFileProp(jid, sid)
self.file_props.is_a_proxy = True
self.file_props.proxy_sender = sender_jid
self.file_props.proxy_receiver = 'test@gajim.org/test2'
Socks5.__init__(self, gajim.idlequeue, host, port, None, None, None)
self.sid = sid
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -730,23 +730,23 @@ class FileTransfersTooltip(BaseTooltip):
current_row = 1
self.create_window()
properties = []
name = file_props['name']
if file_props['type'] == 'r':
file_name = os.path.split(file_props['file-name'