4 commits - docs/syncroton.sql lib/ext lib/init.php lib/kolab_sync_backend_common.php lib/kolab_sync_backend_content.php lib/kolab_sync_backend_device.php lib/kolab_sync_backend_folder.php lib/kolab_sync_backend.php lib/kolab_sync_backend_policy.php lib/kolab_sync_backend_state.php lib/kolab_sync_data_email.php lib/kolab_sync_data.php lib/kolab_sync_db.php lib/kolab_sync.php
Aleksander Machniak
machniak at kolabsys.com
Sun Aug 19 12:16:36 CEST 2012
docs/syncroton.sql | 148 ++-
lib/ext/Roundcube/rcube_mdb2.php | 935 ---------------------
lib/ext/Syncroton/Backend/ABackend.php | 156 +++
lib/ext/Syncroton/Backend/Content.php | 129 --
lib/ext/Syncroton/Backend/Device.php | 103 --
lib/ext/Syncroton/Backend/Folder.php | 212 +---
lib/ext/Syncroton/Backend/IBackend.php | 50 +
lib/ext/Syncroton/Backend/IContent.php | 18
lib/ext/Syncroton/Backend/IDevice.php | 34
lib/ext/Syncroton/Backend/IFolder.php | 33
lib/ext/Syncroton/Backend/ISyncState.php | 18
lib/ext/Syncroton/Backend/Policy.php | 24
lib/ext/Syncroton/Backend/SyncState.php | 199 +---
lib/ext/Syncroton/Command/FolderCreate.php | 76 -
lib/ext/Syncroton/Command/FolderDelete.php | 28
lib/ext/Syncroton/Command/FolderSync.php | 74 -
lib/ext/Syncroton/Command/FolderUpdate.php | 50 -
lib/ext/Syncroton/Command/ItemOperations.php | 3
lib/ext/Syncroton/Command/Options.php | 8
lib/ext/Syncroton/Command/Ping.php | 8
lib/ext/Syncroton/Command/Provision.php | 64 -
lib/ext/Syncroton/Command/Search.php | 73 -
lib/ext/Syncroton/Command/SendMail.php | 23
lib/ext/Syncroton/Command/SmartForward.php | 2
lib/ext/Syncroton/Command/SmartReply.php | 2
lib/ext/Syncroton/Command/Sync.php | 69 -
lib/ext/Syncroton/Command/Wbxml.php | 51 -
lib/ext/Syncroton/Data/AData.php | 24
lib/ext/Syncroton/Data/Calendar.php | 6
lib/ext/Syncroton/Data/Contacts.php | 54 +
lib/ext/Syncroton/Data/Email.php | 30
lib/ext/Syncroton/Data/Factory.php | 9
lib/ext/Syncroton/Data/IDataEmail.php | 21
lib/ext/Syncroton/Data/Tasks.php | 6
lib/ext/Syncroton/Exception/ProvisioningNeeded.php | 1
lib/ext/Syncroton/Model/AEntry.php | 83 +
lib/ext/Syncroton/Model/Contact.php | 84 -
lib/ext/Syncroton/Model/Email.php | 122 --
lib/ext/Syncroton/Model/EmailAttachment.php | 85 -
lib/ext/Syncroton/Model/EmailBody.php | 34
lib/ext/Syncroton/Model/Event.php | 101 --
lib/ext/Syncroton/Model/EventAttendee.php | 77 -
lib/ext/Syncroton/Model/EventException.php | 3
lib/ext/Syncroton/Model/EventRecurrence.php | 39
lib/ext/Syncroton/Model/FileReference.php | 50 -
lib/ext/Syncroton/Model/Folder.php | 61 +
lib/ext/Syncroton/Model/IDevice.php | 4
lib/ext/Syncroton/Model/IFolder.php | 10
lib/ext/Syncroton/Model/IPolicy.php | 32
lib/ext/Syncroton/Model/Policy.php | 75 +
lib/ext/Syncroton/Model/StoreRequest.php | 11
lib/ext/Syncroton/Model/StoreResponse.php | 2
lib/ext/Syncroton/Model/StoreResponseResult.php | 31
lib/ext/Syncroton/Model/SyncCollection.php | 2
lib/ext/Syncroton/Model/Task.php | 72 -
lib/ext/Syncroton/Registry.php | 18
lib/ext/Syncroton/Server.php | 13
lib/init.php | 2
lib/kolab_sync.php | 1
lib/kolab_sync_backend.php | 7
lib/kolab_sync_backend_common.php | 225 +++++
lib/kolab_sync_backend_content.php | 100 --
lib/kolab_sync_backend_device.php | 110 --
lib/kolab_sync_backend_folder.php | 157 +--
lib/kolab_sync_backend_policy.php | 33
lib/kolab_sync_backend_state.php | 144 +--
lib/kolab_sync_data.php | 32
lib/kolab_sync_data_email.php | 23
lib/kolab_sync_db.php | 2
69 files changed, 1675 insertions(+), 2911 deletions(-)
New commits:
commit 5d4a085f7752376684a33df2aaa1461f102e9144
Author: Aleksander Machniak <alec at alec.pl>
Date: Sun Aug 19 12:16:06 2012 +0200
Perf. optimization: replace two similiar queries with one
diff --git a/lib/kolab_sync_backend_state.php b/lib/kolab_sync_backend_state.php
index dfd2127..b239d36 100644
--- a/lib/kolab_sync_backend_state.php
+++ b/lib/kolab_sync_backend_state.php
@@ -150,47 +150,46 @@ class kolab_sync_backend_state extends kolab_sync_backend_common implements Sync
$deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
$folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
+ // get sync data for current request and check if it's the last one
+ // by fetching synckey+1
+ $states = array();
+ $keys = array($_syncKey, $_syncKey + 1);
+
$where['device_id'] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where['type'] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folderId);
- $where['counter'] = $this->db->quote_identifier('counter') . ' = ' . $this->db->quote($_syncKey);
+ $where['counter'] = $this->db->quote_identifier('counter') . ' IN (' . $this->db->array2list($keys, 'int') . ')';
- $select = $this->db->query('SELECT * FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
- $state = $this->db->fetch_assoc($select);
+ $select = $this->db->query('SELECT * FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
- if (empty($state)) {
- return false;
+ while ($row = $this->db->fetch_assoc($select)) {
+ $states[$row['counter']] = $this->get_object($row);
}
- $state = $this->get_object($state);
-
- // check if this was the latest syncKey
- $where['counter'] = $this->db->quote_identifier('counter') . ' = ' . $this->db->quote($_syncKey + 1);
-
- $select = $this->db->query('SELECT * FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
-
- if ($moreRecentState = $this->db->fetch_assoc($select)) {
- $moreRecentState = $this->get_object($moreRecentState);
+ if (empty($states) || empty($states[$_syncKey])) {
+ return false;
}
+ $state = $states[$_syncKey];
+
$where = array();
$where['device_id'] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where['folder_id'] = $this->db->quote_identifier('folder_id') . ' = ' . $this->db->quote($folderId);
$where['is_deleted'] = $this->db->quote_identifier('is_deleted') . ' = 1';
// found more recent synckey => the last sync repsonse got not received by the client
- if ($moreRecentState instanceof Syncroton_Model_ISyncState) {
+ if (!empty($states[$_syncKey + 1])) {
$where['synckey'] = $this->db->quote_identifier('creation_synckey') . ' = ' . $this->db->quote($state->counter);
- // undelete entries marked as deleted in Syncroton_content table
+ // undelete entries marked as deleted in syncroton_content table
$this->db->query('UPDATE syncroton_content SET is_deleted = 0 WHERE ' . implode(' AND ', $where));
- // remove entries added during latest sync in Syncroton_content table
+ // remove entries added during latest sync in syncroton_content table
unset($where['is_deleted']);
$where['synckey'] = $this->db->quote_identifier('creation_synckey') . ' > ' . $this->db->quote($state->counter);
$this->db->query('DELETE FROM syncroton_content WHERE ' . implode(' AND ', $where));
}
else {
- // finaly delete all entries marked for removal in Syncroton_content table
+ // finaly delete all entries marked for removal in syncroton_content table
$this->db->query('DELETE FROM syncroton_content WHERE ' . implode(' AND ', $where));
}
commit 7cea6c3a5b21241376669e6d5dc8e31b50df197b
Author: Aleksander Machniak <alec at alec.pl>
Date: Sun Aug 19 12:02:49 2012 +0200
FIx for the last API change, email default folder wasn't detected properly
diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
index 46ec0d6..fa4d82f 100644
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -439,10 +439,10 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
$folder_id = $this->defaultRootFolder;
return array(
- 'displayname' => 'Inbox',
+ 'displayName' => 'Inbox',
'realid' => $real_id,
- 'folderid' => $folder_id,
- 'parentid' => 0,
+ 'serverId' => $folder_id,
+ 'parentId' => 0,
'type' => $this->defaultFolderType,
);
}
commit ab953c68a3579f12ac22851f0ff9425dedd98ce6
Author: Aleksander Machniak <alec at alec.pl>
Date: Sun Aug 19 11:20:31 2012 +0200
Perf. optimization: don't call SELECT after INSERT, check last_insert_id and return function argument
diff --git a/lib/kolab_sync_backend_common.php b/lib/kolab_sync_backend_common.php
index 34e9623..c7c3b58 100644
--- a/lib/kolab_sync_backend_common.php
+++ b/lib/kolab_sync_backend_common.php
@@ -85,7 +85,7 @@ class kolab_sync_backend_common implements Syncroton_Backend_IBackend
$data = $this->object_to_array($object);
$insert = array();
- $data['id'] = sha1(mt_rand(). microtime());
+ $data['id'] = $object->id = sha1(mt_rand(). microtime());
foreach ($data as $key => $value) {
$insert[$this->db->quote_identifier($key)] = $this->db->quote($value);
@@ -94,7 +94,11 @@ class kolab_sync_backend_common implements Syncroton_Backend_IBackend
$this->db->query('INSERT INTO ' . $this->table_name
. ' (' . implode(', ', array_keys($insert)) . ')' . ' VALUES(' . implode(', ', $insert) . ')');
- return $this->get($data['id']);
+ if (!$this->db->insert_id($this->table_name)) {
+ // @TODO: throw exception
+ }
+
+ return $object;
}
/**
@@ -156,11 +160,11 @@ class kolab_sync_backend_common implements Syncroton_Backend_IBackend
$this->db->query('UPDATE ' . $this->table_name . ' SET ' . implode(', ', $set)
. ' WHERE ' . $this->db->quote_identifier('id') . ' = ' . $this->db->quote($object->id));
- return $this->get($object->id);
+ return $object;
}
/**
- *
+ * Convert array into model object
*/
protected function get_object($data)
{
@@ -177,6 +181,9 @@ class kolab_sync_backend_common implements Syncroton_Backend_IBackend
return new $this->class_name($data);
}
+ /**
+ * Converts model object into array
+ */
protected function object_to_array($object)
{
$data = array();
@@ -194,6 +201,9 @@ class kolab_sync_backend_common implements Syncroton_Backend_IBackend
return $data;
}
+ /**
+ * Convert property name from camel-case to lower-case-with-underscore
+ */
protected function from_camelcase($string)
{
$string = lcfirst($string);
@@ -201,6 +211,9 @@ class kolab_sync_backend_common implements Syncroton_Backend_IBackend
return preg_replace_callback('/([A-Z])/', function ($string) { return '_' . strtolower($string[0]); }, $string);
}
+ /**
+ * Convert property name from lower-case-with-underscore to camel-case
+ */
protected function to_camelcase($string, $ucFirst = true)
{
if ($ucFirst) {
commit 2fe0cfb2ca77a6e28c73ba4708c2f49984a84581
Author: Aleksander Machniak <alec at alec.pl>
Date: Sun Aug 19 09:46:06 2012 +0200
Update Syncroton, update code for the new API
diff --git a/docs/syncroton.sql b/docs/syncroton.sql
index bcd97b7..5e140d9 100644
--- a/docs/syncroton.sql
+++ b/docs/syncroton.sql
@@ -1,57 +1,125 @@
+CREATE TABLE IF NOT EXISTS `syncroton_policy` (
+ `id` varchar(40) NOT NULL,
+ `name` varchar(255) NOT NULL,
+ `description` varchar(255) DEFAULT NULL,
+ `policy_key` varchar(64) NOT NULL,
+ `allow_bluetooth` int(11) DEFAULT NULL,
+ `allow_browser` int(11) DEFAULT NULL,
+ `allow_camera` int(11) DEFAULT NULL,
+ `allow_consumer_email` int(11) DEFAULT NULL,
+ `allow_desktop_sync` int(11) DEFAULT NULL,
+ `allow_h_t_m_l_email` int(11) DEFAULT NULL,
+ `allow_internet_sharing` int(11) DEFAULT NULL,
+ `allow_ir_d_a` int(11) DEFAULT NULL,
+ `allow_p_o_p_i_m_a_p_email` int(11) DEFAULT NULL,
+ `allow_remote_desktop` int(11) DEFAULT NULL,
+ `allow_simple_device_password` int(11) DEFAULT NULL,
+ `allow_s_m_i_m_e_encryption_algorithm_negotiation` int(11) DEFAULT NULL,
+ `allow_s_m_i_m_e_soft_certs` int(11) DEFAULT NULL,
+ `allow_storage_card` int(11) DEFAULT NULL,
+ `allow_text_messaging` int(11) DEFAULT NULL,
+ `allow_unsigned_applications` int(11) DEFAULT NULL,
+ `allow_unsigned_installation_packages` int(11) DEFAULT NULL,
+ `allow_wifi` int(11) DEFAULT NULL,
+ `alphanumeric_device_password_required` int(11) DEFAULT NULL,
+ `approved_application_list` varchar(255) DEFAULT NULL,
+ `attachments_enabled` int(11) DEFAULT NULL,
+ `device_password_enabled` int(11) DEFAULT NULL,
+ `device_password_expiration` int(11) DEFAULT NULL,
+ `device_password_history` int(11) DEFAULT NULL,
+ `max_attachment_size` int(11) DEFAULT NULL,
+ `max_calendar_age_filter` int(11) DEFAULT NULL,
+ `max_device_password_failed_attempts` int(11) DEFAULT NULL,
+ `max_email_age_filter` int(11) DEFAULT NULL,
+ `max_email_body_truncation_size` int(11) DEFAULT NULL,
+ `max_email_h_t_m_l_body_truncation_size` int(11) DEFAULT NULL,
+ `max_inactivity_time_device_lock` int(11) DEFAULT NULL,
+ `min_device_password_complex_characters` int(11) DEFAULT NULL,
+ `min_device_password_length` int(11) DEFAULT NULL,
+ `password_recovery_enabled` int(11) DEFAULT NULL,
+ `require_device_encryption` int(11) DEFAULT NULL,
+ `require_encrypted_s_m_i_m_e_messages` int(11) DEFAULT NULL,
+ `require_encryption_s_m_i_m_e_algorithm` int(11) DEFAULT NULL,
+ `require_manual_sync_when_roaming` int(11) DEFAULT NULL,
+ `require_signed_s_m_i_m_e_algorithm` int(11) DEFAULT NULL,
+ `require_signed_s_m_i_m_e_messages` int(11) DEFAULT NULL,
+ `require_storage_card_encryption` int(11) DEFAULT NULL,
+ `unapproved_in_r_o_m_application_list` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB;
+
CREATE TABLE IF NOT EXISTS `syncroton_device` (
`id` varchar(40) NOT NULL,
`deviceid` varchar(64) NOT NULL,
`devicetype` varchar(64) NOT NULL,
- `policykey` varchar(64) DEFAULT NULL,
- `policy_id` varchar(40) NOT NULL,
`owner_id` varchar(40) NOT NULL,
- `useragent` varchar(255) NOT NULL,
`acsversion` varchar(40) NOT NULL,
+ `policykey` varchar(64) DEFAULT NULL,
+ `policy_id` varchar(40) DEFAULT NULL,
+ `useragent` varchar(255) DEFAULT NULL,
+ `imei` varchar(255) DEFAULT NULL,
+ `model` varchar(255) DEFAULT NULL,
+ `friendlyname` varchar(255) DEFAULT NULL,
+ `os` varchar(255) DEFAULT NULL,
+ `oslanguage` varchar(255) DEFAULT NULL,
+ `phonenumber` varchar(255) DEFAULT NULL,
`pinglifetime` int(11) DEFAULT NULL,
`remotewipe` int(11) DEFAULT '0',
`pingfolder` longblob,
- PRIMARY KEY (`id`)
+ `contactsfilter_id` varchar(40) DEFAULT NULL,
+ `calendarfilter_id` varchar(40) DEFAULT NULL,
+ `tasksfilter_id` varchar(40) DEFAULT NULL,
+ `emailfilter_id` varchar(40) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `owner_id--deviceid` (`owner_id`, `deviceid`)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `syncroton_folder` (
- `id` varchar(40) NOT NULL,
- `device_id` varchar(40) NOT NULL,
- `class` varchar(64) NOT NULL,
- `folderid` varchar(254) NOT NULL,
- `parentid` varchar(254) DEFAULT NULL,
- `displayname` varchar(254) NOT NULL,
- `type` int(11) NOT NULL,
- `creation_time` datetime NOT NULL,
- `lastfiltertype` int(11) DEFAULT NULL,
- PRIMARY KEY (`id`),
- UNIQUE KEY `device_id--class--folderid` (`device_id`,`class`,`folderid`),
- CONSTRAINT `syncroton_folder::device_id--syncroton_device::id` FOREIGN KEY (`device_id`)
- REFERENCES `syncroton_device` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+ `id` varchar(40) NOT NULL,
+ `device_id` varchar(40) NOT NULL,
+ `class` varchar(64) NOT NULL,
+ `folderid` varchar(254) NOT NULL,
+ `parentid` varchar(254) DEFAULT NULL,
+ `displayname` varchar(254) NOT NULL,
+ `type` int(11) NOT NULL,
+ `creation_time` datetime NOT NULL,
+ `lastfiltertype` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `device_id--class--folderid` (`device_id`(40),`class`(40),`folderid`(40)),
+ KEY `folderstates::device_id--devices::id` (`device_id`),
+ CONSTRAINT `folderstates::device_id--devices::id` FOREIGN KEY (`device_id`) REFERENCES `syncroton_device` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
-CREATE TABLE `syncroton_synckey` (
- `id` varchar(40) NOT NULL,
- `device_id` varchar(40) NOT NULL DEFAULT '',
- `type` varchar(64) NOT NULL DEFAULT '',
- `counter` int(11) unsigned NOT NULL DEFAULT '0',
- `lastsync` datetime DEFAULT NULL,
- `pendingdata` longblob,
- PRIMARY KEY (`id`),
- UNIQUE KEY `device_id--type--counter` (`device_id`,`type`,`counter`),
- CONSTRAINT `syncroton_synckey::device_id--syncroton_device::id` FOREIGN KEY (`device_id`)
- REFERENCES `syncroton_device` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+CREATE TABLE IF NOT EXISTS `syncroton_synckey` (
+ `id` varchar(40) NOT NULL,
+ `device_id` varchar(40) NOT NULL DEFAULT '',
+ `type` varchar(64) NOT NULL DEFAULT '',
+ `counter` int(11) NOT NULL DEFAULT '0',
+ `lastsync` datetime DEFAULT NULL,
+ `pendingdata` longblob,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `device_id--type--counter` (`device_id`,`type`,`counter`),
+ CONSTRAINT `syncroton_synckey::device_id--syncroton_device::id` FOREIGN KEY (`device_id`) REFERENCES `syncroton_device` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
-CREATE TABLE `syncroton_content` (
- `id` varchar(40) NOT NULL,
- `device_id` varchar(40) DEFAULT NULL,
- `folder_id` varchar(40) DEFAULT NULL,
- `contentid` varchar(64) DEFAULT NULL,
- `creation_time` datetime DEFAULT NULL,
- `creation_synckey` int(11) NOT NULL,
- `is_deleted` tinyint(1) unsigned DEFAULT '0',
- PRIMARY KEY (`id`),
- UNIQUE KEY `device_id--folder_id--contentid` (`device_id`,`folder_id`,`contentid`),
- CONSTRAINT `syncroton_content::device_id--syncroton_device::id` FOREIGN KEY (`device_id`)
- REFERENCES `syncroton_device` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+CREATE TABLE IF NOT EXISTS `syncroton_content` (
+ `id` varchar(40) NOT NULL,
+ `device_id` varchar(40) DEFAULT NULL,
+ `folder_id` varchar(40) DEFAULT NULL,
+ `contentid` varchar(64) DEFAULT NULL,
+ `creation_time` datetime DEFAULT NULL,
+ `creation_synckey` int(11) NOT NULL,
+ `is_deleted` tinyint(1) DEFAULT '0',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `device_id--folder_id--contentid` (`device_id`(40),`folder_id`(40),`contentid`(40)),
+ KEY `syncroton_contents::device_id` (`device_id`),
+ CONSTRAINT `syncroton_contents::device_id--syncroton_device::id` FOREIGN KEY (`device_id`) REFERENCES `syncroton_device` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB;
+
+CREATE TABLE IF NOT EXISTS `syncroton_data` (
+ `id` varchar(40) NOT NULL,
+ `type` varchar(40) NOT NULL,
+ `folder_id` varchar(40) NOT NULL,
+ `data` longblob,
+ PRIMARY KEY (`id`)
) ENGINE=InnoDB;
diff --git a/lib/ext/Roundcube/rcube_mdb2.php b/lib/ext/Roundcube/rcube_mdb2.php
deleted file mode 100644
index 721963b..0000000
--- a/lib/ext/Roundcube/rcube_mdb2.php
+++ /dev/null
@@ -1,935 +0,0 @@
-<?php
-
-/*
- +-----------------------------------------------------------------------+
- | program/include/rcube_mdb2.php |
- | |
- | This file is part of the Roundcube Webmail client |
- | Copyright (C) 2005-2009, The Roundcube Dev Team |
- | |
- | Licensed under the GNU General Public License version 3 or |
- | any later version with exceptions for skins & plugins. |
- | See the README file for a full license statement. |
- | |
- | PURPOSE: |
- | PEAR:DB wrapper class that implements PEAR MDB2 functions |
- | See http://pear.php.net/package/MDB2 |
- | |
- +-----------------------------------------------------------------------+
- | Author: Lukas Kahwe Smith <smith at pooteeweet.org> |
- +-----------------------------------------------------------------------+
-*/
-
-
-/**
- * Database independent query interface
- *
- * This is a wrapper for the PEAR::MDB2 class
- *
- * @package Database
- * @author David Saez Padros <david at ols.es>
- * @author Thomas Bruederli <roundcube at gmail.com>
- * @author Lukas Kahwe Smith <smith at pooteeweet.org>
- * @version 1.18
- * @link http://pear.php.net/package/MDB2
- */
-class rcube_mdb2
-{
- public $db_dsnw; // DSN for write operations
- public $db_dsnr; // DSN for read operations
- public $db_connected = false; // Already connected ?
- public $db_mode = ''; // Connection mode
- public $db_handle = 0; // Connection handle
- public $db_error = false;
- public $db_error_msg = '';
-
- private $debug_mode = false;
- private $conn_failure = false;
- private $a_query_results = array('dummy');
- private $last_res_id = 0;
- private $tables;
- private $variables;
-
-
- /**
- * Object constructor
- *
- * @param string $db_dsnw DSN for read/write operations
- * @param string $db_dsnr Optional DSN for read only operations
- */
- public function __construct($db_dsnw, $db_dsnr='', $pconn=false)
- {
- if (empty($db_dsnr)) {
- $db_dsnr = $db_dsnw;
- }
-
- $this->db_dsnw = $db_dsnw;
- $this->db_dsnr = $db_dsnr;
- $this->db_pconn = $pconn;
-
- $dsn_array = MDB2::parseDSN($db_dsnw);
- $this->db_provider = $dsn_array['phptype'];
- }
-
-
- /**
- * Connect to specific database
- *
- * @param string $dsn DSN for DB connections
- * @return MDB2 PEAR database handle
- * @access private
- */
- private function dsn_connect($dsn)
- {
- // Use persistent connections if available
- $db_options = array(
- 'persistent' => $this->db_pconn,
- 'emulate_prepared' => $this->debug_mode,
- 'debug' => $this->debug_mode,
- 'debug_handler' => array($this, 'debug_handler'),
- 'portability' => MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL,
- );
-
- if ($this->db_provider == 'pgsql') {
- $db_options['disable_smart_seqname'] = true;
- $db_options['seqname_format'] = '%s';
- }
- $this->db_error = false;
- $this->db_error_msg = null;
-
- $dbh = MDB2::connect($dsn, $db_options);
-
- if (MDB2::isError($dbh)) {
- $this->db_error = true;
- $this->db_error_msg = $dbh->getMessage();
-
- rcube::raise_error(array('code' => 500, 'type' => 'db',
- 'line' => __LINE__, 'file' => __FILE__,
- 'message' => $dbh->getUserInfo()), true, false);
- }
- else if ($this->db_provider == 'sqlite') {
- $dsn_array = MDB2::parseDSN($dsn);
- if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials)) {
- $this->sqlite_create_database($dbh, $this->sqlite_initials);
- }
- }
- else if ($this->db_provider != 'mssql' && $this->db_provider != 'sqlsrv') {
- $dbh->setCharset('utf8');
- }
-
- return $dbh;
- }
-
-
- /**
- * Connect to appropiate database depending on the operation
- *
- * @param string $mode Connection mode (r|w)
- */
- public function db_connect($mode)
- {
- // previous connection failed, don't attempt to connect again
- if ($this->conn_failure) {
- return;
- }
-
- // no replication
- if ($this->db_dsnw == $this->db_dsnr) {
- $mode = 'w';
- }
-
- // Already connected
- if ($this->db_connected) {
- // connected to db with the same or "higher" mode
- if ($this->db_mode == 'w' || $this->db_mode == $mode) {
- return;
- }
- }
-
- $dsn = ($mode == 'r') ? $this->db_dsnr : $this->db_dsnw;
-
- $this->db_handle = $this->dsn_connect($dsn);
- $this->db_connected = !PEAR::isError($this->db_handle);
-
- // use write-master when read-only fails
- if (!$this->db_connected && $mode == 'r') {
- $mode = 'w';
- $this->db_handle = $this->dsn_connect($this->db_dsnw);
- $this->db_connected = !PEAR::isError($this->db_handle);
- }
-
- if ($this->db_connected) {
- $this->db_mode = $mode;
- }
- else {
- $this->conn_failure = true;
- }
- }
-
-
- /**
- * Activate/deactivate debug mode
- *
- * @param boolean $dbg True if SQL queries should be logged
- */
- public function set_debug($dbg = true)
- {
- $this->debug_mode = $dbg;
- if ($this->db_connected) {
- $this->db_handle->setOption('debug', $dbg);
- $this->db_handle->setOption('emulate_prepared', $dbg);
- }
- }
-
-
- /**
- * Getter for error state
- *
- * @param boolean True on error
- */
- public function is_error()
- {
- return $this->db_error ? $this->db_error_msg : false;
- }
-
-
- /**
- * Connection state checker
- *
- * @param boolean True if in connected state
- */
- public function is_connected()
- {
- return PEAR::isError($this->db_handle) ? false : $this->db_connected;
- }
-
-
- /**
- * Is database replication configured?
- * This returns true if dsnw != dsnr
- */
- public function is_replicated()
- {
- return !empty($this->db_dsnr) && $this->db_dsnw != $this->db_dsnr;
- }
-
-
- /**
- * Get database runtime variables
- *
- * @param string Variable name
- * @param mixed Default value if var is not set
- * @return mixed Variable value or default
- */
- public function get_variable($varname, $default = null)
- {
- if (!isset($this->variables)) {
- $this->variables = array();
-
- // only mysql and postgres are know to support this
- if ($this->db_provider == 'pgsql' || $this->db_provider == 'mysql' || $this->db_provider == 'mysqli') {
- $this->db_connect('r');
- $query = $this->db_provider == 'pgsql' ? 'SHOW ALL' : 'SHOW VARIABLES';
- foreach ((array)$this->db_handle->queryAll($query) as $row)
- $this->variables[$row[0]] = $row[1];
- }
- }
-
- return isset($this->variables[$varname]) ? $this->variables[$varname] : $default;
- }
-
-
- /**
- * Execute a SQL query
- *
- * @param string SQL query to execute
- * @param mixed Values to be inserted in query
- *
- * @return number Query handle identifier
- */
- public function query()
- {
- $params = func_get_args();
- $query = array_shift($params);
-
- // Support one argument of type array, instead of n arguments
- if (count($params) == 1 && is_array($params[0])) {
- $params = $params[0];
- }
-
- return $this->_query($query, 0, 0, $params);
- }
-
-
- /**
- * Execute a SQL query with limits
- *
- * @param string SQL query to execute
- * @param number Offset for LIMIT statement
- * @param number Number of rows for LIMIT statement
- * @param mixed Values to be inserted in query
- *
- * @return number Query handle identifier
- */
- public function limitquery()
- {
- $params = func_get_args();
- $query = array_shift($params);
- $offset = array_shift($params);
- $numrows = array_shift($params);
-
- return $this->_query($query, $offset, $numrows, $params);
- }
-
-
- /**
- * Execute a SQL query with limits
- *
- * @param string $query SQL query to execute
- * @param number $offset Offset for LIMIT statement
- * @param number $numrows Number of rows for LIMIT statement
- * @param array $params Values to be inserted in query
- * @return number Query handle identifier
- * @access private
- */
- private function _query($query, $offset, $numrows, $params)
- {
- // Read or write ?
- $mode = (strtolower(substr(trim($query),0,6)) == 'select') ? 'r' : 'w';
-
- $this->db_connect($mode);
-
- // check connection before proceeding
- if (!$this->is_connected()) {
- return null;
- }
-
- if ($this->db_provider == 'sqlite') {
- $this->sqlite_prepare();
- }
-
- if ($numrows || $offset) {
- $result = $this->db_handle->setLimit($numrows,$offset);
- }
-
- if (empty($params)) {
- $result = $mode == 'r' ? $this->db_handle->query($query) : $this->db_handle->exec($query);
- }
- else {
- $params = (array)$params;
- $q = $this->db_handle->prepare($query, null, $mode=='w' ? MDB2_PREPARE_MANIP : null);
- if ($this->db_handle->isError($q)) {
- $this->db_error = true;
- $this->db_error_msg = $q->userinfo;
-
- rcube::raise_error(array('code' => 500, 'type' => 'db',
- 'line' => __LINE__, 'file' => __FILE__,
- 'message' => $this->db_error_msg), true, false);
-
- $result = false;
- }
- else {
- $result = $q->execute($params);
- $q->free();
- }
- }
-
- // add result, even if it's an error
- return $this->_add_result($result);
- }
-
-
- /**
- * Get number of rows for a SQL query
- * If no query handle is specified, the last query will be taken as reference
- *
- * @param number $res_id Optional query handle identifier
- * @return mixed Number of rows or false on failure
- */
- public function num_rows($res_id=null)
- {
- if (!$this->db_connected) {
- return false;
- }
-
- if ($result = $this->_get_result($res_id)) {
- return $result->numRows();
- }
-
- return false;
- }
-
-
- /**
- * Get number of affected rows for the last query
- *
- * @param number $res_id Optional query handle identifier
- * @return mixed Number of rows or false on failure
- */
- public function affected_rows($res_id = null)
- {
- if (!$this->db_connected) {
- return false;
- }
-
- return $this->_get_result($res_id);
- }
-
-
- /**
- * Get last inserted record ID
- * For Postgres databases, a sequence name is required
- *
- * @param string $table Table name (to find the incremented sequence)
- *
- * @return mixed ID or false on failure
- */
- public function insert_id($table = '')
- {
- if (!$this->db_connected || $this->db_mode == 'r') {
- return false;
- }
-
- if ($table) {
- if ($this->db_provider == 'pgsql') {
- // find sequence name
- $table = $this->sequence_name($table);
- }
- else {
- // resolve table name
- $table = $this->table_name($table);
- }
- }
-
- $id = $this->db_handle->lastInsertID($table);
-
- return $this->db_handle->isError($id) ? null : $id;
- }
-
-
- /**
- * Get an associative array for one row
- * If no query handle is specified, the last query will be taken as reference
- *
- * @param number $res_id Optional query handle identifier
- *
- * @return mixed Array with col values or false on failure
- */
- public function fetch_assoc($res_id = null)
- {
- $result = $this->_get_result($res_id);
- return $this->_fetch_row($result, MDB2_FETCHMODE_ASSOC);
- }
-
-
- /**
- * Get an index array for one row
- * If no query handle is specified, the last query will be taken as reference
- *
- * @param number $res_id Optional query handle identifier
- *
- * @return mixed Array with col values or false on failure
- */
- public function fetch_array($res_id = null)
- {
- $result = $this->_get_result($res_id);
- return $this->_fetch_row($result, MDB2_FETCHMODE_ORDERED);
- }
-
-
- /**
- * Get col values for a result row
- *
- * @param MDB2_Result_Common Query $result result handle
- * @param number $mode Fetch mode identifier
- *
- * @return mixed Array with col values or false on failure
- */
- private function _fetch_row($result, $mode)
- {
- if ($result === false || PEAR::isError($result) || !$this->is_connected()) {
- return false;
- }
-
- return $result->fetchRow($mode);
- }
-
-
- /**
- * Wrapper for the SHOW TABLES command
- *
- * @return array List of all tables of the current database
- * @since 0.4-beta
- */
- public function list_tables()
- {
- // get tables if not cached
- if (!$this->tables) {
- $this->db_handle->loadModule('Manager');
- if (!PEAR::isError($result = $this->db_handle->listTables())) {
- $this->tables = $result;
- }
- else {
- $this->tables = array();
- }
- }
-
- return $this->tables;
- }
-
-
- /**
- * Wrapper for SHOW COLUMNS command
- *
- * @param string Table name
- *
- * @return array List of table cols
- */
- public function list_cols($table)
- {
- $this->db_handle->loadModule('Manager');
- if (!PEAR::isError($result = $this->db_handle->listTableFields($table))) {
- return $result;
- }
-
- return null;
- }
-
-
- /**
- * Formats input so it can be safely used in a query
- *
- * @param mixed $input Value to quote
- * @param string $type Type of data
- *
- * @return string Quoted/converted string for use in query
- */
- public function quote($input, $type = null)
- {
- // handle int directly for better performance
- if ($type == 'integer') {
- return intval($input);
- }
-
- // create DB handle if not available
- if (!$this->db_handle) {
- $this->db_connect('r');
- }
-
- return $this->db_connected ? $this->db_handle->quote($input, $type) : addslashes($input);
- }
-
-
- /**
- * Quotes a string so it can be safely used as a table or column name
- *
- * @param string $str Value to quote
- *
- * @return string Quoted string for use in query
- * @deprecated Replaced by rcube_MDB2::quote_identifier
- * @see rcube_mdb2::quote_identifier
- */
- public function quoteIdentifier($str)
- {
- return $this->quote_identifier($str);
- }
-
-
- /**
- * Quotes a string so it can be safely used as a table or column name
- *
- * @param string $str Value to quote
- *
- * @return string Quoted string for use in query
- */
- public function quote_identifier($str)
- {
- if (!$this->db_handle) {
- $this->db_connect('r');
- }
-
- return $this->db_connected ? $this->db_handle->quoteIdentifier($str) : $str;
- }
-
-
- /**
- * Escapes a string
- *
- * @param string $str The string to be escaped
- *
- * @return string The escaped string
- * @since 0.1.1
- */
- public function escapeSimple($str)
- {
- if (!$this->db_handle) {
- $this->db_connect('r');
- }
-
- return $this->db_handle->escape($str);
- }
-
-
- /**
- * Return SQL function for current time and date
- *
- * @return string SQL function to use in query
- */
- public function now()
- {
- switch ($this->db_provider) {
- case 'mssql':
- case 'sqlsrv':
- return "getdate()";
-
- default:
- return "now()";
- }
- }
-
-
- /**
- * Return list of elements for use with SQL's IN clause
- *
- * @param array $arr Input array
- * @param string $type Type of data
- *
- * @return string Comma-separated list of quoted values for use in query
- */
- public function array2list($arr, $type = null)
- {
- if (!is_array($arr)) {
- return $this->quote($arr, $type);
- }
-
- foreach ($arr as $idx => $item) {
- $arr[$idx] = $this->quote($item, $type);
- }
-
- return implode(',', $arr);
- }
-
-
- /**
- * Return SQL statement to convert a field value into a unix timestamp
- *
- * This method is deprecated and should not be used anymore due to limitations
- * of timestamp functions in Mysql (year 2038 problem)
- *
- * @param string $field Field name
- *
- * @return string SQL statement to use in query
- * @deprecated
- */
- public function unixtimestamp($field)
- {
- switch($this->db_provider) {
- case 'pgsql':
- return "EXTRACT (EPOCH FROM $field)";
-
- case 'mssql':
- case 'sqlsrv':
- return "DATEDIFF(second, '19700101', $field) + DATEDIFF(second, GETDATE(), GETUTCDATE())";
-
- default:
- return "UNIX_TIMESTAMP($field)";
- }
- }
-
-
- /**
- * Return SQL statement to convert from a unix timestamp
- *
- * @param string $timestamp Field name
- *
- * @return string SQL statement to use in query
- */
- public function fromunixtime($timestamp)
- {
- return date("'Y-m-d H:i:s'", $timestamp);
- }
-
-
- /**
- * Return SQL statement for case insensitive LIKE
- *
- * @param string $column Field name
- * @param string $value Search value
- *
- * @return string SQL statement to use in query
- */
- public function ilike($column, $value)
- {
- // TODO: use MDB2's matchPattern() function
- switch ($this->db_provider) {
- case 'pgsql':
- return $this->quote_identifier($column).' ILIKE '.$this->quote($value);
- default:
- return $this->quote_identifier($column).' LIKE '.$this->quote($value);
- }
- }
-
-
- /**
- * Abstract SQL statement for value concatenation
- *
- * @return string SQL statement to be used in query
- */
- public function concat(/* col1, col2, ... */)
- {
- $func = '';
- $args = func_get_args();
- if (is_array($args[0]))
- $args = $args[0];
-
- switch ($this->db_provider) {
- case 'mysql':
- case 'mysqli':
- $func = 'CONCAT';
- $delim = ', ';
- break;
- case 'mssql':
- case 'sqlsrv':
- $delim = ' + ';
- // Modify arguments, because + operator requires them to be of type varchar (#1488505)
- // with SQL Server 2012 we can use just CONCAT(), but we need to support older versions
- foreach ($args as $idx => $arg) {
- $args[$idx] = "CAST($arg AS varchar)";
- }
- break;
- default:
- $delim = ' || ';
- }
-
- return $func . '(' . join($delim, $args) . ')';
- }
-
-
- /**
- * Encodes non-UTF-8 characters in string/array/object (recursive)
- *
- * @param mixed $input Data to fix
- *
- * @return mixed Properly UTF-8 encoded data
- */
- public static function encode($input)
- {
- if (is_object($input)) {
- foreach (get_object_vars($input) as $idx => $value) {
- $input->$idx = self::encode($value);
- }
- return $input;
- }
- else if (is_array($input)) {
- foreach ($input as $idx => $value) {
- $input[$idx] = self::encode($value);
- }
- return $input;
- }
-
- return utf8_encode($input);
- }
-
-
- /**
- * Decodes encoded UTF-8 string/object/array (recursive)
- *
- * @param mixed $input Input data
- *
- * @return mixed Decoded data
- */
- public static function decode($input)
- {
- if (is_object($input)) {
- foreach (get_object_vars($input) as $idx => $value) {
- $input->$idx = self::decode($value);
- }
- return $input;
- }
- else if (is_array($input)) {
- foreach ($input as $idx => $value) {
- $input[$idx] = self::decode($value);
- }
- return $input;
- }
-
- return utf8_decode($input);
- }
-
-
- /**
- * Adds a query result and returns a handle ID
- *
- * @param object $res Query handle
- *
- * @return mixed Handle ID
- */
- private function _add_result($res)
- {
- // sql error occured
- if (PEAR::isError($res)) {
- $this->db_error = true;
- $this->db_error_msg = $res->getMessage();
- rcube::raise_error(array('code' => 500, 'type' => 'db',
- 'line' => __LINE__, 'file' => __FILE__,
- 'message' => $res->getMessage() . " Query: "
- . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 512)),
- true, false);
- }
-
- $res_id = sizeof($this->a_query_results);
- $this->last_res_id = $res_id;
- $this->a_query_results[$res_id] = $res;
- return $res_id;
- }
-
-
- /**
- * Resolves a given handle ID and returns the according query handle
- * If no ID is specified, the last resource handle will be returned
- *
- * @param number $res_id Handle ID
- *
- * @return mixed Resource handle or false on failure
- */
- private function _get_result($res_id = null)
- {
- if ($res_id == null) {
- $res_id = $this->last_res_id;
- }
-
- if (isset($this->a_query_results[$res_id])) {
- if (!PEAR::isError($this->a_query_results[$res_id])) {
- return $this->a_query_results[$res_id];
- }
- }
-
- return false;
- }
-
-
- /**
- * Create a sqlite database from a file
- *
- * @param MDB2 $dbh SQLite database handle
- * @param string $file_name File path to use for DB creation
- */
- private function sqlite_create_database($dbh, $file_name)
- {
- if (empty($file_name) || !is_string($file_name)) {
- return;
- }
-
- $data = file_get_contents($file_name);
-
- if (strlen($data)) {
- if (!sqlite_exec($dbh->connection, $data, $error) || MDB2::isError($dbh)) {
- rcube::raise_error(array('code' => 500, 'type' => 'db',
- 'line' => __LINE__, 'file' => __FILE__,
- 'message' => $error), true, false);
- }
- }
- }
-
-
- /**
- * Add some proprietary database functions to the current SQLite handle
- * in order to make it MySQL compatible
- */
- private function sqlite_prepare()
- {
- // we emulate via callback some missing MySQL functions
- sqlite_create_function($this->db_handle->connection,
- 'unix_timestamp', array('rcube_mdb2', 'sqlite_unix_timestamp'));
- sqlite_create_function($this->db_handle->connection,
- 'now', array('rcube_mdb2', 'sqlite_now'));
- }
-
-
- /**
- * Debug handler for the MDB2
- */
- function debug_handler(&$db, $scope, $message, $context = array())
- {
- if ($scope != 'prepare') {
- $debug_output = sprintf('%s(%d): %s;',
- $scope, $db->db_index, rtrim($message, ';'));
- rcube::write_log('sql', $debug_output);
- }
- }
-
-
- /**
- * Return correct name for a specific database table
- *
- * @param string $table Table name
- *
- * @return string Translated table name
- */
- public function table_name($table)
- {
- $rcube = rcube::get_instance();
-
- // return table name if configured
- $config_key = 'db_table_'.$table;
-
- if ($name = $rcube->config->get($config_key)) {
- return $name;
- }
-
- return $table;
- }
-
-
- /**
- * Return correct name for a specific database sequence
- * (used for Postgres only)
- *
- * @param string $sequence Secuence name
- *
- * @return string Translated sequence name
- */
- public function sequence_name($sequence)
- {
- $rcube = rcube::get_instance();
-
- // return sequence name if configured
- $config_key = 'db_sequence_'.$sequence;
-
- if ($name = $rcube->config->get($config_key)) {
- return $name;
- }
-
- return $sequence;
- }
-
-
- /**
- * Callback for sqlite: unix_timestamp()
- */
- public static function sqlite_unix_timestamp($timestamp = '')
- {
- $timestamp = trim($timestamp);
- if (!$timestamp) {
- $ret = time();
- }
- else if (!preg_match('/^[0-9]+$/s', $timestamp)) {
- $ret = strtotime($timestamp);
- }
- else {
- $ret = $timestamp;
- }
-
- return $ret;
- }
-
-
- /**
- * Callback for sqlite: now()
- */
- public static function sqlite_now()
- {
- return date("Y-m-d H:i:s");
- }
-
-}
diff --git a/lib/ext/Syncroton/Backend/ABackend.php b/lib/ext/Syncroton/Backend/ABackend.php
new file mode 100644
index 0000000..d345d6d
--- /dev/null
+++ b/lib/ext/Syncroton/Backend/ABackend.php
@@ -0,0 +1,156 @@
+<?php
+/**
+ * Syncroton
+ *
+ * @package Command
+ * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3
+ * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author Lars Kneschke <l.kneschke at metaways.de>
+ */
+
+/**
+ * class to handle ActiveSync Sync command
+ *
+ * @package Backend
+ */
+
+abstract class Syncroton_Backend_ABackend implements Syncroton_Backend_IBackend
+{
+ /**
+ * the database adapter
+ *
+ * @var Zend_Db_Adapter_Abstract
+ */
+ protected $_db;
+
+ protected $_tablePrefix;
+
+ protected $_tableName;
+
+ protected $_modelClassName;
+
+ protected $_modelInterfaceName;
+
+ public function __construct(Zend_Db_Adapter_Abstract $_db, $_tablePrefix = 'Syncroton_')
+ {
+ $this->_db = $_db;
+ $this->_tablePrefix = $_tablePrefix;
+ }
+
+ /**
+ * create new device
+ *
+ * @param Syncroton_Model_IDevice $_device
+ * @return Syncroton_Model_IDevice
+ */
+ public function create($model)
+ {
+ if (! $model instanceof $this->_modelInterfaceName) {
+ throw new InvalidArgumentException('$model must be instanace of ' . $this->_modelInterfaceName);
+ }
+
+ $data = $this->_convertModelToArray($model);
+
+ $data['id'] = sha1(mt_rand(). microtime());
+
+ $this->_db->insert($this->_tablePrefix . $this->_tableName, $data);
+
+ return $this->get($data['id']);
+ }
+
+ protected function _convertModelToArray($model)
+ {
+ $data = array();
+
+ foreach ($model as $key => $value) {
+ if ($value instanceof DateTime) {
+ $value = $value->format('Y-m-d H:i:s');
+ } elseif (is_object($value) && isset($value->id)) {
+ $value = $value->id;
+ }
+
+ $data[$this->_fromCamelCase($key)] = $value;
+ }
+
+ return $data;
+ }
+
+ /**
+ * @param string $_id
+ * @throws Syncroton_Exception_NotFound
+ * @return Syncroton_Model_IDevice
+ */
+ public function get($id)
+ {
+ $id = $id instanceof $this->_modelInterfaceName ? $id->id : $id;
+
+ $select = $this->_db->select()
+ ->from($this->_tablePrefix . $this->_tableName)
+ ->where('id = ?', $id);
+
+ $stmt = $this->_db->query($select);
+ $data = $stmt->fetch();
+ $stmt = null; # see https://bugs.php.net/bug.php?id=44081
+
+ if ($data === false) {
+ throw new Syncroton_Exception_NotFound('id not found');
+ }
+
+ return $this->_getObject($data);
+ }
+
+ protected function _getObject($data)
+ {
+ foreach ($data as $key => $value) {
+ unset($data[$key]);
+
+ if (!empty($value) && preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', $value)) { # 2012-08-12 07:43:26
+ $value = new DateTime($value, new DateTimeZone('utc'));
+ }
+
+ $data[$this->_toCamelCase($key, false)] = $value;
+ }
+
+ return new $this->_modelClassName($data);
+ }
+
+ public function delete($id)
+ {
+ $id = $id instanceof $this->_modelInterfaceName ? $id->id : $id;
+
+ $result = $this->_db->delete($this->_tablePrefix . $this->_tableName, array('id = ?' => $id));
+
+ return (bool) $result;
+ }
+
+ public function update($model)
+ {
+ if (! $model instanceof $this->_modelInterfaceName) {
+ throw new InvalidArgumentException('$model must be instanace of ' . $this->_modelInterfaceName);
+ }
+
+ $data = $this->_convertModelToArray($model);
+
+ $this->_db->update($this->_tablePrefix . $this->_tableName, $data, array(
+ 'id = ?' => $model->id
+ ));
+
+ return $this->get($model->id);
+ }
+
+ protected function _fromCamelCase($string)
+ {
+ $string = lcfirst($string);
+
+ return preg_replace_callback('/([A-Z])/', function ($string) {return '_' . strtolower($string[0]);}, $string);
+ }
+
+ protected function _toCamelCase($string, $ucFirst = true)
+ {
+ if ($ucFirst === true) {
+ $string = ucfirst($string);
+ }
+
+ return preg_replace_callback('/_([a-z])/', function ($string) {return strtoupper($string[1]);}, $string);
+ }
+}
diff --git a/lib/ext/Syncroton/Backend/Content.php b/lib/ext/Syncroton/Backend/Content.php
index 2500a17..b186b00 100644
--- a/lib/ext/Syncroton/Backend/Content.php
+++ b/lib/ext/Syncroton/Backend/Content.php
@@ -16,48 +16,13 @@
* @package Syncroton
* @subpackage Backend
*/
-class Syncroton_Backend_Content implements Syncroton_Backend_IContent
+class Syncroton_Backend_Content extends Syncroton_Backend_ABackend implements Syncroton_Backend_IContent
{
- /**
- * the database adapter
- *
- * @var Zend_Db_Adapter_Abstract
- */
- protected $_db;
-
- protected $_tablePrefix;
-
- public function __construct(Zend_Db_Adapter_Abstract $_db, $_tablePrefix = 'Syncroton_')
- {
- $this->_db = $_db;
- $this->_tablePrefix = $_tablePrefix;
- }
-
- /**
- * create new content state
- *
- * @param Syncroton_Model_IContent $_state
- * @return Syncroton_Model_IContent
- */
- public function create(Syncroton_Model_IContent $_state)
- {
- $id = sha1(mt_rand(). microtime());
-
- $deviceId = $_state->device_id instanceof Syncroton_Model_IDevice ? $_state->device_id->id : $_state->device_id;
- $folderId = $_state->folder_id instanceof Syncroton_Model_IFolder ? $_state->folder_id->id : $_state->folder_id;
-
- $this->_db->insert($this->_tablePrefix . 'content', array(
- 'id' => $id,
- 'device_id' => $deviceId,
- 'folder_id' => $folderId,
- 'contentid' => $_state->contentid,
- 'creation_time' => $_state->creation_time->format('Y-m-d H:i:s'),
- 'creation_synckey' => $_state->creation_synckey,
- 'is_deleted' => isset($_state->is_deleted) ? (int)!!$_state->is_deleted : 0
- ));
-
- return $this->get($id);
- }
+ protected $_tableName = 'content';
+
+ protected $_modelClassName = 'Syncroton_Model_Content';
+
+ protected $_modelInterfaceName = 'Syncroton_Model_IContent';
/**
* mark state as deleted. The state gets removed finally,
@@ -65,9 +30,9 @@ class Syncroton_Backend_Content implements Syncroton_Backend_IContent
*
* @param Syncroton_Model_IContent|string $_id
*/
- public function delete($_id)
+ public function delete($id)
{
- $id = $_id instanceof Syncroton_Model_IContent ? $_id->id : $_id;
+ $id = $id instanceof $this->_modelInterfaceName ? $id->id : $id;
$this->_db->update($this->_tablePrefix . 'content', array(
'is_deleted' => 1
@@ -78,73 +43,45 @@ class Syncroton_Backend_Content implements Syncroton_Backend_IContent
}
/**
- * @param string $_id
- * @throws Syncroton_Exception_NotFound
- * @return Syncroton_Model_IContent
- */
- public function get($_id)
- {
- $select = $this->_db->select()
- ->from($this->_tablePrefix . 'content')
- ->where('id = ?', $_id);
-
- $stmt = $this->_db->query($select);
- $state = $stmt->fetchObject('Syncroton_Model_Content');
-
- if (! $state instanceof Syncroton_Model_IContent) {
- throw new Syncroton_Exception_NotFound('id not found');
- }
-
- if (!empty($state->creation_time)) {
- $state->creation_time = new DateTime($state->creation_time, new DateTimeZone('utc'));
- }
-
- return $state;
- }
-
- /**
- * @param Syncroton_Model_IDevice|string $_deviceId
- * @param Syncroton_Model_IFolder|string $_folderId
+ * @param Syncroton_Model_IDevice|string $deviceId
+ * @param Syncroton_Model_IFolder|string $folderId
* @param string $_contentId
* @return Syncroton_Model_IContent
*/
- public function getContentState($_deviceId, $_folderId, $_contentId)
+ public function getContentState($deviceId, $folderId, $contentId)
{
- $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
- $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
+ $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId;
+ $folderId = $folderId instanceof Syncroton_Model_IFolder ? $folderId->id : $folderId;
$select = $this->_db->select()
->from($this->_tablePrefix . 'content')
->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId)
->where($this->_db->quoteIdentifier('folder_id') . ' = ?', $folderId)
- ->where($this->_db->quoteIdentifier('contentid') . ' = ?', $_contentId)
+ ->where($this->_db->quoteIdentifier('contentid') . ' = ?', $contentId)
->where($this->_db->quoteIdentifier('is_deleted') . ' = ?', 0);
- $stmt = $this->_db->query($select);
- $state = $stmt->fetchObject('Syncroton_Model_Content');
-
- if (! $state instanceof Syncroton_Model_IContent) {
- throw new Syncroton_Exception_NotFound('id not found');
- }
-
- if (!empty($state->creation_time)) {
- $state->creation_time = new DateTime($state->creation_time, new DateTimeZone('utc'));
- }
-
- return $state;
+ $stmt = $this->_db->query($select);
+ $data = $stmt->fetch();
+ $stmt = null; # see https://bugs.php.net/bug.php?id=44081
+
+ if ($data === false) {
+ throw new Syncroton_Exception_NotFound('id not found');
+ }
+
+ return $this->_getObject($data);
}
/**
* get array of ids which got send to the client for a given class
*
- * @param Syncroton_Model_IDevice|string $_deviceId
- * @param Syncroton_Model_IFolder|string $_folderId
+ * @param Syncroton_Model_IDevice|string $deviceId
+ * @param Syncroton_Model_IFolder|string $folderId
* @return array
*/
- public function getFolderState($_deviceId, $_folderId)
+ public function getFolderState($deviceId, $folderId)
{
- $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
- $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
+ $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId;
+ $folderId = $folderId instanceof Syncroton_Model_IFolder ? $folderId->id : $folderId;
$select = $this->_db->select()
->from($this->_tablePrefix . 'content', 'contentid')
@@ -161,13 +98,13 @@ class Syncroton_Backend_Content implements Syncroton_Backend_IContent
/**
* reset list of stored id
*
- * @param Syncroton_Model_IDevice|string $_deviceId
- * @param Syncroton_Model_IFolder|string $_folderId
+ * @param Syncroton_Model_IDevice|string $deviceId
+ * @param Syncroton_Model_IFolder|string $folderId
*/
- public function resetState($_deviceId, $_folderId)
+ public function resetState($deviceId, $folderId)
{
- $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
- $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
+ $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId;
+ $folderId = $folderId instanceof Syncroton_Model_IFolder ? $folderId->id : $folderId;
$where = array(
$this->_db->quoteInto($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId),
diff --git a/lib/ext/Syncroton/Backend/Device.php b/lib/ext/Syncroton/Backend/Device.php
index 8176a02..f7646b9 100644
--- a/lib/ext/Syncroton/Backend/Device.php
+++ b/lib/ext/Syncroton/Backend/Device.php
@@ -14,68 +14,13 @@
* @package Backend
*/
-class Syncroton_Backend_Device implements Syncroton_Backend_IDevice
+class Syncroton_Backend_Device extends Syncroton_Backend_ABackend implements Syncroton_Backend_IDevice
{
- /**
- * the database adapter
- *
- * @var Zend_Db_Adapter_Abstract
- */
- protected $_db;
+ protected $_tableName = 'device';
- protected $_tablePrefix;
+ protected $_modelClassName = 'Syncroton_Model_Device';
- public function __construct(Zend_Db_Adapter_Abstract $_db, $_tablePrefix = 'Syncroton_')
- {
- $this->_db = $_db;
- $this->_tablePrefix = $_tablePrefix;
- }
-
- /**
- * create new device
- *
- * @param Syncroton_Model_IDevice $_device
- * @return Syncroton_Model_IDevice
- */
- public function create(Syncroton_Model_IDevice $_device)
- {
- $id = sha1(mt_rand(). microtime());
-
- $this->_db->insert($this->_tablePrefix . 'device', array(
- 'id' => $id,
- 'deviceid' => $_device->deviceid,
- 'devicetype' => $_device->devicetype,
- 'owner_id' => $_device->owner_id,
- 'policy_id' => isset($_device->policy_id) ? $_device->policy_id : 1,
- 'policykey' => isset($_device->policykey) ? $_device->policykey : null,
- 'useragent' => isset($_device->useragent) ? $_device->useragent : '',
- 'acsversion' => isset($_device->acsversion) ? $_device->acsversion : '',
- 'remotewipe' => isset($_device->remotewipe) ? $_device->remotewipe : null
- ));
-
- return $this->get($id);
- }
-
- /**
- * @param string $_id
- * @throws Syncroton_Exception_NotFound
- * @return Syncroton_Model_IDevice
- */
- public function get($_id)
- {
- $select = $this->_db->select()
- ->from($this->_tablePrefix . 'device')
- ->where('id = ?', $_id);
-
- $stmt = $this->_db->query($select);
- $device = $stmt->fetchObject('Syncroton_Model_Device');
-
- if (! $device instanceof Syncroton_Model_IDevice) {
- throw new Syncroton_Exception_NotFound('id not found');
- }
-
- return $device;
- }
+ protected $_modelInterfaceName = 'Syncroton_Model_IDevice';
/**
* return device for this user
@@ -88,42 +33,24 @@ class Syncroton_Backend_Device implements Syncroton_Backend_IDevice
public function getUserDevice($ownerId, $deviceId)
{
$select = $this->_db->select()
- ->from($this->_tablePrefix . 'device')
+ ->from($this->_tablePrefix . $this->_tableName)
->where('owner_id = ?', $ownerId)
->where('deviceid = ?', $deviceId);
$stmt = $this->_db->query($select);
- $device = $stmt->fetchObject('Syncroton_Model_Device');
+ $data = $stmt->fetch();
- if (! $device instanceof Syncroton_Model_IDevice) {
- throw new Syncroton_Exception_NotFound('device not found');
+ if ($data === false) {
+ throw new Syncroton_Exception_NotFound('id not found');
+ }
+
+ foreach ($data as $key => $value) {
+ unset($data[$key]);
+ $data[$this->_toCamelCase($key, false)] = $value;
}
- return $device;
- }
-
- public function delete($_id)
- {
- $id = $_id instanceof Syncroton_Model_IDevice ? $_id->id : $_id;
-
- $result = $this->_db->delete($this->_tablePrefix . 'device', array('id = ?' => $id));
-
- return (bool) $result;
- }
-
- public function update(Syncroton_Model_IDevice $_device)
- {
- $this->_db->update($this->_tablePrefix . 'device', array(
- 'acsversion' => $_device->acsversion,
- 'policykey' => $_device->policykey,
- 'pingfolder' => $_device->pingfolder,
- 'pinglifetime' => $_device->pinglifetime,
- 'remotewipe' => $_device->remotewipe
- ), array(
- 'id = ?' => $_device->id
- ));
-
- return $this->get($_device->id);
+ $model = new $this->_modelClassName($data);
+ return $model;
}
}
diff --git a/lib/ext/Syncroton/Backend/Folder.php b/lib/ext/Syncroton/Backend/Folder.php
index 98fd4f4..f42eb08 100644
--- a/lib/ext/Syncroton/Backend/Folder.php
+++ b/lib/ext/Syncroton/Backend/Folder.php
@@ -16,169 +16,121 @@
* @package Syncroton
* @subpackage Backend
*/
-class Syncroton_Backend_Folder implements Syncroton_Backend_IFolder
+class Syncroton_Backend_Folder extends Syncroton_Backend_ABackend implements Syncroton_Backend_IFolder
{
- /**
- * the database adapter
- *
- * @var Zend_Db_Adapter_Abstract
- */
- protected $_db;
+ protected $_tableName = 'folder';
- protected $_tablePrefix;
+ protected $_modelClassName = 'Syncroton_Model_Folder';
- public function __construct(Zend_Db_Adapter_Abstract $_db, $_tablePrefix = 'Syncroton_')
- {
- $this->_db = $_db;
-
- $this->_tablePrefix = $_tablePrefix;
- }
+ protected $_modelInterfaceName = 'Syncroton_Model_IFolder';
/**
- * create new folder state
- *
- * @param Syncroton_Model_IFolder $_folder
- * @return Syncroton_Model_IFolder
+ * (non-PHPdoc)
+ * @see Syncroton_Backend_IFolder::getFolder()
*/
- public function create(Syncroton_Model_IFolder $_folder)
+ public function getFolder($deviceId, $folderId)
{
- $id = sha1(mt_rand(). microtime());
- $deviceId = $_folder->device_id instanceof Syncroton_Model_IDevice ? $_folder->device_id->id : $_folder->device_id;
-
- $this->_db->insert($this->_tablePrefix . 'folder', array(
- 'id' => $id,
- 'device_id' => $deviceId,
- 'class' => $_folder->class,
- 'folderid' => $_folder->folderid instanceof Syncroton_Model_IFolder ? $_folder->folderid->id : $_folder->folderid,
- 'parentid' => $_folder->parentid,
- 'displayname' => $_folder->displayname,
- 'type' => $_folder->type,
- 'creation_time' => $_folder->creation_time->format('Y-m-d H:i:s'),
- 'lastfiltertype' => $_folder->lastfiltertype
- ));
+ $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId;
- return $this->get($id);
- }
-
- public function delete($_id)
- {
- $id = $_id instanceof Syncroton_Model_IFolder ? $_id->id : $_id;
-
- $result = $this->_db->delete($this->_tablePrefix . 'folder', array('id = ?' => $id));
-
- return (bool) $result;
+ $select = $this->_db->select()
+ ->from($this->_tablePrefix . $this->_tableName)
+ ->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId)
+ ->where($this->_db->quoteIdentifier('folderid') . ' = ?', $folderId);
+
+ $stmt = $this->_db->query($select);
+ $data = $stmt->fetch();
+
+ if ($data === false) {
+ throw new Syncroton_Exception_NotFound('id not found');
+ }
+
+ return $this->_getObject($data);
}
/**
- * @param string $_id
- * @throws Syncroton_Exception_NotFound
- * @return Syncroton_Model_IFolder
+ * (non-PHPdoc)
+ * @see Syncroton_Backend_IFolder::getFolderState()
*/
- public function get($_id)
+ public function getFolderState($deviceId, $class)
{
+ $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId;
+
$select = $this->_db->select()
- ->from($this->_tablePrefix . 'folder')
- ->where('id = ?', $_id);
-
- $stmt = $this->_db->query($select);
- $state = $stmt->fetchObject('Syncroton_Model_Folder');
+ ->from($this->_tablePrefix . $this->_tableName)
+ ->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId)
+ ->where($this->_db->quoteIdentifier('class') . ' = ?', $class);
- if (! $state instanceof Syncroton_Model_IFolder) {
- throw new Syncroton_Exception_NotFound('id not found');
- }
+ $result = array();
- if (!empty($state->creation_time)) {
- $state->creation_time = new DateTime($state->creation_time, new DateTimeZone('utc'));
+ $stmt = $this->_db->query($select);
+ while ($data = $stmt->fetch()) {
+ $result[$data['folderid']] = $this->_getObject($data);
}
-
- return $state;
+
+ return $result;
}
/**
- * delete all stored folderId's for given device
- *
- * @param Syncroton_Model_Device|string $_deviceId
- * @param string $_class
+ * (non-PHPdoc)
+ * @see Syncroton_Backend_IFolder::resetState()
*/
- public function resetState($_deviceId)
+ public function resetState($deviceId)
{
- $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
+ $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId;
$where = array(
$this->_db->quoteInto($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId)
);
- $this->_db->delete($this->_tablePrefix . 'folder', $where);
- }
-
- public function update(Syncroton_Model_IFolder $_folder)
- {
- $deviceId = $_folder->device_id instanceof Syncroton_Model_IDevice ? $_folder->device_id->id : $_folder->device_id;
-
- $this->_db->update($this->_tablePrefix . 'folder', array(
- 'lastfiltertype' => $_folder->lastfiltertype,
- 'displayname' => $_folder->displayname,
- 'parentid' => $_folder->parentid
- ), array(
- 'id = ?' => $_folder->id
- ));
-
- return $this->get($_folder->id);
+ $this->_db->delete($this->_tablePrefix . $this->_tableName, $where);
}
/**
- * get array of ids which got send to the client for a given class
- *
- * @param Syncroton_Model_Device|string $_deviceId
- * @param string $_class
- * @return array
+ * (non-PHPdoc)
+ * @see Syncroton_Backend_ABackend::_fromCamelCase()
*/
- public function getFolderState($_deviceId, $_class)
+ protected function _fromCamelCase($string)
{
- $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
-
- $select = $this->_db->select()
- ->from($this->_tablePrefix . 'folder')
- ->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId)
- ->where($this->_db->quoteIdentifier('class') . ' = ?', $_class);
-
- $result = array();
-
- $stmt = $this->_db->query($select);
- while ($row = $stmt->fetchObject("Syncroton_Model_Folder")) {
- $result[$row->folderid] = $row;
- }
-
- return $result;
- }
+ switch ($string) {
+ case 'displayName':
+ case 'parentId':
+ return strtolower($string);
+ break;
+
+ case 'serverId':
+ return 'folderid';
+ break;
+
+ default:
+ return parent::_fromCamelCase($string);
+
+ break;
+ }
+ }
/**
- * get folder indentified by $_folderId
- *
- * @param Syncroton_Model_Device|string $_deviceId
- * @param string $_folderId
- * @return Syncroton_Model_IFolder
- */
- public function getFolder($_deviceId, $_folderId)
+ * (non-PHPdoc)
+ * @see Syncroton_Backend_ABackend::_toCamelCase()
+ */
+ protected function _toCamelCase($string, $ucFirst = true)
{
- $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
-
- $select = $this->_db->select()
- ->from($this->_tablePrefix . 'folder')
- ->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId)
- ->where($this->_db->quoteIdentifier('folderid') . ' = ?', $_folderId);
-
- $stmt = $this->_db->query($select);
- $folder = $stmt->fetchObject('Syncroton_Model_Folder');
-
- if (! $folder instanceof Syncroton_Model_IFolder) {
- throw new Syncroton_Exception_NotFound('folder not found');
- }
-
- if (!empty($folder->creation_time)) {
- $folder->creation_time = new DateTime($folder->creation_time, new DateTimeZone('utc'));
- }
-
- return $folder;
- }
+ switch ($string) {
+ case 'displayname':
+ return 'displayName';
+ break;
+
+ case 'parentid':
+ return 'parentId';
+ break;
+
+ case 'folderid':
+ return 'serverId';
+ break;
+
+ default:
+ return parent::_toCamelCase($string, $ucFirst);
+
+ break;
+ }
+ }
}
diff --git a/lib/ext/Syncroton/Backend/IBackend.php b/lib/ext/Syncroton/Backend/IBackend.php
new file mode 100644
index 0000000..56979fb
--- /dev/null
+++ b/lib/ext/Syncroton/Backend/IBackend.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Syncroton
+ *
+ * @package Command
+ * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3
+ * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author Lars Kneschke <l.kneschke at metaways.de>
+ */
+
+/**
+ * class to handle ActiveSync Sync command
+ *
+ * @package Backend
+ */
+
+interface Syncroton_Backend_IBackend
+{
+ /**
+ * Create a new device
+ *
+ * @param Syncroton_Model_IDevice $device
+ * @return Syncroton_Model_IDevice
+ */
+ public function create($model);
+
+ /**
+ * Deletes one or more existing devices
+ *
+ * @param string|array $_id
+ * @return void
+ */
+ public function delete($id);
+
+ /**
+ * Return a single device
+ *
+ * @param string $_id
+ * @return Syncroton_Model_IDevice
+ */
+ public function get($id);
+
+ /**
+ * Upates an existing persistent record
+ *
+ * @param Syncroton_Model_IDevice $_device
+ * @return Syncroton_Model_IDevice
+ */
+ public function update($model);
+}
diff --git a/lib/ext/Syncroton/Backend/IContent.php b/lib/ext/Syncroton/Backend/IContent.php
index 32d217a..8974e49 100644
--- a/lib/ext/Syncroton/Backend/IContent.php
+++ b/lib/ext/Syncroton/Backend/IContent.php
@@ -16,25 +16,9 @@
* @package Syncroton
* @subpackage Backend
*/
-interface Syncroton_Backend_IContent
+interface Syncroton_Backend_IContent extends Syncroton_Backend_IBackend
{
/**
- * create new content state
- *
- * @param Syncroton_Model_IContent $_contentState
- * @return Syncroton_Model_IContent
- */
- public function create(Syncroton_Model_IContent $_contentState);
-
- /**
- * mark state as deleted. The state gets removed finally,
- * when the synckey gets validated during next sync.
- *
- * @param Syncroton_Model_IContent|string $_id
- */
- public function delete($_id);
-
- /**
* @param Syncroton_Model_IDevice|string $_deviceId
* @param Syncroton_Model_IFolder|string $_folderId
* @param string $_contentId
diff --git a/lib/ext/Syncroton/Backend/IDevice.php b/lib/ext/Syncroton/Backend/IDevice.php
index d6de9fa..27a3a55 100644
--- a/lib/ext/Syncroton/Backend/IDevice.php
+++ b/lib/ext/Syncroton/Backend/IDevice.php
@@ -14,44 +14,12 @@
* @package Backend
*/
-interface Syncroton_Backend_IDevice
+interface Syncroton_Backend_IDevice extends Syncroton_Backend_IBackend
{
/**
- * Create a new device
- *
- * @param Syncroton_Model_IDevice $_device
- * @return Syncroton_Model_IDevice
- */
- public function create(Syncroton_Model_IDevice $_device);
-
- /**
- * Deletes one or more existing devices
- *
- * @param string|array $_id
- * @return void
- */
- public function delete($_id);
-
- /**
- * Return a single device
- *
- * @param string $_id
- * @return Syncroton_Model_IDevice
- */
- public function get($_id);
-
- /**
* @param unknown_type $userId
* @param unknown_type $deviceId
* @return Syncroton_Model_IDevice
*/
public function getUserDevice($userId, $deviceId);
-
- /**
- * Upates an existing persistent record
- *
- * @param Syncroton_Model_IDevice $_device
- * @return Syncroton_Model_IDevice
- */
- public function update(Syncroton_Model_IDevice $_device);
}
diff --git a/lib/ext/Syncroton/Backend/IFolder.php b/lib/ext/Syncroton/Backend/IFolder.php
index 039c5ba..fc1d078 100755
--- a/lib/ext/Syncroton/Backend/IFolder.php
+++ b/lib/ext/Syncroton/Backend/IFolder.php
@@ -16,43 +16,30 @@
* @package Syncroton
* @subpackage Backend
*/
-interface Syncroton_Backend_IFolder
+interface Syncroton_Backend_IFolder extends Syncroton_Backend_IBackend
{
/**
- * @param Syncroton_Model_IFolder $_folder
- * @return Syncroton_Model_IFolder
- */
- public function create(Syncroton_Model_IFolder $_folder);
-
- public function delete($_id);
-
- public function get($_id);
-
- /**
- * get folder indentified by $_folderId
+ * get folder indentified by $folderId
*
- * @param Syncroton_Model_Device|string $_deviceId
- * @param string $_folderId
+ * @param Syncroton_Model_Device|string $deviceId
+ * @param string $folderId
* @return Syncroton_Model_IFolder
*/
- public function getFolder($_deviceId, $_folderId);
+ public function getFolder($deviceId, $folderId);
/**
* get array of ids which got send to the client for a given class
*
- * @param Syncroton_Model_Device $_deviceId
- * @param string $_class
+ * @param Syncroton_Model_Device|string $deviceId
+ * @param string $class
* @return array
*/
- public function getFolderState($_deviceId, $_class);
+ public function getFolderState($deviceId, $class);
/**
* delete all stored folderId's for given device
*
- * @param Syncroton_Model_Device $_deviceId
- * @param string $_class
+ * @param Syncroton_Model_Device|string $deviceId
*/
- public function resetState($_deviceId);
-
- public function update(Syncroton_Model_IFolder $_folder);
+ public function resetState($deviceId);
}
diff --git a/lib/ext/Syncroton/Backend/ISyncState.php b/lib/ext/Syncroton/Backend/ISyncState.php
index d453665..144f61e 100644
--- a/lib/ext/Syncroton/Backend/ISyncState.php
+++ b/lib/ext/Syncroton/Backend/ISyncState.php
@@ -16,29 +16,27 @@
* @package Syncroton
* @subpackage Backend
*/
-interface Syncroton_Backend_ISyncState
+interface Syncroton_Backend_ISyncState extends Syncroton_Backend_IBackend
{
/**
* create new sync state
- *
- * @param Syncroton_Model_ISyncState $_syncState
- * @return Syncroton_Model_ISyncState
+ *
+ * @param Syncroton_Model_IDevice $model
+ * @param boolean $keepPreviousSyncState
*/
- public function create(Syncroton_Model_ISyncState $_syncState);
+ #public function create($model, $keepPreviousSyncState = true);
/**
* always returns the latest syncstate
*
- * @param Syncroton_Model_IDevice|string $_deviceId
- * @param Syncroton_Model_IFolder|string $_folderId
+ * @param Syncroton_Model_IDevice|string $deviceId
+ * @param Syncroton_Model_IFolder|string $folderId
* @return Syncroton_Model_SyncState
*/
- public function getSyncState($_deviceId, $_folderId);
+ public function getSyncState($deviceId, $folderId);
public function resetState($_deviceId, $_type);
- public function update(Syncroton_Model_ISyncState $_syncState);
-
/**
* get array of ids which got send to the client for a given class
*
diff --git a/lib/ext/Syncroton/Backend/Policy.php b/lib/ext/Syncroton/Backend/Policy.php
new file mode 100644
index 0000000..5163359
--- /dev/null
+++ b/lib/ext/Syncroton/Backend/Policy.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * Syncroton
+ *
+ * @package Command
+ * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3
+ * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author Lars Kneschke <l.kneschke at metaways.de>
+ */
+
+/**
+ * class to handle ActiveSync Sync command
+ *
+ * @package Backend
+ */
+
+class Syncroton_Backend_Policy extends Syncroton_Backend_ABackend #implements Syncroton_Backend_IDevice
+{
+ protected $_tableName = 'policy';
+
+ protected $_modelClassName = 'Syncroton_Model_Policy';
+
+ protected $_modelInterfaceName = 'Syncroton_Model_IPolicy';
+}
diff --git a/lib/ext/Syncroton/Backend/SyncState.php b/lib/ext/Syncroton/Backend/SyncState.php
index 078aacc..87dc39c 100644
--- a/lib/ext/Syncroton/Backend/SyncState.php
+++ b/lib/ext/Syncroton/Backend/SyncState.php
@@ -16,46 +16,23 @@
* @package Syncroton
* @subpackage Backend
*/
-class Syncroton_Backend_SyncState implements Syncroton_Backend_ISyncState
+class Syncroton_Backend_SyncState extends Syncroton_Backend_ABackend implements Syncroton_Backend_ISyncState
{
- /**
- * the database adapter
- *
- * @var Zend_Db_Adapter_Abstract
- */
- protected $_db;
-
- protected $_tablePrefix;
-
- public function __construct(Zend_Db_Adapter_Abstract $_db, $_tablePrefix = 'Syncroton_')
- {
- $this->_db = $_db;
- $this->_tablePrefix = $_tablePrefix;
- }
+ protected $_tableName = 'synckey';
+
+ protected $_modelClassName = 'Syncroton_Model_SyncState';
+
+ protected $_modelInterfaceName = 'Syncroton_Model_ISyncState';
/**
- * create new sync state
- *
- * @param Syncroton_Model_ISyncState $_syncState
- * @return Syncroton_Model_SyncState
+ * (non-PHPdoc)
+ * @see Syncroton_Backend_ISyncState::create()
*/
- public function create(Syncroton_Model_ISyncState $_syncState, $_keepPreviousSyncState = true)
+ public function create($model, $keepPreviousSyncState = true)
{
- $id = sha1(mt_rand(). microtime());
- $deviceId = $_syncState->device_id instanceof Syncroton_Model_IDevice ? $_syncState->device_id->id : $_syncState->device_id;
-
- $this->_db->insert($this->_tablePrefix . 'synckey', array(
- 'id' => $id,
- 'device_id' => $deviceId,
- 'type' => $_syncState->type instanceof Syncroton_Model_IFolder ? $_syncState->type->id : $_syncState->type,
- 'counter' => $_syncState->counter,
- 'lastsync' => $_syncState->lastsync->format('Y-m-d H:i:s'),
- 'pendingdata' => isset($_syncState->pendingdata) && is_array($_syncState->pendingdata) ? Zend_Json::encode($_syncState->pendingdata) : null
- ));
-
- $state = $this->get($id);
+ $state = parent::create($model);
- if ($_keepPreviousSyncState !== true) {
+ if ($keepPreviousSyncState !== true) {
// remove all other synckeys
$this->_deleteOtherStates($state);
}
@@ -63,162 +40,140 @@ class Syncroton_Backend_SyncState implements Syncroton_Backend_ISyncState
return $state;
}
- protected function _deleteOtherStates(Syncroton_Model_ISyncState $_state)
+ /**
+ * (non-PHPdoc)
+ * @see Syncroton_Backend_ABackend::_convertModelToArray()
+ */
+ protected function _convertModelToArray($model)
+ {
+ $model = parent::_convertModelToArray($model);
+
+ $model['pendingdata'] = isset($model['pendingdata']) && is_array($model['pendingdata']) ? Zend_Json::encode($model['pendingdata']) : null;
+
+ return $model;
+ }
+
+ /**
+ *
+ * @param Syncroton_Model_ISyncState $state
+ */
+ protected function _deleteOtherStates(Syncroton_Model_ISyncState $state)
{
// remove all other synckeys
$where = array(
- 'device_id = ?' => $_state->device_id,
- 'type = ?' => $_state->type,
- 'counter != ?' => $_state->counter
+ 'device_id = ?' => $state->deviceId,
+ 'type = ?' => $state->type,
+ 'counter != ?' => $state->counter
);
- $this->_db->delete($this->_tablePrefix . 'synckey', $where);
+ $this->_db->delete($this->_tablePrefix . $this->_tableName, $where);
return true;
}
/**
- * @param string $_id
- * @throws Syncroton_Exception_NotFound
- * @return Syncroton_Model_SyncState
+ * (non-PHPdoc)
+ * @see Syncroton_Backend_ABackend::_getObject()
*/
- public function get($_id)
+ protected function _getObject($data)
{
- $select = $this->_db->select()
- ->from($this->_tablePrefix . 'synckey')
- ->where('id = ?', $_id);
-
- $stmt = $this->_db->query($select);
- $state = $stmt->fetchObject('Syncroton_Model_SyncState');
- $stmt = null; # see https://bugs.php.net/bug.php?id=44081
+ $model = parent::_getObject($data);
- if (! $state instanceof Syncroton_Model_ISyncState) {
- throw new Syncroton_Exception_NotFound('id not found');
- }
-
- $this->_convertFields($state);
-
- return $state;
- }
-
- protected function _convertFields(Syncroton_Model_SyncState $state)
- {
- if (!empty($state->lastsync)) {
- $state->lastsync = new DateTime($state->lastsync, new DateTimeZone('utc'));
- }
- if ($state->pendingdata !== NULL) {
- $state->pendingdata = Zend_Json::decode($state->pendingdata);
+ if ($model->pendingdata !== NULL) {
+ $model->pendingdata = Zend_Json::decode($model->pendingdata);
}
+
+ return $model;
}
/**
- * always returns the latest syncstate
- *
- * @param Syncroton_Model_IDevice|string $_deviceId
- * @param Syncroton_Model_IFolder|string $_folderId
- * @return Syncroton_Model_SyncState
+ * (non-PHPdoc)
+ * @see Syncroton_Backend_ISyncState::getSyncState()
*/
- public function getSyncState($_deviceId, $_folderId)
+ public function getSyncState($deviceId, $folderId)
{
- $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
- $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
+ $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId;
+ $folderId = $folderId instanceof Syncroton_Model_IFolder ? $folderId->id : $folderId;
$select = $this->_db->select()
- ->from($this->_tablePrefix . 'synckey')
+ ->from($this->_tablePrefix . $this->_tableName)
->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId)
->where($this->_db->quoteIdentifier('type') . ' = ?', $folderId)
->order('counter DESC')
->limit(1);
- $stmt = $this->_db->query($select);
- $state = $stmt->fetchObject('Syncroton_Model_SyncState');
- $stmt = null; # see https://bugs.php.net/bug.php?id=44081
-
- if (! $state instanceof Syncroton_Model_ISyncState) {
- throw new Syncroton_Exception_NotFound('id not found');
- }
-
- $this->_convertFields($state);
-
- return $state;
+ $stmt = $this->_db->query($select);
+ $data = $stmt->fetch();
+ $stmt = null; # see https://bugs.php.net/bug.php?id=44081
+
+ if ($data === false) {
+ throw new Syncroton_Exception_NotFound('id not found');
+ }
+
+ return $this->_getObject($data);
}
/**
* delete all stored synckeys for given type
*
- * @param Syncroton_Model_IDevice|string $_deviceId
- * @param Syncroton_Model_IFolder|string $_folderId
+ * @param Syncroton_Model_IDevice|string $deviceId
+ * @param Syncroton_Model_IFolder|string $folderId
*/
- public function resetState($_deviceId, $_folderId)
+ public function resetState($deviceId, $folderId)
{
- $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
- $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
+ $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId;
+ $folderId = $folderId instanceof Syncroton_Model_IFolder ? $folderId->id : $folderId;
$where = array(
$this->_db->quoteInto($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId),
$this->_db->quoteInto($this->_db->quoteIdentifier('type') . ' = ?', $folderId)
);
- $this->_db->delete($this->_tablePrefix . 'synckey', $where);
- }
-
- public function update(Syncroton_Model_ISyncState $_syncState)
- {
- $deviceId = $_syncState->device_id instanceof Syncroton_Model_IDevice ? $_syncState->device_id->id : $_syncState->device_id;
-
- $this->_db->update($this->_tablePrefix . 'synckey', array(
- 'counter' => $_syncState->counter,
- 'lastsync' => $_syncState->lastsync->format('Y-m-d H:i:s'),
- 'pendingdata' => isset($_syncState->pendingdata) && is_array($_syncState->pendingdata) ? Zend_Json::encode($_syncState->pendingdata) : null
- ), array(
- 'id = ?' => $_syncState->id
- ));
-
- return $this->get($_syncState->id);
+ $this->_db->delete($this->_tablePrefix . $this->_tableName, $where);
}
/**
* get array of ids which got send to the client for a given class
*
- * @param Syncroton_Model_IDevice|string $_deviceId
- * @param Syncroton_Model_IFolder|string $_folderId
+ * @param Syncroton_Model_IDevice|string $deviceId
+ * @param Syncroton_Model_IFolder|string $folderId
* @return Syncroton_Model_SyncState
*/
- public function validate($_deviceId, $_folderId, $_syncKey)
+ public function validate($deviceId, $folderId, $syncKey)
{
- $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
- $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
+ $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId;
+ $folderId = $folderId instanceof Syncroton_Model_IFolder ? $folderId->id : $folderId;
$select = $this->_db->select()
- ->from($this->_tablePrefix . 'synckey')
+ ->from($this->_tablePrefix . $this->_tableName)
->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId)
- ->where($this->_db->quoteIdentifier('counter') . ' = ?', $_syncKey)
+ ->where($this->_db->quoteIdentifier('counter') . ' = ?', $syncKey)
->where($this->_db->quoteIdentifier('type') . ' = ?', $folderId);
$stmt = $this->_db->query($select);
- $state = $stmt->fetchObject('Syncroton_Model_SyncState');
+ $data = $stmt->fetch();
$stmt = null; # see https://bugs.php.net/bug.php?id=44081
- if (! $state instanceof Syncroton_Model_ISyncState) {
+ if ($data === false) {
return false;
}
- $this->_convertFields($state);
+ $state = $this->_getObject($data);
// check if this was the latest syncKey
$select = $this->_db->select()
- ->from($this->_tablePrefix . 'synckey')
+ ->from($this->_tablePrefix . $this->_tableName)
->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId)
- ->where($this->_db->quoteIdentifier('counter') . ' = ?', $_syncKey + 1)
- ->where($this->_db->quoteIdentifier('type') . ' = ?', $folderId);
+ ->where($this->_db->quoteIdentifier('counter') . ' = ?', $syncKey + 1)
+ ->where($this->_db->quoteIdentifier('type') . ' = ?', $folderId);
$stmt = $this->_db->query($select);
- $moreRecentState = $stmt->fetchObject('Syncroton_Model_SyncState');
+ $moreRecentStateData = $stmt->fetch();
$stmt = null; # see https://bugs.php.net/bug.php?id=44081
// found more recent synckey => the last sync repsone got not received by the client
- if ($moreRecentState instanceof Syncroton_Model_ISyncState) {
+ if ($moreRecentStateData !== false) {
// undelete entries marked as deleted in Syncroton_content table
$this->_db->update($this->_tablePrefix . 'content', array(
'is_deleted' => 0,
diff --git a/lib/ext/Syncroton/Command/FolderCreate.php b/lib/ext/Syncroton/Command/FolderCreate.php
index 47aefcb..1932848 100644
--- a/lib/ext/Syncroton/Command/FolderCreate.php
+++ b/lib/ext/Syncroton/Command/FolderCreate.php
@@ -28,14 +28,10 @@ class Syncroton_Command_FolderCreate extends Syncroton_Command_Wbxml
);
/**
- * synckey sent from client
- *
- * @var string
+ *
+ * @var Syncroton_Model_Folder
*/
- protected $_syncKey;
- protected $_parentId;
- protected $_displayName;
- protected $_type;
+ protected $_folder;
/**
* parse FolderCreate request
@@ -45,29 +41,38 @@ class Syncroton_Command_FolderCreate extends Syncroton_Command_Wbxml
{
$xml = simplexml_import_dom($this->_requestBody);
- $this->_syncKey = (int)$xml->SyncKey;
- $this->_parentId = (string)$xml->ParentId;
- $this->_displayName = (string)$xml->DisplayName;
- $this->_type = (int)$xml->Type;
-
+ $syncKey = (int)$xml->SyncKey;
+
if ($this->_logger instanceof Zend_Log)
- $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " synckey is $this->_syncKey");
+ $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " synckey is $syncKey");
+
+ if (!($this->_syncState = $this->_syncStateBackend->validate($this->_device, 'FolderSync', $syncKey)) instanceof Syncroton_Model_SyncState) {
+
+ $this->_syncStateBackend->resetState($this->_device, 'FolderSync');
+
+ return;
+ }
- switch((int)$xml->Type) {
+ $folder = new Syncroton_Model_Folder($xml);
+
+ if ($this->_logger instanceof Zend_Log)
+ $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " parentId: {$folder->parentId} displayName: {$folder->displayName}");
+
+ switch($folder->type) {
case Syncroton_Command_FolderSync::FOLDERTYPE_CALENDAR_USER_CREATED:
- $this->_class = Syncroton_Data_Factory::CLASS_CALENDAR;
+ $folder->class = Syncroton_Data_Factory::CLASS_CALENDAR;
break;
case Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT_USER_CREATED:
- $this->_class = Syncroton_Data_Factory::CLASS_CONTACTS;
+ $folder->class = Syncroton_Data_Factory::CLASS_CONTACTS;
break;
case Syncroton_Command_FolderSync::FOLDERTYPE_MAIL_USER_CREATED:
- $this->_class = Syncroton_Data_Factory::CLASS_EMAIL;
+ $folder->class = Syncroton_Data_Factory::CLASS_EMAIL;
break;
case Syncroton_Command_FolderSync::FOLDERTYPE_TASK_USER_CREATED:
- $this->_class = Syncroton_Data_Factory::CLASS_TASKS;
+ $folder->class = Syncroton_Data_Factory::CLASS_TASKS;
break;
default:
@@ -75,7 +80,14 @@ class Syncroton_Command_FolderCreate extends Syncroton_Command_Wbxml
break;
}
- $this->_syncState = $this->_syncStateBackend->validate($this->_device, 'FolderSync', $this->_syncKey);
+ $folder->deviceId = $this->_device;
+ $folder->creationTime = $this->_syncTimeStamp;
+
+ $dataController = Syncroton_Data_Factory::factory($folder->class, $this->_device, $this->_syncTimeStamp);
+
+ $this->_folder = $dataController->createFolder($folder);
+
+ $this->_folderBackend->create($this->_folder);
}
/**
@@ -85,34 +97,22 @@ class Syncroton_Command_FolderCreate extends Syncroton_Command_Wbxml
{
$folderCreate = $this->_outputDom->documentElement;
- if($this->_syncState == false) {
+ if (!$this->_syncState instanceof Syncroton_Model_SyncState) {
if ($this->_logger instanceof Zend_Log)
- $this->_logger->info(__METHOD__ . '::' . __LINE__ . " INVALID synckey");
+ $this->_logger->info(__METHOD__ . '::' . __LINE__ . " invalid synckey provided. FolderSync 0 needed.");
$folderCreate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', Syncroton_Command_FolderSync::STATUS_INVALID_SYNC_KEY));
+
} else {
$this->_syncState->counter++;
+ $this->_syncState->lastsync = $this->_syncTimeStamp;
- $dataController = Syncroton_Data_Factory::factory($this->_class, $this->_device, $this->_syncTimeStamp);
-
- $folder = $dataController->createFolder(new Syncroton_Model_Folder(array(
- 'device_id' => $this->_device,
- 'class' => $this->_class,
- 'parentid' => $this->_parentId,
- 'displayname' => $this->_displayName,
- 'type' => $this->_type,
- 'creation_time' => $this->_syncTimeStamp,
- 'lastfiltertype' => null
- )));
+ // store folder in state backend
+ $this->_syncStateBackend->update($this->_syncState);
// create xml output
$folderCreate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', Syncroton_Command_FolderSync::STATUS_SUCCESS));
$folderCreate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'SyncKey', $this->_syncState->counter));
- $folderCreate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'ServerId', $folder->folderid));
-
- // store folder in state backend
- $this->_folderBackend->create($folder);
-
- $this->_syncStateBackend->update($this->_syncState);
+ $folderCreate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'ServerId', $this->_folder->serverId));
}
return $this->_outputDom;
diff --git a/lib/ext/Syncroton/Command/FolderDelete.php b/lib/ext/Syncroton/Command/FolderDelete.php
index e390105..4259ea8 100644
--- a/lib/ext/Syncroton/Command/FolderDelete.php
+++ b/lib/ext/Syncroton/Command/FolderDelete.php
@@ -42,16 +42,22 @@ class Syncroton_Command_FolderDelete extends Syncroton_Command_Wbxml
{
$xml = simplexml_import_dom($this->_requestBody);
- $syncKey = (int)$xml->SyncKey;
- $folderId = (string)$xml->ServerId;
+ $syncKey = (int)$xml->SyncKey;
if ($this->_logger instanceof Zend_Log)
- $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " synckey is $syncKey");
+ $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " synckey is $syncKey");
- $this->_syncState = $this->_syncStateBackend->validate($this->_device, 'FolderSync', $syncKey);
+ if (!($this->_syncState = $this->_syncStateBackend->validate($this->_device, 'FolderSync', $syncKey)) instanceof Syncroton_Model_SyncState) {
+
+ $this->_syncStateBackend->resetState($this->_device, 'FolderSync');
+
+ return;
+ }
+
+ $serverId = (string)$xml->ServerId;
try {
- $this->_folder = $this->_folderBackend->getFolder($this->_device, $folderId);
+ $this->_folder = $this->_folderBackend->getFolder($this->_device, $serverId);
$dataController = Syncroton_Data_Factory::factory($this->_folder->class, $this->_device, $this->_syncTimeStamp);
@@ -73,19 +79,23 @@ class Syncroton_Command_FolderDelete extends Syncroton_Command_Wbxml
{
$folderDelete = $this->_outputDom->documentElement;
- if($this->_syncState == false) {
+ if (!$this->_syncState instanceof Syncroton_Model_SyncState) {
if ($this->_logger instanceof Zend_Log)
- $this->_logger->info(__METHOD__ . '::' . __LINE__ . " INVALID synckey");
+ $this->_logger->info(__METHOD__ . '::' . __LINE__ . " invalid synckey provided. FolderSync 0 needed.");
$folderDelete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', Syncroton_Command_FolderSync::STATUS_INVALID_SYNC_KEY));
+
} else {
if ($this->_folder instanceof Syncroton_Model_IFolder) {
$this->_syncState->counter++;
+ $this->_syncState->lastsync = $this->_syncTimeStamp;
+
+ // store folder in state backend
+ $this->_syncStateBackend->update($this->_syncState);
// create xml output
$folderDelete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', Syncroton_Command_FolderSync::STATUS_SUCCESS));
$folderDelete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'SyncKey', $this->_syncState->counter));
-
- $this->_syncStateBackend->update($this->_syncState);
+
} else {
// create xml output
$folderDelete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', Syncroton_Command_FolderSync::STATUS_FOLDER_NOT_FOUND));
diff --git a/lib/ext/Syncroton/Command/FolderSync.php b/lib/ext/Syncroton/Command/FolderSync.php
index df82ca4..9017798 100644
--- a/lib/ext/Syncroton/Command/FolderSync.php
+++ b/lib/ext/Syncroton/Command/FolderSync.php
@@ -73,21 +73,13 @@ class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml
*/
public function handle()
{
- #if ($this->_statusProvisioning = $this->_checkProvisioningNeeded() !== false) {
- # if (version_compare($this->_device->acsversion, '14.0', '<')) {
- # throw new Syncroton_Exception_ProvisioningNeeded();
- # } else {
- # return;
- # }
- #}
-
$xml = simplexml_import_dom($this->_requestBody);
$syncKey = (int)$xml->SyncKey;
if ($this->_logger instanceof Zend_Log)
$this->_logger->debug(__METHOD__ . '::' . __LINE__ . " synckey is $syncKey");
- if ($syncKey == 0) {
+ if ($syncKey === 0) {
$this->_syncState = new Syncroton_Model_SyncState(array(
'device_id' => $this->_device,
'counter' => 0,
@@ -97,12 +89,12 @@ class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml
// reset state of foldersync
$this->_syncStateBackend->resetState($this->_device, 'FolderSync');
- } else {
- if (($this->_syncState = $this->_syncStateBackend->validate($this->_device, 'FolderSync', $syncKey)) instanceof Syncroton_Model_SyncState) {
- $this->_syncState->lastsync = $this->_syncTimeStamp;
- } else {
- $this->_syncStateBackend->resetState($this->_device, 'FolderSync');
- }
+
+ return;
+ }
+
+ if (!($this->_syncState = $this->_syncStateBackend->validate($this->_device, 'FolderSync', $syncKey)) instanceof Syncroton_Model_SyncState) {
+ $this->_syncStateBackend->resetState($this->_device, 'FolderSync');
}
}
@@ -115,19 +107,10 @@ class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml
{
$folderSync = $this->_outputDom->documentElement;
- // provioning needed?
- #if ($this->_statusProvisioning !== false) {
- # if ($this->_logger instanceof Zend_Log)
- # $this->_logger->info(__METHOD__ . '::' . __LINE__ . " provisiong needed or remote wipe requested");
- # $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', $this->_statusProvisioning));
- #
- # return $this->_outputDom;
- #}
-
// invalid synckey provided
- if($this->_syncState === false) {
+ if (!$this->_syncState instanceof Syncroton_Model_SyncState) {
if ($this->_logger instanceof Zend_Log)
- $this->_logger->info(__METHOD__ . '::' . __LINE__ . " INVALID synckey provided");
+ $this->_logger->info(__METHOD__ . '::' . __LINE__ . " invalid synckey provided. FolderSync 0 needed.");
$folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', self::STATUS_INVALID_SYNC_KEY));
return $this->_outputDom;
@@ -141,7 +124,7 @@ class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml
foreach($this->_classes as $class) {
try {
$dataController = Syncroton_Data_Factory::factory($class, $this->_device, $this->_syncTimeStamp);
- } catch (Zend_Exception $ze) {
+ } catch (Exception $e) {
// backend not defined
if ($this->_logger instanceof Zend_Log)
$this->_logger->info(__METHOD__ . '::' . __LINE__ . " no data backend defined for class: " . $class);
@@ -150,6 +133,7 @@ class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml
// retrieve all folders available in data backend
$serverFolders = $dataController->getAllFolders();
+
// retrieve all folders sent to client
$clientFolders = $this->_folderBackend->getFolderState($this->_device, $class);
@@ -161,24 +145,22 @@ class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml
} else {
$clientFoldersIds = array_keys($clientFolders);
}
-
+
// calculate added entries
$serverDiff = array_diff($serverFoldersIds, $clientFoldersIds);
foreach($serverDiff as $serverFolderId) {
+ // have we created a folderObject in syncroton_folder before?
if (isset($clientFolders[$serverFolderId])) {
- $adds[] = $clientFolders[$serverFolderId];
+ $add = $clientFolders[$serverFolderId];
} else {
- $adds[] = new Syncroton_Model_Folder(array(
- 'device_id' => $this->_device,
- 'class' => $class,
- 'folderid' => $serverFolders[$serverFolderId]->folderid,
- 'parentid' => $serverFolders[$serverFolderId]->parentid,
- 'displayname' => $serverFolders[$serverFolderId]->displayname,
- 'type' => $serverFolders[$serverFolderId]->type,
- 'creation_time' => $this->_syncTimeStamp,
- 'lastfiltertype' => null
- ));
+ $add = $serverFolders[$serverFolderId];
+ $add->creationTime = $this->_syncTimeStamp;
+ $add->deviceId = $this->_device;
+ unset($add->id);
}
+ $add->class = $class;
+
+ $adds[] = $add;
}
// calculate deleted entries
@@ -191,6 +173,7 @@ class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml
$count = count($adds) + /*count($changes) + */count($deletes);
if($count > 0) {
$this->_syncState->counter++;
+ $this->_syncState->lastsync = $this->_syncTimeStamp;
}
// create xml output
@@ -200,17 +183,10 @@ class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml
$changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Count', $count));
foreach($adds as $folder) {
-
$add = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Add'));
- $add->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'ServerId', $folder->folderid));
- $add->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'ParentId', $folder->parentid));
-
- $displayName = $this->_outputDom->createElementNS('uri:FolderHierarchy', 'DisplayName');
- $displayName->appendChild($this->_outputDom->createTextNode($folder->displayname));
- $add->appendChild($displayName);
-
- $add->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Type', $folder->type));
+ $folder->appendXML($add);
+
// store folder in backend
if (empty($folder->id)) {
$this->_folderBackend->create($folder);
@@ -219,7 +195,7 @@ class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml
foreach($deletes as $folder) {
$delete = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Delete'));
- $delete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'ServerId', $folder->folderid));
+ $delete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'ServerId', $folder->serverId));
$this->_folderBackend->delete($folder);
}
diff --git a/lib/ext/Syncroton/Command/FolderUpdate.php b/lib/ext/Syncroton/Command/FolderUpdate.php
index 5089bd7..d219ede 100644
--- a/lib/ext/Syncroton/Command/FolderUpdate.php
+++ b/lib/ext/Syncroton/Command/FolderUpdate.php
@@ -20,17 +20,11 @@ class Syncroton_Command_FolderUpdate extends Syncroton_Command_Wbxml
protected $_defaultNameSpace = 'uri:FolderHierarchy';
protected $_documentElement = 'FolderUpdate';
- protected $_classes = array('Contacts', 'Tasks', 'Email');
-
/**
- * synckey sent from client
- *
- * @var string
+ *
+ * @var Syncroton_Model_Folder
*/
- protected $_syncKey;
- protected $_parentId;
- protected $_displayName;
- protected $_serverId;
+ protected $_folderUpdate;
/**
* parse FolderUpdate request
@@ -40,23 +34,34 @@ class Syncroton_Command_FolderUpdate extends Syncroton_Command_Wbxml
{
$xml = simplexml_import_dom($this->_requestBody);
- $this->_syncKey = (int)$xml->SyncKey;
- $this->_serverId = (string)$xml->ServerId;
+ $syncKey = (int)$xml->SyncKey;
if ($this->_logger instanceof Zend_Log)
- $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " synckey is $this->_syncKey parentId $this->_parentId name $this->_displayName");
+ $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " synckey is $syncKey");
- $this->_syncState = $this->_syncStateBackend->validate($this->_device, 'FolderSync', $this->_syncKey);
+ if (!($this->_syncState = $this->_syncStateBackend->validate($this->_device, 'FolderSync', $syncKey)) instanceof Syncroton_Model_SyncState) {
+
+ $this->_syncStateBackend->resetState($this->_device, 'FolderSync');
+
+ return;
+ }
+
+ $folderUpdate = new Syncroton_Model_Folder($xml);
+
+ if ($this->_logger instanceof Zend_Log)
+ $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " parentId: {$folderUpdate->parentId} displayName: {$folderUpdate->displayName}");
try {
- $folder = $this->_folderBackend->getFolder($this->_device, $this->_serverId);
+ $folder = $this->_folderBackend->getFolder($this->_device, $folderUpdate->serverId);
- $folder->displayname = (string)$xml->DisplayName;
- $folder->parentid = (string)$xml->ParentId;
+ $folder->displayName = $folderUpdate->displayName;
+ $folder->parentId = $folderUpdate->parentId;
$dataController = Syncroton_Data_Factory::factory($folder->class, $this->_device, $this->_syncTimeStamp);
+ // update folder in data backend
$dataController->updateFolder($folder);
+ // update folder status in Syncroton backend
$this->_folderBackend->update($folder);
} catch (Syncroton_Exception_NotFound $senf) {
@@ -74,18 +79,21 @@ class Syncroton_Command_FolderUpdate extends Syncroton_Command_Wbxml
{
$folderUpdate = $this->_outputDom->documentElement;
- if($this->_syncState == false) {
+ if (!$this->_syncState instanceof Syncroton_Model_SyncState) {
if ($this->_logger instanceof Zend_Log)
- $this->_logger->info(__METHOD__ . '::' . __LINE__ . " INVALID synckey");
- $folderUpdate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', Syncroton_Command_FolderSync::STATUS_INVALID_SYNC_KEY));
+ $this->_logger->info(__METHOD__ . '::' . __LINE__ . " invalid synckey provided. FolderSync 0 needed.");
+ $folderUpdate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', Syncroton_Command_FolderSync::STATUS_INVALID_SYNC_KEY));
+
} else {
$this->_syncState->counter++;
+ $this->_syncState->lastsync = $this->_syncTimeStamp;
+ // store folder in state backend
+ $this->_syncStateBackend->update($this->_syncState);
+
// create xml output
$folderUpdate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', Syncroton_Command_FolderSync::STATUS_SUCCESS));
$folderUpdate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'SyncKey', $this->_syncState->counter));
-
- $this->_syncStateBackend->update($this->_syncState);
}
return $this->_outputDom;
diff --git a/lib/ext/Syncroton/Command/ItemOperations.php b/lib/ext/Syncroton/Command/ItemOperations.php
index 12fd0ea..7692970 100644
--- a/lib/ext/Syncroton/Command/ItemOperations.php
+++ b/lib/ext/Syncroton/Command/ItemOperations.php
@@ -127,10 +127,9 @@ class Syncroton_Command_ItemOperations extends Syncroton_Command_Wbxml
$fetchTag->appendChild($properties);
}
} catch (Syncroton_Exception_NotFound $e) {
- //echo __LINE__;
$response->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Status', Syncroton_Command_ItemOperations::STATUS_ITEM_FAILED_CONVERSION));
} catch (Exception $e) {
- //echo __LINE__; echo $e->getMessage(); echo $e->getTraceAsString();
+ //echo __LINE__; echo $e->getMessage(); echo $e->getTraceAsString();
$response->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Status', Syncroton_Command_ItemOperations::STATUS_SERVER_ERROR));
}
}
diff --git a/lib/ext/Syncroton/Command/Options.php b/lib/ext/Syncroton/Command/Options.php
index cbb68c1..35a98e7 100644
--- a/lib/ext/Syncroton/Command/Options.php
+++ b/lib/ext/Syncroton/Command/Options.php
@@ -24,15 +24,9 @@ class Syncroton_Command_Options
*/
public function getResponse()
{
- // same header like Exchange 2003
- #header("MS-Server-ActiveSync: 8.3");
- #header("MS-ASProtocolVersions: 2.5,12.0");
- #header("MS-ASProtocolCommands: CreateCollection,DeleteCollection,FolderCreate,FolderDelete,FolderSync,FolderUpdate,GetAttachment,GetItemEstimate,ItemOperations,MeetingResponse,MoveCollection,MoveItems,Provision,ResolveRecipients,Ping,SendMail,Search,Settings,SmartForward,SmartReply,Sync");
-
// same header like Exchange 2xxx???
header('MS-Server-ActiveSync: 14.00.0536.000');
- header("MS-ASProtocolVersions: 2.5,12.0,12.1,14.0,14.1");
+ header("MS-ASProtocolVersions: 12.0,12.1,14.0,14.1");
header("MS-ASProtocolCommands: CreateCollection,DeleteCollection,FolderCreate,FolderDelete,FolderSync,FolderUpdate,GetAttachment,GetHierarchy,GetItemEstimate,ItemOperations,MeetingResponse,MoveCollection,MoveItems,Provision,ResolveRecipients,Ping,SendMail,Search,Settings,SmartForward,SmartReply,Sync,ValidateCert");
- header('MS-ASProtocolRevisions: 12.1r1');
}
}
diff --git a/lib/ext/Syncroton/Command/Ping.php b/lib/ext/Syncroton/Command/Ping.php
index a2c88b6..e0c101e 100644
--- a/lib/ext/Syncroton/Command/Ping.php
+++ b/lib/ext/Syncroton/Command/Ping.php
@@ -55,7 +55,7 @@ class Syncroton_Command_Ping extends Syncroton_Command_Wbxml
{
$intervalStart = time();
$status = self::STATUS_NO_CHANGES_FOUND;
-
+
// the client does not send a wbxml document, if the Ping parameters did not change compared with the last request
if($this->_requestBody instanceof DOMDocument) {
$xml = simplexml_import_dom($this->_requestBody);
@@ -113,7 +113,7 @@ class Syncroton_Command_Ping extends Syncroton_Command_Wbxml
if ($this->_logger instanceof Zend_Log)
$this->_logger->debug(__METHOD__ . '::' . __LINE__ . " " . $e->getMessage());
if ($this->_logger instanceof Zend_Log)
- $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' syncstate not found. enforce sync for folder: ' . $folder->folderid);
+ $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' syncstate not found. enforce sync for folder: ' . $folder->serverId);
$foundChanges = true;
}
@@ -151,9 +151,9 @@ class Syncroton_Command_Ping extends Syncroton_Command_Wbxml
$folders = $ping->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Folders'));
foreach($this->_foldersWithChanges as $changedFolder) {
- $folder = $folders->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Folder', $changedFolder->folderid));
+ $folder = $folders->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Folder', $changedFolder->serverId));
if ($this->_logger instanceof Zend_Log)
- $this->_logger->info(__METHOD__ . '::' . __LINE__ . " DeviceId: " . $this->_device->deviceid . " changes in folder: " . $changedFolder->folderid);
+ $this->_logger->info(__METHOD__ . '::' . __LINE__ . " DeviceId: " . $this->_device->deviceid . " changes in folder: " . $changedFolder->serverId);
}
}
}
diff --git a/lib/ext/Syncroton/Command/Provision.php b/lib/ext/Syncroton/Command/Provision.php
index 7cf53a2..b4ddf41 100644
--- a/lib/ext/Syncroton/Command/Provision.php
+++ b/lib/ext/Syncroton/Command/Provision.php
@@ -35,6 +35,7 @@ class Syncroton_Command_Provision extends Syncroton_Command_Wbxml
protected $_policyType;
protected $_sendPolicyKey;
+ protected $_deviceInformationSet = false;
/**
* process the XML file and add, change, delete or fetches data
@@ -53,6 +54,12 @@ class Syncroton_Command_Provision extends Syncroton_Command_Wbxml
$this->_device = $this->_deviceBackend->update($this->_device);
}
+ // try to fetch element from Settings namespace
+ $settings = $xml->children('uri:Settings');
+ if (isset($settings->DeviceInformation) && isset($settings->DeviceInformation->Set)) {
+ // @todo update device informations
+ $this->_deviceInformationSet = true;
+ }
}
/**
@@ -61,6 +68,8 @@ class Syncroton_Command_Provision extends Syncroton_Command_Wbxml
*/
public function getResponse()
{
+ $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Settings', 'uri:Settings');
+
// should we wipe the device
if ($this->_device->remotewipe >= self::REMOTEWIPE_REQUESTED) {
$this->_sendRemoteWipe();
@@ -70,7 +79,7 @@ class Syncroton_Command_Provision extends Syncroton_Command_Wbxml
if($this->_sendPolicyKey === NULL) {
$this->_sendPolicy();
- } else {
+ } elseif ($this->_sendPolicyKey == $this->_device->policykey) {
$this->_acknowledgePolicy();
}
}
@@ -96,49 +105,28 @@ class Syncroton_Command_Provision extends Syncroton_Command_Wbxml
if ($this->_logger instanceof Zend_Log)
$this->_logger->info(__METHOD__ . '::' . __LINE__ . ' send policy to device');
- $policyData = '<wap-provisioningdoc>
- <characteristic type="SecurityPolicy">
- <parm name="4131" value="0"/>
- <parm name="4133" value="0"/>
- </characteristic>
- <characteristic type="Registry">
- <characteristic type="HKLM\Comm\Security\Policy\LASSD\AE\{50C13377-C66D-400C-889E-C316FC4AB374}">
- <parm name="AEFrequencyType" value="1"/>
- <parm name="AEFrequencyValue" value="3"/>
- </characteristic>
- <characteristic type="HKLM\Comm\Security\Policy\LASSD">
- <parm name="DeviceWipeThreshold" value="6"/>
- </characteristic>
- <characteristic type="HKLM\Comm\Security\Policy\LASSD">
- <parm name="CodewordFrequency" value="3"/>
- </characteristic>
- <characteristic type="HKLM\Comm\Security\Policy\LASSD\LAP\lap_pw">
- <parm name="MinimumPasswordLength" value="5"/>
- </characteristic>
- <characteristic type="HKLM\Comm\Security\Policy\LASSD\LAP\lap_pw">
- <parm name="PasswordComplexity" value="2"/>
- </characteristic>
- </characteristic>
- </wap-provisioningdoc>';
-
$this->_device->policykey = $this->generatePolicyKey();
$provision = $sync = $this->_outputDom->documentElement;
+ if ($this->_deviceInformationSet === true) {
+ $deviceInformation = $provision->appendChild($this->_outputDom->createElementNS('uri:Settings', 'DeviceInformation'));
+ $deviceInformation->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Status', 1));
+ }
$provision->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Status', 1));
+
$policies = $provision->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Policies'));
$policy = $policies->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Policy'));
$policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'PolicyType', $this->_policyType));
$policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Status', 1));
$policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'PolicyKey', $this->_device->policykey));
if ($this->_policyType == self::POLICYTYPE_XML) {
- $data = $policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Data', $policyData));
+ $data = $policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Data'));
} else {
$data = $policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Data'));
$easProvisionDoc = $data->appendChild($this->_outputDom->createElementNS('uri:Provision', 'EASProvisionDoc'));
- $easProvisionDoc->appendChild($this->_outputDom->createElementNS('uri:Provision', 'DevicePasswordEnabled', 1));
- #$easProvisionDoc->appendChild($this->_outputDom->createElementNS('uri:Provision', 'MinDevicePasswordLength', 4));
- #$easProvisionDoc->appendChild($this->_outputDom->createElementNS('uri:Provision', 'MaxDevicePasswordFailedAttempts', 4));
- #$easProvisionDoc->appendChild($this->_outputDom->createElementNS('uri:Provision', 'MaxInactivityTimeDeviceLock', 60));
+ $this->_policyBackend
+ ->get($this->_device->policyId)
+ ->appendXML($easProvisionDoc);
}
$this->_deviceBackend->update($this->_device);
@@ -162,7 +150,7 @@ class Syncroton_Command_Provision extends Syncroton_Command_Wbxml
if ($this->_logger instanceof Zend_Log)
$this->_logger->info(__METHOD__ . '::' . __LINE__ . ' acknowledge policy');
- $this->_device->policykey = $this->generatePolicyKey();
+ $policykey = $this->_policyBackend->get($this->_device->policyId)->policyKey;
$provision = $sync = $this->_outputDom->documentElement;
$provision->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Status', 1));
@@ -170,15 +158,17 @@ class Syncroton_Command_Provision extends Syncroton_Command_Wbxml
$policy = $policies->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Policy'));
$policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'PolicyType', $this->_policyType));
$policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Status', 1));
- $policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'PolicyKey', $this->_device->policykey));
+ $policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'PolicyKey', $policykey));
+ $this->_device->policykey = null;
$this->_deviceBackend->update($this->_device);
}
-
+
+ /**
+ * generate a random string used as PolicyKey
+ */
public static function generatePolicyKey()
{
- $policyKey = mt_rand(1, mt_getrandmax());
-
- return $policyKey;
+ return sha1(mt_rand(). microtime());
}
}
diff --git a/lib/ext/Syncroton/Command/Search.php b/lib/ext/Syncroton/Command/Search.php
index 4f5f667..7febe29 100644
--- a/lib/ext/Syncroton/Command/Search.php
+++ b/lib/ext/Syncroton/Command/Search.php
@@ -50,51 +50,52 @@ class Syncroton_Command_Search extends Syncroton_Command_Wbxml
*/
public function getResponse()
{
+ $dataController = Syncroton_Data_Factory::factory($this->_store->name, $this->_device, new DateTime());
+
+ if (! $dataController instanceof Syncroton_Data_IDataSearch) {
+ throw new RuntimeException('class must be instanceof Syncroton_Data_IDataSearch');
+ }
+
$storeResponse = new Syncroton_Model_StoreResponse(array(
'Status' => self::STATUS_SUCCESS,
));
+
+ try {
+ $options = $this->_store->options;
+
+ // Search
+ $results = $dataController->search($this->_store->query, $options);
+
+ // Calculate requested range
+ $start = $options['range'][0];
+ $limit = $options['range'][1] + 1;
+ $total = count($results);
+ $storeResponse->Total = $total;
+
+ if ($total) {
+ if ($start > $total) {
+ $start = $total;
+ }
+ if ($limit > $total) {
+ $limit = max($start+1, $total);
+ }
- if ($this->_store->name == Syncroton_Data_Factory::STORE_GAL || $this->_store->name == Syncroton_Data_Factory::STORE_EMAIL) {
- $timestamp = new DateTime();
- $dataController = Syncroton_Data_Factory::factory($this->_store->name, $this->_device, $timestamp);
-
- try {
- $options = $this->_store->options;
- // Search
- $results = $dataController->search($this->_store->query, $options);
-
- // Calculate requested range
- $start = $options['range'][0];
- $limit = $options['range'][1] + 1;
- $total = count($results);
- $storeResponse->Total = $total;
-
- if ($total) {
- if ($start > $total) {
- $start = $total;
- }
- if ($limit > $total) {
- $limit = max($start+1, $total);
- }
-
- if ($start > 0 || $limit < $total) {
- $results = array_slice($results, $start, $limit-$start);
- }
-
- $storeResponse->Range = array($start, $start + count($results) - 1);
+ if ($start > 0 || $limit < $total) {
+ $results = array_slice($results, $start, $limit-$start);
}
- foreach ($results as $result) {
- if (empty($result->Properties)) {
- $result->Properties = $dataController->getSearchEntry($result->LongId, $this->_store->options);
- }
+ $storeResponse->Range = array($start, $start + count($results) - 1);
+ }
- $storeResponse->Result[] = $result;
+ foreach ($results as $result) {
+ if (empty($result->Properties)) {
+ $result->Properties = $dataController->getSearchEntry($result->LongId, $this->_store->options);
}
+
+ $storeResponse->Result[] = $result;
}
- catch (Exception $e) {
- $storeResponse->Status = self::STATUS_SERVER_ERROR;
- }
+ } catch (Exception $e) {
+ $storeResponse->Status = self::STATUS_SERVER_ERROR;
}
$search = $this->_outputDom->documentElement;
diff --git a/lib/ext/Syncroton/Command/SendMail.php b/lib/ext/Syncroton/Command/SendMail.php
index 768eda4..773e27f 100644
--- a/lib/ext/Syncroton/Command/SendMail.php
+++ b/lib/ext/Syncroton/Command/SendMail.php
@@ -21,9 +21,8 @@ class Syncroton_Command_SendMail extends Syncroton_Command_Wbxml
protected $_documentElement = 'Sendmail';
protected $_saveInSent;
- protected $_itemId;
- protected $_collectionId;
- protected $_mime;
+ protected $_source;
+ protected $_replaceMime = false;
/**
* process the XML file and add, change, delete or fetches data
@@ -34,20 +33,28 @@ class Syncroton_Command_SendMail extends Syncroton_Command_Wbxml
{
if ($this->_requestParameters['contentType'] == 'message/rfc822') {
$this->_mime = $this->_requestBody;
- $this->_saveInSent = $this->_requestParameters['SaveInSent'] == 'T';
+ $this->_saveInSent = $this->_requestParameters['saveInSent'] == 'T';
- $this->_collectionId = $this->_requestParameters['CollectionId'];
- $this->_itemId = $this->_requestParameters['ItemId'];
+ $this->_collectionId = $this->_requestParameters['collectionId'];
+ $this->_itemId = $this->_requestParameters['itemId'];
} else {
$xml = simplexml_import_dom($this->_requestBody);
$this->_mime = (string) $xml->Mime;
$this->_saveInSent = isset($xml->SaveInSentItems);
+ $this->_replaceMime = isset($xml->ReplaceMime);
if (isset ($xml->Source)) {
- $this->_collectionId = (string)$xml->Source->FolderId;
- $this->_itemId = (string)$xml->Source->ItemId;
+ if ($xml->Source->LongId) {
+ $this->_source = $xml->Source->LongId;
+ } else {
+ $this->_source = array(
+ 'collectionId' => (string)$xml->Source->FolderId,
+ 'itemId' => (string)$xml->Source->ItemId,
+ 'instanceId' => isset($xml->Source->InstanceId) ? (string)$xml->Source->InstanceId : null
+ );
+ }
}
}
diff --git a/lib/ext/Syncroton/Command/SmartForward.php b/lib/ext/Syncroton/Command/SmartForward.php
index 3ee31e7..e5ce2d1 100644
--- a/lib/ext/Syncroton/Command/SmartForward.php
+++ b/lib/ext/Syncroton/Command/SmartForward.php
@@ -28,6 +28,6 @@ class Syncroton_Command_SmartForward extends Syncroton_Command_SmartReply
{
$dataController = Syncroton_Data_Factory::factory(Syncroton_Data_Factory::CLASS_EMAIL, $this->_device, $this->_syncTimeStamp);
- $dataController->forwardEmail($this->_collectionId, $this->_itemId, $this->_mime, $this->_saveInSent);
+ $dataController->forwardEmail($this->_source, $this->_mime, $this->_saveInSent, $this->_replaceMime);
}
}
diff --git a/lib/ext/Syncroton/Command/SmartReply.php b/lib/ext/Syncroton/Command/SmartReply.php
index 0f03341..f17d16d 100644
--- a/lib/ext/Syncroton/Command/SmartReply.php
+++ b/lib/ext/Syncroton/Command/SmartReply.php
@@ -29,6 +29,6 @@ class Syncroton_Command_SmartReply extends Syncroton_Command_SendMail
{
$dataController = Syncroton_Data_Factory::factory(Syncroton_Data_Factory::CLASS_EMAIL, $this->_device, $this->_syncTimeStamp);
- $dataController->replyEmail($this->_collectionId, $this->_itemId, $this->_mime, $this->_saveInSent);
+ $dataController->replyEmail($this->_source, $this->_mime, $this->_saveInSent, $this->_replaceMime);
}
}
diff --git a/lib/ext/Syncroton/Command/Sync.php b/lib/ext/Syncroton/Command/Sync.php
index 426b739..e9fead9 100644
--- a/lib/ext/Syncroton/Command/Sync.php
+++ b/lib/ext/Syncroton/Command/Sync.php
@@ -84,11 +84,11 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
protected $_modifications = array();
/**
- * total count of items in all collections
+ * the global WindowSize
*
* @var integer
*/
- protected $_totalCount;
+ protected $_globalWindowSize;
/**
* there are more entries than WindowSize available
@@ -108,17 +108,11 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
*/
public function handle()
{
- #if ($this->_statusProvisioning = $this->_checkProvisioningNeeded() !== false) {
- # if (version_compare($this->_device->acsversion, '14.0', '<')) {
- # throw new Syncroton_Exception_ProvisioningNeeded();
- # } else {
- # return;
- # }
- #}
-
// input xml
$xml = simplexml_import_dom($this->_requestBody);
+ $this->_globalWindowSize = isset($xml->WindowSize) ? (int)$xml->WindowSize : 100;
+
foreach ($xml->Collections->Collection as $xmlCollection) {
$collectionData = new Syncroton_Model_SyncCollection($xmlCollection);
@@ -134,8 +128,8 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
// to avoid a syncloop for the iPhone
if ($collectionData->syncKey > 0) {
$collectionData->folder = new Syncroton_Model_Folder(array(
- 'device_id' => $this->_device,
- 'folderid' => $collectionData->collectionId
+ 'deviceId' => $this->_device,
+ 'serverId' => $collectionData->collectionId
));
}
@@ -364,18 +358,14 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
{
$sync = $this->_outputDom->documentElement;
- // provioning needed?
- #if ($this->_statusProvisioning !== false) {
- # if ($this->_logger instanceof Zend_Log)
- # $this->_logger->info(__METHOD__ . '::' . __LINE__ . " provisiong needed or remote wipe requested");
- # $sync->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Status', $this->_statusProvisioning));
- #
- # return $this->_outputDom;
- #}
-
$collections = $sync->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Collections'));
+ $totalChanges = 0;
+
foreach($this->_collections as $collectionData) {
+ $moreAvailable = false;
+ $collectionChanges = 0;
+
// invalid collectionid provided
if (! ($collectionData->folder instanceof Syncroton_Model_IFolder)) {
$collection = $collections->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Collection'));
@@ -416,8 +406,6 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
'deleted' => array(),
);
- $moreAvailable = false;
-
if($collectionData->getChanges === true) {
// continue sync session?
if(is_array($collectionData->syncState->pendingdata)) {
@@ -550,21 +538,15 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
$collection->appendChild($responses);
}
- if ((count($serverModifications['added']) + count($serverModifications['changed']) + count($serverModifications['deleted'])) > $collectionData->windowSize ) {
- $moreAvailable = true;
- $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'MoreAvailable'));
- }
-
$commands = $this->_outputDom->createElementNS('uri:AirSync', 'Commands');
-
/**
* process entries added on server side
*/
$newContentStates = array();
foreach($serverModifications['added'] as $id => $serverId) {
- if($this->_totalCount === $collectionData->windowSize) {
+ if($collectionChanges === $collectionData->windowSize || $totalChanges + $collectionChanges === $this->_globalWindowSize) {
break;
}
@@ -600,7 +582,7 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
$commands->appendChild($add);
- $this->_totalCount++;
+ $collectionChanges++;
} catch (Exception $e) {
if ($this->_logger instanceof Zend_Log)
$this->_logger->warn(__METHOD__ . '::' . __LINE__ . " unable to convert entry to xml: " . $e->getMessage());
@@ -621,10 +603,10 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
* process entries changed on server side
*/
foreach($serverModifications['changed'] as $id => $serverId) {
- if($this->_totalCount === $collectionData->windowSize) {
+ if($collectionChanges === $collectionData->windowSize || $totalChanges + $collectionChanges === $this->_globalWindowSize) {
break;
}
-
+
try {
$change = $this->_outputDom->createElementNS('uri:AirSync', 'Change');
$change->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ServerId', $serverId));
@@ -638,7 +620,7 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
$commands->appendChild($change);
- $this->_totalCount++;
+ $collectionChanges++;
} catch (Exception $e) {
if ($this->_logger instanceof Zend_Log)
$this->_logger->warn(__METHOD__ . '::' . __LINE__ . " unable to convert entry to xml: " . $e->getMessage());
@@ -653,10 +635,10 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
$deletedContentStates = array();
foreach($serverModifications['deleted'] as $id => $serverId) {
- if($this->_totalCount === $collectionData->windowSize) {
+ if($collectionChanges === $collectionData->windowSize || $totalChanges + $collectionChanges === $this->_globalWindowSize) {
break;
}
-
+
try {
// check if we have sent this entry to the phone
$state = $this->_contentStateBackend->getContentState($this->_device, $collectionData->folder, $serverId);
@@ -668,21 +650,30 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
$commands->appendChild($delete);
- $this->_totalCount++;
+ $collectionChanges++;
} catch (Exception $e) {
if ($this->_logger instanceof Zend_Log)
$this->_logger->warn(__METHOD__ . '::' . __LINE__ . " unable to convert entry to xml: " . $e->getMessage());
}
- unset($serverModifications['deleted'][$id]);
+ unset($serverModifications['deleted'][$id]);
}
if ($commands->hasChildNodes() === true) {
+
+ $countOfPendingChanges = (count($serverModifications['added']) + count($serverModifications['changed']) + count($serverModifications['deleted']));
+ if ($countOfPendingChanges > 0) {
+ $moreAvailable = true;
+ $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'MoreAvailable'));
+ }
+
$collection->appendChild($commands);
}
+ $totalChanges += $collectionChanges;
+
if ($this->_logger instanceof Zend_Log)
- $this->_logger->info(__METHOD__ . '::' . __LINE__ . " new synckey is ". $collectionData->syncState->counter);
+ $this->_logger->info(__METHOD__ . '::' . __LINE__ . " new synckey is ". $collectionData->syncState->counter);
}
if (isset($collectionData->syncState) && $collectionData->syncState instanceof Syncroton_Model_ISyncState &&
diff --git a/lib/ext/Syncroton/Command/Wbxml.php b/lib/ext/Syncroton/Command/Wbxml.php
index 0b69857..537900a 100644
--- a/lib/ext/Syncroton/Command/Wbxml.php
+++ b/lib/ext/Syncroton/Command/Wbxml.php
@@ -50,6 +50,12 @@ abstract class Syncroton_Command_Wbxml implements Syncroton_Command_ICommand
protected $_contentStateBackend;
/**
+ *
+ * @var Syncroton_Backend_IPolicy
+ */
+ protected $_policyBackend;
+
+ /**
* the domDocument containing the xml response from the server
*
* @var DOMDocument
@@ -129,24 +135,11 @@ abstract class Syncroton_Command_Wbxml implements Syncroton_Command_ICommand
$this->_folderBackend = Syncroton_Registry::getFolderBackend();
$this->_syncStateBackend = Syncroton_Registry::getSyncStateBackend();
$this->_contentStateBackend = Syncroton_Registry::getContentStateBackend();
+ $this->_policyBackend = Syncroton_Registry::getPolicyBackend();
if (Syncroton_Registry::isRegistered('loggerBackend')) {
$this->_logger = Syncroton_Registry::get('loggerBackend');
}
- if ($this->_skipValidatePolicyKey !== true && $this->_policyKey === null) {
- #throw new Syncroton_Exception_PolicyKeyMissing();
- }
-
- if ($this->_skipValidatePolicyKey !== true && ($this->_policyKey === 0 || $this->_device->policykey != $this->_policyKey)) {
- #throw new Syncroton_Exception_ProvisioningNeeded();
- }
-
- // should we wipe the mobile phone?
- if ($this->_skipValidatePolicyKey !== true && !empty($this->_policyKey) && $this->_device->remotewipe >= Syncroton_Command_Provision::REMOTEWIPE_REQUESTED) {
- throw new Syncroton_Exception_ProvisioningNeeded();
- }
-
-
$this->_syncTimeStamp = new DateTime(null, new DateTimeZone('UTC'));
if ($this->_logger instanceof Zend_Log)
@@ -163,5 +156,33 @@ abstract class Syncroton_Command_Wbxml implements Syncroton_Command_ICommand
$this->_outputDom->formatOutput = false;
$this->_outputDom->encoding = 'utf-8';
- }
+ if ($this->_skipValidatePolicyKey != true) {
+ if (!empty($this->_device->policyId)) {
+ if ($this->_policyKey === null) {
+ throw new Syncroton_Exception_PolicyKeyMissing();
+ }
+
+ $policy = $this->_policyBackend->get($this->_device->policyId);
+
+ if($policy->policyKey != $this->_policyKey) {
+ $this->_outputDom->documentElement->appendChild($this->_outputDom->createElementNS($this->_defaultNameSpace, 'Status', 142));
+
+ $sepn = new Syncroton_Exception_ProvisioningNeeded();
+ $sepn->domDocument = $this->_outputDom;
+
+ throw $sepn;
+ }
+
+ // should we wipe the mobile phone?
+ if ($this->_device->remotewipe >= Syncroton_Command_Provision::REMOTEWIPE_REQUESTED) {
+ $this->_outputDom->documentElement->appendChild($this->_outputDom->createElementNS($this->_defaultNameSpace, 'Status', 140));
+
+ $sepn = new Syncroton_Exception_ProvisioningNeeded();
+ $sepn->domDocument = $this->_outputDom;
+
+ throw $sepn;
+ }
+ }
+ }
+ }
}
diff --git a/lib/ext/Syncroton/Data/AData.php b/lib/ext/Syncroton/Data/AData.php
index 8a9b3b6..4e02ef5 100644
--- a/lib/ext/Syncroton/Data/AData.php
+++ b/lib/ext/Syncroton/Data/AData.php
@@ -47,11 +47,11 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
$folder->id = sha1(mt_rand(). microtime());
// normaly generated on server backend
- $folder->folderid = sha1(mt_rand(). microtime());
+ $folder->serverId = sha1(mt_rand(). microtime());
- Syncroton_Data_AData::$folders[get_class($this)][$folder->folderid] = $folder;
+ Syncroton_Data_AData::$folders[get_class($this)][$folder->serverId] = $folder;
- return Syncroton_Data_AData::$folders[get_class($this)][$folder->folderid];
+ return Syncroton_Data_AData::$folders[get_class($this)][$folder->serverId];
}
public function createEntry($_folderId, Syncroton_Model_IEntry $_entry)
@@ -72,7 +72,7 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
public function deleteEntry($_folderId, $_serverId, $_collectionData)
{
- #$folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->folderid : $_folderId;
+ #$folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->serverId : $_folderId;
$result = $this->_db->delete($this->_tablePrefix . 'data', array('id = ?' => $_serverId));
@@ -83,7 +83,7 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
public function deleteFolder($_folderId)
{
- $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->folderid : $_folderId;
+ $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->serverId : $_folderId;
unset(Syncroton_Data_AData::$folders[get_class($this)][$folderId]);
unset(Syncroton_Data_AData::$entries[get_class($this)][$folderId]);
@@ -129,11 +129,11 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
public function getCountOfChanges(Syncroton_Backend_IContent $contentBackend, Syncroton_Model_IFolder $folder, Syncroton_Model_ISyncState $syncState)
{
$allClientEntries = $contentBackend->getFolderState($this->_device, $folder);
- $allServerEntries = $this->getServerEntries($folder->folderid, $folder->lastfiltertype);
+ $allServerEntries = $this->getServerEntries($folder->serverId, $folder->lastfiltertype);
$addedEntries = array_diff($allServerEntries, $allClientEntries);
$deletedEntries = array_diff($allClientEntries, $allServerEntries);
- $changedEntries = $this->getChangedEntries($folder->folderid, $syncState->lastsync);
+ $changedEntries = $this->getChangedEntries($folder->serverId, $syncState->lastsync);
return count($addedEntries) + count($deletedEntries) + count($changedEntries);
}
@@ -161,14 +161,6 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
}
return unserialize($entry);
-
- #if (!isset(Syncroton_Data_AData::$entries[get_class($this)][$collection->collectionId][$serverId])) {
- # throw new OutOfBoundsException("entry $serverId not found in folder {$collection->collectionId}");
- #}
-
- #return Syncroton_Data_AData::$entries[get_class($this)][$collection->collectionId][$serverId];
-
-
}
public function moveItem($_srcFolderId, $_serverId, $_dstFolderId)
@@ -195,7 +187,7 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
public function updateFolder(Syncroton_Model_IFolder $folder)
{
- Syncroton_Data_AData::$folders[get_class($this)][$folder->folderid] = $folder;
+ Syncroton_Data_AData::$folders[get_class($this)][$folder->serverId] = $folder;
}
diff --git a/lib/ext/Syncroton/Data/Calendar.php b/lib/ext/Syncroton/Data/Calendar.php
index 539d9c2..9f24590 100644
--- a/lib/ext/Syncroton/Data/Calendar.php
+++ b/lib/ext/Syncroton/Data/Calendar.php
@@ -24,9 +24,9 @@ class Syncroton_Data_Calendar extends Syncroton_Data_AData
Syncroton_Data_AData::$folders[get_class($this)] = array(
'calendarFolderId' => new Syncroton_Model_Folder(array(
'id' => sha1(mt_rand(). microtime()),
- 'folderid' => 'calendarFolderId',
- 'parentid' => null,
- 'displayname' => 'Default Contacts Folder',
+ 'serverId' => 'calendarFolderId',
+ 'parentId' => 0,
+ 'displayName' => 'Default Contacts Folder',
'type' => Syncroton_Command_FolderSync::FOLDERTYPE_CALENDAR
))
);
diff --git a/lib/ext/Syncroton/Data/Contacts.php b/lib/ext/Syncroton/Data/Contacts.php
index 5ba8560..133ae00 100644
--- a/lib/ext/Syncroton/Data/Contacts.php
+++ b/lib/ext/Syncroton/Data/Contacts.php
@@ -14,8 +14,48 @@
* @package Model
*/
-class Syncroton_Data_Contacts extends Syncroton_Data_AData
+class Syncroton_Data_Contacts extends Syncroton_Data_AData implements Syncroton_Data_IDataSearch
{
+ /**
+ * (non-PHPdoc)
+ * @see Syncroton_Data_IDataSearch::getSearchEntry()
+ */
+ public function getSearchEntry($longId, $options)
+ {
+ list($collectionId, $serverId) = explode('-', $longId, 2);
+
+ $contact = $this->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $collectionId)), $serverId);
+
+ return new Syncroton_Model_GAL(array(
+ 'FirstName' => $contact->FirstName,
+ 'LastName' => $contact->LastName
+ ));
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see Syncroton_Data_IDataSearch::search()
+ */
+ public function search($query, $options)
+ {
+ $found = array();
+
+ $serverIds = $this->getServerEntries('addressbookFolderId', Syncroton_Command_Sync::FILTER_NOTHING);
+
+ foreach ($serverIds as $serverId) {
+ $contact = $this->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => 'addressbookFolderId')), $serverId);
+
+ if ($contact->FirstName == $query) {
+ $found[] = new Syncroton_Model_StoreResponseResult(array(
+ 'LongId' => 'addressbookFolderId-' . $serverId,
+ 'Properties' => $this->getSearchEntry('addressbookFolderId-' . $serverId, $options)
+ ));
+ }
+ }
+
+ return $found;
+ }
+
protected function _initData()
{
/**
@@ -25,16 +65,16 @@ class Syncroton_Data_Contacts extends Syncroton_Data_AData
Syncroton_Data_AData::$folders[get_class($this)] = array(
'addressbookFolderId' => new Syncroton_Model_Folder(array(
'id' => sha1(mt_rand(). microtime()),
- 'folderid' => 'addressbookFolderId',
- 'parentid' => null,
- 'displayname' => 'Default Contacts Folder',
+ 'serverId' => 'addressbookFolderId',
+ 'parentId' => 0,
+ 'displayName' => 'Default Contacts Folder',
'type' => Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT
)),
'anotherAddressbookFolderId' => new Syncroton_Model_Folder(array(
'id' => sha1(mt_rand(). microtime()),
- 'folderid' => 'anotherAddressbookFolderId',
- 'parentid' => null,
- 'displayname' => 'Another Contacts Folder',
+ 'serverId' => 'anotherAddressbookFolderId',
+ 'parentId' => 0,
+ 'displayName' => 'Another Contacts Folder',
'type' => Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT_USER_CREATED
))
);
diff --git a/lib/ext/Syncroton/Data/Email.php b/lib/ext/Syncroton/Data/Email.php
index 73c280f..9765a7b 100644
--- a/lib/ext/Syncroton/Data/Email.php
+++ b/lib/ext/Syncroton/Data/Email.php
@@ -22,7 +22,11 @@ class Syncroton_Data_Email extends Syncroton_Data_AData implements Syncroton_Dat
public static $entries = array(
);
- public function forwardEmail($collectionId, $itemId, $inputStream, $saveInSent)
+ /**
+ * (non-PHPdoc)
+ * @see Syncroton_Data_IDataEmail::forwardEmail()
+ */
+ public function forwardEmail($source, $inputStream, $saveInSent, $replaceMime)
{
// forward email
}
@@ -36,12 +40,16 @@ class Syncroton_Data_Email extends Syncroton_Data_AData implements Syncroton_Dat
// example code
return new Syncroton_Model_FileReference(array(
- 'ContentType' => 'text/plain',
- 'Data' => 'Lars'
+ 'ContentType' => 'text/plain',
+ 'Data' => 'Lars'
));
}
-
- public function replyEmail($collectionId, $itemId, $inputStream, $saveInSent)
+
+ /**
+ * (non-PHPdoc)
+ * @see Syncroton_Data_IDataEmail::replyEmail()
+ */
+ public function replyEmail($source, $inputStream, $saveInSent, $replaceMime)
{
// forward email
}
@@ -68,16 +76,16 @@ class Syncroton_Data_Email extends Syncroton_Data_AData implements Syncroton_Dat
Syncroton_Data_AData::$folders[get_class($this)] = array(
'emailInboxFolderId' => new Syncroton_Model_Folder(array(
'id' => sha1(mt_rand(). microtime()),
- 'folderid' => 'emailInboxFolderId',
- 'parentid' => null,
- 'displayname' => 'Inbox',
+ 'serverId' => 'emailInboxFolderId',
+ 'parentId' => 0,
+ 'displayName' => 'Inbox',
'type' => Syncroton_Command_FolderSync::FOLDERTYPE_INBOX
)),
'emailSentFolderId' => new Syncroton_Model_Folder(array(
'id' => sha1(mt_rand(). microtime()),
- 'folderid' => 'emailSentFolderId',
- 'parentid' => null,
- 'displayname' => 'Sent',
+ 'serverId' => 'emailSentFolderId',
+ 'parentId' => 0,
+ 'displayName' => 'Sent',
'type' => Syncroton_Command_FolderSync::FOLDERTYPE_SENTMAIL
))
);
diff --git a/lib/ext/Syncroton/Data/Factory.php b/lib/ext/Syncroton/Data/Factory.php
index 29c2bdd..1be6946 100644
--- a/lib/ext/Syncroton/Data/Factory.php
+++ b/lib/ext/Syncroton/Data/Factory.php
@@ -58,18 +58,13 @@ class Syncroton_Data_Factory
break;
default:
- throw new InvalidArgumentException('invalid class type provided');
+ throw new Syncroton_Exception_UnexpectedValue('invalid class type provided');
breeak;
}
$class = new $className($_device, $_timeStamp);
- if ($_classFactory == STORE_EMAIL || $_classFactory == STORE_GAL) {
- if (! $class instanceof Syncroton_Data_IDataSearch) {
- throw new RuntimeException('class must be instanceof Syncroton_Data_IDataSearch');
- }
- }
- else if (! $class instanceof Syncroton_Data_IData) {
+ if (! $class instanceof Syncroton_Data_IData) {
throw new RuntimeException('class must be instanceof Syncroton_Data_IData');
}
diff --git a/lib/ext/Syncroton/Data/IDataEmail.php b/lib/ext/Syncroton/Data/IDataEmail.php
index 731d187..7ecbb37 100644
--- a/lib/ext/Syncroton/Data/IDataEmail.php
+++ b/lib/ext/Syncroton/Data/IDataEmail.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Syncroton
*
@@ -10,7 +9,7 @@
*/
/**
- * class to handle ActiveSync Sync command
+ * intace for email backend
*
* @package Model
*/
@@ -27,21 +26,19 @@ interface Syncroton_Data_IDataEmail
/**
* forward an email
*
- * @param string $collectionId
- * @param string $itemId
- * @param string $inputStream
- * @param string $saveInSent
+ * @param string|array $source is either a string(LongId) or an arrey with following properties collectionId, itemId and instanceId
+ * @param string $inputStream
+ * @param string $saveInSent
*/
- public function forwardEmail($collectionId, $itemId, $inputStream, $saveInSent);
+ public function forwardEmail($source, $inputStream, $saveInSent, $replaceMime);
/**
* reply to an email
*
- * @param string $collectionId
- * @param string $itemId
- * @param string $inputStream
- * @param string $saveInSent
+ * @param string|array $source is either a string(LongId) or an arrey with following properties collectionId, itemId and instanceId
+ * @param string $inputStream
+ * @param string $saveInSent
*/
- public function replyEmail($collectionId, $itemId, $inputStream, $saveInSent);
+ public function replyEmail($source, $inputStream, $saveInSent, $replaceMime);
}
diff --git a/lib/ext/Syncroton/Data/Tasks.php b/lib/ext/Syncroton/Data/Tasks.php
index 6fc6f4d..30a80d2 100644
--- a/lib/ext/Syncroton/Data/Tasks.php
+++ b/lib/ext/Syncroton/Data/Tasks.php
@@ -24,9 +24,9 @@ class Syncroton_Data_Tasks extends Syncroton_Data_AData
Syncroton_Data_AData::$folders[get_class($this)] = array(
'tasksFolderId' => new Syncroton_Model_Folder(array(
'id' => sha1(mt_rand(). microtime()),
- 'folderid' => 'tasksFolderId',
- 'parentid' => null,
- 'displayname' => 'Default Tasks Folder',
+ 'serverId' => 'tasksFolderId',
+ 'parentId' => 0,
+ 'displayName' => 'Default Tasks Folder',
'type' => Syncroton_Command_FolderSync::FOLDERTYPE_TASK
))
);
diff --git a/lib/ext/Syncroton/Exception/ProvisioningNeeded.php b/lib/ext/Syncroton/Exception/ProvisioningNeeded.php
index f2cd5f2..10db726 100644
--- a/lib/ext/Syncroton/Exception/ProvisioningNeeded.php
+++ b/lib/ext/Syncroton/Exception/ProvisioningNeeded.php
@@ -17,4 +17,5 @@
*/
class Syncroton_Exception_ProvisioningNeeded extends Syncroton_Exception
{
+ public $domDocument;
}
diff --git a/lib/ext/Syncroton/Model/AEntry.php b/lib/ext/Syncroton/Model/AEntry.php
index 029118a..7667d11 100644
--- a/lib/ext/Syncroton/Model/AEntry.php
+++ b/lib/ext/Syncroton/Model/AEntry.php
@@ -18,10 +18,14 @@
abstract class Syncroton_Model_AEntry implements Syncroton_Model_IEntry, IteratorAggregate, Countable
{
+ protected $_xmlBaseElement;
+
protected $_elements = array();
protected $_properties = array();
+ protected $_dateTimeFormat = "Y-m-d\TH:i:s.000\Z";
+
public function __construct($properties = null)
{
if ($properties instanceof SimpleXMLElement) {
@@ -33,6 +37,51 @@ abstract class Syncroton_Model_AEntry implements Syncroton_Model_IEntry, Iterato
/**
* (non-PHPdoc)
+ * @see Syncroton_Model_IEntry::appendXML()
+ */
+ public function appendXML(DOMElement $_domParrent)
+ {
+ $this->_addXMLNamespaces($_domParrent);
+
+ foreach($this->_elements as $elementName => $value) {
+ // skip empty values
+ if($value === null || $value === '' || (is_array($value) && empty($value))) {
+ continue;
+ }
+
+ list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
+
+ if ($nameSpace == 'Internal') {
+ continue;
+ }
+
+ $nameSpace = 'uri:' . $nameSpace;
+
+ // strip off any non printable control characters
+ if (!ctype_print($value)) {
+ #$value = $this->removeControlChars($value);
+ }
+
+ $element = $_domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementName));
+
+ if (is_array($value)) {
+ foreach($value as $subValue) {
+ $subElement = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementProperties['childName']);
+
+ $this->_appendXMLElement($subElement, array(), $subValue);
+
+ $element->appendChild($subElement);
+ }
+ } else {
+ $this->_appendXMLElement($element, $elementProperties, $value);
+ }
+
+ $_domParrent->appendChild($element);
+ }
+ }
+
+ /**
+ * (non-PHPdoc)
* @see Countable::count()
*/
public function count()
@@ -87,13 +136,16 @@ abstract class Syncroton_Model_AEntry implements Syncroton_Model_IEntry, Iterato
*/
public function setFromSimpleXMLElement(SimpleXMLElement $properties)
{
- if ($properties->getName() !== $this->_xmlBaseElement) {
+ if (!in_array($properties->getName(), (array) $this->_xmlBaseElement)) {
throw new InvalidArgumentException('Unexpected element name: ' . $properties->getName());
}
$this->_elements = array();
- foreach (array_keys($this->_properties) as $namespace) {
+ foreach (array_keys($this->_properties) as $namespace) {
+ if ($namespace == 'Internal') {
+ continue;
+ }
$functionName = '_parse' . $namespace . 'Namespace';
$this->$functionName($properties);
}
@@ -112,6 +164,27 @@ abstract class Syncroton_Model_AEntry implements Syncroton_Model_IEntry, Iterato
$_domParrent->ownerDocument->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:'.$namespace, 'uri:'.$namespace);
}
}
+
+ protected function _appendXMLElement($element, $elementProperties, $value)
+ {
+ if ($value instanceof Syncroton_Model_IEntry) {
+ $value->appendXML($element);
+ } else {
+ if ($value instanceof DateTime) {
+ $value = $value->format($this->_dateTimeFormat);
+
+ } elseif (isset($elementProperties['encoding']) && $elementProperties['encoding'] == 'base64') {
+ if (is_resource($value)) {
+ stream_filter_append($value, 'convert.base64-encode');
+ $value = stream_get_contents($value);
+ } else {
+ $value = base64_encode($value);
+ }
+ }
+
+ $element->appendChild($element->ownerDocument->createTextNode($value));
+ }
+ }
/**
*
@@ -120,13 +193,13 @@ abstract class Syncroton_Model_AEntry implements Syncroton_Model_IEntry, Iterato
* @return multitype:unknown
*/
protected function _getElementProperties($element)
- {
- foreach($this->_properties as $namespace => $namespaceProperties) {
+ {
+ foreach($this->_properties as $namespace => $namespaceProperties) {
if (array_key_exists($element, $namespaceProperties)) {
return array($namespace, $namespaceProperties[$element]);
}
}
-
+
throw new InvalidArgumentException("$element is no valid property of this object");
}
diff --git a/lib/ext/Syncroton/Model/Contact.php b/lib/ext/Syncroton/Model/Contact.php
index 31e2bdc..d5f20e4 100644
--- a/lib/ext/Syncroton/Model/Contact.php
+++ b/lib/ext/Syncroton/Model/Contact.php
@@ -49,9 +49,9 @@ class Syncroton_Model_Contact extends Syncroton_Model_AEntry
'BusinessFaxNumber' => array('type' => 'string'),
'BusinessPhoneNumber' => array('type' => 'string'),
'CarPhoneNumber' => array('type' => 'string'),
- 'Categories' => array('type' => 'container'),
+ 'Categories' => array('type' => 'container', 'childName' => 'Category'),
//'Category' => array('type' => 'string'),
- 'Children' => array('type' => 'container'),
+ 'Children' => array('type' => 'container', 'childName' => 'Child'),
//'Child' => array('type' => 'string'),
'CompanyName' => array('type' => 'string'),
'Department' => array('type' => 'string'),
@@ -105,86 +105,6 @@ class Syncroton_Model_Contact extends Syncroton_Model_AEntry
)
);
- public function appendXML(DOMElement $_domParrent)
- {
- $this->_addXMLNamespaces($_domParrent);
-
- foreach($this->_elements as $elementName => $value) {
- // skip empty values
- if($value === null || $value === '' || (is_array($value) && empty($value))) {
- continue;
- }
-
- list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
-
- $nameSpace = 'uri:' . $nameSpace;
-
- // strip off any non printable control characters
- if (!ctype_print($value)) {
- #$value = $this->removeControlChars($value);
- }
-
- switch($elementName) {
- case 'Body':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- $value->appendXML($element);
-
- $_domParrent->appendChild($element);
-
- break;
-
- case 'Categories':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- foreach($value as $category) {
- $categoryElement = $_domParrent->ownerDocument->createElementNS($nameSpace, 'Category');
- $categoryElement->appendChild($_domParrent->ownerDocument->createTextNode($category));
-
- $element->appendChild($categoryElement);
- }
-
- $_domParrent->appendChild($element);
-
- break;
-
- case 'Children':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- foreach($value as $child) {
- $childElement = $_domParrent->ownerDocument->createElementNS($nameSpace, 'Child');
- $childElement->appendChild($_domParrent->ownerDocument->createTextNode($child));
-
- $element->appendChild($childElement);
- }
-
- $_domParrent->appendChild($element);
-
- break;
-
- default:
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- if ($value instanceof DateTime) {
- $value = $value->format("Y-m-d\TH:i:s.000\Z");
- }
-
- if (isset($elementProperties['encoding']) && $elementProperties['encoding'] == 'base64') {
- if (is_resource($value)) {
- stream_filter_append($value, 'convert.base64-encode');
- $value = stream_get_contents($value);
- } else {
- $value = base64_encode($value);
- }
- }
-
- $element->appendChild($_domParrent->ownerDocument->createTextNode($value));
-
- $_domParrent->appendChild($element);
- }
- }
- }
-
protected function _parseContactsNamespace(SimpleXMLElement $properties)
{
// fetch data from Contacts namespace
diff --git a/lib/ext/Syncroton/Model/Email.php b/lib/ext/Syncroton/Model/Email.php
index 9985d81..e3aa3ce 100644
--- a/lib/ext/Syncroton/Model/Email.php
+++ b/lib/ext/Syncroton/Model/Email.php
@@ -26,21 +26,20 @@ class Syncroton_Model_Email extends Syncroton_Model_AEntry
protected $_properties = array(
'AirSyncBase' => array(
- 'Attachments' => array('type' => 'container'),
+ 'Attachments' => array('type' => 'container', 'childName' => 'Attachment'),
'ContentType' => array('type' => 'string'),
'Body' => array('type' => 'container'),
'NativeBodyType' => array('type' => 'number'),
),
'Email' => array(
'BusyStatus' => array('type' => 'number'),
- 'Categories' => array('type' => 'container'),
- 'Category' => array('type' => 'string'),
+ 'Categories' => array('type' => 'container', 'childName' => 'Category'),
'Cc' => array('type' => 'string'),
'CompleteTime' => array('type' => 'datetime'),
'ContentClass' => array('type' => 'string'),
'DateReceived' => array('type' => 'datetime'),
- 'DayOfMonth' => array('type' => 'number'),
- 'DayOfWeek' => array('type' => 'number'),
+ #'DayOfMonth' => array('type' => 'number'),
+ #'DayOfWeek' => array('type' => 'number'),
'DisallowNewTimeProposal' => array('type' => 'number'),
'DisplayTo' => array('type' => 'string'),
'DTStamp' => array('type' => 'datetime'),
@@ -52,16 +51,16 @@ class Syncroton_Model_Email extends Syncroton_Model_AEntry
'Importance' => array('type' => 'number'),
'InstanceType' => array('type' => 'number'),
'InternetCPID' => array('type' => 'string'),
- 'Interval' => array('type' => 'number'),
+ #'Interval' => array('type' => 'number'),
'Location' => array('type' => 'string'),
'MeetingRequest' => array('type' => 'container'),
'MessageClass' => array('type' => 'string'),
- 'MonthOfYear' => array('type' => 'number'),
- 'Occurrences' => array('type' => 'number'),
+ #'MonthOfYear' => array('type' => 'number'),
+ #'Occurrences' => array('type' => 'number'),
'Organizer' => array('type' => 'string'),
'Read' => array('type' => 'number'),
- 'Recurrence' => array('type' => 'container'),
- 'RecurrenceId' => array('type' => 'datetime'),
+ #'Recurrence' => array('type' => 'container'),
+ #'RecurrenceId' => array('type' => 'datetime'),
'Recurrences' => array('type' => 'container'),
'Reminder' => array('type' => 'number'),
'ReplyTo' => array('type' => 'string'),
@@ -73,29 +72,17 @@ class Syncroton_Model_Email extends Syncroton_Model_AEntry
'ThreadTopic' => array('type' => 'string'),
'TimeZone' => array('type' => 'timezone'),
'To' => array('type' => 'string'),
- 'Type' => array('type' => 'number'),
- 'Until' => array('type' => 'datetime'),
- 'WeekOfMonth' => array('type' => 'number'),
-
- //'AttName' => 0x07,
- //'AttSize' => 0x08,
- //'Att0Id' => 0x09,
- //'AttMethod' => 0x0a,
- //'AttRemoved' => 0x0b,
- //'Body' => 0x0c,
- //'BodySize' => 0x0d,
- //'BodyTruncated' => 0x0e,
- //'MIMEData' => 0x36,
- //'MIMETruncated' => 0x37,
- //'MIMESize' => 0x38,
+ #'Type' => array('type' => 'number'),
+ #'Until' => array('type' => 'datetime'),
+ #'WeekOfMonth' => array('type' => 'number'),
),
'Email2' => array(
'AccountId' => array('type' => 'string'),
- 'CalendarType' => array('type' => 'number'),
+ #'CalendarType' => array('type' => 'number'),
'ConversationId' => array('type' => 'byteArray'), // @todo handle this
'ConversationIndex' => array('type' => 'byteArray'), // @todo handle this
- 'FirstDayOfWeek' => array('type' => 'number'),
- 'IsLeapMonth' => array('type' => 'number'),
+ #'FirstDayOfWeek' => array('type' => 'number'),
+ #'IsLeapMonth' => array('type' => 'number'),
'LastVerbExecuted' => array('type' => 'number'),
'LastVerbExecutionTime' => array('type' => 'datetime'),
'MeetingMessageType' => array('type' => 'number'),
@@ -106,85 +93,6 @@ class Syncroton_Model_Email extends Syncroton_Model_AEntry
),
);
- public function appendXML(DOMElement $_domParrent)
- {
- $this->_addXMLNamespaces($_domParrent);
-
- foreach($this->_elements as $elementName => $value) {
- // skip empty values
- if($value === null || $value === '' || (is_array($value) && empty($value))) {
- continue;
- }
-
- list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
-
- $nameSpace = 'uri:' . $nameSpace;
-
- // strip off any non printable control characters
- if (!ctype_print($value)) {
- #$value = $this->removeControlChars($value);
- }
-
- switch($elementName) {
- case 'Attachments':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- foreach($value as $attachment) {
- $attachmentElement = $_domParrent->ownerDocument->createElementNS($nameSpace, 'Attachment');
- $attachment->appendXML($attachmentElement);
-
- $element->appendChild($attachmentElement);
- }
-
- $_domParrent->appendChild($element);
-
- break;
-
- case 'Body':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- $value->appendXML($element);
-
- $_domParrent->appendChild($element);
- break;
-
- case 'Categories':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- foreach($value as $category) {
- $categoryElement = $_domParrent->ownerDocument->createElementNS($nameSpace, 'Category');
- $categoryElement->appendChild($_domParrent->ownerDocument->createTextNode($category));
-
- $element->appendChild($categoryElement);
- }
-
- $_domParrent->appendChild($element);
-
- break;
-
- case 'Recurrence':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- $value->appendXML($element);
-
- $_domParrent->appendChild($element);
-
- break;
-
- default:
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- if ($value instanceof DateTime) {
- $value = $value->format("Y-m-d\TH:i:s.000\Z");
- }
- $element->appendChild($_domParrent->ownerDocument->createTextNode($value));
-
- $_domParrent->appendChild($element);
- }
- }
-
- }
-
protected function _parseAirSyncBaseNamespace(SimpleXMLElement $properties)
{
// fetch data from AirSyncBase namespace
diff --git a/lib/ext/Syncroton/Model/EmailAttachment.php b/lib/ext/Syncroton/Model/EmailAttachment.php
index 2bbd69e..e958f7f 100644
--- a/lib/ext/Syncroton/Model/EmailAttachment.php
+++ b/lib/ext/Syncroton/Model/EmailAttachment.php
@@ -19,12 +19,10 @@
* @property string syncKey
* @property int windowSize
*/
-
class Syncroton_Model_EmailAttachment extends Syncroton_Model_AEntry
{
protected $_xmlBaseElement = 'Attachment';
- // @todo handle body
protected $_properties = array(
'AirSyncBase' => array(
'ContentId' => array('type' => 'string'),
@@ -41,89 +39,6 @@ class Syncroton_Model_EmailAttachment extends Syncroton_Model_AEntry
),
);
- public function appendXML(DOMElement $_domParrent)
- {
- $_domParrent->ownerDocument->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:AirSyncBase', 'uri:AirSyncBase');
- $_domParrent->ownerDocument->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Email2', 'uri:Email2');
-
- foreach($this->_elements as $elementName => $value) {
- // skip empty values
- if($value === null || $value === '' || (is_array($value) && empty($value))) {
- continue;
- }
-
- $elementProperties = (isset($this->_properties['AirSyncBase'][$elementName])) ?
- $this->_properties['AirSyncBase'][$elementName] :
- $this->_properties['Email2'][$elementName];
-
- $nameSpace = isset($this->_properties['AirSyncBase'][$elementName]) ? 'uri:AirSyncBase' : 'uri:Email2';
-
- // strip off any non printable control characters
- if (!ctype_print($value)) {
- #$value = $this->removeControlChars($value);
- }
-
- switch($elementName) {
- case 'Categories':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- foreach($value as $category) {
- $categoryElement = $_domParrent->ownerDocument->createElementNS($nameSpace, 'Category');
- $categoryElement->appendChild($_domParrent->ownerDocument->createTextNode($category));
-
- $element->appendChild($categoryElement);
- }
-
- $_domParrent->appendChild($element);
-
- break;
-
- case 'Recurrence':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- $value->appendXML($element);
-
- $_domParrent->appendChild($element);
-
- break;
-
- default:
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- if ($value instanceof DateTime) {
- $value = $value->format("Y-m-d\TH:i:s.000\Z");
- }
- $element->appendChild($_domParrent->ownerDocument->createTextNode($value));
-
- $_domParrent->appendChild($element);
- }
- }
-
- }
-
- /**
- *
- * @param SimpleXMLElement $xmlCollection
- * @throws InvalidArgumentException
- */
- public function setFromSimpleXMLElement(SimpleXMLElement $properties)
- {
- if ($properties->getName() !== $this->_xmlBaseElement) {
- throw new InvalidArgumentException('Unexpected element name: ' . $properties->getName());
- }
-
- $this->_elements = array();
-
- foreach (array_keys($this->_properties) as $namespace) {
- $functionName = '_parse' . $namespace . 'Namespace';
- $this->$functionName($properties);
- }
-
- $airSyncBaseData = $properties->children('uri:AirSyncBase');
-
- return;
- }
-
protected function _parseAirSyncBaseNamespace(SimpleXMLElement $properties)
{
// fetch data from Email namespace
diff --git a/lib/ext/Syncroton/Model/EmailBody.php b/lib/ext/Syncroton/Model/EmailBody.php
index 8f8b318..4f2af2c 100644
--- a/lib/ext/Syncroton/Model/EmailBody.php
+++ b/lib/ext/Syncroton/Model/EmailBody.php
@@ -41,40 +41,6 @@ class Syncroton_Model_EmailBody extends Syncroton_Model_AEntry
),
);
- public function appendXML(DOMElement $_domParrent)
- {
- $this->_addXMLNamespaces($_domParrent);
-
- foreach($this->_elements as $elementName => $value) {
- // skip empty values
- if($value === null || $value === '' || (is_array($value) && empty($value))) {
- continue;
- }
-
- list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
-
- $nameSpace = 'uri:' . $nameSpace;
-
- // strip off any non printable control characters
- if (!ctype_print($value)) {
- #$value = $this->removeControlChars($value);
- }
-
- switch($elementName) {
- default:
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- if ($value instanceof DateTime) {
- $value = $value->format("Y-m-d\TH:i:s.000\Z");
- }
- $element->appendChild($_domParrent->ownerDocument->createTextNode($value));
-
- $_domParrent->appendChild($element);
- }
- }
-
- }
-
/**
*
* @param SimpleXMLElement $xmlCollection
diff --git a/lib/ext/Syncroton/Model/Event.php b/lib/ext/Syncroton/Model/Event.php
index cc37324..1571b30 100644
--- a/lib/ext/Syncroton/Model/Event.php
+++ b/lib/ext/Syncroton/Model/Event.php
@@ -29,9 +29,10 @@ class Syncroton_Model_Event extends Syncroton_Model_AEntry
const BUSY_STATUS_TENATTIVE = 1;
const BUSY_STATUS_BUSY = 2;
+ protected $_dateTimeFormat = "Ymd\THis\Z";
+
protected $_xmlBaseElement = 'ApplicationData';
- // @todo handle body
protected $_properties = array(
'AirSyncBase' => array(
'Body' => array('type' => 'container')
@@ -39,15 +40,15 @@ class Syncroton_Model_Event extends Syncroton_Model_AEntry
'Calendar' => array(
'AllDayEvent' => array('type' => 'number'),
'AppointmentReplyTime' => array('type' => 'datetime'),
- 'Attendees' => array('type' => 'container'),
+ 'Attendees' => array('type' => 'container', 'childName' => 'Attendee'),
//'Body' => 0x0b,
//'BodyTruncated' => 0x0c,
'BusyStatus' => array('type' => 'number'),
- 'Categories' => array('type' => 'container'),
+ 'Categories' => array('type' => 'container', 'childName' => 'Category'),
'DisallowNewTimeProposal' => array('type' => 'number'),
'DtStamp' => array('type' => 'datetime'),
'EndTime' => array('type' => 'datetime'),
- 'Exceptions' => array('type' => 'container'),
+ 'Exceptions' => array('type' => 'container', 'childName' => 'Exception'),
'Location' => array('type' => 'string'),
'MeetingStatus' => array('type' => 'number'),
'OnlineMeetingConfLink' => array('type' => 'string'),
@@ -67,98 +68,6 @@ class Syncroton_Model_Event extends Syncroton_Model_AEntry
)
);
- public function appendXML(DOMElement $_domParrent)
- {
- $this->_addXMLNamespaces($_domParrent);
-
- foreach($this->_elements as $elementName => $value) {
- // skip empty values
- if($value === null || $value === '' || (is_array($value) && empty($value))) {
- continue;
- }
-
- list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
-
- $nameSpace = 'uri:' . $nameSpace;
-
- // strip off any non printable control characters
- if (!ctype_print($value)) {
- #$value = $this->removeControlChars($value);
- }
-
- switch($elementName) {
- case 'Attendees':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- foreach ($value as $attendee) {
- $attendeeElement = $_domParrent->ownerDocument->createElementNS($nameSpace, 'Attendee');
- $attendee->appendXML($attendeeElement);
- $element->appendChild($attendeeElement);
- }
-
- $_domParrent->appendChild($element);
-
- break;
-
- case 'Body':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- $value->appendXML($element);
-
- $_domParrent->appendChild($element);
-
- break;
-
- case 'Categories':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- foreach($value as $category) {
- $categoryElement = $_domParrent->ownerDocument->createElementNS($nameSpace, 'Category');
- $categoryElement->appendChild($_domParrent->ownerDocument->createTextNode($category));
-
- $element->appendChild($categoryElement);
- }
-
- $_domParrent->appendChild($element);
-
- break;
-
- case 'Exceptions':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- foreach ($value as $exception) {
- $exceptionElement = $_domParrent->ownerDocument->createElementNS($nameSpace, 'Exception');
- $exception->appendXML($exceptionElement);
- $element->appendChild($exceptionElement);
- }
-
- $_domParrent->appendChild($element);
-
- break;
-
- case 'Recurrence':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- $value->appendXML($element);
-
- $_domParrent->appendChild($element);
-
- break;
-
- default:
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- if ($value instanceof DateTime) {
- $value = $value->format("Ymd\THis\Z");
- }
- $element->appendChild($_domParrent->ownerDocument->createTextNode($value));
-
- $_domParrent->appendChild($element);
- }
- }
-
- }
-
protected function _parseCalendarNamespace(SimpleXMLElement $properties)
{
// fetch data from Contacts namespace
diff --git a/lib/ext/Syncroton/Model/EventAttendee.php b/lib/ext/Syncroton/Model/EventAttendee.php
index 3e9946d..7827e30 100644
--- a/lib/ext/Syncroton/Model/EventAttendee.php
+++ b/lib/ext/Syncroton/Model/EventAttendee.php
@@ -38,7 +38,6 @@ class Syncroton_Model_EventAttendee extends Syncroton_Model_AEntry
const ATTENDEE_TYPE_OPTIONAL = 2;
const ATTENDEE_TYPE_RESOURCE = 3;
- // @todo handle body
protected $_properties = array(
'Calendar' => array(
'AttendeeStatus' => array('type' => 'number'),
@@ -48,82 +47,6 @@ class Syncroton_Model_EventAttendee extends Syncroton_Model_AEntry
)
);
- public function appendXML(DOMElement $_domParrent)
- {
- $_domParrent->ownerDocument->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Calendar', 'uri:Calendar');
-
- foreach($this->_elements as $elementName => $value) {
- // skip empty values
- if($value === null || $value === '' || (is_array($value) && empty($value))) {
- continue;
- }
-
- $elementProperties = $this->_properties['Calendar'][$elementName];
-
- $nameSpace = 'uri:Calendar';
-
- // strip off any non printable control characters
- if (!ctype_print($value)) {
- #$value = $this->removeControlChars($value);
- }
-
- switch($elementName) {
- case 'Categories':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- foreach($value as $category) {
- $categoryElement = $_domParrent->ownerDocument->createElementNS($nameSpace, 'Category');
- $categoryElement->appendChild($_domParrent->ownerDocument->createTextNode($category));
-
- $element->appendChild($categoryElement);
- }
-
- $_domParrent->appendChild($element);
-
- break;
-
- case 'Children':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- foreach($value as $child) {
- $childElement = $_domParrent->ownerDocument->createElementNS($nameSpace, 'Child');
- $childElement->appendChild($_domParrent->ownerDocument->createTextNode($child));
-
- $element->appendChild($childElement);
- }
-
- $_domParrent->appendChild($element);
-
- break;
-
- case 'Picture':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- if (is_resource($value)) {
- stream_filter_append($value, 'convert.base64-encode');
- $element->appendChild($_domParrent->ownerDocument->createTextNode(stream_get_contents($value)));
- } else {
- $element->appendChild($_domParrent->ownerDocument->createTextNode(base64_encode($value)));
- }
-
- $_domParrent->appendChild($element);
-
- break;
-
- default:
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- if ($value instanceof DateTime) {
- $value = $value->format("Ymd\THis\Z");
- }
- $element->appendChild($_domParrent->ownerDocument->createTextNode($value));
-
- $_domParrent->appendChild($element);
- }
- }
-
- }
-
/**
*
* @param SimpleXMLElement $xmlCollection
diff --git a/lib/ext/Syncroton/Model/EventException.php b/lib/ext/Syncroton/Model/EventException.php
index e6881c9..7ab97d7 100644
--- a/lib/ext/Syncroton/Model/EventException.php
+++ b/lib/ext/Syncroton/Model/EventException.php
@@ -24,7 +24,8 @@ class Syncroton_Model_EventException extends Syncroton_Model_Event
{
protected $_xmlBaseElement = 'Exception';
- // @todo handle body
+ protected $_dateTimeFormat = "Ymd\THis\Z";
+
protected $_properties = array(
'Calendar' => array(
'AllDayEvent' => array('type' => 'number'),
diff --git a/lib/ext/Syncroton/Model/EventRecurrence.php b/lib/ext/Syncroton/Model/EventRecurrence.php
index 83fe039..d8b9f4c 100644
--- a/lib/ext/Syncroton/Model/EventRecurrence.php
+++ b/lib/ext/Syncroton/Model/EventRecurrence.php
@@ -49,8 +49,9 @@ class Syncroton_Model_EventRecurrence extends Syncroton_Model_AEntry
const RECUR_DOW_THURSDAY = 16;
const RECUR_DOW_FRIDAY = 32;
const RECUR_DOW_SATURDAY = 64;
-
- // @todo handle body
+
+ protected $_dateTimeFormat = "Ymd\THis\Z";
+
protected $_properties = array(
'Calendar' => array(
'CalendarType' => array('type' => 'number'),
@@ -67,40 +68,6 @@ class Syncroton_Model_EventRecurrence extends Syncroton_Model_AEntry
)
);
- public function appendXML(DOMElement $_domParrent)
- {
- $this->_addXMLNamespaces($_domParrent);
-
- foreach($this->_elements as $elementName => $value) {
- // skip empty values
- if($value === null || $value === '' || (is_array($value) && empty($value))) {
- continue;
- }
-
- list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
-
- $nameSpace = 'uri:' . $nameSpace;
-
- // strip off any non printable control characters
- if (!ctype_print($value)) {
- #$value = $this->removeControlChars($value);
- }
-
- switch($elementName) {
- default:
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- if ($value instanceof DateTime) {
- $value = $value->format("Ymd\THis\Z");
- }
- $element->appendChild($_domParrent->ownerDocument->createTextNode($value));
-
- $_domParrent->appendChild($element);
- }
- }
-
- }
-
protected function _parseCalendarNamespace(SimpleXMLElement $properties)
{
// fetch data from Contacts namespace
diff --git a/lib/ext/Syncroton/Model/FileReference.php b/lib/ext/Syncroton/Model/FileReference.php
index b22bcb0..6c2e67d 100644
--- a/lib/ext/Syncroton/Model/FileReference.php
+++ b/lib/ext/Syncroton/Model/FileReference.php
@@ -29,56 +29,6 @@ class Syncroton_Model_FileReference extends Syncroton_Model_AEntry
)
);
- /**
- * append email data to xml element
- *
- * @param DOMElement $_domParrent the parrent xml node
- * @param string $_folderId the local folder id
- */
- public function appendXML(DOMElement $_domParrent)
- {
- $this->_addXMLNamespaces($_domParrent);
-
- foreach($this->_elements as $elementName => $value) {
- // skip empty values
- if($value === null || $value === '' || (is_array($value) && empty($value))) {
- continue;
- }
-
- list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
-
- $nameSpace = 'uri:' . $nameSpace;
-
- // strip off any non printable control characters
- if (!ctype_print($value)) {
- #$value = $this->removeControlChars($value);
- }
-
- switch($elementName) {
- default:
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- if ($value instanceof DateTime) {
- $value = $value->format("Y-m-d\TH:i:s.000\Z");
- }
-
- if (isset($elementProperties['encoding']) && $elementProperties['encoding'] == 'base64') {
- if (is_resource($value)) {
- stream_filter_append($value, 'convert.base64-encode');
- $value = stream_get_contents($value);
- } else {
- $value = base64_encode($value);
- }
- }
-
- $element->appendChild($_domParrent->ownerDocument->createTextNode($value));
-
- $_domParrent->appendChild($element);
- }
- }
-
- }
-
/**
*
* @param SimpleXMLElement $xmlCollection
diff --git a/lib/ext/Syncroton/Model/Folder.php b/lib/ext/Syncroton/Model/Folder.php
index 7aaf91a..50cb189 100644
--- a/lib/ext/Syncroton/Model/Folder.php
+++ b/lib/ext/Syncroton/Model/Folder.php
@@ -15,18 +15,59 @@
* @package Model
*/
-class Syncroton_Model_Folder implements Syncroton_Model_IFolder
+class Syncroton_Model_Folder extends Syncroton_Model_AEntry implements Syncroton_Model_IFolder
{
- public function __construct(array $_data = array())
- {
- $this->setFromArray($_data);
- }
+ protected $_xmlBaseElement = array('FolderUpdate', 'FolderCreate');
- public function setFromArray(array $_data)
- {
- foreach($_data as $key => $value) {
- $this->$key = $value;
- }
+ protected $_properties = array(
+ 'FolderHierarchy' => array(
+ 'parentId' => array('type' => 'string'),
+ 'serverId' => array('type' => 'string'),
+ 'displayName' => array('type' => 'string'),
+ 'type' => array('type' => 'number')
+ ),
+ 'Internal' => array(
+ 'id' => array('type' => 'string'),
+ 'deviceId' => array('type' => 'string'),
+ 'class' => array('type' => 'string'),
+ 'creationTime' => array('type' => 'datetime'),
+ 'lastfiltertype' => array('type' => 'number')
+ ),
+ );
+
+ protected function _parseFolderHierarchyNamespace(SimpleXMLElement $properties)
+ {
+ // fetch data from Contacts namespace
+ $children = $properties->children('uri:FolderHierarchy');
+
+ foreach ($children as $elementName => $xmlElement) {
+ $elementName = lcfirst($elementName);
+
+ if (!isset($this->_properties['FolderHierarchy'][$elementName])) {
+ continue;
+ }
+
+ switch ($elementName) {
+ default:
+ list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
+
+ switch ($elementProperties['type']) {
+ case 'datetime':
+ $this->$elementName = new DateTime((string) $xmlElement, new DateTimeZone('UTC'));
+
+ break;
+
+ case 'number':
+ $this->$elementName = (int) $xmlElement;
+
+ break;
+ default:
+ $this->$elementName = (string) $xmlElement;
+
+ break;
+ }
+ }
+ }
}
}
diff --git a/lib/ext/Syncroton/Model/IDevice.php b/lib/ext/Syncroton/Model/IDevice.php
index c084f8c..e2c347e 100644
--- a/lib/ext/Syncroton/Model/IDevice.php
+++ b/lib/ext/Syncroton/Model/IDevice.php
@@ -17,8 +17,8 @@
* @property string deviceid
* @property string devicetype
* @property string policykey
- * @property string policy_id
- * @property string owner_id
+ * @property string policyId
+ * @property string ownerId
* @property string acsversion
* @property string pingfolder
* @property string pinglifetime
diff --git a/lib/ext/Syncroton/Model/IFolder.php b/lib/ext/Syncroton/Model/IFolder.php
index ca1e8e3..4ec3700 100644
--- a/lib/ext/Syncroton/Model/IFolder.php
+++ b/lib/ext/Syncroton/Model/IFolder.php
@@ -14,12 +14,12 @@
*
* @package Model
* @property string id
- * @property string device_id
+ * @property string deviceId
* @property string class
- * @property string folderid
- * @property string parentid
- * @property string displayname
- * @property string creation_time
+ * @property string serverId
+ * @property string parentId
+ * @property string displayName
+ * @property string creationTime
* @property string lastfiltertype
*/
diff --git a/lib/ext/Syncroton/Model/IPolicy.php b/lib/ext/Syncroton/Model/IPolicy.php
new file mode 100644
index 0000000..b6929d3
--- /dev/null
+++ b/lib/ext/Syncroton/Model/IPolicy.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * Syncroton
+ *
+ * @package Model
+ * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3
+ * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author Lars Kneschke <l.kneschke at metaways.de>
+ */
+
+/**
+ * class to handle ActiveSync Sync command
+ *
+ * @package Model
+ * @property string id
+ * @property string deviceid
+ * @property string devicetype
+ * @property string policyKey
+ * @property string policyId
+ * @property string ownerId
+ * @property string acsversion
+ * @property string pingfolder
+ * @property string pinglifetime
+ * @property string remotewipe
+ * @property string useragent
+ */
+
+interface Syncroton_Model_IPolicy
+{
+}
+
diff --git a/lib/ext/Syncroton/Model/Policy.php b/lib/ext/Syncroton/Model/Policy.php
new file mode 100644
index 0000000..9b1dcf3
--- /dev/null
+++ b/lib/ext/Syncroton/Model/Policy.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Syncroton
+ *
+ * @package Model
+ * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3
+ * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author Lars Kneschke <l.kneschke at metaways.de>
+ */
+
+/**
+ * class to handle ActiveSync Sync command
+ *
+ * @package Model
+ */
+
+class Syncroton_Model_Policy extends Syncroton_Model_AEntry implements Syncroton_Model_IPolicy
+{
+ protected $_xmlBaseElement = 'EASProvisionDoc';
+
+ protected $_properties = array(
+ 'Internal' => array(
+ 'id' => array('type' => 'string'),
+ 'description' => array('type' => 'string'),
+ 'name' => array('type' => 'string'),
+ 'policyKey' => array('type' => 'string'),
+ ),
+ 'Provision' => array(
+ 'allowBluetooth' => array('type' => 'number'),
+ 'allowSMIMEEncryptionAlgorithmNegotiation' => array('type' => 'number'),
+ 'allowBrowser' => array('type' => 'number'),
+ 'allowCamera' => array('type' => 'number'),
+ 'allowConsumerEmail' => array('type' => 'number'),
+ 'allowDesktopSync' => array('type' => 'number'),
+ 'allowHTMLEmail' => array('type' => 'number'),
+ 'allowInternetSharing' => array('type' => 'number'),
+ 'allowIrDA' => array('type' => 'number'),
+ 'allowPOPIMAPEmail' => array('type' => 'number'),
+ 'allowRemoteDesktop' => array('type' => 'number'),
+ 'allowSimpleDevicePassword' => array('type' => 'number'),
+ 'allowSMIMEEncryptionAlgorithmNegotiation' => array('type' => 'number'),
+ 'allowSMIMESoftCerts' => array('type' => 'number'),
+ 'allowStorageCard' => array('type' => 'number'),
+ 'allowTextMessaging' => array('type' => 'number'),
+ 'allowUnsignedApplications' => array('type' => 'number'),
+ 'allowUnsignedInstallationPackages' => array('type' => 'number'),
+ 'allowWifi' => array('type' => 'number'),
+ 'alphanumericDevicePasswordRequired' => array('type' => 'number'),
+ 'approvedApplicationList' => array('type' => 'container', 'childName' => 'Hash'),
+ 'attachmentsEnabled' => array('type' => 'number'),
+ 'devicePasswordEnabled' => array('type' => 'number'),
+ 'devicePasswordExpiration' => array('type' => 'number'),
+ 'devicePasswordHistory' => array('type' => 'number'),
+ 'maxAttachmentSize' => array('type' => 'number'),
+ 'maxCalendarAgeFilter' => array('type' => 'number'),
+ 'maxDevicePasswordFailedAttempts' => array('type' => 'number'),
+ 'maxEmailAgeFilter' => array('type' => 'number'),
+ 'maxEmailBodyTruncationSize' => array('type' => 'number'),
+ 'maxEmailHTMLBodyTruncationSize' => array('type' => 'number'),
+ 'maxInactivityTimeDeviceLock' => array('type' => 'number'),
+ 'minDevicePasswordComplexCharacters' => array('type' => 'number'),
+ 'minDevicePasswordLength' => array('type' => 'number'),
+ 'passwordRecoveryEnabled' => array('type' => 'number'),
+ 'requireDeviceEncryption' => array('type' => 'number'),
+ 'requireEncryptedSMIMEMessages' => array('type' => 'number'),
+ 'requireEncryptionSMIMEAlgorithm' => array('type' => 'number'),
+ 'requireManualSyncWhenRoaming' => array('type' => 'number'),
+ 'requireSignedSMIMEAlgorithm' => array('type' => 'number'),
+ 'requireSignedSMIMEMessages' => array('type' => 'number'),
+ 'requireStorageCardEncryption' => array('type' => 'number'),
+ 'unapprovedInROMApplicationList' => array('type' => 'container', 'childName' => 'ApplicationName')
+ )
+ );
+}
+
diff --git a/lib/ext/Syncroton/Model/StoreRequest.php b/lib/ext/Syncroton/Model/StoreRequest.php
index a108e35..e78f41c 100644
--- a/lib/ext/Syncroton/Model/StoreRequest.php
+++ b/lib/ext/Syncroton/Model/StoreRequest.php
@@ -80,11 +80,10 @@ class Syncroton_Model_StoreRequest
if (isset($xmlStore->Query)) {
$this->_store['query'] = (string) $xmlStore->Query;
}
- }
- else if (isset($xmlStore->Query)) {
+ } elseif (isset($xmlStore->Query)) {
if (isset($xmlStore->Query->And)) {
if (isset($xmlStore->Query->And->FreeText)) {
- $this->_store['query']['and']['freeText'] = (string) $xmlStore->Query->And->FreeText;
+ $this->_store['query']['and']['freetext'] = (string) $xmlStore->Query->And->FreeText;
}
if (isset($xmlStore->Query->And->ConversationId)) {
$this->_store['query']['and']['conversationId'] = (string) $xmlStore->Query->And->ConversationId;
@@ -115,8 +114,7 @@ class Syncroton_Model_StoreRequest
foreach ($airSync as $name => $value) {
if ($name == 'Class') {
$this->_store['query']['and']['classes'][] = (string) $value;
- }
- else if ($name == 'CollectionId') {
+ } elseif ($name == 'CollectionId') {
$this->_store['query']['and']['collections'][] = (string) $value;
}
}
@@ -164,8 +162,7 @@ class Syncroton_Model_StoreRequest
if (!empty($xmlStore->Options->Range)) {
$this->_store['options']['range'] = (string) $xmlStore->Options->Range;
- }
- else {
+ } else {
switch ($this->_store['name']) {
case 'DocumentLibrary':
case 'Document Library': //?
diff --git a/lib/ext/Syncroton/Model/StoreResponse.php b/lib/ext/Syncroton/Model/StoreResponse.php
index 51706a1..cd1770f 100644
--- a/lib/ext/Syncroton/Model/StoreResponse.php
+++ b/lib/ext/Syncroton/Model/StoreResponse.php
@@ -33,7 +33,7 @@ class Syncroton_Model_StoreResponse extends Syncroton_Model_AEntry
const STATUS_ACCESSBLOCKED = 13;
const STATUS_CREDENTIALSREQUIRED = 14;
- protected $_xmlBaseElement = 'ApplicationData';
+ protected $_xmlBaseElement = 'Store';
protected $_properties = array(
'Search' => array(
diff --git a/lib/ext/Syncroton/Model/StoreResponseResult.php b/lib/ext/Syncroton/Model/StoreResponseResult.php
index 2e1dcca..b79f863 100644
--- a/lib/ext/Syncroton/Model/StoreResponseResult.php
+++ b/lib/ext/Syncroton/Model/StoreResponseResult.php
@@ -16,7 +16,7 @@
*/
class Syncroton_Model_StoreResponseResult extends Syncroton_Model_AEntry
{
- protected $_xmlBaseElement = 'ApplicationData';
+ protected $_xmlBaseElement = 'Result';
protected $_properties = array(
'AirSync' => array(
@@ -28,33 +28,4 @@ class Syncroton_Model_StoreResponseResult extends Syncroton_Model_AEntry
'Properties' => array('type' => 'container'),
)
);
-
- public function appendXML(DOMElement $_domParrent)
- {
- $this->_addXMLNamespaces($_domParrent);
-
- foreach ($this->_elements as $elementName => $value) {
- // skip empty values
- if ($value === null || $value === '') {
- continue;
- }
-
- list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
-
- $nameSpace = 'uri:' . $nameSpace;
-
- switch ($elementName) {
- case 'Properties':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
- $value->appendXML($element);
- $_domParrent->appendChild($element);
- break;
-
- default:
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
- $element->appendChild($_domParrent->ownerDocument->createTextNode($value));
- $_domParrent->appendChild($element);
- }
- }
- }
}
diff --git a/lib/ext/Syncroton/Model/SyncCollection.php b/lib/ext/Syncroton/Model/SyncCollection.php
index 140881d..736c582 100644
--- a/lib/ext/Syncroton/Model/SyncCollection.php
+++ b/lib/ext/Syncroton/Model/SyncCollection.php
@@ -188,7 +188,7 @@ class Syncroton_Model_SyncCollection
'collectionId' => (string)$xmlCollection->CollectionId,
'deletesAsMoves' => isset($xmlCollection->DeletesAsMoves) && (string)$xmlCollection->DeletesAsMoves === '0' ? false : true,
'conversationMode' => isset($xmlCollection->ConversationMode) && (string)$xmlCollection->ConversationMode === '0' ? false : true,
- 'getChanges' => isset($xmlCollection->GetChanges) ? true : false,
+ 'getChanges' => isset($xmlCollection->GetChanges) && (string) $xmlCollection->GetChanges === '0' ? false : true,
'windowSize' => isset($xmlCollection->WindowSize) ? (int)$xmlCollection->WindowSize : 100,
'class' => isset($xmlCollection->Class) ? (string)$xmlCollection->Class : null,
'options' => array(
diff --git a/lib/ext/Syncroton/Model/Task.php b/lib/ext/Syncroton/Model/Task.php
index 30ebc70..ec42cff 100644
--- a/lib/ext/Syncroton/Model/Task.php
+++ b/lib/ext/Syncroton/Model/Task.php
@@ -24,16 +24,12 @@ class Syncroton_Model_Task extends Syncroton_Model_AEntry
{
protected $_xmlBaseElement = 'ApplicationData';
- // @todo handle body
protected $_properties = array(
'AirSyncBase' => array(
'Body' => array('type' => 'container')
),
'Tasks' => array(
- //'Body' => 0x05,
- //'BodySize' => 0x06,
- //'BodyTruncated' => 0x07,
- 'Categories' => array('type' => 'container'),
+ 'Categories' => array('type' => 'container', 'childName' => 'Category'),
'Complete' => array('type' => 'number'),
'DateCompleted' => array('type' => 'datetime'),
'DueDate' => array('type' => 'datetime'),
@@ -49,72 +45,6 @@ class Syncroton_Model_Task extends Syncroton_Model_AEntry
)
);
- public function appendXML(DOMElement $_domParrent)
- {
- $this->_addXMLNamespaces($_domParrent);
-
- foreach($this->_elements as $elementName => $value) {
- // skip empty values
- if($value === null || $value === '' || (is_array($value) && empty($value))) {
- continue;
- }
-
- list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
-
- $nameSpace = 'uri:' . $nameSpace;
-
- // strip off any non printable control characters
- if (!ctype_print($value)) {
- #$value = $this->removeControlChars($value);
- }
-
- switch($elementName) {
- case 'Body':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- $value->appendXML($element);
-
- $_domParrent->appendChild($element);
-
- break;
-
- case 'Categories':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- foreach($value as $category) {
- $categoryElement = $_domParrent->ownerDocument->createElementNS($nameSpace, 'Category');
- $categoryElement->appendChild($_domParrent->ownerDocument->createTextNode($category));
-
- $element->appendChild($categoryElement);
- }
-
- $_domParrent->appendChild($element);
-
- break;
-
- case 'Recurrence':
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- $value->appendXML($element);
-
- $_domParrent->appendChild($element);
-
- break;
-
- default:
- $element = $_domParrent->ownerDocument->createElementNS($nameSpace, $elementName);
-
- if ($value instanceof DateTime) {
- $value = $value->format("Y-m-d\TH:i:s.000\Z");
- }
- $element->appendChild($_domParrent->ownerDocument->createTextNode($value));
-
- $_domParrent->appendChild($element);
- }
- }
-
- }
-
protected function _parseTasksNamespace(SimpleXMLElement $properties)
{
// fetch data from Contacts namespace
diff --git a/lib/ext/Syncroton/Registry.php b/lib/ext/Syncroton/Registry.php
index 32838a6..c971456 100644
--- a/lib/ext/Syncroton/Registry.php
+++ b/lib/ext/Syncroton/Registry.php
@@ -41,6 +41,7 @@ class Syncroton_Registry extends ArrayObject
const CONTENTSTATEBACKEND = 'contentstatebackend';
const DEVICEBACKEND = 'devicebackend';
const FOLDERBACKEND = 'folderbackend';
+ const POLICYBACKEND = 'policybackend';
const SYNCSTATEBACKEND = 'syncstatebackend';
/**
@@ -238,6 +239,23 @@ class Syncroton_Registry extends ArrayObject
}
/**
+ * returns policy backend
+ *
+ * creates Syncroton_Backend_Policy on the fly if not set before via
+ * Syncroton_Registry::set(self::POLICYBACKEND, $backend);
+ *
+ * @return Syncroton_Backend_ISyncState
+ */
+ public static function getPolicyBackend()
+ {
+ if (!self::isRegistered(self::POLICYBACKEND)) {
+ self::set(self::POLICYBACKEND, new Syncroton_Backend_Policy(self::getDatabase()));
+ }
+
+ return self::get(self::POLICYBACKEND);
+ }
+
+ /**
* returns syncstate backend
*
* creates Syncroton_Backend_SyncState on the fly if not before via
diff --git a/lib/ext/Syncroton/Server.php b/lib/ext/Syncroton/Server.php
index 94fa4a9..862614c 100644
--- a/lib/ext/Syncroton/Server.php
+++ b/lib/ext/Syncroton/Server.php
@@ -137,9 +137,16 @@ class Syncroton_Server
if ($this->_logger instanceof Zend_Log)
$this->_logger->info(__METHOD__ . '::' . __LINE__ . " provisioning needed");
- header("HTTP/1.1 449 Retry after sending a PROVISION command");
-
- return;
+ if (version_compare($device->acsversion, '14.0', '>=')) {
+ $response = $sepn->domDocument;
+ } else {
+ // pre 14.0 method
+ header("HTTP/1.1 449 Retry after sending a PROVISION command");
+
+ return;
+ }
+
+
} catch (Exception $e) {
if ($this->_logger instanceof Zend_Log)
diff --git a/lib/init.php b/lib/init.php
index f137342..3e63921 100644
--- a/lib/init.php
+++ b/lib/init.php
@@ -85,7 +85,6 @@ function kolab_sync_autoload($classname)
// Roundcube Framework
$filename = preg_replace(
array(
- '/MDB2_(.+)/',
'/Mail_(.+)/',
'/Net_(.+)/',
'/Auth_(.+)/',
@@ -93,7 +92,6 @@ function kolab_sync_autoload($classname)
'/^utf8$/',
),
array(
- 'MDB2/\\1',
'Mail/\\1',
'Net/\\1',
'Auth/\\1',
diff --git a/lib/kolab_sync.php b/lib/kolab_sync.php
index 647515d..741fb04 100644
--- a/lib/kolab_sync.php
+++ b/lib/kolab_sync.php
@@ -122,6 +122,7 @@ class kolab_sync extends rcube
Syncroton_Registry::set(Syncroton_Registry::FOLDERBACKEND, new kolab_sync_backend_folder);
Syncroton_Registry::set(Syncroton_Registry::SYNCSTATEBACKEND, new kolab_sync_backend_state);
Syncroton_Registry::set(Syncroton_Registry::CONTENTSTATEBACKEND, new kolab_sync_backend_content);
+ Syncroton_Registry::set(Syncroton_Registry::POLICYBACKEND, new kolab_sync_backend_policy);
Syncroton_Registry::setContactsDataClass('kolab_sync_data_contacts');
Syncroton_Registry::setCalendarDataClass('kolab_sync_data_calendar');
diff --git a/lib/kolab_sync_backend.php b/lib/kolab_sync_backend.php
index d9413fa..8a64878 100644
--- a/lib/kolab_sync_backend.php
+++ b/lib/kolab_sync_backend.php
@@ -92,6 +92,7 @@ class kolab_sync_backend
public function startup()
{
$this->storage = rcube::get_instance()->get_storage();
+
// @TODO: reset cache? if we do this for every request the cache would be useless
// There's no session here
//$this->storage->clear_cache('mailboxes.', true);
@@ -574,9 +575,9 @@ class kolab_sync_backend
// Syncroton folder data array
return array(
- 'folderid' => $folder_id,
- 'parentid' => count($items) ? self::folder_id(implode($delim, $items)) : 0,
- 'displayname' => rcube_charset::convert($name, 'UTF7-IMAP', kolab_sync::CHARSET),
+ 'serverId' => $folder_id,
+ 'parentId' => count($items) ? self::folder_id(implode($delim, $items)) : 0,
+ 'displayName' => rcube_charset::convert($name, 'UTF7-IMAP', kolab_sync::CHARSET),
'type' => self::type_kolab2activesync($type),
);
}
diff --git a/lib/kolab_sync_backend_common.php b/lib/kolab_sync_backend_common.php
new file mode 100644
index 0000000..34e9623
--- /dev/null
+++ b/lib/kolab_sync_backend_common.php
@@ -0,0 +1,212 @@
+<?php
+
+/**
+ +--------------------------------------------------------------------------+
+ | Kolab Sync (ActiveSync for Kolab) |
+ | |
+ | Copyright (C) 2011-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/> |
+ +--------------------------------------------------------------------------+
+ | Author: Aleksander Machniak <machniak at kolabsys.com> |
+ +--------------------------------------------------------------------------+
+*/
+
+/**
+ * Parent backend class for kolab backends
+ */
+class kolab_sync_backend_common implements Syncroton_Backend_IBackend
+{
+ /**
+ * Table name
+ *
+ * @var string
+ */
+ protected $table_name;
+
+ /**
+ * Model interface name
+ *
+ * @var string
+ */
+ protected $interface_name;
+
+ /**
+ * Backend interface name
+ *
+ * @var string
+ */
+ protected $class_name;
+
+ /**
+ * SQL Database engine
+ *
+ * @var rcube_db
+ */
+ protected $db;
+
+
+ /**
+ * Constructor
+ */
+ function __construct()
+ {
+ $this->db = rcube::get_instance()->get_dbh();
+
+ if (empty($this->class_name)) {
+ $this->class_name = str_replace('Model_I', 'Model_', $this->interface_name);
+ }
+ }
+
+ /**
+ * Creates new Syncroton data object in database
+ *
+ * @param Syncroton_Model_* $object
+ * @throws InvalidArgumentException
+ * @return Syncroton_Model_*
+ */
+ public function create($object)
+ {
+ if (! $object instanceof $this->interface_name) {
+ throw new InvalidArgumentException('$object must be instanace of ' . $this->interface_name);
+ }
+
+ $data = $this->object_to_array($object);
+ $insert = array();
+
+ $data['id'] = sha1(mt_rand(). microtime());
+
+ foreach ($data as $key => $value) {
+ $insert[$this->db->quote_identifier($key)] = $this->db->quote($value);
+ }
+
+ $this->db->query('INSERT INTO ' . $this->table_name
+ . ' (' . implode(', ', array_keys($insert)) . ')' . ' VALUES(' . implode(', ', $insert) . ')');
+
+ return $this->get($data['id']);
+ }
+
+ /**
+ * Returns Syncroton data object
+ *
+ * @param string $id
+ * @throws Syncroton_Exception_NotFound
+ * @return Syncroton_Model_*
+ */
+ public function get($id)
+ {
+ $id = $id instanceof $this->interface_name ? $id->id : $id;
+
+ $select = $this->db->query('SELECT * FROM ' . $this->table_name . ' WHERE id = ?', array($id));
+ $data = $this->db->fetch_assoc($select);
+
+ if (empty($data)) {
+ throw new Syncroton_Exception_NotFound('Object not found');
+ }
+
+ return $this->get_object($data);
+ }
+
+ /**
+ * Deletes Syncroton data object
+ *
+ * @param string $id
+ * @return bool
+ */
+ public function delete($id)
+ {
+ $id = $id instanceof $this->interface_name ? $id->id : $id;
+
+ $result = $this->db->query('DELETE FROM ' . $this->table_name .' WHERE id = ?', array($id));
+
+ return (bool) $this->db->affected_rows($result);
+ }
+
+ /**
+ * Updates Syncroton data object
+ *
+ * @param Syncroton_Model_* $object
+ * @throws InvalidArgumentException
+ * @return Syncroton_Model_*
+ */
+ public function update($object)
+ {
+ if (! $object instanceof $this->interface_name) {
+ throw new InvalidArgumentException('$object must be instanace of ' . $this->interface_name);
+ }
+
+ $data = $this->object_to_array($object);
+ $set = array();
+
+ foreach ($data as $key => $value) {
+ $set[] = $this->db->quote_identifier($key) . ' = ' . $this->db->quote($value);
+ }
+
+ $this->db->query('UPDATE ' . $this->table_name . ' SET ' . implode(', ', $set)
+ . ' WHERE ' . $this->db->quote_identifier('id') . ' = ' . $this->db->quote($object->id));
+
+ return $this->get($object->id);
+ }
+
+ /**
+ *
+ */
+ protected function get_object($data)
+ {
+ foreach ($data as $key => $value) {
+ unset($data[$key]);
+
+ if (!empty($value) && preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', $value)) { // 2012-08-12 07:43:26
+ $value = new DateTime($value, new DateTimeZone('utc'));
+ }
+
+ $data[$this->to_camelcase($key, false)] = $value;
+ }
+
+ return new $this->class_name($data);
+ }
+
+ protected function object_to_array($object)
+ {
+ $data = array();
+
+ foreach ($object as $key => $value) {
+ if ($value instanceof DateTime) {
+ $value = $value->format('Y-m-d H:i:s');
+ } elseif (is_object($value) && isset($value->id)) {
+ $value = $value->id;
+ }
+
+ $data[$this->from_camelcase($key)] = $value;
+ }
+
+ return $data;
+ }
+
+ protected function from_camelcase($string)
+ {
+ $string = lcfirst($string);
+
+ return preg_replace_callback('/([A-Z])/', function ($string) { return '_' . strtolower($string[0]); }, $string);
+ }
+
+ protected function to_camelcase($string, $ucFirst = true)
+ {
+ if ($ucFirst) {
+ $string = ucfirst($string);
+ }
+
+ return preg_replace_callback('/_([a-z])/', function ($string) { return strtoupper($string[1]); }, $string);
+ }
+}
diff --git a/lib/kolab_sync_backend_content.php b/lib/kolab_sync_backend_content.php
index 27c2a29..c13a343 100644
--- a/lib/kolab_sync_backend_content.php
+++ b/lib/kolab_sync_backend_content.php
@@ -24,90 +24,29 @@
*/
/**
- *
- * @package Syncroton
- * @subpackage Backend
+ * Kolab backend class for content storage
*/
-class kolab_sync_backend_content implements Syncroton_Backend_IContent
+class kolab_sync_backend_content extends kolab_sync_backend_common implements Syncroton_Backend_IContent
{
- /**
- * the database adapter
- *
- * @var rcube_mdb2
- */
- protected $db;
+ protected $table_name = 'syncroton_content';
+ protected $interface_name = 'Syncroton_Model_IContent';
- public function __construct()
- {
- $this->db = rcube::get_instance()->get_dbh();
- }
-
- /**
- * create new content state
- *
- * @param Syncroton_Model_IContent $_state
- * @return Syncroton_Model_IContent
- */
- public function create(Syncroton_Model_IContent $_state)
- {
- $id = sha1(mt_rand(). microtime());
-
- $deviceId = $_state->device_id instanceof Syncroton_Model_IDevice ? $_state->device_id->id : $_state->device_id;
- $folderId = $_state->folder_id instanceof Syncroton_Model_IFolder ? $_state->folder_id->id : $_state->folder_id;
-
- $insert[$this->db->quote_identifier('id')] = $this->db->quote($id);
- $insert[$this->db->quote_identifier('device_id')] = $this->db->quote($deviceId);
- $insert[$this->db->quote_identifier('folder_id')] = $this->db->quote($folderId);
- $insert[$this->db->quote_identifier('contentid')] = $this->db->quote($_state->contentid);
- $insert[$this->db->quote_identifier('creation_time')] = $this->db->quote($_state->creation_time->format('Y-m-d H:i:s'));
- $insert[$this->db->quote_identifier('creation_synckey')] = $this->db->quote($_state->creation_synckey);
- $insert[$this->db->quote_identifier('is_deleted')] = $this->db->quote(isset($_state->is_deleted) ? (int)!!$_state->is_deleted : 0);
-
- $this->db->query('INSERT INTO syncroton_content '
- . ' (' . implode(', ', array_keys($insert)) . ')' . ' VALUES(' . implode(', ', $insert) . ')');
-
- return $this->get($id);
- }
-
/**
* mark state as deleted. The state gets removed finally,
* when the synckey gets validated during next sync.
*
- * @param Syncroton_Model_IContent|string $_id
+ * @param Syncroton_Model_IContent|string $id
*/
- public function delete($_id)
+ public function delete($id)
{
- $id = $_id instanceof Syncroton_Model_IContent ? $_id->id : $_id;
+ $id = $id instanceof Syncroton_Model_IContent ? $id->id : $id;
- $result = $this->db->query('UPDATE syncroton_content SET is_deleted = 1 WHERE id = ?', array($id));
+ $result = $this->db->query('UPDATE ' . $this->table_name . ' SET is_deleted = 1 WHERE id = ?', array($id));
-// return (bool) $this->db->affected_rows($result);
+ return (bool) $this->db->affected_rows($result);
}
- /**
- * @param string $_id
- * @throws Syncroton_Exception_NotFound
- * @return Syncroton_Model_IContent
- */
- public function get($_id)
- {
- $select = $this->db->query('SELECT * FROM syncroton_content WHERE id = ?', array($_id));
-
- if ($state = $this->db->fetch_assoc($select)) {
- $state = new Syncroton_Model_Content($state);
- }
-
- if (! $state instanceof Syncroton_Model_IContent) {
- throw new Syncroton_Exception_NotFound('id not found');
- }
-
- if (!empty($state->creation_time)) {
- $state->creation_time = new DateTime($state->creation_time, new DateTimeZone('utc'));
- }
-
- return $state;
- }
/**
* @param Syncroton_Model_IDevice|string $_deviceId
@@ -125,21 +64,14 @@ class kolab_sync_backend_content implements Syncroton_Backend_IContent
$where[] = $this->db->quote_identifier('contentid') . ' = ' . $this->db->quote($_contentId);
$where[] = $this->db->quote_identifier('is_deleted') . ' = 0';
- $select = $this->db->query('SELECT * FROM syncroton_content WHERE ' . implode(' AND ', $where));
-
- if ($state = $this->db->fetch_assoc($select)) {
- $state = new Syncroton_Model_Content($state);
- }
-
- if (! $state instanceof Syncroton_Model_IContent) {
- throw new Syncroton_Exception_NotFound('id not found');
- }
+ $select = $this->db->query('SELECT * FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
+ $state = $this->db->fetch_assoc($select);
- if (!empty($state->creation_time)) {
- $state->creation_time = new DateTime($state->creation_time, new DateTimeZone('utc'));
+ if (empty($state)) {
+ throw new Syncroton_Exception_NotFound('Content not found');
}
- return $state;
+ return $this->get_object($state);
}
/**
@@ -158,7 +90,7 @@ class kolab_sync_backend_content implements Syncroton_Backend_IContent
$where[] = $this->db->quote_identifier('folder_id') . ' = ' . $this->db->quote($folderId);
$where[] = $this->db->quote_identifier('is_deleted') . ' = 0';
- $select = $this->db->query('SELECT contentid FROM syncroton_content WHERE ' . implode(' AND ', $where));
+ $select = $this->db->query('SELECT contentid FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
$result = array();
while ($state = $this->db->fetch_assoc($select)) {
@@ -182,6 +114,6 @@ class kolab_sync_backend_content implements Syncroton_Backend_IContent
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where[] = $this->db->quote_identifier('folder_id') . ' = ' . $this->db->quote($folderId);
- $this->db->query('DELETE FROM syncroton_content WHERE ' . implode(' AND ', $where));
+ $this->db->query('DELETE FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
}
}
diff --git a/lib/kolab_sync_backend_device.php b/lib/kolab_sync_backend_device.php
index 2c5e8fe..34a9759 100644
--- a/lib/kolab_sync_backend_device.php
+++ b/lib/kolab_sync_backend_device.php
@@ -24,10 +24,13 @@
*/
/**
- *
+ * Kolab backend class for device storage
*/
-class kolab_sync_backend_device implements Syncroton_Backend_IDevice
+class kolab_sync_backend_device extends kolab_sync_backend_common implements Syncroton_Backend_IDevice
{
+ protected $table_name = 'syncroton_device';
+ protected $interface_name = 'Syncroton_Model_IDevice';
+
/**
* Kolab Sync backend
*
@@ -35,77 +38,61 @@ class kolab_sync_backend_device implements Syncroton_Backend_IDevice
*/
protected $backend;
+
/**
- * the database adapter
- *
- * @var rcube_mdb2
+ * Constructor
*/
- protected $db;
-
-
public function __construct()
{
+ parent::__construct();
$this->backend = kolab_sync_backend::get_instance();
- $this->db = rcube::get_instance()->get_dbh();
}
+
/**
* create new device
*
- * @param Syncroton_Model_IDevice $_device
+ * @param Syncroton_Model_IDevice $device
+ *
* @return Syncroton_Model_IDevice
*/
- public function create(Syncroton_Model_IDevice $device)
+ public function create($device)
{
- $id = sha1(mt_rand() . microtime());
+ $device = parent::create($device);
// Create device entry in kolab backend
$created = $this->backend->device_create(array(
- 'ID' => $id,
+ 'ID' => $device->id,
'TYPE' => $device->devicetype,
), $device->deviceid);
if (!$created) {
- throw new Syncroton_Exception_NotFound('device creation failed');
+ throw new Syncroton_Exception_NotFound('Device creation failed');
}
- $insert[$this->db->quote_identifier('id')] = $this->db->quote($id);
- $insert[$this->db->quote_identifier('deviceid')] = $this->db->quote($device->deviceid);
- $insert[$this->db->quote_identifier('devicetype')] = $this->db->quote($device->devicetype);
- $insert[$this->db->quote_identifier('owner_id')] = $this->db->quote($device->owner_id);
- $insert[$this->db->quote_identifier('policy_id')] = isset($device->policy_id) ? $this->db->quote($device->policy_id) : 1;
- $insert[$this->db->quote_identifier('policykey')] = isset($device->policykey) ? $this->db->quote($device->policykey) : 'NULL';
- $insert[$this->db->quote_identifier('useragent')] = isset($device->useragent) ? $this->db->quote($device->useragent) : "''";
- $insert[$this->db->quote_identifier('acsversion')] = isset($device->acsversion) ? $this->db->quote($device->acsversion) : "''";
- $insert[$this->db->quote_identifier('remotewipe')] = isset($device->remotewipe) ? $this->db->quote($device->remotewipe) : 'NULL';
-
- // Add entry to database
- $this->db->query('INSERT INTO syncroton_device'
- . ' (' . implode(', ', array_keys($insert)) . ')' . ' VALUES(' . implode(', ', $insert) . ')');
-
- return $this->get($id);
+ return $device;
}
+
/**
- * @param string $_id
- * @throws Syncroton_Exception_NotFound
- * @return Syncroton_Model_IDevice
+ * Delete a device
+ *
+ * @param Syncroton_Model_IDevice $device
+ *
+ * @return bool True on success, False on failure
*/
- public function get($id)
+ public function delete($device)
{
- $select = $this->db->query('SELECT * FROM syncroton_device WHERE id = ?', array($id));
-
- if ($device = $this->db->fetch_assoc($select)) {
- $device = new Syncroton_Model_Device($device);
- }
+ $result = $this->backend->device_delete($device->deviceid);
- if (! $device instanceof Syncroton_Model_IDevice) {
- throw new Syncroton_Exception_NotFound('id not found');
+ if ($result) {
+ $result = parent::delete($device);
}
- return $device;
+ return $result;
}
+
/**
* return device for this user
*
@@ -119,15 +106,14 @@ class kolab_sync_backend_device implements Syncroton_Backend_IDevice
$where[] = $this->db->quote_identifier('deviceid') . ' = ' . $this->db->quote($deviceId);
$where[] = $this->db->quote_identifier('owner_id') . ' = ' . $this->db->quote($ownerId);
- $select = $this->db->query('SELECT * FROM syncroton_device WHERE ' . implode(' AND ', $where));
+ $select = $this->db->query('SELECT * FROM ' . $this->table_name . ' WHERE ' . implode(' AND ', $where));
+ $device = $this->db->fetch_assoc($select);
- if ($device = $this->db->fetch_assoc($select)) {
- $device = new Syncroton_Model_Device($device);
+ if (empty($device)) {
+ throw new Syncroton_Exception_NotFound('Device not found');
}
- if (! $device instanceof Syncroton_Model_IDevice) {
- throw new Syncroton_Exception_NotFound('id not found');
- }
+ $device = $this->get_object($device);
// Make sure device exists (could be deleted by the user)
$dev = $this->backend->device_get($deviceId);
@@ -135,37 +121,9 @@ class kolab_sync_backend_device implements Syncroton_Backend_IDevice
// Remove the device (and related cached data) from database
$this->delete($device);
- throw new Syncroton_Exception_NotFound('device not found');
+ throw new Syncroton_Exception_NotFound('Device not found');
}
return $device;
}
-
- public function delete($device)
- {
- $result = $this->backend->device_delete($device->deviceid);
-
- if ($result) {
- $result = $this->db->query('DELETE FROM syncroton_device'
- . ' WHERE ' . $this->db->quote_identifier('id') . ' = ' . $this->db->quote($device->id));
- $result = (bool) $this->db->affected_rows($result);
- }
-
- return $result;
- }
-
- public function update(Syncroton_Model_IDevice $device)
- {
- $set[] = $this->db->quote_identifier('policykey') . ' = ' . (isset($device->policykey) ? $this->db->quote($device->policykey) : 'NULL');
- $set[] = $this->db->quote_identifier('useragent') . ' = ' . (isset($device->useragent) ? $this->db->quote($device->useragent) : "''");
- $set[] = $this->db->quote_identifier('acsversion') . ' = ' . (isset($device->acsversion) ? $this->db->quote($device->acsversion) : "''");
- $set[] = $this->db->quote_identifier('remotewipe') . ' = ' . (isset($device->remotewipe) ? $this->db->quote($device->remotewipe) : 'NULL');
- $set[] = $this->db->quote_identifier('pinglifetime') . ' = ' . (isset($device->pinglifetime) ? $this->db->quote($device->pinglifetime) : 'NULL');
- $set[] = $this->db->quote_identifier('pingfolder') . ' = ' . (isset($device->pingfolder) ? $this->db->quote($device->pingfolder) : 'NULL');
-
- $this->db->query('UPDATE syncroton_device SET ' . implode(', ', $set)
- . ' WHERE ' . $this->db->quote_identifier('id') . ' = ' . $this->db->quote($device->id));
-
- return $this->get($device->id);
- }
}
diff --git a/lib/kolab_sync_backend_folder.php b/lib/kolab_sync_backend_folder.php
index 4fcb295..8b60b18 100644
--- a/lib/kolab_sync_backend_folder.php
+++ b/lib/kolab_sync_backend_folder.php
@@ -24,86 +24,12 @@
*/
/**
- * sql backend class for the folder state
- *
- * @package Syncroton
- * @subpackage Backend
+ * Kolab backend class for the folder state storage
*/
-class kolab_sync_backend_folder implements Syncroton_Backend_IFolder
+class kolab_sync_backend_folder extends kolab_sync_backend_common implements Syncroton_Backend_IFolder
{
- /**
- * the database adapter
- *
- * @var rcube_mdb2
- */
- protected $db;
-
-
- public function __construct()
- {
- $this->db = rcube::get_instance()->get_dbh();
- }
-
- /**
- * create new folder state
- *
- * @param Syncroton_Model_IFolder $_folder
- * @return Syncroton_Model_IFolder
- */
- public function create(Syncroton_Model_IFolder $_folder)
- {
- $id = sha1(mt_rand(). microtime());
- $deviceId = $_folder->device_id instanceof Syncroton_Model_IDevice ? $_folder->device_id->id : $_folder->device_id;
- $folderId = $_folder->folderid instanceof Syncroton_Model_IFolder ? $_folder->folderid->id : $_folder->folderid;
-
- $insert[$this->db->quote_identifier('id')] = $this->db->quote($id);
- $insert[$this->db->quote_identifier('device_id')] = $this->db->quote($deviceId);
- $insert[$this->db->quote_identifier('class')] = $this->db->quote($_folder->class);
- $insert[$this->db->quote_identifier('folderid')] = $this->db->quote($folderId);
- $insert[$this->db->quote_identifier('parentid')] = $this->db->quote($_folder->parentid);
- $insert[$this->db->quote_identifier('displayname')] = $this->db->quote($_folder->displayname);
- $insert[$this->db->quote_identifier('type')] = $this->db->quote($_folder->type);
- $insert[$this->db->quote_identifier('creation_time')] = $this->db->quote($_folder->creation_time->format('Y-m-d H:i:s'));
- $insert[$this->db->quote_identifier('lastfiltertype')] = $this->db->quote($_folder->lastfiltertype);
-
- $this->db->query('INSERT INTO syncroton_folder'
- . ' (' . implode(', ', array_keys($insert)) . ')' . ' VALUES(' . implode(', ', $insert) . ')');
-
- return $this->get($id);
- }
-
- public function delete($_id)
- {
- $id = $_id instanceof Syncroton_Model_IFolder ? $_id->id : $_id;
-
- $result = $this->db->query('DELETE FROM syncroton_folder WHERE id = ?', array($id));
-
- return (bool) $this->db->affected_rows($result);
- }
-
- /**
- * @param string $_id
- * @throws Syncroton_Exception_NotFound
- * @return Syncroton_Model_IFolder
- */
- public function get($_id)
- {
- $select = $this->db->query('SELECT * FROM syncroton_folder WHERE id = ?', array($_id));
-
- if ($state = $this->db->fetch_assoc($select)) {
- $state = new Syncroton_Model_Folder($state);
- }
-
- if (! $state instanceof Syncroton_Model_IFolder) {
- throw new Syncroton_Exception_NotFound('id not found');
- }
-
- if (!empty($state->creation_time)) {
- $state->creation_time = new DateTime($state->creation_time, new DateTimeZone('utc'));
- }
-
- return $state;
- }
+ protected $table_name = 'syncroton_folder';
+ protected $interface_name = 'Syncroton_Model_IFolder';
/**
* delete all stored folderId's for given device
@@ -117,16 +43,9 @@ class kolab_sync_backend_folder implements Syncroton_Backend_IFolder
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
- $this->db->query('DELETE FROM syncroton_folder WHERE ' . implode(' AND ', $where));
+ $this->db->query('DELETE FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
}
- public function update(Syncroton_Model_IFolder $_folder)
- {
- $this->db->query('UPDATE syncroton_folder SET lastfiltertype = ? WHERE id = ?',
- array($_folder->lastfiltertype, $_folder->id));
-
- return $this->get($_folder->id);
- }
/**
* get array of ids which got send to the client for a given class
@@ -143,11 +62,11 @@ class kolab_sync_backend_folder implements Syncroton_Backend_IFolder
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where[] = $this->db->quote_identifier('class') . ' = ' . $this->db->quote($_class);
- $select = $this->db->query('SELECT * FROM syncroton_folder WHERE ' . implode(' AND ', $where));
+ $select = $this->db->query('SELECT * FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
$result = array();
- while ($row = $this->db->fetch_assoc($select)) {
- $result[$row['folderid']] = new Syncroton_Model_Folder($row);
+ while ($folder = $this->db->fetch_assoc($select)) {
+ $result[$folder['folderid']] = $this->get_object($folder);
}
return $result;
@@ -167,20 +86,62 @@ class kolab_sync_backend_folder implements Syncroton_Backend_IFolder
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where[] = $this->db->quote_identifier('folderid') . ' = ' . $this->db->quote($_folderId);
- $select = $this->db->query('SELECT * FROM syncroton_folder WHERE ' . implode(' AND ', $where));
+ $select = $this->db->query('SELECT * FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
+ $folder = $this->db->fetch_assoc($select);
- if ($folder = $this->db->fetch_assoc($select)) {
- $folder = new Syncroton_Model_Folder($folder);
+ if (empty($folder)) {
+ throw new Syncroton_Exception_NotFound('Folder not found');
}
- if (! $folder instanceof Syncroton_Model_IFolder) {
- throw new Syncroton_Exception_NotFound('folder not found');
- }
+ return $this->get_object($folder);
+ }
+
- if (!empty($folder->creation_time)) {
- $folder->creation_time = new DateTime($folder->creation_time, new DateTimeZone('utc'));
+ /**
+ * (non-PHPdoc)
+ * @see kolab_sync_backend_common::from_camelcase()
+ */
+ protected function from_camelcase($string)
+ {
+ switch ($string) {
+ case 'displayName':
+ case 'parentId':
+ return strtolower($string);
+ break;
+
+ case 'serverId':
+ return 'folderid';
+ break;
+
+ default:
+ return parent::from_camelcase($string);
+ break;
}
+ }
- return $folder;
+
+ /**
+ * (non-PHPdoc)
+ * @see kolab_sync_backend_common::to_camelcase()
+ */
+ protected function to_camelcase($string, $ucFirst = true)
+ {
+ switch ($string) {
+ case 'displayname':
+ return 'displayName';
+ break;
+
+ case 'parentid':
+ return 'parentId';
+ break;
+
+ case 'folderid':
+ return 'serverId';
+ break;
+
+ default:
+ return parent::to_camelcase($string, $ucFirst);
+ break;
+ }
}
}
diff --git a/lib/kolab_sync_backend_policy.php b/lib/kolab_sync_backend_policy.php
new file mode 100644
index 0000000..d7b8f09
--- /dev/null
+++ b/lib/kolab_sync_backend_policy.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ +--------------------------------------------------------------------------+
+ | Kolab Sync (ActiveSync for Kolab) |
+ | |
+ | Copyright (C) 2011-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/> |
+ +--------------------------------------------------------------------------+
+ | Author: Aleksander Machniak <machniak at kolabsys.com> |
+ +--------------------------------------------------------------------------+
+*/
+
+/**
+ * sql backend class for policy storage
+ */
+class kolab_sync_backend_policy extends kolab_sync_backend_common //implements Syncroton_Backend_IPolicy
+{
+ protected $table_name = 'syncroton_policy';
+ protected $interface_name = 'Syncroton_Model_IPolicy';
+}
diff --git a/lib/kolab_sync_backend_state.php b/lib/kolab_sync_backend_state.php
index a59ef43..dfd2127 100644
--- a/lib/kolab_sync_backend_state.php
+++ b/lib/kolab_sync_backend_state.php
@@ -24,25 +24,12 @@
*/
/**
- * sql backend class for the folder state
- *
- * @package Syncroton
- * @subpackage Backend
+ * Kolab backend class for the folder state storage
*/
-class kolab_sync_backend_state implements Syncroton_Backend_ISyncState
+class kolab_sync_backend_state extends kolab_sync_backend_common implements Syncroton_Backend_ISyncState
{
- /**
- * the database adapter
- *
- * @var rcube_mdb2
- */
- protected $db;
-
-
- public function __construct()
- {
- $this->db = rcube::get_instance()->get_dbh();
- }
+ protected $table_name = 'syncroton_synckey';
+ protected $interface_name = 'Syncroton_Model_ISyncState';
/**
* create new sync state
@@ -50,31 +37,16 @@ class kolab_sync_backend_state implements Syncroton_Backend_ISyncState
* @param Syncroton_Model_ISyncState $_syncState
* @return Syncroton_Model_SyncState
*/
- public function create(Syncroton_Model_ISyncState $_syncState, $_keepPreviousSyncState = true)
+ public function create($object, $_keepPreviousSyncState = true)
{
- $id = sha1(mt_rand(). microtime());
- $deviceId = $_syncState->device_id instanceof Syncroton_Model_IDevice ? $_syncState->device_id->id : $_syncState->device_id;
- $type = $_syncState->type instanceof Syncroton_Model_IFolder ? $_syncState->type->id : $_syncState->type;
- $data = is_array($_syncState->pendingdata) ? json_encode($_syncState->pendingdata) : null;
-
- $insert[$this->db->quote_identifier('id')] = $this->db->quote($id);
- $insert[$this->db->quote_identifier('device_id')] = $this->db->quote($deviceId);
- $insert[$this->db->quote_identifier('type')] = $this->db->quote($type);
- $insert[$this->db->quote_identifier('counter')] = $this->db->quote($_syncState->counter);
- $insert[$this->db->quote_identifier('lastsync')] = $this->db->quote($_syncState->lastsync->format('Y-m-d H:i:s'));
- $insert[$this->db->quote_identifier('pendingdata')] = $data ? $this->db->quote($data) : 'NULL';
-
- $this->db->query('INSERT INTO syncroton_synckey'
- . ' (' . implode(', ', array_keys($insert)) . ')' . ' VALUES(' . implode(', ', $insert) . ')');
-
- $state = $this->get($id);
+ $object = parent::create($object);
if ($_keepPreviousSyncState !== true) {
// remove all other synckeys
- $this->_deleteOtherStates($state);
+ $this->_deleteOtherStates($object);
}
- return $state;
+ return $object;
}
protected function _deleteOtherStates(Syncroton_Model_ISyncState $_state)
@@ -84,43 +56,42 @@ class kolab_sync_backend_state implements Syncroton_Backend_ISyncState
$where[] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($_state->type);
$where[] = $this->db->quote_identifier('counter') . ' <> ' . $this->db->quote($_state->counter);
- $this->db->query('DELETE FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
+ $this->db->query('DELETE FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
return true;
}
+
/**
- * @param string $_id
- * @throws Syncroton_Exception_NotFound
- * @return Syncroton_Model_SyncState
+ * @see kolab_sync_backend_common::object_to_array()
*/
- public function get($_id)
+ protected function object_to_array($object)
{
- $select = $this->db->query('SELECT * FROM syncroton_synckey WHERE id = ?', array($_id));
+ $data = parent::object_to_array($object);
- if ($state = $this->db->fetch_assoc($select)) {
- $state = new Syncroton_Model_SyncState($state);
+ if (is_array($object->pendingdata)) {
+ $data['pendingdata'] = json_encode($object->pendingdata);
}
- if (! $state instanceof Syncroton_Model_ISyncState) {
- throw new Syncroton_Exception_NotFound('id not found');
- }
-
- $this->_convertFields($state);
-
- return $state;
+ return $data;
}
- protected function _convertFields(Syncroton_Model_SyncState $state)
+
+ /**
+ * @see kolab_sync_backend_common::get_object()
+ */
+ protected function get_object($data)
{
- if (!empty($state->lastsync)) {
- $state->lastsync = new DateTime($state->lastsync, new DateTimeZone('utc'));
- }
- if ($state->pendingdata) {
- $state->pendingdata = json_decode($state->pendingdata);
+ $object = parent::get_object($data);
+
+ if ($object->pendingdata) {
+ $object->pendingdata = json_decode($object->pendingdata);
}
+
+ return $object;
}
+
/**
* always returns the latest syncstate
*
@@ -136,20 +107,16 @@ class kolab_sync_backend_state implements Syncroton_Backend_ISyncState
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where[] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folderId);
- $select = $this->db->limitquery('SELECT * FROM syncroton_synckey WHERE ' . implode(' AND ', $where)
+ $select = $this->db->limitquery('SELECT * FROM ' . $this->table_name . ' WHERE ' . implode(' AND ', $where)
.' ORDER BY counter DESC', 0, 1);
- if ($state = $this->db->fetch_assoc($select)) {
- $state = new Syncroton_Model_SyncState($state);
- }
+ $state = $this->db->fetch_assoc($select);
- if (! $state instanceof Syncroton_Model_ISyncState) {
- throw new Syncroton_Exception_NotFound('id not found');
+ if (empty($state)) {
+ throw new Syncroton_Exception_NotFound('SyncState not found');
}
- $this->_convertFields($state);
-
- return $state;
+ return $this->get_object($state);
}
/**
@@ -166,18 +133,9 @@ class kolab_sync_backend_state implements Syncroton_Backend_ISyncState
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where[] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folderId);
- $this->db->query('DELETE FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
+ $this->db->query('DELETE FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
}
- public function update(Syncroton_Model_ISyncState $_syncState)
- {
- $data = is_array($_syncState->pendingdata) ? json_encode($_syncState->pendingdata) : 'null';
-
- $this->db->query('UPDATE syncroton_synckey SET counter = ?, lastsync = ?, pendingdata = ? WHERE id = ?',
- array($_syncState->counter, $_syncState->lastsync->format('Y-m-d H:i:s'), $data, $_syncState->id));
-
- return $this->get($_syncState->id);
- }
/**
* get array of ids which got send to the client for a given class
@@ -197,16 +155,13 @@ class kolab_sync_backend_state implements Syncroton_Backend_ISyncState
$where['counter'] = $this->db->quote_identifier('counter') . ' = ' . $this->db->quote($_syncKey);
$select = $this->db->query('SELECT * FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
+ $state = $this->db->fetch_assoc($select);
- if ($state = $this->db->fetch_assoc($select)) {
- $state = new Syncroton_Model_SyncState($state);
- }
-
- if (! $state instanceof Syncroton_Model_ISyncState) {
+ if (empty($state)) {
return false;
}
- $this->_convertFields($state);
+ $state = $this->get_object($state);
// check if this was the latest syncKey
$where['counter'] = $this->db->quote_identifier('counter') . ' = ' . $this->db->quote($_syncKey + 1);
@@ -214,7 +169,7 @@ class kolab_sync_backend_state implements Syncroton_Backend_ISyncState
$select = $this->db->query('SELECT * FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
if ($moreRecentState = $this->db->fetch_assoc($select)) {
- $moreRecentState = new Syncroton_Model_SyncState($moreRecentState);
+ $moreRecentState = $this->get_object($moreRecentState);
}
$where = array();
diff --git a/lib/kolab_sync_data.php b/lib/kolab_sync_data.php
index b64568d..3820c24 100644
--- a/lib/kolab_sync_data.php
+++ b/lib/kolab_sync_data.php
@@ -196,7 +196,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
}
if ($default = $this->getDefaultFolder()) {
- $list = array($default['folderid'] => $default);
+ $list = array($default['serverId'] => $default);
}
foreach ($list as $idx => $folder) {
@@ -231,9 +231,9 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
}
// Remember real folder ID and set ID/name to root folder
- $default['realid'] = $default['folderid'];
- $default['folderid'] = $this->defaultRootFolder;
- $default['displayname'] = $this->defaultFolder;
+ $default['realid'] = $default['serverId'];
+ $default['serverId'] = $this->defaultRootFolder;
+ $default['displayName'] = $this->defaultFolder;
return $default;
}
@@ -243,9 +243,9 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
*/
public function createFolder(Syncroton_Model_IFolder $folder)
{
- $parentid = $folder->parentid;
+ $parentid = $folder->parentId;
$type = $folder->type;
- $display_name = $folder->displayname;
+ $display_name = $folder->displayName;
if ($parentid) {
$parent = $this->backend->folder_id2name($parentid, $this->device->deviceid);
@@ -264,7 +264,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
$result = $this->backend->folder_create($name, $type, $this->device->deviceid);
if ($result) {
- $folder->folderid = $this->backend->folder_id($name);
+ $folder->serverId = $this->backend->folder_id($name);
return $folder;
}
@@ -276,10 +276,10 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
*/
public function updateFolder(Syncroton_Model_IFolder $folder)
{
- $parentid = $folder->parentid;
+ $parentid = $folder->parentId;
$type = $folder->type;
- $display_name = $folder->displayname;
- $old_name = $this->backend->folder_id2name($folder->folderid, $this->device->deviceid);
+ $display_name = $folder->displayName;
+ $old_name = $this->backend->folder_id2name($folder->serverId, $this->device->deviceid);
if ($parentid) {
$parent = $this->backend->folder_id2name($parentid, $this->device->deviceid);
@@ -304,7 +304,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
}
if ($result) {
- $folder->folderid = $this->backend->folder_id($name);
+ $folder->serverId = $this->backend->folder_id($name);
return $folder;
}
@@ -317,7 +317,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
public function deleteFolder($folder)
{
if ($folder instanceof Syncroton_Model_IFolder) {
- $folder = $folder->folderid;
+ $folder = $folder->serverId;
}
$name = $this->backend->folder_id2name($folder, $this->device->deviceid);
@@ -594,7 +594,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
// @TODO: Consider looping over all folders here, not in getServerEntries() and
// getChangesEntriesCount(). This way we could break the loop and not check all folders (see @TODO below)
// or at least skip redundant cache sync of the same folder
- $allServerEntries = $this->getServerEntries($folder->folderid, $folder->lastfiltertype);
+ $allServerEntries = $this->getServerEntries($folder->serverId, $folder->lastfiltertype);
$addedEntries = array_diff($allServerEntries, $allClientEntries);
$deletedEntries = array_diff($allClientEntries, $allServerEntries);
@@ -604,7 +604,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
// so in case when count($addedEntries) + count($deletedEntries) != 0 we don't need
// to count changed entries here. We could also revert the order in such case
// and execute getChangedEntriesCount() before
- $changedEntries = $this->getChangedEntriesCount($folder->folderid, $syncState->lastsync);
+ $changedEntries = $this->getChangedEntriesCount($folder->serverId, $syncState->lastsync);
return count($addedEntries) + count($deletedEntries) + $changedEntries;
}
@@ -616,7 +616,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
protected function getObject($folderid, $entryid, &$folder = null)
{
if ($folderid instanceof Syncroton_Model_IFolder) {
- $folderid = $folderid->folderid;
+ $folderid = $folderid->serverId;
}
if ($folderid == $this->defaultRootFolder) {
@@ -651,7 +651,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
{
if ($folderid == $this->defaultRootFolder) {
$default = $this->getDefaultFolder();
- $folderid = isset($default['realid']) ? $default['realid'] : $default['folderid'];
+ $folderid = isset($default['realid']) ? $default['realid'] : $default['serverId'];
}
$foldername = $this->backend->folder_id2name($folderid, $this->device->deviceid);
diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
index 6cdc476..46ec0d6 100644
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -552,7 +552,7 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
}
}
- public function forwardEmail($collectionId, $itemId, $body, $saveInSent)
+ public function forwardEmail($itemId, $body, $saveInSent, $replaceMime)
{
/*
@TODO:
@@ -566,14 +566,6 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
as an attachment to the outgoing message. When the SmartForward command is used for a normal message
or a meeting, the behavior of the SmartForward command is the same as that of the SmartReply command (section 2.2.2.18).
*/
- /*
- @TODO:
- The LongId element is an optional child element of the Source element in SmartForward command requests and
- SmartReply command requests that specifies the long ID for the source message, which is returned in the Search
- command response message (section 2.2.2.14.2). If the LongId element is present, the FolderId (section 2.2.3.69),
- ItemId (section 2.2.3.84), and InstanceId (section 2.2.3.83.2) elements are not present.
- The LongId element value can be up to 256 characters in length.
- */
$msg = $this->parseMessageId($itemId);
$message = $this->getObject($itemId);
@@ -610,7 +602,7 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
}
}
- public function replyEmail($collectionId, $itemId, $body, $saveInSent)
+ public function replyEmail($itemId, $body, $saveInSent, $replaceMime)
{
$msg = $this->parseMessageId($itemId);
$message = $this->getObject($itemId);
@@ -916,6 +908,11 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
*/
protected function parseMessageId($entryid)
{
+ // replyEmail/forwardEmail
+ if (is_array($entryid)) {
+ $entryid = $entryid['itemId'];
+ }
+
list($folderid, $uid) = explode('::', $entryid);
$foldername = $this->backend->folder_id2name($folderid, $this->device->deviceid);
diff --git a/lib/kolab_sync_db.php b/lib/kolab_sync_db.php
index 80ddf72..b56ce52 100644
--- a/lib/kolab_sync_db.php
+++ b/lib/kolab_sync_db.php
@@ -31,7 +31,7 @@ class kolab_sync_db
/**
* the database adapter
*
- * @var rcube_mdb2
+ * @var rcube_db
*/
protected $db;
More information about the commits
mailing list