Page MenuHomePhorge

D4436.1775297487.diff
No OneTemporary

Authored By
Unknown
Size
7 KB
Referenced Files
None
Subscribers
None

D4436.1775297487.diff

diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -117,6 +117,48 @@
}
}
+ /**
+ * Encode a globalObjId according to https://interoperability.blob.core.windows.net/files/MS-ASEMAIL/%5bMS-ASEMAIL%5d-150526.pdf 2.2.2.3
+ *
+ * @param array $data An array with the data to encode
+ *
+ * @return string the encoded globalObjId
+ */
+ public static function encodeGlobalObjId(array $data): string
+ {
+ $classid = "040000008200e00074c5b7101a82e008";
+ $uid = $data['uid'];
+ $vcalid = "vCal-Uid\1\0\0\0{$uid}\0";
+
+ $packed = pack(
+ "H32nCCPx8Va*",
+ $classid,
+ $data['year'] ?? 0,
+ $data['month'] ?? 0,
+ $data['day'] ?? 0,
+ $data['now'] ?? 0,
+ strlen($vcalid),
+ $vcalid
+ );
+
+ return base64_encode($packed);
+ }
+
+ /**
+ * Decode a globalObjId according to https://interoperability.blob.core.windows.net/files/MS-ASEMAIL/%5bMS-ASEMAIL%5d-150526.pdf 2.2.2.3
+ *
+ * @param string the encoded globalObjId
+ *
+ * @return array An array with the decoded data
+ */
+ public static function decodeGlobalObjId(string $globalObjId): array
+ {
+ $unpackString = 'H32classid/nyear/Cmonth/Cday/Pnow/x8/Vbytecount/a*data';
+ $decoded = unpack($unpackString, base64_decode($globalObjId));
+ $decoded['uid'] = substr($decoded['data'], strlen("vCal-Uid\1\0\0\0"), -1);
+ return $decoded;
+ }
+
/**
* Creates model object
*
@@ -339,20 +381,54 @@
$result['nativeBodyType'] = $message->has_html_part() ? 2 : 1;
// Message class
+ $result['messageClass'] = 'IPM.Note';
+ $result['contentClass'] = 'urn:content-classes:message';
+
if ($headers->ctype == 'multipart/signed'
&& !empty($message->parts[1])
&& $message->parts[1]->mimetype == 'application/pkcs7-signature'
) {
$result['messageClass'] = 'IPM.Note.SMIME.MultipartSigned';
+ $result['contentClass'] = 'urn:content-classes:message';
}
else if ($headers->ctype == 'application/pkcs7-mime' || $headers->ctype == 'application/x-pkcs7-mime') {
$result['messageClass'] = 'IPM.Note.SMIME';
- }
- else {
- $result['messageClass'] = 'IPM.Note';
- }
+ $result['contentClass'] = 'urn:content-classes:message';
+ }
+ //TODO detect the correct type
+ else if ($headers->ctype == 'multipart/alternative' || $headers->ctype == 'text/calendar') {
+ if ($event = $this->get_invitation_event_from_message($message)) {
+ $result['messageClass'] = 'IPM.Schedule.Meeting.Request';
+ $result['contentClass'] = 'urn:content-classes:calendarmessage';
+
+ $meeting = array();
+
+ //TODO fill in the details
+ $meeting['allDayEvent'] = 0;
+ $meeting['startTime'] = $event['start'];
+ $meeting['dtStamp'] = $event['created'];
+ $meeting['endTime'] = $event['end'];
+ //TODO set recurring or not
+ $meeting['instanceType'] = Syncroton_Model_EmailMeetingRequest::TYPE_NORMAL;
+ // Timezone
+ // Kolab Format 3.0 and xCal does support timezone per-date, but ActiveSync allows
+ // only one timezone per-event. We'll use timezone of the start date
+ if ($event['start'] instanceof DateTime) {
+ $timezone = $event['start']->getTimezone();
+
+ if ($timezone && ($tz_name = $timezone->getName()) != 'UTC') {
+ $tzc = kolab_sync_timezone_converter::getInstance();
+ if ($tz_name = $tzc->encodeTimezone($tz_name, $event['start']->format('Y-m-d'))) {
+ $meeting['timeZone'] = $tz_name;
+ }
+ }
+ }
+ $meeting['globalObjId'] = self::encodeGlobalObjId(['uid' => $event['uid']]);
+ $meeting['meetingMessageType'] = Syncroton_Model_EmailMeetingRequest::MESSAGE_TYPE_NORMAL;
- $result['contentClass'] = 'urn:content-classes:message';
+ $result['meetingRequest'] = new Syncroton_Model_EmailMeetingRequest($meeting);
+ }
+ }
// Categories (Tags)
if (isset($this->tag_categories) && $this->tag_categories) {
@@ -1672,6 +1748,25 @@
return $out;
}
+ /**
+ * Returns calendar event data from the iTip invitation attached to a mail message
+ */
+ public function get_invitation_event_from_message($message)
+ {
+ // Parse the message and find iTip attachments
+ $libcal = libcalendaring::get_instance();
+ $libcal->mail_message_load(array('object' => $message));
+ $ical_objects = $libcal->get_mail_ical_objects();
+
+ // We support only one event in the iTip
+ foreach ($ical_objects as $mime_id => $event) {
+ if ($event['_type'] == 'event') {
+ return $event;
+ }
+ }
+ return null;
+ }
+
/**
* Returns calendar event data from the iTip invitation attached to a mail message
*/
@@ -1679,18 +1774,9 @@
{
// Get the mail message object
if ($message = $this->getObject($messageId)) {
- // Parse the message and find iTip attachments
- $libcal = libcalendaring::get_instance();
- $libcal->mail_message_load(array('object' => $message));
- $ical_objects = $libcal->get_mail_ical_objects();
-
- // We support only one event in the iTip
- foreach ($ical_objects as $mime_id => $event) {
- if ($event['_type'] == 'event') {
- return $event;
- }
- }
+ return $this->get_invitation_event_from_message($message);
}
+ return null;
}
diff --git a/tests/globalid_converter.php b/tests/globalid_converter.php
new file mode 100644
--- /dev/null
+++ b/tests/globalid_converter.php
@@ -0,0 +1,32 @@
+<?php
+
+require_once "../lib/kolab_sync_data.php";
+require_once "../lib/kolab_sync_data_email.php";
+
+class globalid_converter extends PHPUnit\Framework\TestCase
+{
+ function test_decode()
+ {
+ // https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-asemail/e7424ddc-dd10-431e-a0b7-5c794863370e
+ $input = 'BAAAAIIA4AB0xbcQGoLgCAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAAHZDYWwtVWlkAQAAAHs4MTQxMkQzQy0yQTI0LTRFOUQtQjIwRS0xMUY3QkJFOTI3OTl9AA==';
+ $output = kolab_sync_data_email::decodeGlobalObjId($input);
+
+ $this->assertSame(51, $output['bytecount']);
+ $this->assertSame('{81412D3C-2A24-4E9D-B20E-11F7BBE92799}', $output['uid']);
+
+ $encoded = kolab_sync_data_email::encodeGlobalObjId($output);
+ $this->assertSame($encoded, $input);
+
+
+ $input = 'BAAAAIIA4AB0xbcQGoLgCAfUCRDgQMnBJoXEAQAAAAAAAAAAEAAAAAvw7UtuTulOnjnjhns3jvM=';
+ $output = kolab_sync_data_email::decodeGlobalObjId($input);
+
+ $this->assertSame(16, $output['bytecount']);
+ $this->assertSame(2004, $output['year']);
+ $this->assertSame(9, $output['month']);
+ $this->assertSame(16, $output['day']);
+ //FIXME we don't currently implement non ical uids
+ // $encoded = kolab_sync_data_email::encodeGlobalObjId($output);
+ // $this->assertSame($encoded, $input);
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 4, 10:11 AM (8 h, 50 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18828946
Default Alt Text
D4436.1775297487.diff (7 KB)

Event Timeline