annotate src/plugins/plugin_xep_0329.py @ 2503:c0bec8bac2b5

XEP-0329: implementation of File Information Sharing: the plugin do an implementation for client and component. For client, any directory from local file can be shared. For component file are stored using new file handling mechanism from SàT. Permission is handled, using "public" and "whitelist" for now.
author Goffi <goffi@goffi.org>
date Wed, 28 Feb 2018 18:28:39 +0100
parents
children 025afb04c10b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2503
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/env python2
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
2 # -*- coding: utf-8 -*-
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
3
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 # SAT plugin for File Information Sharing (XEP-0329)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
5 # Copyright (C) 2009-2018 Jérôme Poisson (goffi@goffi.org)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
6
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # This program is free software: you can redistribute it and/or modify
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # it under the terms of the GNU Affero General Public License as published by
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # the Free Software Foundation, either version 3 of the License, or
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
10 # (at your option) any later version.
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
11
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # This program is distributed in the hope that it will be useful,
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
15 # GNU Affero General Public License for more details.
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
16
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # You should have received a copy of the GNU Affero General Public License
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
19
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
20 from sat.core.i18n import _
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
21 from sat.core import exceptions
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
22 from sat.core.constants import Const as C
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
23 from sat.core.log import getLogger
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
24 log = getLogger(__name__)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
25 from sat.tools import stream
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
26 from sat.tools.common import regex
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
27 from wokkel import disco, iwokkel
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
28 from zope.interface import implements
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
29 from twisted.words.protocols.jabber import xmlstream
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
30 from twisted.words.protocols.jabber import jid
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
31 from twisted.words.protocols.jabber import error as jabber_error
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 from twisted.internet import defer
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 import mimetypes
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
34 import json
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 import os
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
36
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
37
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
38 PLUGIN_INFO = {
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
39 C.PI_NAME: "File Information Sharing",
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
40 C.PI_IMPORT_NAME: "XEP-0329",
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
41 C.PI_TYPE: "XEP",
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
42 C.PI_MODES: C.PLUG_MODE_BOTH,
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
43 C.PI_PROTOCOLS: ["XEP-0329"],
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
44 C.PI_DEPENDENCIES: ["XEP-0234", "XEP-0300"],
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
45 C.PI_MAIN: "XEP_0329",
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
46 C.PI_HANDLER: "yes",
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 C.PI_DESCRIPTION: _(u"""Implementation of File Information Sharing""")
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
48 }
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
49
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
50 NS_FIS = 'urn:xmpp:fis:0'
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
51
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
52 IQ_FIS_REQUEST = C.IQ_GET + '/query[@xmlns="' + NS_FIS + '"]'
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
53 SINGLE_FILES_DIR = u"files"
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
54 TYPE_VIRTUAL= u'virtual'
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
55 TYPE_PATH = u'path'
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
56 SHARE_TYPES = (TYPE_PATH, TYPE_VIRTUAL)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
57 KEY_TYPE = u'type'
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
58
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
59
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
60 class ShareNode(object):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
61 """node containing directory or files to share, virtual or real"""
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
62 host = None
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
63
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
64 def __init__(self, name, parent, type_, access, path=None):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
65 assert type_ in SHARE_TYPES
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
66 if name is not None:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
67 if name == u'..' or u'/' in name or u'\\' in name:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
68 log.warning(_(u'path change chars found in name [{name}], hack attempt?').format(name=name))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
69 if name == u'..':
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
70 name = u'--'
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
71 else:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
72 name = regex.pathEscape(name)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
73 self.name = name
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
74 self.children = {}
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
75 self.type = type_
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
76 self.access = {} if access is None else access
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
77 assert isinstance(self.access, dict)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
78 self.persistent = False
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
79 self.parent = None
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
80 if parent is not None:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
81 assert name
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
82 parent.addChild(self)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
83 else:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
84 assert name is None
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
85 if path is not None:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
86 if type_ != TYPE_PATH:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
87 raise exceptions.InternalError(_(u"path can only be set on path nodes"))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
88 self._path = path
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
89
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
90 @property
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
91 def path(self):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
92 return self._path
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
93
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
94 def __getitem__(self, key):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
95 return self.children[key]
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
96
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
97 def __contains__(self, item):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
98 return self.children.__contains__(item)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
99
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
100 def __iter__(self):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
101 return self.children.__iter__
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
102
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
103 def iteritems(self):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
104 return self.children.iteritems()
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
105
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
106 def getOrCreate(self, name, type_=TYPE_VIRTUAL, access=None):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
107 """get a node or create a virtual one and return it"""
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
108 if access is None:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
109 access = {C.ACCESS_PERM_READ: {KEY_TYPE: C.ACCESS_TYPE_PUBLIC}}
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
110 try:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
111 return self.children[name]
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
112 except KeyError:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
113 node = ShareNode(name, self, type_=type_, access=access)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
114 return node
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
115
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
116 def addChild(self, node):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
117 if node.parent is not None:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
118 raise exceptions.ConflictError(_(u"a node can't have several parents"))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
119 node.parent = self
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
120 self.children[node.name] = node
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
121
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
122 def _checkNodePermission(self, client, node, perms, peer_jid):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
123 """Check access to this node for peer_jid
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
124
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
125 @param node(SharedNode): node to check access
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
126 @param perms(unicode): permissions to check, iterable of C.ACCESS_PERM_*
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
127 @param peer_jid(jid.JID): entity which try to access the node
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
128 @return (bool): True if entity can access
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
129 """
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
130 file_data = {u'access':self.access, u'owner': client.jid.userhostJID()}
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
131 try:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
132 self.host.memory.checkFilePermission(file_data, peer_jid, perms)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
133 except exceptions.PermissionError:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
134 return False
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
135 else:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
136 return True
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
137
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
138 def checkPermissions(self, client, peer_jid, perms=(C.ACCESS_PERM_READ,), check_parents=True):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
139 """check that peer_jid can access this node and all its parents
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
140
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
141 @param peer_jid(jid.JID): entrity trying to access the node
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
142 @param perms(unicode): permissions to check, iterable of C.ACCESS_PERM_*
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
143 @param check_parents(bool): if True, access of all parents of this node will be checked too
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
144 @return (bool): True if entity can access this node
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
145 """
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
146 peer_jid = peer_jid.userhostJID()
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
147 if peer_jid == client.jid.userhostJID():
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
148 return True
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
149
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
150 parent = self
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
151 while parent != None:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
152 if not self._checkNodePermission(client, parent, perms, peer_jid):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
153 return False
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
154 parent = parent.parent
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
155
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
156 return True
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
157
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
158 @staticmethod
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
159 def find(client, path, peer_jid, perms=(C.ACCESS_PERM_READ,)):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
160 """find node corresponding to a path
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
161
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
162 @param path(unicode): path to the requested file or directory
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
163 @param peer_jid(jid.JID): entity trying to find the node
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
164 used to check permission
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
165 @return (dict, unicode): shared data, remaining path
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
166 @raise exceptions.PermissionError: user can't access this file
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
167 @raise exceptions.DataError: path is invalid
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
168 @raise NotFound: path lead to a non existing file/directory
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
169 """
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
170 path_elts = filter(None, path.split(u'/'))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
171
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
172 if u'..' in path_elts:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
173 log.warning(_(u'parent dir ("..") found in path, hack attempt? path is {path} [{profile}]').format(
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
174 path=path, profile=client.profile))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
175 raise exceptions.PermissionError(u"illegal path elements")
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
176
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
177 if not path_elts:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
178 raise exceptions.DataError(_(u'path is invalid: {path}').format(path=path))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
179
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
180 node = client._XEP_0329_root_node
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
181
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
182 while path_elts:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
183 if node.type == TYPE_VIRTUAL:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
184 try:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
185 node = node[path_elts.pop(0)]
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
186 except KeyError:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
187 raise exceptions.NotFound
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
188 elif node.type == TYPE_PATH:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
189 break
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
190
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
191 if not node.checkPermissions(client, peer_jid, perms = perms):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
192 raise exceptions.PermissionError(u"permission denied")
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
193
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
194 return node, u'/'.join(path_elts)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
195
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
196
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
197 class XEP_0329(object):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
198
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
199 def __init__(self, host):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
200 log.info(_("File Information Sharing initialization"))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
201 self.host = host
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
202 ShareNode.host = host
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
203 self._h = host.plugins['XEP-0300']
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
204 self._jf = host.plugins['XEP-0234']
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
205 host.bridge.addMethod("FISList", ".plugin", in_sign='ssa{ss}s', out_sign='aa{ss}', method=self._listFiles, async=True)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
206 host.bridge.addMethod("FISSharePath", ".plugin", in_sign='ssss', out_sign='s', method=self._sharePath)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
207 host.trigger.add("XEP-0234_fileSendingRequest", self._fileSendingRequestTrigger)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
208
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
209 def getHandler(self, client):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
210 return XEP_0329_handler(self)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
211
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
212 def profileConnected(self, client):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
213 if not client.is_component:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
214 client._XEP_0329_root_node = ShareNode(None, None, TYPE_VIRTUAL, {C.ACCESS_PERM_READ: {KEY_TYPE: C.ACCESS_TYPE_PUBLIC}})
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
215 client._XEP_0329_names_data = {} # name to share map
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
216
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
217 def _fileSendingRequestTrigger(self, client, session, content_data, content_name, file_data, file_elt):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
218 """this trigger check that a requested file is available, and fill suitable data if so
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
219
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
220 path and name are used to retrieve the file. If path is missing, we try our luck with known names
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
221 """
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
222 if client.is_component:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
223 return True, None
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
224
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
225 try:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
226 name = file_data[u'name']
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
227 except KeyError:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
228 return True, None
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
229 assert u'/' not in name
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
230
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
231 path = file_data.get(u'path')
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
232 if path is not None:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
233 # we have a path, we can follow it to find node
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
234 try:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
235 node, rem_path = ShareNode.find(client, path, session[u'peer_jid'])
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
236 except (exceptions.PermissionError, exceptions.NotFound):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
237 # no file, or file not allowed, we continue normal workflow
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
238 return True, None
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
239 except exceptions.DataError:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
240 log.warning(_(u'invalid path: {path}').format(path=path))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
241 return True, None
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
242
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
243 if node.type == TYPE_VIRTUAL:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
244 # we have a virtual node, so name must link to a path node
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
245 try:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
246 path = node[name].path
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
247 except KeyError:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
248 return True, None
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
249 elif node.type == TYPE_PATH:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
250 # we have a path node, so we can retrieve the full path now
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
251 path = os.path.join(node.path, rem_path, name)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
252 else:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
253 raise exceptions.InternalError(u'unknown type: {type}'.format(type=node.type))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
254 if not os.path.exists(path):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
255 return True, None
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
256 size = os.path.getsize(path)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
257 else:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
258 # we don't have the path, we try to find the file by its name
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
259 try:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
260 name_data = client._XEP_0329_names_data[name]
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
261 except KeyError:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
262 return True, None
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
263
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
264 for path, shared_file in name_data.iteritems():
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
265 if True: # FIXME: filters are here
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
266 break
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
267 else:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
268 return True, None
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
269 parent_node = shared_file[u'parent']
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
270 if not parent_node.checkPermissions(client, session[u'peer_jid']):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
271 log.warning(_(u"{peer_jid} requested a file (s)he can't access [{profile}]").format(
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
272 peer_jid = session[u'peer_jid'], profile = client.profile))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
273 return True, None
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
274 size = shared_file[u'size']
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
275
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
276 file_data[u'size'] = size
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
277 file_elt.addElement(u'size', content=unicode(size))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
278 hash_algo = file_data[u'hash_algo'] = self._h.getDefaultAlgo()
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
279 hasher = file_data[u'hash_hasher'] = self._h.getHasher(hash_algo)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
280 file_elt.addChild(self._h.buildHashUsedElt(hash_algo))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
281 content_data['stream_object'] = stream.FileStreamObject(
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
282 self.host,
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
283 client,
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
284 path,
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
285 uid=self._jf.getProgressId(session, content_name),
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
286 size=size,
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
287 data_cb=lambda data: hasher.update(data),
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
288 )
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
289 return False, True
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
290
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
291 # common methods
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
292
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
293 def _requestHandler(self, client, iq_elt, root_nodes_cb, files_from_node_cb):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
294 iq_elt.handled = True
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
295 owner = jid.JID(iq_elt['from']).userhostJID()
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
296 node = iq_elt.query.getAttribute('node')
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
297 if not node:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
298 d = defer.maybeDeferred(root_nodes_cb, client, iq_elt, owner)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
299 else:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
300 d = defer.maybeDeferred(files_from_node_cb, client, iq_elt, owner, node)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
301 d.addErrback(lambda failure_: log.error(_(u"error while retrieving files: {msg}").format(msg=failure_)))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
302
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
303 def _iqError(self, client, iq_elt, condition="item-not-found"):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
304 error_elt = jabber_error.StanzaError(condition).toResponse(iq_elt)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
305 client.send(error_elt)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
306
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
307 # client
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
308
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
309 def _addPathData(self, client, query_elt, path, parent_node):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
310 """Fill query_elt with files/directories found in path"""
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
311 name = os.path.basename(path)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
312 if os.path.isfile(path):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
313 size = os.path.getsize(path)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
314 media_type = mimetypes.guess_type(path, strict=False)[0]
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
315 file_elt = self._jf.buildFileElement(name = name,
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
316 size = size,
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
317 media_type = media_type,
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
318 date = os.path.getmtime(path))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
319
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
320 query_elt.addChild(file_elt)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
321 # we don't specify hash as it would be too resource intensive to calculate it for all files
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
322 # we add file to name_data, so users can request it later
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
323 name_data = client._XEP_0329_names_data.setdefault(name, {})
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
324 if path not in name_data:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
325 name_data[path] = {'size': size,
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
326 'media_type': media_type,
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
327 'parent': parent_node}
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
328 else:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
329 # we have a directory
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
330 directory_elt = query_elt.addElement('directory')
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
331 directory_elt['name'] = name
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
332
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
333 def _pathNodeHandler(self, client, iq_elt, query_elt, node, path):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
334 """Fill query_elt for path nodes, i.e. physical directories"""
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
335 path = os.path.join(node.path, path)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
336
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
337 if not os.path.exists(path):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
338 # path may have been moved since it has been shared
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
339 return self._iqError(client, iq_elt)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
340 elif os.path.isfile(path):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
341 self._addPathData(client, query_elt, path, node)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
342 else:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
343 for name in sorted(os.listdir(path.encode('utf-8')), key=lambda n: n.lower()):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
344 try:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
345 name = name.decode('utf-8', 'strict')
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
346 except UnicodeDecodeError as e:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
347 log.warning(_(u"ignoring invalid unicode name ({name}): {msg}").format(
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
348 name = name.decode('utf-8', 'replace'),
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
349 msg = e))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
350 continue
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
351 full_path = os.path.join(path, name)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
352 self._addPathData(client, query_elt, full_path, node)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
353
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
354 def _virtualNodeHandler(self, client, peer_jid, iq_elt, query_elt, node):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
355 """Fill query_elt for virtual nodes"""
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
356 for name, child_node in node.iteritems():
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
357 if not child_node.checkPermissions(client, peer_jid, check_parents=False):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
358 continue
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
359 node_type = child_node.type
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
360 if node_type == TYPE_VIRTUAL:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
361 directory_elt = query_elt.addElement('directory')
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
362 directory_elt['name'] = name
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
363 elif node_type == TYPE_PATH:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
364 self._addPathData(client, query_elt, child_node.path, child_node)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
365 else:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
366 raise exceptions.InternalError(_(u'unexpected type: {type}').format(type=node_type))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
367
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
368 def _getRootNodesCb(self, client, iq_elt, owner):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
369 peer_jid = jid.JID(iq_elt['from'])
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
370 iq_result_elt = xmlstream.toResponse(iq_elt, 'result')
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
371 query_elt = iq_result_elt.addElement((NS_FIS, 'query'))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
372 for name, node in client._XEP_0329_root_node.iteritems():
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
373 if not node.checkPermissions(client, peer_jid, check_parents=False):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
374 continue
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
375 directory_elt = query_elt.addElement('directory')
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
376 directory_elt['name'] = name
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
377 client.send(iq_result_elt)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
378
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
379 def _getFilesFromNodeCb(self, client, iq_elt, owner, node_path):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
380 """Main method to retrieve files/directories from a node_path"""
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
381 peer_jid = jid.JID(iq_elt[u'from'])
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
382 try:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
383 node, path = ShareNode.find(client, node_path, peer_jid)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
384 except (exceptions.PermissionError, exceptions.NotFound):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
385 return self._iqError(client, iq_elt)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
386 except exceptions.DataError:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
387 return self._iqError(client, iq_elt, condition='not-acceptable')
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
388
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
389 node_type = node.type
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
390 peer_jid = jid.JID(iq_elt['from'])
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
391 iq_result_elt = xmlstream.toResponse(iq_elt, 'result')
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
392 query_elt = iq_result_elt.addElement((NS_FIS, 'query'))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
393 query_elt[u'node'] = node_path
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
394
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
395 # we now fill query_elt according to node_type
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
396 if node_type == TYPE_PATH:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
397 # it's a physical path
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
398 self._pathNodeHandler(client, iq_elt, query_elt, node, path)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
399 elif node_type == TYPE_VIRTUAL:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
400 assert not path
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
401 self._virtualNodeHandler(client, peer_jid, iq_elt, query_elt, node)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
402 else:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
403 raise exceptions.InternalError(_(u'unknown node type: {type}').format(type=node_type))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
404
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
405 client.send(iq_result_elt)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
406
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
407 def onRequest(self, iq_elt, client):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
408 return self._requestHandler(client, iq_elt, self._getRootNodesCb, self._getFilesFromNodeCb)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
409
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
410 # Component
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
411
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
412 @defer.inlineCallbacks
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
413 def _compGetRootNodesCb(self, client, iq_elt, owner):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
414 peer_jid = jid.JID(iq_elt['from'])
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
415 files_data = yield self.host.memory.getFiles(client, peer_jid=peer_jid, parent=u'',
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
416 type_=C.FILE_TYPE_DIRECTORY, owner=owner)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
417 iq_result_elt = xmlstream.toResponse(iq_elt, 'result')
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
418 query_elt = iq_result_elt.addElement((NS_FIS, 'query'))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
419 for file_data in files_data:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
420 name = file_data[u'name']
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
421 directory_elt = query_elt.addElement(u'directory')
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
422 directory_elt[u'name'] = name
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
423 client.send(iq_result_elt)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
424
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
425 @defer.inlineCallbacks
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
426 def _compGetFilesFromNodeCb(self, client, iq_elt, owner, node_path):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
427 peer_jid = jid.JID(iq_elt['from'])
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
428 try:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
429 files_data = yield self.host.memory.getFiles(client, peer_jid=peer_jid, path=node_path, owner=owner)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
430 except exceptions.NotFound:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
431 self._iqError(client, iq_elt)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
432 return
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
433 iq_result_elt = xmlstream.toResponse(iq_elt, 'result')
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
434 query_elt = iq_result_elt.addElement((NS_FIS, 'query'))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
435 query_elt[u'node'] = node_path
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
436 for file_data in files_data:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
437 file_elt = self._jf.buildFileElementFromDict(file_data,
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
438 date=file_data.get(u'modified', file_data[u'created']))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
439 query_elt.addChild(file_elt)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
440 client.send(iq_result_elt)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
441
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
442 def onComponentRequest(self, iq_elt, client):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
443 return self._requestHandler(client, iq_elt, self._compGetRootNodesCb, self._compGetFilesFromNodeCb)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
444
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
445 def _parseResult(self, iq_elt):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
446 query_elt = next(iq_elt.elements(NS_FIS, 'query'))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
447 files = []
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
448
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
449 for elt in query_elt.elements():
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
450 if elt.name == 'file':
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
451 # we have a file
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
452 try:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
453 file_data = self._jf.parseFileElement(elt)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
454 except exceptions.DataError:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
455 continue
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
456 file_data[u'type'] = C.FILE_TYPE_FILE
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
457 elif elt.name == 'directory' and elt.uri == NS_FIS:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
458 # we have a directory
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
459
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
460 file_data = {'name': elt['name'], 'type': C.FILE_TYPE_DIRECTORY}
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
461 else:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
462 log.warning(_(u"unexpected element, ignoring: {elt}").format(elt=elt.toXml()))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
463 continue
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
464 files.append(file_data)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
465 return files
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
466
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
467 # file methods #
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
468
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
469 def _serializeData(self, files_data):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
470 for file_data in files_data:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
471 for key, value in file_data.iteritems():
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
472 file_data[key] = unicode(value)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
473 return files_data
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
474
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
475 def _listFiles(self, target_jid, path, extra, profile):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
476 client = self.host.getClient(profile)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
477 target_jid = client.jid.userhostJID() if not target_jid else jid.JID(target_jid)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
478 d = self.listFiles(client, target_jid, path or None)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
479 d.addCallback(self._serializeData)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
480 return d
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
481
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
482 def listFiles(self, client, target_jid, path=None, extra=None):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
483 """List file shared by an entity
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
484
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
485 @param target_jid(jid.JID): jid of the sharing entity
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
486 @param path(unicode, None): path to the directory containing shared files
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
487 None to get root directories
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
488 @param extra(dict, None): extra data
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
489 @return list(dict): shared files
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
490 """
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
491 iq_elt = client.IQ('get')
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
492 iq_elt['to'] = target_jid.full()
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
493 query_elt = iq_elt.addElement((NS_FIS, 'query'))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
494 if path:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
495 query_elt['node'] = path
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
496 d = iq_elt.send()
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
497 d.addCallback(self._parseResult)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
498 return d
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
499
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
500 def _sharePath(self, name, path, access, profile):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
501 client = self.host.getClient(profile)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
502 access= json.loads(access)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
503 return self.sharePath(client, name or None, path, access)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
504
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
505 def sharePath(self, client, name, path, access):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
506 if client.is_component:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
507 raise exceptions.ClientTypeError
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
508 if not os.path.exists(path):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
509 raise ValueError(_(u"This path doesn't exist!"))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
510 if not path or not path.strip(u' /'):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
511 raise ValueError(_(u"A path need to be specified"))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
512
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
513 node = client._XEP_0329_root_node
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
514 node_type = TYPE_PATH
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
515 if os.path.isfile(path):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
516 # we have a single file, the workflow is diferrent as we store all single files in the same dir
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
517 node = node.getOrCreate(SINGLE_FILES_DIR)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
518
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
519 if not name:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
520 name = os.path.basename(path.rstrip(u' /'))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
521 if not name:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
522 raise exceptions.InternalError(_(u"Can't find a proper name"))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
523
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
524 if not isinstance(access, dict):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
525 raise ValueError(_(u'access must be a dict'))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
526
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
527 if name in node or name == SINGLE_FILES_DIR:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
528 idx = 1
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
529 new_name = name + '_' + unicode(idx)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
530 while new_name in node:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
531 idx += 1
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
532 new_name = name + '_' + unicode(idx)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
533 name = new_name
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
534 log.info(_(u"A directory with this name is already shared, renamed to {new_name} [{profile}]".format(
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
535 new_name=new_name, profile=client.profile)))
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
536
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
537 ShareNode(name=name, parent=node, type_=node_type, access=access, path=path)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
538 return name
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
539
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
540
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
541 class XEP_0329_handler(xmlstream.XMPPHandler):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
542 implements(iwokkel.IDisco)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
543
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
544 def __init__(self, plugin_parent):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
545 self.plugin_parent = plugin_parent
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
546 self.host = plugin_parent.host
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
547
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
548 def connectionInitialized(self):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
549 if self.parent.is_component:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
550 self.xmlstream.addObserver(IQ_FIS_REQUEST, self.plugin_parent.onComponentRequest, client=self.parent)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
551 else:
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
552 self.xmlstream.addObserver(IQ_FIS_REQUEST, self.plugin_parent.onRequest, client=self.parent)
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
553
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
554 def getDiscoInfo(self, requestor, target, nodeIdentifier=''):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
555 return [disco.DiscoFeature(NS_FIS)]
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
556
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
557 def getDiscoItems(self, requestor, target, nodeIdentifier=''):
c0bec8bac2b5 XEP-0329: implementation of File Information Sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
558 return []