ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Plugin.php
Go to the documentation of this file.
1<?php
2
3namespace Sabre\DAV\Sharing;
4
15
27class Plugin extends ServerPlugin {
28
31 const ACCESS_READ = 2;
33 const ACCESS_NOACCESS = 4;
34
36 const INVITE_ACCEPTED = 2;
37 const INVITE_DECLINED = 3;
38 const INVITE_INVALID = 4;
39
45 protected $server;
46
55 function getFeatures() {
56
57 return ['resource-sharing'];
58
59 }
60
69 function getPluginName() {
70
71 return 'sharing';
72
73 }
74
87
88 $this->server = $server;
89
90 $server->xml->elementMap['{DAV:}share-resource'] = 'Sabre\\DAV\\Xml\\Request\\ShareResource';
91
92 array_push(
93 $server->protectedProperties,
94 '{DAV:}share-mode'
95 );
96
97 $server->on('method:POST', [$this, 'httpPost']);
98 $server->on('propFind', [$this, 'propFind']);
99 $server->on('getSupportedPrivilegeSet', [$this, 'getSupportedPrivilegeSet']);
100 $server->on('onHTMLActionsPanel', [$this, 'htmlActionsPanel']);
101 $server->on('onBrowserPostAction', [$this, 'browserPostAction']);
102
103 }
104
115 function shareResource($path, array $sharees) {
116
117 $node = $this->server->tree->getNodeForPath($path);
118
119 if (!$node instanceof ISharedNode) {
120
121 throw new Forbidden('Sharing is not allowed on this node');
122
123 }
124
125 // Getting ACL info
126 $acl = $this->server->getPlugin('acl');
127
128 // If there's no ACL support, we allow everything
129 if ($acl) {
130 $acl->checkPrivileges($path, '{DAV:}share');
131 }
132
133 foreach ($sharees as $sharee) {
134 // We're going to attempt to get a local principal uri for a share
135 // href by emitting the getPrincipalByUri event.
136 $principal = null;
137 $this->server->emit('getPrincipalByUri', [$sharee->href, &$principal]);
138 $sharee->principal = $principal;
139 }
140 $node->updateInvites($sharees);
141
142 }
143
153 function propFind(PropFind $propFind, INode $node) {
154
155 if ($node instanceof ISharedNode) {
156
157 $propFind->handle('{DAV:}share-access', function() use ($node) {
158
159 return new Property\ShareAccess($node->getShareAccess());
160
161 });
162 $propFind->handle('{DAV:}invite', function() use ($node) {
163
164 return new Property\Invite($node->getInvites());
165
166 });
167 $propFind->handle('{DAV:}share-resource-uri', function() use ($node) {
168
169 return new Property\Href($node->getShareResourceUri());
170
171 });
172
173 }
174
175 }
176
185
186 $path = $request->getPath();
187 $contentType = $request->getHeader('Content-Type');
188
189 // We're only interested in the davsharing content type.
190 if (strpos($contentType, 'application/davsharing+xml') === false) {
191 return;
192 }
193
194 $message = $this->server->xml->parse(
195 $request->getBody(),
196 $request->getUrl(),
197 $documentType
198 );
199
200 switch ($documentType) {
201
202 case '{DAV:}share-resource':
203
204 $this->shareResource($path, $message->sharees);
205 $response->setStatus(200);
206 // Adding this because sending a response body may cause issues,
207 // and I wanted some type of indicator the response was handled.
208 $response->setHeader('X-Sabre-Status', 'everything-went-well');
209
210 // Breaking the event chain
211 return false;
212
213 default :
214 throw new BadRequest('Unexpected document type: ' . $documentType . ' for this Content-Type');
215
216 }
217
218 }
219
229 function getSupportedPrivilegeSet(INode $node, array &$supportedPrivilegeSet) {
230
231 if ($node instanceof ISharedNode) {
232 $supportedPrivilegeSet['{DAV:}share'] = [
233 'abstract' => false,
234 'aggregates' => [],
235 ];
236 }
237 }
238
250 function getPluginInfo() {
251
252 return [
253 'name' => $this->getPluginName(),
254 'description' => 'This plugin implements WebDAV resource sharing',
255 'link' => 'https://github.com/evert/webdav-sharing'
256 ];
257
258 }
259
269 function htmlActionsPanel(INode $node, &$output, $path) {
270
271 if (!$node instanceof ISharedNode) {
272 return;
273 }
274
275 $aclPlugin = $this->server->getPlugin('acl');
276 if ($aclPlugin) {
277 if (!$aclPlugin->checkPrivileges($path, '{DAV:}share', \Sabre\DAVACL\Plugin::R_PARENT, false)) {
278 // Sharing is not permitted, we will not draw this interface.
279 return;
280 }
281 }
282
283 $output .= '<tr><td colspan="2"><form method="post" action="">
284 <h3>Share this resource</h3>
285 <input type="hidden" name="sabreAction" value="share" />
286 <label>Share with (uri):</label> <input type="text" name="href" placeholder="mailto:user@example.org"/><br />
287 <label>Access</label>
288 <select name="access">
289 <option value="readwrite">Read-write</option>
290 <option value="read">Read-only</option>
291 <option value="no-access">Revoke access</option>
292 </select><br />
293 <input type="submit" value="share" />
294 </form>
295 </td></tr>';
296
297 }
298
307 function browserPostAction($path, $action, $postVars) {
308
309 if ($action !== 'share') {
310 return;
311 }
312
313 if (empty($postVars['href'])) {
314 throw new BadRequest('The "href" POST parameter is required');
315 }
316 if (empty($postVars['access'])) {
317 throw new BadRequest('The "access" POST parameter is required');
318 }
319
320 $accessMap = [
321 'readwrite' => self::ACCESS_READWRITE,
322 'read' => self::ACCESS_READ,
323 'no-access' => self::ACCESS_NOACCESS,
324 ];
325
326 if (!isset($accessMap[$postVars['access']])) {
327 throw new BadRequest('The "access" POST must be readwrite, read or no-access');
328 }
329 $sharee = new Sharee([
330 'href' => $postVars['href'],
331 'access' => $accessMap[$postVars['access']],
332 ]);
333
334 $this->shareResource(
335 $path,
336 [$sharee]
337 );
338 return false;
339
340 }
341
342}
$path
Definition: aliased.php:25
foreach($paths as $path) $request
Definition: asyncclient.php:32
$aclPlugin
An exception for terminatinating execution or to throw for unit testing.
This class holds all the information about a PROPFIND request.
Definition: PropFind.php:11
handle($propertyName, $valueOrCallBack)
Handles a specific property.
Definition: PropFind.php:94
The baseclass for all server plugins.
Main DAV server class.
Definition: Server.php:23
This plugin implements HTTP requests and properties related to:
Definition: Plugin.php:27
browserPostAction($path, $action, $postVars)
This method is triggered for POST actions generated by the browser plugin.
Definition: Plugin.php:307
getPluginInfo()
Returns a bunch of meta-data about the plugin.
Definition: Plugin.php:250
getPluginName()
Returns a plugin name.
Definition: Plugin.php:69
htmlActionsPanel(INode $node, &$output, $path)
This method is used to generate HTML output for the DAV\Browser\Plugin.
Definition: Plugin.php:269
httpPost(RequestInterface $request, ResponseInterface $response)
We intercept this to handle POST requests on shared resources.
Definition: Plugin.php:184
propFind(PropFind $propFind, INode $node)
This event is triggered when properties are requested for nodes.
Definition: Plugin.php:153
getSupportedPrivilegeSet(INode $node, array &$supportedPrivilegeSet)
This method is triggered whenever a subsystem reqeuests the privileges hat are supported on a particu...
Definition: Plugin.php:229
getFeatures()
This method should return a list of server-features.
Definition: Plugin.php:55
initialize(Server $server)
This initializes the plugin.
Definition: Plugin.php:86
shareResource($path, array $sharees)
Updates the list of sharees on a shared resource.
Definition: Plugin.php:115
This class represents the {DAV:}sharee element.
Definition: Sharee.php:21
$action
The INode interface is the base interface, and the parent class of both ICollection and IFile.
Definition: INode.php:12
This interface represents a resource that has sharing capabilities, either because it's possible for ...
Definition: ISharedNode.php:16
The RequestInterface represents a HTTP request.
This interface represents a HTTP response.
setStatus($status)
Sets the HTTP status code.
catch(Exception $e) $message
if( $path[strlen( $path) - 1]==='/') if(is_dir($path)) if(!file_exists( $path)) if(preg_match('#\.php$#D', mb_strtolower($path, 'UTF-8'))) $contentType
Definition: module.php:144
$response