2 commits - lib/ext lib/kolab_sync_backend.php lib/kolab_sync_data_email.php lib/kolab_sync_data.php
Aleksander Machniak
machniak at kolabsys.com
Tue Oct 9 14:06:45 CEST 2012
lib/ext/Syncroton/Command/FolderCreate.php | 10 -
lib/ext/Syncroton/Command/FolderDelete.php | 67 ++++------
lib/ext/Syncroton/Command/FolderSync.php | 61 +++++----
lib/ext/Syncroton/Command/FolderUpdate.php | 28 ++--
lib/ext/Syncroton/Command/Ping.php | 58 +++++---
lib/ext/Syncroton/Command/Provision.php | 53 +++++--
lib/ext/Syncroton/Command/Search.php | 3
lib/ext/Syncroton/Command/SendMail.php | 2
lib/ext/Syncroton/Command/Settings.php | 27 ++--
lib/ext/Syncroton/Command/Sync.php | 104 ++++++++-------
lib/ext/Syncroton/Command/Wbxml.php | 4
lib/ext/Syncroton/Data/IDataSearch.php | 10 -
lib/ext/Syncroton/Server.php | 194 +++++++++++++++--------------
lib/kolab_sync_backend.php | 25 ++-
lib/kolab_sync_data.php | 64 +++++++--
lib/kolab_sync_data_email.php | 45 ++++++
16 files changed, 452 insertions(+), 303 deletions(-)
New commits:
commit 5fd57443fcefac69be20016d618e1a9df0ef8f1e
Author: Aleksander Machniak <alec at alec.pl>
Date: Tue Oct 9 11:43:08 2012 +0200
Improve backend errors handling (Bug #1088)
diff --git a/lib/kolab_sync_backend.php b/lib/kolab_sync_backend.php
index 659fe6e..1804614 100644
--- a/lib/kolab_sync_backend.php
+++ b/lib/kolab_sync_backend.php
@@ -142,18 +142,22 @@ class kolab_sync_backend
* @param string $deviceid Device identifier
* @param string $type Folder type
*
- * @return array List of mailbox folders
+ * @return array|bool List of mailbox folders, False on backend failure
*/
public function folders_list($deviceid, $type)
{
- $folders_list = array();
-
// get all folders of specified type
$folders = (array) kolab_storage::list_folders('', '*', $type, false, $typedata);
// get folders activesync config
$folderdata = $this->folder_meta();
+ if (!is_array($folders) || !is_array($folderdata)) {
+ return false;
+ }
+
+ $folders_list = array();
+
// check if folders are "subscribed" for activesync
foreach ($folderdata as $folder => $meta) {
if (empty($meta['FOLDER']) || empty($meta['FOLDER'][$deviceid])
@@ -178,7 +182,7 @@ class kolab_sync_backend
/**
* Getter for folder metadata
*
- * @return array Hash array with meta data for each folder
+ * @return array|bool Hash array with meta data for each folder, False on backend failure
*/
public function folder_meta()
{
@@ -187,8 +191,8 @@ class kolab_sync_backend
// get folders activesync config
$folderdata = $this->storage->get_metadata("*", self::ASYNC_KEY);
- if (empty($folderdata)) {
- return $this->folder_meta;
+ if (!is_array($folderdata)) {
+ return false;
}
foreach ($folderdata as $folder => $meta) {
@@ -292,6 +296,11 @@ class kolab_sync_backend
// get folders activesync config
$metadata = $this->folder_meta();
+
+ if (!is_array($metadata)) {
+ return false;
+ }
+
$metadata = $metadata[$name];
if ($flag) {
@@ -676,6 +685,10 @@ class kolab_sync_backend
// get all folders of specified type
$folderdata = $this->folder_meta();
+ if (!is_array($folderdata)) {
+ return null;
+ }
+
// check if folders are "subscribed" for activesync
foreach ($folderdata as $folder => $meta) {
if (empty($meta['FOLDER']) || empty($meta['FOLDER'][$deviceid])
diff --git a/lib/kolab_sync_data.php b/lib/kolab_sync_data.php
index c238a91..2f9fc36 100644
--- a/lib/kolab_sync_data.php
+++ b/lib/kolab_sync_data.php
@@ -194,6 +194,12 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
$list = array($default['serverId'] => $default);
}
+ // getAllFolders() is called only in FolderSync
+ // throw Syncroton_Exception_Status_FolderSync exception
+ if (!is_array($list)) {
+ throw new Syncroton_Exception_Status_FolderSync(Syncroton_Exception_Status_FolderSync::FOLDER_SERVER_ERROR);
+ }
+
foreach ($list as $idx => $folder) {
$list[$idx] = new Syncroton_Model_Folder($folder);
}
@@ -210,7 +216,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
$folders = $this->backend->folders_list($this->device->deviceid, $this->modelName);
if (empty($folders)) {
- return null;
+ return $folders;
}
foreach ($folders as $folder) {
@@ -367,7 +373,10 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
{
$entry = $this->toKolab($entry, $folderId);
$entry = $this->createObject($folderId, $entry);
- // @TODO: throw exception on error
+
+ if (empty($entry)) {
+ throw new Syncroton_Exception_Status_Sync(Syncroton_Exception_Status_Sync::SYNC_SERVER_ERROR);
+ }
return $entry['uid'];
}
@@ -391,7 +400,10 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
$entry = $this->toKolab($entry, $folderId, $oldEntry);
$entry = $this->updateObject($folderId, $serverId, $entry);
- // @TODO: throw exception on error
+
+ if (empty($entry)) {
+ throw new Syncroton_Exception_Status_Sync(Syncroton_Exception_Status_Sync::SYNC_SERVER_ERROR);
+ }
return $entry['uid'];
}
@@ -405,7 +417,11 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
*/
public function deleteEntry($folderId, $serverId, $collectionData)
{
- $this->deleteObject($folderId, $serverId);
+ $deleted = $this->deleteObject($folderId, $serverId);
+
+ if (!$deleted) {
+ throw new Syncroton_Exception_Status_Sync(Syncroton_Exception_Status_Sync::SYNC_SERVER_ERROR);
+ }
}
@@ -429,6 +445,11 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
{
if ($folderid == $this->defaultRootFolder) {
$folders = $this->backend->folders_list($this->device->deviceid, $this->modelName);
+
+ if (!is_array($folders)) {
+ throw new Syncroton_Exception_Status(Syncroton_Exception_Status::SERVER_ERROR);
+ }
+
$folders = array_keys($folders);
}
else {
@@ -500,9 +521,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
*/
public function getChangedEntries($folderId, DateTime $start, DateTime $end = null)
{
- $filter = array();
-
- $filter[] = array('changed', '>', $start);
+ $filter = array(array('changed', '>', $start));
if ($endTimeStamp) {
$filter[] = array('changed', '<=', $end);
@@ -524,9 +543,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
*/
public function getChangedEntriesCount($folderId, DateTime $start, DateTime $end = null)
{
- $filter = array();
-
- $filter[] = array('changed', '>', $start);
+ $filter = array(array('changed', '>', $start));
if ($endTimeStamp) {
$filter[] = array('changed', '<=', $end);
@@ -605,6 +622,11 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
if ($folderid == $this->defaultRootFolder) {
$folders = $this->backend->folders_list($this->device->deviceid, $this->modelName);
+
+ if (!is_array($folders)) {
+ return null;
+ }
+
$folders = array_keys($folders);
}
else {
@@ -620,7 +642,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
$folder = $this->getFolderObject($foldername);
- if ($object = $folder->get_object($entryid)) {
+ if ($folder && ($object = $folder->get_object($entryid))) {
$object['_folderid'] = $folderid;
return $object;
@@ -635,13 +657,18 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
{
if ($folderid == $this->defaultRootFolder) {
$default = $this->getDefaultFolder();
+
+ if (!is_array($default)) {
+ return null;
+ }
+
$folderid = isset($default['realid']) ? $default['realid'] : $default['serverId'];
}
$foldername = $this->backend->folder_id2name($folderid, $this->device->deviceid);
$folder = $this->getFolderObject($foldername);
- if ($folder->save($data)) {
+ if ($folder && $folder->save($data)) {
return $data;
}
}
@@ -656,7 +683,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
if ($object) {
$folder = $this->getFolderObject($object['_mailbox']);
- if ($folder->save($data)) {
+ if ($folder && $folder->save($data)) {
return $data;
}
}
@@ -671,7 +698,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
if ($object) {
$folder = $this->getFolderObject($object['_mailbox']);
- return $folder->delete($entryid);
+ return $folder && $folder->delete($entryid);
}
}
@@ -684,6 +711,10 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
*/
protected function getFolderObject($name)
{
+ if ($name === null) {
+ return null;
+ }
+
if (!isset($this->folders[$name])) {
$this->folders[$name] = kolab_storage::get_folder($name);
}
@@ -701,6 +732,11 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
protected function getFolderConfig($name)
{
$metadata = $this->backend->folder_meta();
+
+ if (!is_array($metadata)) {
+ return array();
+ }
+
$deviceid = $this->device->deviceid;
$config = $metadata[$name]['FOLDER'][$deviceid];
diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
index a041d7f..e197b23 100644
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -409,6 +409,10 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
{
$list = $this->backend->folders_list($this->device->deviceid, $this->modelName);
+ if (!is_array($list)) {
+ throw new Syncroton_Exception_Status_FolderSync(Syncroton_Esception_Status_FolderSync::FOLDER_SERVER_ERROR);
+ }
+
// device doesn't support multiple folders
if (!in_array(strtolower($this->device->devicetype), array('iphone', 'ipad', 'thundertine', 'windowsphone'))) {
// We'll return max. one folder of supported type
@@ -448,6 +452,10 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
$list = $this->backend->folders_list($this->device->deviceid, $this->modelName);
$result = array();
+ if (!is_array($list)) {
+ throw new Syncroton_Exception_NotFound('Folder not found');
+ }
+
// device supports multiple folders?
if (in_array(strtolower($this->device->devicetype), array('iphone', 'ipad', 'thundertine', 'windowsphone'))) {
if ($list[$folder_id]) {
@@ -527,8 +535,13 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
*/
public function updateEntry($folderId, $serverId, Syncroton_Model_IEntry $entry)
{
- $msg = $this->parseMessageId($serverId);
- $message = $this->getObject($serverId);
+ $msg = $this->parseMessageId($serverId);
+ $message = $this->getObject($serverId);
+
+ if (empty($message)) {
+ throw new Syncroton_Exception_Status_Sync(Syncroton_Exception_Status_Sync::SYNC_SERVER_ERROR);
+ }
+
$is_flagged = !empty($message->headers->flags['FLAGGED']);
// Read status change
@@ -563,6 +576,10 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
$trash = kolab_sync::get_instance()->config->get('trash_mbox');
$msg = $this->parseMessageId($serverId);
+ if (empty($msg)) {
+ throw new Syncroton_Exception_Status_Sync(Syncroton_Exception_Status_Sync::SYNC_SERVER_ERROR);
+ }
+
// move message to trash folder
if ($collection->deletesAsMoves
&& strlen($trash)
@@ -632,6 +649,10 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
$msg = $this->parseMessageId($itemId);
$message = $this->getObject($itemId);
+ if (!$message) {
+ throw new Syncroton_Exception_Status(Syncroton_Exception_Status::ITEM_NOT_FOUND);
+ }
+
// Parse message
list($headers, $body) = $this->backend->parse_mime($body, true);
@@ -677,6 +698,10 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
$msg = $this->parseMessageId($itemId);
$message = $this->getObject($itemId);
+ if (!$message) {
+ throw new Syncroton_Exception_Status(Syncroton_Exception_Status::ITEM_NOT_FOUND);
+ }
+
// Parse message
// @TODO: messages with attachments
list($headers, $body) = $this->backend->parse_mime($body, true);
@@ -799,6 +824,10 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
throw new Exception('Empty/invalid search request');
}
+ if (!is_array($folders)) {
+ throw new Syncroton_Exception_Status(Syncroton_Exception_Status::SERVER_ERROR);
+ }
+
$result = array();
// no sorting for best performance
$sort_by = null;
@@ -928,7 +957,10 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
// @TODO: DeepTraversal
if (empty($folders)) {
$folders = $this->backend->folders_list($this->device->deviceid, $this->modelName);
- $folders = array_keys($folders);
+
+ if (is_array($folders)) {
+ $folders = array_keys($folders);
+ }
}
return array($folders, $search_str);
@@ -962,7 +994,12 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
{
list($folderid, $uid, $part_id) = explode('::', $fileReference);
- $message = $this->getObject($fileReference);
+ $message = $this->getObject($fileReference);
+
+ if (!$message) {
+ throw new Syncroton_Exception_NotFound('Message not found');
+ }
+
$part = $message->mime_parts[$part_id];
$body = $message->get_part_content($part_id);
$content_type = $part->mimetype;
commit 607f8b195acf08c17a22885ca0dd75b6e17de981
Author: Aleksander Machniak <alec at alec.pl>
Date: Mon Oct 8 12:14:04 2012 +0200
Update Syncroton with some small improvements and fixes
diff --git a/lib/ext/Syncroton/Command/FolderCreate.php b/lib/ext/Syncroton/Command/FolderCreate.php
index 1932848..d87cd9d 100644
--- a/lib/ext/Syncroton/Command/FolderCreate.php
+++ b/lib/ext/Syncroton/Command/FolderCreate.php
@@ -20,13 +20,6 @@ class Syncroton_Command_FolderCreate extends Syncroton_Command_Wbxml
protected $_defaultNameSpace = 'uri:FolderHierarchy';
protected $_documentElement = 'FolderCreate';
- protected $_classes = array(
- Syncroton_Data_Factory::CLASS_CALENDAR,
- Syncroton_Data_Factory::CLASS_CONTACTS,
- Syncroton_Data_Factory::CLASS_EMAIL,
- Syncroton_Data_Factory::CLASS_TASKS
- );
-
/**
*
* @var Syncroton_Model_Folder
@@ -47,9 +40,6 @@ class Syncroton_Command_FolderCreate extends Syncroton_Command_Wbxml
$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;
}
diff --git a/lib/ext/Syncroton/Command/FolderDelete.php b/lib/ext/Syncroton/Command/FolderDelete.php
index 4259ea8..048372b 100644
--- a/lib/ext/Syncroton/Command/FolderDelete.php
+++ b/lib/ext/Syncroton/Command/FolderDelete.php
@@ -20,14 +20,10 @@ class Syncroton_Command_FolderDelete extends Syncroton_Command_Wbxml
protected $_defaultNameSpace = 'uri:FolderHierarchy';
protected $_documentElement = 'FolderDelete';
- protected $_classes = array(
- Syncroton_Data_Factory::CLASS_CALENDAR,
- Syncroton_Data_Factory::CLASS_CONTACTS,
- Syncroton_Data_Factory::CLASS_EMAIL,
- Syncroton_Data_Factory::CLASS_TASKS
- );
-
- protected $_serverId;
+ /**
+ * @var Syncroton_Model_SyncState
+ */
+ protected $_folder;
/**
* @var Syncroton_Model_ISyncState
@@ -36,38 +32,41 @@ class Syncroton_Command_FolderDelete extends Syncroton_Command_Wbxml
/**
* parse FolderDelete request
- *
*/
public function handle()
{
$xml = simplexml_import_dom($this->_requestBody);
- $syncKey = (int)$xml->SyncKey;
-
+ // parse xml request
+ $syncKey = (int)$xml->SyncKey;
+ $serverId = (string)$xml->ServerId;
+
if ($this->_logger instanceof Zend_Log)
$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;
}
- $serverId = (string)$xml->ServerId;
-
try {
- $this->_folder = $this->_folderBackend->getFolder($this->_device, $serverId);
+ $folder = $this->_folderBackend->getFolder($this->_device, $serverId);
- $dataController = Syncroton_Data_Factory::factory($this->_folder->class, $this->_device, $this->_syncTimeStamp);
+ $dataController = Syncroton_Data_Factory::factory($folder->class, $this->_device, $this->_syncTimeStamp);
- $dataController->deleteFolder($this->_folder);
- $this->_folderBackend->delete($this->_folder);
+ // delete folder in data backend
+ $dataController->deleteFolder($folder);
} catch (Syncroton_Exception_NotFound $senf) {
if ($this->_logger instanceof Zend_Log)
$this->_logger->debug(__METHOD__ . '::' . __LINE__ . " " . $senf->getMessage());
+
+ return;
}
+
+ // delete folder in syncState backend
+ $this->_folderBackend->delete($folder);
+
+ $this->_folder = $folder;
}
/**
@@ -84,23 +83,19 @@ class Syncroton_Command_FolderDelete extends Syncroton_Command_Wbxml
$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));
+ } elseif (!$this->_folder instanceof Syncroton_Model_IFolder) {
+ $folderDelete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', Syncroton_Command_FolderSync::STATUS_FOLDER_NOT_FOUND));
+
} 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));
-
- } else {
- // create xml output
- $folderDelete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', Syncroton_Command_FolderSync::STATUS_FOLDER_NOT_FOUND));
- $folderDelete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'SyncKey', $this->_syncState->counter));
- }
+ $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));
}
return $this->_outputDom;
diff --git a/lib/ext/Syncroton/Command/FolderSync.php b/lib/ext/Syncroton/Command/FolderSync.php
index 99be44c..8c4917d 100644
--- a/lib/ext/Syncroton/Command/FolderSync.php
+++ b/lib/ext/Syncroton/Command/FolderSync.php
@@ -31,7 +31,6 @@ class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml
/**
* some usefull constants for working with the xml files
- *
*/
const FOLDERTYPE_GENERIC_USER_CREATED = 1;
const FOLDERTYPE_INBOX = 2;
@@ -115,12 +114,10 @@ class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml
return $this->_outputDom;
}
-
- $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', self::STATUS_SUCCESS));
-
+
$adds = array();
$deletes = array();
-
+
foreach($this->_classes as $class) {
try {
$dataController = Syncroton_Data_Factory::factory($class, $this->_device, $this->_syncTimeStamp);
@@ -130,25 +127,45 @@ class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml
$this->_logger->info(__METHOD__ . '::' . __LINE__ . " no data backend defined for class: " . $class);
continue;
}
-
- // retrieve all folders available in data backend
- $serverFolders = $dataController->getAllFolders();
-
- // retrieve all folders sent to client
- $clientFolders = $this->_folderBackend->getFolderState($this->_device, $class);
-
+
+ try {
+ // retrieve all folders available in data backend
+ $serverFolders = $dataController->getAllFolders();
+
+ // retrieve all folders sent to client
+ $clientFolders = $this->_folderBackend->getFolderState($this->_device, $class);
+
+ } catch (Exception $e) {
+ if ($this->_logger instanceof Zend_Log)
+ $this->_logger->crit(__METHOD__ . '::' . __LINE__ . " Syncing folder hierarchy failed: " . $e->getMessage());
+ if ($this->_logger instanceof Zend_Log)
+ $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " Syncing folder hierarchy failed: " . $e->getTraceAsString());
+
+ // The Status element is global for all collections. If one collection fails,
+ // a failure status MUST be returned for all collections.
+ if ($e instanceof Syncroton_Exception_Status) {
+ $status = $e->getCode();
+ } else {
+ $status = Syncroton_Exception_Status_FolderSync::UNKNOWN_ERROR;
+ }
+
+ $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', $status));
+
+ return $this->_outputDom;
+ }
+
$serverFoldersIds = array_keys($serverFolders);
-
+
// is this the first sync?
- if($this->_syncState->counter == 0) {
+ if ($this->_syncState->counter == 0) {
$clientFoldersIds = array();
} else {
$clientFoldersIds = array_keys($clientFolders);
- }
-
+ }
+
// calculate added entries
$serverDiff = array_diff($serverFoldersIds, $clientFoldersIds);
- foreach($serverDiff as $serverFolderId) {
+ foreach ($serverDiff as $serverFolderId) {
// have we created a folderObject in syncroton_folder before?
if (isset($clientFolders[$serverFolderId])) {
$add = $clientFolders[$serverFolderId];
@@ -159,17 +176,19 @@ class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml
unset($add->id);
}
$add->class = $class;
-
+
$adds[] = $add;
}
-
+
// calculate deleted entries
$serverDiff = array_diff($clientFoldersIds, $serverFoldersIds);
- foreach($serverDiff as $serverFolderId) {
+ foreach ($serverDiff as $serverFolderId) {
$deletes[] = $clientFolders[$serverFolderId];
}
}
-
+
+ $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', self::STATUS_SUCCESS));
+
$count = count($adds) + /*count($changes) + */count($deletes);
if($count > 0) {
$this->_syncState->counter++;
diff --git a/lib/ext/Syncroton/Command/FolderUpdate.php b/lib/ext/Syncroton/Command/FolderUpdate.php
index d219ede..55d1e54 100644
--- a/lib/ext/Syncroton/Command/FolderUpdate.php
+++ b/lib/ext/Syncroton/Command/FolderUpdate.php
@@ -21,6 +21,11 @@ class Syncroton_Command_FolderUpdate extends Syncroton_Command_Wbxml
protected $_documentElement = 'FolderUpdate';
/**
+ * @var Syncroton_Model_SyncState
+ */
+ protected $_folder;
+
+ /**
*
* @var Syncroton_Model_Folder
*/
@@ -40,34 +45,34 @@ class Syncroton_Command_FolderUpdate extends Syncroton_Command_Wbxml
$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;
}
- $folderUpdate = new Syncroton_Model_Folder($xml);
+ $updatedFolder = new Syncroton_Model_Folder($xml);
if ($this->_logger instanceof Zend_Log)
- $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " parentId: {$folderUpdate->parentId} displayName: {$folderUpdate->displayName}");
+ $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " parentId: {$updatedFolder->parentId} displayName: {$updatedFolder->displayName}");
try {
- $folder = $this->_folderBackend->getFolder($this->_device, $folderUpdate->serverId);
+ $folder = $this->_folderBackend->getFolder($this->_device, $updatedFolder->serverId);
- $folder->displayName = $folderUpdate->displayName;
- $folder->parentId = $folderUpdate->parentId;
+ $folder->displayName = $updatedFolder->displayName;
+ $folder->parentId = $updatedFolder->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) {
if ($this->_logger instanceof Zend_Log)
$this->_logger->debug(__METHOD__ . '::' . __LINE__ . " " . $senf->getMessage());
+
+ return;
}
+
+ // update folder status in Syncroton backend
+ $this->_folder = $this->_folderBackend->update($folder);
}
/**
@@ -84,6 +89,9 @@ class Syncroton_Command_FolderUpdate extends Syncroton_Command_Wbxml
$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));
+ } elseif (!$this->_folder instanceof Syncroton_Model_IFolder) {
+ $folderUpdate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', Syncroton_Command_FolderSync::STATUS_FOLDER_NOT_FOUND));
+
} else {
$this->_syncState->counter++;
$this->_syncState->lastsync = $this->_syncTimeStamp;
diff --git a/lib/ext/Syncroton/Command/Ping.php b/lib/ext/Syncroton/Command/Ping.php
index e0c101e..52a2140 100644
--- a/lib/ext/Syncroton/Command/Ping.php
+++ b/lib/ext/Syncroton/Command/Ping.php
@@ -30,17 +30,25 @@ class Syncroton_Command_Ping extends Syncroton_Command_Wbxml
protected $_changesDetected = false;
- const PING_TIMEOUT = 60;
+ /**
+ *
+ * @var int
+ */
+ public static $pingTimeout = 60;
+
+ /**
+ *
+ * @var int
+ */
+ public static $quietTime = 180;
/**
- * Enter description here...
- *
* @var Syncroton_Backend_StandAlone_Abstract
*/
protected $_dataBackend;
protected $_defaultNameSpace = 'uri:Ping';
- protected $_documentElement = 'Ping';
+ protected $_documentElement = 'Ping';
protected $_foldersWithChanges = array();
@@ -72,7 +80,7 @@ class Syncroton_Command_Ping extends Syncroton_Command_Wbxml
// does the folder exist?
$folder = $this->_folderBackend->getFolder($this->_device, (string)$folderXml->Id);
- $folders[] = $folder;
+ $folders[$folder->id] = $folder;
} catch (Syncroton_Exception_NotFound $senf) {
if ($this->_logger instanceof Zend_Log)
$this->_logger->debug(__METHOD__ . '::' . __LINE__ . " " . $senf->getMessage());
@@ -80,7 +88,7 @@ class Syncroton_Command_Ping extends Syncroton_Command_Wbxml
break;
}
}
- $this->_device->pingfolder = serialize($folders);
+ $this->_device->pingfolder = serialize(array_keys($folders));
}
$this->_device = $this->_deviceBackend->update($this->_device);
}
@@ -95,17 +103,33 @@ class Syncroton_Command_Ping extends Syncroton_Command_Wbxml
if ($this->_logger instanceof Zend_Log)
$this->_logger->debug(__METHOD__ . '::' . __LINE__ . " Folders to monitor($lifeTime / $intervalStart / $intervalEnd / $status): " . print_r($folders, true));
- if($status === self::STATUS_NO_CHANGES_FOUND) {
+ if ($status === self::STATUS_NO_CHANGES_FOUND) {
$folderWithChanges = array();
do {
- foreach((array) $folders as $folder) {
+ sleep(self::$pingTimeout);
+
+ $now = new DateTime('now', new DateTimeZone('utc'));
+
+ foreach ((array) $folders as $folderId) {
+ $folder = $this->_folderBackend->get($folderId);
+
$dataController = Syncroton_Data_Factory::factory($folder->class, $this->_device, $this->_syncTimeStamp);
try {
$syncState = $this->_syncStateBackend->getSyncState($this->_device, $folder);
-
+
+ // another process synchronized data of this folder already. let's skip it
+ if ($syncState->lastsync > $this->_syncTimeStamp) {
+ continue;
+ }
+
+ // safe battery time by skipping folders which got synchronied less than self::$quietTime seconds ago
+ if (($now->getTimestamp() - $syncState->lastsync->getTimestamp()) < self::$quietTime) {
+ continue;
+ }
+
$foundChanges = !!$dataController->getCountOfChanges($this->_contentStateBackend, $folder, $syncState);
} catch (Syncroton_Exception_NotFound $e) {
@@ -118,28 +142,22 @@ class Syncroton_Command_Ping extends Syncroton_Command_Wbxml
$foundChanges = true;
}
- if($foundChanges == true) {
+ if ($foundChanges == true) {
$this->_foldersWithChanges[] = $folder;
$status = self::STATUS_CHANGES_FOUND;
}
}
- if($status === self::STATUS_CHANGES_FOUND) {
- break;
- }
-
- // another process synchronized data already
- if(isset($syncState) && $syncState->lastsync > $this->_syncTimeStamp) {
- if ($this->_logger instanceof Zend_Log)
- $this->_logger->info(__METHOD__ . '::' . __LINE__ . " terminate ping process. Some other process updated data already.");
+ if ($status === self::STATUS_CHANGES_FOUND) {
break;
}
- sleep(self::PING_TIMEOUT);
$secondsLeft = $intervalEnd - time();
+
if ($this->_logger instanceof Zend_Log)
$this->_logger->debug(__METHOD__ . '::' . __LINE__ . " DeviceId: " . $this->_device->deviceid . " seconds left: " . $secondsLeft);
- } while($secondsLeft > 0);
+
+ } while ($secondsLeft > 0);
}
if ($this->_logger instanceof Zend_Log)
diff --git a/lib/ext/Syncroton/Command/Provision.php b/lib/ext/Syncroton/Command/Provision.php
index 417267c..a3e7328 100644
--- a/lib/ext/Syncroton/Command/Provision.php
+++ b/lib/ext/Syncroton/Command/Provision.php
@@ -20,7 +20,6 @@ class Syncroton_Command_Provision extends Syncroton_Command_Wbxml
protected $_defaultNameSpace = 'uri:Provision';
protected $_documentElement = 'Provision';
- const POLICYTYPE_XML = 'MS-WAP-Provisioning-XML';
const POLICYTYPE_WBXML = 'MS-EAS-Provisioning-WBXML';
const STATUS_SUCCESS = 1;
@@ -28,6 +27,12 @@ class Syncroton_Command_Provision extends Syncroton_Command_Wbxml
const STATUS_GENERAL_SERVER_ERROR = 3;
const STATUS_DEVICE_MANAGED_EXTERNALLY = 4;
+ const STATUS_POLICY_SUCCESS = 1;
+ const STATUS_POLICY_NOPOLICY = 2;
+ const STATUS_POLICY_UNKNOWNTYPE = 3;
+ const STATUS_POLICY_CORRUPTED = 4;
+ const STATUS_POLICY_WRONGPOLICYKEY = 5;
+
const REMOTEWIPE_REQUESTED = 1;
const REMOTEWIPE_CONFIRMED = 2;
@@ -35,7 +40,11 @@ class Syncroton_Command_Provision extends Syncroton_Command_Wbxml
protected $_policyType;
protected $_sendPolicyKey;
- protected $_deviceInformationSet = false;
+
+ /**
+ * @var Syncroton_Model_DeviceInformation
+ */
+ protected $_deviceInformation;
/**
* process the XML file and add, change, delete or fetches data
@@ -57,8 +66,17 @@ class Syncroton_Command_Provision extends Syncroton_Command_Wbxml
// 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;
+ $this->_deviceInformation = new Syncroton_Model_DeviceInformation($settings->DeviceInformation->Set);
+
+ $this->_device->model = $this->_deviceInformation->model;
+ $this->_device->imei = $this->_deviceInformation->iMEI;
+ $this->_device->friendlyname = $this->_deviceInformation->friendlyName;
+ $this->_device->os = $this->_deviceInformation->oS;
+ $this->_device->oslanguage = $this->_deviceInformation->oSLanguage;
+ $this->_device->phonenumber = $this->_deviceInformation->phoneNumber;
+
+ $this->_device = $this->_deviceBackend->update($this->_device);
+
}
}
@@ -105,31 +123,38 @@ class Syncroton_Command_Provision extends Syncroton_Command_Wbxml
if ($this->_logger instanceof Zend_Log)
$this->_logger->info(__METHOD__ . '::' . __LINE__ . ' send policy to device');
- $this->_device->policykey = $this->generatePolicyKey();
-
$provision = $sync = $this->_outputDom->documentElement;
- if ($this->_deviceInformationSet === true) {
+ $provision->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Status', 1));
+
+ // settings
+ if ($this->_deviceInformation instanceof Syncroton_Model_DeviceInformation) {
$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
$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'));
+
+ if ($this->_policyType != self::POLICYTYPE_WBXML) {
+ $policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Status', self::STATUS_POLICY_UNKNOWNTYPE));
+ } elseif (empty($this->_device->policyId)) {
+ $policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Status', self::STATUS_POLICY_NOPOLICY));
} else {
+ $this->_device->policykey = $this->generatePolicyKey();
+
+ $policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Status', self::STATUS_POLICY_SUCCESS));
+ $policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'PolicyKey', $this->_device->policykey));
+
$data = $policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Data'));
$easProvisionDoc = $data->appendChild($this->_outputDom->createElementNS('uri:Provision', 'EASProvisionDoc'));
$this->_policyBackend
->get($this->_device->policyId)
->appendXML($easProvisionDoc, $this->_device);
+
+ $this->_deviceBackend->update($this->_device);
}
-
- $this->_deviceBackend->update($this->_device);
}
/**
diff --git a/lib/ext/Syncroton/Command/Search.php b/lib/ext/Syncroton/Command/Search.php
index cf9eddd..4913785 100644
--- a/lib/ext/Syncroton/Command/Search.php
+++ b/lib/ext/Syncroton/Command/Search.php
@@ -57,12 +57,9 @@ class Syncroton_Command_Search extends Syncroton_Command_Wbxml
}
try {
- $options = $this->_store->options;
-
// Search
$storeResponse = $dataController->search($this->_store);
$storeResponse->status = self::STATUS_SUCCESS;
-
} catch (Exception $e) {
if ($this->_logger instanceof Zend_Log)
$this->_logger->debug(__METHOD__ . '::' . __LINE__ . " search exception: " . $e->getMessage());
diff --git a/lib/ext/Syncroton/Command/SendMail.php b/lib/ext/Syncroton/Command/SendMail.php
index 603a61f..c25f813 100644
--- a/lib/ext/Syncroton/Command/SendMail.php
+++ b/lib/ext/Syncroton/Command/SendMail.php
@@ -33,7 +33,7 @@ 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'];
$this->_replaceMime = false;
$this->_source = array(
diff --git a/lib/ext/Syncroton/Command/Settings.php b/lib/ext/Syncroton/Command/Settings.php
index 6d779e3..e322355 100644
--- a/lib/ext/Syncroton/Command/Settings.php
+++ b/lib/ext/Syncroton/Command/Settings.php
@@ -30,8 +30,11 @@ class Syncroton_Command_Settings extends Syncroton_Command_Wbxml
protected $_defaultNameSpace = 'uri:Settings';
protected $_documentElement = 'Settings';
- protected $_deviceInformationSet = false;
- protected $_userInformationRequested = false;
+ /**
+ * @var Syncroton_Model_DeviceInformation
+ */
+ protected $_deviceInformation;
+ protected $_userInformationRequested = false;
/**
@@ -43,15 +46,15 @@ class Syncroton_Command_Settings extends Syncroton_Command_Wbxml
$xml = simplexml_import_dom($this->_requestBody);
if(isset($xml->DeviceInformation->Set)) {
- $this->_deviceInformationSet = true;
-
- $this->_device->model = (string)$xml->DeviceInformation->Set->Model;
- $this->_device->imei = (string)$xml->DeviceInformation->Set->IMEI;
- $this->_device->friendlyname = (string)$xml->DeviceInformation->Set->FriendlyName;
- $this->_device->os = (string)$xml->DeviceInformation->Set->OS;
- $this->_device->oslanguage = (string)$xml->DeviceInformation->Set->OSLanguage;
- $this->_device->phonenumber = (string)$xml->DeviceInformation->Set->PhoneNumber;
-
+ $this->_deviceInformation = new Syncroton_Model_DeviceInformation($xml->DeviceInformation->Set);
+
+ $this->_device->model = $this->_deviceInformation->model;
+ $this->_device->imei = $this->_deviceInformation->iMEI;
+ $this->_device->friendlyname = $this->_deviceInformation->friendlyName;
+ $this->_device->os = $this->_deviceInformation->oS;
+ $this->_device->oslanguage = $this->_deviceInformation->oSLanguage;
+ $this->_device->phonenumber = $this->_deviceInformation->phoneNumber;
+
$this->_device = $this->_deviceBackend->update($this->_device);
}
@@ -71,7 +74,7 @@ class Syncroton_Command_Settings extends Syncroton_Command_Wbxml
$settings->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Status', self::STATUS_SUCCESS));
- if($this->_deviceInformationSet === true) {
+ if ($this->_deviceInformation instanceof Syncroton_Model_DeviceInformation) {
$deviceInformation = $settings->appendChild($this->_outputDom->createElementNS('uri:Settings', 'DeviceInformation'));
$set = $deviceInformation->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Set'));
$set->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Status', self::STATUS_SUCCESS));
diff --git a/lib/ext/Syncroton/Command/Sync.php b/lib/ext/Syncroton/Command/Sync.php
index ea28966..3d6ddd6 100644
--- a/lib/ext/Syncroton/Command/Sync.php
+++ b/lib/ext/Syncroton/Command/Sync.php
@@ -460,58 +460,72 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
$serverModifications = $collectionData->syncState->pendingdata;
} else {
- // fetch entries added since last sync
- $allClientEntries = $this->_contentStateBackend->getFolderState($this->_device, $collectionData->folder);
- $allServerEntries = $dataController->getServerEntries($collectionData->collectionId, $collectionData->options['filterType']);
-
- // add entries
- $serverDiff = array_diff($allServerEntries, $allClientEntries);
- // add entries which produced problems during delete from client
- $serverModifications['added'] = $clientModifications['forceAdd'];
- // add entries not yet sent to client
- $serverModifications['added'] = array_unique(array_merge($serverModifications['added'], $serverDiff));
-
- # @todo still needed?
- foreach($serverModifications['added'] as $id => $serverId) {
- // skip entries added by client during this sync session
- if(isset($clientModifications['added'][$serverId]) && !isset($clientModifications['forceAdd'][$serverId])) {
- if ($this->_logger instanceof Zend_Log)
- $this->_logger->info(__METHOD__ . '::' . __LINE__ . " skipped added entry: " . $serverId);
- unset($serverModifications['added'][$id]);
- }
- }
-
- // entries to be deleted
- $serverModifications['deleted'] = array_diff($allClientEntries, $allServerEntries);
-
- // fetch entries changed since last sync
- $serverModifications['changed'] = $dataController->getChangedEntries($collectionData->collectionId, $collectionData->syncState->lastsync, $this->_syncTimeStamp);
- $serverModifications['changed'] = array_merge($serverModifications['changed'], $clientModifications['forceChange']);
-
- foreach($serverModifications['changed'] as $id => $serverId) {
- // skip entry, if it got changed by client during current sync
- if(isset($clientModifications['changed'][$serverId]) && !isset($clientModifications['forceChange'][$serverId])) {
- if ($this->_logger instanceof Zend_Log)
- $this->_logger->info(__METHOD__ . '::' . __LINE__ . " skipped changed entry: " . $serverId);
- unset($serverModifications['changed'][$id]);
+ try {
+ // fetch entries added since last sync
+ $allClientEntries = $this->_contentStateBackend->getFolderState($this->_device, $collectionData->folder);
+ $allServerEntries = $dataController->getServerEntries($collectionData->collectionId, $collectionData->options['filterType']);
+
+ // add entries
+ $serverDiff = array_diff($allServerEntries, $allClientEntries);
+ // add entries which produced problems during delete from client
+ $serverModifications['added'] = $clientModifications['forceAdd'];
+ // add entries not yet sent to client
+ $serverModifications['added'] = array_unique(array_merge($serverModifications['added'], $serverDiff));
+
+ // @todo still needed?
+ foreach($serverModifications['added'] as $id => $serverId) {
+ // skip entries added by client during this sync session
+ if(isset($clientModifications['added'][$serverId]) && !isset($clientModifications['forceAdd'][$serverId])) {
+ if ($this->_logger instanceof Zend_Log)
+ $this->_logger->info(__METHOD__ . '::' . __LINE__ . " skipped added entry: " . $serverId);
+ unset($serverModifications['added'][$id]);
+ }
}
- // skip entry, make sure we don't sent entries already added by client in this request
- else if (isset($clientModifications['added'][$serverId]) && !isset($clientModifications['forceAdd'][$serverId])) {
- if ($this->_logger instanceof Zend_Log)
- $this->_logger->info(__METHOD__ . '::' . __LINE__ . " skipped change for added entry: " . $serverId);
- unset($serverModifications['changed'][$id]);
+
+ // entries to be deleted
+ $serverModifications['deleted'] = array_diff($allClientEntries, $allServerEntries);
+
+ // fetch entries changed since last sync
+ $serverModifications['changed'] = $dataController->getChangedEntries($collectionData->collectionId, $collectionData->syncState->lastsync, $this->_syncTimeStamp);
+ $serverModifications['changed'] = array_merge($serverModifications['changed'], $clientModifications['forceChange']);
+
+ foreach($serverModifications['changed'] as $id => $serverId) {
+ // skip entry, if it got changed by client during current sync
+ if(isset($clientModifications['changed'][$serverId]) && !isset($clientModifications['forceChange'][$serverId])) {
+ if ($this->_logger instanceof Zend_Log)
+ $this->_logger->info(__METHOD__ . '::' . __LINE__ . " skipped changed entry: " . $serverId);
+ unset($serverModifications['changed'][$id]);
+ }
+ // skip entry, make sure we don't sent entries already added by client in this request
+ else if (isset($clientModifications['added'][$serverId]) && !isset($clientModifications['forceAdd'][$serverId])) {
+ if ($this->_logger instanceof Zend_Log)
+ $this->_logger->info(__METHOD__ . '::' . __LINE__ . " skipped change for added entry: " . $serverId);
+ unset($serverModifications['changed'][$id]);
+ }
}
+
+ // entries comeing in scope are already in $serverModifications['added'] and do not need to
+ // be send with $serverCanges
+ $serverModifications['changed'] = array_diff($serverModifications['changed'], $serverModifications['added']);
+ } catch (Exception $e) {
+ if ($this->_logger instanceof Zend_Log)
+ $this->_logger->crit(__METHOD__ . '::' . __LINE__ . " Folder state checking failed: " . $e->getMessage());
+ if ($this->_logger instanceof Zend_Log)
+ $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " Folder state checking failed: " . $e->getTraceAsString());
+
+ // Prevent from removing client entries when getServerEntries() fails
+ // @todo: should we set Status and break the loop here?
+ $serverModifications = array(
+ 'added' => array(),
+ 'changed' => array(),
+ 'deleted' => array(),
+ );
}
-
- // entries comeing in scope are already in $serverModifications['added'] and do not need to
- // be send with $serverCanges
- $serverModifications['changed'] = array_diff($serverModifications['changed'], $serverModifications['added']);
}
-
+
if ($this->_logger instanceof Zend_Log)
$this->_logger->info(__METHOD__ . '::' . __LINE__ . " found (added/changed/deleted) " . count($serverModifications['added']) . '/' . count($serverModifications['changed']) . '/' . count($serverModifications['deleted']) . ' entries for sync from server to client');
}
-
// collection header
$collection = $collections->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Collection'));
diff --git a/lib/ext/Syncroton/Command/Wbxml.php b/lib/ext/Syncroton/Command/Wbxml.php
index f87a71e..cab5cc9 100644
--- a/lib/ext/Syncroton/Command/Wbxml.php
+++ b/lib/ext/Syncroton/Command/Wbxml.php
@@ -161,10 +161,6 @@ abstract class Syncroton_Command_Wbxml implements Syncroton_Command_ICommand
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) {
diff --git a/lib/ext/Syncroton/Data/IDataSearch.php b/lib/ext/Syncroton/Data/IDataSearch.php
index d499efe..5546f8d 100644
--- a/lib/ext/Syncroton/Data/IDataSearch.php
+++ b/lib/ext/Syncroton/Data/IDataSearch.php
@@ -19,16 +19,6 @@
interface Syncroton_Data_IDataSearch
{
/**
- * Returns properties of search entry
- *
- * @param string $longId Entry identifier
- * @param array $options Search options
- *
- * @return Syncroton_Model_IEntry
- */
- public function getSearchEntry($longId, $options);
-
- /**
* Search command handler
*
* @param Syncroton_Model_StoreRequest $store Search query parameters
diff --git a/lib/ext/Syncroton/Server.php b/lib/ext/Syncroton/Server.php
index 7cd61bb..a9bc110 100644
--- a/lib/ext/Syncroton/Server.php
+++ b/lib/ext/Syncroton/Server.php
@@ -102,7 +102,7 @@ class Syncroton_Server
// get user device
$device = $this->_getUserDevice($this->_userId, $requestParameters);
- if ($requestParameters['contentType'] == 'application/vnd.ms-sync.wbxml') {
+ if ($requestParameters['contentType'] == 'application/vnd.ms-sync.wbxml' || $requestParameters['contentType'] == 'application/vnd.ms-sync') {
// decode wbxml request
try {
$decoder = new Syncroton_Wbxml_Decoder($this->_body);
@@ -129,12 +129,6 @@ class Syncroton_Server
$response = $command->getResponse();
- } catch (Syncroton_Exception_PolicyKeyMissing $sepkm) {
- if ($this->_logger instanceof Zend_Log)
- $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " X-MS-POLICYKEY missing (" . $_command. ')');
-
- header("HTTP/1.1 400 header X-MS-POLICYKEY not found");
-
} catch (Syncroton_Exception_ProvisioningNeeded $sepn) {
if ($this->_logger instanceof Zend_Log)
$this->_logger->info(__METHOD__ . '::' . __LINE__ . " provisioning needed");
@@ -191,103 +185,117 @@ class Syncroton_Server
*/
protected function _getRequestParameters(Zend_Controller_Request_Http $request)
{
- if(count($_GET) == 1) {
- $arrayKeys = array_keys($_GET);
-
- $base64Decoded = base64_decode($arrayKeys[0]);
+ if (!isset($_GET['DeviceId'])) {
+ $commands = array(
+ 0 => 'Sync',
+ 1 => 'SendMail',
+ 2 => 'SmartForward',
+ 3 => 'SmartReply',
+ 4 => 'GetAttachment',
+ 9 => 'FolderSync',
+ 10 => 'FolderCreate',
+ 11 => 'FolderDelete',
+ 12 => 'FolderUpdate',
+ 13 => 'MoveItems',
+ 14 => 'GetItemEstimate',
+ 15 => 'MeetingResponse',
+ 16 => 'Search',
+ 17 => 'Settings',
+ 18 => 'Ping',
+ 19 => 'ItemOperations',
+ 20 => 'Provision',
+ 21 => 'ResolveRecipients',
+ 22 => 'ValidateCert'
+ );
+
+ // find the first $_GET parameter which has a key but no value
+ // the key are the request parameters
+ foreach ($_GET as $key => $value) {
+ if (empty($value)) {
+ $requestParameters = $key;
+ break;
+ }
+ }
$stream = fopen("php://temp", 'r+');
- fwrite($stream, base64_decode($arrayKeys[0]));
+ fwrite($stream, base64_decode($requestParameters));
rewind($stream);
- #fpassthru($stream);rewind($stream);
+ // unpack the first 4 bytes
+ $unpacked = unpack('CprotocolVersion/Ccommand/vlocale', fread($stream, 4));
- $protocolVersion = ord(fread($stream, 1));
- switch (ord(fread($stream, 1))) {
- case 0:
- $command = 'Sync';
- break;
- case 1:
- $command = 'SendMail';
- break;
- case 2:
- $command = 'SmartForward';
- break;
- case 3:
- $command = 'SmartReply';
- break;
- case 4:
- $command = 'GetAttachment';
- break;
- case 9:
- $command = 'FolderSync';
- break;
- case 10:
- $command = 'FolderCreate';
- break;
- case 11:
- $command = 'FolderDelete';
- break;
- case 12:
- $command = 'FolderUpdate';
- break;
- case 13:
- $command = 'MoveItems';
- break;
- case 14:
- $command = 'GetItemEstimate';
- break;
- case 15:
- $command = 'MeetingResponse';
- break;
- case 16:
- $command = 'Search';
- break;
- case 17:
- $command = 'Settings';
- break;
- case 18:
- $command = 'Ping';
- break;
- case 19:
- $command = 'ItemOperations';
- break;
- case 20:
- $command = 'Provision';
- break;
- case 21:
- $command = 'ResolveRecipients';
- break;
- case 22:
- $command = 'ValidateCert';
- break;
- }
+ $protocolVersion = $unpacked['protocolVersion'];
+ $command = $commands[$unpacked['command']];
+ $locale = $unpacked['locale'];
- $locale = fread($stream, 2);
+ // unpack deviceId
+ $length = ord(fread($stream, 1));
+ if ($length > 0) {
+ $unpacked = unpack('H' . $length*2 . 'string', fread($stream, $length));
+ $deviceId = $unpacked['string'];
+ }
- $deviceIdLength = ord(fread($stream, 1));
- if ($deviceIdLength > 0) {
- $deviceId = fread($stream, $deviceIdLength);
- }
+ // unpack policyKey
+ $length = ord(fread($stream, 1));
+ if ($length > 0) {
+ $unpacked = unpack('Vstring', fread($stream, $length));
+ $policyKey = $unpacked['string'];
+ }
+
+ // unpack device type
+ $length = ord(fread($stream, 1));
+ if ($length > 0) {
+ $unpacked = unpack('A' . $length . 'string', fread($stream, $length));
+ $deviceType = $unpacked['string'];
+ }
- $policyKeyLength = ord(fread($stream, 1));
- if ($policyKeyLength > 0) {
- $policyKey = fread($stream, 4);
+ while (! feof($stream)) {
+ $tag = ord(fread($stream, 1));
+ $length = ord(fread($stream, 1));
+
+ switch ($tag) {
+ case 0:
+ $unpacked = unpack('A' . $length . 'string', fread($stream, $length));
+
+ $attachmentName = $unpacked['string'];
+ break;
+
+ case 1:
+ $unpacked = unpack('A' . $length . 'string', fread($stream, $length));
+
+ $collectionId = $unpacked['string'];
+ break;
+
+ case 3:
+ $unpacked = unpack('A' . $length . 'string', fread($stream, $length));
+
+ $itemId = $unpacked['string'];
+ break;
+
+ case 7:
+ $options = ord(fread($stream, 1));
+
+ $saveInSent = !!($options & 0x01);
+ $acceptMultiPart = !!($options & 0x02);
+ break;
+
+ default:
+ if ($this->_logger instanceof Zend_Log)
+ $this->_logger->crit(__METHOD__ . '::' . __LINE__ . " found unhandled command parameters");
+
+ }
}
-
- $deviceTypeLength = ord(fread($stream, 1));
- $deviceType = fread($stream, $deviceTypeLength);
-
- // @todo parse command parameters
+
$result = array(
'protocolVersion' => $protocolVersion,
'command' => $command,
'deviceId' => $deviceId,
- 'deviceType' => $deviceType,
- 'saveInSent' => null,
- 'collectionId' => null,
- 'itemId' => null,
- 'attachmentName' => null
+ 'deviceType' => isset($deviceType) ? $deviceType : null,
+ 'policyKey' => isset($policyKey) ? $policyKey : null,
+ 'saveInSent' => isset($saveInSent) ? $saveInSent : false,
+ 'collectionId' => isset($collectionId) ? $collectionId : null,
+ 'itemId' => isset($itemId) ? $itemId : null,
+ 'attachmentName' => isset($attachmentName) ? $attachmentName : null
);
} else {
$result = array(
@@ -295,7 +303,8 @@ class Syncroton_Server
'command' => $request->getQuery('Cmd'),
'deviceId' => $request->getQuery('DeviceId'),
'deviceType' => $request->getQuery('DeviceType'),
- 'saveInSent' => $request->getQuery('SaveInSent'),
+ 'policyKey' => $request->getServer('HTTP_X_MS_POLICYKEY'),
+ 'saveInSent' => $request->getQuery('SaveInSent') == 'T',
'collectionId' => $request->getQuery('CollectionId'),
'itemId' => $request->getQuery('ItemId'),
'attachmentName' => $request->getQuery('AttachmentName'),
@@ -303,7 +312,6 @@ class Syncroton_Server
}
$result['userAgent'] = $request->getServer('HTTP_USER_AGENT', $result['deviceType']);
- $result['policyKey'] = $request->getServer('HTTP_X_MS_POLICYKEY');
$result['contentType'] = $request->getServer('CONTENT_TYPE');
return $result;
More information about the commits
mailing list