10926 private flag not working in iOS / OSX
authorPhilipp Schüle <p.schuele@metaways.de>
Wed, 25 Mar 2015 13:48:38 +0000 (14:48 +0100)
committerPhilipp Schüle <p.schuele@metaways.de>
Thu, 26 Mar 2015 10:01:06 +0000 (11:01 +0100)
* use OSX CalDAV converter as bases for iOS
* OSX 10.10 iCal writes X-CALENDARSERVER-ACCESS property to VCALENDAR
  component instead of VEVENT
* adds a test for iOS ics with X-CALENDARSERVER-ACCESS:CONFIDENTIAL

NOTE: iCal does not display the private field as soon as an attendee
      or an organizer is present in the VCALENDAR. This means one can
      set private flag from the client but not see/edit it in case
      the event was once retrieved from server

https://forge.tine20.org/view.php?id=10926

Change-Id: I903663fcaf48749fde6d80e95dde9436e4133996
Reviewed-on: http://gerrit.tine20.com/customers/1766
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
Tested-by: Philipp Schüle <p.schuele@metaways.de>
tests/tine20/Calendar/Convert/Event/VCalendar/MacOSXTest.php
tests/tine20/Calendar/Import/files/ios_private.ics [new file with mode: 0644]
tine20/Calendar/Convert/Event/VCalendar/Abstract.php
tine20/Calendar/Convert/Event/VCalendar/Iphone.php
tine20/Calendar/Convert/Event/VCalendar/MacOSX.php
tine20/Calendar/Frontend/WebDAV/Event.php
tine20/Tinebase/Convert/Interface.php

index c5445b4..5f4c0d6 100644 (file)
@@ -85,7 +85,7 @@ class Calendar_Convert_Event_VCalendar_MacOSXTest extends PHPUnit_Framework_Test
 
     public function testConvertToTine20ModelXCalendarAccess()
     {
-        $converter = Calendar_Convert_Event_VCalendar_Factory::factory(Calendar_Convert_Event_VCalendar_Factory::CLIENT_MACOSX, '10.7.5');
+        $converter = Calendar_Convert_Event_VCalendar_Factory::factory(Calendar_Convert_Event_VCalendar_Factory::CLIENT_MACOSX, '10.10.2');
 
         $vcalendarStream = fopen(dirname(__FILE__) . '/../../../Import/files/apple_calendar_lion_access_private.ics', 'r');
         $event = $converter->toTine20Model($vcalendarStream);
@@ -94,5 +94,18 @@ class Calendar_Convert_Event_VCalendar_MacOSXTest extends PHPUnit_Framework_Test
         $vcalendarStream = fopen(dirname(__FILE__) . '/../../../Import/files/apple_calendar_lion_access_attendee.ics', 'r');
         $event = $converter->toTine20Model($vcalendarStream);
         $this->assertEquals(Calendar_Model_Event::CLASS_PUBLIC, $event->class);
+
+        $iosPrivateIcs = dirname(__FILE__) . '/../../../Import/files/ios_private.ics';
+        $vcalendarStream = fopen($iosPrivateIcs, 'r');
+        $event = $converter->toTine20Model($vcalendarStream);
+        $this->assertEquals(Calendar_Model_Event::CLASS_PRIVATE, $event->class);
+
+        // try again with ios user agent
+        $iosUserAgent = 'iOS/8.2 (12D508) dataaccessd/1.0';
+        list($backend, $version) = Calendar_Convert_Event_VCalendar_Factory::parseUserAgent($iosUserAgent);
+        $converter = Calendar_Convert_Event_VCalendar_Factory::factory($backend, $version);
+        $vcalendarStream = fopen($iosPrivateIcs, 'r');
+        $event = $converter->toTine20Model($vcalendarStream);
+        $this->assertEquals(Calendar_Model_Event::CLASS_PRIVATE, $event->class);
     }
 }
