From ee1ea4c9502b36af7cb1da4493d8be3781b09d5e Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Sat, 3 Nov 2007 10:14:05 +1300 Subject: [PATCH] Refactoring of the principal into an object class. --- inc/CalDAVPrincipal.php | 153 ++++++++++++++++++++++++++++++++ inc/CalDAVRequest.php | 22 ++--- inc/caldav-PROPFIND.php | 4 +- inc/caldav-REPORT-principal.php | 3 - rscds.webprj | 1 + 5 files changed, 168 insertions(+), 15 deletions(-) create mode 100644 inc/CalDAVPrincipal.php diff --git a/inc/CalDAVPrincipal.php b/inc/CalDAVPrincipal.php new file mode 100644 index 00000000..3764d205 --- /dev/null +++ b/inc/CalDAVPrincipal.php @@ -0,0 +1,153 @@ + +* @copyright Catalyst .Net Ltd +* @license http://gnu.org/copyleft/gpl.html GNU GPL v2 +*/ + +/** +* @var $_CalDAVPrincipalCache +* A global variable holding a cache of any DAV Principals which are +* read from the DB. +*/ +$_CalDAVPrincipalCache = (object) array( 'p' => array(), 'u' => array() ); + + +/** +* A class for things to do with a DAV Principal +* +* @package davical +*/ +class CalDAVPrincipal +{ + /** + * @var The home URL of the principal + */ + var $url; + + /** + * @var RFC4791: Identifies the URL(s) of any WebDAV collections that contain + * calendar collections owned by the associated principal resource. + */ + var $calendar_home_set; + + /** + * @var draft-desruisseaux-caldav-sched-03: Identify the URL of the scheduling + * Inbox collection owned by the associated principal resource. + */ + var $schedule_inbox_url; + + /** + * @var draft-desruisseaux-caldav-sched-03: Identify the URL of the scheduling + * Outbox collection owned by the associated principal resource. + */ + var $schedule_outbox_url; + + /** + * Constructor + * @param mixed $parameters If null, an empty Principal is created. If it + * is an integer then that ID is read (if possible). If it is + * an array then the Principal matching the supplied elements is read. + * + * @return boolean Whether we actually read data from the DB to initialise the record. + */ + function CalDAVPrincipal( $parameters = null ) { + global $session, $c; + + if ( $parameters == null ) return false; + if ( is_int($parameters) ) { + dbg_error_log( "principal", "Principal: %d", $parameters ); + $usr = getUserByID($parameters); + } + else if ( is_array($parameters) ) { + if ( isset($parameters['username']) ) { + $usr = getUserByName($parameters['username']); + } + else if ( isset($parameters['user_no']) ) { + $usr = getUserByID($parameters['user_no']); + } + else if ( isset($parameters['path']) ) { + dbg_error_log( "principal", "Finding Principal from path: '%s'", $parameters['path'] ); + if ( $username = $this->UsernameFromPath($parameters['path'],$parameters['options']) ) { + $usr = getUserByName($username); + if ( isset($parameters['options']['allow_by_email']) && is_object($usr) && preg_match( '#/(\S+@\S+[.]\S+)$#', $parameters['path']) ) { + $this->by_email = true; + } + } + } + else if ( isset($parameters['principal-property-search']) ) { + $usr = $this->PropertySearch($parameters['principal-property-search']); + } + } + if ( !isset($usr) || !is_object($usr) ) return false; + + $this->InitialiseRecord($usr); + } + + + /** + * Initialise the Principal object from a $usr record from the DB. + * @param object $usr The usr record from the DB. + */ + function InitialiseRecord($usr) { + global $c; + foreach( $usr AS $k => $v ) { + $this->{$k} = $v; + } + + $this->url = sprintf( "%s/~%d/", $c->protocol_server_port_script, $this->user_no); + $this->calendar_home_set = sprintf( "%s/%s/", $c->protocol_server_port_script, $this->username); + $this->schedule_inbox_url = sprintf( "%s.inbox/", $this->url); + $this->schedule_outbox_url = sprintf( "%s.outbox/", $this->url); + + dbg_error_log( "principal", "User: %s (%d) URL: %s, Home: %s", $this->username, $this->user_no, $this->url, $this->calendar_home_set ); + } + + + /** + * Work out the username, based on elements of the path. + * @param string $path The path to be used. + * @param array $options The request options, controlling whether e-mail paths are allowed. + */ + function UsernameFromPath( $path, $options = null ) { + global $session, $c; + + if ( $path == '/' || $path == '' ) { + dbg_error_log( "principal", "No useful path split possible" ); + return false; + } + + $path_split = explode('/', $path ); + @dbg_error_log( "principal", "Path split into at least /// %s /// %s /// %s", $path_split[1], $path_split[2], $path_split[3] ); + + if ( substr($path,0,1) == '~' ) { + // URL is for a principal, by ID + $user_no = intval(substr($path,1)); + $user = getUserByID($user_no); + $username = $user->username; + } + else { + $username = $path_split[1]; + + if ( isset($options['allow_by_email']) && preg_match( '#/(\S+@\S+[.]\S+)$#', $path, $matches) ) { + $email = $matches[1]; + $qry = new PgQuery("SELECT user_no FROM usr WHERE email = ?;", $email ); + if ( $qry->Exec("principal") && $user = $qry->Fetch() ) { + $user_no = $user->user_no; + $username = $user->username; + } + } + elseif( $user = getUserByName( $username, 'caldav') ) { + $user_no = $user->user_no; + } + } + return $username; + } + + + +} \ No newline at end of file diff --git a/inc/CalDAVRequest.php b/inc/CalDAVRequest.php index 749bd2f7..f858ac5d 100644 --- a/inc/CalDAVRequest.php +++ b/inc/CalDAVRequest.php @@ -7,21 +7,22 @@ * - Utility functions which we can use to decide whether this * is a permitted activity for this user. * -* @package rscds -* @subpackage CalDAVRequest +* @package davical +* @subpackage Request * @author Andrew McMillan * @copyright Catalyst .Net Ltd * @license http://gnu.org/copyleft/gpl.html GNU GPL v2 */ require_once("XMLElement.php"); +require_once("CalDAVPrincipal.php"); define('DEPTH_INFINITY', 9999); /** * A class for collecting things to do with this request. * -* @package rscds +* @package davical */ class CalDAVRequest { @@ -150,15 +151,17 @@ class CalDAVRequest } } + $this->user_no = $session->user_no; + $this->username = $session->username; + /** * Extract the user whom we are accessing - * TODO: Replace this by something which properly sets up the DAV 'principal' */ - $this->UserFromPath(); - $this->principal->url = sprintf( "%s/%s/", $c->protocol_server_port_script, $this->principal->username); - $this->principal->calendar_home_set = sprintf( "%s", $this->principal->url); - $this->principal->schedule_inbox_url = sprintf( "%s.inbox/", $this->principal->url); - $this->principal->schedule_outbox_url = sprintf( "%s.outbox/", $this->principal->url); + $this->principal = new CalDAVPrincipal( array( "path" => $this->path, "options" => $this->options ) ); + if ( isset($this->principal->user_no) ) $this->user_no = $this->principal->user_no; + if ( isset($this->principal->username)) $this->username = $this->principal->username; + if ( isset($this->principal->by_email)) $this->by_email = true; + /** * Evaluate our permissions for accessing the target @@ -584,4 +587,3 @@ class CalDAVRequest } } -?> \ No newline at end of file diff --git a/inc/caldav-PROPFIND.php b/inc/caldav-PROPFIND.php index cf61d0c8..da760631 100644 --- a/inc/caldav-PROPFIND.php +++ b/inc/caldav-PROPFIND.php @@ -77,8 +77,8 @@ foreach( $request->xml_tags AS $k => $v ) { * Handled calendar-schedule properties */ case 'CALENDAR-USER-ADDRESS-SET': /** CalDAV+s: slightly supported */ - case 'SCHEDULE-INBOX-URL': /** CalDAV+s: not supported */ - case 'SCHEDULE-OUTBOX-URL': /** CalDAV+s: not supported */ +// case 'SCHEDULE-INBOX-URL': /** CalDAV+s: not supported */ +// case 'SCHEDULE-OUTBOX-URL': /** CalDAV+s: not supported */ $attribute_list[$tag] = 1; dbg_error_log( "PROPFIND", "Adding %s attribute '%s'", $namespace, $tag ); break; diff --git a/inc/caldav-REPORT-principal.php b/inc/caldav-REPORT-principal.php index 0f9f11cb..4cbf9d6f 100644 --- a/inc/caldav-REPORT-principal.php +++ b/inc/caldav-REPORT-principal.php @@ -22,9 +22,6 @@ function principal_to_xml( $properties, $item ) { $denied = array(); foreach( $properties AS $k => $v ) { switch( $v ) { -// case 'DAV::GETCONTENTTYPE': -// $prop->NewElement("getcontenttype", "text/x-vcard" ); -// break; case 'DAV::RESOURCETYPE': $prop->NewElement("resourcetype", new XMLElement("principal") ); break; diff --git a/rscds.webprj b/rscds.webprj index 696fd70a..96261753 100644 --- a/rscds.webprj +++ b/rscds.webprj @@ -242,5 +242,6 @@ +