Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117771454
D515.1775238159.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
12 KB
Referenced Files
None
Subscribers
None
D515.1775238159.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D515: Implement setAttendeeStatus
Attached
Detach File
Event Timeline