Split dav_name into real_dav_name & bound_dav_name.

This is a first stage in disconnecting these two for an
implementation of WebDAV BIND which is going to arrive in
the next few days...
This commit is contained in:
Andrew McMillan 2010-03-11 23:59:18 +13:00
parent 9f3deeb416
commit 3e455c8543

View File

@ -49,6 +49,16 @@ class DAVResource
*/
protected $contenttype;
/**
* @var The name which this resource is being retrieved as
*/
protected $bound_dav_name;
/**
* @var The canonical name which this resource exists at
*/
protected $real_dav_name;
/**
* @var An object which is the collection record for this resource, or for it's container
*/
@ -117,7 +127,8 @@ class DAVResource
*/
function __construct( $parameters = null ) {
$this->exists = null;
$this->dav_name = null;
$this->bound_dav_name = null;
$this->real_dav_name = null;
$this->unique_tag = null;
$this->resource = null;
$this->collection = null;
@ -158,15 +169,16 @@ class DAVResource
if ( $row == null ) return;
$this->exists = true;
$this->dav_name = $row->dav_name;
$this->_is_collection = preg_match( '{/$}', $row->dav_name );
$this->real_dav_name = $row->dav_name;
$this->bound_dav_name = (isset($row->bound_dav_name)? $row->bound_dav_name : $row->dav_name);
$this->_is_collection = preg_match( '{/$}', $this->real_dav_name );
if ( $this->_is_collection ) {
$this->contenttype = 'httpd/unix-directory';
$this->collection = (object) array();
$this->_is_principal = preg_match( '{^/[^/]+/$}', $row->dav_name );
if ( preg_match( '#^(/principals/[^/]+/[^/]+)/?$#', $row->dav_name, $matches) ) {
$this->_is_principal = preg_match( '{^/[^/]+/$}', $this->real_dav_name );
if ( preg_match( '#^(/principals/[^/]+/[^/]+)/?$#', $this->real_dav_name, $matches) ) {
$this->collection->dav_name = $matches[1].'/';
$this->collection->type = 'principal_link';
$this->_is_principal = true;
@ -176,7 +188,7 @@ class DAVResource
$this->resource = (object) array();
}
dbg_error_log( 'DAVResource', ':FromRow: Named "%s" is%s a collection.', $row->dav_name, ($this->_is_collection?'':' not') );
dbg_error_log( 'DAVResource', ':FromRow: Named "%s" is%s a collection.', $this->real_dav_name, ($this->_is_collection?'':' not') );
foreach( $row AS $k => $v ) {
if ( $this->_is_collection )
@ -205,9 +217,9 @@ class DAVResource
$this->collection->type = 'calendar';
else if ( $row->is_addressbook == 't' )
$this->collection->type = 'addressbook';
else if ( preg_match( '#^((/[^/]+/)\.(in|out)/)[^/]*$#', $this->dav_name, $matches ) )
else if ( preg_match( '#^((/[^/]+/)\.(in|out)/)[^/]*$#', $this->real_dav_name, $matches ) )
$this->collection->type = 'schedule-'. $matches[3]. 'box';
else if ( $this->dav_name == '/' )
else if ( $this->real_dav_name == '/' )
$this->collection->type = 'root';
else
$this->collection->type = 'collection';
@ -237,7 +249,7 @@ class DAVResource
function FromPath($inpath) {
global $c;
$this->dav_name = DeconstructURL($inpath);
$this->real_dav_name = DeconstructURL($inpath);
$this->FetchCollection();
if ( $this->_is_collection ) {
@ -247,7 +259,7 @@ class DAVResource
$this->FetchResource();
}
dbg_error_log( 'DAVResource', ':FromPath: Path "%s" is%s a collection%s.',
$this->dav_name, ($this->_is_collection?' '.$this->resourcetypes:' not'), ($this->_is_principal?' and a principal':'') );
$this->real_dav_name, ($this->_is_collection?' '.$this->resourcetypes:' not'), ($this->_is_principal?' and a principal':'') );
}
@ -267,7 +279,7 @@ class DAVResource
* The collection URL for this request is therefore the longest row in the result, so we
* can "... ORDER BY LENGTH(dav_name) DESC LIMIT 1"
*/
dbg_error_log( 'DAVResource', ':FetchCollection: Looking for collection for "%s".', $this->dav_name );
dbg_error_log( 'DAVResource', ':FetchCollection: Looking for collection for "%s".', $this->real_dav_name );
$this->collection = (object) array(
'collection_id' => -1,
@ -283,11 +295,11 @@ class DAVResource
$base_sql .= 'LEFT JOIN time_zone ON (collection.timezone=time_zone.tz_id) ';
$base_sql .= 'WHERE ';
$sql = $base_sql .'collection.dav_name = :raw_path ';
$params = array( ':raw_path' => $this->dav_name, ':session_principal' => $session->principal_id, ':scan_depth' => $c->permission_scan_depth );
if ( !preg_match( '#/$#', $this->dav_name ) ) {
$params = array( ':raw_path' => $this->real_dav_name, ':session_principal' => $session->principal_id, ':scan_depth' => $c->permission_scan_depth );
if ( !preg_match( '#/$#', $this->real_dav_name ) ) {
$sql .= ' OR collection.dav_name = :up_to_slash OR collection.dav_name = :plus_slash ';
$params[':up_to_slash'] = preg_replace( '#[^/]*$#', '', $this->dav_name);
$params[':plus_slash'] = $this->dav_name.'/';
$params[':up_to_slash'] = preg_replace( '#[^/]*$#', '', $this->real_dav_name);
$params[':plus_slash'] = $this->real_dav_name.'/';
}
$sql .= 'ORDER BY LENGTH(collection.dav_name) DESC LIMIT 1';
$qry = new AwlQuery( $sql, $params );
@ -298,33 +310,34 @@ class DAVResource
$this->collection->type = 'calendar';
else if ( $row->is_addressbook == 't' )
$this->collection->type = 'addressbook';
else if ( preg_match( '#^((/[^/]+/)\.(in|out)/)[^/]*$#', $this->dav_name, $matches ) )
else if ( preg_match( '#^((/[^/]+/)\.(in|out)/)[^/]*$#', $this->real_dav_name, $matches ) )
$this->collection->type = 'schedule-'. $matches[3]. 'box';
else
$this->collection->type = 'collection';
}
else if ( preg_match( '#^((/[^/]+/)\.(in|out)/)[^/]*$#', $this->dav_name, $matches ) ) {
else if ( preg_match( '#^((/[^/]+/)\.(in|out)/)[^/]*$#', $this->real_dav_name, $matches ) ) {
// The request is for a scheduling inbox or outbox (or something inside one) and we should auto-create it
$params = array( ':user_no' => $session->user_no, ':parent_container' => $matches[2], ':dav_name' => $matches[1] );
$params['displayname'] = $session->fullname . ($matches[3] == 'in' ? ' Inbox' : ' Outbox');
$this->collection->type = 'schedule-'. $matches[3]. 'box';
$params['resourcetypes'] = sprintf('<DAV::collection/><urn:ietf:params:xml:ns:caldav:%s/>', $this->collection->type );
$params[':displayname'] = $session->fullname . ($matches[3] == 'in' ? ' Inbox' : ' Outbox');
$this->collection_type = 'schedule-'. $matches[3]. 'box';
$params[':resourcetypes'] = sprintf('<DAV::collection/><urn:ietf:params:xml:ns:caldav:%s/>', $this->collection_type );
$sql = <<<EOSQL
INSERT INTO collection ( user_no, parent_container, dav_name, dav_displayname, is_calendar, created, modified, dav_etag, resourcetypes )
VALUES( :user_no, :parent_container, :dav_name, :dav_displayname, FALSE, current_timestamp, current_timestamp, '1', :resourcetypes )
VALUES( :user_no, :parent_container, :dav_name, :displayname, FALSE, current_timestamp, current_timestamp, '1', :resourcetypes )
EOSQL;
$qry = new AwlQuery( $sql, $params );
$qry->Exec('DAVResource');
dbg_error_log( 'DAVResource', 'Created new collection as "$displayname".' );
$params = array( ':raw_path' => $this->dav_name, ':session_principal' => $session->principal_id );
$params = array( ':raw_path' => $this->real_dav_name, ':session_principal' => $session->principal_id, ':scan_depth' => $c->permission_scan_depth );
$qry = new AwlQuery( $base_sql . ' dav_name = :raw_path', $params );
if ( $qry->Exec('DAVResource') && $qry->rows() == 1 && ($row = $qry->Fetch()) ) {
$this->collection = $row;
$this->collection->exists = true;
$this->collection->type = $this->collection_type;
}
}
else if ( preg_match( '#^(/([^/]+)/calendar-proxy-(read|write))/?[^/]*$#', $this->dav_name, $matches ) ) {
else if ( preg_match( '#^(/([^/]+)/calendar-proxy-(read|write))/?[^/]*$#', $this->real_dav_name, $matches ) ) {
$this->collection->type = 'proxy';
$this->_is_proxy_request = true;
$this->proxy_type = $matches[3];
@ -332,17 +345,17 @@ EOSQL;
$this->collection->dav_displayname = sprintf( '%s proxy %s', $matches[2], $matches[3] );
$this->collection->exists = true;
}
else if ( preg_match( '#^(/[^/]+)/?$#', $this->dav_name, $matches) ) {
else if ( preg_match( '#^(/[^/]+)/?$#', $this->real_dav_name, $matches) ) {
$this->collection->dav_name = $matches[1].'/';
$this->collection->type = 'principal';
$this->_is_principal = true;
}
else if ( preg_match( '#^(/principals/[^/]+/[^/]+)/?$#', $this->dav_name, $matches) ) {
else if ( preg_match( '#^(/principals/[^/]+/[^/]+)/?$#', $this->real_dav_name, $matches) ) {
$this->collection->dav_name = $matches[1].'/';
$this->collection->type = 'principal_link';
$this->_is_principal = true;
}
else if ( $this->dav_name == '/' ) {
else if ( $this->real_dav_name == '/' ) {
$this->collection->dav_name = '/';
$this->collection->type = 'root';
$this->collection->exists = true;
@ -350,16 +363,16 @@ EOSQL;
$this->collection->default_privileges = (1 | 16 | 32);
}
else {
dbg_error_log( 'DAVResource', 'No collection for path "%s".', $this->dav_name );
dbg_error_log( 'DAVResource', 'No collection for path "%s".', $this->real_dav_name );
$this->collection->exists = false;
$this->collection->dav_name = preg_replace('{/[^/]*$}', '/', $this->dav_name);
$this->collection->dav_name = preg_replace('{/[^/]*$}', '/', $this->real_dav_name);
}
dbg_error_log( 'DAVResource', ':FetchCollection: Found collection named "%s" of type "%s".', $this->collection->dav_name, $this->collection->type );
$this->_is_collection = ( $this->collection->dav_name == $this->dav_name || $this->collection->dav_name == $this->dav_name.'/' );
$this->_is_collection = ( $this->collection->dav_name == $this->real_dav_name || $this->collection->dav_name == $this->real_dav_name.'/' );
if ( $this->_is_collection ) {
$this->dav_name = $this->collection->dav_name;
$this->real_dav_name = $this->collection->dav_name;
$this->_is_calendar = ($this->collection->type == 'calendar');
$this->_is_addressbook = ($this->collection->type == 'addressbook');
$this->contenttype = 'httpd/unix-directory';
@ -388,7 +401,7 @@ EOSQL;
*/
function FetchPrincipal() {
global $c, $session;
$this->principal = new CalDAVPrincipal( array( "path" => $this->dav_name ) );
$this->principal = new CalDAVPrincipal( array( "path" => $this->real_dav_name ) );
if ( $this->_is_principal && $this->principal->Exists() ) {
// $this->contenttype = 'httpd/unix-directory';
$this->exists = true;
@ -413,7 +426,7 @@ EOSQL;
SELECT * FROM caldav_data LEFT JOIN calendar_item USING (collection_id,dav_id)
WHERE caldav_data.dav_name = :dav_name
EOQRY;
$params = array( ':dav_name' => $this->dav_name );
$params = array( ':dav_name' => $this->real_dav_name );
$qry = new AwlQuery( $sql, $params );
if ( $qry->Exec('DAVResource') && $qry->rows() > 0 ) {
@ -440,7 +453,7 @@ EOQRY;
if ( isset($this->dead_properties) ) return;
$this->dead_properties = array();
$qry = new AwlQuery('SELECT property_name, property_value FROM property WHERE dav_name= :dav_name', array(':dav_name' => $this->dav_name) );
$qry = new AwlQuery('SELECT property_name, property_value FROM property WHERE dav_name= :dav_name', array(':dav_name' => $this->real_dav_name) );
if ( $qry->Exec('DAVResource') ) {
while ( $property = $qry->Fetch() ) {
$this->dead_properties[$property->property_name] = $property->property_value;
@ -455,7 +468,7 @@ EOQRY;
function FetchPrivileges() {
global $session, $request;
if ( $this->dav_name == '/' || $this->dav_name == '' ) {
if ( $this->real_dav_name == '/' || $this->real_dav_name == '' ) {
$this->privileges = (1 | 16 | 32); // read + read-acl + read-current-user-privilege-set
dbg_error_log( 'DAVResource', 'Read permissions for user accessing /' );
return;
@ -489,7 +502,7 @@ EOQRY;
$this->privileges = $this->collection->path_privs;
if ( is_string($this->privileges) ) $this->privileges = bindec( $this->privileges );
if ( isset($request->ticket) && $request->ticket->MatchesPath($this->dav_name) ) {
if ( isset($request->ticket) && $request->ticket->MatchesPath($this->real_dav_name) ) {
$this->privileges |= $request->ticket->privileges();
dbg_error_log( 'DAVResource', 'Applying permissions for ticket "%s" now: %s', $request->ticket->id(), decbin($this->privileges) );
}
@ -528,7 +541,7 @@ EOQRY;
if ( $this->HavePrivilegeTo($privilege) ) return;
$request->NeedPrivilege( $privilege, $this->dav_name );
$request->NeedPrivilege( $privilege, $this->real_dav_name );
exit(0); // Unecessary, but might clarify things
}
@ -764,7 +777,7 @@ EOQRY;
* Find the locks that might apply and load them into an array
*/
$sql = 'SELECT * FROM locks WHERE :this_path::text ~ (\'^\'||dav_name||:match_end)::text';
$qry = new AwlQuery($sql, array( ':this_path' => $this->dav_name, ':match_end' => ($depth == DEPTH_INFINITY ? '' : '$') ) );
$qry = new AwlQuery($sql, array( ':this_path' => $this->real_dav_name, ':match_end' => ($depth == DEPTH_INFINITY ? '' : '$') ) );
if ( $qry->Exec('DAVResource',__LINE__,__FILE__) ) {
while( $lock_row = $qry->Fetch() ) {
$this->_locks_found[$lock_row->opaquelocktoken] = $lock_row;
@ -777,7 +790,7 @@ EOQRY;
}
foreach( $this->_locks_found AS $lock_token => $lock_row ) {
if ( $lock_row->depth == DEPTH_INFINITY || $lock_row->dav_name == $this->dav_name ) {
if ( $lock_row->depth == DEPTH_INFINITY || $lock_row->dav_name == $this->real_dav_name ) {
return $lock_token;
}
}
@ -843,7 +856,7 @@ EOQRY;
if ( !isset($this->resource) ) $this->FetchResource();
}
}
// dbg_error_log('DAVResource',' Checking whether "%s" exists. It would appear %s.', $this->dav_name, ($this->exists ? 'so' : 'not') );
// dbg_error_log('DAVResource',' Checking whether "%s" exists. It would appear %s.', $this->real_dav_name, ($this->exists ? 'so' : 'not') );
return $this->exists;
}
@ -852,7 +865,7 @@ EOQRY;
* Returns the dav_name of the resource in our internal namespace
*/
function dav_name() {
if ( isset($this->dav_name) ) return $this->dav_name;
if ( isset($this->real_dav_name) ) return $this->real_dav_name;
return null;
}
@ -913,7 +926,7 @@ EOQRY;
$this->parent_container_type = 'calendar';
else if ( $parent->is_addressbook == 't' )
$this->parent_container_type = 'addressbook';
else if ( preg_match( '#^((/[^/]+/)\.(in|out)/)[^/]*$#', $this->dav_name, $matches ) )
else if ( preg_match( '#^((/[^/]+/)\.(in|out)/)[^/]*$#', $this->real_dav_name, $matches ) )
$this->parent_container_type = 'schedule-'. $matches[3]. 'box';
else
$this->parent_container_type = 'collection';
@ -1015,7 +1028,7 @@ EOQRY;
if ( isset($this->principal->{$name}) ) return $this->principal->{$name};
if ( isset($this->collection->{$name}) ) return $this->collection->{$name};
}
// dbg_error_log( 'DAVResource', ':GetProperty: Failed to find property "%s" on "%s".', $name, $this->dav_name );
// dbg_error_log( 'DAVResource', ':GetProperty: Failed to find property "%s" on "%s".', $name, $this->real_dav_name );
}
return $value;
@ -1047,7 +1060,7 @@ EOQRY;
function ResourceProperty( $tag, $prop, &$reply, &$denied ) {
global $c, $session, $request;
// dbg_error_log( 'DAVResource', 'Processing "%s" on "%s".', $tag, $this->dav_name );
// dbg_error_log( 'DAVResource', 'Processing "%s" on "%s".', $tag, $this->real_dav_name );
if ( $reply === null ) $reply = $GLOBALS['reply'];
@ -1061,7 +1074,7 @@ EOQRY;
break;
case 'DAV::href':
$prop->NewElement('href', ConstructURL($this->dav_name) );
$prop->NewElement('href', ConstructURL($this->real_dav_name) );
break;
case 'DAV::getcontenttype':
@ -1254,7 +1267,7 @@ EOQRY;
$reply->NSElement($prop, $tag, $this->dead_properties[$tag] );
}
else {
// dbg_error_log( 'DAVResource', 'Request for unsupported property "%s" of path "%s".', $tag, $this->dav_name );
// dbg_error_log( 'DAVResource', 'Request for unsupported property "%s" of path "%s".', $tag, $this->real_dav_name );
return false;
}
}
@ -1274,7 +1287,7 @@ EOQRY;
function GetPropStat( $properties, &$reply, $props_only = false ) {
global $request;
dbg_error_log('DAVResource',':GetPropStat: propstat for href "%s"', $this->dav_name );
dbg_error_log('DAVResource',':GetPropStat: propstat for href "%s"', $this->real_dav_name );
$prop = new XMLElement('prop');
$denied = array();
@ -1290,7 +1303,7 @@ EOQRY;
$found = $this->principal->PrincipalProperty( $tag, $prop, $reply, $denied );
}
if ( ! $found ) {
// dbg_error_log( 'DAVResource', 'Request for unsupported property "%s" of resource "%s".', $tag, $this->dav_name );
// dbg_error_log( 'DAVResource', 'Request for unsupported property "%s" of resource "%s".', $tag, $this->real_dav_name );
$not_found[] = $reply->Tag($tag);
}
}
@ -1333,7 +1346,7 @@ EOQRY;
function RenderAsXML( $properties, &$reply, $props_only = false ) {
global $session, $c, $request;
dbg_error_log('DAVResource',':RenderAsXML: Resource "%s"', $this->dav_name );
dbg_error_log('DAVResource',':RenderAsXML: Resource "%s"', $this->real_dav_name );
if ( !$this->Exists() ) return null;
@ -1343,7 +1356,7 @@ EOQRY;
}
$elements = $this->GetPropStat( $properties, $reply );
array_unshift( $elements, $reply->href(ConstructURL($this->dav_name)));
array_unshift( $elements, $reply->href(ConstructURL($this->real_dav_name)));
$response = new XMLElement( 'response', $elements );