Newer
Older
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():
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
'''
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.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,
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
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)