Overview

Packages

  • awl
    • caldav-client-v2
    • RRule
  • davical
    • authentication
      • drivers
    • caldav
    • DAViCalSession
    • DAVTicket
    • external-bind
    • feed
    • HTTPAuthSession
    • iSchedule
    • iSchedule-POST
    • logging
    • metrics
    • Principal
    • propfind
    • PublicSession
    • Request
    • Resource
    • tzservice
  • None
  • PHP

Functions

  • add_failure
  • check_for_expansion
  • component_to_xml
  • controlRequestContainer
  • delete_collection
  • deliverItipCancel
  • display_status
  • do_scheduling_for_delete
  • do_scheduling_reply
  • do_scheduling_requests
  • doImipMessage
  • doItipAttendeeReply
  • doItipOrganizerCancel
  • export_iCalendar
  • GetItip
  • GetTZID
  • handle_cancel_request
  • handle_freebusy_request
  • handle_schedule_reply
  • handle_schedule_request
  • import_addressbook_collection
  • import_calendar_collection
  • import_collection
  • late_catch_fatal_error
  • logRequestHeaders
  • obfuscated_event
  • process_ace
  • processItipCancel
  • property_response
  • public_events_only
  • rollback
  • rollback_on_error
  • send_dav_header
  • simple_write_resource
  • write_alarms
  • write_attendees
  • write_resource
  • Overview
  • Package
  • Function
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: /**
  3: * CalDAV Server - handle REPORT method
  4: *
  5: * @package   davical
  6: * @subpackage   caldav
  7: * @author    Andrew McMillan <andrew@morphoss.com>
  8: * @copyright Catalyst .Net Ltd, Morphoss Ltd
  9: * @license   http://gnu.org/copyleft/gpl.html GNU GPL v2
 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 ); // They may have either
 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; // Not that the above include should return anyway
 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; // Not that it should return anyway.
 60:   case 'DAV::principal-search-property-set':
 61:     include("caldav-REPORT-pps-set.php");
 62:     exit; // Not that it should return anyway.
 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; // Not that it should return anyway.
 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; // Not that it should return anyway.
 77:   case 'DAV::principal-match':
 78:     include("caldav-REPORT-principal-match.php");
 79:     exit; // Not that it should return anyway.
 80: }
 81: 
 82: /**
 83: * check if we need to do expansion of recurring events
 84: * @param object $calendar_data_node
 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; /** We don't support expansion on PHP5.1 */
 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: * Return XML for a single component from the DB
109: *
110: * @param array $properties The properties for this component
111: * @param string $item The DB row data for this component
112: *
113: * @return string An XML document which is the response for the component
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:           // the user is not admin / owner of this calendar looking at his calendar and can not admin the other cal
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); // Just an empty resourcetype for a non-collection.
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:         // It's harder.  We need the DAVResource() to get this one.
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: // These reports are always allowed to see the resource_data because they are special
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: 
DAViCal API documentation generated by ApiGen 2.8.0