function AllowedTo($do_something) { return true; } } $d = new iSchedule(); if ($d->validateRequest()) { $ical = new vCalendar($request->raw_post); $attendee = array(); $addresses = array(); $attendees = $ical->GetAttendees(); foreach ($attendees as $v) { $email = preg_replace('/^mailto:/i', '', $v->Value()); $addresses[] = $email; } $organizer = $ical->GetOrganizer(); $addresses[] = preg_replace('/^mailto:/i', '', $organizer->Value()); $recipients = array(); $attendees_ok = array(); $attendees_fail = array(); if (strpos($_SERVER['HTTP_RECIPIENT'], ',') === false) { // single recipient $recipients[] = $_SERVER['HTTP_RECIPIENT']; } else { $rcpt = explode(',', $_SERVER['HTTP_RECIPIENT']); foreach ($rcpt as $k => $v) { $recipients[$k] = preg_replace('/^mailto:/i', '', trim($v)); } } if (!in_array(preg_replace('/^mailto:/i', '', $_SERVER['HTTP_ORIGINATOR']), $addresses)) { // should this be case sensitive?
/** * Deliver scheduling replies to organizer and other attendees * @param vComponent $ical the VCALENDAR to deliver * @return false on error */ function handle_schedule_reply(vCalendar $ical) { global $c, $session, $request; $resources = $ical->GetComponents('VTIMEZONE', false); $ic = $resources[0]; $etag = md5($request->raw_post); $organizer = $ical->GetOrganizer(); // for now we treat events with out organizers as an error if (empty($organizer)) { return false; } $att = $ical->GetAttendees(); $attendees = array_merge($organizer, $att); dbg_error_log("PUT", "Attempting to deliver scheduling request for %d attendees", count($attendees)); foreach ($attendees as $k => $attendee) { $attendee_email = preg_replace('/^mailto:/i', '', $attendee->Value()); dbg_error_log("PUT", "Delivering to %s", $attendee_email); $attendee_principal = new DAVPrincipal(array('email' => $attendee_email, 'options' => array('allow_by_email' => true))); $deliver_path = $attendee_principal->internal_url('schedule_inbox'); $attendee_email = preg_replace('/^mailto:/i', '', $attendee->Value()); if ($attendee_email == $request->principal->email) { dbg_error_log("PUT", "not delivering to owner"); continue; } $ar = new DAVResource($deliver_path); if (!$ar->HavePrivilegeTo('schedule-deliver-reply')) { $reply = new XMLDocument(array('DAV:' => '')); $privnodes = array($reply->href($attendee_principal->url('schedule_inbox')), new XMLElement('privilege')); // RFC3744 specifies that we can only respond with one needed privilege, so we pick the first. $reply->NSElement($privnodes[1], 'schedule-deliver-reply'); $xml = new XMLElement('need-privileges', new XMLElement('resource', $privnodes)); $xmldoc = $reply->Render('error', $xml); $request->DoResponse(403, $xmldoc, 'text/xml; charset="utf-8"'); continue; } $ncal = new vCalendar(array('METHOD' => 'REPLY')); $ncal->AddComponent(array_merge($ical->GetComponents('VEVENT', false), array($ic))); $content = $ncal->Render(); write_resource(new DAVResource($deliver_path . $etag . '.ics'), $content, $ar, $request->user_no, md5($content), $put_action_type = 'INSERT', $caldav_context = true, $log_action = true, $etag); } $request->DoResponse(201, 'Created'); }
function doItipAttendeeReply(vCalendar $resource, $partstat) { global $request; $organizer = $resource->GetOrganizer(); $organizer_email = preg_replace('/^mailto:/i', '', $organizer->Value()); $organizer_principal = new Principal('email', $organizer_email); if (!$organizer_principal->Exists()) { dbg_error_log('schedule', 'Unknown ORGANIZER "%s" - unable to notify.', $organizer->Value()); header("Debug: Could maybe do the iMIP message dance for organizer " . $organizer->Value()); return true; } $sql = 'SELECT caldav_data.dav_name, caldav_data.caldav_data FROM caldav_data JOIN calendar_item USING(dav_id) '; $sql .= 'WHERE caldav_data.collection_id IN (SELECT collection_id FROM collection WHERE is_calendar AND user_no =?) '; $sql .= 'AND uid=? LIMIT 1'; $uids = $resource->GetPropertiesByPath('/VCALENDAR/*/UID'); if (count($uids) == 0) { dbg_error_log('schedule', 'No UID in VCALENDAR - giving up on REPLY.'); return true; } $uid = $uids[0]->Value(); $qry = new AwlQuery($sql, $organizer_principal->user_no(), $uid); if (!$qry->Exec('schedule', __LINE__, __FILE__) || $qry->rows() < 1) { dbg_error_log('schedule', 'Could not find original event from organizer - giving up on REPLY.'); return true; } $row = $qry->Fetch(); $collection_path = preg_replace('{/[^/]+$}', '/', $row->dav_name); $segment_name = str_replace($collection_path, '', $row->dav_name); $vcal = new vCalendar($row->caldav_data); $attendees = $vcal->GetAttendees(); foreach ($attendees as $v) { $email = preg_replace('/^mailto:/i', '', $v->Value()); if ($email == $request->principal->email()) { $attendee = $v; break; } } if (empty($attendee)) { dbg_error_log('schedule', 'Could not find ATTENDEE in VEVENT - giving up on REPLY.'); return true; } $attendee->SetParameterValue('PARTSTAT', $partstat); $attendee->SetParameterValue('SCHEDULE-STATUS', '2.0'); $vcal->UpdateAttendeeStatus($request->principal->email(), clone $attendee); $organizer_calendar = new WritableCollection(array('path' => $collection_path)); $organizer_inbox = new WritableCollection(array('path' => $organizer_principal->internal_url('schedule-inbox'))); $schedule_reply = GetItip(new vCalendar($row->caldav_data), 'REPLY', $attendee->Value()); $schedule_request = GetItip(new vCalendar($row->caldav_data), 'REQUEST', null); dbg_error_log('schedule', 'Writing ATTENDEE scheduling REPLY from %s to %s', $request->principal->email(), $organizer_principal->email()); $response = '3.7'; // Organizer was not found on server. if (!$organizer_calendar->Exists()) { if (doImipMessage('REPLY', $organizer_principal->email(), $vcal)) { $response = '1.1'; // Scheduling whoosit 'Sent' } else { dbg_error_log('ERROR', 'Default calendar at "%s" does not exist for user "%s"', $organizer_calendar->dav_name(), $schedule_target->username()); $response = '5.2'; // No scheduling support for user } } else { if (!$organizer_inbox->HavePrivilegeTo('schedule-deliver-reply')) { $response = '3.8'; // No authority to deliver replies to organizer. } $response = '1.2'; // Scheduling reply delivered successfully if ($organizer_calendar->WriteCalendarMember($vcal, false, false, $segment_name) === false) { dbg_error_log('ERROR', 'Could not write updated calendar member to %s', $attendee_calendar->dav_name()); trace_bug('Failed to write scheduling resource.'); } $organizer_inbox->WriteCalendarMember($schedule_reply, false, false, $request->principal->username() . $segment_name); } dbg_error_log('schedule', 'Status for organizer <%s> set to "%s"', $organizer->Value(), $response); $organizer->SetParameterValue('SCHEDULE-STATUS', $response); $resource->UpdateOrganizerStatus($organizer); // Which was passed in by reference, and we're updating it here. // Now we loop through the *other* ATTENDEEs, updating them on the status of the ATTENDEE DECLINE/ACCEPT foreach ($attendees as $attendee) { $email = preg_replace('/^mailto:/i', '', $attendee->Value()); if ($email == $request->principal->email() || $email == $organizer_principal->email()) { continue; } $agent = $attendee->GetParameterValue('SCHEDULE-AGENT'); if (!empty($agent) && $agent != 'SERVER') { continue; } $schedule_target = new Principal('email', $email); if ($schedule_target->Exists()) { $attendee_calendar = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-default-calendar'))); if (!$attendee_calendar->Exists()) { dbg_error_log('ERROR', 'Default calendar at "%s" does not exist for user "%s"', $attendee_calendar->dav_name(), $schedule_target->username()); continue; } else { $attendee_inbox = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-inbox'))); if (!$attendee_inbox->HavePrivilegeTo('schedule-deliver-invite')) { continue; } if ($attendee_calendar->WriteCalendarMember($vcal, false) === false) { dbg_error_log('ERROR', 'Could not write updated calendar member to %s', $attendee_calendar->dav_name()); trace_bug('Failed to write scheduling resource.'); } $attendee_inbox->WriteCalendarMember($schedule_request, false); } } else { header("Debug: Could maybe do the iMIP message dance for attendee " . $email); } } return true; }