summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/libkolab/lib/kolab_format.php95
-rw-r--r--plugins/libkolab/lib/kolab_format_configuration.php2
-rw-r--r--plugins/libkolab/lib/kolab_format_contact.php135
-rw-r--r--plugins/libkolab/lib/kolab_format_distributionlist.php17
-rw-r--r--plugins/libkolab/lib/kolab_storage.php3
-rw-r--r--plugins/libkolab/lib/kolab_storage_folder.php21
6 files changed, 194 insertions, 79 deletions
diff --git a/plugins/libkolab/lib/kolab_format.php b/plugins/libkolab/lib/kolab_format.php
index 622b411..d976328 100644
--- a/plugins/libkolab/lib/kolab_format.php
+++ b/plugins/libkolab/lib/kolab_format.php
@@ -37,6 +37,7 @@ abstract class kolab_format
protected $handler;
protected $data;
protected $xmldata;
+ protected $kolab_object;
protected $loaded = false;
protected $version = 2.0;
@@ -165,36 +166,6 @@ abstract class kolab_format
}
/**
- * Convert a libkolabxml vector to a PHP array
- *
- * @param object vector Object
- * @return array Indexed array contaning vector elements
- */
- public static function vector2array($vec, $max = PHP_INT_MAX)
- {
- $arr = array();
- for ($i=0; $i < $vec->size() && $i < $max; $i++)
- $arr[] = $vec->get($i);
- return $arr;
- }
-
- /**
- * Build a libkolabxml vector (string) from a PHP array
- *
- * @param array Array with vector elements
- * @return object vectors
- */
- public static function array2vector($arr)
- {
- $vec = new vectors;
- foreach ((array)$arr as $val) {
- if (strlen($val))
- $vec->push($val);
- }
- return $vec;
- }
-
- /**
* Parse the X-Kolab-Type header from MIME messages and return the object type in short form
*
* @param string X-Kolab-Type header value
@@ -215,7 +186,7 @@ abstract class kolab_format
$handler = Horde_Kolab_Format::factory('XML', $this->xmltype, array('subtype' => $this->subtype));
if (!is_object($handler) || is_a($handler, 'PEAR_Error')) {
- return false;
+ return;
}
$this->handler = $handler;
@@ -227,45 +198,32 @@ abstract class kolab_format
*
* @return boolean True if there were errors, False if OK
*/
- protected function format_errors()
+ protected function format_errors($p)
{
- $ret = $log = false;
- switch (kolabformat::error()) {
- case kolabformat::NoError:
- $ret = false;
- break;
- case kolabformat::Warning:
- $ret = false;
- $log = "Warning";
- break;
- default:
- $ret = true;
- $log = "Error";
- }
+ $ret = false;
- if ($log) {
+ if (is_object($p) && is_a($p, 'PEAR_Error')) {
rcube::raise_error(array(
'code' => 660,
'type' => 'php',
'file' => __FILE__,
'line' => __LINE__,
- 'message' => "kolabformat $log: " . kolabformat::errorMessage(),
+ 'message' => "Horde_Kolab_Format error: " . $p->getMessage(),
), true);
+
+ $ret = true;
}
return $ret;
}
/**
- * Save the last generated UID to the object properties.
- * Should be called after kolabformat::writeXXXX();
+ * Generate a unique identifier for a Kolab object
*/
- protected function update_uid()
+ protected function generate_uid()
{
- // get generated UID
- if (!$this->data['uid']) {
- $this->data['uid'] = 'TODO';
- }
+ $rc = rcube::get_instance();
+ return strtoupper(md5(time() . uniqid(rand())) . '-' . substr(md5($rc->user ? $rc->user->get_username() : rand()), 0, 16));
}
/**
@@ -298,11 +256,15 @@ abstract class kolab_format
*/
public function load($xml)
{
+ $this->loaded = false;
+
// XML-to-array
$object = $this->handler->load($xml);
- $this->fromkolab2($object);
-
- $this->loaded = !$this->format_errors();
+ if (!$this->format_errors($object)) {
+ $this->kolab_object = $object;
+ $this->fromkolab2($object);
+ $this->loaded = true;
+ }
}
/**
@@ -315,12 +277,23 @@ abstract class kolab_format
{
$this->init();
- // TODO: implement his
+ if ($version && !self::supports($version))
+ return false;
+
+ // generate UID if not set
+ if (!$this->kolab_object['uid']) {
+ $this->kolab_object['uid'] = $this->generate_uid();
+ }
+
+ $xml = $this->handler->save($this->kolab_object);
- if (!$this->format_errors())
- $this->update_uid();
- else
+ if (!$this->format_errors($xml) && strlen($xml)) {
+ $this->xmldata = $xml;
+ $this->data['uid'] = $this->kolab_object['uid'];
+ }
+ else {
$this->xmldata = null;
+ }
return $this->xmldata;
}
diff --git a/plugins/libkolab/lib/kolab_format_configuration.php b/plugins/libkolab/lib/kolab_format_configuration.php
index 2970b10..edf22f7 100644
--- a/plugins/libkolab/lib/kolab_format_configuration.php
+++ b/plugins/libkolab/lib/kolab_format_configuration.php
@@ -63,7 +63,7 @@ class kolab_format_configuration extends kolab_format
$this->CTYPE = 'application/x-vnd.kolab.configuration.' . $this->subtype;
// cache this data
- $this->data = $object;
+ $this->data = $this->kolab_object = $object;
unset($this->data['_formatobj']);
}
diff --git a/plugins/libkolab/lib/kolab_format_contact.php b/plugins/libkolab/lib/kolab_format_contact.php
index fb033e3..cab7ded 100644
--- a/plugins/libkolab/lib/kolab_format_contact.php
+++ b/plugins/libkolab/lib/kolab_format_contact.php
@@ -94,6 +94,13 @@ class kolab_format_contact extends kolab_format
private $kolab2_addresstypes = array(
'business' => 'work'
);
+ private $kolab2_arrays = array(
+ 'web-page' => 'url',
+ 'im-address' => true,
+ 'manager-name' => true,
+ 'assistant' => true,
+ 'children' => true,
+ );
private $kolab2_gender = array(0 => 'male', 1 => 'female');
@@ -114,7 +121,112 @@ class kolab_format_contact extends kolab_format
{
$this->init();
- // TODO: implement this
+ if ($object['uid'])
+ $this->kolab_object['uid'] = $object['uid'];
+
+ $this->kolab_object['last-modification-date'] = time();
+
+ // map fields rcube => $kolab
+ foreach ($this->kolab2_fieldmap as $kolab => $rcube) {
+ $this->kolab_object[$kolab] = $object[$rcube];
+ }
+
+ // map gener values
+ if (isset($object['gender'])) {
+ $gender_map = array_flip($this->kolab2_gender);
+ $this->kolab_object['gender'] = $gender_map[$object['gender']];
+ }
+
+ // format dates
+ if ($object['birthday'] && ($date = @strtotime($object['birthday'])))
+ $this->kolab_object['birthday'] = date('Y-m-d', $date);
+ if ($object['anniversary'] && ($date = @strtotime($object['anniversary'])))
+ $this->kolab_object['anniversary'] = date('Y-m-d', $date);
+
+ // make sure these attributes are single string values
+ foreach ($this->kolab2_arrays as $col => $field) {
+ if (!is_array($this->kolab_object[$col]))
+ continue;
+ if ($field === true) {
+ $values = $this->kolab_object[$col];
+ }
+ else {
+ $values = array();
+ foreach ($this->kolab_object[$col] as $v)
+ $values[] = $v[$field];
+ }
+ $this->kolab_object[$col] = join('; ', $values);
+ }
+
+ // save email addresses to field 'emails'
+ $emails = array();
+ foreach ((array)$object['email'] as $email)
+ $emails[] = $email;
+ $this->kolab_object['emails'] = join(', ', array_filter($emails));
+ unset($this->kolab_object['email']);
+
+ // map phone types
+ foreach ((array)$this->kolab_object['phone'] as $i => $phone) {
+ if ($type = $this->phonetypes[$phone['type']])
+ $this->kolab_object['phone'][$i]['type'] = $type;
+ }
+
+ // save addresses (how weird is that?!)
+ $this->kolab_object['address'] = array();
+ $seen_types = array();
+ foreach ((array)$object['address'] as $adr) {
+ if ($type = $this->addresstypes[$adr['type']]) {
+ $updated = false;
+ $basekey = 'addr-' . $type . '-';
+
+ $this->kolab_object[$basekey . 'type'] = $type;
+ $this->kolab_object[$basekey . 'street'] = $adr['street'];
+ $this->kolab_object[$basekey . 'locality'] = $adr['locality'];
+ $this->kolab_object[$basekey . 'postal-code'] = $adr['zipcode'];
+ $this->kolab_object[$basekey . 'region'] = $adr['region'];
+ $this->kolab_object[$basekey . 'country'] = $adr['country'];
+
+ // check if we updates an existing address entry of this type...
+ foreach($this->kolab_object['address'] as $index => $address) {
+ if ($this->kolab_object['type'] == $type) {
+ $this->kolab_object['address'][$index] = $new_address;
+ $updated = true;
+ }
+ }
+
+ // ... add as new if not
+ if (!$updated) {
+ $this->kolab_object['address'][] = array(
+ 'type' => $type,
+ 'street' => $adr['street'],
+ 'locality' => $adr['locality'],
+ 'postal-code' => $adr['code'],
+ 'region' => $adr['region'],
+ 'country' => $adr['country'],
+ );
+ }
+
+ $seen_types[$type] = true;
+ }
+ else if ($adr['type'] == 'office') {
+ $this->kolab_object['office-location'] = $adr['locality'];
+ }
+ }
+
+ // unset removed address properties
+ foreach ($this->addresstypes as $type) {
+ if (!$seen_types[$type]) {
+ $basekey = 'addr-' . $type . '-';
+ unset(
+ $this->kolab_object[$basekey . 'type'],
+ $this->kolab_object[$basekey . 'street'],
+ $this->kolab_object[$basekey . 'locality'],
+ $this->kolab_object[$basekey . 'postal-code'],
+ $this->kolab_object[$basekey . 'region'],
+ $this->kolab_object[$basekey . 'country']
+ );
+ }
+ }
// cache this data
$this->data = $object;
@@ -126,7 +238,7 @@ class kolab_format_contact extends kolab_format
*/
public function is_valid()
{
- return $this->data;
+ return strlen($this->data['uid']);
}
/**
@@ -155,13 +267,28 @@ class kolab_format_contact extends kolab_format
{
$object = array(
'uid' => $record['uid'],
+ 'changed' => $record['last-modification-date'],
'email' => array(),
'phone' => array(),
);
foreach ($this->kolab2_fieldmap as $kolab => $rcube) {
- if (is_array($record[$kolab]) || strlen($record[$kolab]))
- $object[$rcube] = $record[$kolab];
+ if (is_array($record[$kolab]) || strlen($record[$kolab])) {
+ $object[$rcube] = $record[$kolab];
+
+ // split pseudo-arry values
+ if ($field = $this->kolab2_arrays[$kolab]) {
+ if ($field === true) {
+ $object[$rcube] = explode('; ', $record[$kolab]);
+ }
+ else {
+ $values = array();
+ foreach (explode('; ', $record[$kolab]) as $v)
+ $values[] = array($field => $v);
+ $object[$rcube] = $values;
+ }
+ }
+ }
}
if (isset($record['gender']))
diff --git a/plugins/libkolab/lib/kolab_format_distributionlist.php b/plugins/libkolab/lib/kolab_format_distributionlist.php
index ce44f38..b6fc566 100644
--- a/plugins/libkolab/lib/kolab_format_distributionlist.php
+++ b/plugins/libkolab/lib/kolab_format_distributionlist.php
@@ -38,7 +38,20 @@ class kolab_format_distributionlist extends kolab_format
{
$this->init();
- // TODO: implement this
+ if ($object['uid'])
+ $this->kolab_object['uid'] = $object['uid'];
+
+ $this->kolab_object['last-modification-date'] = time();
+ $this->kolab_object['last-name'] = $object['name'];
+ $this->kolab_object['member'] = array();
+
+ foreach ($object['member'] as $member) {
+ $this->kolab_object['member'][] = array(
+ 'uid' => $member['uid'],
+ 'smtp-address' => $member['email'],
+ 'display-name' => $member['name'],
+ );
+ }
// set type property for proper caching
$object['_type'] = 'distribution-list';
@@ -50,7 +63,7 @@ class kolab_format_distributionlist extends kolab_format
public function is_valid()
{
- return $this->data;
+ return !empty($this->data['uid']);
}
/**
diff --git a/plugins/libkolab/lib/kolab_storage.php b/plugins/libkolab/lib/kolab_storage.php
index 79f949a..5b8eca7 100644
--- a/plugins/libkolab/lib/kolab_storage.php
+++ b/plugins/libkolab/lib/kolab_storage.php
@@ -31,7 +31,7 @@ class kolab_storage
const SERVERSIDE_SUBSCRIPTION = 0;
const CLIENTSIDE_SUBSCRIPTION = 1;
- public static $version = 3.0;
+ public static $version = 2.0;
public static $last_error;
private static $ready = false;
@@ -50,7 +50,6 @@ class kolab_storage
$rcmail = rcube::get_instance();
self::$config = $rcmail->config;
- self::$version = $rcmail->config->get('kolab_format_version', self::$version);
self::$imap = $rcmail->get_storage();
self::$ready = class_exists('Horde_Kolab_Format') &&
(self::$imap->get_capability('METADATA') || self::$imap->get_capability('ANNOTATEMORE') || self::$imap->get_capability('ANNOTATEMORE2'));
diff --git a/plugins/libkolab/lib/kolab_storage_folder.php b/plugins/libkolab/lib/kolab_storage_folder.php
index 5ba5fa4..23bb3a6 100644
--- a/plugins/libkolab/lib/kolab_storage_folder.php
+++ b/plugins/libkolab/lib/kolab_storage_folder.php
@@ -543,22 +543,25 @@ class kolab_storage_folder
if ($object['_attachments'][$key] == false) {
unset($object['_attachments'][$key]);
}
- // load photo.attachment from old Kolab2 format to be directly embedded in xcard block
+ // load photo.attachment from old Kolab2 format
else if ($type == 'contact' && ($key == 'photo.attachment' || $key == 'kolab-picture.png') && $att['id']) {
- if (!isset($object['photo']))
- $object['photo'] = $this->get_attachment($object['_msguid'], $att['id'], $object['_mailbox']);
- unset($object['_attachments'][$key]);
+ $existing_photo = true;
+ if (isset($object['photo']))
+ unset($object['_attachments'][$key]);
+ else
+ $object['photo'] = $key;
}
}
}
- // save contact photo to attachment for Kolab2 format
- if (kolab_storage::$version == 2.0 && $object['photo'] && !$existing_photo) {
- $attkey = 'kolab-picture.png'; // this file name is hard-coded in libkolab/kolabformatV2/contact.cpp
+ // save new contact photo to attachment for Kolab2 format
+ if ($object['photo'] && !$existing_photo) {
+ $attkey = 'photo.attachment'; // this file name is hard-coded in libkolab/kolabformatV2/contact.cpp
$object['_attachments'][$attkey] = array(
'mimetype'=> rc_image_content_type($object['photo']),
'content' => preg_match('![^a-z0-9/=+-]!i', $object['photo']) ? $object['photo'] : base64_decode($object['photo']),
);
+ $object['photo'] = $attkey;
}
// process attachments
@@ -716,11 +719,11 @@ class kolab_storage_folder
return false;
$format->set($object);
- $xml = $format->write(kolab_storage::$version);
+ $xml = $format->write();
$object['uid'] = $format->uid; // read UID from format
$object['_formatobj'] = $format;
- if (!$format->is_valid() || empty($object['uid'])) {
+ if (empty($xml) || !$format->is_valid() || empty($object['uid'])) {
return false;
}