DAViCal
Loading...
Searching...
No Matches
caldav-REPORT-principal.php
1<?php
2
3if ( $request->depth > 0 ) {
4 $request->DoResponse( 400, 'The principal-property-search REPORT is only defined for Depth "0".' );
5}
6
10$searches = $xmltree->GetPath('/DAV::principal-property-search/DAV::property-search');
11dbg_log_array( "principal", "SEARCH", $searches, true );
12
13$clause_joiner = " AND ";
14$CS_search_test = $xmltree->GetAttribute('test');
15if ( isset($CS_search_test) && $CS_search_test == 'anyof' ) {
16 $clause_joiner = " OR ";
17}
18
19# Calendar on macOS searches for the principal type as an attribute.
20$principal_type = $xmltree->GetAttribute('type');
21
22$params = array();
23$typewhere = "";
24$where = "";
25$join = "";
26
27dbg_error_log("SEARCH", "type: '%s'", $principal_type );
28
29// This is ugly, but macOS specifies the calendar type as an attribute
30if (isset($principal_type)) {
31 $typewhere = 'principal_type.label = :principal_type';
32 $params[':principal_type'] = $principal_type;
33
34 $join = 'LEFT JOIN principal_type ON (type_id = principal_type_id)';
35}
36
37foreach( $searches AS $k => $search ) {
38 $qry_props = $search->GetPath('/DAV::property-search/DAV::prop/*'); // There may be many
39 $match = $search->GetPath('/DAV::property-search/DAV::match'); // There may only be one
40 if ( empty($match) or !is_object($match[0]) ) {
41 dbg_error_log("ERROR", "Unable to extract a match clause from '%s'", $search->RenderContent() );
42 continue;
43 }
44 dbg_log_array( "principal", "MATCH", $match, true );
45 $match = $match[0]->GetContent();
46 $subwhere = "";
47 foreach( $qry_props AS $k1 => $v1 ) {
48 if ( $subwhere != "" ) $subwhere .= " OR ";
49 switch( $v1->GetNSTag() ) {
50 case 'DAV::displayname':
51 $subwhere .= ' displayname ILIKE :displayname_match ';
52 $params[':displayname_match'] = '%'.$match.'%';
53 break;
54
55 case 'urn:ietf:params:xml:ns:caldav:calendar-user-address-set':
56 $match = preg_replace('{^.*/caldav.php/([^/]+)(/.*)?$}', '\\1', $match);
57 $match = preg_replace('{^mailto:}', '', $match);
58 $subwhere .= ' (email ILIKE :user_address_match OR username ILIKE :user_address_match) ';
59 $params[':user_address_match'] = '%'.$match.'%';
60 break;
61
62 case 'urn:ietf:params:xml:ns:caldav:calendar-home-set':
63 $match = preg_replace('{^.*/caldav.php}', '', $match);
64 $subwhere .= ' dav_name LIKE :calendar_home_match ';
65 $params[':calendar_home_match'] = $match.'%';
66 break;
67
68 default:
73 dbg_error_log("principal", "Unhandled tag '%s' to match '%s'\n", $v1->GetNSTag(), $match );
74 }
75 }
76 if ( $subwhere != "" ) {
77 $where .= sprintf( "%s(%s)", ($where == "" ? "" : $clause_joiner), $subwhere );
78 }
79}
80
81if ( $where != "" && $typewhere != "" ) {
82 $where = "WHERE $typewhere AND $where";
83} elseif ( $where != "" ) {
84 $where = "WHERE $where";
85} elseif ( $typewhere != "" ) {
86 $where = "WHERE $typewhere";
87}
88
89$sql = "SELECT * FROM dav_principal $join $where ORDER BY principal_id LIMIT 100";
90$qry = new AwlQuery($sql, $params);
91
92
93$get_props = $xmltree->GetPath('/DAV::principal-property-search/DAV::prop/*');
94$properties = array();
95foreach( $get_props AS $k1 => $v1 ) {
96 $properties[] = $v1->GetNSTag();
97}
98
99$responses = array();
100if ( $qry->Exec("REPORT",__LINE__,__FILE__) && $qry->rows() > 0 ) {
101 while( $row = $qry->Fetch() ) {
102 $principal = new DAVResource($row);
103 $responses[] = $principal->RenderAsXML( $properties, $reply );
104 }
105}
106
107$multistatus = new XMLElement( "multistatus", $responses, $reply->GetXmlNsArray() );
108
109$request->XMLResponse( 207, $multistatus );