diff --git a/inc/caldav-REPORT-principal-match.php b/inc/caldav-REPORT-principal-match.php
new file mode 100644
index 00000000..e86d4918
--- /dev/null
+++ b/inc/caldav-REPORT-principal-match.php
@@ -0,0 +1,57 @@
+NeedPrivilege(array('DAV::read','DAV::read-current-user-privilege-set','DAV::read-acl'));
+
+/**
+ * Build the array of properties to include in the report output
+ */
+$match = $xmltree->GetPath('/DAV::principal-match/DAV::self');
+if ( count ( $match ) == 0 ) {
+ $match = $xmltree->GetPath('/DAV::principal-match/DAV::principal-property');
+ $match_self = false;
+}
+else {
+ $match_self = true;
+}
+if ( count ( $match ) == 0 ) {
+ $request->DoResponse( 400, 'Badly formed principal-match REPORT request.' );
+}
+
+$target = new DAVResource($request->path);
+
+$where = '';
+if ( $match_self ) {
+ // Technically we should restrict to finding the principal somewhere *below* the
+ // request path in the hierarchy, but we'll quietly ignore that because it's
+ // unlikely that anything would actually be wanting that behaviour.
+ $where .= 'username = :username';
+ $params = array(':username' => $session->username );
+}
+else {
+ $params = array(':dav_name'=>'/'.$request->principal->GetProperty('username').'/');
+}
+
+if ( $where != "" ) $where = "WHERE $where";
+$sql = "SELECT * FROM dav_principal $where ORDER BY principal_id LIMIT 100";
+$qry = new AwlQuery($sql, $params);
+
+
+$get_props = $xmltree->GetPath('/DAV::principal-match/DAV::prop/*');
+$properties = array();
+foreach( $get_props AS $k1 => $v1 ) {
+ $properties[] = $v1->GetTag();
+}
+
+if ( $qry->Exec("REPORT",__LINE__,__FILE__) && $qry->rows() > 0 ) {
+ while( $row = $qry->Fetch() ) {
+ $principal = new DAVResource($row);
+ $responses[] = $principal->RenderAsXML( $properties, $reply );
+ }
+}
+
+$multistatus = new XMLElement( "multistatus", $responses, $reply->GetXmlNsArray() );
+
+$request->XMLResponse( 207, $multistatus );
\ No newline at end of file
diff --git a/inc/caldav-REPORT.php b/inc/caldav-REPORT.php
index 49c7812c..e2a6d633 100644
--- a/inc/caldav-REPORT.php
+++ b/inc/caldav-REPORT.php
@@ -66,6 +66,9 @@ switch( $xmltree->GetTag() ) {
case 'DAV::expand-property':
include("caldav-REPORT-expand-property.php");
exit; // Not that it should return anyway.
+ case 'DAV::principal-match':
+ include("caldav-REPORT-principal-match.php");
+ exit; // Not that it should return anyway.
}
diff --git a/testing/tests/regression-suite/0970-REPORT-principal-match-self.result b/testing/tests/regression-suite/0970-REPORT-principal-match-self.result
new file mode 100644
index 00000000..f478cb9a
--- /dev/null
+++ b/testing/tests/regression-suite/0970-REPORT-principal-match-self.result
@@ -0,0 +1,22 @@
+HTTP/1.1 207 Multi-Status
+Date: Dow, 01 Jan 2000 00:00:00 GMT
+DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule
+DAV: extended-mkcol, calendar-proxy, bind, addressbook
+ETag: "7656abee424b0f6763c3851c78613769"
+Content-Length: 362
+Content-Type: text/xml; charset="utf-8"
+
+
+
+
+ /caldav.php/user1/
+
+
+
+ /caldav.php/user1/
+
+
+ HTTP/1.1 200 OK
+
+
+
diff --git a/testing/tests/regression-suite/0970-REPORT-principal-match-self.test b/testing/tests/regression-suite/0970-REPORT-principal-match-self.test
new file mode 100644
index 00000000..0cea589f
--- /dev/null
+++ b/testing/tests/regression-suite/0970-REPORT-principal-match-self.test
@@ -0,0 +1,23 @@
+#
+# principal-match REPORT on self as user1
+#
+TYPE=REPORT
+URL=http://mycaldav/caldav.php/
+AUTH=user1:user1
+
+HEADER=User-Agent: DAViCal Testing
+HEADER=Accept: text/xml
+HEADER=Content-Type: text/xml; charset=utf-8
+HEADER=Depth: 0
+HEAD
+
+BEGINDATA
+
+
+
+
+
+
+
+ENDDATA
+
diff --git a/testing/tests/regression-suite/0971-REPORT-principal-match-prop.result b/testing/tests/regression-suite/0971-REPORT-principal-match-prop.result
new file mode 100644
index 00000000..7db3fe85
--- /dev/null
+++ b/testing/tests/regression-suite/0971-REPORT-principal-match-prop.result
@@ -0,0 +1,83 @@
+HTTP/1.1 207 Multi-Status
+Date: Dow, 01 Jan 2000 00:00:00 GMT
+DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule
+DAV: extended-mkcol, calendar-proxy, bind, addressbook
+ETag: "c6026dd8dbea9512cd6e210a06f30c4a"
+Content-Length: 1795
+Content-Type: text/xml; charset="utf-8"
+
+
+
+
+ /caldav.php/user1/
+
+
+
+ /caldav.php/user1/
+
+ User 1
+
+ HTTP/1.1 200 OK
+
+
+
+ /caldav.php/user2/
+
+
+
+ /caldav.php/user2/
+
+ User 2
+
+ HTTP/1.1 200 OK
+
+
+
+ /caldav.php/user3/
+
+
+
+ /caldav.php/user3/
+
+ User 3
+
+ HTTP/1.1 200 OK
+
+
+
+ /caldav.php/user4/
+
+
+
+ /caldav.php/user4/
+
+ User 4
+
+ HTTP/1.1 200 OK
+
+
+
+ /caldav.php/user5/
+
+
+
+ /caldav.php/user5/
+
+ User 5
+
+ HTTP/1.1 200 OK
+
+
+
+ /caldav.php/User%20Six/
+
+
+
+ /caldav.php/User%20Six/
+
+ User 6
+
+ HTTP/1.1 200 OK
+
+
+
diff --git a/testing/tests/regression-suite/0971-REPORT-principal-match-prop.test b/testing/tests/regression-suite/0971-REPORT-principal-match-prop.test
new file mode 100644
index 00000000..2e509312
--- /dev/null
+++ b/testing/tests/regression-suite/0971-REPORT-principal-match-prop.test
@@ -0,0 +1,29 @@
+#
+# principal-match REPORT on a principal-property (displayname)
+#
+TYPE=REPORT
+URL=http://mycaldav/caldav.php/
+AUTH=user1:user1
+
+HEADER=User-Agent: DAViCal Testing
+HEADER=Accept: text/xml
+HEADER=Content-Type: text/xml; charset=utf-8
+HEADER=Depth: 0
+HEAD
+
+BEGINDATA
+
+
+
+
+
+
+ User
+
+
+
+
+
+
+ENDDATA
+