/** * Converts a text/calendar part into SyncMeetingRequest * This is called on received messages, it's not called for events generated from the mobile * * @param $part MIME part * @param $output SyncMail object * @param $is_sent_folder boolean */ function parse_meeting_calendar($part, &$output, $is_sent_folder) { $ical = new iCalComponent(); $ical->ParseFrom($part->body); ZLog::Write(LOGLEVEL_WBXML, sprintf("BackendIMAP->parse_meeting_calendar(): %s", $part->body)); // Get UID $uid = false; $props = $ical->GetPropertiesByPath("VEVENT/UID"); if (count($props) > 0) { $uid = $props[0]->Value(); } $method = false; $props = $ical->GetPropertiesByPath("VCALENDAR/METHOD"); if (count($props) > 0) { $method = strtolower($props[0]->Value()); ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->parse_meeting_calendar(): Using method from vcalendar object: %s", $method)); } else { if (isset($part->ctype_parameters["method"])) { $method = strtolower($part->ctype_parameters["method"]); ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->parse_meeting_calendar(): Using method from mime part object: %s", $method)); } } if ($method === false) { ZLog::Write(LOGLEVEL_WARN, sprintf("BackendIMAP->parse_meeting_calendar() - No method header, please report it to the developers")); $output->messageclass = "IPM.Appointment"; } else { switch ($method) { case "cancel": $output->messageclass = "IPM.Schedule.Meeting.Canceled"; ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): Event canceled, removing calendar object"); delete_calendar_dav($uid); break; case "counter": ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): Counter received"); $output->messageclass = "IPM.Schedule.Meeting.Resp.Tent"; $output->meetingrequest->disallownewtimeproposal = 0; break; case "reply": ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): Reply received"); $props = $ical->GetPropertiesByPath('VEVENT/ATTENDEE'); for ($i = 0; $i < count($props); $i++) { $mailto = $props[$i]->Value(); $props_params = $props[$i]->Parameters(); $status = strtolower($props_params["PARTSTAT"]); if (!$is_sent_folder) { // Only evaluate received replies, not sent $res = update_calendar_attendee($uid, $mailto, $status); } else { $res = true; } if ($res) { // Only set messageclass for replies changing my calendar object switch ($status) { case "accepted": $output->messageclass = "IPM.Schedule.Meeting.Resp.Pos"; ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): Update attendee -> accepted"); break; case "needs-action": $output->messageclass = "IPM.Schedule.Meeting.Resp.Tent"; ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): Update attendee -> needs-action"); break; case "tentative": $output->messageclass = "IPM.Schedule.Meeting.Resp.Tent"; ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): Update attendee -> tentative"); break; case "declined": $output->messageclass = "IPM.Schedule.Meeting.Resp.Neg"; ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): Update attendee -> declined"); break; default: ZLog::Write(LOGLEVEL_WARN, sprintf("BackendIMAP->parse_meeting_calendar() - Unknown reply status <%s>, please report it to the developers", $status)); $output->messageclass = "IPM.Appointment"; break; } } } $output->meetingrequest->disallownewtimeproposal = 1; break; case "request": $output->messageclass = "IPM.Schedule.Meeting.Request"; $output->meetingrequest->disallownewtimeproposal = 0; ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): New request"); // New meeting, we don't create it now, because we need to confirm it first, but if we don't create it we won't see it in the calendar break; default: ZLog::Write(LOGLEVEL_WARN, sprintf("BackendIMAP->parse_meeting_calendar() - Unknown method <%s>, please report it to the developers", strtolower($part->headers["method"]))); $output->messageclass = "IPM.Appointment"; $output->meetingrequest->disallownewtimeproposal = 0; break; } } $props = $ical->GetPropertiesByPath('VEVENT/DTSTAMP'); if (count($props) == 1) { $output->meetingrequest->dtstamp = TimezoneUtil::MakeUTCDate($props[0]->Value()); } $props = $ical->GetPropertiesByPath('VEVENT/UID'); if (count($props) == 1) { $output->meetingrequest->globalobjid = $props[0]->Value(); } $props = $ical->GetPropertiesByPath('VEVENT/DTSTART'); if (count($props) == 1) { $output->meetingrequest->starttime = TimezoneUtil::MakeUTCDate($props[0]->Value()); if (strlen($props[0]->Value()) == 8) { $output->meetingrequest->alldayevent = 1; } } $props = $ical->GetPropertiesByPath('VEVENT/DTEND'); if (count($props) == 1) { $output->meetingrequest->endtime = TimezoneUtil::MakeUTCDate($props[0]->Value()); if (strlen($props[0]->Value()) == 8) { $output->meetingrequest->alldayevent = 1; } } $props = $ical->GetPropertiesByPath('VEVENT/ORGANIZER'); if (count($props) == 1) { $output->meetingrequest->organizer = str_ireplace("MAILTO:", "", $props[0]->Value()); } $props = $ical->GetPropertiesByPath('VEVENT/LOCATION'); if (count($props) == 1) { $output->meetingrequest->location = $props[0]->Value(); } $props = $ical->GetPropertiesByPath('VEVENT/CLASS'); if (count($props) == 1) { switch ($props[0]->Value()) { case "PUBLIC": $output->meetingrequest->sensitivity = "0"; break; case "PRIVATE": $output->meetingrequest->sensitivity = "2"; break; case "CONFIDENTIAL": $output->meetingrequest->sensitivity = "3"; break; default: ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->parse_meeting_calendar() - Unknown VEVENT/CLASS '%s'. Using 0", $props[0]->Value())); $output->meetingrequest->sensitivity = "0"; break; } } else { ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar() - No sensitivity class. Using 0"); $output->meetingrequest->sensitivity = "0"; } // Get $tz from first timezone $props = $ical->GetPropertiesByPath("VTIMEZONE/TZID"); if (count($props) > 0) { // TimeZones shouldn't have dots $tzname = str_replace(".", "", $props[0]->Value()); $tz = TimezoneUtil::GetFullTZFromTZName($tzname); } else { $tz = TimezoneUtil::GetFullTZ(); } $output->meetingrequest->timezone = base64_encode(TimezoneUtil::GetSyncBlobFromTZ($tz)); // Fixed values $output->meetingrequest->instancetype = 0; $output->meetingrequest->responserequested = 1; $output->meetingrequest->busystatus = 2; // TODO: reminder $output->meetingrequest->reminder = ""; }
/** * Parse 1 VEvent * @param ical_vtodo $vtodo * @param SyncAppointment(Exception) $message * @param int $truncsize */ private function _ParseVTodoToSyncObject($vtodo, $message, $truncsize) { //Default $message->reminderset = "0"; $message->importance = "1"; $message->complete = "0"; $properties = $vtodo->GetProperties(); foreach ($properties as $property) { switch ($property->Name()) { case "SUMMARY": $message->subject = $property->Value(); break; case "STATUS": switch ($property->Value()) { case "NEEDS-ACTION": case "IN-PROCESS": $message->complete = "0"; break; case "COMPLETED": case "CANCELLED": $message->complete = "1"; break; } break; case "COMPLETED": $message->datecompleted = TimezoneUtil::MakeUTCDate($property->Value()); break; case "DUE": $message->utcduedate = TimezoneUtil::MakeUTCDate($property->Value()); break; case "PRIORITY": $priority = $property->Value(); if ($priority <= 3) { $message->importance = "0"; } if ($priority <= 6) { $message->importance = "1"; } if ($priority > 6) { $message->importance = "2"; } break; case "RRULE": $message->recurrence = $this->_ParseRecurrence($property->Value(), "vtodo"); break; case "CLASS": switch ($property->Value()) { case "PUBLIC": $message->sensitivity = "0"; break; case "PRIVATE": $message->sensitivity = "2"; break; case "CONFIDENTIAL": $message->sensitivity = "3"; break; } break; case "DTSTART": $message->utcstartdate = TimezoneUtil::MakeUTCDate($property->Value()); break; case "SUMMARY": $message->subject = $property->Value(); break; case "CATEGORIES": $categories = explode(",", $property->Value()); $message->categories = $categories; break; } } if (isset($message->recurrence)) { $message->recurrence->start = $message->utcstartdate; } $valarm = current($vtodo->GetComponents("VALARM")); if ($valarm) { $properties = $valarm->GetProperties(); foreach ($properties as $property) { if ($property->Name() == "TRIGGER") { $parameters = $property->Parameters(); if (array_key_exists("VALUE", $parameters) && $parameters["VALUE"] == "DATE-TIME") { $message->remindertime = TimezoneUtil::MakeUTCDate($property->Value()); $message->reminderset = "1"; } elseif (!array_key_exists("VALUE", $parameters) || $parameters["VALUE"] == "DURATION") { $val = str_replace("-", "", $property->Value()); $interval = new DateInterval($val); $start = date_create("@" . $message->utcstartdate); $message->remindertime = date_timestamp_get(date_sub($start, $interval)); $message->reminderset = "1"; } } } } return $message; }