plugin XEP-0329: new methods/signals to handle shares:

2 new methods:
- FISLocalSharesGet retrieve paths shared locally
- FISUnsharePath stop sharing a file or directory

2 new signals:
- FISSharedPathNew triggered when a new path is shared
- FISSharedPathRemoved triggered when a path is not shared anymore
This commit is contained in:
Goffi 2018-05-22 10:06:07 +02:00
commit fd73022ccb
2 changed files with 73 additions and 6 deletions

View file

@ -277,7 +277,7 @@ class XEP_0234(object):
"""Request a file using jingle file transfer
@param peer_jid(jid.JID): destinee jid
@param filepath(str): absolute path of the file
@param filepath(str): absolute path where the file will be downloaded
@param name(unicode, None): name of the file
@param file_hash(unicode, None): hash of the file
@return (D(unicode)): progress id

View file

@ -97,13 +97,16 @@ class ShareNode(object):
return self.children.__contains__(item)
def __iter__(self):
return self.children.__iter__
return self.children.__iter__()
def iteritems(self):
return self.children.iteritems()
def itervalues(self):
return self.children.itervalues()
def getOrCreate(self, name, type_=TYPE_VIRTUAL, access=None):
"""get a node or create a virtual one and return it"""
"""get a node or create a virtual node and return it"""
if access is None:
access = {C.ACCESS_PERM_READ: {KEY_TYPE: C.ACCESS_TYPE_PUBLIC}}
try:
@ -118,6 +121,15 @@ class ShareNode(object):
node.parent = self
self.children[node.name] = node
def removeFromParent(self):
try:
del self.parent.children[self.name]
except TypeError:
raise exceptions.InternalError(u'trying to remove a node from inexisting parent')
except KeyError:
raise exceptions.InternalError(u"node not found in parent's children")
self.parent = None
def _checkNodePermission(self, client, node, perms, peer_jid):
"""Check access to this node for peer_jid
@ -192,6 +204,40 @@ class ShareNode(object):
return node, u'/'.join(path_elts)
def findByLocalPath(self, path):
"""retrieve nodes linking to local path
@return (list[ShareNode]): found nodes associated to path
@raise exceptions.NotFound: no node has been found with this path
"""
shared_paths = self.getSharedPaths()
try:
return shared_paths[path]
except KeyError:
raise exceptions.NotFound
def _getSharedPaths(self, node, paths):
if node.type == TYPE_VIRTUAL:
for node in node.itervalues():
self._getSharedPaths(node, paths)
elif node.type == TYPE_PATH:
paths.setdefault(node.path, []).append(node)
else:
raise exceptions.InternalError(u'unknown node type: {type}'.format(
type = node.type))
def getSharedPaths(self):
"""retrieve nodes by shared path
this method will retrieve recursively shared path in children of this node
@return (dict): map from shared path to list of nodes
"""
if self.type == TYPE_PATH:
raise exceptions.InternalError("getSharedPaths must be used on a virtual node")
paths = {}
self._getSharedPaths(self, paths)
return paths
class XEP_0329(object):
@ -202,7 +248,11 @@ class XEP_0329(object):
self._h = host.plugins['XEP-0300']
self._jf = host.plugins['XEP-0234']
host.bridge.addMethod("FISList", ".plugin", in_sign='ssa{ss}s', out_sign='aa{ss}', method=self._listFiles, async=True)
host.bridge.addMethod("FISLocalSharesGet", ".plugin", in_sign='s', out_sign='as', method=self._localSharesGet)
host.bridge.addMethod("FISSharePath", ".plugin", in_sign='ssss', out_sign='s', method=self._sharePath)
host.bridge.addMethod("FISUnsharePath", ".plugin", in_sign='ss', out_sign='', method=self._unsharePath)
host.bridge.addSignal("FISSharedPathNew", ".plugin", signature='sss')
host.bridge.addSignal("FISSharedPathRemoved", ".plugin", signature='ss')
host.trigger.add("XEP-0234_fileSendingRequest", self._fileSendingRequestTrigger)
host.registerNamespace('fis', NS_FIS)
@ -504,6 +554,13 @@ class XEP_0329(object):
d.addCallback(self._parseResult)
return d
def _localSharesGet(self, profile):
client = self.host.getClient(profile)
return self.localSharesGet(client)
def localSharesGet(self, client):
return client._XEP_0329_root_node.getSharedPaths().keys()
def _sharePath(self, name, path, access, profile):
client = self.host.getClient(profile)
access= json.loads(access)
@ -516,6 +573,8 @@ class XEP_0329(object):
raise ValueError(_(u"This path doesn't exist!"))
if not path or not path.strip(u' /'):
raise ValueError(_(u"A path need to be specified"))
if not isinstance(access, dict):
raise ValueError(_(u'access must be a dict'))
node = client._XEP_0329_root_node
node_type = TYPE_PATH
@ -528,9 +587,6 @@ class XEP_0329(object):
if not name:
raise exceptions.InternalError(_(u"Can't find a proper name"))
if not isinstance(access, dict):
raise ValueError(_(u'access must be a dict'))
if name in node or name == SINGLE_FILES_DIR:
idx = 1
new_name = name + '_' + unicode(idx)
@ -542,8 +598,19 @@ class XEP_0329(object):
new_name=new_name, profile=client.profile)))
ShareNode(name=name, parent=node, type_=node_type, access=access, path=path)
self.host.bridge.FISSharedPathNew(path, name, client.profile)
return name
def _unsharePath(self, path, profile):
client = self.host.getClient(profile)
return self.unsharePath(client, path)
def unsharePath(self, client, path):
nodes = client._XEP_0329_root_node.findByLocalPath(path)
for node in nodes:
node.removeFromParent()
self.host.bridge.FISSharedPathRemoved(path, client.profile)
class XEP_0329_handler(xmlstream.XMPPHandler):
implements(iwokkel.IDisco)