ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Sabre\DAVACL\Plugin Class Reference

SabreDAV ACL Plugin. More...

+ Inheritance diagram for Sabre\DAVACL\Plugin:
+ Collaboration diagram for Sabre\DAVACL\Plugin:

Public Member Functions

 getFeatures ()
 Returns a list of features added by this plugin. More...
 
 getMethods ($uri)
 Returns a list of available methods for a given url. More...
 
 getPluginName ()
 Returns a plugin name. More...
 
 getSupportedReportSet ($uri)
 Returns a list of reports this plugin supports. More...
 
 checkPrivileges ($uri, $privileges, $recursion=self::R_PARENT, $throwExceptions=true)
 Checks if the current user has the specified privilege(s). More...
 
 getCurrentUserPrincipals ()
 Returns a list of principals that's associated to the current user, either directly or through group membership. More...
 
 setDefaultAcl (array $acl)
 Sets the default ACL rules. More...
 
 getDefaultAcl ()
 Returns the default ACL rules. More...
 
 getPrincipalMembership ($mainPrincipal)
 Returns all the principal groups the specified principal is a member of. More...
 
 principalMatchesPrincipal ($checkPrincipal, $currentPrincipal=null)
 Find out of a principal equals another principal. More...
 
 getSupportedPrivilegeSet ($node)
 Returns a tree of supported privileges for a resource. More...
 
 getFlatPrivilegeSet ($node)
 Returns the supported privilege set as a flat list. More...
 
 getAcl ($node)
 Returns the full ACL list. More...
 
 getCurrentUserPrivilegeSet ($node)
 Returns a list of privileges the current user has on a particular node. More...
 
 getPrincipalByUri ($uri)
 Returns a principal based on its uri. More...
 
 principalSearch (array $searchProperties, array $requestedProperties, $collectionUri=null, $test='allof')
 Principal property search. More...
 
 initialize (DAV\Server $server)
 Sets up the plugin. More...
 
 beforeMethod (RequestInterface $request, ResponseInterface $response)
 Triggered before any method is handled. More...
 
 beforeBind ($uri)
 Triggered before a new node is created. More...
 
 beforeUnbind ($uri)
 Triggered before a node is deleted. More...
 
 beforeUnlock ($uri, DAV\Locks\LockInfo $lock)
 Triggered before a node is unlocked. More...
 
 propFind (DAV\PropFind $propFind, DAV\INode $node)
 Triggered before properties are looked up in specific nodes. More...
 
 propPatch ($path, DAV\PropPatch $propPatch)
 This method intercepts PROPPATCH methods and make sure the group-member-set is updated correctly. More...
 
 report ($reportName, $report, $path)
 This method handles HTTP REPORT requests. More...
 
 httpAcl (RequestInterface $request, ResponseInterface $response)
 This method is responsible for handling the 'ACL' event. More...
 
 htmlActionsPanel (DAV\INode $node, &$output)
 This method is used to generate HTML output for the DAV. More...
 
 getPluginInfo ()
 Returns a bunch of meta-data about the plugin. More...
 
- Public Member Functions inherited from Sabre\DAV\ServerPlugin
 initialize (Server $server)
 This initializes the plugin. More...
 
 getFeatures ()
 This method should return a list of server-features. More...
 
 getHTTPMethods ($path)
 Use this method to tell the server this plugin defines additional HTTP methods. More...
 
 getPluginName ()
 Returns a plugin name. More...
 
 getSupportedReportSet ($uri)
 Returns a list of reports this plugin supports. More...
 
 getPluginInfo ()
 Returns a bunch of meta-data about the plugin. More...
 

Data Fields

const R_PARENT = 1
 Recursion constants. More...
 
const R_RECURSIVE = 2
 Recursion constants. More...
 
const R_RECURSIVEPARENTS = 3
 Recursion constants. More...
 
 $principalCollectionSet
 
 $hideNodesFromListings = false
 
 $principalSearchPropertySet
 
 $adminPrincipals = []
 
 $allowUnauthenticatedAccess = true
 

Protected Member Functions

 principalMatchReport ($path, Xml\Request\PrincipalMatchReport $report)
 The principal-match report is defined in RFC3744, section 9.3. More...
 
 expandPropertyReport ($path, $report)
 The expand-property report is defined in RFC3253 section 3.8. More...
 
 expandProperties ($path, array $requestedProperties, $depth)
 This method expands all the properties and returns a list with property values. More...
 
 principalSearchPropertySetReport ($path, $report)
 principalSearchPropertySetReport More...
 
 principalPropertySearchReport ($path, Xml\Request\PrincipalPropertySearchReport $report)
 principalPropertySearchReport More...
 
 aclPrincipalPropSetReport ($path, Xml\Request\AclPrincipalPropSetReport $report)
 aclPrincipalPropSet REPORT More...
 

Protected Attributes

 $server
 
 $defaultAcl
 
 $principalMembershipCache = []
 

Detailed Description

SabreDAV ACL Plugin.

This plugin provides functionality to enforce ACL permissions. ACL is defined in RFC3744.

In addition it also provides support for the {DAV:}current-user-principal property, defined in RFC5397 and the {DAV:}expand-property report, as defined in RFC3253.

