Branch 'roundcubemail-plugins-kolab-format2' - plugins/libkolab

Thomas Brüderli bruederli at kolabsys.com
Mon Nov 12 17:13:13 CET 2012


 plugins/libkolab/README                                |   15 
 plugins/libkolab/config.inc.php.dist                   |    2 
 plugins/libkolab/lib/kolab_format.php                  |  115 +---
 plugins/libkolab/lib/kolab_format_configuration.php    |   59 --
 plugins/libkolab/lib/kolab_format_contact.php          |  373 +--------------
 plugins/libkolab/lib/kolab_format_distributionlist.php |   72 ---
 plugins/libkolab/lib/kolab_format_event.php            |   98 ----
 plugins/libkolab/lib/kolab_format_journal.php          |   43 -
 plugins/libkolab/lib/kolab_format_note.php             |   42 -
 plugins/libkolab/lib/kolab_format_task.php             |   58 --
 plugins/libkolab/lib/kolab_format_xcal.php             |  400 -----------------
 plugins/libkolab/lib/kolab_storage.php                 |    2 
 plugins/libkolab/lib/kolab_storage_cache.php           |    4 
 plugins/libkolab/lib/kolab_storage_folder.php          |   12 
 plugins/libkolab/libkolab.php                          |    7 
 15 files changed, 126 insertions(+), 1176 deletions(-)

New commits:
commit d9cd404227f62656fab48620336397cdc351a605
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Mon Nov 12 16:17:52 2012 +0100

    Remove libkolab(xml) dependecies and function calls; require Horde_Kolab_Format* classes

diff --git a/plugins/libkolab/README b/plugins/libkolab/README
index 0a3c0ce..7e27c79 100644
--- a/plugins/libkolab/README
+++ b/plugins/libkolab/README
@@ -1,22 +1,17 @@
-libkolab plugin to access to Kolab groupware data
-=================================================
+libkolab plugin to access to Kolab groupware 2.x data
+=====================================================
 
 The contained library classes establish a connection to the Kolab server
 and manage the access to the Kolab groupware objects stored in various
-IMAP folders. For reading and writing these objects, the PHP bindings of
-the libkolabxml library are used.
+IMAP folders. For reading and writing these objects, the Horde Kolab_Format
+packages are used.
 
 
 REQUIREMENTS
 ------------
-* libkolabxml PHP bindings
-  - kolabformat.so loaded into PHP
-  - kolabformat.php placed somewhere in the include_path
 * PEAR: HTTP/Request2
 * PEAR: Net/URL2
-
-* Optional for old format support:
-  Horde Kolab_Format package and all of its dependencies
+* Horde Kolab_Format package and all of its dependencies
   which are at least Horde_(Browser,DOM,NLS,String,Utils)
 
 
diff --git a/plugins/libkolab/config.inc.php.dist b/plugins/libkolab/config.inc.php.dist
index cb44652..496a3f9 100644
--- a/plugins/libkolab/config.inc.php.dist
+++ b/plugins/libkolab/config.inc.php.dist
@@ -2,7 +2,7 @@
     /* Configuration for libkolab */
 
     $rcmail_config['kolab_cache'] = true;
-	$rcmail_config['kolab_format_version']  = 3.0;
+    $rcmail_config['kolab_format_version']  = 3.0;
 
     $rcmail_config['kolab_freebusy_server'] = 'https://' . $_SESSION['imap_host'] . '/freebusy';
     $rcmail_config['kolab_ssl_verify_peer'] = true;
diff --git a/plugins/libkolab/lib/kolab_format.php b/plugins/libkolab/lib/kolab_format.php
index a414781..622b411 100644
--- a/plugins/libkolab/lib/kolab_format.php
+++ b/plugins/libkolab/lib/kolab_format.php
@@ -1,10 +1,10 @@
 <?php
 
 /**
- * Kolab format model class wrapping libkolabxml bindings
+ * Kolab format model class
  *
  * Abstract base class for different Kolab groupware objects read from/written
- * to the new Kolab 3 format using the PHP bindings of libkolabxml.
+ * to the Kolab 2 format using Horde_Kolab_Format classes.
  *
  * @version @package_version@
  * @author Thomas Bruederli <bruederli at kolabsys.com>
@@ -30,21 +30,18 @@ abstract class kolab_format
     public static $timezone;
 
     public /*abstract*/ $CTYPE;
-    public /*abstract*/ $CTYPEv2;
 
-    protected /*abstract*/ $objclass;
-    protected /*abstract*/ $read_func;
-    protected /*abstract*/ $write_func;
+    protected /*abstract*/ $xmltype;
+    protected /*abstract*/ $subtype;
 
-    protected $obj;
+    protected $handler;
     protected $data;
     protected $xmldata;
-    protected $xmlobject;
     protected $loaded = false;
-    protected $version = 3.0;
+    protected $version = 2.0;
 
     const KTYPE_PREFIX = 'application/x-vnd.kolab.';
-    const PRODUCT_ID = 'Roundcube-libkolab-0.9';
+    const PRODUCT_ID = 'Roundcube-libkolab-horde-0.9';
 
     /**
      * Factory method to instantiate a kolab_format object of the given type and version
@@ -54,7 +51,7 @@ abstract class kolab_format
      * @param string Cached xml data to initialize with
      * @return object kolab_format
      */
-    public static function factory($type, $version = 3.0, $xmldata = null)
+    public static function factory($type, $version = 2.0, $xmldata = null)
     {
         if (!isset(self::$timezone))
             self::$timezone = new DateTimeZone('UTC');
@@ -62,11 +59,13 @@ abstract class kolab_format
         if (!self::supports($version))
             return PEAR::raiseError("No support for Kolab format version " . $version);
 
+        list($xmltype, $subtype) = explode('.', $type);
+
         $type = preg_replace('/configuration\.[a-z.]+$/', 'configuration', $type);
-        $suffix = preg_replace('/[^a-z]+/', '', $type);
+        $suffix = preg_replace('/[^a-z]+/', '', $xmltype);
         $classname = 'kolab_format_' . $suffix;
         if (class_exists($classname))
-            return new $classname($xmldata, $version);
+            return new $classname($xmldata, $subtype);
 
         return PEAR::raiseError("Failed to load Kolab Format wrapper for type " . $type);
     }
@@ -80,9 +79,9 @@ abstract class kolab_format
     public static function supports($version)
     {
         if ($version == 2.0)
-            return class_exists('kolabobject');
-        // default is version 3
-        return class_exists('kolabformat');
+            return class_exists('Horde_Kolab_Format');
+
+        return false;
     }
 
     /**
@@ -210,17 +209,17 @@ abstract class kolab_format
     /**
      * Default constructor of all kolab_format_* objects
      */
-    public function __construct($xmldata = null, $version = null)
+    public function __construct($xmldata = null, $subtype = null)
     {
-        $this->obj = new $this->objclass;
-        $this->xmldata = $xmldata;
+        $this->subtype = $subtype;
 
-        if ($version)
-            $this->version = $version;
+        $handler = Horde_Kolab_Format::factory('XML', $this->xmltype, array('subtype' => $this->subtype));
+        if (!is_object($handler) || is_a($handler, 'PEAR_Error')) {
+            return false;
+        }
 
-        // use libkolab module if available
-        if (class_exists('kolabobject'))
-            $this->xmlobject = new XMLObject();
+        $this->handler = $handler;
+        $this->xmldata = $xmldata;
     }
 
     /**
@@ -265,8 +264,7 @@ abstract class kolab_format
     {
         // get generated UID
         if (!$this->data['uid']) {
-            $this->data['uid'] = $this->xmlobject ? $this->xmlobject->getSerializedUID() : kolabformat::getSerializedUID();
-            $this->obj->setUid($this->data['uid']);
+            $this->data['uid'] = 'TODO';
         }
     }
 
@@ -285,39 +283,6 @@ abstract class kolab_format
     }
 
     /**
-     * Get constant value for libkolab's version parameter
-     *
-     * @param float Version value to convert
-     * @return int Constant value of either kolabobject::KolabV2 or kolabobject::KolabV3 or false if kolabobject module isn't available
-     */
-    protected function libversion($v = null)
-    {
-        if (class_exists('kolabobject')) {
-            $version = $v ?: $this->version;
-            if ($version <= 2.0)
-                return kolabobject::KolabV2;
-            else
-                return kolabobject::KolabV3;
-        }
-
-        return false;
-    }
-
-    /**
-     * Determine the correct libkolab(xml) wrapper function for the given call
-     * depending on the available PHP modules
-     */
-    protected function libfunc($func)
-    {
-        if (is_array($func) || strpos($func, '::'))
-            return $func;
-        else if (class_exists('kolabobject'))
-            return array($this->xmlobject, $func);
-        else
-            return 'kolabformat::' . $func;
-    }
-
-    /**
      * Direct getter for object properties
      */
     public function __get($var)
