1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10:
11: dbg_error_log("REPORT", "method handler");
12:
13: require_once("XMLDocument.php");
14: require_once('DAVResource.php');
15:
16: require_once('RRule.php');
17:
18: if ( ! ini_get('open_basedir') && (isset($c->dbg['ALL']) || (isset($c->dbg['report']) && $c->dbg['report'])) ) {
19: $fh = fopen('/var/log/davical/REPORT.debug','w');
20: if ( $fh ) {
21: fwrite($fh,$request->raw_post);
22: fclose($fh);
23: }
24: }
25:
26: if ( !isset($request->xml_tags) ) {
27: $request->DoResponse( 406, translate("REPORT body contains no XML data!") );
28: }
29: $position = 0;
30: $xmltree = BuildXMLTree( $request->xml_tags, $position);
31: if ( !is_object($xmltree) ) {
32: $request->DoResponse( 406, translate("REPORT body is not valid XML data!") );
33: }
34:
35: $target = new DAVResource($request->path);
36:
37: if ( $xmltree->GetNSTag() != 'DAV::principal-property-search'
38: && $xmltree->GetNSTag() != 'DAV::principal-property-search-set' ) {
39: $target->NeedPrivilege( array('DAV::read', 'urn:ietf:params:xml:ns:caldav:read-free-busy'), true );
40: }
41:
42: require_once("vCalendar.php");
43:
44: $reportnum = -1;
45: $report = array();
46: $denied = array();
47: $unsupported = array();
48: if ( isset($prop_filter) ) unset($prop_filter);
49:
50: if ( $xmltree->GetNSTag() == 'urn:ietf:params:xml:ns:caldav:free-busy-query' ) {
51: include("caldav-REPORT-freebusy.php");
52: exit;
53: }
54:
55: $reply = new XMLDocument( array( "DAV:" => "" ) );
56: switch( $xmltree->GetNSTag() ) {
57: case 'DAV::principal-property-search':
58: include("caldav-REPORT-principal.php");
59: exit;
60: case 'DAV::principal-search-property-set':
61: include("caldav-REPORT-pps-set.php");
62: exit;
63: case 'DAV::sync-collection':
64: if ( $target->IsExternal() ) {
65: require_once("external-fetch.php");
66: update_external ( $target );
67: }
68: include("caldav-REPORT-sync-collection.php");
69: exit;
70: case 'DAV::expand-property':
71: if ( $target->IsExternal() ) {
72: require_once("external-fetch.php");
73: update_external ( $target );
74: }
75: include("caldav-REPORT-expand-property.php");
76: exit;
77: case 'DAV::principal-match':
78: include("caldav-REPORT-principal-match.php");
79: exit;
80: }
81:
82: 83: 84: 85:
86: function check_for_expansion( $calendar_data_node ) {
87: global $need_expansion, $expand_range_start, $expand_range_end, $expand_as_floating;
88:
89: if ( !class_exists('DateTime') ) return;
90:
91: $expansion = $calendar_data_node->GetElements('urn:ietf:params:xml:ns:caldav:expand');
92: if ( isset($expansion[0]) ) {
93: $need_expansion = true;
94: $expand_range_start = $expansion[0]->GetAttribute('start');
95: $expand_range_end = $expansion[0]->GetAttribute('end');
96: $expand_as_floating = $expansion[0]->GetAttribute('floating');
97: if ( isset($expand_range_start) ) $expand_range_start = new RepeatRuleDateTime($expand_range_start);
98: if ( isset($expand_range_end) ) $expand_range_end = new RepeatRuleDateTime($expand_range_end);
99: if ( isset($expand_as_floating) && $expand_as_floating == "yes" )
100: $expand_as_floating = true;
101: else
102: $expand_as_floating = false;
103: }
104: }
105:
106:
107: 108: 109: 110: 111: 112: 113: 114:
115: function component_to_xml( $properties, $item ) {
116: global $session, $c, $request, $reply;
117:
118: dbg_error_log("REPORT","Building XML Response for item '%s'", $item->dav_name );
119:
120: $denied = array();
121: $unsupported = array();
122: $caldav_data = $item->caldav_data;
123: $displayname = preg_replace( '{^.*/}', '', $item->dav_name );
124: $type = 'unknown';
125: $contenttype = 'text/plain';
126: switch( strtoupper($item->caldav_type) ) {
127: case 'VJOURNAL':
128: case 'VEVENT':
129: case 'VTODO':
130: $displayname = $item->summary;
131: $type = 'calendar';
132: $contenttype = 'text/calendar';
133: if ( isset($properties['urn:ietf:params:xml:ns:caldav:calendar-data']) || isset($properties['DAV::displayname']) ) {
134: if ( !$request->AllowedTo('all') && $session->user_no != $item->user_no ) {
135:
136: if ( $item->class == 'CONFIDENTIAL' || !$request->AllowedTo('read') ) {
137: dbg_error_log("REPORT","Anonymising confidential event for: %s", $item->dav_name );
138: $vcal = new vCalendar( $caldav_data );
139: $caldav_data = $vcal->Confidential()->Render();
140: $displayname = translate('Busy');
141: }
142: }
143: }
144:
145: if ( isset($c->hide_alarm) && $c->hide_alarm ) {
146: $dav_resource = new DAVResource($item->dav_name);
147: if ( isset($properties['urn:ietf:params:xml:ns:caldav:calendar-data']) && !$dav_resource->HavePrivilegeTo('write') ) {
148: dbg_error_log("REPORT","Stripping event alarms for: %s", $item->dav_name );
149: $vcal = new vCalendar($caldav_data);
150: $vcal->ClearComponents('VALARM');
151: $caldav_data = $vcal->Render();
152: }
153: }
154: break;
155:
156: case 'VCARD':
157: $displayname = $item->fn;
158: $type = 'vcard';
159: $contenttype = 'text/vcard';
160: break;
161: }
162:
163: $url = ConstructURL($item->dav_name);
164:
165: $prop = new XMLElement("prop");
166: $need_resource = false;
167: foreach( $properties AS $full_tag => $v ) {
168: $base_tag = preg_replace('{^.*:}', '', $full_tag );
169: switch( $full_tag ) {
170: case 'DAV::getcontentlength':
171: $contentlength = strlen($caldav_data);
172: $prop->NewElement($base_tag, $contentlength );
173: break;
174: case 'DAV::getlastmodified':
175: $prop->NewElement($base_tag, ISODateToHTTPDate($item->modified) );
176: break;
177: case 'urn:ietf:params:xml:ns:caldav:calendar-data':
178: if ( $type == 'calendar' ) $reply->CalDAVElement($prop, $base_tag, $caldav_data );
179: else $unsupported[] = $base_tag;
180: break;
181: case 'urn:ietf:params:xml:ns:carddav:address-data':
182: if ( $type == 'vcard' ) $reply->CardDAVElement($prop, $base_tag, $caldav_data );
183: else $unsupported[] = $base_tag;
184: break;
185: case 'DAV::getcontenttype':
186: $prop->NewElement($base_tag, $contenttype );
187: break;
188: case 'DAV::current-user-principal':
189: $prop->NewElement("current-user-principal", $request->current_user_principal_xml);
190: break;
191: case 'DAV::displayname':
192: $prop->NewElement($base_tag, $displayname );
193: break;
194: case 'DAV::resourcetype':
195: $prop->NewElement($base_tag);
196: break;
197: case 'DAV::getetag':
198: $prop->NewElement($base_tag, '"'.$item->dav_etag.'"' );
199: break;
200: case '"current-user-privilege-set"':
201: $prop->NewElement($base_tag, privileges($request->permissions) );
202: break;
203: default:
204:
205: $need_resource = true;
206: }
207: if ( $need_resource ) break;
208: }
209: $href = new XMLElement("href", $url );
210: if ( $need_resource ) {
211: if ( !isset($dav_resource) ) $dav_resource = new DAVResource($item->dav_name);
212: $elements = $dav_resource->GetPropStat(array_keys($properties), $reply);
213: array_unshift($elements, $href);
214: }
215: else {
216: $elements = array($href);
217: $status = new XMLElement("status", "HTTP/1.1 200 OK" );
218: $elements[] = new XMLElement( "propstat", array( $prop, $status) );
219: if ( count($denied) > 0 ) {
220: $status = new XMLElement("status", "HTTP/1.1 403 Forbidden" );
221: $noprop = new XMLElement("prop");
222: foreach( $denied AS $k => $v ) {
223: $reply->NSElement($noprop, $v);
224: }
225: $elements[] = new XMLElement( "propstat", array( $noprop, $status) );
226: }
227:
228: if ( ! $request->PreferMinimal() && count($unsupported) > 0 ) {
229: $status = new XMLElement("status", "HTTP/1.1 404 Not Found" );
230: $noprop = new XMLElement("prop");
231: foreach( $unsupported AS $k => $v ) {
232: $reply->NSElement($noprop, $v);
233: }
234: $elements[] = new XMLElement( "propstat", array( $noprop, $status) );
235: }
236: }
237:
238: $response = new XMLElement( "response", $elements );
239:
240: return $response;
241: }
242:
243: if ( $target->IsExternal() ) {
244: require_once("external-fetch.php");
245: update_external ( $target );
246: }
247:
248:
249: $c->sync_resource_data_ok = true;
250:
251: if ( $xmltree->GetNSTag() == "urn:ietf:params:xml:ns:caldav:calendar-query" ) {
252: $calquery = $xmltree->GetPath("/urn:ietf:params:xml:ns:caldav:calendar-query/*");
253: include("caldav-REPORT-calquery.php");
254: }
255: elseif ( $xmltree->GetNSTag() == "urn:ietf:params:xml:ns:caldav:calendar-multiget" ) {
256: $mode = 'caldav';
257: $qry_content = $xmltree->GetContent('urn:ietf:params:xml:ns:caldav:calendar-multiget');
258: include("caldav-REPORT-multiget.php");
259: }
260: elseif ( $xmltree->GetNSTag() == "urn:ietf:params:xml:ns:carddav:addressbook-multiget" ) {
261: $mode = 'carddav';
262: $qry_content = $xmltree->GetContent('urn:ietf:params:xml:ns:carddav:addressbook-multiget');
263: include("caldav-REPORT-multiget.php");
264: }
265: elseif ( $xmltree->GetNSTag() == "urn:ietf:params:xml:ns:carddav:addressbook-query" ) {
266: $cardquery = $xmltree->GetPath("/urn:ietf:params:xml:ns:carddav:addressbook-query/*");
267: include("caldav-REPORT-cardquery.php");
268: }
269: else {
270: dbg_error_log( 'ERROR', "Request for unsupported report type '%s'.", $xmltree->GetNSTag() );
271: $request->PreconditionFailed( 403, 'DAV::supported-report', sprintf( '"%s" is not a supported report type', $xmltree->GetNSTag()) );
272: }
273:
274: