split XEP-0096 (FT negociation) and XEP-0066 (Socks5 bytestream) into 2 clases
This commit is contained in:
parent
7387d779c0
commit
72f10672e5
10
AUTHORS
10
AUTHORS
|
@ -1,8 +1,13 @@
|
||||||
CURRENT DEVELOPERS:
|
CURRENT DEVELOPERS:
|
||||||
|
|
||||||
Alexander Cherniuk (ts33kr AT gmail.com)
|
Alexander Cherniuk (ts33kr AT gmail.com)
|
||||||
|
Nikos Kouremenos (kourem AT gmail.com)
|
||||||
Yann Leboulanger (asterix AT lagaule.org)
|
Yann Leboulanger (asterix AT lagaule.org)
|
||||||
|
Julien Pivotto (roidelapluie AT gmail.com)
|
||||||
Jonathan Schleifer (js-gajim AT webkeks.org)
|
Jonathan Schleifer (js-gajim AT webkeks.org)
|
||||||
|
Travis Shirk (travis AT pobox.com)
|
||||||
|
Brendan Taylor (whateley AT gmail.com)
|
||||||
|
Jean-Marie Traissard (jim AT lapin.org)
|
||||||
|
|
||||||
PAST DEVELOPERS:
|
PAST DEVELOPERS:
|
||||||
|
|
||||||
|
@ -10,8 +15,3 @@ Stefan Bethge (stefan AT lanpartei.de)
|
||||||
Stephan Erb (steve-e AT h3c.de)
|
Stephan Erb (steve-e AT h3c.de)
|
||||||
Vincent Hanquez (tab AT snarc.org)
|
Vincent Hanquez (tab AT snarc.org)
|
||||||
Dimitur Kirov (dkirov AT gmail.com)
|
Dimitur Kirov (dkirov AT gmail.com)
|
||||||
Nikos Kouremenos (kourem AT gmail.com)
|
|
||||||
Julien Pivotto (roidelapluie AT gmail.com)
|
|
||||||
Travis Shirk (travis AT pobox.com)
|
|
||||||
Brendan Taylor (whateley AT gmail.com)
|
|
||||||
Jean-Marie Traissard (jim AT lapin.org)
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ from common.commands import ConnectionCommands
|
||||||
from common.pubsub import ConnectionPubSub
|
from common.pubsub import ConnectionPubSub
|
||||||
from common.pep import ConnectionPEP
|
from common.pep import ConnectionPEP
|
||||||
from common.protocol.caps import ConnectionCaps
|
from common.protocol.caps import ConnectionCaps
|
||||||
from common.protocol.bytestream import ConnectionBytestream
|
from common.protocol.bytestream import ConnectionSocks5Bytestream
|
||||||
import common.caps_cache as capscache
|
import common.caps_cache as capscache
|
||||||
if gajim.HAVE_FARSIGHT:
|
if gajim.HAVE_FARSIGHT:
|
||||||
from common.jingle import ConnectionJingle
|
from common.jingle import ConnectionJingle
|
||||||
|
@ -915,13 +915,13 @@ class ConnectionHandlersBase:
|
||||||
|
|
||||||
return sess
|
return sess
|
||||||
|
|
||||||
class ConnectionHandlers(ConnectionVcard, ConnectionBytestream,
|
class ConnectionHandlers(ConnectionVcard, ConnectionSocks5Bytestream,
|
||||||
ConnectionDisco, ConnectionCommands, ConnectionPubSub, ConnectionPEP,
|
ConnectionDisco, ConnectionCommands, ConnectionPubSub, ConnectionPEP,
|
||||||
ConnectionCaps, ConnectionHandlersBase, ConnectionJingle):
|
ConnectionCaps, ConnectionHandlersBase, ConnectionJingle):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
global HAS_IDLE
|
global HAS_IDLE
|
||||||
ConnectionVcard.__init__(self)
|
ConnectionVcard.__init__(self)
|
||||||
ConnectionBytestream.__init__(self)
|
ConnectionSocks5Bytestream.__init__(self)
|
||||||
ConnectionCommands.__init__(self)
|
ConnectionCommands.__init__(self)
|
||||||
ConnectionPubSub.__init__(self)
|
ConnectionPubSub.__init__(self)
|
||||||
ConnectionPEP.__init__(self, account=self.name, dispatcher=self,
|
ConnectionPEP.__init__(self, account=self.name, dispatcher=self,
|
||||||
|
|
|
@ -75,6 +75,190 @@ class ConnectionBytestream:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.files_props = {}
|
self.files_props = {}
|
||||||
|
|
||||||
|
def _ft_get_our_jid(self):
|
||||||
|
our_jid = gajim.get_jid_from_account(self.name)
|
||||||
|
resource = self.server_resource
|
||||||
|
return our_jid + '/' + resource
|
||||||
|
|
||||||
|
def _ft_get_receiver_jid(self, file_props):
|
||||||
|
return file_props['receiver'].jid + '/' + file_props['receiver'].resource
|
||||||
|
|
||||||
|
def _ft_get_from(self, iq_obj):
|
||||||
|
return helpers.get_full_jid_from_iq(iq_obj)
|
||||||
|
|
||||||
|
def _ft_get_streamhost_jid_attr(self, streamhost):
|
||||||
|
return helpers.parse_jid(streamhost.getAttr('jid'))
|
||||||
|
|
||||||
|
def send_file_request(self, file_props):
|
||||||
|
"""
|
||||||
|
Send iq for new FT request
|
||||||
|
"""
|
||||||
|
if not self.connection or self.connected < 2:
|
||||||
|
return
|
||||||
|
file_props['sender'] = self._ft_get_our_jid()
|
||||||
|
fjid = self._ft_get_receiver_jid(file_props)
|
||||||
|
iq = xmpp.Iq(to=fjid, typ='set')
|
||||||
|
iq.setID(file_props['sid'])
|
||||||
|
self.files_props[file_props['sid']] = file_props
|
||||||
|
si = iq.setTag('si', namespace=xmpp.NS_SI)
|
||||||
|
si.setAttr('profile', xmpp.NS_FILE)
|
||||||
|
si.setAttr('id', file_props['sid'])
|
||||||
|
file_tag = si.setTag('file', namespace=xmpp.NS_FILE)
|
||||||
|
file_tag.setAttr('name', file_props['name'])
|
||||||
|
file_tag.setAttr('size', file_props['size'])
|
||||||
|
desc = file_tag.setTag('desc')
|
||||||
|
if 'desc' in file_props:
|
||||||
|
desc.setData(file_props['desc'])
|
||||||
|
file_tag.setTag('range')
|
||||||
|
feature = si.setTag('feature', namespace=xmpp.NS_FEATURE)
|
||||||
|
_feature = xmpp.DataForm(typ='form')
|
||||||
|
feature.addChild(node=_feature)
|
||||||
|
field = _feature.setField('stream-method')
|
||||||
|
field.setAttr('type', 'list-single')
|
||||||
|
field.addOption(xmpp.NS_BYTESTREAM)
|
||||||
|
self.connection.send(iq)
|
||||||
|
|
||||||
|
def send_file_approval(self, file_props):
|
||||||
|
"""
|
||||||
|
Send iq, confirming that we want to download the file
|
||||||
|
"""
|
||||||
|
# user response to ConfirmationDialog may come after we've disconneted
|
||||||
|
if not self.connection or self.connected < 2:
|
||||||
|
return
|
||||||
|
iq = xmpp.Iq(to=unicode(file_props['sender']), typ='result')
|
||||||
|
iq.setAttr('id', file_props['request-id'])
|
||||||
|
si = iq.setTag('si', namespace=xmpp.NS_SI)
|
||||||
|
if 'offset' in file_props and file_props['offset']:
|
||||||
|
file_tag = si.setTag('file', namespace=xmpp.NS_FILE)
|
||||||
|
range_tag = file_tag.setTag('range')
|
||||||
|
range_tag.setAttr('offset', file_props['offset'])
|
||||||
|
feature = si.setTag('feature', namespace=xmpp.NS_FEATURE)
|
||||||
|
_feature = xmpp.DataForm(typ='submit')
|
||||||
|
feature.addChild(node=_feature)
|
||||||
|
field = _feature.setField('stream-method')
|
||||||
|
field.delAttr('type')
|
||||||
|
field.setValue(xmpp.NS_BYTESTREAM)
|
||||||
|
self.connection.send(iq)
|
||||||
|
|
||||||
|
def send_file_rejection(self, file_props, code='403', typ=None):
|
||||||
|
"""
|
||||||
|
Inform sender that we refuse to download the file
|
||||||
|
|
||||||
|
typ is used when code = '400', in this case typ can be 'strean' for
|
||||||
|
invalid stream or 'profile' for invalid profile
|
||||||
|
"""
|
||||||
|
# user response to ConfirmationDialog may come after we've disconneted
|
||||||
|
if not self.connection or self.connected < 2:
|
||||||
|
return
|
||||||
|
iq = xmpp.Iq(to=unicode(file_props['sender']), typ='error')
|
||||||
|
iq.setAttr('id', file_props['request-id'])
|
||||||
|
if code == '400' and typ in ('stream', 'profile'):
|
||||||
|
name = 'bad-request'
|
||||||
|
text = ''
|
||||||
|
else:
|
||||||
|
name = 'forbidden'
|
||||||
|
text = 'Offer Declined'
|
||||||
|
err = xmpp.ErrorNode(code=code, typ='cancel', name=name, text=text)
|
||||||
|
if code == '400' and typ in ('stream', 'profile'):
|
||||||
|
if typ == 'stream':
|
||||||
|
err.setTag('no-valid-streams', namespace=xmpp.NS_SI)
|
||||||
|
else:
|
||||||
|
err.setTag('bad-profile', namespace=xmpp.NS_SI)
|
||||||
|
iq.addChild(node=err)
|
||||||
|
self.connection.send(iq)
|
||||||
|
|
||||||
|
def _siResultCB(self, con, iq_obj):
|
||||||
|
file_props = self.files_props.get(iq_obj.getAttr('id'))
|
||||||
|
if not file_props:
|
||||||
|
return
|
||||||
|
if 'request-id' in file_props:
|
||||||
|
# we have already sent streamhosts info
|
||||||
|
return
|
||||||
|
file_props['receiver'] = self._ft_get_from(iq_obj)
|
||||||
|
si = iq_obj.getTag('si')
|
||||||
|
file_tag = si.getTag('file')
|
||||||
|
range_tag = None
|
||||||
|
if file_tag:
|
||||||
|
range_tag = file_tag.getTag('range')
|
||||||
|
if range_tag:
|
||||||
|
offset = range_tag.getAttr('offset')
|
||||||
|
if offset:
|
||||||
|
file_props['offset'] = int(offset)
|
||||||
|
length = range_tag.getAttr('length')
|
||||||
|
if length:
|
||||||
|
file_props['length'] = int(length)
|
||||||
|
feature = si.setTag('feature')
|
||||||
|
if feature.getNamespace() != xmpp.NS_FEATURE:
|
||||||
|
return
|
||||||
|
form_tag = feature.getTag('x')
|
||||||
|
form = xmpp.DataForm(node=form_tag)
|
||||||
|
field = form.getField('stream-method')
|
||||||
|
if field.getValue() != xmpp.NS_BYTESTREAM:
|
||||||
|
return
|
||||||
|
self._send_socks5_info(file_props)
|
||||||
|
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]
|
||||||
|
if xmpp.NS_BYTESTREAM 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))
|
||||||
|
raise xmpp.NodeProcessed
|
||||||
|
|
||||||
|
def _siErrorCB(self, con, iq_obj):
|
||||||
|
si = iq_obj.getTag('si')
|
||||||
|
profile = si.getAttr('profile')
|
||||||
|
if profile != xmpp.NS_FILE:
|
||||||
|
return
|
||||||
|
file_props = self.files_props.get(iq_obj.getAttr('id'))
|
||||||
|
if not file_props:
|
||||||
|
return
|
||||||
|
jid = self._ft_get_from(iq_obj)
|
||||||
|
file_props['error'] = -3
|
||||||
|
self.dispatch('FILE_REQUEST_ERROR', (jid, file_props, ''))
|
||||||
|
raise xmpp.NodeProcessed
|
||||||
|
|
||||||
|
class ConnectionSocks5Bytestream(ConnectionBytestream):
|
||||||
|
|
||||||
def send_success_connect_reply(self, streamhost):
|
def send_success_connect_reply(self, streamhost):
|
||||||
"""
|
"""
|
||||||
Send reply to the initiator of FT that we made a connection
|
Send reply to the initiator of FT that we made a connection
|
||||||
|
@ -252,92 +436,6 @@ class ConnectionBytestream:
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def send_file_rejection(self, file_props, code='403', typ=None):
|
|
||||||
"""
|
|
||||||
Inform sender that we refuse to download the file
|
|
||||||
|
|
||||||
typ is used when code = '400', in this case typ can be 'strean' for
|
|
||||||
invalid stream or 'profile' for invalid profile
|
|
||||||
"""
|
|
||||||
# user response to ConfirmationDialog may come after we've disconneted
|
|
||||||
if not self.connection or self.connected < 2:
|
|
||||||
return
|
|
||||||
iq = xmpp.Iq(to=unicode(file_props['sender']), typ='error')
|
|
||||||
iq.setAttr('id', file_props['request-id'])
|
|
||||||
if code == '400' and typ in ('stream', 'profile'):
|
|
||||||
name = 'bad-request'
|
|
||||||
text = ''
|
|
||||||
else:
|
|
||||||
name = 'forbidden'
|
|
||||||
text = 'Offer Declined'
|
|
||||||
err = xmpp.ErrorNode(code=code, typ='cancel', name=name, text=text)
|
|
||||||
if code == '400' and typ in ('stream', 'profile'):
|
|
||||||
if typ == 'stream':
|
|
||||||
err.setTag('no-valid-streams', namespace=xmpp.NS_SI)
|
|
||||||
else:
|
|
||||||
err.setTag('bad-profile', namespace=xmpp.NS_SI)
|
|
||||||
iq.addChild(node=err)
|
|
||||||
self.connection.send(iq)
|
|
||||||
|
|
||||||
def send_file_approval(self, file_props):
|
|
||||||
"""
|
|
||||||
Send iq, confirming that we want to download the file
|
|
||||||
"""
|
|
||||||
# user response to ConfirmationDialog may come after we've disconneted
|
|
||||||
if not self.connection or self.connected < 2:
|
|
||||||
return
|
|
||||||
iq = xmpp.Iq(to=unicode(file_props['sender']), typ='result')
|
|
||||||
iq.setAttr('id', file_props['request-id'])
|
|
||||||
si = iq.setTag('si', namespace=xmpp.NS_SI)
|
|
||||||
if 'offset' in file_props and file_props['offset']:
|
|
||||||
file_tag = si.setTag('file', namespace=xmpp.NS_FILE)
|
|
||||||
range_tag = file_tag.setTag('range')
|
|
||||||
range_tag.setAttr('offset', file_props['offset'])
|
|
||||||
feature = si.setTag('feature', namespace=xmpp.NS_FEATURE)
|
|
||||||
_feature = xmpp.DataForm(typ='submit')
|
|
||||||
feature.addChild(node=_feature)
|
|
||||||
field = _feature.setField('stream-method')
|
|
||||||
field.delAttr('type')
|
|
||||||
field.setValue(xmpp.NS_BYTESTREAM)
|
|
||||||
self.connection.send(iq)
|
|
||||||
|
|
||||||
def _ft_get_our_jid(self):
|
|
||||||
our_jid = gajim.get_jid_from_account(self.name)
|
|
||||||
resource = self.server_resource
|
|
||||||
return our_jid + '/' + resource
|
|
||||||
|
|
||||||
def _ft_get_receiver_jid(self, file_props):
|
|
||||||
return file_props['receiver'].jid + '/' + file_props['receiver'].resource
|
|
||||||
|
|
||||||
def send_file_request(self, file_props):
|
|
||||||
"""
|
|
||||||
Send iq for new FT request
|
|
||||||
"""
|
|
||||||
if not self.connection or self.connected < 2:
|
|
||||||
return
|
|
||||||
file_props['sender'] = self._ft_get_our_jid()
|
|
||||||
fjid = self._ft_get_receiver_jid(file_props)
|
|
||||||
iq = xmpp.Iq(to=fjid, typ='set')
|
|
||||||
iq.setID(file_props['sid'])
|
|
||||||
self.files_props[file_props['sid']] = file_props
|
|
||||||
si = iq.setTag('si', namespace=xmpp.NS_SI)
|
|
||||||
si.setAttr('profile', xmpp.NS_FILE)
|
|
||||||
si.setAttr('id', file_props['sid'])
|
|
||||||
file_tag = si.setTag('file', namespace=xmpp.NS_FILE)
|
|
||||||
file_tag.setAttr('name', file_props['name'])
|
|
||||||
file_tag.setAttr('size', file_props['size'])
|
|
||||||
desc = file_tag.setTag('desc')
|
|
||||||
if 'desc' in file_props:
|
|
||||||
desc.setData(file_props['desc'])
|
|
||||||
file_tag.setTag('range')
|
|
||||||
feature = si.setTag('feature', namespace=xmpp.NS_FEATURE)
|
|
||||||
_feature = xmpp.DataForm(typ='form')
|
|
||||||
feature.addChild(node=_feature)
|
|
||||||
field = _feature.setField('stream-method')
|
|
||||||
field.setAttr('type', 'list-single')
|
|
||||||
field.addOption(xmpp.NS_BYTESTREAM)
|
|
||||||
self.connection.send(iq)
|
|
||||||
|
|
||||||
def _result_socks5_sid(self, sid, hash_id):
|
def _result_socks5_sid(self, sid, hash_id):
|
||||||
"""
|
"""
|
||||||
Store the result of SHA message from auth
|
Store the result of SHA message from auth
|
||||||
|
@ -406,9 +504,6 @@ class ConnectionBytestream:
|
||||||
self.dispatch('FILE_REQUEST_ERROR', (jid, file_props, ''))
|
self.dispatch('FILE_REQUEST_ERROR', (jid, file_props, ''))
|
||||||
raise xmpp.NodeProcessed
|
raise xmpp.NodeProcessed
|
||||||
|
|
||||||
def _ft_get_from(self, iq_obj):
|
|
||||||
return helpers.get_full_jid_from_iq(iq_obj)
|
|
||||||
|
|
||||||
def _bytestreamSetCB(self, con, iq_obj):
|
def _bytestreamSetCB(self, con, iq_obj):
|
||||||
target = unicode(iq_obj.getAttr('to'))
|
target = unicode(iq_obj.getAttr('to'))
|
||||||
id_ = unicode(iq_obj.getAttr('id'))
|
id_ = unicode(iq_obj.getAttr('id'))
|
||||||
|
@ -466,9 +561,6 @@ class ConnectionBytestream:
|
||||||
gajim.socks5queue.activate_proxy(host['idx'])
|
gajim.socks5queue.activate_proxy(host['idx'])
|
||||||
raise xmpp.NodeProcessed
|
raise xmpp.NodeProcessed
|
||||||
|
|
||||||
def _ft_get_streamhost_jid_attr(self, streamhost):
|
|
||||||
return helpers.parse_jid(streamhost.getAttr('jid'))
|
|
||||||
|
|
||||||
def _bytestreamResultCB(self, con, iq_obj):
|
def _bytestreamResultCB(self, con, iq_obj):
|
||||||
frm = self._ft_get_from(iq_obj)
|
frm = self._ft_get_from(iq_obj)
|
||||||
real_id = unicode(iq_obj.getAttr('id'))
|
real_id = unicode(iq_obj.getAttr('id'))
|
||||||
|
@ -542,98 +634,7 @@ class ConnectionBytestream:
|
||||||
|
|
||||||
raise xmpp.NodeProcessed
|
raise xmpp.NodeProcessed
|
||||||
|
|
||||||
def _siResultCB(self, con, iq_obj):
|
class ConnectionSocks5BytestreamZeroconf(ConnectionSocks5Bytestream):
|
||||||
file_props = self.files_props.get(iq_obj.getAttr('id'))
|
|
||||||
if not file_props:
|
|
||||||
return
|
|
||||||
if 'request-id' in file_props:
|
|
||||||
# we have already sent streamhosts info
|
|
||||||
return
|
|
||||||
file_props['receiver'] = self._ft_get_from(iq_obj)
|
|
||||||
si = iq_obj.getTag('si')
|
|
||||||
file_tag = si.getTag('file')
|
|
||||||
range_tag = None
|
|
||||||
if file_tag:
|
|
||||||
range_tag = file_tag.getTag('range')
|
|
||||||
if range_tag:
|
|
||||||
offset = range_tag.getAttr('offset')
|
|
||||||
if offset:
|
|
||||||
file_props['offset'] = int(offset)
|
|
||||||
length = range_tag.getAttr('length')
|
|
||||||
if length:
|
|
||||||
file_props['length'] = int(length)
|
|
||||||
feature = si.setTag('feature')
|
|
||||||
if feature.getNamespace() != xmpp.NS_FEATURE:
|
|
||||||
return
|
|
||||||
form_tag = feature.getTag('x')
|
|
||||||
form = xmpp.DataForm(node=form_tag)
|
|
||||||
field = form.getField('stream-method')
|
|
||||||
if field.getValue() != xmpp.NS_BYTESTREAM:
|
|
||||||
return
|
|
||||||
self._send_socks5_info(file_props)
|
|
||||||
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]
|
|
||||||
if xmpp.NS_BYTESTREAM 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))
|
|
||||||
raise xmpp.NodeProcessed
|
|
||||||
|
|
||||||
def _siErrorCB(self, con, iq_obj):
|
|
||||||
si = iq_obj.getTag('si')
|
|
||||||
profile = si.getAttr('profile')
|
|
||||||
if profile != xmpp.NS_FILE:
|
|
||||||
return
|
|
||||||
file_props = self.files_props.get(iq_obj.getAttr('id'))
|
|
||||||
if not file_props:
|
|
||||||
return
|
|
||||||
jid = self._ft_get_from(iq_obj)
|
|
||||||
file_props['error'] = -3
|
|
||||||
self.dispatch('FILE_REQUEST_ERROR', (jid, file_props, ''))
|
|
||||||
raise xmpp.NodeProcessed
|
|
||||||
|
|
||||||
|
|
||||||
class ConnectionBytestreamZeroconf(ConnectionBytestream):
|
|
||||||
|
|
||||||
def _ft_get_from(self, iq_obj):
|
def _ft_get_from(self, iq_obj):
|
||||||
return unicode(iq_obj.getFrom())
|
return unicode(iq_obj.getFrom())
|
||||||
|
|
|
@ -35,7 +35,7 @@ from common import gajim
|
||||||
from common.zeroconf import zeroconf
|
from common.zeroconf import zeroconf
|
||||||
from common.commands import ConnectionCommands
|
from common.commands import ConnectionCommands
|
||||||
from common.pep import ConnectionPEP
|
from common.pep import ConnectionPEP
|
||||||
from common.protocol.bytestream import ConnectionBytestreamZeroconf
|
from common.protocol.bytestream import ConnectionSocks5BytestreamZeroconf
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger('gajim.c.z.connection_handlers_zeroconf')
|
log = logging.getLogger('gajim.c.z.connection_handlers_zeroconf')
|
||||||
|
@ -70,8 +70,9 @@ class ConnectionVcard(connection_handlers.ConnectionVcard):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ConnectionHandlersZeroconf(ConnectionVcard, ConnectionBytestreamZeroconf,
|
class ConnectionHandlersZeroconf(ConnectionVcard,
|
||||||
ConnectionCommands, ConnectionPEP, connection_handlers.ConnectionHandlersBase):
|
ConnectionSocks5BytestreamZeroconf, ConnectionCommands, ConnectionPEP,
|
||||||
|
connection_handlers.ConnectionHandlersBase):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ConnectionVcard.__init__(self)
|
ConnectionVcard.__init__(self)
|
||||||
ConnectionBytestreamZeroconf.__init__(self)
|
ConnectionBytestreamZeroconf.__init__(self)
|
||||||
|
|
Loading…
Reference in New Issue