diff --git a/tests/tine20/Calendar/Import/files/ios_private.ics b/tests/tine20/Calendar/Import/files/ios_private.ics
new file mode 100644 (file)
index 0000000..1ef52f3
--- /dev/null
@@ -0,0 +1,34 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Apple Inc.//iOS 8.2//EN
+VERSION:2.0
+X-CALENDARSERVER-ACCESS:CONFIDENTIAL
+BEGIN:VTIMEZONE
+TZID:Europe/Berlin
+BEGIN:DAYLIGHT
+DTSTART:19810329T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
+TZNAME:MESZ
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:19961027T030000
+RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
+TZNAME:MEZ
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+CREATED:20150325T133444Z
+DTEND;TZID=Europe/Berlin:20150327T154500
+DTSTAMP:20150325T133500Z
+DTSTART;TZID=Europe/Berlin:20150327T144500
+LAST-MODIFIED:20150325T133444Z
+SEQUENCE:1
+SUMMARY:Privates
+TRANSP:OPAQUE
+UID:464683D1-15A8-4874-A6E4-1536C9669842
+END:VEVENT
+END:VCALENDAR
index 5f8510c..a153a03 100644 (file)
@@ -183,13 +183,13 @@ class Calendar_Convert_Event_VCalendar_Abstract extends Tinebase_Convert_VCalend
 
             if ($organizerContact instanceof Addressbook_Model_Contact && !empty($organizerContact->email)) {
                 $organizer = $vevent->add(
-                    'ORGANIZER', 
-                    'mailto:' . $organizerContact->email, 
+                    'ORGANIZER',
+                    'mailto:' . $organizerContact->email,
                     array('CN' => $organizerContact->n_fileas, 'EMAIL' => $organizerContact->email)
                 );
             }
         }
-        
+
         $this->_addEventAttendee($vevent, $event);
         
         $optionalProperties = array(
@@ -210,9 +210,9 @@ class Calendar_Convert_Event_VCalendar_Abstract extends Tinebase_Convert_VCalend
             }
         }
 
-        $vevent->add('X-CALENDARSERVER-ACCESS',
-            $event->class == Calendar_Model_Event::CLASS_PUBLIC ? 'PUBLIC' : 'CONFIDENTIAL'
-        );
+        $class = $event->class == Calendar_Model_Event::CLASS_PUBLIC ? 'PUBLIC' : 'CONFIDENTIAL';
+        $vcalendar->add('X-CALENDARSERVER-ACCESS', $class);
+        $vevent->add('X-CALENDARSERVER-ACCESS', $class);
 
         // categories
         if (!isset($event->tags)) {
@@ -678,7 +678,7 @@ class Calendar_Convert_Event_VCalendar_Abstract extends Tinebase_Convert_VCalend
      */
     protected function _convertVevent(\Sabre\VObject\Component\VEvent $vevent, Calendar_Model_Event $event, $options)
     {
-        if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) 
+        if (Tinebase_Core::isLogLevel(Zend_Log::TRACE))
             Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' vevent ' . $vevent->serialize());
         
         $newAttendees = array();
index 2de9fe2..a6be4c1 100644 (file)
  * @package     Calendar
  * @subpackage  Convert
  */
-class Calendar_Convert_Event_VCalendar_Iphone extends Calendar_Convert_Event_VCalendar_Abstract
+class Calendar_Convert_Event_VCalendar_Iphone extends Calendar_Convert_Event_VCalendar_MacOSX
 {
     // DAVKit/4.0 (728.4); iCalendar/1 (42.1); iPhone/3.1.3 7E18
     // DAVKit/5.0 (767); iCalendar/5.0 (79); iPhone/4.2.1 8C148
     // iOS/5.0.1 (9A405) dataaccessd/1.0
+    // iOS/7.1.2 (11D257) dataaccessd/1.0
+    // iOS/8.2 (12D508) dataaccessd/1.0
     const HEADER_MATCH = '/(iPhone|iOS)\/(?P<version>\S+)/';
-    
-    protected $_supportedFields = array(
-        'seq',
-        'dtend',
-        'transp',
-        'class',
-        'description',
-        #'geo',
-        'location',
-        'priority',
-        'summary',
-        'url',
-        'alarms',
-        #'tags',
-        'dtstart',
-        'exdate',
-        'rrule',
-        'recurid',
-        'is_all_day_event',
-        #'rrule_until',
-        'originator_tz'
-    );
 }
