changeset 4a3d1e985d27 in /home/hg/repos/gajim-plugins
author: Jefry Lagrange jefry.reyes@gmail.com branches: details:gajim-plugins?cmd=changeset;node=4a3d1e985d27 description: fix on_request
diffstat:
file_sharing/database.py | 31 ++++++++----- file_sharing/fshare.py | 2 +- file_sharing/fshare_protocol.py | 89 ++++++++++++++++++++++++++++--------- file_sharing/tests/TestProtocol.py | 60 ++++++++++++++++++++++-- 4 files changed, 139 insertions(+), 43 deletions(-)
diffs (truncated from 326 to 300 lines):
diff -r 0b93039de291 -r 4a3d1e985d27 file_sharing/database.py --- a/file_sharing/database.py Sat Aug 31 11:32:26 2013 +0400 +++ b/file_sharing/database.py Sat Aug 31 20:52:19 2013 -0400 @@ -1,12 +1,19 @@ import sqlite3 -from common import gajim import sys import os
+''' +TODO: + 1-) Modify the database class to use models instead of method arguments + 2-) Normalize the database. Don't save dirs and files in the same table +''' + class FilesharingDatabase: - def __init__(self, plugin): - self.plugin = plugin - path_l = os.path.split(plugin.config.FILE_PATH) + + def __init__(self, FILE_PATH=None): + if not FILE_PATH: + return + path_l = os.path.split(FILE_PATH) path = os.path.join(path_l[0], 'shared_files.db') db_exist = os.path.exists(path) self.conn = sqlite3.connect(path) @@ -31,13 +38,13 @@ self.conn.commit() c.close()
- def get_toplevel_files(self, account, requester): + def get_toplevel_dirs(self, account, requester): c = self.conn.cursor() data = (account, requester) c.execute("SELECT relative_path, hash_sha1, size, description, " + "mod_date, is_dir FROM (files JOIN permissions ON" + " files.fid=permissions.fid) WHERE account=? AND requester=?" + - " AND relative_path NOT LIKE '%/%'", data) + " AND is_dir=1 AND relative_path NOT LIKE '%/%'", data) result = c.fetchall() c.close() return result @@ -88,16 +95,15 @@ else: data = (account, requester, name) sql = "SELECT relative_path, hash_sha1, size, description, " + \ - "mod_date, file_path FROM (files JOIN permissions ON" + \ + "mod_date, file_path, is_dir FROM (files JOIN permissions ON" + \ " files.fid=permissions.fid) WHERE account=? AND requester=?" +\ " AND relative_path=?" c.execute(sql, data) result = c.fetchall() c.close() - if result == []: - return None - else: + if result != []: return result[0] + return result
def get_files_name(self, account, requester): result = self.get_files(account, requester) @@ -115,7 +121,8 @@ >>> _delete_file(1) """ self._check_duplicate(account, requester, file_) - requester = gajim.get_jid_without_resource(requester) + if requester.find('/') != -1: + raise Exception('The requester must be given without a resource attached') c = self.conn.cursor() c.execute("INSERT INTO files (file_path, " + "relative_path, hash_sha1, size, description, mod_date, " + @@ -138,7 +145,7 @@ data = (account, requester, file_[2]) c.execute("SELECT * FROM (files JOIN permissions ON" + " files.fid=permissions.fid) WHERE account=? AND requester=?" + - " AND hash_sha1=?)", data) + " AND hash_sha1=?", data) result.extend(c.fetchall()) if len(result) > 0: raise Exception('Duplicated entry') diff -r 0b93039de291 -r 4a3d1e985d27 file_sharing/fshare.py --- a/file_sharing/fshare.py Sat Aug 31 11:32:26 2013 +0400 +++ b/file_sharing/fshare.py Sat Aug 31 20:52:19 2013 -0400 @@ -29,7 +29,7 @@ self.config_dialog = FileSharePluginConfigDialog(self) home_path = os.path.expanduser('~/') self.config_default_values = {'incoming_dir': (home_path, '')} - self.database = database.FilesharingDatabase(self) + self.database = database.FilesharingDatabase(self.config.FILE_PATH) # Create one protocol handler per account accounts = gajim.contacts.get_accounts() for account in gajim.contacts.get_accounts(): diff -r 0b93039de291 -r 4a3d1e985d27 file_sharing/fshare_protocol.py --- a/file_sharing/fshare_protocol.py Sat Aug 31 11:32:26 2013 +0400 +++ b/file_sharing/fshare_protocol.py Sat Aug 31 20:52:19 2013 -0400 @@ -21,6 +21,27 @@ # set our jid with resource self.ourjid = ourjid
+ + def convert_dbformat(self, records): + # Converts db output format to the one expected by the Protocol methods + formatted = [] + for record in records: + r = {'name' : record[0]} + if record[-1] == 0: + r['type'] = 'file' + if record[1] != None or record[1] != '': + r['hash'] = record[1] + if record[2] != None or record[2] != '': + r['size'] = record[2] + if record[3] != None or record[3] != '': + r['desc'] = record[3] + if record[4] != None or record[4] != '': + r['date'] = record[4] + else: + r['type'] = 'directory' + formatted.append(r) + return formatted + def request(self, contact, stanzaID, path=None): iq = nbxmpp.Iq(typ='get', to=contact, frm=self.ourjid) iq.setID(stanzaID) @@ -66,7 +87,7 @@ raise Exception("Unexpected Type") return iq
-class ProtocolDispatcher(): +class ProtocolDispatcher(Protocol): ''' Sends and receives stanzas ''' @@ -77,7 +98,8 @@ self.plugin = plugin self.conn = gajim.connections[self.account] # get our jid with resource - self.ourjid = gajim.get_jid_from_account(self.account) + ourjid = gajim.get_jid_from_account(self.account) + Protocol.__init__(self, ourjid) self.fsw = None
@@ -96,31 +118,48 @@ # TODO: reply with malformed stanza error pass
+ + def on_toplevel_request(self, stanza, jid): + roots = self.plugin.database.get_toplevel_dirs(self.account, jid) + items = [] + for root in roots: + items.append({'type' : 'directory', + 'name' : root[0] + }) + return self.offer(stanza.getID(), jid, None, items) + + def on_dir_request(self, stanza, fjid, jid, dir_): + result = self.plugin.database.get_files_from_dir(self.account, jid, dir_) + result = self.convert_dbformat(result) + return self.offer(stanza.getID(), fjid, dir_, result) + def on_request(self, stanza, fjid): - node = stanza.getQuery().getAttr('node') - jid = gajim.get_jid_without_resource(fjid) - result = self.plugin.database.get_file(self.account, jid, None, node) - return - - + jid = get_jid_without_resource(fjid) if stanza.getTag('error'): # TODO: better handle this return -1 - 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) - return 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) - return response + node = stanza.getQuery().getAttr('node') + if node is None: + return self.on_toplevel_request(stanza, jid) + result = self.plugin.database.get_file(self.account, jid, None, node) + if result == []: + return self.offer(stanza.getID(), fjid, node, result) + if result[-1] == 1: + # The peer asked for the content of a dir + reply = self.on_dir_request(self, stanza, fjid) + else: + # The peer asked for more information on a file + # TODO: Refactor, make method to convert db format to expect file + # format + file_ = [{'type' : 'file', + 'name' : result[0].split('/')[-1], + 'hash' : result[1], + 'size' : result[2], + 'desc' : result[3], + 'date' : result[4], + }] + reply = self.offer(stanza.getID(), fjid, node, file_) + return reply
def on_offer(self, stanza, fjid): offered = [] @@ -140,6 +179,10 @@ return offered
+ +def get_jid_without_resource(jid): + return jid.split('/')[0] + def get_files_info(stanza): # Crawls the stanza in search for file and dir structure. files = [] diff -r 0b93039de291 -r 4a3d1e985d27 file_sharing/tests/TestProtocol.py --- a/file_sharing/tests/TestProtocol.py Sat Aug 31 11:32:26 2013 +0400 +++ b/file_sharing/tests/TestProtocol.py Sat Aug 31 20:52:19 2013 -0400 @@ -22,6 +22,15 @@ self.assertEqual(iq.getQuery().getNamespace(), fshare_protocol.NS_FILE_SHARING) self.assertEqual(iq.getQuery().getAttr('node'), 'documents/test2.txt')
+ def test_convert_dbformat(self): + file_ = [(u'relative_path', u'hash', 999, u'description', + u'date', u'file_path', 0)] + formatted = self.protocol.convert_dbformat(file_) + self.assertNotEqual(len(formatted), 0) + for item in formatted: + self.assertEqual(type(item), type({})) + self.assertEqual(formatted[0]['type'], 'file') + def test_buildFileNode(self): file_info = {'name' : 'test2.text', 'desc' : 'test', @@ -58,18 +67,33 @@
# Mock modules -fshare_protocol.gajim = Mock() +gajim = Mock() +attr = {'get_jid_from_account.return_value': 'test@gajim.org/test'} +gajim.configure_mock(**attr) +fshare_protocol.gajim = gajim fshare_protocol.helpers = Mock()
class TestProtocolDispatcher(unittest.TestCase):
def setUp(self): - self.account = 'test@gajim.org/test' + self.account = 'test@gajim.org' self.protocol = fshare_protocol.Protocol(self.account) testc = {self.account : Mock()} fshare_protocol.gajim.connections = testc + database = Mock() + top_dirs = [(u'relative_path1', None, None, None, None, 1), + (u'relative_path2', None, None, None, None, 1)] + file_ = (u'file1', u'hash', 999, u'description', + u'date', u'file_path', 0) + attr = {'get_toplevel_dirs.return_value': top_dirs, + 'get_file.return_value': file_, + 'get_files_from_dir.return_value' : [file_, top_dirs[0]] + } + database.configure_mock(**attr) + plugin = Mock() + plugin.database = database self.dispatcher = fshare_protocol.ProtocolDispatcher( - self.account, Mock()) + self.account, plugin)
def test_handler(self): iq = self.protocol.request('peer@gajim.org/test', '1234', @@ -96,18 +120,40 @@ offered_files = self.dispatcher.on_offer(iq, 'peer@gajim.org/test') self.assertEqual(len(offered_files), 2)
- - def test_on_request(self): + def test_on_dir_request(self): iq = self.protocol.request('peer@gajim.org/test', '1234', 'documents') - response = self.dispatcher.on_request(iq, 'peer@gajim.org/test') + response = self.dispatcher.on_dir_request(iq, 'peer@gajim.org/test', + 'peer@gajim.org', 'documents') self.assertEqual(response.getType(), 'result') self.assertNotEqual(response.getID(), None) self.assertEqual(response.getQuery().getName(), 'query') self.assertEqual(response.getQuery().getNamespace(), fshare_protocol.NS_FILE_SHARING) self.assertEqual(response.getQuery().getAttr('node'), 'documents') node = response.getQuery() - self.assertEqual(len(node.getChildren()), 0)