source: contrib/davical/inc/caldav-ACL.php @ 3733

Revision 3733, 8.4 KB checked in by gabriel.malheiros, 13 years ago (diff)

Ticket #1541 - <Davical customizado para o Expresso.Utiliza Caldav e CardDav?>

Line 
1<?php
2/**
3* CalDAV Server - handle ACL method
4*
5* @package   davical
6* @subpackage   caldav
7* @author    Andrew McMillan <andrew@morphoss.com>
8* @copyright Morphoss Ltd
9* @license   http://gnu.org/copyleft/gpl.html GNU GPL v2
10*/
11dbg_error_log("ACL", "method handler");
12
13require_once('DAVResource.php');
14
15$request->NeedPrivilege('DAV::write-acl');
16
17if ( ! ini_get('open_basedir') && (isset($c->dbg['ALL']) || (isset($c->dbg['put']) && $c->dbg['put'])) ) {
18  $fh = fopen('/tmp/MOVE.txt','w');
19  if ( $fh ) {
20    fwrite($fh,$request->raw_post);
21    fclose($fh);
22  }
23}
24
25$resource = new DAVResource( $request->path );
26
27/**
28* Preconditions
29   (DAV:no-ace-conflict): The ACEs submitted in the ACL request MUST NOT
30   conflict with each other.  This is a catchall error code indicating
31   that an implementation-specific ACL restriction has been violated.
32
33   (DAV:no-protected-ace-conflict): The ACEs submitted in the ACL
34   request MUST NOT conflict with the protected ACEs on the resource.
35   For example, if the resource has a protected ACE granting DAV:write
36   to a given principal, then it would not be consistent if the ACL
37   request submitted an ACE denying DAV:write to the same principal.
38
39   (DAV:no-inherited-ace-conflict): The ACEs submitted in the ACL
40   request MUST NOT conflict with the inherited ACEs on the resource.
41   For example, if the resource inherits an ACE from its parent
42   collection granting DAV:write to a given principal, then it would not
43   be consistent if the ACL request submitted an ACE denying DAV:write
44   to the same principal.  Note that reporting of this error will be
45   implementation-dependent.  Implementations MUST either report this
46   error or allow the ACE to be set, and then let normal ACE evaluation
47   rules determine whether the new ACE has any impact on the privileges
48   available to a specific principal.
49
50   (DAV:limited-number-of-aces): The number of ACEs submitted in the ACL
51   request MUST NOT exceed the number of ACEs allowed on that resource.
52   However, ACL-compliant servers MUST support at least one ACE granting
53   privileges to a single principal, and one ACE granting privileges to
54   a group.
55
56   (DAV:deny-before-grant): All non-inherited deny ACEs MUST precede all
57   non-inherited grant ACEs.
58
59   (DAV:grant-only): The ACEs submitted in the ACL request MUST NOT
60   include a deny ACE.  This precondition applies only when the ACL
61   restrictions of the resource include the DAV:grant-only constraint
62   (defined in Section 5.6.1).
63
64   (DAV:no-invert):  The ACL request MUST NOT include a DAV:invert
65   element.  This precondition applies only when the ACL semantics of
66   the resource includes the DAV:no-invert constraint (defined in
67   Section 5.6.2).
68
69   (DAV:no-abstract): The ACL request MUST NOT attempt to grant or deny
70   an abstract privilege (see Section 5.3).
71
72   (DAV:not-supported-privilege): The ACEs submitted in the ACL request
73   MUST be supported by the resource.
74
75   (DAV:missing-required-principal): The result of the ACL request MUST
76   have at least one ACE for each principal identified in a
77   DAV:required-principal XML element in the ACL semantics of that
78   resource (see Section 5.5).
79
80   (DAV:recognized-principal): Every principal URL in the ACL request
81   MUST identify a principal resource.
82
83   (DAV:allowed-principal): The principals specified in the ACEs
84   submitted in the ACL request MUST be allowed as principals for the
85   resource.  For example, a server where only authenticated principals
86   can access resources would not allow the DAV:all or
87   DAV:unauthenticated principals to be used in an ACE, since these
88   would allow unauthenticated access to resources.
89*/
90
91$position = 0;
92$xmltree = BuildXMLTree( $request->xml_tags, $position);
93$aces = $xmltree->GetPath("/DAV::acl/*");
94
95$grantor = new DAVResource($request->path);
96if ( ! $grantor->Exists() ) $request->DoResponse( 404 );
97$by_principal  = null;
98$by_collection = null;
99if ( $grantor->IsPrincipal() ) $by_principal = $grantor->GetProperty('principal_id');
100else if ( $grantor->IsCollection() ) $by_collection = $grantor->GetProperty('collection_id');
101else $request->PreconditionFailed(403,'not-supported-privilege','ACLs may only be applied to Principals or Collections');
102
103$qry = new AwlQuery('BEGIN');
104$qry->Exec('ACL',__LINE__,__FILE__);
105
106foreach( $aces AS $k => $ace ) {
107  $elements = $ace->GetContent();
108  $principal = $elements[0];
109  $grant = $elements[1];
110  if ( $principal->GetTag() != 'DAV::principal' ) $request->MalformedRequest('ACL request must contain a principal, not '.$principal->GetTag());
111  $grant_tag = $grant->GetTag();
112  if ( $grant_tag == 'DAV::deny' )   $request->PreconditionFailed(403,'grant-only');
113  if ( $grant_tag == 'DAV::invert' ) $request->PreconditionFailed(403,'no-invert');
114  if ( $grant->GetTag() != 'DAV::grant' ) $request->MalformedRequest('ACL request must contain a principal for each ACE');
115
116  $privilege_names = array();
117  $xml_privs = $grant->GetPath("/DAV::grant/DAV::privilege/*");
118  foreach( $xml_privs AS $k => $priv ) {
119    $privilege_names[] = $priv->GetTag();
120  }
121  $privileges = privilege_to_bits($privilege_names);
122
123  $principal_content = $principal->GetContent();
124  if ( count($principal_content) != 1 ) $request->MalformedRequest('ACL request must contain exactly one principal per ACE');
125  $principal_content = $principal_content[0];
126  switch( $principal_content->GetTag() ) {
127    case 'DAV::property':
128      $principal_property = $principal_content->GetContent();
129      if ( $principal_property[0]->GetTag() != 'DAV::owner' ) $request->PreconditionFailed(403, 'recognized-principal' );
130      if ( privilege_to_bits('all') != $privileges ) {
131        $request->PreconditionFailed(403, 'no-protected-ace-conflict', 'Owner must always have all permissions' );
132      }
133      continue;  // and then we ignore it, since it's protected
134      break;
135
136    case 'DAV::unauthenticated':
137      $request->PreconditionFailed(403, 'allowed-principal', 'May not set privileges for unauthenticated users' );
138      break;
139
140    case 'DAV::href':
141      $principal_type = 'href';
142      $principal = new DAVResource( DeconstructURL($principal_content->GetContent()) );
143      if ( ! $principal->Exists() || !$principal->IsPrincipal() )
144        $request->PreconditionFailed(403,'recognized-principal', 'Principal "' + $principal_content->GetContent() + '" not found.');
145      $sqlparms = array( ':to_principal' => $principal->GetProperty('principal_id') );
146      $where = 'WHERE to_principal=:to_principal AND ';
147      if ( isset($by_principal) ) {
148        $sqlparms[':by_principal'] = $by_principal;
149        $where .= 'by_principal = :by_principal';
150      }
151      else {
152        $sqlparms[':by_collection'] = $by_collection;
153        $where .= 'by_collection = :by_collection';
154      }
155      $qry = new AwlQuery('SELECT privileges FROM grants '.$where, $sqlparms);
156      if ( $qry->Exec('ACL',__LINE__,__FILE__) && $qry->rows() == 1 && $current = $qry->Fetch() ) {
157        $sql = 'UPDATE grants SET privileges=:privileges::INT::BIT(24) '.$where;
158      }
159      else {
160        $sqlparms[':by_principal'] = $by_principal;
161        $sqlparms[':by_collection'] = $by_collection;
162        $sql = 'INSERT INTO grants (by_principal, by_collection, to_principal, privileges) VALUES(:by_principal, :by_collection, :to_principal, :privileges::INT::BIT(24))';
163      }
164      $sqlparms[':privileges'] = $privileges;
165      $qry = new AwlQuery($sql, $sqlparms);
166      $qry->Exec('ACL',__LINE__,__FILE__);
167      break;
168
169    case 'DAV::authenticated':
170      $principal_type = 'authenticated';
171      if ( bindec($grantor->GetProperty('default_privileges')) == $privileges ) continue; // There is no change, so skip it
172      $sqlparms = array( ':privileges' => $privileges );
173      if ( isset($by_collection) ) {
174        $sql = 'UPDATE collection SET default_privileges=:privileges::INT::BIT(24) WHERE collection_id=:by_collection';
175        $sqlparms[':by_collection'] = $by_collection;
176      }
177      else {
178        $sql = 'UPDATE principal SET default_privileges=:privileges::INT::BIT(24) WHERE principal_id=:by_principal';
179        $sqlparms[':by_principal'] = $by_principal;
180      }
181      $qry = new AwlQuery($sql, $sqlparms);
182      $qry->Exec('ACL',__LINE__,__FILE__);
183      break;
184
185    case 'DAV::all':
186//      $principal_type = 'all';
187      $request->PreconditionFailed(403, 'allowed-principal', 'May not set privileges for unauthenticated users' );
188      break;
189
190    default:
191      $request->PreconditionFailed(403, 'recognized-principal' );
192      break;
193  }
194
195}
196
197$qry = new AwlQuery('COMMIT');
198$qry->Exec('ACL',__LINE__,__FILE__);
199
200
201$request->DoResponse( 200 );
Note: See TracBrowser for help on using the repository browser.