index f7379b3..88daafe 100644 (file)
@@ -79,12 +79,10 @@ class Calendar_Convert_Event_VCalendar_MacOSX extends Calendar_Convert_Event_VCa
     {
         $return = parent::_findMainEvent($vcalendar);
 
-        if (version_compare($this->_version, '10.8', '<')) {
-            // NOTE 10.7 sometimes writes access into calendar property
-            if (isset($vcalendar->{'X-CALENDARSERVER-ACCESS'})) {
-                foreach ($vcalendar->VEVENT as $vevent) {
-                    $vevent->{'X-CALENDARSERVER-ACCESS'} = $vcalendar->{'X-CALENDARSERVER-ACCESS'};
-                }
+        // NOTE 10.7 and 10.10 sometimes write access into calendar property
+        if (isset($vcalendar->{'X-CALENDARSERVER-ACCESS'})) {
+            foreach ($vcalendar->VEVENT as $vevent) {
+                $vevent->{'X-CALENDARSERVER-ACCESS'} = $vcalendar->{'X-CALENDARSERVER-ACCESS'};
             }
         }
 
@@ -102,13 +100,11 @@ class Calendar_Convert_Event_VCalendar_MacOSX extends Calendar_Convert_Event_VCa
     {
         $return = parent::_convertVevent($vevent, $event, $options);
 
-        if (version_compare($this->_version, '10.8', '<')) {
-            // NOTE: 10.7 sometimes uses (internal?) int's
-            if (isset($vevent->{'X-CALENDARSERVER-ACCESS'}) && (int) (string) $vevent->{'X-CALENDARSERVER-ACCESS'} > 0) {
-                $event->class = (int) (string) $vevent->{'X-CALENDARSERVER-ACCESS'} == 1 ?
-                    Calendar_Model_Event::CLASS_PUBLIC :
-                    Calendar_Model_Event::CLASS_PRIVATE;
-            }
+        // NOTE: 10.7 sometimes uses (internal?) int's
+        if (isset($vevent->{'X-CALENDARSERVER-ACCESS'}) && (int) (string) $vevent->{'X-CALENDARSERVER-ACCESS'} > 0) {
+            $event->class = (int) (string) $vevent->{'X-CALENDARSERVER-ACCESS'} == 1 ?
+                Calendar_Model_Event::CLASS_PUBLIC :
+                Calendar_Model_Event::CLASS_PRIVATE;
         }
 
         return $return;
index d448c1b..91ecbab 100644 (file)
@@ -438,6 +438,10 @@ class Calendar_Frontend_WebDAV_Event extends Sabre\DAV\File implements Sabre\Cal
             Calendar_Convert_Event_VCalendar_Abstract::OPTION_USE_SERVER_MODLOG => true,
         ));
 
+        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG))
+            Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " " . print_r($event->toArray(), true));
+
+
         $currentEvent = $this->getRecord();
         $currentContainer = Tinebase_Container::getInstance()->getContainerById($currentEvent->container_id);
 
index 262c714..20a4b06 100644 (file)
@@ -23,7 +23,7 @@ interface Tinebase_Convert_Interface
      * 
      * @param  mixed                     $_blob
      * @param  Tinebase_Record_Abstract  $_record  update existing record
-     * @return Tinebase_Model_Contact
+     * @return Tinebase_Record_Abstract
      */
     public function toTine20Model($_blob, Tinebase_Record_Abstract $_record = null);