Author
Evert Pot (http://evertpot.com/) http://sabre.io/license/ Modified BSD License

Definition at line 31 of file Plugin.php.

Member Function Documentation

◆ aclPrincipalPropSetReport()

Sabre\DAVACL\Plugin::aclPrincipalPropSetReport (   $path,
Xml\Request\AclPrincipalPropSetReport  $report 
)
protected

aclPrincipalPropSet REPORT

This method is responsible for handling the {DAV:}acl-principal-prop-set REPORT, as defined in:

https://tools.ietf.org/html/rfc3744#section-9.2

This REPORT allows a user to quickly fetch information about all principals specified in the access control list. Most commonly this is used to for example generate a UI with ACL rules, allowing you to show names for principals for every entry.

Parameters
string$path
Xml\Request\AclPrincipalPropSetReport$report
Returns
void

Definition at line 1544 of file Plugin.php.

References $path.

Referenced by Sabre\DAVACL\Plugin\report().

1544  {
1545 
1546  if ($this->server->getHTTPDepth(0) !== 0) {
1547  throw new BadRequest('The {DAV:}acl-principal-prop-set REPORT only supports Depth 0');
1548  }
1549 
1550  // Fetching ACL rules for the given path. We're using the property
1551  // API and not the local getACL, because it will ensure that all
1552  // business rules and restrictions are applied.
1553  $acl = $this->server->getProperties($path, '{DAV:}acl');
1554 
1555  if (!$acl || !isset($acl['{DAV:}acl'])) {
1556  throw new Forbidden('Could not fetch ACL rules for this path');
1557  }
1558 
1559  $principals = [];
1560  foreach ($acl['{DAV:}acl']->getPrivileges() as $ace) {
1561 
1562  if ($ace['principal'][0] === '{') {
1563  // It's not a principal, it's one of the special rules such as {DAV:}authenticated
1564  continue;
1565  }
1566 
1567  $principals[] = $ace['principal'];
1568 
1569  }
1570 
1571  $properties = $this->server->getPropertiesForMultiplePaths(
1572  $principals,
1573  $report->properties
1574  );
1575 
1576  $this->server->httpResponse->setStatus(207);
1577  $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
1578  $this->server->httpResponse->setBody(
1579  $this->server->generateMultiStatus($properties)
1580  );
1581 
1582  }
$path
Definition: aliased.php:25
+ Here is the caller graph for this function:

◆ beforeBind()

Sabre\DAVACL\Plugin::beforeBind (   $uri)

Triggered before a new node is created.

This allows us to check permissions for any operation that creates a new node, such as PUT, MKCOL, MKCALENDAR, LOCK, COPY and MOVE.

Parameters
string$uri
Returns
void

Definition at line 942 of file Plugin.php.

References Sabre\DAVACL\Plugin\checkPrivileges(), and Sabre\Uri\split().

942  {
943 
944  list($parentUri) = Uri\split($uri);
945  $this->checkPrivileges($parentUri, '{DAV:}bind');
946 
947  }
split($path)
Returns the 'dirname' and 'basename' for a path.
Definition: functions.php:279
checkPrivileges($uri, $privileges, $recursion=self::R_PARENT, $throwExceptions=true)
Checks if the current user has the specified privilege(s).
Definition: Plugin.php:192
+ Here is the call graph for this function:

◆ beforeMethod()

Sabre\DAVACL\Plugin::beforeMethod ( RequestInterface  $request,
ResponseInterface  $response 
)

Triggered before any method is handled.

Parameters
RequestInterface$request
ResponseInterface$response
Returns
void

Definition at line 873 of file Plugin.php.

References $path, Sabre\DAVACL\Plugin\checkPrivileges(), Sabre\HTTP\RequestInterface\getMethod(), and Sabre\HTTP\RequestInterface\getPath().

873  {
874 
875  $method = $request->getMethod();
876  $path = $request->getPath();
877 
878  $exists = $this->server->tree->nodeExists($path);
879 
880  // If the node doesn't exists, none of these checks apply
881  if (!$exists) return;
882 
883  switch ($method) {
884 
885  case 'GET' :
886  case 'HEAD' :
887  case 'OPTIONS' :
888  // For these 3 we only need to know if the node is readable.
889  $this->checkPrivileges($path, '{DAV:}read');
890  break;
891 
892  case 'PUT' :
893  case 'LOCK' :
894  // This method requires the write-content priv if the node
895  // already exists, and bind on the parent if the node is being
896  // created.
897  // The bind privilege is handled in the beforeBind event.
898  $this->checkPrivileges($path, '{DAV:}write-content');
899  break;
900 
901  case 'UNLOCK' :
902  // Unlock is always allowed at the moment.
903  break;
904 
905  case 'PROPPATCH' :
906  $this->checkPrivileges($path, '{DAV:}write-properties');
907  break;
908 
909  case 'ACL' :
910  $this->checkPrivileges($path, '{DAV:}write-acl');
911  break;
912 
913  case 'COPY' :
914  case 'MOVE' :
915  // Copy requires read privileges on the entire source tree.
916  // If the target exists write-content normally needs to be
917  // checked, however, we're deleting the node beforehand and
918  // creating a new one after, so this is handled by the
919  // beforeUnbind event.
920  //
921  // The creation of the new node is handled by the beforeBind
922  // event.
923  //
924  // If MOVE is used beforeUnbind will also be used to check if
925  // the sourcenode can be deleted.
926  $this->checkPrivileges($path, '{DAV:}read', self::R_RECURSIVE);
927  break;
928 
929  }
930 
931  }
$path
Definition: aliased.php:25
foreach($paths as $path) $request
Definition: asyncclient.php:32
checkPrivileges($uri, $privileges, $recursion=self::R_PARENT, $throwExceptions=true)
Checks if the current user has the specified privilege(s).
Definition: Plugin.php:192
+ Here is the call graph for this function:

◆ beforeUnbind()

Sabre\DAVACL\Plugin::beforeUnbind (   $uri)

Triggered before a node is deleted.

This allows us to check permissions for any operation that will delete an existing node.

Parameters
string$uri
Returns
void

Definition at line 958 of file Plugin.php.

References Sabre\DAVACL\Plugin\checkPrivileges(), and Sabre\Uri\split().

958  {
959 
960  list($parentUri) = Uri\split($uri);
961  $this->checkPrivileges($parentUri, '{DAV:}unbind', self::R_RECURSIVEPARENTS);
962 
963  }
split($path)
Returns the 'dirname' and 'basename' for a path.
Definition: functions.php:279
checkPrivileges($uri, $privileges, $recursion=self::R_PARENT, $throwExceptions=true)
Checks if the current user has the specified privilege(s).
Definition: Plugin.php:192
+ Here is the call graph for this function:

◆ beforeUnlock()

Sabre\DAVACL\Plugin::beforeUnlock (   $uri,
DAV\Locks\LockInfo  $lock 
)

Triggered before a node is unlocked.

Parameters
string$uri
DAV\Locks\LockInfo$lock: not yet implemented
Returns
void

Definition at line 973 of file Plugin.php.

973  {
974 
975 
976  }

◆ checkPrivileges()

Sabre\DAVACL\Plugin::checkPrivileges (   $uri,
  $privileges,
  $recursion = self::R_PARENT,
  $throwExceptions = true 
)

Checks if the current user has the specified privilege(s).

You can specify a single privilege, or a list of privileges. This method will throw an exception if the privilege is not available and return true otherwise.

Parameters
string$uri
array | string$privileges
int$recursion
bool$throwExceptionsif set to false, this method won't throw exceptions.
Exceptions
NeedPrivileges
NotAuthenticated
Returns
bool

Definition at line 192 of file Plugin.php.

References $authPlugin, $failed, and Sabre\DAVACL\Plugin\getCurrentUserPrivilegeSet().

Referenced by Sabre\DAVACL\Plugin\beforeBind(), Sabre\DAVACL\Plugin\beforeMethod(), Sabre\DAVACL\Plugin\beforeUnbind(), and Sabre\DAVACL\Plugin\propFind().

192  {
193 
194  if (!is_array($privileges)) $privileges = [$privileges];
195 
196  $acl = $this->getCurrentUserPrivilegeSet($uri);
197 
198  $failed = [];
199  foreach ($privileges as $priv) {
200 
201  if (!in_array($priv, $acl)) {
202  $failed[] = $priv;
203  }
204 
205  }
206 
207  if ($failed) {
208  if ($this->allowUnauthenticatedAccess && is_null($this->getCurrentUserPrincipal())) {
209  // We are not authenticated. Kicking in the Auth plugin.
210  $authPlugin = $this->server->getPlugin('auth');
211  $reasons = $authPlugin->getLoginFailedReasons();
212  $authPlugin->challenge(
213  $this->server->httpRequest,
214  $this->server->httpResponse
215  );
216  throw new notAuthenticated(implode(', ', $reasons) . '. Login was needed for privilege: ' . implode(', ', $failed) . ' on ' . $uri);
217  }
218  if ($throwExceptions) {
219 
220  throw new NeedPrivileges($uri, $failed);
221  } else {
222  return false;
223  }
224  }
225  return true;
226 
227  }
$failed
Definition: Utf8Test.php:85
$authPlugin
getCurrentUserPrivilegeSet($node)
Returns a list of privileges the current user has on a particular node.
Definition: Plugin.php:618
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ expandProperties()

Sabre\DAVACL\Plugin::expandProperties (   $path,
array  $requestedProperties,
  $depth 
)
protected

This method expands all the properties and returns a list with property values.

Parameters
array$path
array$requestedPropertiesthe list of required properties
int$depth
Returns
array

Definition at line 1392 of file Plugin.php.

References $path, and $result.

Referenced by Sabre\DAVACL\Plugin\expandPropertyReport().

1392  {
1393 
1394  $foundProperties = $this->server->getPropertiesForPath($path, array_keys($requestedProperties), $depth);
1395 
1396  $result = [];
1397 
1398  foreach ($foundProperties as $node) {
1399 
1400  foreach ($requestedProperties as $propertyName => $childRequestedProperties) {
1401 
1402  // We're only traversing if sub-properties were requested
1403  if (count($childRequestedProperties) === 0) continue;
1404 
1405  // We only have to do the expansion if the property was found
1406  // and it contains an href element.
1407  if (!array_key_exists($propertyName, $node[200])) continue;
1408 
1409  if (!$node[200][$propertyName] instanceof DAV\Xml\Property\Href) {
1410  continue;
1411  }
1412 
1413  $childHrefs = $node[200][$propertyName]->getHrefs();
1414  $childProps = [];
1415 
1416  foreach ($childHrefs as $href) {
1417  // Gathering the result of the children
1418  $childProps[] = [
1419  'name' => '{DAV:}response',
1420  'value' => $this->expandProperties($href, $childRequestedProperties, 0)[0]
1421  ];
1422  }
1423 
1424  // Replacing the property with its expanded form.
1425  $node[200][$propertyName] = $childProps;
1426 
1427  }
1428  $result[] = new DAV\Xml\Element\Response($node['href'], $node);
1429 
1430  }
1431 
1432  return $result;
1433 
1434  }
$path
Definition: aliased.php:25
$result
expandProperties($path, array $requestedProperties, $depth)
This method expands all the properties and returns a list with property values.
Definition: Plugin.php:1392
+ Here is the caller graph for this function:

◆ expandPropertyReport()

Sabre\DAVACL\Plugin::expandPropertyReport (   $path,
  $report 
)
protected

The expand-property report is defined in RFC3253 section 3.8.

This report is very similar to a standard PROPFIND. The difference is that it has the additional ability to look at properties containing a {DAV:}href element, follow that property and grab additional elements there.

Other rfc's, such as ACL rely on this report, so it made sense to put it in this plugin.

Parameters
string$path
Xml\Request\ExpandPropertyReport$report
Returns
void

Definition at line 1366 of file Plugin.php.

References $path, $result, $xml, and Sabre\DAVACL\Plugin\expandProperties().

Referenced by Sabre\DAVACL\Plugin\report().

1366  {
1367 
1368  $depth = $this->server->getHTTPDepth(0);
1369 
1370  $result = $this->expandProperties($path, $report->properties, $depth);
1371 
1372  $xml = $this->server->xml->write(
1373  '{DAV:}multistatus',
1374  new DAV\Xml\Response\MultiStatus($result),
1375  $this->server->getBaseUri()
1376  );
1377  $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
1378  $this->server->httpResponse->setStatus(207);
1379  $this->server->httpResponse->setBody($xml);
1380 
1381  }
$path
Definition: aliased.php:25
$result
expandProperties($path, array $requestedProperties, $depth)
This method expands all the properties and returns a list with property values.
Definition: Plugin.php:1392
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getAcl()

Sabre\DAVACL\Plugin::getAcl (   $node)

Returns the full ACL list.

Either a uri or a INode may be passed.

null will be returned if the node doesn't support ACLs.

Parameters
string | DAV\INode$node
Returns
array

Definition at line 587 of file Plugin.php.

References Sabre\DAVACL\Plugin\getDefaultAcl().

587  {
588 
589  if (is_string($node)) {
590  $node = $this->server->tree->getNodeForPath($node);
591  }
592  if (!$node instanceof IACL) {
593  return $this->getDefaultAcl();
594  }
595  $acl = $node->getACL();
596  foreach ($this->adminPrincipals as $adminPrincipal) {
597  $acl[] = [
598  'principal' => $adminPrincipal,
599  'privilege' => '{DAV:}all',
600  'protected' => true,
601  ];
602  }
603  return $acl;
604 
605  }
getDefaultAcl()
Returns the default ACL rules.
Definition: Plugin.php:289
+ Here is the call graph for this function:

◆ getCurrentUserPrincipals()

Sabre\DAVACL\Plugin::getCurrentUserPrincipals ( )

Returns a list of principals that's associated to the current user, either directly or through group membership.

Returns
array

Definition at line 255 of file Plugin.php.

References Sabre\DAVACL\Plugin\getPrincipalMembership().

Referenced by Sabre\DAVACL\Plugin\principalMatchReport().

255  {
256 
257  $currentUser = $this->getCurrentUserPrincipal();
258 
259  if (is_null($currentUser)) return [];
260 
261  return array_merge(
262  [$currentUser],
263  $this->getPrincipalMembership($currentUser)
264  );
265 
266  }
getPrincipalMembership($mainPrincipal)
Returns all the principal groups the specified principal is a member of.
Definition: Plugin.php:327
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getCurrentUserPrivilegeSet()

Sabre\DAVACL\Plugin::getCurrentUserPrivilegeSet (   $node)

Returns a list of privileges the current user has on a particular node.

Either a uri or a DAV may be passed.

null will be returned if the node doesn't support ACLs.

Parameters
string | DAV\INode$node
Returns
array

Definition at line 618 of file Plugin.php.

References $current, Sabre\DAVACL\Plugin\getFlatPrivilegeSet(), and Sabre\DAVACL\Plugin\principalMatchesPrincipal().

Referenced by Sabre\DAVACL\Plugin\checkPrivileges(), and Sabre\DAVACL\Plugin\propFind().

618  {
619 
620  if (is_string($node)) {
621  $node = $this->server->tree->getNodeForPath($node);
622  }
623 
624  $acl = $this->getACL($node);
625 
626  $collected = [];
627 
628  $isAuthenticated = $this->getCurrentUserPrincipal() !== null;
629 
630  foreach ($acl as $ace) {
631 
632  $principal = $ace['principal'];
633 
634  switch ($principal) {
635 
636  case '{DAV:}owner' :
637  $owner = $node->getOwner();
638  if ($owner && $this->principalMatchesPrincipal($owner)) {
639  $collected[] = $ace;
640  }
641  break;
642 
643 
644  // 'all' matches for every user
645  case '{DAV:}all' :
646  $collected[] = $ace;
647  break;
648 
649  case '{DAV:}authenticated' :
650  // Authenticated users only
651  if ($isAuthenticated) {
652  $collected[] = $ace;
653  }
654  break;
655 
656  case '{DAV:}unauthenticated' :
657  // Unauthenticated users only
658  if (!$isAuthenticated) {
659  $collected[] = $ace;
660  }
661  break;
662 
663  default :
664  if ($this->principalMatchesPrincipal($ace['principal'])) {
665  $collected[] = $ace;
666  }
667  break;
668 
669  }
670 
671 
672  }
673 
674  // Now we deduct all aggregated privileges.
675  $flat = $this->getFlatPrivilegeSet($node);
676 
677  $collected2 = [];
678  while (count($collected)) {
679 
680  $current = array_pop($collected);
681  $collected2[] = $current['privilege'];
682 
683  if (!isset($flat[$current['privilege']])) {
684  // Ignoring privileges that are not in the supported-privileges list.
685  $this->server->getLogger()->debug('A node has the "' . $current['privilege'] . '" in its ACL list, but this privilege was not reported in the supportedPrivilegeSet list. This will be ignored.');
686  continue;
687  }
688  foreach ($flat[$current['privilege']]['aggregates'] as $subPriv) {
689  $collected2[] = $subPriv;
690  $collected[] = $flat[$subPriv];
691  }
692 
693  }
694 
695  return array_values(array_unique($collected2));
696 
697  }
principalMatchesPrincipal($checkPrincipal, $currentPrincipal=null)
Find out of a principal equals another principal.
Definition: Plugin.php:386
getFlatPrivilegeSet($node)
Returns the supported privilege set as a flat list.
Definition: Plugin.php:529
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getDefaultAcl()

Sabre\DAVACL\Plugin::getDefaultAcl ( )

Returns the default ACL rules.

These rules are used for all nodes that don't implement the IACL interface.

Returns
array

Definition at line 289 of file Plugin.php.

References Sabre\DAVACL\Plugin\$defaultAcl.

Referenced by Sabre\DAVACL\Plugin\getAcl().

289  {
290 
291  return $this->defaultAcl;
292 
293  }
+ Here is the caller graph for this function:

◆ getFeatures()

Sabre\DAVACL\Plugin::getFeatures ( )

Returns a list of features added by this plugin.

This list is used in the response of a HTTP OPTIONS request.

Returns
array

Definition at line 123 of file Plugin.php.

123  {
124 
125  return ['access-control', 'calendarserver-principal-property-search'];
126 
127  }

◆ getFlatPrivilegeSet()

Sabre\DAVACL\Plugin::getFlatPrivilegeSet (   $node)
final

Returns the supported privilege set as a flat list.

This is much easier to parse.

The returned list will be index by privilege name. The value is a struct containing the following properties:

  • aggregates
  • abstract
  • concrete
Parameters
string | INode$node
Returns
array

Definition at line 529 of file Plugin.php.

References Sabre\DAVACL\Plugin\getSupportedPrivilegeSet().

Referenced by Sabre\DAVACL\Plugin\getCurrentUserPrivilegeSet(), and Sabre\DAVACL\Plugin\httpAcl().

529  {
530 
531  $privs = [
532  'abstract' => false,
533  'aggregates' => $this->getSupportedPrivilegeSet($node)
534  ];
535 
536  $fpsTraverse = null;
537  $fpsTraverse = function($privName, $privInfo, $concrete, &$flat) use (&$fpsTraverse) {
538 
539  $myPriv = [
540  'privilege' => $privName,
541  'abstract' => isset($privInfo['abstract']) && $privInfo['abstract'],
542  'aggregates' => [],
543  'concrete' => isset($privInfo['abstract']) && $privInfo['abstract'] ? $concrete : $privName,
544  ];
545 
546  if (isset($privInfo['aggregates'])) {
547 
548  foreach ($privInfo['aggregates'] as $subPrivName => $subPrivInfo) {
549 
550  $myPriv['aggregates'][] = $subPrivName;
551 
552  }
553 
554  }
555 
556  $flat[$privName] = $myPriv;
557 
558  if (isset($privInfo['aggregates'])) {
559 
560  foreach ($privInfo['aggregates'] as $subPrivName => $subPrivInfo) {
561 
562  $fpsTraverse($subPrivName, $subPrivInfo, $myPriv['concrete'], $flat);
563 
564  }
565 
566  }
567 
568  };
569 
570  $flat = [];
571  $fpsTraverse('{DAV:}all', $privs, null, $flat);
572 
573  return $flat;
574 
575  }
getSupportedPrivilegeSet($node)
Returns a tree of supported privileges for a resource.
Definition: Plugin.php:441
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getMethods()

Sabre\DAVACL\Plugin::getMethods (   $uri)

Returns a list of available methods for a given url.

Parameters
string$uri
Returns
array

Definition at line 135 of file Plugin.php.

135  {
136 
137  return ['ACL'];
138 
139  }

◆ getPluginInfo()

Sabre\DAVACL\Plugin::getPluginInfo ( )

Returns a bunch of meta-data about the plugin.

Providing this information is optional, and is mainly displayed by the Browser plugin.

The description key in the returned array may contain html and will not be sanitized.

Returns
array

Definition at line 1627 of file Plugin.php.

References Sabre\DAVACL\Plugin\getPluginName().

1627  {
1628 
1629  return [
1630  'name' => $this->getPluginName(),
1631  'description' => 'Adds support for WebDAV ACL (rfc3744)',
1632  'link' => 'http://sabre.io/dav/acl/',
1633  ];
1634 
1635  }
getPluginName()
Returns a plugin name.
Definition: Plugin.php:149
+ Here is the call graph for this function:

◆ getPluginName()

Sabre\DAVACL\Plugin::getPluginName ( )

Returns a plugin name.

Using this name other plugins will be able to access other plugins using Sabre::getPlugin

Returns
string

Definition at line 149 of file Plugin.php.

Referenced by Sabre\DAVACL\Plugin\getPluginInfo().

149  {
150 
151  return 'acl';
152 
153  }
+ Here is the caller graph for this function:

◆ getPrincipalByUri()

Sabre\DAVACL\Plugin::getPrincipalByUri (   $uri)

Returns a principal based on its uri.

Returns null if the principal could not be found.

Parameters
string$uri
Returns
null|string

Definition at line 708 of file Plugin.php.

References Sabre\DAVACL\Plugin\$principalCollectionSet, and $result.

Referenced by Sabre\DAVACL\Plugin\initialize().

708  {
709 
710  $result = null;
711  $collections = $this->principalCollectionSet;
712  foreach ($collections as $collection) {
713 
714  try {
715  $principalCollection = $this->server->tree->getNodeForPath($collection);
716  } catch (NotFound $e) {
717  // Ignore and move on
718  continue;
719  }
720 
721  if (!$principalCollection instanceof IPrincipalCollection) {
722  // Not a principal collection, we're simply going to ignore
723  // this.
724  continue;
725  }
726 
727  $result = $principalCollection->findByUri($uri);
728  if ($result) {
729  return $result;
730  }
731 
732  }
733 
734  }
$result
+ Here is the caller graph for this function:

◆ getPrincipalMembership()

Sabre\DAVACL\Plugin::getPrincipalMembership (   $mainPrincipal)

Returns all the principal groups the specified principal is a member of.

Parameters
string$mainPrincipal
Returns
array

Definition at line 327 of file Plugin.php.

Referenced by Sabre\DAVACL\Plugin\getCurrentUserPrincipals(), and Sabre\DAVACL\Plugin\principalMatchesPrincipal().

327  {
328 
329  // First check our cache
330  if (isset($this->principalMembershipCache[$mainPrincipal])) {
331  return $this->principalMembershipCache[$mainPrincipal];
332  }
333 
334  $check = [$mainPrincipal];
335  $principals = [];
336 
337  while (count($check)) {
338 
339  $principal = array_shift($check);
340 
341  $node = $this->server->tree->getNodeForPath($principal);
342  if ($node instanceof IPrincipal) {
343  foreach ($node->getGroupMembership() as $groupMember) {
344 
345  if (!in_array($groupMember, $principals)) {
346 
347  $check[] = $groupMember;
348  $principals[] = $groupMember;
349 
350  }
351 
352  }
353 
354  }
355 
356  }
357 
358  // Store the result in the cache
359  $this->principalMembershipCache[$mainPrincipal] = $principals;
360 
361  return $principals;
362 
363  }
+ Here is the caller graph for this function:

◆ getSupportedPrivilegeSet()

Sabre\DAVACL\Plugin::getSupportedPrivilegeSet (   $node)

Returns a tree of supported privileges for a resource.

The returned array structure should be in this form:

[ [ 'privilege' => '{DAV:}read', 'abstract' => false, 'aggregates' => [] ] ]

Privileges can be nested using "aggregates". Doing so means that if you assign someone the aggregating privilege, all the sub-privileges will automatically be granted.

Marking a privilege as abstract means that the privilege cannot be directly assigned, but must be assigned via the parent privilege.

So a more complex version might look like this:

[ [ 'privilege' => '{DAV:}read', 'abstract' => false, 'aggregates' => [ [ 'privilege' => '{DAV:}read-acl', 'abstract' => false, 'aggregates' => [], ] ] ] ]

Parameters
string | INode$node
Returns
array

Definition at line 441 of file Plugin.php.

Referenced by Sabre\DAVACL\Plugin\getFlatPrivilegeSet(), and Sabre\DAVACL\Plugin\propFind().

441  {
442 
443  if (is_string($node)) {
444  $node = $this->server->tree->getNodeForPath($node);
445  }
446 
447  $supportedPrivileges = null;
448  if ($node instanceof IACL) {
449  $supportedPrivileges = $node->getSupportedPrivilegeSet();
450  }
451 
452  if (is_null($supportedPrivileges)) {
453 
454  // Default
455  $supportedPrivileges = [
456  '{DAV:}read' => [
457  'abstract' => false,
458  'aggregates' => [
459  '{DAV:}read-acl' => [
460  'abstract' => false,
461  'aggregates' => [],
462  ],
463  '{DAV:}read-current-user-privilege-set' => [
464  'abstract' => false,
465  'aggregates' => [],
466  ],
467  ],
468  ],
469  '{DAV:}write' => [
470  'abstract' => false,
471  'aggregates' => [
472  '{DAV:}write-properties' => [
473  'abstract' => false,
474  'aggregates' => [],
475  ],
476  '{DAV:}write-content' => [
477  'abstract' => false,
478  'aggregates' => [],
479  ],
480  '{DAV:}unlock' => [
481  'abstract' => false,
482  'aggregates' => [],
483  ],
484  ],
485  ],
486  ];
487  if ($node instanceof DAV\ICollection) {
488  $supportedPrivileges['{DAV:}write']['aggregates']['{DAV:}bind'] = [
489  'abstract' => false,
490  'aggregates' => [],
491  ];
492  $supportedPrivileges['{DAV:}write']['aggregates']['{DAV:}unbind'] = [
493  'abstract' => false,
494  'aggregates' => [],
495  ];
496  }
497  if ($node instanceof IACL) {
498  $supportedPrivileges['{DAV:}write']['aggregates']['{DAV:}write-acl'] = [
499  'abstract' => false,
500  'aggregates' => [],
501  ];
502  }
503 
504  }
505 
506  $this->server->emit(
507  'getSupportedPrivilegeSet',
508  [$node, &$supportedPrivileges]
509  );
510 
511  return $supportedPrivileges;
512 
513  }
+ Here is the caller graph for this function:

◆ getSupportedReportSet()

Sabre\DAVACL\Plugin::getSupportedReportSet (   $uri)

Returns a list of reports this plugin supports.

This will be used in the {DAV:}supported-report-set property. Note that you still need to subscribe to the 'report' event to actually implement them

Parameters
string$uri
Returns
array

Definition at line 165 of file Plugin.php.

165  {
166 
167  return [
168  '{DAV:}expand-property',
169  '{DAV:}principal-match',
170  '{DAV:}principal-property-search',
171  '{DAV:}principal-search-property-set',
172  ];
173 
174  }

◆ htmlActionsPanel()

Sabre\DAVACL\Plugin::htmlActionsPanel ( DAV\INode  $node,
$output 
)

This method is used to generate HTML output for the DAV.

This allows us to generate an interface users can use to create new calendars.

Parameters
DAV\INode$node
string$output
Returns
bool

Definition at line 1596 of file Plugin.php.

References Sabre\VObject\$output.

1596  {
1597 
1598  if (!$node instanceof PrincipalCollection)
1599  return;
1600 
1601  $output .= '<tr><td colspan="2"><form method="post" action="">
1602  <h3>Create new principal</h3>
1603  <input type="hidden" name="sabreAction" value="mkcol" />
1604  <input type="hidden" name="resourceType" value="{DAV:}principal" />
1605  <label>Name (uri):</label> <input type="text" name="name" /><br />
1606  <label>Display name:</label> <input type="text" name="{DAV:}displayname" /><br />
1607  <label>Email address:</label> <input type="text" name="{http://sabredav*DOT*org/ns}email-address" /><br />
1608  <input type="submit" value="create" />
1609  </form>
1610  </td></tr>';
1611 
1612  return false;
1613 
1614  }

◆ httpAcl()

Sabre\DAVACL\Plugin::httpAcl ( RequestInterface  $request,
ResponseInterface  $response 
)

This method is responsible for handling the 'ACL' event.

Parameters
RequestInterface$request
ResponseInterface$response
Returns
bool

Definition at line 1166 of file Plugin.php.

References $path, Sabre\HTTP\MessageInterface\getBodyAsString(), Sabre\DAVACL\Plugin\getFlatPrivilegeSet(), Sabre\HTTP\RequestInterface\getPath(), and Sabre\HTTP\ResponseInterface\setStatus().

1166  {
1167 
1168  $path = $request->getPath();
1169  $body = $request->getBodyAsString();
1170 
1171  if (!$body) {
1172  throw new DAV\Exception\BadRequest('XML body expected in ACL request');
1173  }
1174 
1175  $acl = $this->server->xml->expect('{DAV:}acl', $body);
1176  $newAcl = $acl->getPrivileges();
1177 
1178  // Normalizing urls
1179  foreach ($newAcl as $k => $newAce) {
1180  $newAcl[$k]['principal'] = $this->server->calculateUri($newAce['principal']);
1181  }
1182  $node = $this->server->tree->getNodeForPath($path);
1183 
1184  if (!$node instanceof IACL) {
1185  throw new DAV\Exception\MethodNotAllowed('This node does not support the ACL method');
1186  }
1187 
1188  $oldAcl = $this->getACL($node);
1189 
1190  $supportedPrivileges = $this->getFlatPrivilegeSet($node);
1191 
1192  /* Checking if protected principals from the existing principal set are
1193  not overwritten. */
1194  foreach ($oldAcl as $oldAce) {
1195 
1196  if (!isset($oldAce['protected']) || !$oldAce['protected']) continue;
1197 
1198  $found = false;
1199  foreach ($newAcl as $newAce) {
1200  if (
1201  $newAce['privilege'] === $oldAce['privilege'] &&
1202  $newAce['principal'] === $oldAce['principal'] &&
1203  $newAce['protected']
1204  )
1205  $found = true;
1206  }
1207 
1208  if (!$found)
1209  throw new Exception\AceConflict('This resource contained a protected {DAV:}ace, but this privilege did not occur in the ACL request');
1210 
1211  }
1212 
1213  foreach ($newAcl as $newAce) {
1214 
1215  // Do we recognize the privilege
1216  if (!isset($supportedPrivileges[$newAce['privilege']])) {
1217  throw new Exception\NotSupportedPrivilege('The privilege you specified (' . $newAce['privilege'] . ') is not recognized by this server');
1218  }
1219 
1220  if ($supportedPrivileges[$newAce['privilege']]['abstract']) {
1221  throw new Exception\NoAbstract('The privilege you specified (' . $newAce['privilege'] . ') is an abstract privilege');
1222  }
1223 
1224  // Looking up the principal
1225  try {
1226  $principal = $this->server->tree->getNodeForPath($newAce['principal']);
1227  } catch (NotFound $e) {
1228  throw new Exception\NotRecognizedPrincipal('The specified principal (' . $newAce['principal'] . ') does not exist');
1229  }
1230  if (!($principal instanceof IPrincipal)) {
1231  throw new Exception\NotRecognizedPrincipal('The specified uri (' . $newAce['principal'] . ') is not a principal');
1232  }
1233 
1234  }
1235  $node->setACL($newAcl);
1236 
1237  $response->setStatus(200);
1238 
1239  // Breaking the event chain, because we handled this method.
1240  return false;
1241 
1242  }
$path
Definition: aliased.php:25
foreach($paths as $path) $request
Definition: asyncclient.php:32
getFlatPrivilegeSet($node)
Returns the supported privilege set as a flat list.
Definition: Plugin.php:529
$response
+ Here is the call graph for this function:

◆ initialize()

Sabre\DAVACL\Plugin::initialize ( DAV\Server  $server)

Sets up the plugin.

This method is automatically called by the server class.

Parameters
DAV\Server$server
Returns
void

Definition at line 804 of file Plugin.php.

References $authPlugin, Sabre\DAVACL\Plugin\$server, and Sabre\DAVACL\Plugin\getPrincipalByUri().

804  {
805 
806  if ($this->allowUnauthenticatedAccess) {
807  $authPlugin = $server->getPlugin('auth');
808  if (!$authPlugin) {
809  throw new \Exception('The Auth plugin must be loaded before the ACL plugin if you want to allow unauthenticated access.');
810  }
811  $authPlugin->autoRequireLogin = false;
812  }
813 
814  $this->server = $server;
815  $server->on('propFind', [$this, 'propFind'], 20);
816  $server->on('beforeMethod', [$this, 'beforeMethod'], 20);
817  $server->on('beforeBind', [$this, 'beforeBind'], 20);
818  $server->on('beforeUnbind', [$this, 'beforeUnbind'], 20);
819  $server->on('propPatch', [$this, 'propPatch']);
820  $server->on('beforeUnlock', [$this, 'beforeUnlock'], 20);
821  $server->on('report', [$this, 'report']);
822  $server->on('method:ACL', [$this, 'httpAcl']);
823  $server->on('onHTMLActionsPanel', [$this, 'htmlActionsPanel']);
824  $server->on('getPrincipalByUri', function($principal, &$uri) {
825 
826  $uri = $this->getPrincipalByUri($principal);
827 
828  // Break event chain
829  if ($uri) return false;
830 
831  });
832 
833  array_push($server->protectedProperties,
834  '{DAV:}alternate-URI-set',
835  '{DAV:}principal-URL',
836  '{DAV:}group-membership',
837  '{DAV:}principal-collection-set',
838  '{DAV:}current-user-principal',
839  '{DAV:}supported-privilege-set',
840  '{DAV:}current-user-privilege-set',
841  '{DAV:}acl',
842  '{DAV:}acl-restrictions',
843  '{DAV:}inherited-acl-set',
844  '{DAV:}owner',
845  '{DAV:}group'
846  );
847 
848  // Automatically mapping nodes implementing IPrincipal to the
849  // {DAV:}principal resourcetype.
850  $server->resourceTypeMapping['Sabre\\DAVACL\\IPrincipal'] = '{DAV:}principal';
851 
852  // Mapping the group-member-set property to the HrefList property
853  // class.
854  $server->xml->elementMap['{DAV:}group-member-set'] = 'Sabre\\DAV\\Xml\\Property\\Href';
855  $server->xml->elementMap['{DAV:}acl'] = 'Sabre\\DAVACL\\Xml\\Property\\Acl';
856  $server->xml->elementMap['{DAV:}acl-principal-prop-set'] = 'Sabre\\DAVACL\\Xml\\Request\\AclPrincipalPropSetReport';
857  $server->xml->elementMap['{DAV:}expand-property'] = 'Sabre\\DAVACL\\Xml\\Request\\ExpandPropertyReport';
858  $server->xml->elementMap['{DAV:}principal-property-search'] = 'Sabre\\DAVACL\\Xml\\Request\\PrincipalPropertySearchReport';
859  $server->xml->elementMap['{DAV:}principal-search-property-set'] = 'Sabre\\DAVACL\\Xml\\Request\\PrincipalSearchPropertySetReport';
860  $server->xml->elementMap['{DAV:}principal-match'] = 'Sabre\\DAVACL\\Xml\\Request\\PrincipalMatchReport';
861 
862  }
getPrincipalByUri($uri)
Returns a principal based on its uri.
Definition: Plugin.php:708
$authPlugin
+ Here is the call graph for this function:

◆ principalMatchesPrincipal()

Sabre\DAVACL\Plugin::principalMatchesPrincipal (   $checkPrincipal,
  $currentPrincipal = null 
)

Find out of a principal equals another principal.

This is a quick way to find out whether a principal URI is part of a group, or any subgroups.

The first argument is the principal URI you want to check against. For example the principal group, and the second argument is the principal of which you want to find out of it is the same as the first principal, or in a member of the first principal's group or subgroups.

So the arguments are not interchangeable. If principal A is in group B, passing 'B', 'A' will yield true, but 'A', 'B' is false.

If the second argument is not passed, we will use the current user principal.

Parameters
string$checkPrincipal
string$currentPrincipal
Returns
bool

Definition at line 386 of file Plugin.php.

References Sabre\DAVACL\Plugin\getPrincipalMembership().

Referenced by Sabre\DAVACL\Plugin\getCurrentUserPrivilegeSet().

386  {
387 
388  if (is_null($currentPrincipal)) {
389  $currentPrincipal = $this->getCurrentUserPrincipal();
390  }
391  if ($currentPrincipal === $checkPrincipal) {
392  return true;
393  }
394  return in_array(
395  $checkPrincipal,
396  $this->getPrincipalMembership($currentPrincipal)
397  );
398 
399  }
getPrincipalMembership($mainPrincipal)
Returns all the principal groups the specified principal is a member of.
Definition: Plugin.php:327
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ principalMatchReport()

Sabre\DAVACL\Plugin::principalMatchReport (   $path,
Xml\Request\PrincipalMatchReport  $report 
)
protected

The principal-match report is defined in RFC3744, section 9.3.

This report allows a client to figure out based on the current user, or a principal URL, the principal URL and principal URLs of groups that principal belongs to.

Parameters
string$path
Xml\Request\PrincipalMatchReport$report
Returns
void

Definition at line 1259 of file Plugin.php.

References $path, $result, and Sabre\DAVACL\Plugin\getCurrentUserPrincipals().

Referenced by Sabre\DAVACL\Plugin\report().

1259  {
1260 
1261  $depth = $this->server->getHTTPDepth(0);
1262  if ($depth !== 0) {
1263  throw new BadRequest('The principal-match report is only defined on Depth: 0');
1264  }
1265 
1266  $currentPrincipals = $this->getCurrentUserPrincipals();
1267 
1268  $result = [];
1269 
1270  if ($report->type === Xml\Request\PrincipalMatchReport::SELF) {
1271 
1272  // Finding all principals under the request uri that match the
1273  // current principal.
1274  foreach ($currentPrincipals as $currentPrincipal) {
1275 
1276  if ($currentPrincipal === $path || strpos($currentPrincipal, $path . '/') === 0) {
1277  $result[] = $currentPrincipal;
1278  }
1279 
1280  }
1281 
1282  } else {
1283 
1284  // We need to find all resources that have a property that matches
1285  // one of the current principals.
1286  $candidates = $this->server->getPropertiesForPath(
1287  $path,
1288  [$report->principalProperty],
1289  1
1290  );
1291 
1292  foreach ($candidates as $candidate) {
1293 
1294  if (!isset($candidate[200][$report->principalProperty])) {
1295  continue;
1296  }
1297 
1298  $hrefs = $candidate[200][$report->principalProperty];
1299 
1300  if (!$hrefs instanceof Href) {
1301  continue;
1302  }
1303 
1304  foreach ($hrefs->getHrefs() as $href) {
1305  if (in_array(trim($href, '/'), $currentPrincipals)) {
1306  $result[] = $candidate['href'];
1307  continue 2;
1308  }
1309  }
1310  }
1311 
1312  }
1313 
1314  $responses = [];
1315 
1316  foreach ($result as $item) {
1317 
1318  $properties = [];
1319 
1320  if ($report->properties) {
1321 
1322  $foo = $this->server->getPropertiesForPath($item, $report->properties);
1323  $foo = $foo[0];
1324  $item = $foo['href'];
1325  unset($foo['href']);
1326  $properties = $foo;
1327 
1328  }
1329 
1330  $responses[] = new DAV\Xml\Element\Response(
1331  $item,
1332  $properties,
1333  '200'
1334  );
1335 
1336  }
1337 
1338  $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
1339  $this->server->httpResponse->setStatus(207);
1340  $this->server->httpResponse->setBody(
1341  $this->server->xml->write(
1342  '{DAV:}multistatus',
1343  $responses,
1344  $this->server->getBaseUri()
1345  )
1346  );
1347 
1348 
1349  }
$path
Definition: aliased.php:25
$result
getCurrentUserPrincipals()
Returns a list of principals that&#39;s associated to the current user, either directly or through group ...
Definition: Plugin.php:255
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ principalPropertySearchReport()

Sabre\DAVACL\Plugin::principalPropertySearchReport (   $path,
Xml\Request\PrincipalPropertySearchReport  $report 
)
protected

principalPropertySearchReport

This method is responsible for handing the {DAV:}principal-property-search report. This report can be used for clients to search for groups of principals, based on the value of one or more properties.

Parameters
string$path
Xml\Request\PrincipalPropertySearchReport$report
Returns
void

Definition at line 1503 of file Plugin.php.

References $path, $result, and Sabre\DAVACL\Plugin\principalSearch().

Referenced by Sabre\DAVACL\Plugin\report().

1503  {
1504 
1505  if ($report->applyToPrincipalCollectionSet) {
1506  $path = null;
1507  }
1508  if ($this->server->getHttpDepth('0') !== 0) {
1509  throw new BadRequest('Depth must be 0');
1510  }
1511  $result = $this->principalSearch(
1512  $report->searchProperties,
1513  $report->properties,
1514  $path,
1515  $report->test
1516  );
1517 
1518  $prefer = $this->server->getHTTPPrefer();
1519 
1520  $this->server->httpResponse->setStatus(207);
1521  $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
1522  $this->server->httpResponse->setHeader('Vary', 'Brief,Prefer');
1523  $this->server->httpResponse->setBody($this->server->generateMultiStatus($result, $prefer['return'] === 'minimal'));
1524 
1525  }
$path
Definition: aliased.php:25
$result
principalSearch(array $searchProperties, array $requestedProperties, $collectionUri=null, $test='allof')
Principal property search.
Definition: Plugin.php:759
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ principalSearch()

Sabre\DAVACL\Plugin::principalSearch ( array  $searchProperties,
array  $requestedProperties,
  $collectionUri = null,
  $test = 'allof' 
)

Principal property search.

This method can search for principals matching certain values in properties.

This method will return a list of properties for the matched properties.

Parameters
array$searchPropertiesThe properties to search on. This is a key-value list. The keys are property names, and the values the strings to match them on.
array$requestedPropertiesThis is the list of properties to return for every match.
string$collectionUriThe principal collection to search on. If this is ommitted, the standard principal collection-set will be used.
string$test"allof" to use AND to search the properties. 'anyof' for OR.
Returns
array This method returns an array structure similar to Sabre::getPropertiesForPath. Returned properties are index by a HTTP status code.

Definition at line 759 of file Plugin.php.

References Sabre\DAVACL\Plugin\$principalCollectionSet, $result, $results, and $test.

Referenced by Sabre\DAVACL\Plugin\principalPropertySearchReport().

759  {
760 
761  if (!is_null($collectionUri)) {
762  $uris = [$collectionUri];
763  } else {
765  }
766 
767  $lookupResults = [];
768  foreach ($uris as $uri) {
769 
770  $principalCollection = $this->server->tree->getNodeForPath($uri);
771  if (!$principalCollection instanceof IPrincipalCollection) {
772  // Not a principal collection, we're simply going to ignore
773  // this.
774  continue;
775  }
776 
777  $results = $principalCollection->searchPrincipals($searchProperties, $test);
778  foreach ($results as $result) {
779  $lookupResults[] = rtrim($uri, '/') . '/' . $result;
780  }
781 
782  }
783 
784  $matches = [];
785 
786  foreach ($lookupResults as $lookupResult) {
787 
788  list($matches[]) = $this->server->getPropertiesForPath($lookupResult, $requestedProperties, 0);
789 
790  }
791 
792  return $matches;
793 
794  }
$result
$results
Definition: svg-scanner.php:47
$test
Definition: Utf8Test.php:84
+ Here is the caller graph for this function:

◆ principalSearchPropertySetReport()

Sabre\DAVACL\Plugin::principalSearchPropertySetReport (   $path,
  $report 
)
protected

principalSearchPropertySetReport

This method responsible for handing the {DAV:}principal-search-property-set report. This report returns a list of properties the client may search on, using the {DAV:}principal-property-search report.

Parameters
string$path
Xml\Request\PrincipalSearchPropertySetReport$report
Returns
void

Definition at line 1448 of file Plugin.php.

References $description.

Referenced by Sabre\DAVACL\Plugin\report().

1448  {
1449 
1450  $httpDepth = $this->server->getHTTPDepth(0);
1451  if ($httpDepth !== 0) {
1452  throw new DAV\Exception\BadRequest('This report is only defined when Depth: 0');
1453  }
1454 
1455  $writer = $this->server->xml->getWriter();
1456  $writer->openMemory();
1457  $writer->startDocument();
1458 
1459  $writer->startElement('{DAV:}principal-search-property-set');
1460 
1461  foreach ($this->principalSearchPropertySet as $propertyName => $description) {
1462 
1463  $writer->startElement('{DAV:}principal-search-property');
1464  $writer->startElement('{DAV:}prop');
1465 
1466  $writer->writeElement($propertyName);
1467 
1468  $writer->endElement(); // prop
1469 
1470  if ($description) {
1471  $writer->write([[
1472  'name' => '{DAV:}description',
1473  'value' => $description,
1474  'attributes' => ['xml:lang' => 'en']
1475  ]]);
1476  }
1477 
1478  $writer->endElement(); // principal-search-property
1479 
1480 
1481  }
1482 
1483  $writer->endElement(); // principal-search-property-set
1484 
1485  $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
1486  $this->server->httpResponse->setStatus(200);
1487  $this->server->httpResponse->setBody($writer->outputMemory());
1488 
1489  }
+ Here is the caller graph for this function:

◆ propFind()

Sabre\DAVACL\Plugin::propFind ( DAV\PropFind  $propFind,
DAV\INode  $node 
)

Triggered before properties are looked up in specific nodes.

Parameters
DAV\PropFind$propFind
DAV\INode$nodereally should be broken into multiple methods, or even a class.
Returns
bool

Definition at line 986 of file Plugin.php.

References $path, Sabre\DAVACL\Plugin\$principalCollectionSet, $url, Sabre\DAVACL\Plugin\checkPrivileges(), Sabre\DAVACL\Plugin\getCurrentUserPrivilegeSet(), and Sabre\DAVACL\Plugin\getSupportedPrivilegeSet().

986  {
987 
988  $path = $propFind->getPath();
989 
990  // Checking the read permission
991  if (!$this->checkPrivileges($path, '{DAV:}read', self::R_PARENT, false)) {
992  // User is not allowed to read properties
993 
994  // Returning false causes the property-fetching system to pretend
995  // that the node does not exist, and will cause it to be hidden
996  // from listings such as PROPFIND or the browser plugin.
997  if ($this->hideNodesFromListings) {
998  return false;
999  }
1000 
1001  // Otherwise we simply mark every property as 403.
1002  foreach ($propFind->getRequestedProperties() as $requestedProperty) {
1003  $propFind->set($requestedProperty, null, 403);
1004  }
1005 
1006  return;
1007 
1008  }
1009 
1010  /* Adding principal properties */
1011  if ($node instanceof IPrincipal) {
1012 
1013  $propFind->handle('{DAV:}alternate-URI-set', function() use ($node) {
1014  return new Href($node->getAlternateUriSet());
1015  });
1016  $propFind->handle('{DAV:}principal-URL', function() use ($node) {
1017  return new Href($node->getPrincipalUrl() . '/');
1018  });
1019  $propFind->handle('{DAV:}group-member-set', function() use ($node) {
1020  $members = $node->getGroupMemberSet();
1021  foreach ($members as $k => $member) {
1022  $members[$k] = rtrim($member, '/') . '/';
1023  }
1024  return new Href($members);
1025  });
1026  $propFind->handle('{DAV:}group-membership', function() use ($node) {
1027  $members = $node->getGroupMembership();
1028  foreach ($members as $k => $member) {
1029  $members[$k] = rtrim($member, '/') . '/';
1030  }
1031  return new Href($members);
1032  });
1033  $propFind->handle('{DAV:}displayname', [$node, 'getDisplayName']);
1034 
1035  }
1036 
1037  $propFind->handle('{DAV:}principal-collection-set', function() {
1038 
1040  // Ensuring all collections end with a slash
1041  foreach ($val as $k => $v) $val[$k] = $v . '/';
1042  return new Href($val);
1043 
1044  });
1045  $propFind->handle('{DAV:}current-user-principal', function() {
1046  if ($url = $this->getCurrentUserPrincipal()) {
1047  return new Xml\Property\Principal(Xml\Property\Principal::HREF, $url . '/');
1048  } else {
1049  return new Xml\Property\Principal(Xml\Property\Principal::UNAUTHENTICATED);
1050  }
1051  });
1052  $propFind->handle('{DAV:}supported-privilege-set', function() use ($node) {
1053  return new Xml\Property\SupportedPrivilegeSet($this->getSupportedPrivilegeSet($node));
1054  });
1055  $propFind->handle('{DAV:}current-user-privilege-set', function() use ($node, $propFind, $path) {
1056  if (!$this->checkPrivileges($path, '{DAV:}read-current-user-privilege-set', self::R_PARENT, false)) {
1057  $propFind->set('{DAV:}current-user-privilege-set', null, 403);
1058  } else {
1059  $val = $this->getCurrentUserPrivilegeSet($node);
1060  return new Xml\Property\CurrentUserPrivilegeSet($val);
1061  }
1062  });
1063  $propFind->handle('{DAV:}acl', function() use ($node, $propFind, $path) {
1064  /* The ACL property contains all the permissions */
1065  if (!$this->checkPrivileges($path, '{DAV:}read-acl', self::R_PARENT, false)) {
1066  $propFind->set('{DAV:}acl', null, 403);
1067  } else {
1068  $acl = $this->getACL($node);
1069  return new Xml\Property\Acl($this->getACL($node));
1070  }
1071  });
1072  $propFind->handle('{DAV:}acl-restrictions', function() {
1073  return new Xml\Property\AclRestrictions();
1074  });
1075 
1076  /* Adding ACL properties */
1077  if ($node instanceof IACL) {
1078  $propFind->handle('{DAV:}owner', function() use ($node) {
1079  return new Href($node->getOwner() . '/');
1080  });
1081  }
1082 
1083  }
$path
Definition: aliased.php:25
getSupportedPrivilegeSet($node)
Returns a tree of supported privileges for a resource.
Definition: Plugin.php:441
checkPrivileges($uri, $privileges, $recursion=self::R_PARENT, $throwExceptions=true)
Checks if the current user has the specified privilege(s).
Definition: Plugin.php:192
$url
getCurrentUserPrivilegeSet($node)
Returns a list of privileges the current user has on a particular node.
Definition: Plugin.php:618
+ Here is the call graph for this function:

◆ propPatch()

Sabre\DAVACL\Plugin::propPatch (   $path,
DAV\PropPatch  $propPatch 
)

This method intercepts PROPPATCH methods and make sure the group-member-set is updated correctly.

Parameters
string$path
DAV\PropPatch$propPatch
Returns
void

Definition at line 1093 of file Plugin.php.

References $path.

1093  {
1094 
1095  $propPatch->handle('{DAV:}group-member-set', function($value) use ($path) {
1096  if (is_null($value)) {
1097  $memberSet = [];
1098  } elseif ($value instanceof Href) {
1099  $memberSet = array_map(
1100  [$this->server, 'calculateUri'],
1101  $value->getHrefs()
1102  );
1103  } else {
1104  throw new DAV\Exception('The group-member-set property MUST be an instance of Sabre\DAV\Property\HrefList or null');
1105  }
1106  $node = $this->server->tree->getNodeForPath($path);
1107  if (!($node instanceof IPrincipal)) {
1108  // Fail
1109  return false;
1110  }
1111 
1112  $node->setGroupMemberSet($memberSet);
1113  // We must also clear our cache, just in case
1114 
1115  $this->principalMembershipCache = [];
1116 
1117  return true;
1118  });
1119 
1120  }
$path
Definition: aliased.php:25

◆ report()

Sabre\DAVACL\Plugin::report (   $reportName,
  $report,
  $path 
)

This method handles HTTP REPORT requests.

Parameters
string$reportName
mixed$report
mixed$path
Returns
bool

Definition at line 1130 of file Plugin.php.

References $path, Sabre\DAVACL\Plugin\aclPrincipalPropSetReport(), Sabre\DAVACL\Plugin\expandPropertyReport(), Sabre\DAVACL\Plugin\principalMatchReport(), Sabre\DAVACL\Plugin\principalPropertySearchReport(), and Sabre\DAVACL\Plugin\principalSearchPropertySetReport().

1130  {
1131 
1132  switch ($reportName) {
1133 
1134  case '{DAV:}principal-property-search' :
1135  $this->server->transactionType = 'report-principal-property-search';
1136  $this->principalPropertySearchReport($path, $report);
1137  return false;
1138  case '{DAV:}principal-search-property-set' :
1139  $this->server->transactionType = 'report-principal-search-property-set';
1140  $this->principalSearchPropertySetReport($path, $report);
1141  return false;
1142  case '{DAV:}expand-property' :
1143  $this->server->transactionType = 'report-expand-property';
1144  $this->expandPropertyReport($path, $report);
1145  return false;
1146  case '{DAV:}principal-match' :
1147  $this->server->transactionType = 'report-principal-match';
1148  $this->principalMatchReport($path, $report);
1149  return false;
1150  case '{DAV:}acl-principal-prop-set' :
1151  $this->server->transactionType = 'acl-principal-prop-set';
1152  $this->aclPrincipalPropSetReport($path, $report);
1153  return false;
1154 
1155  }
1156 
1157  }
$path
Definition: aliased.php:25
aclPrincipalPropSetReport($path, Xml\Request\AclPrincipalPropSetReport $report)
aclPrincipalPropSet REPORT
Definition: Plugin.php:1544
principalPropertySearchReport($path, Xml\Request\PrincipalPropertySearchReport $report)
principalPropertySearchReport
Definition: Plugin.php:1503
expandPropertyReport($path, $report)
The expand-property report is defined in RFC3253 section 3.8.
Definition: Plugin.php:1366
principalSearchPropertySetReport($path, $report)
principalSearchPropertySetReport
Definition: Plugin.php:1448
principalMatchReport($path, Xml\Request\PrincipalMatchReport $report)
The principal-match report is defined in RFC3744, section 9.3.
Definition: Plugin.php:1259
+ Here is the call graph for this function:

◆ setDefaultAcl()

Sabre\DAVACL\Plugin::setDefaultAcl ( array  $acl)

Sets the default ACL rules.

These rules are used for all nodes that don't implement the IACL interface.

Parameters
array$acl
Returns
void

Definition at line 276 of file Plugin.php.

276  {
277 
278  $this->defaultAcl = $acl;
279 
280  }

Field Documentation

◆ $adminPrincipals

Sabre\DAVACL\Plugin::$adminPrincipals = []

Definition at line 102 of file Plugin.php.

◆ $allowUnauthenticatedAccess

Sabre\DAVACL\Plugin::$allowUnauthenticatedAccess = true

Definition at line 114 of file Plugin.php.

◆ $defaultAcl

Sabre\DAVACL\Plugin::$defaultAcl
protected
Initial value:
= [
[
'principal' => '{DAV:}authenticated',
'protected' => true

Definition at line 304 of file Plugin.php.

Referenced by Sabre\DAVACL\Plugin\getDefaultAcl().

◆ $hideNodesFromListings

Sabre\DAVACL\Plugin::$hideNodesFromListings = false

Definition at line 80 of file Plugin.php.

◆ $principalCollectionSet

Sabre\DAVACL\Plugin::$principalCollectionSet
Initial value:
= [
'principals',
]

Definition at line 67 of file Plugin.php.

Referenced by Sabre\DAVACL\Plugin\getPrincipalByUri(), Sabre\DAVACL\Plugin\principalSearch(), and Sabre\DAVACL\Plugin\propFind().

◆ $principalMembershipCache

Sabre\DAVACL\Plugin::$principalMembershipCache = []
protected

Definition at line 318 of file Plugin.php.

◆ $principalSearchPropertySet

Sabre\DAVACL\Plugin::$principalSearchPropertySet
Initial value:
= [
'{DAV:}displayname' => 'Display name'

Definition at line 90 of file Plugin.php.

◆ $server

Sabre\DAVACL\Plugin::$server
protected

Definition at line 59 of file Plugin.php.

Referenced by Sabre\DAVACL\Plugin\initialize().

◆ R_PARENT

const Sabre\DAVACL\Plugin::R_PARENT = 1

Recursion constants.

This only checks the base node

Definition at line 38 of file Plugin.php.

Referenced by Sabre\DAVACL\SimplePluginTest\testCheckPrivileges().

◆ R_RECURSIVE

const Sabre\DAVACL\Plugin::R_RECURSIVE = 2

Recursion constants.

This checks every node in the tree

Definition at line 45 of file Plugin.php.

◆ R_RECURSIVEPARENTS

const Sabre\DAVACL\Plugin::R_RECURSIVEPARENTS = 3

Recursion constants.

This checks every parentnode in the tree, but not leaf-nodes.

Definition at line 52 of file Plugin.php.


The documentation for this class was generated from the following file: