Page MenuHomePhorge

D515.1775238159.diff
No OneTemporary

Authored By
Unknown
Size
12 KB
Referenced Files
None
Subscribers
None

D515.1775238159.diff

diff --git a/lib/kolab_sync.php b/lib/kolab_sync.php
--- a/lib/kolab_sync.php
+++ b/lib/kolab_sync.php
@@ -82,7 +82,7 @@
// e.g. are not using output or rcmail objects or
// doesn't throw errors when using them
$plugins = (array)$this->config->get('activesync_plugins', array('kolab_auth'));
- $plugins = array_unique(array_merge($plugins, array('libkolab')));
+ $plugins = array_unique(array_merge($plugins, array('libcalendaring', 'libkolab')));
// Initialize/load plugins
$this->plugins = kolab_sync_plugin_api::get_instance();
diff --git a/lib/kolab_sync_data.php b/lib/kolab_sync_data.php
--- a/lib/kolab_sync_data.php
+++ b/lib/kolab_sync_data.php
@@ -92,6 +92,11 @@
protected $imap_folders = array();
/**
+ * Shortcut to logging.
+ */
+ protected $log;
+
+ /**
* Timezone
*
* @var string
@@ -186,6 +191,8 @@
$this->defaultRootFolder = $this->defaultFolder . '::Syncroton';
+ $this->log = Syncroton_Registry::get('loggerBackend');
+
// set internal timezone of kolab_format to user timezone
try {
$this->timezone = rcube::get_instance()->config->get('timezone', 'GMT');
@@ -954,18 +961,16 @@
$crc = $matches[1];
$uid = $matches[2];
- if (strlen($entryid) >= 64) {
- foreach ($folder->select(array(array('uid', '~*', $uid))) as $object) {
- if (($object['uid'] == $uid || strpos($object['uid'], $uid) === 0)
- && $crc == $this->objectCRC($object['uid'], $folder)
- ) {
- $object['_folderid'] = $folderid;
- return $object;
- }
+ foreach ($folder->select(array(array('uid', '~*', $uid))) as $object) {
+ if (($object['uid'] == $uid || strpos($object['uid'], $uid) === 0)
+ && $crc == $this->objectCRC($object['uid'], $folder)
+ ) {
+ $object['_folderid'] = $folderid;
+ return $object;
}
-
- continue;
}
+
+ continue;
}
// Or (faster) strict UID matching...
diff --git a/lib/kolab_sync_data_calendar.php b/lib/kolab_sync_data_calendar.php
--- a/lib/kolab_sync_data_calendar.php
+++ b/lib/kolab_sync_data_calendar.php
@@ -180,6 +180,14 @@
public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId, $as_array = false)
{
$event = is_array($serverId) ? $serverId : $this->getObject($collection->collectionId, $serverId);
+
+ // If there is no such event, return NULL (otherwise this function
+ // returns a new Syncroton_Model_Event, that is further treated as if
+ // it were a valid, existing entry.
+ if (!$event) {
+ return NULL;
+ }
+
$config = $this->getFolderConfig($event['_mailbox']);
$result = array();
@@ -273,11 +281,11 @@
if ($name = $attendee['name']) {
$result['organizerName'] = $name;
}
+
if ($email = $attendee['email']) {
$result['organizerEmail'] = $email;
}
- unset($event['attendees'][$idx]);
break;
}
}
@@ -286,11 +294,15 @@
// Attendees
if (!empty($event['attendees'])) {
foreach ($event['attendees'] as $idx => $attendee) {
- $att = array();
+ if ($attendee['role'] == 'ORGANIZER')
+ continue;
+
+ $att = Array();
if ($name = $attendee['name']) {
$att['name'] = $name;
}
+
if ($email = $attendee['email']) {
$att['email'] = $email;
}
@@ -450,32 +462,65 @@
$name = $data->organizerName;
$email = $data->organizerEmail;
if ($name || $email) {
- $event['attendees'][] = array(
+ $_attendee = array(
'role' => 'ORGANIZER',
'name' => $name,
'email' => $email,
);
+
+ if ($this->asversion >= 12) {
+ $_attendee['status'] = $data->meetingStatus == 3 ? 'ACCEPTED' : 'DECLINED';
+ $_attendee['rsvp'] = FALSE;
+ }
+
+ $event['attendees'][] = $_attendee;
}
}
// Attendees
if (isset($data->attendees)) {
foreach ($data->attendees as $attendee) {
+ if ($attendee->email == $data->organizerEmail)
+ continue;
+
$role = false;
+
if (isset($attendee->attendeeType)) {
- $role = array_search($attendee->attendeeType, $this->attendeeTypeMap);
+ $role = array_search(
+ $attendee->attendeeType,
+ $this->attendeeTypeMap
+ );
+
}
+
if ($role === false) {
- $role = array_search(self::ATTENDEE_TYPE_REQUIRED, $this->attendeeTypeMap);
+ $role = array_search(
+ self::ATTENDEE_TYPE_REQUIRED,
+ $this->attendeeTypeMap
+ );
}
- // AttendeeStatus send only on repsonse (?)
-
- $event['attendees'][] = array(
- 'role' => $role,
- 'name' => $attendee->name,
- 'email' => $attendee->email,
+ // AttendeeStatus send only on response (?)
+ $_attendee = array(
+ 'role' => $role,
+ 'name' => $attendee->name,
+ 'email' => $attendee->email,
);
+
+ if ($this->asversion >= 12) {
+ if ($status = $attendee->attendeeStatus) {
+ $_attendee['status'] = array_search(
+ $status,
+ $this->attendeeStatusMap
+ );
+
+ if ($status == self::ATTENDEE_STATUS_UNKNOWN) {
+ $_attendee['rsvp'] = TRUE;
+ }
+ }
+ }
+
+ $event['attendees'][] = $_attendee;
}
}
@@ -506,8 +551,102 @@
*/
public function setAttendeeStatus(Syncroton_Model_MeetingResponse $request)
{
+ /*
+ * The request actually involves an iTip request.
+ *
+ * - Get to the iTip,
+ * - Extract the event UID,
+ * - If not already an event in the user's calendar(s), create the event,
+ * - If already an event, update that event.
+ */
+
+ $object = $this->parseMessageId($request->requestId);
+ $message = new rcube_message($object['uid'], $object['foldername']);
+
+ // Parse the message
+ $libcal = libcalendaring::get_instance();
+ $libcal->mail_message_load(array('object' => $message));
+ $ical_objects = $libcal->get_mail_ical_objects();
+
+ $uid = $ical_objects->objects[0]['uid'];
+
+ // Search the user's (event) folders
+ $folders = $this->listFolders();
+
+ $serverIds = Array();
+ foreach ($folders as $folder => $attrs) {
+ $serverIds[] = $this->serverId($uid, $attrs['imap_name']);
+ }
+
+ // Go search for a match
+ $existing_event = NULL;
+
+ foreach ($serverIds as $serverId) {
+ foreach ($folders as $_folderid => $attrs) {
+ $collection = new Syncroton_Model_SyncCollection(
+ Array(
+ 'collectionId' => $_folderid
+ )
+ );
+
+ $existing_event = $this->getEntry(
+ $collection,
+ $serverId
+ );
+
+ if ($existing_event) {
+ $folderId = $_folderid;
+ break;
+ }
+ }
+
+ if ($existing_event) {
+ break;
+ }
+ }
+
+ /*
+ Consider;
+
+ - $existing_event->sensitivity (private, confidential, public)
+ - $existing_event->attendees[$x]->{role,rsvp,status}
+ - $request->userresponse
+ */
+
+ if ($existing_event) {
+ // This is an existing event that needs updating
+ $user_emails = kolab_sync::get_instance()->user->list_emails();
+ $user_emails = array_map(
+ function($v) { return $v['email']; },
+ $user_emails
+ );
+
+ foreach ($existing_event->attendees as $idx => $attendee) {
+ if (in_array_nocase($attendee->email, $user_emails)) {
+ $this->log->debug("found my record, updating status");
+ switch ($request->userResponse) {
+ case Syncroton_Model_MeetingResponse::RESPONSE_ACCEPTED:
+ $existing_event->attendees[$idx]->attendeeStatus = self::ATTENDEE_STATUS_ACCEPTED;
+ break;
+ case Syncroton_Model_MeetingResponse::RESPONSE_DECLINED:
+ $existing_event->attendees[$idx]->attendeeStatus = self::ATTENDEE_STATUS_DECLINED;
+ break;
+ case Syncroton_Model_MeetingResponse::RESPONSE_TENTATIVE:
+ $existing_event->attendees[$idx]->attendeeStatus = self::ATTENDEE_STATUS_TENTATIVE;
+ break;
+ }
+ }
+ }
+
+ $this->updateEntry($folderId, $serverId, $existing_event);
+
+ } else {
+ // This is a new event
+ $this->log->debug("This is a new event");
+ }
+
// @TODO: not implemented
- throw new Syncroton_Exception_Status_MeetingResponse(Syncroton_Exception_Status_MeetingResponse::MEETING_ERROR);
+ throw new Syncroton_Exception_Status_MeetingResponse(1);
}
/**
@@ -562,20 +701,25 @@
// TODO: Delegation/aliases support
$user_emails = kolab_sync::get_instance()->user->list_emails();
$user_emails = array_map(function($v) { return $v['email']; }, $user_emails);
- $is_organizer = true;
+ $is_organizer = false;
foreach ($event['attendees'] as $attendee) {
+ if ($attendee['role'] != 'ORGANIZER') {
+ // Irrelevant, skip
+ continue;
+ }
+
if (in_array_nocase($attendee['email'], $user_emails)) {
- $is_organizer = false;
+ $is_organizer = true;
break;
}
}
if ($event['status'] == 'CANCELLED') {
- $status = !empty($is_organizer) ? 5 : 7;
+ $status = $is_organizer ? 5 : 7;
}
else {
- $status = !empty($is_organizer) ? 1 : 3;
+ $status = $is_organizer ? 1 : 3;
}
}
@@ -698,4 +842,26 @@
$entry->endTime = $rounded;
}
}
+
+ private function parseMessageId($entryid)
+ {
+ // replyEmail/forwardEmail
+ if (is_array($entryid)) {
+ $entryid = $entryid['itemId'];
+ }
+
+ list($folderid, $uid) = explode('::', $entryid);
+ $foldername = $this->backend->folder_id2name($folderid, $this->device->deviceid);
+
+ if ($foldername === null || $foldername === false) {
+ // @TODO exception?
+ return null;
+ }
+
+ return array(
+ 'uid' => $uid,
+ 'folderid' => $folderid,
+ 'foldername' => $foldername,
+ );
+ }
}

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 3, 5:42 PM (4 d, 5 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18825263
Default Alt Text
D515.1775238159.diff (12 KB)

Event Timeline