Projects
Kolab:16:Enterprise
kolab-syncroton
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 59
View file
kolab-syncroton.spec
Changed
@@ -37,7 +37,7 @@ %global upstream_version 2.4.2 Name: kolab-syncroton -Version: 2.4.2.2 +Version: 2.4.2.9 Release: 1%{?dist} Summary: ActiveSync for Kolab Groupware
View file
debian.changelog
Changed
@@ -1,4 +1,4 @@ -kolab-syncroton (2.4.2.2-0~kolab1) unstable; urgency=low +kolab-syncroton (2.4.2.9-0~kolab1) unstable; urgency=low * Release version 2.4.2
View file
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EmailMeetingRequest.php
Changed
@@ -68,8 +68,6 @@ const MESSAGE_TYPE_COPY = 5; const MESSAGE_TYPE_DELEGATED = 6; - protected $_dateTimeFormat = "Ymd\THis\Z"; - protected $_xmlBaseElement = 'MeetingRequest'; protected $_properties = array( @@ -80,7 +78,7 @@ 'dtStamp' => array('type' => 'datetime'), 'endTime' => array('type' => 'datetime'), 'globalObjId' => array('type' => 'string'), - 'instanceType' => array('type' => 'datetime'), + 'instanceType' => array('type' => 'number'), 'location' => array('type' => 'string'), 'organizer' => array('type' => 'string'), //e-mail address 'recurrenceId' => array('type' => 'datetime'),
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data.php
Changed
@@ -1265,10 +1265,12 @@ if ($count == 2 && $name_items0 == 'x-custom') { $value = null; - foreach ((array) $data'x-custom' as $val) { - if (is_array($val) && $val0 == $name_items1) { - $value = $val1; - break; + if (!empty($data'x-custom') && is_array($data'x-custom')) { + foreach ($data'x-custom' as $val) { + if (is_array($val) && $val0 == $name_items1) { + $value = $val1; + break; + } } }
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data_calendar.php
Changed
@@ -116,7 +116,8 @@ const SENSITIVITY_PRIVATE = 2; const SENSITIVITY_CONFIDENTIAL = 3; - const KEY_DTSTAMP = 'x-custom.X-ACTIVESYNC-DTSTAMP'; + const KEY_DTSTAMP = 'x-custom.X-ACTIVESYNC-DTSTAMP'; + const KEY_REPLYTIME = 'x-custom.X-ACTIVESYNC-REPLYTIME'; /** * Mapping of attendee status @@ -184,6 +185,7 @@ $config = $this->getFolderConfig($event'_mailbox'); $result = array(); $is_outlook = stripos($this->device->devicetype, 'outlook') !== false; + $is_android = stripos($this->device->devicetype, 'android') !== false; // 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 @@ -231,7 +233,7 @@ break; case 'free_busy': - if (!$is_outlook && !empty($value)) { + if (!empty($value)) { $value = $this->busyStatusMap$value; } break; @@ -287,17 +289,17 @@ $user_emails = $this->user_emails(); foreach ($event'attendees' as $idx => $attendee) { - $att = array(); - - if ($email = $attendee'email') { - $att'email' = $email; - } - else { + if (empty($attendee'email')) { // In Activesync email is required continue; } - $att'name' = $attendee'name' ?: $email; + $email = $attendee'email'; + + $att = + 'email' => $email, + 'name' => !empty($attendee'name') ? $attendee'name' : $email, + ; $type = isset($attendee'role') ? $this->attendeeTypeMap$attendee'role' : null; $status = isset($attendee'status') ? $this->attendeeStatusMap$attendee'status' : null; @@ -306,7 +308,7 @@ if (isset($attendee'cutype') && strtolower($attendee'cutype') == 'resource') { $att'attendeeType' = self::ATTENDEE_TYPE_RESOURCE; } else { - $att'attendeeType' = $type ?: self::ATTENDEE_TYPE_REQUIRED; + $att'attendeeType' = $type ?: self::ATTENDEE_TYPE_REQUIRED; } $att'attendeeStatus' = $status ?: self::ATTENDEE_STATUS_UNKNOWN; } @@ -316,7 +318,7 @@ $resp_type = $status ?: self::ATTENDEE_STATUS_UNKNOWN; // Synchronize the attendee status to the event status to get the same behaviour as outlook. - if ($is_outlook) { + if (($is_outlook || $is_android )&& isset($attendee'status')) { if ($attendee'status' == 'ACCEPTED') { $result'busyStatus' = self::BUSY_STATUS_BUSY; } @@ -324,7 +326,6 @@ $result'busyStatus' = self::BUSY_STATUS_TENTATIVE; } } - } $result'attendees' = new Syncroton_Model_EventAttendee($att); @@ -341,6 +342,17 @@ $result'responseRequested' = $result'meetingStatus' == 3 && $user_rsvp ? 1 : 0; $result'responseType' = $result'meetingStatus' == 3 ? $resp_type : null; + // Appointment Reply Time (without it Outlook displays e.g. "Accepted on None") + if ($resp_type != self::ATTENDEE_STATUS_UNKNOWN) { + if ($reply_time = $this->getKolabDataItem($event, self::KEY_REPLYTIME)) { + $result'appointmentReplyTime' = new DateTime($reply_time, new DateTimeZone('UTC')); + } elseif (!empty($event'changed')) { + $reply_time = clone $event'changed'; + $reply_time->setTimezone(new DateTimeZone('UTC')); + $result'appointmentReplyTime' = $reply_time; + } + } + return $as_array ? $result : new Syncroton_Model_Event($result); } @@ -377,6 +389,7 @@ $is_exception = $data instanceof Syncroton_Model_EventException; $dummy_tz = str_repeat('A', 230) . '=='; $is_outlook = stripos($this->device->devicetype, 'outlook') !== false; + $is_android = stripos($this->device->devicetype, 'android') !== false; // check data validity $this->check_event($data); @@ -451,7 +464,7 @@ case 'free_busy': // Outlook sets the busy state to the attendance state, and we don't want to change the event state based on that. // Outlook doesn't have the concept of an event state, so we just ignore this. - if ($is_outlook) { + if ($is_outlook || $is_android) { continue 2; } $map = array_flip($this->busyStatusMap); @@ -562,7 +575,7 @@ } // Outlook does not send the correct attendee status when changing between accepted and tentative, but it toggles the busyStatus. - if ($is_outlook) { + if ($is_outlook || $is_android) { $status = null; if ($data->busyStatus == self::BUSY_STATUS_BUSY) { $status = "ACCEPTED"; @@ -654,11 +667,9 @@ case 'DECLINED': $event'free_busy' = 'free'; break; } */ - // Store Outlook response timestamp for further use - if (stripos($this->device->devicetype, 'outlook') !== false) { - $dtstamp = new DateTime('now', new DateTimeZone('UTC')); - $dtstamp = $dtstamp->format(DateTime::ATOM); - } + // Store response timestamp for further use + $reply_time = new DateTime('now', new DateTimeZone('UTC')); + $this->setKolabDataItem($event, self::KEY_REPLYTIME, $reply_time->format('Ymd\THis\Z')); // Update/Save the event if (empty($existing)) { @@ -778,6 +789,13 @@ // to an iTip request with bumped SEQUENCE $old'sequence' += 1; + // Copy new custom properties + if (!empty($event'x-custom')) { + foreach ($event'x-custom' as $key => $val) { + $old'x-custom'$key = $val; + } + } + // Update the event return $this->save_event($old, $status); }
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data_email.php
Changed
@@ -127,8 +127,12 @@ public static function encodeGlobalObjId(array $data): string { $classid = "040000008200e00074c5b7101a82e008"; - $uid = $data'uid'; - $vcalid = "vCal-Uid\1\0\0\0{$uid}\0"; + if (!empty($data'data')) { + $payload = $data'data'; + } else { + $uid = $data'uid'; + $payload = "vCal-Uid\1\0\0\0{$uid}\0"; + } $packed = pack( "H32nCCPx8Va*", @@ -137,8 +141,8 @@ $data'month' ?? 0, $data'day' ?? 0, $data'now' ?? 0, - strlen($vcalid), - $vcalid + strlen($payload), + $payload ); return base64_encode($packed); @@ -393,34 +397,34 @@ else if ($headers->ctype == 'application/pkcs7-mime' || $headers->ctype == 'application/x-pkcs7-mime') { $result'messageClass' = 'IPM.Note.SMIME'; } - else if ($event = $this->get_invitation_event_from_message($message)) { + // FIXME disabled for now because it results in broken invitations on android (gmail client) and ios + // else if ($event = $this->get_invitation_event_from_message($message)) { + else if (false) { $result'messageClass' = 'IPM.Schedule.Meeting.Request'; $result'contentClass' = 'urn:content-classes:calendarmessage'; $meeting = array(); $meeting'allDayEvent' = $event'allday' ?? null ? 1 : 0; - $meeting'startTime' = $event'start'; - $meeting'dtStamp' = $event'created' ?? null; - $meeting'endTime' = $event'end' ?? null; + $meeting'startTime' = self::date_from_kolab($event'start'); + $meeting'dtStamp' = self::date_from_kolab($event'dtstamp' ?? null); + $meeting'endTime' = self::date_from_kolab($event'end' ?? null); $meeting'location' = $event'location' ?? null; - - //TODO implement recurrences. We can't detect exceptions like this (don't know how), and the recurrences structure is different from event, - //so that also doesn't work like this. - // if (isset($event'recurrence''EXCEPTIONS')) { - // $meeting'instanceType' = Syncroton_Model_EmailMeetingRequest::TYPE_RECURRING_EXCEPTION; - // $this->recurrence_from_kolab($collection, $event, $meeting); - // // } else if (isset($event'recurrence')) { - // // $meeting'instanceType' = Syncroton_Model_EmailMeetingRequest::TYPE_RECURRING_SINGLE; - // // $meeting'recurrenceId' = set the date; - // } else if (isset($event'recurrence')) { - // $meeting'instanceType' = Syncroton_Model_EmailMeetingRequest::TYPE_RECURRING_MASTER; - // $this->recurrence_from_kolab($collection, $event, $meeting); - // } else { - // $meeting'instanceType' = Syncroton_Model_EmailMeetingRequest::TYPE_NORMAL; - // } $meeting'instanceType' = Syncroton_Model_EmailMeetingRequest::TYPE_NORMAL; + if (!empty($event'recurrence_date')) { + $meeting'recurrenceId' = self::date_from_kolab($event'recurrence_date'); + if (!empty($event'status') && $event'status' == 'CANCELLED') { + $meeting'instanceType' = Syncroton_Model_EmailMeetingRequest::TYPE_RECURRING_EXCEPTION; + } else { + $meeting'instanceType' = Syncroton_Model_EmailMeetingRequest::TYPE_RECURRING_SINGLE; + } + } else if (!empty($event'recurrence')) { + $meeting'instanceType' = Syncroton_Model_EmailMeetingRequest::TYPE_RECURRING_MASTER; + // TODO: MeetingRequest recurrence is different that the one in Calendar + // $this->recurrence_from_kolab($collection, $event, $meeting); + } + // Organizer if (!empty($event'attendees')) { foreach ($event'attendees' as $idx => $attendee) { @@ -431,10 +435,18 @@ } } + $fileTime = ($event'start'->getTimestamp() + 11644473600) * 10000000; // 1.1.1600 - 1.1.1970 difference in seconds. Converted to microseconds + // 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 $meeting'timeZone' = kolab_sync_timezone_converter::encodeTimezoneFromDate($event'start'); - $meeting'globalObjId' = self::encodeGlobalObjId('uid' => $event'uid'); + $meeting'globalObjId' = self::encodeGlobalObjId( + 'uid' => $event'uid', + 'year' => intval($event'start'->format('Y')), + 'month' => intval($event'start'->format('n')), + 'day' => intval($event'start'->format('j')), + 'now' => $fileTime, + ); // TODO handle other methods if ($event'_method' == 'REQUEST') { @@ -443,6 +455,10 @@ $meeting'meetingMessageType' = Syncroton_Model_EmailMeetingRequest::MESSAGE_TYPE_NORMAL; } + // New time proposals aren't supported by Kolab. + // This disables the UI elements related to this on the client side + $meeting'disallowNewTimeProposal' = 1; + $result'meetingRequest' = new Syncroton_Model_EmailMeetingRequest($meeting); } @@ -452,6 +468,8 @@ $result'categories' = $this->getKolabTags($message); } + $is_ios = preg_match('/(iphone|ipad)/i', $this->device->devicetype); + // attachments $attachments = array_merge($message->attachments, $message->inline_parts); if (!empty($attachments)) { @@ -460,6 +478,10 @@ foreach ($attachments as $attachment) { $att = array(); + if ($is_ios && !empty($event) && $attachment->mime_id == $event'_mime_id') { + continue; + } + $filename = rcube_charset::clean($attachment->filename); if (empty($filename) && $attachment->mimetype == 'text/html') { $filename = 'HTML Part'; @@ -1787,9 +1809,12 @@ foreach ($ical_objects as $mime_id => $event) { if ($event'_type' == 'event') { $event'_method' = $ical_objects->method; + $event'_mime_id' = $ical_objects->mime_id; + return $event; } } + return null; }
View file
kolab-syncroton-2.4.2.tar.gz/tests/globalid_converter.php
Changed
@@ -1,11 +1,11 @@ <?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() + /** + * Test GlobalObjId encoding/decoding + */ + function test_globalobjid() { // https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-asemail/e7424ddc-dd10-431e-a0b7-5c794863370e $input = 'BAAAAIIA4AB0xbcQGoLgCAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAAHZDYWwtVWlkAQAAAHs4MTQxMkQzQy0yQTI0LTRFOUQtQjIwRS0xMUY3QkJFOTI3OTl9AA=='; @@ -17,7 +17,6 @@ $encoded = kolab_sync_data_email::encodeGlobalObjId($output); $this->assertSame($encoded, $input); - $input = 'BAAAAIIA4AB0xbcQGoLgCAfUCRDgQMnBJoXEAQAAAAAAAAAAEAAAAAvw7UtuTulOnjnjhns3jvM='; $output = kolab_sync_data_email::decodeGlobalObjId($input); @@ -25,8 +24,14 @@ $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); + $this->assertSame(127373090979660000, $output'now'); + + // This is how the "now" value is interpreted + // $winSecs = (int)($output'now' / 10000000); // convert microseconds to seconds + // $unixTimestamp = ($winSecs - 11644473600); // subtract 1.1.1600 - 1.1.1970 difference in seconds + // print(date(DateTime::RFC822, $unixTimestamp)); + + $encoded = kolab_sync_data_email::encodeGlobalObjId($output); + $this->assertSame($encoded, $input); } }
View file
kolab-syncroton-2.4.2.tar.gz/tests/phpunit.xml
Changed
@@ -7,8 +7,10 @@ <file>data.php</file> <file>data_calendar.php</file> <file>data_tasks.php</file> + <file>globalid_converter.php</file> <file>message.php</file> <file>timezone_converter.php</file> + <file>wbxml.php</file> </testsuite> </testsuites> </phpunit>
View file
kolab-syncroton-2.4.2.tar.gz/tests/wbxml.php
Changed
@@ -1,6 +1,6 @@ <?php -class message extends PHPUnit\Framework\TestCase +class wbxml extends PHPUnit\Framework\TestCase { //function testDecode() //{ @@ -881,8 +881,12 @@ $dom = new DOMDocument(); $dom->loadXML($xml); - + + $start = microtime(true); $encoder->encode($dom); + $end = microtime(true); + + $this->assertTrue($end - $start < 0.05); } }
View file
kolab-syncroton.dsc
Changed
@@ -2,7 +2,7 @@ Source: kolab-syncroton Binary: kolab-syncroton Architecture: all -Version: 1:2.4.2.2-1~kolab1 +Version: 1:2.4.2.9-1~kolab1 Maintainer: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> Uploaders: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> Homepage: http://www.kolab.org/
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.