DAViCal
Loading...
Searching...
No Matches
iSchedule-POST.php
1<?php
11
12require_once('iSchedule.php');
13require_once('vComponent.php');
14require_once('vCalendar.php');
15require_once('WritableCollection.php');
16include_once('freebusy-functions.php');
17
18
20 private $user_active;
21 private $created;
22 private $modified;
23 private $password;
24 private $fullname;
25 private $email_ok;
26 private $date_format_type;
27 private $locale;
28 private $type_id;
29 private $type_label;
30 private $displayname;
31 private $default_privileges;
32 private $is_principal;
33 private $is_calendar;
34 private $is_addressbook;
35 private $collection_id;
36 private $resourcetypes;
37 private $privileges;
38 private $username;
39 public $user_no;
40 public $principal_id;
41 private $logged_in;
42 private $email;
43 private $dav_name;
44 private $principal;
45
46 function __construct($principal) {
47 // Assign each field in the selected record to the object
48 foreach( $principal AS $k => $v ) {
49 $this->{$k} = $v;
50 }
51 $this->username = $principal->username();
52 $this->user_no = $principal->user_no();
53 $this->principal_id = $principal->principal_id();
54 $this->email = $principal->email();
55 $this->dav_name = $principal->dav_name();
56 $this->principal = $principal;
57
58 $this->logged_in = true;
59
60 }
61
62 function AllowedTo($do_something) {
63 return true;
64 }
65}
66
67$d = new iSchedule ();
68if ( $d->validateRequest ( ) ) {
69 $ical = new vCalendar( $request->raw_post );
70 $attendee = Array ();
71 $addresses = Array ();
72 $attendees = $ical->GetAttendees();
73 foreach( $attendees AS $v ) {
74 $email = preg_replace( '/^mailto:/i', '', $v->Value() );
75 $addresses[] = $email;
76 }
77 $organizer = $ical->GetOrganizer();
78 $addresses[] = preg_replace( '/^mailto:/i', '', $organizer->Value() );
79 $recipients = Array ();
80 $attendees_ok = Array ();
81 $attendees_fail = Array ();
82 if ( strpos ( $_SERVER['HTTP_RECIPIENT'], ',' ) === false ) { // single recipient
83 $recipients[] = $_SERVER['HTTP_RECIPIENT'];
84 }
85 else {
86 $rcpt = explode ( ',', $_SERVER['HTTP_RECIPIENT'] );
87 foreach ( $rcpt as $k => $v ) {
88 $recipients[$k] = preg_replace( '/^mailto:/i', '', trim ( $v ) );
89 }
90 }
91 if ( ! in_array ( preg_replace( '/^mailto:/i', '', $_SERVER['HTTP_ORIGINATOR'] ), $addresses ) ) { // should this be case sensitive?
92 $request->DoResponse( 412, translate('sender must be organizer or attendee of event') );
93 }
94 foreach ( $recipients as $v ) {
95 if ( ! in_array ( preg_replace( '/^mailto:/i', '', $v ), $addresses ) ) { // should this be case sensitive?
96 dbg_error_log('ischedule','recipient missing from event ' . $v );
97 $reply->XMLResponse( 403, translate('recipient must be organizer or attendee of event') . $v );
98 continue;
99 }
100 $email = preg_replace( '/^mailto:/', '', $v );
101 dbg_error_log('ischedule','recipient ' . $v );
102 $schedule_target = new Principal('email',$email);
103 if ( $schedule_target == false ){
104 array_push ( $attendees_fail, $schedule_target );
105 continue;
106 }
107 array_push ( $attendees_ok, $schedule_target );
108 // TODO: add originator addressbook and existing event lookup as whitelist
109 }
110 $method = $ical->GetPValue('METHOD');
111
112 $content_type = explode ( ';', $_SERVER['CONTENT_TYPE'] );
113 if ( $content_type[0] != 'text/calendar' )
114 $reply->XMLResponse( 406, 'content must be text/calendar' );
115
116 $content_parts = Array ();
117 foreach ( $content_type as $v ) {
118 if ($v == 'text/calendar')
119 continue;
120
121 list ( $a, $b ) = explode ( '=', trim ( $v ), 2 );
122 $content_parts[strtolower($a)] = strtoupper($b);
123 }
124 if ( isset ( $content_parts['method'] ) )
125 $method = $content_parts['method']; // override method from icalendar
126 switch ( $method )
127 {
128 case 'REQUEST':
129 if ( $content_parts['component'] == 'VFREEBUSY' ) {
130 ischedule_freebusy_request ( $ical, $attendees_ok, $attendees_fail );
131 }
132 if ( $content_parts['component'] == 'VEVENT' ) {
133 ischedule_request ( $ical, $attendees_ok, $attendees_fail );
134 // scheduling event request
135 }
136 if ( $content_parts['component'] == 'VTODO' ) {
137 ischedule_request ( $ical, $attendees_ok, $attendees_fail );
138 // scheduling todo request
139 }
140 if ( $content_parts['component'] == 'VJOURNAL' ) {
141 // scheduling journal request, not sure how to handle this or if it will ever by used
142 }
143 break;
144 case 'REPLY':
145 ischedule_request ( $ical, $attendees_ok, $attendees_fail );
146 break;
147 case 'ADD':
148 ischedule_request ( $ical, $attendees_ok, $attendees_fail );
149 break;
150 case 'CANCEL':
151 ischedule_request ( $ical, $attendees_ok, $attendees_fail );
152 break;
153 case 'PUBLISH':
154 break;
155 case 'REFRESH':
156 break;
157 case 'COUNTER':
158 break;
159 case 'DECLINECOUNTER':
160 break;
161 default:
162 dbg_error_log('ischedule','invalid request' );
163 $request->DoResponse( 400, translate('invalid request') );
164 }
165}
166else {
167 dbg_error_log('ischedule','invalid request' );
168 $request->DoResponse( 400, translate('invalid request') );
169}
170
171function ischedule_freebusy_request( $ic, $attendees, $attendees_fail) {
172 global $c, $session, $request;
173 $reply = new XMLDocument( array( "urn:ietf:params:xml:ns:ischedule" => "I" ) );
174 $icalAttendees = $ic->GetAttendees();
175 $responses = array();
176 $ical = $ic->GetComponents('VFREEBUSY');
177 $ical = $ical[0];
178 $fbq_start = $ical->GetPValue('DTSTART');
179 $fbq_end = $ical->GetPValue('DTEND');
180 if ( ! ( isset($fbq_start) || isset($fbq_end) ) ) {
181 $request->DoResponse( 400, 'All valid freebusy requests MUST contain a DTSTART and a DTEND' );
182 }
183
184 $range_start = new RepeatRuleDateTime($fbq_start);
185 $range_end = new RepeatRuleDateTime($fbq_end);
186
187 foreach( $attendees AS $k => $attendee ) {
188 $response = $reply->NewXMLElement("response", false, false, 'urn:ietf:params:xml:ns:ischedule');
189 $fb = get_freebusy( '^'.$attendee->dav_name, $range_start, $range_end );
190
191 $fb->AddProperty( 'UID', $ical->GetPValue('UID') );
192 $fb->SetProperties( $ical->GetProperties('ORGANIZER'), 'ORGANIZER');
193 foreach ( $ical->GetProperties('ATTENDEE') as $at ) {
194 if ( $at->Value() == 'mailto:' . $attendee->email )
195 $fb->AddProperty( $at );
196 }
197
198 $vcal = new vCalendar( array('METHOD' => 'REPLY') );
199 $vcal->AddComponent( $fb );
200
201 $response = $reply->NewXMLElement( "response", false, false, 'urn:ietf:params:xml:ns:ischedule' );
202 $response->NewElement( "recipient", 'mailto:'.$attendee->email, false, 'urn:ietf:params:xml:ns:ischedule' );
203 $response->NewElement( "request-status", "2.0;Success", false, 'urn:ietf:params:xml:ns:ischedule' );
204 $response->NewElement( "calendar-data", $vcal->Render(), false, 'urn:ietf:params:xml:ns:ischedule' );
205
206 $responses[] = $response;
207 }
208
209 foreach ( $attendees_fail AS $k => $attendee ) {
210 $XMLresponse = $reply->NewXMLElement("response", false, false, 'urn:ietf:params:xml:ns:ischedule');
211 $XMLresponse->NewElement( "recipient", $reply->href('mailto:'.$attendee));
212 $XMLresponse->NewElement( "request-status",'5.3;cannot schedule this user, unknown or access denied');
213 $responses[] = $XMLresponse;
214 }
215 $response = $reply->NewXMLElement( "schedule-response", $responses, $reply->GetXmlNsArray(), 'urn:ietf:params:xml:ns:ischedule' );
216 $request->XMLResponse( 200, $response );
217}
218
219function ischedule_request( $ic, $attendees, $attendees_fail ) {
220 global $c, $session, $request;
221 $oldSession = $session;
222 $reply = new XMLDocument( array( "urn:ietf:params:xml:ns:ischedule" => "I" ) );
223 $responses = array();
224 $ical = $ic->GetComponents('VEVENT');
225 $ical = $ical[0];
226
227 foreach ( $attendees AS $k => $attendee ) {
228 $XMLresponse = $reply->NewXMLElement("response", false, false, 'urn:ietf:params:xml:ns:ischedule');
229 dbg_error_log('ischedule','scheduling event for ' .$attendee->email);
230 $schedule_target = new Principal('email',$attendee->email);
231 $response = '3.7'; // Attendee was not found on server.
232 if ( $schedule_target->Exists() ) {
233 $session = new FakeSession($schedule_target);
234 $attendee_calendar = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-default-calendar')));
235 if ( !$attendee_calendar->Exists() ) {
236 dbg_error_log('ERROR','Default calendar at "%s" does not exist for user "%s"',
237 $attendee_calendar->dav_name(), $schedule_target->username());
238 $response = '5.3;cannot schedule this user, unknown or access denied'; // No scheduling support for user
239 }
240 else {
241 $attendee_inbox = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-inbox')));
242 if ( ! $attendee_inbox->HavePrivilegeTo('schedule-deliver-invite') ) {
243 $response = '3.8;denied'; // No authority to deliver invitations to user.
244 }
245 else if ( $attendee_inbox->WriteCalendarMember($ic, false) !== false ) {
246 $response = '2.0;delivered'; // Scheduling invitation delivered successfully
247 }
248 }
249 $session = $oldSession;
250 }
251 dbg_error_log( 'ischedule', 'Status for attendee <%s> set to "%s"', $attendee->email, $response );
252 $XMLresponse->NewElement("recipient", 'mailto:'.$attendee->email, false, 'urn:ietf:params:xml:ns:ischedule' );
253 $XMLresponse->NewElement("request-status", $response, false, 'urn:ietf:params:xml:ns:ischedule' );
254 $responses[] = $XMLresponse;
255 }
256
257 foreach ( $attendees_fail AS $k => $attendee ) {
258 $XMLresponse = $reply->NewXMLElement("response", false, false, 'urn:ietf:params:xml:ns:ischedule');
259 $XMLresponse->NewElement("recipient", 'mailto:'.$attendee->email, false, 'urn:ietf:params:xml:ns:ischedule' );
260 $XMLresponse->NewElement("request-status", '5.3;cannot schedule this user, unknown or access denied', false, 'urn:ietf:params:xml:ns:ischedule' );
261 $responses[] = $XMLresponse;
262 }
263
264 $response = $reply->NewXMLElement( "schedule-response", $responses, $reply->GetXmlNsArray(), 'urn:ietf:params:xml:ns:ischedule' );
265 $request->XMLResponse( 200, $response );
266}
267
268function ischedule_cancel( $ic, $attendees, $attendees_fail ) {
269 global $c, $session, $request;
270 $reply = new XMLDocument( array("DAV:" => "", "urn:ietf:params:xml:ns:caldav" => "C", "urn:ietf:params:xml:ns:ischedule" => "I" ) );
271 $responses = array();
272 $ical = $ic->GetComponents('VEVENT');
273 $ical = $ical[0];
274
275 foreach ( $attendees AS $k => $attendee ) {
276 $XMLresponse = $reply->NewXMLElement("response", false, false, 'urn:ietf:params:xml:ns:ischedule');
277 dbg_error_log('ischedule','scheduling event for ' .$attendee->email);
278 $schedule_target = new Principal('email',$attendee->email);
279 $response = '3.7'; // Attendee was not found on server.
280 if ( $schedule_target->Exists() ) {
281 $attendee_calendar = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-default-calendar')));
282 if ( !$attendee_calendar->Exists() ) {
283 dbg_error_log('ERROR','Default calendar at "%s" does not exist for user "%s"',
284 $attendee_calendar->dav_name(), $schedule_target->username());
285 $response = '5.3;cannot schedule this user, unknown or access denied'; // No scheduling support for user
286 }
287 else {
288 $attendee_inbox = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-inbox')));
289 if ( ! $attendee_inbox->HavePrivilegeTo('schedule-deliver-invite') ) {
290 $response = '3.8;denied'; // No authority to deliver invitations to user.
291 }
292 else if ( $attendee_inbox->WriteCalendarMember($ic, false) !== false ) {
293 $response = '2.0;delivered'; // Scheduling invitation delivered successfully
294 }
295 }
296 }
297 dbg_error_log( 'PUT', 'Status for attendee <%s> set to "%s"', $attendee->email, $response );
298 $XMLresponse->NewElement("recipient", $reply->href('mailto:'.$attendee->email), false, 'urn:ietf:params:xml:ns:ischedule' );
299 $XMLresponse->NewElement("request-status", $response, false, 'urn:ietf:params:xml:ns:ischedule' );
300 $responses[] = $XMLresponse;
301 }
302
303 foreach ( $attendees_fail AS $k => $attendee ) {
304 $XMLresponse = $reply->NewXMLElement("response", false, false, 'urn:ietf:params:xml:ns:ischedule');
305 $XMLresponse->NewElement("recipient", $reply->href('mailto:'.$attendee->email), false, 'urn:ietf:params:xml:ns:ischedule' );
306 $XMLresponse->NewElement("request-status", '5.3;cannot schedule this user, unknown or access denied', false, 'urn:ietf:params:xml:ns:ischedule' );
307 $responses[] = $XMLresponse;
308 }
309
310 $response = $reply->NewXMLElement( "schedule-response", $responses, $reply->GetXmlNsArray(), 'urn:ietf:params:xml:ns:ischedule' );
311 $request->XMLResponse( 200, $response );
312}
313