Under development.

This commit is contained in:
Andrew McMillan 2009-10-26 00:10:18 +13:00
parent 6fee9fcb02
commit 1f5961e1b1

View File

@ -6,9 +6,12 @@
* @subpackage Resource
* @author Andrew McMillan <andrew@mcmillan.net.nz>
* @copyright Morphoss Ltd
* @license http://gnu.org/copyleft/gpl.html GNU GPL v2 or later
* @license http://gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('AwlQuery.php');
/**
* A class for things to do with a DAV Resource
*
@ -56,6 +59,16 @@ class DAVResource
*/
private $_is_principal;
/**
* @var True if this resource is a calendar collection
*/
private $_is_calendar;
/**
* @var True if this resource is an addressbook collection
*/
private $_is_addressbook;
/**
* Constructor
* @param mixed $parameters If null, an empty Resourced is created.
@ -65,10 +78,15 @@ class DAVResource
function __construct( $parameters = null ) {
$this->_is_principal = false;
$this->_is_collection = false;
$this->_is_calendar = false;
$this->_is_addressbook = false;
if ( isset($parameters) && is_object($parameters) ) {
$this->FromRow($parameters);
}
else if ( isset($parameters) && is_array($parameters) ) {
if ( isset($parameters['path']) ) {
$this->FromPath($parameters['path']);
}
}
}
@ -94,6 +112,117 @@ class DAVResource
}
/**
* Initialise from a path
* @param object $inpath The path to populate the resource data from
*/
function FromPath($inpath) {
global $c;
$this->path = rawurldecode($inpath);
/** Allow a path like .../username/calendar.ics to translate into the calendar URL */
if ( preg_match( '#^(/[^/]+/[^/]+).ics$#', $this->path, $matches ) ) {
$this->path = $matches[1]. '/';
}
/** strip doubled slashes */
if ( strstr($this->path,'//') ) $this->path = preg_replace( '#//+#', '/', $this->path);
$this->FindCollection();
}
/**
* Find the collection associated with this resource.
*/
function FindCollection() {
/**
* RFC4918, 8.3: Identifiers for collections SHOULD end in '/'
* - also discussed at more length in 5.2
*
* So we look for a collection which matches one of the following URLs:
* - The exact request.
* - If the exact request, doesn't end in '/', then the request URL with a '/' appended
* - The request URL truncated to the last '/'
* 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"
*/
$this->collection = (object) array(
'collection_id' => -1,
'type' => 'unknown',
'is_calendar' => false, 'is_principal' => false, 'is_addressbook' => false, 'resourcetypes' => '<DAV::collection/>',
);
$sql = "SELECT * FROM collection WHERE dav_name = :raw_path ";
$params = array( ':raw_path' => $this->path);
if ( !preg_match( '#/$#', $this->path ) ) {
$sql .= ' OR dav_name = :up_to_slash OR dav_name = :plus_slash'
$params[':up_to_slash'] = preg_replace( '#[^/]*$#', '', $this->path);
$params[':plus_slash'] = $this->path."/";
}
$sql .= "ORDER BY LENGTH(dav_name) DESC LIMIT 1";
$qry = new AwlQuery( $sql, $params );
if ( $qry->Exec('caldav') && $qry->rows == 1 && ($row = $qry->Fetch()) ) {
$this->collection = $row;
$this->collection = $row;
if ( $row->is_calendar == 't' ) $this->collection->type = 'calendar';
else if ( $row->is_addressbook == 't' ) $this->collection->type = 'addressbook';
else $this->collection->type = 'collection';
}
else if ( preg_match( '#^((/[^/]+/)\.(in|out)/)[^/]*$#', $this->path, $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 );
$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 )
EOSQL;
$qry = new AwlQuery( $sql, $params );
$qry->Exec('caldav');
dbg_error_log( "caldav", "Created new collection as '$displayname'." );
$qry = new AwlQuery( "SELECT * FROM collection WHERE user_no = :user_no AND dav_name = :dav_name", $params );
if ( $qry->Exec('caldav') && $qry->rows == 1 && ($row = $qry->Fetch()) ) {
$this->collection = $row;
$this->collection->type = $this->collection_type;
}
}
else if ( preg_match( '#^((/[^/]+/)calendar-proxy-(read|write))/?[^/]*$#', $this->path, $matches ) ) {
$this->collection_type = 'proxy';
$this->_is_proxy_request = true;
$this->proxy_type = $matches[3];
$this->collection_path = $matches[1].'/';
}
else if ( $this->options['allow_by_email'] && preg_match( '#^/(\S+@\S+[.]\S+)/?$#', $this->path) ) {
/** @TODO: we should deprecate this now that Evolution 2.27 can do scheduling extensions */
$this->collection_id = -1;
$this->collection_type = 'email';
$this->collection_path = $this->path;
$this->_is_principal = true;
}
else if ( preg_match( '#^(/[^/]+)/?$#', $this->path, $matches) || preg_match( '#^(/principals/[^/]+/[^/]+)/?$#', $this->path, $matches) ) {
$this->collection_id = -1;
$this->collection_path = $matches[1].'/'; // Enforce trailling '/'
$this->collection_type = 'principal';
$this->_is_principal = true;
if ( preg_match( '#^(/principals/[^/]+/[^/]+)/?$#', $this->path, $matches) ) {
// Force a depth of 0 on these, which are at the wrong URL.
$this->depth = 0;
}
}
else if ( $this->path == '/' ) {
$this->collection_id = -1;
$this->collection_path = '/';
$this->collection_type = 'root';
}
}
/**
* Return general server-related properties for this URL
*/
@ -107,11 +236,11 @@ class DAVResource
switch( $tag ) {
case 'DAV::href':
$prop->NewElement('href', ConstructURL($this->dav_name) );
break;
break;
case 'DAV::getcontenttype':
$prop->NewElement('getcontenttype', $this->contenttype );
break;
break;
case 'DAV::resourcetype':
$prop->NewElement('resourcetype', $this->resourcetype );
@ -139,7 +268,7 @@ class DAVResource
// // After a careful reading of RFC3744 we see that this must be the principal-URL of the owner
// $reply->DAVElement( $prop, 'owner', $reply->href( $this->principal_url) ) );
// break;
// Empty tag responses.
case 'DAV::alternate-URI-set':
case 'DAV::getcontentlength':
@ -226,7 +355,7 @@ class DAVResource
}
return $elements;
}
/**
* Render XML for this resource