diff --git a/inc/caldav-REPORT-principal.php b/inc/caldav-REPORT-principal.php
new file mode 100644
index 00000000..2c174e01
--- /dev/null
+++ b/inc/caldav-REPORT-principal.php
@@ -0,0 +1,118 @@
+username );
+
+ $this_url = $c->protocol_server_port_script . $request->dav_name;
+ $principal_url = sprintf( "%s/%s/", $c->protocol_server_port_script, $item->username);
+ $home_calendar = sprintf( "%s/%s/%s/", $c->protocol_server_port_script, $item->username, $c->home_calendar_name);
+ $prop = new XMLElement("prop");
+ $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", false, array("xmlns" => "DAV:")) );
+ break;
+ case 'DAV::DISPLAYNAME':
+ $prop->NewElement("displayname", $item->username );
+ break;
+ case 'DAV::PRINCIPAL-URL':
+ $prop->NewElement("principal-url", $principal_url );
+ break;
+ case 'DAV::ALTERNATE-URI':
+ $prop->NewElement("alternate-uri" );
+ break;
+ case 'DAV::GROUP-MEMBER-SET':
+ $prop->NewElement("group-member-set" );
+ break;
+ case 'URN:IETF:PARAMS:XML:NS:CALDAV:CALENDAR-HOME-SET':
+ $prop->NewElement("calendar-home-set", $home_calendar, array("xmlns" => "urn:ietf:params:xml:ns:caldav") );
+ break;
+ case 'SOME-DENIED-PROPERTY': /** TODO: indicating the style for future expansion */
+ $denied[] = $v;
+ break;
+ default:
+ dbg_error_log( 'REPORT', "Request for unsupported property '%s' of principal.", $item->username );
+ break;
+ }
+ }
+ $status = new XMLElement("status", "HTTP/1.1 200 OK" );
+
+ $propstat = new XMLElement( "propstat", array( $prop, $status) );
+ $href = new XMLElement("href", $url );
+
+ $elements = array($href,$propstat);
+
+ if ( count($denied) > 0 ) {
+ $status = new XMLElement("status", "HTTP/1.1 403 Forbidden" );
+ $noprop = new XMLElement("prop");
+ foreach( $denied AS $k => $v ) {
+ $noprop->NewElement( strtolower($v) );
+ }
+ $elements[] = new XMLElement( "propstat", array( $noprop, $status) );
+ }
+
+ $response = new XMLElement( "response", $elements );
+
+ return $response;
+}
+
+/**
+ * Build the array of properties to include in the report output
+ */
+$searches = $xmltree->GetPath('/DAV::PRINCIPAL-PROPERTY-SEARCH/DAV::PROPERTY-SEARCH');
+dbg_log_array( "principal", "SEARCH", $searches, true );
+
+$where = "";
+foreach( $searches AS $k => $search ) {
+ $qry_props = $search->GetPath('/DAV::PROPERTY-SEARCH/DAV::PROP/*');
+ $match = $search->GetPath('/DAV::PROPERTY-SEARCH/DAV::MATCH');
+ dbg_log_array( "principal", "MATCH", $match, true );
+ $match = qpg($match[0]->GetContent());
+ $subwhere = "";
+ foreach( $qry_props AS $k1 => $v1 ) {
+ if ( $subwhere != "" ) $subwhere .= " OR ";
+ switch( $v1->GetTag() ) {
+ case 'DAV::DISPLAYNAME':
+ $subwhere .= "username = ".$match;
+ break;
+ default:
+ printf("Unhandled tag '%s'\n", $v1->GetTag() );
+ }
+ }
+ $where .= sprintf( "%s(%s)", ($where == "" ? "" : " AND "), $subwhere );
+}
+
+$get_props = $xmltree->GetPath('/DAV::PRINCIPAL-PROPERTY-SEARCH/DAV::PROP/*');
+$properties = array();
+foreach( $get_props AS $k1 => $v1 ) {
+ $properties[] = $v1->GetTag();
+}
+$sql = "SELECT * FROM usr WHERE $where";
+$qry = new PgQuery($sql);
+
+
+if ( $qry->Exec("REPORT",__LINE__,__FILE__) && $qry->rows > 0 ) {
+ while( $principal_object = $qry->Fetch() ) {
+ $responses[] = principal_to_xml( $properties, $principal_object );
+ }
+}
+
+$multistatus = new XMLElement( "multistatus", $responses, array('xmlns'=>'DAV:') );
+
+$request->XMLResponse( 207, $multistatus );
diff --git a/inc/caldav-REPORT.php b/inc/caldav-REPORT.php
index 26dcdad8..d2cd9fc9 100644
--- a/inc/caldav-REPORT.php
+++ b/inc/caldav-REPORT.php
@@ -37,6 +37,10 @@ if ( $xmltree->GetTag() == "URN:IETF:PARAMS:XML:NS:CALDAV:FREE-BUSY-QUERY" ) {
include("caldav-REPORT-freebusy.php");
exit; // Not that the above include should return anyway
}
+if ( $xmltree->GetTag() == "DAV::PRINCIPAL-PROPERTY-SEARCH" ) {
+ include("caldav-REPORT-principal.php");
+ exit; // Not that the above include should return anyway
+}
// Must have read privilege for all other reports
if ( ! ($request->AllowedTo('read') ) ) {
diff --git a/testing/tests/regression-suite/860-Spec-REPORT-principal.result b/testing/tests/regression-suite/860-Spec-REPORT-principal.result
new file mode 100644
index 00000000..19fcee2e
--- /dev/null
+++ b/testing/tests/regression-suite/860-Spec-REPORT-principal.result
@@ -0,0 +1,19 @@
+HTTP/1.1 207 Multi-Status
+Date: Dow, 01 Jan 2000 00:00:00 GMT
+ETag: "c345629a9689adce5411818c3c29aa43"
+Content-Length: 358
+Content-Type: text/xml; charset="utf-8"
+
+
+
+
+
+
+
+ http://mycaldav/caldav.php/user1/home/
+ user1
+
+ HTTP/1.1 200 OK
+
+
+
diff --git a/testing/tests/regression-suite/860-Spec-REPORT-principal.test b/testing/tests/regression-suite/860-Spec-REPORT-principal.test
index 7817db61..e3110d59 100644
--- a/testing/tests/regression-suite/860-Spec-REPORT-principal.test
+++ b/testing/tests/regression-suite/860-Spec-REPORT-principal.test
@@ -20,7 +20,7 @@ BEGINDATA
- karora
+ user1