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\Browser\Plugin. 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/) @license 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.

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

References $path.

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

+ 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.

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

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

+ 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.

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 }
foreach($paths as $path) $request
Definition: asyncclient.php:32

References $path, $request, and Sabre\DAVACL\Plugin\checkPrivileges().

+ 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.

958 {
959
960 list($parentUri) = Uri\split($uri);
961 $this->checkPrivileges($parentUri, '{DAV:}unbind', self::R_RECURSIVEPARENTS);
962
963 }

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

+ 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@TODO: 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.

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

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().

+ 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.

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 }
$result
expandProperties($path, array $requestedProperties, $depth)
This method expands all the properties and returns a list with property values.
Definition: Plugin.php:1392

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

Referenced by Sabre\DAVACL\Plugin\expandProperties(), and Sabre\DAVACL\Plugin\expandPropertyReport().

+ Here is the call graph for this function:
+ 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.

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 }

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

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

+ 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.

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

References Sabre\DAVACL\Plugin\getDefaultAcl().

+ 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.

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

References Sabre\DAVACL\Plugin\getPrincipalMembership().

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

+ 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\INode may be passed.

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

Parameters
string | DAV\INode$node
Returns
array

Reimplemented in Sabre\DAVACL\MockPlugin.

Definition at line 618 of file Plugin.php.

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 }
getFlatPrivilegeSet($node)
Returns the supported privilege set as a flat list.
Definition: Plugin.php:529
principalMatchesPrincipal($checkPrincipal, $currentPrincipal=null)
Find out of a principal equals another principal.
Definition: Plugin.php:386

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

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

+ 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.

289 {
290
291 return $this->defaultAcl;
292
293 }

References Sabre\DAVACL\Plugin\$defaultAcl.

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

+ 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

Reimplemented from Sabre\DAV\ServerPlugin.

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.

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

References Sabre\DAVACL\Plugin\getSupportedPrivilegeSet().

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

+ 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

Reimplemented from Sabre\DAV\ServerPlugin.

Definition at line 1627 of file Plugin.php.

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

References Sabre\DAVACL\Plugin\getPluginName().

+ 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\DAV\Server::getPlugin

Returns
string

Reimplemented from Sabre\DAV\ServerPlugin.

Definition at line 149 of file Plugin.php.

149 {
150
151 return 'acl';
152
153 }

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

+ 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.

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 }

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

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

+ 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.

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 }

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

+ 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.

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 }

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

+ 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

Reimplemented from Sabre\DAV\ServerPlugin.

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\Browser\Plugin.

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.

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 }

References Sabre\VObject\$output.

◆ 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.

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 }
$response

References $path, $request, $response, and Sabre\DAVACL\Plugin\getFlatPrivilegeSet().

+ 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.

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

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

+ 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.

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 }

References Sabre\DAVACL\Plugin\getPrincipalMembership().

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

+ 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.

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 }
getCurrentUserPrincipals()
Returns a list of principals that's associated to the current user, either directly or through group ...
Definition: Plugin.php:255

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

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

+ 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.

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 }
principalSearch(array $searchProperties, array $requestedProperties, $collectionUri=null, $test='allof')
Principal property search.
Definition: Plugin.php:759

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

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

+ 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\DAV\Server::getPropertiesForPath. Returned properties are index by a HTTP status code.

Definition at line 759 of file Plugin.php.

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 }
$test
Definition: Utf8Test.php:84
$results
Definition: svg-scanner.php:47

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

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

+ 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.

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 }

References $description.

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

+ 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$node@TODO really should be broken into multiple methods, or even a class.
Returns
bool

Definition at line 986 of file Plugin.php.

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 }
$url

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

+ 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.

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 }

References $path.

◆ 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.

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 }
principalSearchPropertySetReport($path, $report)
principalSearchPropertySetReport
Definition: Plugin.php:1448
expandPropertyReport($path, $report)
The expand-property report is defined in RFC3253 section 3.8.
Definition: Plugin.php:1366
principalPropertySearchReport($path, Xml\Request\PrincipalPropertySearchReport $report)
principalPropertySearchReport
Definition: Plugin.php:1503
principalMatchReport($path, Xml\Request\PrincipalMatchReport $report)
The principal-match report is defined in RFC3744, section 9.3.
Definition: Plugin.php:1259
aclPrincipalPropSetReport($path, Xml\Request\AclPrincipalPropSetReport $report)
aclPrincipalPropSet REPORT
Definition: Plugin.php:1544

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

+ 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,
'privilege' => '{DAV:}all',
],
]

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',
'{http:
]

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: