ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Plugin.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Sabre\DAV\Sharing;
4 
15 
27 class Plugin extends ServerPlugin {
28 
29  const ACCESS_NOTSHARED = 0;
30  const ACCESS_SHAREDOWNER = 1;
31  const ACCESS_READ = 2;
32  const ACCESS_READWRITE = 3;
33  const ACCESS_NOACCESS = 4;
34 
35  const INVITE_NORESPONSE = 1;
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 }
This interface represents a HTTP response.
The RequestInterface represents a HTTP request.
handle($propertyName, $valueOrCallBack)
Handles a specific property.
Definition: PropFind.php:94
$path
Definition: aliased.php:25
This class represents the {DAV:}sharee element.
Definition: Sharee.php:21
The baseclass for all server plugins.
on($eventName, callable $callBack, $priority=100)
Subscribe to an event.
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
$action
foreach($paths as $path) $request
Definition: asyncclient.php:32
httpPost(RequestInterface $request, ResponseInterface $response)
We intercept this to handle POST requests on shared resources.
Definition: Plugin.php:184
This class holds all the information about a PROPFIND request.
Definition: PropFind.php:11
browserPostAction($path, $action, $postVars)
This method is triggered for POST actions generated by the browser plugin.
Definition: Plugin.php:307
getPluginName()
Returns a plugin name.
Definition: Plugin.php:69
catch(Exception $e) $message
This plugin implements HTTP requests and properties related to:
Definition: Plugin.php:27
setStatus($status)
Sets the HTTP status code.
getFeatures()
This method should return a list of server-features.
Definition: Plugin.php:55
getUrl()
Returns the request url.
This interface represents a resource that has sharing capabilities, either because it&#39;s possible for ...
Definition: ISharedNode.php:16
htmlActionsPanel(INode $node, &$output, $path)
This method is used to generate HTML output for the DAV.
Definition: Plugin.php:269
Main DAV server class.
Definition: Server.php:23
getHeader($name)
Returns a specific HTTP header, based on it&#39;s name.
getPluginInfo()
Returns a bunch of meta-data about the plugin.
Definition: Plugin.php:250
initialize(Server $server)
This initializes the plugin.
Definition: Plugin.php:86
The INode interface is the base interface, and the parent class of both ICollection and IFile...
Definition: INode.php:12
getPath()
Returns the relative path.
propFind(PropFind $propFind, INode $node)
This event is triggered when properties are requested for nodes.
Definition: Plugin.php:153
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
shareResource($path, array $sharees)
Updates the list of sharees on a shared resource.
Definition: Plugin.php:115
setHeader($name, $value)
Updates a HTTP header.
getBody()
Returns the message body, as it&#39;s internal representation.
$aclPlugin