@@ -333,17 +298,9 @@ abstract class kolab_format
      */
     public function load($xml)
     {
-        $read_func = $this->libfunc($this->read_func);
-
-        if (is_array($read_func))
-            $r = call_user_func($read_func, $xml, $this->libversion());
-        else
-            $r = call_user_func($read_func, $xml, false);
-
-        if (is_resource($r))
-            $this->obj = new $this->objclass($r);
-        else if (is_a($r, $this->objclass))
-            $this->obj = $r;
+        // XML-to-array
+        $object = $this->handler->load($xml);
+        $this->fromkolab2($object);
 
         $this->loaded = !$this->format_errors();
     }
@@ -357,11 +314,8 @@ abstract class kolab_format
     public function write($version = null)
     {
         $this->init();
-        $write_func = $this->libfunc($this->write_func);
-        if (is_array($write_func))
-            $this->xmldata = call_user_func($write_func, $this->obj, $this->libversion($version), self::PRODUCT_ID);
-        else
-            $this->xmldata = call_user_func($write_func, $this->obj, self::PRODUCT_ID);
+
+        // TODO: implement his
 
         if (!$this->format_errors())
             $this->update_uid();
@@ -384,11 +338,18 @@ abstract class kolab_format
     abstract public function is_valid();
 
     /**
-     * Convert the Kolab object into a hash array data structure
+     * Getter for the parsed object data
      *
      * @return array  Kolab object data as hash array
      */
-    abstract public function to_array();
+    public function to_array()
+    {
+        // load from XML if not done yet
+        if (!empty($this->data))
+            $this->init();
+
+        return $this->data;
+    }
 
     /**
      * Load object data from Kolab2 format
diff --git a/plugins/libkolab/lib/kolab_format_configuration.php b/plugins/libkolab/lib/kolab_format_configuration.php
index 918928b..2970b10 100644
--- a/plugins/libkolab/lib/kolab_format_configuration.php
+++ b/plugins/libkolab/lib/kolab_format_configuration.php
@@ -25,11 +25,8 @@
 class kolab_format_configuration extends kolab_format
 {
     public $CTYPE = 'application/x-vnd.kolab.configuration';
-    public $CTYPEv2 = 'application/x-vnd.kolab.configuration';
 
-    protected $objclass = 'Configuration';
-    protected $read_func = 'readConfiguration';
-    protected $write_func = 'writeConfiguration';
+    protected $xmltype = 'configuration';
 
     private $type_map = array(
         'dictionary' => Configuration::TypeDictionary,
@@ -46,31 +43,24 @@ class kolab_format_configuration extends kolab_format
     {
         $this->init();
 
+        if ($object['type'])
+            $this->subtype = $object['type'];
+
         // read type-specific properties
-        switch ($object['type']) {
+        switch ($this->subtype) {
         case 'dictionary':
-            $dict = new Dictionary($object['language']);
-            $dict->setEntries(self::array2vector($object['e']));
-            $this->obj = new Configuration($dict);
+            // TODO: implement this
             break;
 
         case 'category':
             // TODO: implement this
-            $categories = new vectorcategorycolor;
-            $this->obj = new Configuration($categories);
             break;
         default:
             return false;
         }
 
-        // set some automatic values if missing
-        if (!empty($object['uid']))
-            $this->obj->setUid($object['uid']);
-        if (!empty($object['created']))
-            $this->obj->setCreated(self::get_datetime($object['created']));
-
         // adjust content-type string
-        $this->CTYPE = $this->CTYPEv2 = 'application/x-vnd.kolab.configuration.' . $object['type'];
+        $this->CTYPE = 'application/x-vnd.kolab.configuration.' . $this->subtype;
 
         // cache this data
         $this->data = $object;
@@ -92,39 +82,16 @@ class kolab_format_configuration extends kolab_format
      */
     public function to_array()
     {
-        // return cached result
+        // load from XML if not done yet
         if (!empty($this->data))
-            return $this->data;
-
-        $this->init();
-        $type_map = array_flip($this->type_map);
-
-        // read object properties
-        $object = array(
-            'uid'     => $this->obj->uid(),
-            'created' => self::php_datetime($this->obj->created()),
-            'changed' => self::php_datetime($this->obj->lastModified()),
-            'type'    => $type_map[$this->obj->type()],
-        );
-
-        // read type-specific properties
-        switch ($object['type']) {
-        case 'dictionary':
-            $dict = $this->obj->dictionary();
-            $object['language'] = $dict->language();
-            $object['e'] = self::vector2array($dict->entries());
-            break;
-
-        case 'category':
-            // TODO: implement this
-            break;
-        }
+            $this->init();
 
         // adjust content-type string
-        if ($object['type'])
-            $this->CTYPE = $this->CTYPEv2 = 'application/x-vnd.kolab.configuration.' . $object['type'];
+        if ($this->data['type']) {
+            $this->subtype = $this->data;
+            $this->CTYPE = 'application/x-vnd.kolab.configuration.' . $this->subtype;
+        }
 
-        $this->data = $object;
         return $this->data;
     }
 
diff --git a/plugins/libkolab/lib/kolab_format_contact.php b/plugins/libkolab/lib/kolab_format_contact.php
index b147c38..fb033e3 100644
--- a/plugins/libkolab/lib/kolab_format_contact.php
+++ b/plugins/libkolab/lib/kolab_format_contact.php
@@ -24,47 +24,39 @@
 
 class kolab_format_contact extends kolab_format
 {
-    public $CTYPE = 'application/vcard+xml';
-    public $CTYPEv2 = 'application/x-vnd.kolab.contact';
+    public $CTYPE = 'application/x-vnd.kolab.contact';
 
-    protected $objclass = 'Contact';
-    protected $read_func = 'readContact';
-    protected $write_func = 'writeContact';
+    protected $xmltype = 'contact';
 
     public static $fulltext_cols = array('name', 'firstname', 'surname', 'middlename', 'email');
 
     public $phonetypes = array(
-        'home'    => Telephone::Home,
-        'work'    => Telephone::Work,
-        'text'    => Telephone::Text,
-        'main'    => Telephone::Voice,
-        'homefax' => Telephone::Fax,
-        'workfax' => Telephone::Fax,
-        'mobile'  => Telephone::Cell,
-        'video'   => Telephone::Video,
-        'pager'   => Telephone::Pager,
-        'car'     => Telephone::Car,
-        'other'   => Telephone::Textphone,
+        'home'    => 'home1',
+        'work'    => 'business1',
+        'text'    => 'text',
+        'main'    => 'primary',
+        'homefax' => 'homefax',
+        'workfax' => 'businessfax',
+        'mobile'  => 'mobile',
+        'isdn'    => 'isdn',
+        'pager'   => 'pager',
+        'car'     => 'car',
+        'company' => 'company',
+        'radio'   => 'radio',
+        'telex'   => 'telex',
+        'ttytdd'  => 'ttytdd',
+        'other'   => 'other',
+        'assistant' => 'assistant',
+        'callback'  => 'callback',
     );
 
     public $addresstypes = array(
-        'home' => Address::Home,
-        'work' => Address::Work,
+        'home' => 'home',
+        'work' => 'business',
+        'other' => 'other',
         'office' => 0,
     );
 
-    private $gendermap = array(
-        'female' => Contact::Female,
-        'male'   => Contact::Male,
-    );
-
-    private $relatedmap = array(
-        'manager'   => Related::Manager,
-        'assistant' => Related::Assistant,
-        'spouse'    => Related::Spouse,
-        'children'  => Related::Child,
-    );
-
     // old Kolab 2 format field map
     private $kolab2_fieldmap = array(
       // kolab       => roundcube
@@ -108,13 +100,9 @@ class kolab_format_contact extends kolab_format
     /**
      * Default constructor
      */
-    function __construct($xmldata = null, $version = 3.0)
+    function __construct($xmldata = null, $subtype = null)
     {
-        parent::__construct($xmldata, $version);
-
-        // complete phone types
-        $this->phonetypes['homefax'] |= Telephone::Home;
-        $this->phonetypes['workfax'] |= Telephone::Work;
+        parent::__construct($xmldata, $subtype);
     }
 
     /**
@@ -126,168 +114,7 @@ class kolab_format_contact extends kolab_format
     {
         $this->init();
 
-        // set some automatic values if missing
-        if (false && !$this->obj->created()) {
-            if (!empty($object['created']))
-                $object['created'] = new DateTime('now', self::$timezone);
-            $this->obj->setCreated(self::get_datetime($object['created']));
-        }
-
-        if (!empty($object['uid']))
-            $this->obj->setUid($object['uid']);
-
-        $object['changed'] = new DateTime('now', self::$timezone);
-        $this->obj->setLastModified(self::get_datetime($object['changed'], new DateTimeZone('UTC')));
-
-        // do the hard work of setting object values
-        $nc = new NameComponents;
-        $nc->setSurnames(self::array2vector($object['surname']));
-        $nc->setGiven(self::array2vector($object['firstname']));
-        $nc->setAdditional(self::array2vector($object['middlename']));
-        $nc->setPrefixes(self::array2vector($object['prefix']));
-        $nc->setSuffixes(self::array2vector($object['suffix']));
-        $this->obj->setNameComponents($nc);
-        $this->obj->setName($object['name']);
-
-        if (isset($object['nickname']))
-            $this->obj->setNickNames(self::array2vector($object['nickname']));
-        if (isset($object['profession']))
-            $this->obj->setTitles(self::array2vector($object['profession']));
-
-        // organisation related properties (affiliation)
-        $org = new Affiliation;
-        $offices = new vectoraddress;
-        if ($object['organization'])
-            $org->setOrganisation($object['organization']);
-        if ($object['department'])
-            $org->setOrganisationalUnits(self::array2vector($object['department']));
-        if ($object['jobtitle'])
-            $org->setRoles(self::array2vector($object['jobtitle']));
-
-        $rels = new vectorrelated;
-        if ($object['manager']) {
-            foreach ((array)$object['manager'] as $manager)
-                $rels->push(new Related(Related::Text, $manager, Related::Manager));
-        }
-        if ($object['assistant']) {
-            foreach ((array)$object['assistant'] as $assistant)
-                $rels->push(new Related(Related::Text, $assistant, Related::Assistant));
-        }
-        $org->setRelateds($rels);
-
-        // email, im, url
-        $this->obj->setEmailAddresses(self::array2vector($object['email']));
-        $this->obj->setIMaddresses(self::array2vector($object['im']));
-
-        $vurls = new vectorurl;
-        foreach ((array)$object['website'] as $url) {
-            $type = $url['type'] == 'blog' ? Url::Blog : Url::NoType;
-            $vurls->push(new Url($url['url'], $type));
-        }
-        $this->obj->setUrls($vurls);
-
-        // addresses
-        $adrs = new vectoraddress;
-        foreach ((array)$object['address'] as $address) {
-            $adr = new Address;
-            $type = $this->addresstypes[$address['type']];
-            if (isset($type))
-                $adr->setTypes($type);
-            else if ($address['type'])
-                $adr->setLabel($address['type']);
-            if ($address['street'])
-                $adr->setStreet($address['street']);
-            if ($address['locality'])
-                $adr->setLocality($address['locality']);
-            if ($address['code'])
-                $adr->setCode($address['code']);
-            if ($address['region'])
-                $adr->setRegion($address['region']);
-            if ($address['country'])
-                $adr->setCountry($address['country']);
-
-            if ($address['type'] == 'office')
-                $offices->push($adr);
-            else
-                $adrs->push($adr);
-        }
-        $this->obj->setAddresses($adrs);
-        $org->setAddresses($offices);
-
-        // add org affiliation after addresses are set
-        $orgs = new vectoraffiliation;
-        $orgs->push($org);
-        $this->obj->setAffiliations($orgs);
-
-        // telephones
-        $tels = new vectortelephone;
-        foreach ((array)$object['phone'] as $phone) {
-            $tel = new Telephone;
-            if (isset($this->phonetypes[$phone['type']]))
-                $tel->setTypes($this->phonetypes[$phone['type']]);
-            $tel->setNumber($phone['number']);
-            $tels->push($tel);
-        }
-        $this->obj->setTelephones($tels);
-
-        if (isset($object['gender']))
-            $this->obj->setGender($this->gendermap[$object['gender']] ? $this->gendermap[$object['gender']] : Contact::NotSet);
-        if (isset($object['notes']))
-            $this->obj->setNote($object['notes']);
-        if (isset($object['freebusyurl']))
-            $this->obj->setFreeBusyUrl($object['freebusyurl']);
-        if (isset($object['birthday']))
-            $this->obj->setBDay(self::get_datetime($object['birthday'], false, true));
-        if (isset($object['anniversary']))
-            $this->obj->setAnniversary(self::get_datetime($object['anniversary'], false, true));
-
-        if (!empty($object['photo'])) {
-            if ($type = rcube_mime::image_content_type($object['photo']))
-                $this->obj->setPhoto($object['photo'], $type);
-        }
-        else if (isset($object['photo']))
-            $this->obj->setPhoto('','');
-        else if ($this->obj->photoMimetype())  // load saved photo for caching
-            $object['photo'] = $this->obj->photo();
-
-        // spouse and children are relateds
-        $rels = new vectorrelated;
-        if ($object['spouse']) {
-            $rels->push(new Related(Related::Text, $object['spouse'], Related::Spouse));
-        }
-        if ($object['children']) {
-            foreach ((array)$object['children'] as $child)
-                $rels->push(new Related(Related::Text, $child, Related::Child));
-        }
-        $this->obj->setRelateds($rels);
-
-        // insert/replace crypto keys
-        $pgp_index = $pkcs7_index = -1;
-        $keys = $this->obj->keys();
-        for ($i=0; $i < $keys->size(); $i++) {
-            $key = $keys->get($i);
-            if ($pgp_index < 0 && $key->type() == Key::PGP)
-                $pgp_index = $i;
-            else if ($pkcs7_index < 0 && $key->type() == Key::PKCS7_MIME)
-                $pkcs7_index = $i;
-        }
-
-        $pgpkey   = $object['pgppublickey']   ? new Key($object['pgppublickey'], Key::PGP) : new Key();
-        $pkcs7key = $object['pkcs7publickey'] ? new Key($object['pkcs7publickey'], Key::PKCS7_MIME) : new Key();
-
-        if ($pgp_index >= 0)
-            $keys->set($pgp_index, $pgpkey);
-        else if (!empty($object['pgppublickey']))
-            $keys->push($pgpkey);
-        if ($pkcs7_index >= 0)
-            $keys->set($pkcs7_index, $pkcs7key);
-        else if (!empty($object['pkcs7publickey']))
-            $keys->push($pkcs7key);
-
-        $this->obj->setKeys($keys);
-
-        // TODO: handle language, gpslocation, etc.
-
+        // TODO: implement this
 
         // cache this data
         $this->data = $object;
@@ -299,103 +126,6 @@ class kolab_format_contact extends kolab_format
      */
     public function is_valid()
     {
-        return $this->data || (is_object($this->obj) && $this->obj->uid() /*$this->obj->isValid()*/);
-    }
-
-    /**
-     * Convert the Contact object into a hash array data structure
-     *
-     * @return array  Contact data as hash array
-     */
-    public function to_array()
-    {
-        // return cached result
-        if (!empty($this->data))
-            return $this->data;
-
-        $this->init();
-
-        // read object properties into local data object
-        $object = array(
-            'uid'       => $this->obj->uid(),
-            'name'      => $this->obj->name(),
-            'changed'   => self::php_datetime($this->obj->lastModified()),
-        );
-
-        $nc = $this->obj->nameComponents();
-        $object['surname']    = join(' ', self::vector2array($nc->surnames()));
-        $object['firstname']  = join(' ', self::vector2array($nc->given()));
-        $object['middlename'] = join(' ', self::vector2array($nc->additional()));
-        $object['prefix']     = join(' ', self::vector2array($nc->prefixes()));
-        $object['suffix']     = join(' ', self::vector2array($nc->suffixes()));
-        $object['nickname']   = join(' ', self::vector2array($this->obj->nickNames()));
-        $object['profession'] = join(' ', self::vector2array($this->obj->titles()));
-
-        // organisation related properties (affiliation)
-        $orgs = $this->obj->affiliations();
-        if ($orgs->size()) {
-            $org = $orgs->get(0);
-            $object['organization']   = $org->organisation();
-            $object['jobtitle']       = join(' ', self::vector2array($org->roles()));
-            $object['department']     = join(' ', self::vector2array($org->organisationalUnits()));
-            $this->read_relateds($org->relateds(), $object);
-        }
-
-        $object['email']   = self::vector2array($this->obj->emailAddresses());
-        $object['im']      = self::vector2array($this->obj->imAddresses());
-
-        $urls = $this->obj->urls();
-        for ($i=0; $i < $urls->size(); $i++) {
-            $url = $urls->get($i);
-            $subtype = $url->type() == Url::Blog ? 'blog' : 'homepage';
-            $object['website'][] = array('url' => $url->url(), 'type' => $subtype);
-        }
-
-        // addresses
-        $this->read_addresses($this->obj->addresses(), $object);
-        if ($org && ($offices = $org->addresses()))
-            $this->read_addresses($offices, $object, 'office');
-
-        // telehones
-        $tels = $this->obj->telephones();
-        $teltypes = array_flip($this->phonetypes);
-        for ($i=0; $i < $tels->size(); $i++) {
-            $tel = $tels->get($i);
-            $object['phone'][] = array('number' => $tel->number(), 'type' => $teltypes[$tel->types()]);
-        }
-
-        $object['notes'] = $this->obj->note();
-        $object['freebusyurl'] = $this->obj->freeBusyUrl();
-
-        if ($bday = self::php_datetime($this->obj->bDay()))
-            $object['birthday'] = $bday->format('c');
-
-        if ($anniversary = self::php_datetime($this->obj->anniversary()))
-            $object['anniversary'] = $anniversary->format('c');
-
-        $gendermap = array_flip($this->gendermap);
-        if (($g = $this->obj->gender()) && $gendermap[$g])
-            $object['gender'] = $gendermap[$g];
-
-        if ($this->obj->photoMimetype())
-            $object['photo'] = $this->obj->photo();
-        else if ($this->xmlobject && ($photo_name = $this->xmlobject->pictureAttachmentName()))
-        	$object['photo'] = $photo_name;
-
-        // relateds -> spouse, children
-        $this->read_relateds($this->obj->relateds(), $object);
-
-        // crypto settings: currently only key values are supported
-        $keys = $this->obj->keys();
-        for ($i=0; is_object($keys) && $i < $keys->size(); $i++) {
-            $key = $keys->get($i);
-            if ($key->type() == Key::PGP)
-                $object['pgppublickey'] = $key->key();
-            else if ($key->type() == Key::PKCS7_MIME)
-                $object['pkcs7publickey'] = $key->key();
-        }
-
-        $this->data = $object;
         return $this->data;
     }
 
@@ -444,9 +174,10 @@ class kolab_format_contact extends kolab_format
             $object['email'] = preg_split('/,\s*/', $record['emails']);
 
         if (is_array($record['address'])) {
+            $kolab2_addresstypes = array_flip($this->addresstypes);
             foreach ($record['address'] as $i => $adr) {
                 $object['address'][] = array(
-                    'type' => $this->kolab2_addresstypes[$adr['type']] ? $this->kolab2_addresstypes[$adr['type']] : $adr['type'],
+                    'type' => $kolab2_addresstypes[$adr['type']] ? $kolab2_addresstypes[$adr['type']] : $adr['type'],
                     'street' => $adr['street'],
                     'locality' => $adr['locality'],
                     'code' => $adr['postal-code'],
@@ -456,6 +187,15 @@ class kolab_format_contact extends kolab_format
             }
         }
 
+        // map Kolab format phone types to Roundcube types
+        if (!empty($object['phone'])) {
+            $kolab2_phonetypes = array_merge(array_flip($this->phonetypes), $this->kolab2_phonetypes);
+            foreach ($object['phone'] as $i => $phone) {
+                if ($type = $kolab2_phonetypes[$phone['type']])
+                    $object['phone'][$i]['type'] = $type;
+            }
+        }
+
         // office location goes into an address block
         if ($record['office-location'])
             $object['address'][] = array('type' => 'office', 'locality' => $record['office-location']);
@@ -468,45 +208,4 @@ class kolab_format_contact extends kolab_format
         $this->data = array_filter($object);
     }
 
-    /**
-     * Helper method to copy contents of an Address vector to the contact data object
-     */
-    private function read_addresses($addresses, &$object, $type = null)
-    {
-        $adrtypes = array_flip($this->addresstypes);
-
-        for ($i=0; $i < $addresses->size(); $i++) {
-            $adr = $addresses->get($i);
-            $object['address'][] = array(
-                'type'     => $type ? $type : ($adrtypes[$adr->types()] ? $adrtypes[$adr->types()] : ''), /*$adr->label()),*/
-                'street'   => $adr->street(),
-                'code'     => $adr->code(),
-                'locality' => $adr->locality(),
-                'region'   => $adr->region(),
-                'country'  => $adr->country()
-            );
-        }
-    }
-
-    /**
-     * Helper method to map contents of a Related vector to the contact data object
-     */
-    private function read_relateds($rels, &$object)
-    {
-        $typemap = array_flip($this->relatedmap);
-
-        for ($i=0; $i < $rels->size(); $i++) {
-            $rel = $rels->get($i);
-            if ($rel->type() != Related::Text)  // we can't handle UID relations yet
-                continue;
-
-            $types = $rel->relationTypes();
-            foreach ($typemap as $t => $field) {
-                if ($types & $t) {
-                    $object[$field][] = $rel->text();
-                    break;
-                }
-            }
-        }
-    }
 }
diff --git a/plugins/libkolab/lib/kolab_format_distributionlist.php b/plugins/libkolab/lib/kolab_format_distributionlist.php
index ba54742..ce44f38 100644
--- a/plugins/libkolab/lib/kolab_format_distributionlist.php
+++ b/plugins/libkolab/lib/kolab_format_distributionlist.php
@@ -24,12 +24,9 @@
 
 class kolab_format_distributionlist extends kolab_format
 {
-    public $CTYPE = 'application/vcard+xml';
-    public $CTYPEv2 = 'application/x-vnd.kolab.distribution-list';
+    public $CTYPE = 'application/x-vnd.kolab.distribution-list';
 
-    protected $objclass = 'DistList';
-    protected $read_func = 'readDistlist';
-    protected $write_func = 'writeDistlist';
+    protected $xmltype = 'distributionlist';
 
 
     /**
@@ -41,31 +38,7 @@ class kolab_format_distributionlist extends kolab_format
     {
         $this->init();
 
-        // set some automatic values if missing
-        if (!empty($object['uid']))
-            $this->obj->setUid($object['uid']);
-
-        $object['changed'] = new DateTime('now', self::$timezone);
-        $this->obj->setLastModified(self::get_datetime($object['changed'], new DateTimeZone('UTC')));
-
-        $this->obj->setName($object['name']);
-
-        $seen = array();
-        $members = new vectorcontactref;
-        foreach ((array)$object['member'] as $member) {
-            if ($member['uid'])
-                $m = new ContactReference(ContactReference::UidReference, $member['uid']);
-            else if ($member['email'])
-                $m = new ContactReference(ContactReference::EmailReference, $member['email']);
-            else
-                continue;
-
-            $m->setName($member['name']);
-            $members->push($m);
-            $seen[$member['email']]++;
-        }
-
-        $this->obj->setMembers($members);
+        // TODO: implement this
 
         // set type property for proper caching
         $object['_type'] = 'distribution-list';
@@ -77,7 +50,7 @@ class kolab_format_distributionlist extends kolab_format
 
     public function is_valid()
     {
-        return $this->data || (is_object($this->obj) && $this->obj->isValid());
+        return $this->data;
     }
 
     /**
@@ -103,41 +76,4 @@ class kolab_format_distributionlist extends kolab_format
         $this->data = $object;
     }
 
-    /**
-     * Convert the Distlist object into a hash array data structure
-     *
-     * @return array  Distribution list data as hash array
-     */
-    public function to_array()
-    {
-        // return cached result
-        if (!empty($this->data))
-            return $this->data;
-
-        $this->init();
-
-        // read object properties
-        $object = array(
-            'uid'       => $this->obj->uid(),
-            'changed'   => self::php_datetime($this->obj->lastModified()),
-            'name'      => $this->obj->name(),
-            'member'    => array(),
-            '_type'     => 'distribution-list',
-        );
-
-        $members = $this->obj->members();
-        for ($i=0; $i < $members->size(); $i++) {
-            $member = $members->get($i);
-#            if ($member->type() == ContactReference::UidReference && ($uid = $member->uid()))
-                $object['member'][] = array(
-                    'uid' => $member->uid(),
-                    'email' => $member->email(),
-                    'name' => $member->name(),
-                );
-        }
-
-        $this->data = $object;
-        return $this->data;
-    }
-
 }
diff --git a/plugins/libkolab/lib/kolab_format_event.php b/plugins/libkolab/lib/kolab_format_event.php
index d1e6b2e..0a960b1 100644
--- a/plugins/libkolab/lib/kolab_format_event.php
+++ b/plugins/libkolab/lib/kolab_format_event.php
@@ -22,13 +22,13 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-class kolab_format_event extends kolab_format_xcal
+class kolab_format_event extends kolab_format
 {
-    public $CTYPEv2 = 'application/x-vnd.kolab.event';
+    public $CTYPE = 'application/x-vnd.kolab.event';
 
-    protected $objclass = 'Event';
-    protected $read_func = 'readEvent';
-    protected $write_func = 'writeEvent';
+    protected $xmltype = 'event';
+
+    public static $fulltext_cols = array('title', 'description', 'location', 'attendees:name', 'attendees:email', 'categories');
 
     private $kolab2_rolemap = array(
         'required' => 'REQ-PARTICIPANT',
@@ -52,7 +52,7 @@ class kolab_format_event extends kolab_format_xcal
      */
     public function to_libcal()
     {
-        return class_exists('kolabcalendaring') ? new EventCal($this->obj) : false;
+        return false;
     }
 
     /**
@@ -64,32 +64,7 @@ class kolab_format_event extends kolab_format_xcal
     {
         $this->init();
 
-        // set common xcal properties
-        parent::set($object);
-
-        // do the hard work of setting object values
-        $this->obj->setStart(self::get_datetime($object['start'], null, $object['allday']));
-        $this->obj->setEnd(self::get_datetime($object['end'], null, $object['allday']));
-        $this->obj->setTransparency($object['free_busy'] == 'free');
-
-        $status = kolabformat::StatusUndefined;
-        if ($object['free_busy'] == 'tentative')
-            $status = kolabformat::StatusTentative;
-        if ($object['cancelled'])
-            $status = kolabformat::StatusCancelled;
-        $this->obj->setStatus($status);
-
-        // save attachments
-        $vattach = new vectorattachment;
-        foreach ((array)$object['_attachments'] as $cid => $attr) {
-            if (empty($attr))
-                continue;
-            $attach = new Attachment;
-            $attach->setLabel((string)$attr['name']);
-            $attach->setUri('cid:' . $cid, $attr['mimetype']);
-            $vattach->push($attach);
-        }
-        $this->obj->setAttachments($vattach);
+        // TODO: implement this
 
         // cache this data
         $this->data = $object;
@@ -101,65 +76,6 @@ class kolab_format_event extends kolab_format_xcal
      */
     public function is_valid()
     {
-        return $this->data || (is_object($this->obj) && $this->obj->isValid() && $this->obj->uid());
-    }
-
-    /**
-     * Convert the Event object into a hash array data structure
-     *
-     * @return array  Event data as hash array
-     */
-    public function to_array()
-    {
-        // return cached result
-        if (!empty($this->data))
-            return $this->data;
-
-        $this->init();
-
-        // read common xcal props
-        $object = parent::to_array();
-
-        // read object properties
-        $object += array(
-            'end'         => self::php_datetime($this->obj->end()),
-            'allday'      => $this->obj->start()->isDateOnly(),
-            'free_busy'   => $this->obj->transparency() ? 'free' : 'busy',  // TODO: transparency is only boolean
-            'attendees'   => array(),
-        );
-
-        // organizer is part of the attendees list in Roundcube
-        if ($object['organizer']) {
-            $object['organizer']['role'] = 'ORGANIZER';
-            array_unshift($object['attendees'], $object['organizer']);
-        }
-
-        // status defines different event properties...
-        $status = $this->obj->status();
-        if ($status == kolabformat::StatusTentative)
-          $object['free_busy'] = 'tentative';
-        else if ($status == kolabformat::StatusCancelled)
-          $objec['cancelled'] = true;
-
-        // handle attachments
-        $vattach = $this->obj->attachments();
-        for ($i=0; $i < $vattach->size(); $i++) {
-            $attach = $vattach->get($i);
-
-            // skip cid: attachments which are mime message parts handled by kolab_storage_folder
-            if (substr($attach->uri(), 0, 4) != 'cid:' && $attach->label()) {
-                $name = $attach->label();
-                $data = $attach->data();
-                $object['_attachments'][$name] = array(
-                    'name'     => $name,
-                    'mimetype' => $attach->mimetype(),
-                    'size'     => strlen($data),
-                    'content'  => $data,
-                );
-            }
-        }
-
-        $this->data = $object;
         return $this->data;
     }
 
diff --git a/plugins/libkolab/lib/kolab_format_journal.php b/plugins/libkolab/lib/kolab_format_journal.php
index 9144ea2..3e1d8ed 100644
--- a/plugins/libkolab/lib/kolab_format_journal.php
+++ b/plugins/libkolab/lib/kolab_format_journal.php
@@ -24,12 +24,9 @@
 
 class kolab_format_journal extends kolab_format
 {
-    public $CTYPE = 'application/calendar+xml';
-    public $CTYPEv2 = 'application/x-vnd.kolab.journal';
+    public $CTYPE = 'application/x-vnd.kolab.journal';
 
-    protected $objclass = 'Journal';
-    protected $read_func = 'readJournal';
-    protected $write_func = 'writeJournal';
+    protected $xmltype = 'journal';
 
 
     /**
@@ -41,13 +38,6 @@ class kolab_format_journal extends kolab_format
     {
         $this->init();
 
-        // set some automatic values if missing
-        if (!empty($object['uid']))
-            $this->obj->setUid($object['uid']);
-
-        $object['changed'] = new DateTime('now', self::$timezone);
-        $this->obj->setLastModified(self::get_datetime($object['changed'], new DateTimeZone('UTC')));
-
         // TODO: set object propeties
 
         // cache this data
@@ -60,7 +50,7 @@ class kolab_format_journal extends kolab_format
      */
     public function is_valid()
     {
-        return $this->data || (is_object($this->obj) && $this->obj->isValid());
+        return $this->data;
     }
 
     /**
@@ -78,31 +68,4 @@ class kolab_format_journal extends kolab_format
         $this->data = $object;
     }
 
-    /**
-     * Convert the Configuration object into a hash array data structure
-     *
-     * @return array  Config object data as hash array
-     */
-    public function to_array()
-    {
-        // return cached result
-        if (!empty($this->data))
-            return $this->data;
-
-        $this->init();
-
-        // read object properties
-        $object = array(
-            'uid'     => $this->obj->uid(),
-            'created' => self::php_datetime($this->obj->created()),
-            'changed' => self::php_datetime($this->obj->lastModified()),
-        );
-
-
-        // TODO: read object properties
-
-        $this->data = $object;
-        return $this->data;
-    }
-
 }
diff --git a/plugins/libkolab/lib/kolab_format_note.php b/plugins/libkolab/lib/kolab_format_note.php
index 48e963e..da17f72 100644
--- a/plugins/libkolab/lib/kolab_format_note.php
+++ b/plugins/libkolab/lib/kolab_format_note.php
@@ -25,11 +25,8 @@
 class kolab_format_note extends kolab_format
 {
     public $CTYPE = 'application/x-vnd.kolab.note';
-    public $CTYPEv2 = 'application/x-vnd.kolab.note';
 
-    protected $objclass = 'Note';
-    protected $read_func = 'readNote';
-    protected $write_func = 'writeNote';
+    protected $xmltype = 'note';
 
 
     /**
@@ -41,13 +38,6 @@ class kolab_format_note extends kolab_format
     {
         $this->init();
 
-        // set some automatic values if missing
-        if (!empty($object['uid']))
-            $this->obj->setUid($object['uid']);
-
-        $object['changed'] = new DateTime('now', self::$timezone);
-        $this->obj->setLastModified(self::get_datetime($object['changed'], new DateTimeZone('UTC')));
-
         // TODO: set object propeties
 
         // cache this data
@@ -60,7 +50,7 @@ class kolab_format_note extends kolab_format
      */
     public function is_valid()
     {
-        return $this->data || (is_object($this->obj) && $this->obj->isValid());
+        return $this->data;
     }
 
     /**
@@ -73,35 +63,9 @@ class kolab_format_note extends kolab_format
             'changed' => $record['last-modification-date'],
         );
 
+        // TODO: implement this
 
         $this->data = $object;
     }
 
-    /**
-     * Convert the Configuration object into a hash array data structure
-     *
-     * @return array  Config object data as hash array
-     */
-    public function to_array()
-    {
-        // return cached result
-        if (!empty($this->data))
-            return $this->data;
-
-        $this->init();
-
-        // read object properties
-        $object = array(
-            'uid'       => $this->obj->uid(),
-            'created'   => self::php_datetime($this->obj->created()),
-            'changed'   => self::php_datetime($this->obj->lastModified()),
-        );
-
-
-        // TODO: read object properties
-
-        $this->data = $object;
-        return $this->data;
-    }
-
 }
diff --git a/plugins/libkolab/lib/kolab_format_task.php b/plugins/libkolab/lib/kolab_format_task.php
index 0bfac3d..d1d29f4 100644
--- a/plugins/libkolab/lib/kolab_format_task.php
+++ b/plugins/libkolab/lib/kolab_format_task.php
@@ -22,13 +22,13 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-class kolab_format_task extends kolab_format_xcal
+class kolab_format_task extends kolab_format
 {
-    public $CTYPEv2 = 'application/x-vnd.kolab.task';
+    public $CTYPE = 'application/x-vnd.kolab.task';
 
-    protected $objclass = 'Todo';
-    protected $read_func = 'readTodo';
-    protected $write_func = 'writeTodo';
+    protected $xmltype = 'task';
+
+    public static $fulltext_cols = array('title', 'description', 'location', 'attendees:name', 'attendees:email', 'categories');
 
 
     /**
@@ -40,20 +40,7 @@ class kolab_format_task extends kolab_format_xcal
     {
         $this->init();
 
-        // set common xcal properties
-        parent::set($object);
-
-        $this->obj->setPercentComplete(intval($object['complete']));
-
-        if (isset($object['start']))
-            $this->obj->setStart(self::get_datetime($object['start'], null, $object['start']->_dateonly));
-
-        $this->obj->setDue(self::get_datetime($object['due'], null, $object['due']->_dateonly));
-
-        $related = new vectors;
-        if (!empty($object['parent_id']))
-            $related->push($object['parent_id']);
-        $this->obj->setRelatedTo($related);
+        // TODO: implement this
 
         // cache this data
         $this->data = $object;
@@ -65,39 +52,6 @@ class kolab_format_task extends kolab_format_xcal
      */
     public function is_valid()
     {
-        return $this->data || (is_object($this->obj) && $this->obj->isValid());
-    }
-
-    /**
-     * Convert the Configuration object into a hash array data structure
-     *
-     * @return array  Config object data as hash array
-     */
-    public function to_array()
-    {
-        // return cached result
-        if (!empty($this->data))
-            return $this->data;
-
-        $this->init();
-
-        // read common xcal props
-        $object = parent::to_array();
-
-        $object['complete'] = intval($this->obj->percentComplete());
-
-        // if due date is set
-        if ($due = $this->obj->due())
-            $object['due'] = self::php_datetime($due);
-
-        // related-to points to parent task; we only support one relation
-        $related = self::vector2array($this->obj->relatedTo());
-        if (count($related))
-            $object['parent_id'] = $related[0];
-
-        // TODO: map more properties
-
-        $this->data = $object;
         return $this->data;
     }
 
diff --git a/plugins/libkolab/lib/kolab_format_xcal.php b/plugins/libkolab/lib/kolab_format_xcal.php
deleted file mode 100644
index 3e1a721..0000000
--- a/plugins/libkolab/lib/kolab_format_xcal.php
+++ /dev/null
@@ -1,400 +0,0 @@
-<?php
-
-/**
- * Xcal based Kolab format class wrapping libkolabxml bindings
- *
- * Base class for xcal-based Kolab groupware objects such as event, todo, journal
- *
- * @version @package_version@
- * @author Thomas Bruederli <bruederli at kolabsys.com>
- *
- * Copyright (C) 2012, Kolab Systems AG <contact at kolabsys.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-abstract class kolab_format_xcal extends kolab_format
-{
-    public $CTYPE = 'application/calendar+xml';
-
-    public static $fulltext_cols = array('title', 'description', 'location', 'attendees:name', 'attendees:email', 'categories');
-
-    protected $sensitivity_map = array(
-        'public'       => kolabformat::ClassPublic,
-        'private'      => kolabformat::ClassPrivate,
-        'confidential' => kolabformat::ClassConfidential,
-    );
-
-    protected $role_map = array(
-        'REQ-PARTICIPANT' => kolabformat::Required,
-        'OPT-PARTICIPANT' => kolabformat::Optional,
-        'NON-PARTICIPANT' => kolabformat::NonParticipant,
-        'CHAIR' => kolabformat::Chair,
-    );
-
-    protected $rrule_type_map = array(
-        'MINUTELY' => RecurrenceRule::Minutely,
-        'HOURLY' => RecurrenceRule::Hourly,
-        'DAILY' => RecurrenceRule::Daily,
-        'WEEKLY' => RecurrenceRule::Weekly,
-        'MONTHLY' => RecurrenceRule::Monthly,
-        'YEARLY' => RecurrenceRule::Yearly,
-    );
-
-    protected $weekday_map = array(
-        'MO' => kolabformat::Monday,
-        'TU' => kolabformat::Tuesday,
-        'WE' => kolabformat::Wednesday,
-        'TH' => kolabformat::Thursday,
-        'FR' => kolabformat::Friday,
-        'SA' => kolabformat::Saturday,
-        'SU' => kolabformat::Sunday,
-    );
-
-    protected $alarm_type_map = array(
-        'DISPLAY' => Alarm::DisplayAlarm,
-        'EMAIL' => Alarm::EMailAlarm,
-        'AUDIO' => Alarm::AudioAlarm,
-    );
-
-    private $status_map = array(
-        'NEEDS-ACTION' => kolabformat::StatusNeedsAction,
-        'IN-PROCESS'   => kolabformat::StatusInProcess,
-        'COMPLETED'    => kolabformat::StatusCompleted,
-        'CANCELLED'    => kolabformat::StatusCancelled,
-    );
-
-    protected $part_status_map = array(
-        'UNKNOWN' => kolabformat::PartNeedsAction,
-        'NEEDS-ACTION' => kolabformat::PartNeedsAction,
-        'TENTATIVE' => kolabformat::PartTentative,
-        'ACCEPTED' => kolabformat::PartAccepted,
-        'DECLINED' => kolabformat::PartDeclined,
-        'DELEGATED' => kolabformat::PartDelegated,
-      );
-
-
-    /**
-     * Convert common xcard properties into a hash array data structure
-     *
-     * @return array  Object data as hash array
-     */
-    public function to_array()
-    {
-        $status_map = array_flip($this->status_map);
-        $sensitivity_map = array_flip($this->sensitivity_map);
-
-        $object = array(
-            'uid'         => $this->obj->uid(),
-            'created'     => self::php_datetime($this->obj->created()),
-            'changed'     => self::php_datetime($this->obj->lastModified()),
-            'sequence'    => intval($this->obj->sequence()),
-            'title'       => $this->obj->summary(),
-            'location'    => $this->obj->location(),
-            'description' => $this->obj->description(),
-            'status'      => $this->status_map[$this->obj->status()],
-            'sensitivity' => $sensitivity_map[$this->obj->classification()],
-            'priority'    => $this->obj->priority(),
-            'categories'  => self::vector2array($this->obj->categories()),
-            'start'       => self::php_datetime($this->obj->start()),
-        );
-
-        // read organizer and attendees
-        if ($organizer = $this->obj->organizer()) {
-            $object['organizer'] = array(
-                'email' => $organizer->email(),
-                'name' => $organizer->name(),
-            );
-        }
-
-        $role_map = array_flip($this->role_map);
-        $part_status_map = array_flip($this->part_status_map);
-        $attvec = $this->obj->attendees();
-        for ($i=0; $i < $attvec->size(); $i++) {
-            $attendee = $attvec->get($i);
-            $cr = $attendee->contact();
-            $object['attendees'][] = array(
-                'role' => $role_map[$attendee->role()],
-                'status' => $part_status_map[$attendee->partStat()],
-                'rsvp' => $attendee->rsvp(),
-                'email' => $cr->email(),
-                'name' => $cr->name(),
-            );
-        }
-
-        // read recurrence rule
-        if (($rr = $this->obj->recurrenceRule()) && $rr->isValid()) {
-            $rrule_type_map = array_flip($this->rrule_type_map);
-            $object['recurrence'] = array('FREQ' => $rrule_type_map[$rr->frequency()]);
-
-            if ($intvl = $rr->interval())
-                $object['recurrence']['INTERVAL'] = $intvl;
-
-            if (($count = $rr->count()) && $count > 0) {
-                $object['recurrence']['COUNT'] = $count;
-            }
-            else if ($until = self::php_datetime($rr->end())) {
-                $until->setTime($object['start']->format('G'), $object['start']->format('i'), 0);
-                $object['recurrence']['UNTIL'] = $until;
-            }
-
-            if (($byday = $rr->byday()) && $byday->size()) {
-                $weekday_map = array_flip($this->weekday_map);
-                $weekdays = array();
-                for ($i=0; $i < $byday->size(); $i++) {
-                    $daypos = $byday->get($i);
-                    $prefix = $daypos->occurence();
-                    $weekdays[] = ($prefix ? $prefix : '') . $weekday_map[$daypos->weekday()];
-                }
-                $object['recurrence']['BYDAY'] = join(',', $weekdays);
-            }
-
-            if (($bymday = $rr->bymonthday()) && $bymday->size()) {
-                $object['recurrence']['BYMONTHDAY'] = join(',', self::vector2array($bymday));
-            }
-
-            if (($bymonth = $rr->bymonth()) && $bymonth->size()) {
-                $object['recurrence']['BYMONTH'] = join(',', self::vector2array($bymonth));
-            }
-
-            if ($exceptions = $this->obj->exceptionDates()) {
-                for ($i=0; $i < $exceptions->size(); $i++) {
-                    if ($exdate = self::php_datetime($exceptions->get($i)))
-                        $object['recurrence']['EXDATE'][] = $exdate;
-                }
-            }
-        }
-
-        // read alarm
-        $valarms = $this->obj->alarms();
-        $alarm_types = array_flip($this->alarm_type_map);
-        for ($i=0; $i < $valarms->size(); $i++) {
-            $alarm = $valarms->get($i);
-            $type = $alarm_types[$alarm->type()];
-
-            if ($type == 'DISPLAY' || $type == 'EMAIL') {  // only DISPLAY and EMAIL alarms are supported
-                if ($start = self::php_datetime($alarm->start())) {
-                    $object['alarms'] = '@' . $start->format('U');
-                }
-                else if ($offset = $alarm->relativeStart()) {
-                    $value = $alarm->relativeTo() == kolabformat::End ? '+' : '-';
-                    if      ($w = $offset->weeks())     $value .= $w . 'W';
-                    else if ($d = $offset->days())      $value .= $d . 'D';
-                    else if ($h = $offset->hours())     $value .= $h . 'H';
-                    else if ($m = $offset->minutes())   $value .= $m . 'M';
-                    else if ($s = $offset->seconds())   $value .= $s . 'S';
-                    else continue;
-
-                    $object['alarms'] = $value;
-                }
-                $object['alarms']  .= ':' . $type;
-                break;
-            }
-        }
-
-        return $object;
-    }
-
-
-    /**
-     * Set common xcal properties to the kolabformat object
-     *
-     * @param array  Event data as hash array
-     */
-    public function set(&$object)
-    {
-        $is_new = !$this->obj->uid();
-
-        // set some automatic values if missing
-        if (!$this->obj->created()) {
-            if (!empty($object['created']))
-                $object['created'] = new DateTime('now', self::$timezone);
-            $this->obj->setCreated(self::get_datetime($object['created']));
-        }
-
-        if (!empty($object['uid']))
-            $this->obj->setUid($object['uid']);
-
-        $object['changed'] = new DateTime('now', self::$timezone);
-        $this->obj->setLastModified(self::get_datetime($object['changed'], new DateTimeZone('UTC')));
-
-        // increment sequence on updates
-        $object['sequence'] = !$is_new ? $this->obj->sequence()+1 : 0;
-        $this->obj->setSequence($object['sequence']);
-
-        $this->obj->setSummary($object['title']);
-        $this->obj->setLocation($object['location']);
-        $this->obj->setDescription($object['description']);
-        $this->obj->setPriority($object['priority']);
-        $this->obj->setClassification($this->sensitivity_map[$object['sensitivity']]);
-        $this->obj->setCategories(self::array2vector($object['categories']));
-
-        // process event attendees
-        $attendees = new vectorattendee;
-        foreach ((array)$object['attendees'] as $attendee) {
-            if ($attendee['role'] == 'ORGANIZER') {
-                $object['organizer'] = $attendee;
-            }
-            else {
-                $cr = new ContactReference(ContactReference::EmailReference, $attendee['email']);
-                $cr->setName($attendee['name']);
-
-                $att = new Attendee;
-                $att->setContact($cr);
-                $att->setPartStat($this->status_map[$attendee['status']]);
-                $att->setRole($this->role_map[$attendee['role']] ? $this->role_map[$attendee['role']] : kolabformat::Required);
-                $att->setRSVP((bool)$attendee['rsvp']);
-
-                if ($att->isValid()) {
-                    $attendees->push($att);
-                }
-                else {
-                    rcube::raise_error(array(
-                        'code' => 600, 'type' => 'php',
-                        'file' => __FILE__, 'line' => __LINE__,
-                        'message' => "Invalid event attendee: " . json_encode($attendee),
-                    ), true);
-                }
-            }
-        }
-        $this->obj->setAttendees($attendees);
-
-        if ($object['organizer']) {
-            $organizer = new ContactReference(ContactReference::EmailReference, $object['organizer']['email']);
-            $organizer->setName($object['organizer']['name']);
-            $this->obj->setOrganizer($organizer);
-        }
-
-        // save recurrence rule
-        if ($object['recurrence']) {
-            $rr = new RecurrenceRule;
-            $rr->setFrequency($this->rrule_type_map[$object['recurrence']['FREQ']]);
-
-            if ($object['recurrence']['INTERVAL'])
-                $rr->setInterval(intval($object['recurrence']['INTERVAL']));
-
-            if ($object['recurrence']['BYDAY']) {
-                $byday = new vectordaypos;
-                foreach (explode(',', $object['recurrence']['BYDAY']) as $day) {
-                    $occurrence = 0;
-                    if (preg_match('/^([\d-]+)([A-Z]+)$/', $day, $m)) {
-                        $occurrence = intval($m[1]);
-                        $day = $m[2];
-                    }
-                    if (isset($this->weekday_map[$day]))
-                        $byday->push(new DayPos($occurrence, $this->weekday_map[$day]));
-                }
-                $rr->setByday($byday);
-            }
-
-            if ($object['recurrence']['BYMONTHDAY']) {
-                $bymday = new vectori;
-                foreach (explode(',', $object['recurrence']['BYMONTHDAY']) as $day)
-                    $bymday->push(intval($day));
-                $rr->setBymonthday($bymday);
-            }
-
-            if ($object['recurrence']['BYMONTH']) {
-                $bymonth = new vectori;
-                foreach (explode(',', $object['recurrence']['BYMONTH']) as $month)
-                    $bymonth->push(intval($month));
-                $rr->setBymonth($bymonth);
-            }
-
-            if ($object['recurrence']['COUNT'])
-                $rr->setCount(intval($object['recurrence']['COUNT']));
-            else if ($object['recurrence']['UNTIL'])
-                $rr->setEnd(self::get_datetime($object['recurrence']['UNTIL'], null, true));
-
-            if ($rr->isValid()) {
-                $this->obj->setRecurrenceRule($rr);
-
-                // add exception dates (only if recurrence rule is valid)
-                $exdates = new vectordatetime;
-                foreach ((array)$object['recurrence']['EXDATE'] as $exdate)
-                    $exdates->push(self::get_datetime($exdate, null, true));
-                $this->obj->setExceptionDates($exdates);
-            }
-            else {
-                rcube::raise_error(array(
-                    'code' => 600, 'type' => 'php',
-                    'file' => __FILE__, 'line' => __LINE__,
-                    'message' => "Invalid event recurrence rule: " . json_encode($object['recurrence']),
-                ), true);
-            }
-        }
-
-        // save alarm
-        $valarms = new vectoralarm;
-        if ($object['alarms']) {
-            list($offset, $type) = explode(":", $object['alarms']);
-
-            if ($type == 'EMAIL') {  // email alarms implicitly go to event owner
-                $recipients = new vectorcontactref;
-                $recipients->push(new ContactReference(ContactReference::EmailReference, $object['_owner']));
-                $alarm = new Alarm($object['title'], strval($object['description']), $recipients);
-            }
-            else {  // default: display alarm
-                $alarm = new Alarm($object['title']);
-            }
-
-            if (preg_match('/^@(\d+)/', $offset, $d)) {
-                $alarm->setStart(self::get_datetime($d[1], new DateTimeZone('UTC')));
-            }
-            else if (preg_match('/^([-+]?)(\d+)([SMHDW])/', $offset, $d)) {
-                $days = $hours = $minutes = $seconds = 0;
-                switch ($d[3]) {
-                    case 'W': $days  = 7*intval($d[2]); break;
-                    case 'D': $days    = intval($d[2]); break;
-                    case 'H': $hours   = intval($d[2]); break;
-                    case 'M': $minutes = intval($d[2]); break;
-                    case 'S': $seconds = intval($d[2]); break;
-                }
-                $alarm->setRelativeStart(new Duration($days, $hours, $minutes, $seconds, $d[1] == '-'), $d[1] == '-' ? kolabformat::Start : kolabformat::End);
-            }
-
-            $valarms->push($alarm);
-        }
-        $this->obj->setAlarms($valarms);
-    }
-
-    /**
-     * Callback for kolab_storage_cache to get words to index for fulltext search
-     *
-     * @return array List of words to save in cache
-     */
-    public function get_words()
-    {
-        $data = '';
-        foreach (self::$fulltext_cols as $colname) {
-            list($col, $field) = explode(':', $colname);
-
-            if ($field) {
-                $a = array();
-                foreach ((array)$this->data[$col] as $attr)
-                    $a[] = $attr[$field];
-                $val = join(' ', $a);
-            }
-            else {
-                $val = is_array($this->data[$col]) ? join(' ', $this->data[$col]) : $this->data[$col];
-            }
-
-            if (strlen($val))
-                $data .= $val . ' ';
-        }
-
-        return array_unique(rcube_utils::normalize_string($data, true));
-    }
-
-}
\ No newline at end of file
diff --git a/plugins/libkolab/lib/kolab_storage.php b/plugins/libkolab/lib/kolab_storage.php
index ac7de34..79f949a 100644
--- a/plugins/libkolab/lib/kolab_storage.php
+++ b/plugins/libkolab/lib/kolab_storage.php
@@ -52,7 +52,7 @@ class kolab_storage
         self::$config = $rcmail->config;
         self::$version = $rcmail->config->get('kolab_format_version', self::$version);
         self::$imap = $rcmail->get_storage();
-        self::$ready = class_exists('kolabformat') &&
+        self::$ready = class_exists('Horde_Kolab_Format') &&
             (self::$imap->get_capability('METADATA') || self::$imap->get_capability('ANNOTATEMORE') || self::$imap->get_capability('ANNOTATEMORE2'));
 
         if (self::$ready) {
diff --git a/plugins/libkolab/lib/kolab_storage_cache.php b/plugins/libkolab/lib/kolab_storage_cache.php
index 9eac164..f5dbe01 100644
--- a/plugins/libkolab/lib/kolab_storage_cache.php
+++ b/plugins/libkolab/lib/kolab_storage_cache.php
@@ -534,7 +534,7 @@ class kolab_storage_cache
         }
 
         if ($object['_formatobj']) {
-            $sql_data['xml'] = preg_replace('!(</?[a-z0-9:-]+>)[\n\r\t\s]+!ms', '$1', (string)$object['_formatobj']->write(3.0));
+            $sql_data['xml'] = preg_replace('!(</?[a-z0-9:-]+>)[\n\r\t\s]+!ms', '$1', (string)$object['_formatobj']->write());
             $sql_data['tags'] = ' ' . join(' ', $object['_formatobj']->get_tags()) . ' ';  // pad with spaces for strict/prefix search
             $sql_data['words'] = ' ' . join(' ', $object['_formatobj']->get_words()) . ' ';
         }
@@ -582,7 +582,7 @@ class kolab_storage_cache
         $object['_type'] = $sql_arr['type'];
         $object['_msguid'] = $sql_arr['msguid'];
         $object['_mailbox'] = $this->folder->name;
-        $object['_formatobj'] = kolab_format::factory($sql_arr['type'], 3.0, $sql_arr['xml']);
+        $object['_formatobj'] = kolab_format::factory($sql_arr['type'], 2.0, $sql_arr['xml']);
 
         return $object;
     }
diff --git a/plugins/libkolab/lib/kolab_storage_folder.php b/plugins/libkolab/lib/kolab_storage_folder.php
index 302efd6..5ba5fa4 100644
--- a/plugins/libkolab/lib/kolab_storage_folder.php
+++ b/plugins/libkolab/lib/kolab_storage_folder.php
@@ -480,14 +480,7 @@ class kolab_storage_folder
         // check kolab format version
         $format_version = $headers->others['x-kolab-mime-version'];
         if (empty($format_version)) {
-            list($xmltype, $subtype) = explode('.', $object_type);
-            $xmlhead = substr($xml, 0, 512);
-
-            // detect old Kolab 2.0 format
-            if (strpos($xmlhead, '<' . $xmltype) !== false && strpos($xmlhead, 'xmlns=') === false)
-                $format_version = 2.0;
-            else
-                $format_version = 3.0; // assume 3.0
+            $format_version = 2.0; // assume 2.0
         }
 
         // get Kolab format handler for the given type
@@ -752,9 +745,8 @@ class kolab_storage_folder
             . 'To view this object you will need an email client that understands the Kolab Groupware format. '
             . "For a list of such email clients please visit http://www.kolab.org/\n\n");
 
-        $ctype = kolab_storage::$version == 2.0 ? $format->CTYPEv2 : $format->CTYPE;
         $mime->addAttachment($xml,  // file
-            $ctype,                 // content-type
+            $format->CTYPE,         // content-type
             'kolab.xml',            // filename
             false,                  // is_file
             '8bit',                 // encoding
diff --git a/plugins/libkolab/libkolab.php b/plugins/libkolab/libkolab.php
index 887d308..5e55943 100644
--- a/plugins/libkolab/libkolab.php
+++ b/plugins/libkolab/libkolab.php
@@ -50,12 +50,15 @@ class libkolab extends rcube_plugin
             kolab_format::$timezone = new DateTimeZone('GMT');
         }
 
-        // load (old) dependencies if available
-        if (@include_once('Horde/Util.php')) {
+        // load Horde Kolab_Format dependencies
+        if (include_once('Horde/Util.php')) {
             include_once 'Horde/Kolab/Format.php';
             include_once 'Horde/Kolab/Format/XML.php';
             include_once 'Horde/Kolab/Format/XML/contact.php';
+            include_once 'Horde/Kolab/Format/XML/distributionlist.php';
             include_once 'Horde/Kolab/Format/XML/event.php';
+            include_once 'Horde/Kolab/Format/XML/note.php';
+            include_once 'Horde/Kolab/Format/XML/task.php';
             include_once 'Horde_Kolab_Format_XML_configuration.php';
 
             String::setDefaultCharset('UTF-8');





More information about the commits mailing list