changeset dca85f817d2b in /home/hg/repos/gajim
details:http://hg.gajim.org/gajim?cmd=changeset;node=dca85f817d2b description: Jingle FT is now functionnal!! Thanks Jefry for the long time debugging with me
diffstat:
src/adhoc_commands.py | 2 +- src/chat_control.py | 22 +- src/common/connection_handlers_events.py | 111 +++-- src/common/dataforms.py | 8 +- src/common/file_props.py | 156 ++++++++ src/common/jingle.py | 2 +- src/common/jingle_content.py | 16 +- src/common/jingle_ft.py | 97 ++-- src/common/jingle_ftstates.py | 76 +-- src/common/jingle_transport.py | 35 +- src/common/jingle_xtls.py | 28 +- src/common/pep.py | 26 +- src/common/protocol/bytestream.py | 469 +++++++++++------------- src/common/proxy65_manager.py | 17 +- src/common/resolver.py | 10 +- src/common/socks5.py | 581 +++++++++++++----------------- src/common/stanza_session.py | 2 +- src/common/xmpp/protocol.py | 28 +- src/config.py | 2 +- src/dataforms_widget.py | 26 +- src/filetransfers_window.py | 277 +++++++------- src/groupchat_control.py | 2 +- src/gui_interface.py | 109 ++--- src/roster_window.py | 4 +- src/search_window.py | 2 +- src/statusicon.py | 2 +- src/tooltips.py | 49 +- test/lib/gajim_mocks.py | 2 +- 28 files changed, 1096 insertions(+), 1065 deletions(-)
diffs (truncated from 4574 to 300 lines):
diff -r 0c6bb3ae90e1 -r dca85f817d2b src/adhoc_commands.py --- a/src/adhoc_commands.py Wed Aug 22 22:42:00 2012 +0400 +++ b/src/adhoc_commands.py Thu Aug 23 13:10:30 2012 +0200 @@ -371,7 +371,7 @@ _('The form is not filled correctly.')) self.data_form_widget.set_sensitive(True) return - self.data_form_widget.data_form.type = 'submit' + self.data_form_widget.data_form.type_ = 'submit' else: self.data_form_widget.hide()
diff -r 0c6bb3ae90e1 -r dca85f817d2b src/chat_control.py --- a/src/chat_control.py Wed Aug 22 22:42:00 2012 +0400 +++ b/src/chat_control.py Thu Aug 23 13:10:30 2012 +0200 @@ -1737,8 +1737,8 @@
# Send file if (self.contact.supports(NS_FILE) or \ - self.contact.supports(NS_JINGLE_FILE_TRANSFER)) or \ - self.type_id == 'chat' or self.gc_contact.resource: + self.contact.supports(NS_JINGLE_FILE_TRANSFER)) or \ + self.type_id == 'chat' or self.gc_contact.resource: self._send_file_button.set_sensitive(True) self._send_file_button.set_tooltip_text('') else: @@ -3223,11 +3223,11 @@ """ 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) @@ -3236,9 +3236,7 @@ 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') @@ -3252,9 +3250,9 @@
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) diff -r 0c6bb3ae90e1 -r dca85f817d2b src/common/connection_handlers_events.py --- a/src/common/connection_handlers_events.py Wed Aug 22 22:42:00 2012 +0400 +++ b/src/common/connection_handlers_events.py Thu Aug 23 13:10:30 2012 +0200 @@ -37,6 +37,7 @@ 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
@@ -1684,7 +1685,7 @@ pep = pep_class.get_tag_as_PEP(self.fjid, self.conn.name, self.event_tag) if pep: - self.pep_type = pep.type + self.pep_type = pep.type_ return True
items = self.event_tag.getTag('items') @@ -1942,16 +1943,59 @@ 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') + for child in file_tag.getChildren(): + name = child.getName() + 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 + 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,9 +2009,9 @@ return self.dataform = dataforms.ExtendForm(node=form_tag) for f in self.dataform.iter_fields(): - if f.var == 'stream-method' and f.type == 'list-single': + 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,56 +2019,25 @@ typ='stream') raise xmpp.NodeProcessed file_tag = si.getTag('file') - for child in file_tag.getChildren(): - name = child.getName() - if name in ('name', 'size', 'hash', 'date'): - val = child.getData() + for name, val in file_tag.getAttrs().items(): 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') + if name == 'name': + self.file_props.name = val + if name == 'size': + self.file_props.size = 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): diff -r 0c6bb3ae90e1 -r dca85f817d2b src/common/dataforms.py --- a/src/common/dataforms.py Wed Aug 22 22:42:00 2012 +0400 +++ b/src/common/dataforms.py Thu Aug 23 13:10:30 2012 +0200 @@ -120,7 +120,7 @@ if extend is None: ExtendedNode.__init__(self, 'field')
- self.type = typ + self.type_ = typ self.var = var if value is not None: self.value = value @@ -248,7 +248,7 @@ self.delChild(t)
return locals() - + def is_valid(self): return True
@@ -463,7 +463,7 @@ def iter_values(self): for element in self.getTags('value'): yield element.getData() - + def is_valid(self): if not self.required: return True @@ -577,7 +577,7 @@
def __getitem__(self, item): return self.vars[item] - + def is_valid(self): for f in self.iter_fields(): if not f.is_valid(): diff -r 0c6bb3ae90e1 -r dca85f817d2b src/common/file_props.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/file_props.py Thu Aug 23 13:10:30 2012 +0200 @@ -0,0 +1,156 @@ +""" +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):