3 dbg_error_log("REPORT", "method handler");
5 require_once("XMLElement.php");
6 require_once("vEvent.php");
8 $report_path = $_SERVER['PATH_INFO'];
10 $attributes = array();
13 foreach( $request->xml_tags
AS $k => $v ) {
15 switch ( $v['tag'] ) {
17 case 'URN:IETF:PARAMS:XML:NS:CALDAV:CALENDAR-MULTIGET':
18 dbg_log_array( "REPORT", "CALENDAR-MULTIGET", $v, true );
19 $report[$reportnum]['multiget'] = 1;
20 if ( $v['type'] == "open" ) {
21 $multiget_names = array();
23 else if ( $v['type'] == "close" ) {
24 $report[$reportnum]['get_names'] = $multiget_names;
25 unset($multiget_names);
29 case 'URN:IETF:PARAMS:XML:NS:CALDAV:CALENDAR-DATA':
30 dbg_log_array( "REPORT", "CALENDAR-DATA", $v, true );
31 if ( $v['type'] == "complete" ) {
32 $report[$reportnum]['include_data'] = 1;
36 case 'URN:IETF:PARAMS:XML:NS:CALDAV:CALENDAR-QUERY':
37 dbg_log_array( "REPORT", "CALENDAR-QUERY", $v, true );
38 if ( $v['type'] == "open" ) {
40 $report_type = substr($v['tag'],30);
41 $report[$reportnum]['type'] = $report_type;
42 $report[$reportnum]['include_href'] = 1;
43 $report[$reportnum]['include_data'] = 0;
44 $report[$reportnum]['start'] = date('Ymd\THis\Z',(time() - (86400 * 100))); // Default to the last 100 days.
45 $report[$reportnum]['end'] = date('Ymd\THis\Z');;
52 case 'URN:IETF:PARAMS:XML:NS:CALDAV:TIME-RANGE':
53 dbg_log_array( "REPORT", "TIME-RANGE", $v, true );
54 if ( isset($v['attributes']['START']) ) {
55 $report[$reportnum]['start'] = $v['attributes']['START'];
57 if ( isset($v['attributes']['END']) ) {
58 $report[$reportnum]['end'] = $v['attributes']['END'];
62 case 'URN:IETF:PARAMS:XML:NS:CALDAV:COMP-FILTER':
63 dbg_log_array( "REPORT", "COMP-FILTER", $v, true );
64 if ( isset($v['attributes']['NAME']) && ($v['attributes']['NAME'] == 'VCALENDAR' )) {
65 $report[$reportnum]['calendar'] = 1;
67 if ( isset($v['attributes']['NAME']) ) {
68 if ( isset($report[$reportnum]['calendar']) && ($v['attributes']['NAME'] == 'VEVENT') ) {
69 $report[$reportnum]['calendar-event'] = 1;
71 if ( isset($report[$reportnum]['calendar']) && ($v['attributes']['NAME'] == 'VTODO') ) {
72 $report[$reportnum]['calendar-todo'] = 1;
74 if ( isset($report[$reportnum]['calendar']) && ($v['attributes']['NAME'] == 'VFREEBUSY') ) {
75 $report[$reportnum]['calendar-freebusy'] = 1;
80 case 'URN:IETF:PARAMS:XML:NS:CALDAV:FILTER':
81 dbg_error_log( "REPORT", "Not using %s information which follows...", $v['tag'] );
82 dbg_log_array( "REPORT", "FILTER", $v, true );
86 dbg_log_array( "REPORT", "DAV::PROP", $v, true );
87 if ( isset($report_type) ) {
88 if ( $v['type'] == "open" ) {
89 $report_properties = array();
91 else if ( $v['type'] == "close" ) {
92 $report[$reportnum]['properties'] = $report_properties;
93 unset($report_properties);
96 dbg_error_log( "REPORT", "Unexpected DAV::PROP type of ".$v['type'] );
100 dbg_error_log( "REPORT", "Unexpected DAV::PROP type of ".$v['type']." when no active report type.");
105 case 'DAV::GETCONTENTLENGTH':
106 case 'DAV::GETCONTENTTYPE':
107 case 'DAV::RESOURCETYPE':
108 if ( isset($report_properties) ) {
109 $attribute = substr($v['tag'],5);
110 $report_properties[$attribute] = 1;
115 dbg_log_array( "REPORT", "DAV::HREF", $v, true );
116 if ( isset($report[$reportnum]['multiget']) ) {
117 $multiget_names[] = $v['value'];
121 dbg_error_log( "REPORT", "Unhandled tag >>".$v['tag']."<<");
125 if ( $reportnum == -1 ) {
126 // Fake the request anyway...
128 $report_type = substr($v['tag'],30);
129 $report[$reportnum]['type'] = $report_type;
130 $report[$reportnum]['include_href'] = 1;
131 $report[$reportnum]['include_data'] = 0;
132 $report[$reportnum]['start'] = date('Ymd\THis\Z',(time() - (86400 * 40))); // Default to the last 40 days.
133 $report[$reportnum]['end'] = date('Ymd\THis\Z');;
136 if ( $unsupported_stuff ) {
138 * FIXME This is really a template for what we should do in the event of an error.
140 header('HTTP/1.1 403 Forbidden');
141 header('Content-Type: application/xml; charset="utf-8"');
143 <?xml version="1.0" encoding="utf-8" ?>
144 <D:error xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
146 <C:prop-filter name="X-ABC-GUID"/>
147 </C:supported-filter>
153 $report_user_no = $session->user_no
;
154 $report_user_name = $session->username
;
155 if ( $session->AllowedTo("Admin") ||
$session->AllowedTo("Support") ||
$session->AllowedTo("Accounts") ) {
156 if ( preg_match( "#^/([^/]+)(/|$)#", $report_path, $matches ) ) {
157 $in_username = $matches[1];
158 $qry = new PgQuery( "SELECT user_no FROM usr WHERE username = ?;", $in_username );
159 if ( $qry->Exec("REPORT") && $row = $qry->Fetch() ) {
160 $report_user_no = $row->user_no
;
161 $report_user_name = $in_username;
167 $ical_date_format = vEvent
::SqlDateFormat();
168 $ical_duration_format = vEvent
::SqlDurationFormat();
170 for( $i=0; $i <= $reportnum; $i++
) {
171 dbg_error_log("REPORT", "Report[%d] Start:%s, End: %s, Events: %d, Todos: %d, Freebusy: %d",
172 $i, $report[$i]['start'], $report[$i]['end'], $report[$i]['calendar-event'], $report[$i]['calendar-todo'], $report[$i]['calendar-freebusy']);
173 if ( $report[$i]['calendar-event'] != 1 ) continue;
175 SELECT usr.username, dav_etag, timesheet_id,
176 to_char(work_on,$ical_date_format) AS dtstamp,
177 to_char(work_on + case when work_on::time < '06:00'::time then '09:00'::time else '00:00'::time end,$ical_date_format) AS dtstart,
178 to_char(work_duration,$ical_duration_format) AS duration,
179 work_description AS summary,
180 'WR#'||request_id::text AS location,
181 'WR#'||request_id::text || ' - ' || brief AS description,
182 'Invoice '||charged_details::text || ', Charged $'|| to_char(charged_amount,'FM999,999,990.00') ||' by ' || chgby.username || ' on ' || to_char(work_charged,'d/mm/YY') AS invoiced
183 FROM request_timesheet JOIN request USING (request_id) JOIN usr ON (work_by_id=usr.user_no)
184 LEFT OUTER JOIN usr chgby ON (charged_by_id = chgby.user_no)
185 WHERE work_by_id = ? AND work_duration IS NOT NULL
190 if ( isset( $report[$i]['start'] ) ) {
191 $where = "AND ((work_on + work_duration) >= ".qpg($report[$i]['start'])."::timestamp with time zone) ";
193 if ( isset( $report[$i]['end'] ) ) {
194 $where .= "AND work_on <= ".qpg($report[$i]['end'])."::timestamp with time zone ";
197 $sql .= " ORDER BY work_on ASC";
199 $responses = array();
200 $qry = new PgQuery( $sql, $report_user_no );
201 // echo $qry->querystring;
202 if ( $qry->Exec() && $qry->rows
> 0 ) {
203 while( $ts = $qry->Fetch() ) {
204 if ( $ts->invoiced
!= "" ) $ts->description
.= "\n" . $ts->invoiced
;
205 $response = new XMLElement("response" );
206 $prop = new XMLElement("prop" );
207 $ev = new vEvent( array(
208 'uid' => $ts->timesheet_id
."@".$_SERVER['SERVER_NAME'],
209 'dtstart' => $ts->dtstart
,
210 'duration' => $ts->duration
,
211 'summary' => $ts->summary
,
212 'location' => $ts->location
,
213 'description' => $ts->description
216 if ( isset($report[$i]['include_href']) && $report[$i]['include_href'] > 0 ) {
217 $url = sprintf("http://%s:%d%s/%s/%d.ics", $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], $_SERVER['SCRIPT_NAME'], $report_user_name, $ts->timesheet_id
);
218 $response->NewElement("href",$url);
220 if ( isset($report[$i]['include_data']) && $report[$i]['include_data'] > 0 ) {
221 $caldata = $ev->Render();
222 $prop->NewElement("calendar-data",$caldata, array("xmlns" => "urn:ietf:params:xml:ns:caldav") );
224 if ( isset($report[$i]['properties']['GETETAG']) ) {
225 $prop->NewElement("getetag", '"'.$ts->dav_etag
.'"' );
227 $status = new XMLElement("status", "HTTP/1.1 200 OK" );
229 $response->NewElement( "propstat", array( $prop, $status) );
231 $responses[] = $response;
233 dbg_error_log("REPORT", "TS Response: ETag >>%s<< >>%s<<", $ts->dav_etag
, $url );
238 * We also include _all_ caldav_data entries in there, since these
239 * are events which failed to parse into timesheets.
241 $qry = new PgQuery( "SELECT * FROM caldav_data WHERE user_no = ?", $report_user_no );
242 if ( $qry->Exec() && $qry->rows
> 0 ) {
243 while( $dav = $qry->Fetch() ) {
244 $response = new XMLElement("response" );
245 $prop = new XMLElement("prop" );
246 $url = sprintf("http://%s:%d%s%s", $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], $_SERVER['SCRIPT_NAME'], $dav->dav_name
);
248 if ( isset($report[$i]['include_href']) && $report[$i]['include_href'] > 0 ) {
249 $response->NewElement("href",$url);
251 if ( isset($report[$i]['include_data']) && $report[$i]['include_data'] > 0 ) {
252 $prop->NewElement("calendar-data",$dav->caldav_data
, array("xmlns" => "urn:ietf:params:xml:ns:caldav") );
254 if ( isset($report[$i]['properties']['GETETAG']) ) {
255 $prop->NewElement("getetag", '"'.$dav->dav_etag
.'"' );
257 $status = new XMLElement("status", "HTTP/1.1 200 OK" );
259 $response->NewElement( "propstat", array( $prop, $status) );
261 $responses[] = $response;
263 dbg_error_log("REPORT", "DAV Response: ETag >>%s<< >>%s<<", $dav->dav_etag
, $url );
268 $multistatus = new XMLElement( "multistatus", $responses, array('xmlns'=>'DAV:') );
270 // dbg_log_array( "REPORT", "XML", $multistatus, true );
272 $xmldoc = $multistatus->Render();
273 $etag = md5($xmldoc);
275 header("HTTP/1.1 207 Multi-Status");
276 header("Content-type: text/xml;charset=UTF-8");
277 header("DAV: 1, 2, calendar-schedule");
278 header("ETag: \"$etag\"");
280 echo'<?xml version="1.0" encoding="UTF-8" ?>'."\n";