Page MenuHomePhorge

D473.1775958209.diff
No OneTemporary

Authored By
Unknown
Size
7 KB
Referenced Files
None
Subscribers
None

D473.1775958209.diff

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
@@ -484,7 +484,7 @@
throw new Syncroton_Exception_Status_Sync(Syncroton_Exception_Status_Sync::SYNC_SERVER_ERROR);
}
- return $entry['uid'];
+ return $entry['_serverId'];
}
/**
@@ -505,13 +505,13 @@
}
$entry = $this->toKolab($entry, $folderId, $oldEntry);
- $entry = $this->updateObject($folderId, $serverId, $entry);
+ $entry = $this->updateObject($folderId, $serverId, $entry);
if (empty($entry)) {
throw new Syncroton_Exception_Status_Sync(Syncroton_Exception_Status_Sync::SYNC_SERVER_ERROR);
}
- return $entry['uid'];
+ return $entry['_serverId'];
}
/**
@@ -602,8 +602,8 @@
if (!is_array($uids)) {
$error = true;
}
- else {
- $result = array_merge($result, $uids);
+ else if (!empty($uids)) {
+ $result = array_merge($result, $this->applyServerId($uids, $folder));
}
break;
}
@@ -641,8 +641,8 @@
case self::RESULT_UID:
$uids = $folder->get_uids($tag_filter);
- if (is_array($uids)) {
- $result = array_unique(array_merge($result, $uids));
+ if (is_array($uids) && !empty($uids)) {
+ $result = array_unique(array_merge($result, $this->applyServerId($uids, $folder)));
}
break;
@@ -944,10 +944,37 @@
$foldername = $this->backend->folder_id2name($folderid, $this->device->deviceid);
$folder = $this->getFolderObject($foldername);
- if ($folder && $folder->valid && ($object = $folder->get_object($entryid))) {
- $object['_folderid'] = $folderid;
+ if ($folder && $folder->valid) {
+ $crc = null;
+ $uid = $entryid;
+
+ // See self::serverId() for full explanation
+ // Use (slower) UID prefix matching...
+ if (preg_match('/^CRC([0-9A-Fa-f]{8})(.+)$/', $uid, $matches)) {
+ $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;
+ }
+ }
+
+ continue;
+ }
+ }
- return $object;
+ // Or (faster) strict UID matching...
+ if (($object = $folder->get_object($uid))
+ && ($crc === null || $crc == $this->objectCRC($object['uid'], $folder))
+ ) {
+ $object['_folderid'] = $folderid;
+ return $object;
+ }
}
}
}
@@ -981,6 +1008,8 @@
$this->setKolabTags($data['uid'], $tags);
}
+ $data['_serverId'] = $this->serverId($data['uid'], $folder);
+
return $data;
}
}
@@ -1006,6 +1035,8 @@
$this->setKolabTags($data['uid'], $tags);
}
+ $data['_serverId'] = $this->serverId($object['uid'], $folder);
+
return $data;
}
}
@@ -1021,7 +1052,7 @@
if ($object) {
$folder = $this->getFolderObject($object['_mailbox']);
- if ($folder && $folder->valid && $folder->delete($entryid)) {
+ if ($folder && $folder->valid && $folder->delete($object['uid'])) {
if ($this->tag_categories) {
$this->setKolabTags($object['uid'], null);
}
@@ -1848,4 +1879,65 @@
return false;
}
+
+ /**
+ * Generate CRC-based ServerId from object UID
+ */
+ protected function serverId($uid, $folder)
+ {
+ if ($this->modelName == 'mail') {
+ return $uid;
+ }
+
+ // When ActiveSync communicates with the client, it refers to objects with a ServerId
+ // We can't use object UID for ServerId because:
+ // - ServerId is limited to 64 chars,
+ // - there can be multiple calendars with a copy of the same event.
+ //
+ // The solution is to; Take the original UID, and regardless of its length, execute the following:
+ // - Hash the UID concatenated with the Folder ID using CRC32b,
+ // - Prefix the UID with 'CRC' and the hash string,
+ // - Tryncate the result to 64 characters.
+ //
+ // Searching for the server-side copy of the object now follows the logic;
+ // - If the ServerId is prefixed with 'CRC', strip off the first 11 characters
+ // and we search for the UID using the remainder;
+ // - if the UID is shorter than 53 characters, it'll be the complete UID,
+ // - if the UID is longer than 53 characters, it'll be the truncated UID,
+ // and we search for a wildcard match of <uid>*
+ // When multiple copies of the same event are found, the same CRC32b hash can be used
+ // on the events metadata (i.e. the copy's UID and Folder ID), and compared with the CRC from the ServerId.
+
+ // ServerId is max. 64 characters, below we generate a string of max. 64 chars
+ // Note: crc32b is always 8 characters
+ return 'CRC' . $this->objectCRC($uid, $folder) . substr($uid, 0, 53);
+ }
+
+ /**
+ * Calculate checksum on object UID and folder UID
+ */
+ protected function objectCRC($uid, $folder)
+ {
+ if (!is_object($folder)) {
+ $folder = $this->getFolderObject($folder);
+ }
+
+ $folder_uid = $folder->get_uid();
+
+ return strtoupper(hash('crc32b', $folder_uid . $uid)); // always 8 chars
+ }
+
+ /**
+ * Apply serverId() on a set of uids
+ */
+ protected function applyServerId($uids, $folder)
+ {
+ if (!empty($uids) && $this->modelName != 'mail') {
+ $self = $this;
+ $func = function($uid) use ($self, $folder) { return $self->serverId($uid, $folder); };
+ $uids = array_map($func, $uids);
+ }
+
+ return $uids;
+ }
}
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
@@ -413,14 +413,6 @@
continue 2;
}
break;
-
- case 'uid':
- // If UID is too long, use auto-generated UID (#1034)
- // It's because UID is used as ServerId which cannot be longer than 64 chars
- if (strlen($value) > 64) {
- $value = null;
- }
- break;
}
$this->setKolabDataItem($event, $name, $value);

File Metadata

Mime Type
text/plain
Expires
Sun, Apr 12, 1:43 AM (4 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18833841
Default Alt Text
D473.1775958209.diff (7 KB)

Event Timeline