import nbxmpp from nbxmpp import Hashes try: from common import helpers from common import gajim except ImportError: print "Import Error: Ignore if we are testing" # Namespace for file sharing NS_FILE_SHARING = 'http://gajim.org/protocol/filesharing' class Protocol(): ''' Creates and extracts information from stanzas ''' def __init__(self, ourjid): # set our jid with resource self.ourjid = ourjid def request(self, contact, stanzaID, path=None): iq = nbxmpp.Iq(typ='get', to=contact, frm=self.ourjid) iq.setID(stanzaID) query = iq.setQuery() query.setNamespace(NS_FILE_SHARING) query.setAttr('node', path) return iq def buildReply(self, typ, stanza): iq = nbxmpp.Iq(typ, to=stanza.getFrom(), frm=stanza.getTo(), attrs={'id': stanza.getID()}) iq.addChild(name='match', namespace=NS_FILE_SHARING) return iq def offer(self, id_, contact, items): iq = nbxmpp.Iq(typ='result', to=contact, frm=self.ourjid, attrs={'id': id_}) match = iq.addChild(name='match', namespace=NS_FILE_SHARING) offer = match.addChild(name='offer') if len(items) == 0: offer.addChild(name='directory') else: for i in items: # if it is a directory if i[5] == True: item = offer.addChild(name='directory') name = item.addChild('name') name.setData('/' + i[0]) else: item = offer.addChild(name='file') item.addChild('name').setData('/' + i[0]) if i[1] != '': h = Hashes() h.addHash(i[1], 'sha-1') item.addChild(node=h) item.addChild('size').setData(i[2]) item.addChild('desc').setData(i[3]) item.addChild('date').setData(i[4]) return iq class ProtocolDispatcher(): ''' Sends and receives stanzas ''' def __init__(self, account, plugin): self.account = account self.plugin = plugin self.conn = gajim.connections[self.account] # get our jid with resource self.ourjid = gajim.get_jid_from_account(self.account) self.fsw = None def set_window(self, fsw): self.fsw = fsw def set_window(self, window): self.fsw = window def handler(self, stanza): # handles incoming match stanza if stanza.getTag('match').getTag('offer'): self.on_offer(stanza) elif stanza.getTag('match').getTag('request'): self.on_request(stanza) else: # TODO: reply with malformed stanza error pass def on_request(self, stanza): try: fjid = helpers.get_full_jid_from_iq(stanza) except helpers.InvalidFormat: # A message from a non-valid JID arrived, it has been ignored. return if stanza.getTag('error'): # TODO: better handle this return jid = gajim.get_jid_without_resource(fjid) req = stanza.getTag('match').getTag('request') if req.getTag('directory') and not \ req.getTag('directory').getChildren(): # We just received a toplevel directory request files = self.plugin.database.get_toplevel_files(self.account, jid) response = self.offer(stanza.getID(), fjid, files) self.conn.connection.send(response) elif req.getTag('directory') and req.getTag('directory').getTag('name'): dir_ = req.getTag('directory').getTag('name').getData()[1:] files = self.plugin.database.get_files_from_dir(self.account, jid, dir_) response = self.offer(stanza.getID(), fjid, files) self.conn.connection.send(response) def on_offer(self, stanza): # We just got a stanza offering files fjid = helpers.get_full_jid_from_iq(stanza) info = get_files_info(stanza) if fjid not in self.fsw.browse_jid or not info: # We weren't expecting anything from this contact, do nothing # Or we didn't receive any offering files return flist = [] for f in info[0]: flist.append(f['name']) flist.extend(info[1]) self.fsw.browse_fref = self.fsw.add_file_list(flist, self.fsw.ts_search, self.fsw.browse_fref, self.fsw.browse_jid[fjid] ) for f in info[0]: iter_ = self.fsw.browse_fref[f['name']] path = self.fsw.ts_search.get_path(iter_) self.fsw.brw_file_info[path] = (f['name'], f['date'], f['size'], f['hash'], f['desc']) # TODO: add tooltip ''' for f in info[0]: r = self.fsw.browse_fref[f['name']] path = self.fsw.ts_search.get_path(r) # AM HERE WORKING ON THE TOOLTIP tooltip.set_text('noooo') self.fsw.tv_search.set_tooltip_row(tooltip, path) ''' for dir_ in info[1]: if dir_ not in self.fsw.empty_row_child: parent = self.fsw.browse_fref[dir_] row = self.fsw.ts_search.append(parent, ('',)) self.fsw.empty_row_child[dir_] = row def get_files_info(stanza): # Crawls the stanza in search for file and dir structure. files = [] dirs = [] children = stanza.getTag('match').getTag('offer').getChildren() for c in children: if c.getName() == 'file': f = {'name' : \ c.getTag('name').getData()[1:] if c.getTag('name') else '', 'size' : c.getTag('size').getData() if c.getTag('size') else '', 'date' : c.getTag('date').getData() if c.getTag('date') else '', 'desc' : c.getTag('desc').getData() if c.getTag('desc') else '', # TODO: handle different hash algo 'hash' : c.getTag('hash').getData() if c.getTag('hash') else '', } files.append(f) else: dirname = c.getTag('name') if dirname is None: return None dirs.append(dirname.getData()[1:]) return (files, dirs)