diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index fdc17eb..ffab2d7 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -1,47 +1,47 @@ in([__DIR__]) ->exclude([ - 'lib/ext', + 'lib/ext/Roundcube', 'lib/plugins', 'vendor', ]) ->ignoreDotFiles(false) ->name('*.php.dist'); return (new Config()) ->setRiskyAllowed(true) ->setRules([ '@PHP74Migration' => true, '@PHP74Migration:risky' => true, '@PHP80Migration' => true, '@PSR1' => true, '@PSR12' => true, 'concat_space' => [ 'spacing' => 'one', ], 'declare_strict_types' => false, 'phpdoc_add_missing_param_annotation' => false, 'use_arrow_functions' => false, 'void_return' => false, 'yoda_style' => [ 'equal' => false, 'identical' => false, ], // TODO - risky 'no_unset_on_property' => false, 'random_api_migration' => false, 'strict_param' => false, ]) ->setFinder($finder) ->setCacheFile(sys_get_temp_dir() . '/php-cs-fixer.' . md5(__DIR__) . '.cache'); diff --git a/lib/ext/Syncroton/Backend/ABackend.php b/lib/ext/Syncroton/Backend/ABackend.php index 7e63d8d..ce4f322 100644 --- a/lib/ext/Syncroton/Backend/ABackend.php +++ b/lib/ext/Syncroton/Backend/ABackend.php @@ -1,212 +1,212 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage 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; - + /** * the constructor - * + * * @param Zend_Db_Adapter_Abstract $_db * @param string $_tablePrefix */ public function __construct(Zend_Db_Adapter_Abstract $_db, $_tablePrefix = 'Syncroton_') { $this->_db = $_db; $this->_tablePrefix = $_tablePrefix; } /** * create new device - * + * * @param Syncroton_Model_AEntry $model * @return Syncroton_Model_AEntry */ public function create($model) { if (! $model instanceof $this->_modelInterfaceName) { throw new InvalidArgumentException('$model must be instance of ' . $this->_modelInterfaceName); } - + $data = $this->_convertModelToArray($model); - - $data['id'] = sha1(mt_rand(). microtime()); + + $data['id'] = sha1(mt_rand() . microtime()); $this->_db->insert($this->_tablePrefix . $this->_tableName, $data); - + return $this->get($data['id']); } - + /** * convert iteratable object to array - * + * * @param Syncroton_Model_AEntry $model * @return array */ protected function _convertModelToArray($model) { - $data = array(); - + $data = []; + 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_AEntry */ public function get($id) { $id = $id instanceof $this->_modelInterfaceName ? $id->id : $id; - + if (empty($id)) { throw new Syncroton_Exception_NotFound('id can not be empty'); } - + $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); } - + /** * convert array to object - * + * * @param array $data * @return object */ 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); } - + /** * (non-PHPdoc) * @see Syncroton_Backend_IBackend::delete() */ public function delete($id) { $id = $id instanceof $this->_modelInterfaceName ? $id->id : $id; // @phpstan-ignore-line - - $result = $this->_db->delete($this->_tablePrefix . $this->_tableName, array('id = ?' => $id)); - + + $result = $this->_db->delete($this->_tablePrefix . $this->_tableName, ['id = ?' => $id]); + return (bool) $result; } - + /** * (non-PHPdoc) * @see Syncroton_Backend_IBackend::update() */ 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 // @phpstan-ignore-line - )); - + + $this->_db->update($this->_tablePrefix . $this->_tableName, $data, [ + 'id = ?' => $model->id, // @phpstan-ignore-line + ]); + return $this->get($model->id); // @phpstan-ignore-line } /** * Returns list of user accounts * * @param Syncroton_Model_Device $device The device * * @return array List of Syncroton_Model_Account objects */ public function userAccounts($device) { - return array(); + return []; } /** * convert from camelCase to camel_case * @param string $string * @return string */ protected function _fromCamelCase($string) { $string = lcfirst($string); - + return preg_replace_callback('/([A-Z])/', function ($string) {return '_' . strtolower($string[0]);}, $string); } - + /** * convert from camel_case to camelCase - * + * * @param string $string * @param bool $ucFirst * @return 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 f43231f..d33e0a3 100644 --- a/lib/ext/Syncroton/Backend/Content.php +++ b/lib/ext/Syncroton/Backend/Content.php @@ -1,120 +1,120 @@ * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) - * + * */ /** * sql backend class for the folder state * * @package Syncroton * @subpackage Backend */ class Syncroton_Backend_Content extends Syncroton_Backend_ABackend implements Syncroton_Backend_IContent { - protected $_tableName = 'content'; - - protected $_modelClassName = 'Syncroton_Model_Content'; - - protected $_modelInterfaceName = 'Syncroton_Model_IContent'; - + protected $_tableName = 'content'; + + protected $_modelClassName = 'Syncroton_Model_Content'; + + protected $_modelInterfaceName = 'Syncroton_Model_IContent'; + /** - * mark state as deleted. The state gets removed finally, + * mark state as deleted. The state gets removed finally, * when the synckey gets validated during next sync. - * + * * @param Syncroton_Model_IContent|string $id * * @return bool */ public function delete($id) { $id = $id instanceof $this->_modelInterfaceName ? $id->id : $id; - - $this->_db->update($this->_tablePrefix . 'content', array( - 'is_deleted' => 1 - ), array( - 'id = ?' => $id - )); + + $this->_db->update($this->_tablePrefix . 'content', [ + 'is_deleted' => 1, + ], [ + 'id = ?' => $id, + ]); return true; } - + /** * @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) { $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('device_id') . ' = ?', $deviceId) + ->where($this->_db->quoteIdentifier('folder_id') . ' = ?', $folderId) + ->where($this->_db->quoteIdentifier('contentid') . ' = ?', $contentId) ->where($this->_db->quoteIdentifier('is_deleted') . ' = ?', 0); - - $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); + + $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 int $syncKey * @return array */ public function getFolderState($deviceId, $folderId, $syncKey = null) { $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') - ->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId) - ->where($this->_db->quoteIdentifier('folder_id') . ' = ?', $folderId) + ->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId) + ->where($this->_db->quoteIdentifier('folder_id') . ' = ?', $folderId) ->where($this->_db->quoteIdentifier('is_deleted') . ' = ?', 0); - + $stmt = $this->_db->query($select); $result = $stmt->fetchAll(Zend_Db::FETCH_COLUMN); - + return $result; } - + /** * reset list of stored id * * @param Syncroton_Model_IDevice|string $deviceId * @param Syncroton_Model_IFolder|string $folderId */ public function resetState($deviceId, $folderId) { $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId; $folderId = $folderId instanceof Syncroton_Model_IFolder ? $folderId->id : $folderId; - - $where = array( + + $where = [ $this->_db->quoteInto($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId), - $this->_db->quoteInto($this->_db->quoteIdentifier('folder_id') . ' = ?', $folderId) - ); - + $this->_db->quoteInto($this->_db->quoteIdentifier('folder_id') . ' = ?', $folderId), + ]; + $this->_db->delete($this->_tablePrefix . 'content', $where); } } diff --git a/lib/ext/Syncroton/Backend/Device.php b/lib/ext/Syncroton/Backend/Device.php index e668bb0..5c99368 100644 --- a/lib/ext/Syncroton/Backend/Device.php +++ b/lib/ext/Syncroton/Backend/Device.php @@ -1,94 +1,94 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Backend */ class Syncroton_Backend_Device extends Syncroton_Backend_ABackend implements Syncroton_Backend_IDevice { protected $_tableName = 'device'; - + protected $_modelClassName = 'Syncroton_Model_Device'; - + protected $_modelInterfaceName = 'Syncroton_Model_IDevice'; - + /** * return device for this user - * + * * @param string $ownerId * @param string $deviceId * @throws Syncroton_Exception_NotFound * @return Syncroton_Model_Device */ public function getUserDevice($ownerId, $deviceId) { $select = $this->_db->select() ->from($this->_tablePrefix . $this->_tableName) ->where('owner_id = ?', $ownerId) ->where('deviceid = ?', $deviceId); - + $stmt = $this->_db->query($select); $data = $stmt->fetch(); - + 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; } - + $model = new $this->_modelClassName($data); - + return $model; } /** * Returns list of user accounts * * @param Syncroton_Model_Device $device The device * * @return array List of Syncroton_Model_Account objects */ public function userAccounts($device) { - return array(); + return []; } /** * Returns OOF information * * @param array $request Oof/Get request data * * @return Syncroton_Model_Oof|null Response object or NULL if OOF is not supported * @throws Syncroton_Exception_Status */ public function getOOF($request) { return null; // not implemented } /** * Sets OOF information * * @param Syncroton_Model_Oof $request Request object * * @throws Syncroton_Exception_Status */ public function setOOF($request) { // not implemented } } diff --git a/lib/ext/Syncroton/Backend/Folder.php b/lib/ext/Syncroton/Backend/Folder.php index da940e0..926315a 100644 --- a/lib/ext/Syncroton/Backend/Folder.php +++ b/lib/ext/Syncroton/Backend/Folder.php @@ -1,136 +1,136 @@ * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) - * + * */ /** * sql backend class for the folder state * * @package Syncroton * @subpackage Backend */ class Syncroton_Backend_Folder extends Syncroton_Backend_ABackend implements Syncroton_Backend_IFolder { protected $_tableName = 'folder'; - + protected $_modelClassName = 'Syncroton_Model_Folder'; - + protected $_modelInterfaceName = 'Syncroton_Model_IFolder'; - + /** * (non-PHPdoc) * @see Syncroton_Backend_IFolder::getFolder() */ public function getFolder($deviceId, $folderId) { $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId; - + $select = $this->_db->select() ->from($this->_tablePrefix . $this->_tableName) ->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId) - ->where($this->_db->quoteIdentifier('folderid') . ' = ?', $folderId); - + ->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); } - + /** * (non-PHPdoc) * @see Syncroton_Backend_IFolder::getFolderState() */ public function getFolderState($deviceId, $class) { $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId; - + $select = $this->_db->select() ->from($this->_tablePrefix . $this->_tableName) ->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId) - ->where($this->_db->quoteIdentifier('class') . ' = ?', $class); - - $result = array(); - + ->where($this->_db->quoteIdentifier('class') . ' = ?', $class); + + $result = []; + $stmt = $this->_db->query($select); while ($data = $stmt->fetch()) { - $result[$data['folderid']] = $this->_getObject($data); + $result[$data['folderid']] = $this->_getObject($data); } - + return $result; } - + /** * (non-PHPdoc) * @see Syncroton_Backend_IFolder::resetState() */ public function resetState($deviceId) { $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId; - - $where = array( - $this->_db->quoteInto($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId) - ); - + + $where = [ + $this->_db->quoteInto($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId), + ]; + $this->_db->delete($this->_tablePrefix . $this->_tableName, $where); } /** * (non-PHPdoc) * @see Syncroton_Backend_IFolder::hasHierarchyChanges() */ public function hasHierarchyChanges($device) { return false; // not implemented } /** * (non-PHPdoc) * @see Syncroton_Backend_ABackend::_fromCamelCase() */ protected function _fromCamelCase($string) { switch ($string) { case 'displayName': case 'parentId': return strtolower($string); - + case 'serverId': return 'folderid'; - + default: return parent::_fromCamelCase($string); } } - + /** * (non-PHPdoc) * @see Syncroton_Backend_ABackend::_toCamelCase() */ protected function _toCamelCase($string, $ucFirst = true) { switch ($string) { case 'displayname': return 'displayName'; - + case 'parentid': return 'parentId'; - + case 'folderid': return 'serverId'; - + default: return parent::_toCamelCase($string, $ucFirst); } } } diff --git a/lib/ext/Syncroton/Backend/IBackend.php b/lib/ext/Syncroton/Backend/IBackend.php index 6763f51..90d4532 100644 --- a/lib/ext/Syncroton/Backend/IBackend.php +++ b/lib/ext/Syncroton/Backend/IBackend.php @@ -1,51 +1,51 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Backend */ interface Syncroton_Backend_IBackend { /** * Create a new device * * @param Syncroton_Model_IEntry $model * @return Syncroton_Model_IEntry */ public function create($model); - + /** * Deletes one or more existing devices * * @param string|Syncroton_Model_IEntry $id * @return bool */ public function delete($id); - + /** * Return a single device * * @param string $id * @return Syncroton_Model_IEntry */ public function get($id); - + /** * Upates an existing persistent record * * @param Syncroton_Model_IEntry $model * @return Syncroton_Model_IEntry */ public function update($model); } diff --git a/lib/ext/Syncroton/Backend/Policy.php b/lib/ext/Syncroton/Backend/Policy.php index dee8d95..3e660e5 100644 --- a/lib/ext/Syncroton/Backend/Policy.php +++ b/lib/ext/Syncroton/Backend/Policy.php @@ -1,71 +1,71 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Backend */ class Syncroton_Backend_Policy extends Syncroton_Backend_ABackend { protected $_tableName = 'policy'; - + protected $_modelClassName = 'Syncroton_Model_Policy'; - + protected $_modelInterfaceName = 'Syncroton_Model_IPolicy'; - + /** * convert iteratable object to array - * + * * @param Syncroton_Model_IXMLEntry $model * @return array */ protected function _convertModelToArray($model) { $policyValues = $model->getProperties('Provision'); - - $policy = array(); - + + $policy = []; + foreach ($policyValues as $policyName) { - if ($model->$policyName !== NULL) { + if ($model->$policyName !== null) { $policy[$policyName] = $model->$policyName; } - + unset($model->$policyName); } $data = parent::_convertModelToArray($model); - + $data['json_policy'] = Zend_Json::encode($policy); - + return $data; } - + /** * convert array to object - * + * * @param array $data * @return object */ protected function _getObject($data) { $policy = Zend_Json::decode($data['json_policy']); - + foreach ($policy as $policyKey => $policyValue) { $data[$policyKey] = $policyValue; } - + unset($data['json_policy']); - + return parent::_getObject($data); } } diff --git a/lib/ext/Syncroton/Backend/SyncState.php b/lib/ext/Syncroton/Backend/SyncState.php index 6f5fa0e..8a6c6aa 100644 --- a/lib/ext/Syncroton/Backend/SyncState.php +++ b/lib/ext/Syncroton/Backend/SyncState.php @@ -1,215 +1,215 @@ * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) - * + * */ /** * sql backend class for the folder state * * @package Syncroton * @subpackage Backend */ class Syncroton_Backend_SyncState extends Syncroton_Backend_ABackend implements Syncroton_Backend_ISyncState { - protected $_tableName = 'synckey'; - - protected $_modelClassName = 'Syncroton_Model_SyncState'; + protected $_tableName = 'synckey'; + + protected $_modelClassName = 'Syncroton_Model_SyncState'; + + protected $_modelInterfaceName = 'Syncroton_Model_ISyncState'; - protected $_modelInterfaceName = 'Syncroton_Model_ISyncState'; - /** * (non-PHPdoc) * @see Syncroton_Backend_ISyncState::create() */ public function create($model, $keepPreviousSyncState = true) { $state = parent::create($model); - + if ($keepPreviousSyncState !== true) { // remove all other synckeys $this->_deleteOtherStates($state); } - + return $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( + $where = [ 'device_id = ?' => $state->deviceId, 'type = ?' => $state->type, - 'counter != ?' => $state->counter - ); - + 'counter != ?' => $state->counter, + ]; + $this->_db->delete($this->_tablePrefix . $this->_tableName, $where); - + return true; - + } - + /** * (non-PHPdoc) * @see Syncroton_Backend_ABackend::_getObject() */ - protected function _getObject($data) + protected function _getObject($data) { $model = parent::_getObject($data); - - if ($model->pendingdata !== NULL) { - $model->pendingdata = Zend_Json::decode($model->pendingdata); + + if ($model->pendingdata !== null) { + $model->pendingdata = Zend_Json::decode($model->pendingdata); } - - return $model; + + return $model; } - + /** * (non-PHPdoc) * @see Syncroton_Backend_ISyncState::getSyncState() */ public function getSyncState($deviceId, $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 . $this->_tableName) ->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId) - ->where($this->_db->quoteIdentifier('type') . ' = ?', $folderId) + ->where($this->_db->quoteIdentifier('type') . ' = ?', $folderId) ->order('counter DESC') ->limit(1); - - $stmt = $this->_db->query($select); + + $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'); - } - + $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 */ public function resetState($deviceId, $folderId) { $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId; $folderId = $folderId instanceof Syncroton_Model_IFolder ? $folderId->id : $folderId; - - $where = array( + + $where = [ $this->_db->quoteInto($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId), - $this->_db->quoteInto($this->_db->quoteIdentifier('type') . ' = ?', $folderId) - ); - + $this->_db->quoteInto($this->_db->quoteIdentifier('type') . ' = ?', $folderId), + ]; + $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 int $syncKey * * @return Syncroton_Model_SyncState|false */ public function validate($deviceId, $folderId, $syncKey) { $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 . $this->_tableName) ->where($this->_db->quoteIdentifier('device_id') . ' = ?', $deviceId) - ->where($this->_db->quoteIdentifier('counter') . ' = ?', $syncKey) - ->where($this->_db->quoteIdentifier('type') . ' = ?', $folderId); - + ->where($this->_db->quoteIdentifier('counter') . ' = ?', $syncKey) + ->where($this->_db->quoteIdentifier('type') . ' = ?', $folderId); + $stmt = $this->_db->query($select); $data = $stmt->fetch(); $stmt = null; # see https://bugs.php.net/bug.php?id=44081 - + if ($data === false) { return false; } $state = $this->_getObject($data); - + // check if this was the latest syncKey $select = $this->_db->select() ->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); $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 ($moreRecentStateData !== false) { // undelete entries marked as deleted in Syncroton_content table - $this->_db->update($this->_tablePrefix . 'content', array( + $this->_db->update($this->_tablePrefix . 'content', [ 'is_deleted' => 0, - ), array( + ], [ 'device_id = ?' => $deviceId, 'folder_id = ?' => $folderId, 'creation_synckey = ?' => $state->counter, - 'is_deleted = ?' => 1 - )); - + 'is_deleted = ?' => 1, + ]); + } else { - // finally delete all entries marked for removal in Syncroton_content table - $this->_db->delete($this->_tablePrefix . 'content', array( + // finally delete all entries marked for removal in Syncroton_content table + $this->_db->delete($this->_tablePrefix . 'content', [ 'device_id = ?' => $deviceId, 'folder_id = ?' => $folderId, - 'is_deleted = ?' => 1 - )); + 'is_deleted = ?' => 1, + ]); } - + // remove all other synckeys $this->_deleteOtherStates($state); - + // remove entries from Syncroton_content table with an creation_synckey bigger than current one - $this->_db->delete($this->_tablePrefix . 'content', array( + $this->_db->delete($this->_tablePrefix . 'content', [ 'device_id = ?' => $deviceId, 'folder_id = ?' => $folderId, 'creation_synckey > ?' => $state->counter, - )); - + ]); + return $state; } public function haveNext($deviceid, $folderid, $sync_key) { return false; // not implemented } } diff --git a/lib/ext/Syncroton/Command/AutoDiscover.php b/lib/ext/Syncroton/Command/AutoDiscover.php index 30d748c..81b3519 100644 --- a/lib/ext/Syncroton/Command/AutoDiscover.php +++ b/lib/ext/Syncroton/Command/AutoDiscover.php @@ -1,127 +1,127 @@ */ /** * class to handle AutoDiscover command * * @package Syncroton * @subpackage Command */ class Syncroton_Command_AutoDiscover extends Syncroton_Command_Wbxml { /** * the domDocucment containing the xml request from the client * * @var DOMDocument */ protected $requestBody; - + protected $emailAddress; - - public $mobileSyncUrl; - - public $certEnrollUrl; - + + public $mobileSyncUrl; + + public $certEnrollUrl; + /** * constructor of this class - * + * * @param DOMDocument $requestBody * @param Syncroton_Model_IDevice $device * @param array $requestParams */ // @phpstan-ignore-next-line public function __construct($requestBody, Syncroton_Model_IDevice $device, $requestParams = []) { $this->requestBody = $requestBody; } - + /** - * process the incoming data + * process the incoming data */ public function handle() { $xpath = new DomXPath($this->requestBody); $xpath->registerNamespace('2006', 'http://schemas.microsoft.com/exchange/autodiscover/mobilesync/requestschema/2006'); - + $nodes = $xpath->query('//2006:Autodiscover/2006:Request/2006:EMailAddress'); if ($nodes->length === 0) { throw new Syncroton_Exception(); } - + $this->emailAddress = $nodes->item(0)->nodeValue; } - + /** * create the response - * + * * @return DOMDocument */ public function getResponse() { // Creates an instance of the DOMImplementation class $imp = new DOMImplementation(); - + // Creates a DOMDocument instance $document = $imp->createDocument("http://schemas.microsoft.com/exchange/autodiscover/mobilesync/requestschema/2006", 'Autodiscover'); $document->xmlVersion = '1.0'; $document->encoding = 'UTF-8'; $document->formatOutput = false; - + $response = $document->documentElement->appendChild($document->createElement('Response')); - + $user = $response->appendChild($document->createElement('User')); $user->appendChild($document->createElement('EMailAddress', $this->emailAddress)); - + $settings = $document->createElement('Settings'); - + if (!empty($this->mobileSyncUrl)) { $server = $document->createElement('Server'); - + $server->appendChild($document->createElement('Type', 'MobileSync')); - - $server->appendChild($document->createElement('Url', $this->mobileSyncUrl)); + + $server->appendChild($document->createElement('Url', $this->mobileSyncUrl)); $server->appendChild($document->createElement('Name', $this->mobileSyncUrl)); - + $settings->appendChild($server); } - + if (!empty($this->certEnrollUrl)) { $server = $document->createElement('Server'); - + $server->appendChild($document->createElement('Type', 'CertEnroll')); - - $server->appendChild($document->createElement('Url', $this->certEnrollUrl)); + + $server->appendChild($document->createElement('Url', $this->certEnrollUrl)); $server->appendChild($document->createElement('Name')); $server->appendChild($document->createElement('ServerData', 'CertEnrollTemplate')); - + $settings->appendChild($server); } - + if ($settings->hasChildNodes()) { $action = $response->appendChild($document->createElement('Action')); $action->appendChild($settings); } - + return $document; } - + /** * return headers of command - * + * * @return array list of headers */ public function getHeaders() { - return array( - 'Content-Type' => 'text/xml;charset=utf-8' - ); + return [ + 'Content-Type' => 'text/xml;charset=utf-8', + ]; } } diff --git a/lib/ext/Syncroton/Command/FolderCreate.php b/lib/ext/Syncroton/Command/FolderCreate.php index d9f8489..a632142 100644 --- a/lib/ext/Syncroton/Command/FolderCreate.php +++ b/lib/ext/Syncroton/Command/FolderCreate.php @@ -1,155 +1,162 @@ */ /** * class to handle ActiveSync FolderCreate command * * @package Syncroton * @subpackage Command */ class Syncroton_Command_FolderCreate extends Syncroton_Command_Wbxml { protected $_defaultNameSpace = 'uri:FolderHierarchy'; protected $_documentElement = 'FolderCreate'; - + /** * @var Syncroton_Model_IFolder */ protected $_folder; /** * @var int */ protected $_status; - + /** * parse FolderCreate request */ public function handle() { $xml = simplexml_import_dom($this->_requestBody); - + $syncKey = (int)$xml->SyncKey; - if ($this->_logger instanceof Zend_Log) + 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) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " invalid synckey provided. FolderSync 0 needed."); + } $this->_status = Syncroton_Command_FolderSync::STATUS_INVALID_SYNC_KEY; return; } - + $folder = new Syncroton_Model_Folder($xml); - - if ($this->_logger instanceof Zend_Log) + + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " parentId: {$folder->parentId} displayName: {$folder->displayName}"); + } if (!strlen($folder->displayName)) { $this->_status = Syncroton_Command_FolderSync::STATUS_MISFORMATTED; return; } - + switch($folder->type) { case Syncroton_Command_FolderSync::FOLDERTYPE_CALENDAR_USER_CREATED: $folder->class = Syncroton_Data_Factory::CLASS_CALENDAR; break; - + case Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT_USER_CREATED: $folder->class = Syncroton_Data_Factory::CLASS_CONTACTS; break; - + case Syncroton_Command_FolderSync::FOLDERTYPE_MAIL_USER_CREATED: $folder->class = Syncroton_Data_Factory::CLASS_EMAIL; break; case Syncroton_Command_FolderSync::FOLDERTYPE_NOTE_USER_CREATED: $folder->class = Syncroton_Data_Factory::CLASS_NOTES; break; - + case Syncroton_Command_FolderSync::FOLDERTYPE_TASK_USER_CREATED: $folder->class = Syncroton_Data_Factory::CLASS_TASKS; break; - + default: // unsupported type return; } try { $dataController = Syncroton_Data_Factory::factory($folder->class, $this->_device, $this->_syncTimeStamp); $this->_folder = $dataController->createFolder($folder); if (!$this->_folder) { $this->_status = Syncroton_Command_FolderSync::STATUS_UNKNOWN_ERROR; } else { $this->_folder->class = $folder->class; $this->_folder->deviceId = $this->_device->id; $this->_folder->creationTime = $this->_syncTimeStamp; // Check if the folder already exists to avoid a duplicate insert attempt in db try { $this->_folderBackend->getFolder($this->_device, $this->_folder->serverId); - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " Attempted to create a folder that already exists. parentId: {$folder->parentId} displayName: {$folder->displayName}"); + } // The folder already exists $this->_status = Syncroton_Command_FolderSync::STATUS_FOLDER_EXISTS; } catch (Syncroton_Exception_NotFound $e) { // This is the normal case - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " " . $e->getMessage()); + } $this->_folderBackend->create($this->_folder); } } } catch (Syncroton_Exception_Status $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " " . $e->getMessage()); + } $this->_status = $e->getCode(); } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " " . $e->getMessage()); + } $this->_status = Syncroton_Command_FolderSync::STATUS_UNKNOWN_ERROR; } } - + /** * generate FolderCreate response */ public function getResponse() { $folderCreate = $this->_outputDom->documentElement; - + if ($this->_status) { $folderCreate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', $this->_status)); } else { $this->_syncState->counter++; $this->_syncState->lastsync = $this->_syncTimeStamp; - + // 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', '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', $this->_folder->serverId)); } - + return $this->_outputDom; } } diff --git a/lib/ext/Syncroton/Command/FolderDelete.php b/lib/ext/Syncroton/Command/FolderDelete.php index 314d451..257d308 100644 --- a/lib/ext/Syncroton/Command/FolderDelete.php +++ b/lib/ext/Syncroton/Command/FolderDelete.php @@ -1,98 +1,101 @@ */ /** * class to handle ActiveSync FolderDelete command * * @package Syncroton * @subpackage Command */ -class Syncroton_Command_FolderDelete extends Syncroton_Command_Wbxml -{ +class Syncroton_Command_FolderDelete extends Syncroton_Command_Wbxml +{ protected $_defaultNameSpace = 'uri:FolderHierarchy'; protected $_documentElement = 'FolderDelete'; - + /** * @var Syncroton_Model_IFolder */ protected $_folder; - + /** * parse FolderDelete request */ public function handle() { $xml = simplexml_import_dom($this->_requestBody); - + // parse xml request $syncKey = (int)$xml->SyncKey; - $serverId = (string)$xml->ServerId; - - if ($this->_logger instanceof Zend_Log) + $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) { - return; + return; } - + try { $folder = $this->_folderBackend->getFolder($this->_device, $serverId); - + $dataController = Syncroton_Data_Factory::factory($folder->class, $this->_device, $this->_syncTimeStamp); - + // delete folder in data backend $dataController->deleteFolder($folder); - + } catch (Syncroton_Exception_NotFound $senf) { - if ($this->_logger instanceof Zend_Log) + 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; } - + /** * generate FolderDelete response * * @todo currently we support only the main folder which contains all contacts/tasks/events/notes per class */ public function getResponse() { $folderDelete = $this->_outputDom->documentElement; - + if (!$this->_syncState instanceof Syncroton_Model_SyncState) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $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 { $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 13218cf..565832e 100644 --- a/lib/ext/Syncroton/Command/FolderSync.php +++ b/lib/ext/Syncroton/Command/FolderSync.php @@ -1,287 +1,292 @@ */ /** * class to handle ActiveSync FolderSync command * * @package Syncroton * @subpackage Command */ -class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml +class Syncroton_Command_FolderSync extends Syncroton_Command_Wbxml { - const STATUS_SUCCESS = 1; - const STATUS_FOLDER_EXISTS = 2; - const STATUS_IS_SPECIAL_FOLDER = 3; - const STATUS_FOLDER_NOT_FOUND = 4; - const STATUS_PARENT_FOLDER_NOT_FOUND = 5; - const STATUS_SERVER_ERROR = 6; - const STATUS_ACCESS_DENIED = 7; - const STATUS_REQUEST_TIMED_OUT = 8; - const STATUS_INVALID_SYNC_KEY = 9; - const STATUS_MISFORMATTED = 10; - const STATUS_UNKNOWN_ERROR = 11; + public const STATUS_SUCCESS = 1; + public const STATUS_FOLDER_EXISTS = 2; + public const STATUS_IS_SPECIAL_FOLDER = 3; + public const STATUS_FOLDER_NOT_FOUND = 4; + public const STATUS_PARENT_FOLDER_NOT_FOUND = 5; + public const STATUS_SERVER_ERROR = 6; + public const STATUS_ACCESS_DENIED = 7; + public const STATUS_REQUEST_TIMED_OUT = 8; + public const STATUS_INVALID_SYNC_KEY = 9; + public const STATUS_MISFORMATTED = 10; + public const STATUS_UNKNOWN_ERROR = 11; /** * some usefull constants for working with the xml files */ - const FOLDERTYPE_GENERIC_USER_CREATED = 1; - const FOLDERTYPE_INBOX = 2; - const FOLDERTYPE_DRAFTS = 3; - const FOLDERTYPE_DELETEDITEMS = 4; - const FOLDERTYPE_SENTMAIL = 5; - const FOLDERTYPE_OUTBOX = 6; - const FOLDERTYPE_TASK = 7; - const FOLDERTYPE_CALENDAR = 8; - const FOLDERTYPE_CONTACT = 9; - const FOLDERTYPE_NOTE = 10; - const FOLDERTYPE_JOURNAL = 11; - const FOLDERTYPE_MAIL_USER_CREATED = 12; - const FOLDERTYPE_CALENDAR_USER_CREATED = 13; - const FOLDERTYPE_CONTACT_USER_CREATED = 14; - const FOLDERTYPE_TASK_USER_CREATED = 15; - const FOLDERTYPE_JOURNAL_USER_CREATED = 16; - const FOLDERTYPE_NOTE_USER_CREATED = 17; - const FOLDERTYPE_UNKOWN = 18; - + public const FOLDERTYPE_GENERIC_USER_CREATED = 1; + public const FOLDERTYPE_INBOX = 2; + public const FOLDERTYPE_DRAFTS = 3; + public const FOLDERTYPE_DELETEDITEMS = 4; + public const FOLDERTYPE_SENTMAIL = 5; + public const FOLDERTYPE_OUTBOX = 6; + public const FOLDERTYPE_TASK = 7; + public const FOLDERTYPE_CALENDAR = 8; + public const FOLDERTYPE_CONTACT = 9; + public const FOLDERTYPE_NOTE = 10; + public const FOLDERTYPE_JOURNAL = 11; + public const FOLDERTYPE_MAIL_USER_CREATED = 12; + public const FOLDERTYPE_CALENDAR_USER_CREATED = 13; + public const FOLDERTYPE_CONTACT_USER_CREATED = 14; + public const FOLDERTYPE_TASK_USER_CREATED = 15; + public const FOLDERTYPE_JOURNAL_USER_CREATED = 16; + public const FOLDERTYPE_NOTE_USER_CREATED = 17; + public const FOLDERTYPE_UNKOWN = 18; + protected $_defaultNameSpace = 'uri:FolderHierarchy'; protected $_documentElement = 'FolderSync'; - - protected $_classes = array( + + protected $_classes = [ Syncroton_Data_Factory::CLASS_CALENDAR, Syncroton_Data_Factory::CLASS_CONTACTS, Syncroton_Data_Factory::CLASS_EMAIL, Syncroton_Data_Factory::CLASS_NOTES, - Syncroton_Data_Factory::CLASS_TASKS - ); + Syncroton_Data_Factory::CLASS_TASKS, + ]; /** * @var string */ protected $_syncKey; /** * Parse FolderSync request */ public function handle() { $xml = simplexml_import_dom($this->_requestBody); $syncKey = (int)$xml->SyncKey; - - if ($this->_logger instanceof Zend_Log) + + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " synckey is $syncKey"); - + } + if ($syncKey === 0) { - $this->_syncState = new Syncroton_Model_SyncState(array( + $this->_syncState = new Syncroton_Model_SyncState([ 'device_id' => $this->_device, 'counter' => 0, 'type' => 'FolderSync', - 'lastsync' => $this->_syncTimeStamp - )); - + 'lastsync' => $this->_syncTimeStamp, + ]); + // reset state of foldersync $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'); } } - + /** * generate FolderSync response - * + * * @todo changes are missing in response (folder got renamed for example) */ public function getResponse() { $folderSync = $this->_outputDom->documentElement; - + // invalid synckey provided if (!$this->_syncState instanceof Syncroton_Model_SyncState) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $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; } // send headers from options command also when FolderSync SyncKey is 0 if ($this->_syncState->counter == 0) { $optionsCommand = new Syncroton_Command_Options(); $this->_headers = array_merge($this->_headers, $optionsCommand->getHeaders()); } - - $adds = array(); - $updates = array(); - $deletes = array(); + + $adds = []; + $updates = []; + $deletes = []; foreach($this->_classes as $class) { try { $dataController = Syncroton_Data_Factory::factory($class, $this->_device, $this->_syncTimeStamp); } catch (Exception $e) { // backend not defined - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " no data backend defined for class: " . $class); + } continue; } try { // retrieve all folders available in data backend $serverFolders = $dataController->getAllFolders(); - + // retrieve all folders sent to client $clientFolders = $this->_folderBackend->getFolderState($this->_device, $class); - + if ($this->_syncState->counter > 0) { // retrieve all folders changed since last sync $changedFolders = $dataController->getChangedFolders($this->_syncState->lastsync, $this->_syncTimeStamp); } else { - $changedFolders = array(); + $changedFolders = []; } - + // only folders which were sent to the client already are allowed to be in $changedFolders $changedFolders = array_intersect_key($changedFolders, $clientFolders); - + } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->crit(__METHOD__ . '::' . __LINE__ . " Syncing folder hierarchy failed: " . $e->getMessage()); - if ($this->_logger instanceof Zend_Log) + } + 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) { - $clientFoldersIds = array(); + $clientFoldersIds = []; } 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])) { $add = $clientFolders[$serverFolderId]; } else { $add = $serverFolders[$serverFolderId]; $add->creationTime = $this->_syncTimeStamp; $add->deviceId = $this->_device->id; unset($add->id); } $add->class = $class; $adds[] = $add; } // calculate changed entries foreach ($changedFolders as $changedFolder) { $change = $clientFolders[$changedFolder->serverId]; - + $change->displayName = $changedFolder->displayName; $change->parentId = $changedFolder->parentId; $change->type = $changedFolder->type; - + $updates[] = $change; } // Find changes in case backend does not support folder changes detection. // On some backends getChangedFolders() can return an empty result. // We make sure all is up-to-date comparing folder properties. foreach ($clientFoldersIds as $folderId) { if (isset($serverFolders[$folderId])) { $c = $clientFolders[$folderId]; $s = $serverFolders[$folderId]; if ($c->displayName !== $s->displayName || strval($c->parentId) !== strval($s->parentId) || $c->type != $s->type ) { $c->displayName = $s->displayName; $c->parentId = $s->parentId; $c->type = $s->type; $updates[] = $c; } } } // calculate deleted entries $serverDiff = array_diff($clientFoldersIds, $serverFoldersIds); foreach ($serverDiff as $serverFolderId) { $deletes[] = $clientFolders[$serverFolderId]; } } $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', self::STATUS_SUCCESS)); $count = count($adds) + count($updates) + count($deletes); if($count > 0) { $this->_syncState->counter++; $this->_syncState->lastsync = $this->_syncTimeStamp; } - + // create xml output $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'SyncKey', $this->_syncState->counter)); - - $changes = $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Changes')); + + $changes = $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Changes')); $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Count', $count)); - + foreach($adds as $folder) { $add = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Add')); - + $folder->appendXML($add, $this->_device); // store folder in backend if (empty($folder->id)) { $this->_folderBackend->create($folder); } } - + foreach($updates as $folder) { $update = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Update')); - + $folder->appendXML($update, $this->_device); - + $this->_folderBackend->update($folder); } - + foreach($deletes as $folder) { $delete = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Delete')); $delete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'ServerId', $folder->serverId)); - + $this->_folderBackend->delete($folder); } - + if (empty($this->_syncState->id)) { $this->_syncStateBackend->create($this->_syncState); } else { $this->_syncStateBackend->update($this->_syncState); } - + return $this->_outputDom; - } + } } diff --git a/lib/ext/Syncroton/Command/FolderUpdate.php b/lib/ext/Syncroton/Command/FolderUpdate.php index e3134bc..61c7144 100644 --- a/lib/ext/Syncroton/Command/FolderUpdate.php +++ b/lib/ext/Syncroton/Command/FolderUpdate.php @@ -1,109 +1,113 @@ */ /** * class to handle ActiveSync FolderUpdate command * * @package Syncroton * @subpackage Command */ -class Syncroton_Command_FolderUpdate extends Syncroton_Command_Wbxml -{ +class Syncroton_Command_FolderUpdate extends Syncroton_Command_Wbxml +{ protected $_defaultNameSpace = 'uri:FolderHierarchy'; protected $_documentElement = 'FolderUpdate'; - + /** * @var Syncroton_Model_IFolder */ protected $_folder; - + /** - * + * * @var Syncroton_Model_Folder */ protected $_folderUpdate; - + /** * parse FolderUpdate request * */ public function handle() { $xml = simplexml_import_dom($this->_requestBody); - + $syncKey = (int)$xml->SyncKey; - - if ($this->_logger instanceof Zend_Log) + + 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) { return; } - + $updatedFolder = new Syncroton_Model_Folder($xml); - - if ($this->_logger instanceof Zend_Log) - $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " parentId: {$updatedFolder->parentId} displayName: {$updatedFolder->displayName}"); - + + if ($this->_logger instanceof Zend_Log) { + $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " parentId: {$updatedFolder->parentId} displayName: {$updatedFolder->displayName}"); + } + try { $folder = $this->_folderBackend->getFolder($this->_device, $updatedFolder->serverId); - + $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); - + } catch (Syncroton_Exception_NotFound $senf) { - if ($this->_logger instanceof Zend_Log) + 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); // @phpstan-ignore-line } - + /** * generate FolderUpdate response * * @todo currently we support only the main folder which contains all contacts/tasks/events/notes per class */ - public function getResponse($_keepSession = FALSE) + public function getResponse($_keepSession = false) { $folderUpdate = $this->_outputDom->documentElement; - + if (!$this->_syncState instanceof Syncroton_Model_SyncState) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $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)); - + } + $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; - + // 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', 'Status', Syncroton_Command_FolderSync::STATUS_SUCCESS)); $folderUpdate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'SyncKey', $this->_syncState->counter)); } - + return $this->_outputDom; - } + } } diff --git a/lib/ext/Syncroton/Command/GetAttachment.php b/lib/ext/Syncroton/Command/GetAttachment.php index e7d66fb..050ef1d 100644 --- a/lib/ext/Syncroton/Command/GetAttachment.php +++ b/lib/ext/Syncroton/Command/GetAttachment.php @@ -1,67 +1,67 @@ */ /** * class to handle ActiveSync GetAttachment command * * @package Syncroton * @subpackage Command */ class Syncroton_Command_GetAttachment extends Syncroton_Command_Wbxml { /** * * @var string */ protected $_attachmentName; - + protected $_skipValidatePolicyKey = true; - + /** - * process the XML file and add, change, delete or fetches data + * process the XML file and add, change, delete or fetches data */ public function handle() { $this->_attachmentName = $this->_requestParameters['attachmentName']; } - + /** * this function generates the response for the client - * + * * @return void */ public function getResponse() { $dataController = Syncroton_Data_Factory::factory(Syncroton_Data_Factory::CLASS_EMAIL, $this->_device, $this->_syncTimeStamp); - + $attachment = $dataController->getFileReference($this->_attachmentName); - + if (PHP_SAPI !== 'cli') { - // cache for 3600 seconds + // cache for 3600 seconds $maxAge = 3600; - $now = new DateTime('now', new DateTimeZone('UTC')); - header('Cache-Control: private, max-age=' . $maxAge); - header("Expires: " . gmdate('D, d M Y H:i:s', $now->modify("+{$maxAge} sec")->getTimestamp()) . " GMT"); - - // overwrite Pragma header from session - header("Pragma: cache"); - - #header('Content-Disposition: attachment; filename="' . $filename . '"'); - header("Content-Type: " . $attachment->contentType); + $now = new DateTime('now', new DateTimeZone('UTC')); + header('Cache-Control: private, max-age=' . $maxAge); + header("Expires: " . gmdate('D, d M Y H:i:s', $now->modify("+{$maxAge} sec")->getTimestamp()) . " GMT"); + + // overwrite Pragma header from session + header("Pragma: cache"); + + #header('Content-Disposition: attachment; filename="' . $filename . '"'); + header("Content-Type: " . $attachment->contentType); } - + if (is_resource($attachment->data)) { fpassthru($attachment->data); } else { echo $attachment->data; } } } diff --git a/lib/ext/Syncroton/Command/GetItemEstimate.php b/lib/ext/Syncroton/Command/GetItemEstimate.php index c1ff330..6b4cad1 100644 --- a/lib/ext/Syncroton/Command/GetItemEstimate.php +++ b/lib/ext/Syncroton/Command/GetItemEstimate.php @@ -1,147 +1,151 @@ */ /** * class to handle ActiveSync GetItemEstimate command * * @package Syncroton * @subpackage Command */ -class Syncroton_Command_GetItemEstimate extends Syncroton_Command_Wbxml +class Syncroton_Command_GetItemEstimate extends Syncroton_Command_Wbxml { - const STATUS_SUCCESS = 1; - const STATUS_INVALID_COLLECTION = 2; - const STATUS_SYNC_STATE_NOT_PRIMED = 3; - const STATUS_INVALID_SYNC_KEY = 4; - + public const STATUS_SUCCESS = 1; + public const STATUS_INVALID_COLLECTION = 2; + public const STATUS_SYNC_STATE_NOT_PRIMED = 3; + public const STATUS_INVALID_SYNC_KEY = 4; + protected $_defaultNameSpace = 'uri:ItemEstimate'; protected $_documentElement = 'GetItemEstimate'; - + /** * list of collections * * @var array */ - protected $_collections = array(); - + protected $_collections = []; + /** */ public function handle() { $xml = simplexml_import_dom($this->_requestBody); - + foreach ($xml->Collections->Collection as $xmlCollection) { - + // fetch values from a different namespace $airSyncValues = $xmlCollection->children('uri:AirSync'); - - $collectionData = array( + + $collectionData = [ 'syncKey' => (int)$airSyncValues->SyncKey, 'collectionId' => (string) $xmlCollection->CollectionId, 'class' => isset($xmlCollection->Class) ? (string) $xmlCollection->Class : null, - 'filterType' => isset($airSyncValues->Options) && isset($airSyncValues->Options->FilterType) ? (int)$airSyncValues->Options->FilterType : 0 - ); - - if ($this->_logger instanceof Zend_Log) + 'filterType' => isset($airSyncValues->Options) && isset($airSyncValues->Options->FilterType) ? (int)$airSyncValues->Options->FilterType : 0, + ]; + + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " synckey is {$collectionData['syncKey']} class: {$collectionData['class']} collectionid: {$collectionData['collectionId']} filtertype: {$collectionData['filterType']}"); - + } + try { // does the folder exist? $collectionData['folder'] = $this->_folderBackend->getFolder($this->_device, $collectionData['collectionId']); $collectionData['folder']->lastfiltertype = $collectionData['filterType']; - + if($collectionData['syncKey'] === 0) { - $collectionData['syncState'] = new Syncroton_Model_SyncState(array( + $collectionData['syncState'] = new Syncroton_Model_SyncState([ 'device_id' => $this->_device, 'counter' => 0, 'type' => $collectionData['folder'], - 'lastsync' => $this->_syncTimeStamp - )); - + 'lastsync' => $this->_syncTimeStamp, + ]); + // reset sync state for this folder $this->_syncStateBackend->resetState($this->_device, $collectionData['folder']); $this->_contentStateBackend->resetState($this->_device, $collectionData['folder']); - + } else { $collectionData['syncState'] = $this->_syncStateBackend->validate($this->_device, $collectionData['folder'], $collectionData['syncKey']); } } catch (Syncroton_Exception_NotFound $senf) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " " . $senf->getMessage()); + } } - + $this->_collections[$collectionData['collectionId']] = $collectionData; } - } - + } + /** * (non-PHPdoc) * @see Syncroton_Command_Wbxml::getResponse() */ public function getResponse() { $itemEstimate = $this->_outputDom->documentElement; - + foreach($this->_collections as $collectionData) { $response = $itemEstimate->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Response')); // invalid collectionid provided if (empty($collectionData['folder'])) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " folder does not exist"); - + } + $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Status', self::STATUS_INVALID_COLLECTION)); $collection = $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Collection')); $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'CollectionId', $collectionData['collectionId'])); $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Estimate', 0)); - + } elseif (! ($collectionData['syncState'] instanceof Syncroton_Model_ISyncState)) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " invalid synckey ${collectionData['syncKey']} provided"); + } /* * Android phones (and maybe others) don't take care about status 4(INVALID_SYNC_KEY) * To solve the problem we always return status 1(SUCCESS) even the sync key is invalid with Estimate set to 1. * This way the phone gets forced to sync. Handling invalid synckeys during sync command works without any problems. - * + * $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Status', self::STATUS_INVALID_SYNC_KEY)); $collection = $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Collection')); - $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'CollectionId', $collectionData['collectionId'])); + $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'CollectionId', $collectionData['collectionId'])); $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Estimate', 0)); */ - + $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Status', self::STATUS_SUCCESS)); $collection = $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Collection')); - $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'CollectionId', $collectionData['collectionId'])); - $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Estimate', 1)); + $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'CollectionId', $collectionData['collectionId'])); + $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Estimate', 1)); } else { $dataController = Syncroton_Data_Factory::factory($collectionData['folder']->class, $this->_device, $this->_syncTimeStamp); - + $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Status', self::STATUS_SUCCESS)); $collection = $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Collection')); $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'CollectionId', $collectionData['collectionId'])); if($collectionData['syncState']->counter === 0) { // this is the first sync. in most cases there are data on the server. $count = count($dataController->getServerEntries($collectionData['collectionId'], $collectionData['filterType'])); } else { $count = $dataController->getCountOfChanges($this->_contentStateBackend, $collectionData['folder'], $collectionData['syncState']); } $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Estimate', $count)); } - + // folderState can be NULL in case of not existing folder if (isset($collectionData['folder']) && $collectionData['folder']->isDirty()) { $this->_folderBackend->update($collectionData['folder']); } } - + return $this->_outputDom; } } diff --git a/lib/ext/Syncroton/Command/ICommand.php b/lib/ext/Syncroton/Command/ICommand.php index b3df712..164112d 100644 --- a/lib/ext/Syncroton/Command/ICommand.php +++ b/lib/ext/Syncroton/Command/ICommand.php @@ -1,45 +1,45 @@ */ /** * interface for all Syncroton command classes * * @package Syncroton * @subpackage Command */ -interface Syncroton_Command_ICommand +interface Syncroton_Command_ICommand { /** * constructor of this class - * + * * @param resource $_requestBody * @param Syncroton_Model_IDevice $_device * @param array $_requestParams */ public function __construct($_requestBody, Syncroton_Model_IDevice $_device, $_requestParams = []); - + /** - * process the incoming data + * process the incoming data */ public function handle(); /** * create the response */ public function getResponse(); - + /** * return headers of command - * + * * @return array list of headers */ public function getHeaders(); } diff --git a/lib/ext/Syncroton/Command/ItemOperations.php b/lib/ext/Syncroton/Command/ItemOperations.php index 1353467..0f3fafe 100644 --- a/lib/ext/Syncroton/Command/ItemOperations.php +++ b/lib/ext/Syncroton/Command/ItemOperations.php @@ -1,307 +1,305 @@ */ /** * class to handle ActiveSync ItemOperations command * * @package Syncroton * @subpackage Command */ -class Syncroton_Command_ItemOperations extends Syncroton_Command_Wbxml -{ - const STATUS_SUCCESS = 1; - const STATUS_PROTOCOL_ERROR = 2; - const STATUS_SERVER_ERROR = 3; - - const STATUS_ITEM_FAILED_CONVERSION = 14; - +class Syncroton_Command_ItemOperations extends Syncroton_Command_Wbxml +{ + public const STATUS_SUCCESS = 1; + public const STATUS_PROTOCOL_ERROR = 2; + public const STATUS_SERVER_ERROR = 3; + + public const STATUS_ITEM_FAILED_CONVERSION = 14; + protected $_defaultNameSpace = 'uri:ItemOperations'; protected $_documentElement = 'ItemOperations'; - + /** * list of items to move - * + * * @var array */ - protected $_fetches = array(); - + protected $_fetches = []; + /** * list of folder to empty - * + * * @var array */ - protected $_emptyFolderContents = array(); - + protected $_emptyFolderContents = []; + /** * parse MoveItems request * */ public function handle() { $xml = simplexml_import_dom($this->_requestBody); - + if (isset($xml->Fetch)) { foreach ($xml->Fetch as $fetch) { $this->_fetches[] = $this->_handleFetch($fetch); } } - + if (isset($xml->EmptyFolderContents)) { foreach ($xml->EmptyFolderContents as $emptyFolderContents) { $this->_emptyFolderContents[] = $this->_handleEmptyFolderContents($emptyFolderContents); } } } - + /** * generate ItemOperations response - * + * * @todo add multipart support to all types of fetches */ public function getResponse() { // add aditional namespaces - $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:AirSyncBase' , 'uri:AirSyncBase'); - $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:AirSync' , 'uri:AirSync'); - $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Search' , 'uri:Search'); - + $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:AirSyncBase', 'uri:AirSyncBase'); + $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:AirSync', 'uri:AirSync'); + $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Search', 'uri:Search'); + $itemOperations = $this->_outputDom->documentElement; - + $itemOperations->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Status', Syncroton_Command_ItemOperations::STATUS_SUCCESS)); - + $response = $itemOperations->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Response')); - + foreach ($this->_fetches as $fetch) { $fetchTag = $response->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Fetch')); - + try { $dataController = Syncroton_Data_Factory::factory($fetch['store'], $this->_device, $this->_syncTimeStamp); - + if (isset($fetch['collectionId'])) { $fetchTag->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Status', Syncroton_Command_ItemOperations::STATUS_SUCCESS)); $fetchTag->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'CollectionId', $fetch['collectionId'])); - $fetchTag->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ServerId', $fetch['serverId'])); - + $fetchTag->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ServerId', $fetch['serverId'])); + $properties = $this->_outputDom->createElementNS('uri:ItemOperations', 'Properties'); $dataController - ->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $fetch['collectionId'], 'options' => $fetch['options'])), $fetch['serverId']) + ->getEntry(new Syncroton_Model_SyncCollection(['collectionId' => $fetch['collectionId'], 'options' => $fetch['options']]), $fetch['serverId']) ->appendXML($properties, $this->_device); $fetchTag->appendChild($properties); - + } elseif (isset($fetch['longId'])) { $fetchTag->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Status', Syncroton_Command_ItemOperations::STATUS_SUCCESS)); $fetchTag->appendChild($this->_outputDom->createElementNS('uri:Search', 'LongId', $fetch['longId'])); - + $properties = $this->_outputDom->createElementNS('uri:ItemOperations', 'Properties'); $dataController - ->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $fetch['longId'], 'options' => $fetch['options'])), $fetch['longId']) + ->getEntry(new Syncroton_Model_SyncCollection(['collectionId' => $fetch['longId'], 'options' => $fetch['options']]), $fetch['longId']) ->appendXML($properties, $this->_device); $fetchTag->appendChild($properties); - + } elseif (isset($fetch['fileReference'])) { $fetchTag->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Status', Syncroton_Command_ItemOperations::STATUS_SUCCESS)); $fetchTag->appendChild($this->_outputDom->createElementNS('uri:AirSyncBase', 'FileReference', $fetch['fileReference'])); $properties = $this->_outputDom->createElementNS('uri:ItemOperations', 'Properties'); - + $fileReference = $dataController->getFileReference($fetch['fileReference']); - + // unset data field and move content to stream if (!empty($this->_requestParameters['acceptMultipart'])) { $this->_headers['Content-Type'] = 'application/vnd.ms-sync.multipart'; - + $partStream = fopen("php://temp", 'r+'); - + if (is_resource($fileReference->data)) { stream_copy_to_stream($fileReference->data, $partStream); } else { fwrite($partStream, $fileReference->data); } - + unset($fileReference->data); - + $this->_parts[] = $partStream; - + $fileReference->part = count($this->_parts); - } - + } + /** * the client requested a range. But we return the whole file. - * + * * That's not correct, but allowed. The server is allowed to overwrite the range. - * + * * @todo implement cutting $fileReference->data into pieces */ if (isset($fetch['options']['range'])) { $dataSize = $this->_getDataSize($fileReference->data); - + $total = $this->_outputDom->createElementNS('uri:ItemOperations', 'Total', $dataSize); $properties->appendChild($total); - - $rangeEnd = $dataSize > 0 ? $dataSize - 1 : 0; + + $rangeEnd = $dataSize > 0 ? $dataSize - 1 : 0; $range = $this->_outputDom->createElementNS('uri:ItemOperations', 'Range', '0-' . $rangeEnd); $properties->appendChild($range); } - + $fileReference->appendXML($properties, $this->_device); - + $fetchTag->appendChild($properties); } } catch (Syncroton_Exception_NotFound $e) { $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(); $response->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Status', Syncroton_Command_ItemOperations::STATUS_SERVER_ERROR)); } } - + foreach ($this->_emptyFolderContents as $emptyFolderContents) { - + try { $folder = $this->_folderBackend->getFolder($this->_device, $emptyFolderContents['collectionId']); $dataController = Syncroton_Data_Factory::factory($folder->class, $this->_device, $this->_syncTimeStamp); $dataController->emptyFolderContents($emptyFolderContents['collectionId'], $emptyFolderContents['options']); $status = Syncroton_Command_ItemOperations::STATUS_SUCCESS; - } - catch (Syncroton_Exception_Status_ItemOperations $e) { + } catch (Syncroton_Exception_Status_ItemOperations $e) { $status = $e->getCode(); - } - catch (Exception $e) { + } catch (Exception $e) { $status = Syncroton_Exception_Status_ItemOperations::ITEM_SERVER_ERROR; } $emptyFolderContentsTag = $this->_outputDom->createElementNS('uri:ItemOperations', 'EmptyFolderContents'); - + $emptyFolderContentsTag->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Status', $status)); $emptyFolderContentsTag->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'CollectionId', $emptyFolderContents['collectionId'])); - + $response->appendChild($emptyFolderContentsTag); } - + return $this->_outputDom; } - + /** * parse fetch request - * + * * @param SimpleXMLElement $fetch * @return array */ protected function _handleFetch(SimpleXMLElement $fetch) { - $fetchArray = array( + $fetchArray = [ 'store' => (string)$fetch->Store, - 'options' => array() - ); - + 'options' => [], + ]; + // try to fetch element from namespace AirSync $airSync = $fetch->children('uri:AirSync'); - + if (isset($airSync->CollectionId)) { $fetchArray['collectionId'] = (string)$airSync->CollectionId; $fetchArray['serverId'] = (string)$airSync->ServerId; } - + // try to fetch element from namespace Search $search = $fetch->children('uri:Search'); - + if (isset($search->LongId)) { $fetchArray['longId'] = (string)$search->LongId; } - + // try to fetch element from namespace AirSyncBase $airSyncBase = $fetch->children('uri:AirSyncBase'); - + if (isset($airSyncBase->FileReference)) { $fetchArray['fileReference'] = (string)$airSyncBase->FileReference; } - + if (isset($fetch->Options)) { // try to fetch element from namespace AirSyncBase $airSyncBase = $fetch->Options->children('uri:AirSyncBase'); - + if (isset($airSyncBase->BodyPreference)) { foreach ($airSyncBase->BodyPreference as $bodyPreference) { $type = (int) $bodyPreference->Type; - $fetchArray['options']['bodyPreferences'][$type] = array( - 'type' => $type - ); - + $fetchArray['options']['bodyPreferences'][$type] = [ + 'type' => $type, + ]; + // optional if (isset($bodyPreference->TruncationSize)) { $fetchArray['options']['bodyPreferences'][$type]['truncationSize'] = (int) $bodyPreference->TruncationSize; } - + // optional if (isset($bodyPreference->AllOrNone)) { $fetchArray['options']['bodyPreferences'][$type]['allOrNone'] = (int) $bodyPreference->AllOrNone; } } } $airSync = $fetch->Options->children('uri:AirSync'); if (isset($airSync->MIMESupport)) { $fetchArray['options']['mimeSupport'] = (int) $airSync->MIMESupport; } - + if (isset($fetch->Options->Range)) { $fetchArray['options']['range'] = (string) $fetch->Options->Range; } } - + return $fetchArray; } - + /** * handle empty folder request - * + * * @param SimpleXMLElement $emptyFolderContent * @return array */ protected function _handleEmptyFolderContents(SimpleXMLElement $emptyFolderContent) { - $folderArray = array( + $folderArray = [ 'collectiondId' => null, - 'options' => array('deleteSubFolders' => FALSE) - ); - + 'options' => ['deleteSubFolders' => false], + ]; + // try to fetch element from namespace AirSync $airSync = $emptyFolderContent->children('uri:AirSync'); - + $folderArray['collectionId'] = (string)$airSync->CollectionId; - + if (isset($emptyFolderContent->Options)) { - $folderArray['options']['deleteSubFolders'] = isset($emptyFolderContent->Options->DeleteSubFolders); + $folderArray['options']['deleteSubFolders'] = isset($emptyFolderContent->Options->DeleteSubFolders); } - + return $folderArray; } /** * return length of data - * + * * @param string|resource $data * @return number */ protected function _getDataSize($data) { if (is_resource($data)) { rewind($data); fseek($data, 0, SEEK_END); return ftell($data); } else { return strlen($data); } } } diff --git a/lib/ext/Syncroton/Command/MeetingResponse.php b/lib/ext/Syncroton/Command/MeetingResponse.php index 696295f..1597ba0 100644 --- a/lib/ext/Syncroton/Command/MeetingResponse.php +++ b/lib/ext/Syncroton/Command/MeetingResponse.php @@ -1,86 +1,86 @@ */ /** * class to handle ActiveSync MeetingResponse command * * @package Syncroton * @subpackage Command */ class Syncroton_Command_MeetingResponse extends Syncroton_Command_Wbxml { - protected $_results = array(); - + protected $_results = []; + protected $_defaultNameSpace = 'uri:MeetingResponse'; protected $_documentElement = 'MeetingResponse'; /** * parse MeetingResponse request */ public function handle() { /** @var Syncroton_Data_IDataCalendar $dataController */ $dataController = Syncroton_Data_Factory::factory(Syncroton_Data_Factory::CLASS_CALENDAR, $this->_device, $this->_syncTimeStamp); - + $xml = simplexml_import_dom($this->_requestBody); foreach ($xml as $meetingResponse) { $request = new Syncroton_Model_MeetingResponse($meetingResponse); - + try { $calendarId = $dataController->setAttendeeStatus($request); - - $this->_results[] = array( + + $this->_results[] = [ 'calendarId' => $calendarId, 'request' => $request, - 'status' => 1 - ); - + 'status' => 1, + ]; + } catch (Syncroton_Exception_Status_MeetingResponse $sesmr) { - $this->_results[] = array( + $this->_results[] = [ 'request' => $request, - 'status' => $sesmr->getCode() - ); + 'status' => $sesmr->getCode(), + ]; } } } /** * generate MeetingResponse response */ public function getResponse() { $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Search', 'uri:Search'); - + $meetingResponse = $this->_outputDom->documentElement; foreach ($this->_results as $result) { $resultElement = $this->_outputDom->createElementNS('uri:MeetingResponse', 'Result'); - + if (isset($result['request']->requestId)) { $resultElement->appendChild($this->_outputDom->createElementNS('uri:MeetingResponse', 'RequestId', $result['request']->requestId)); } elseif (isset($result['request']->longId)) { $resultElement->appendChild($this->_outputDom->createElementNS('uri:Search', 'LongId', $result['request']->longId)); } - + $resultElement->appendChild($this->_outputDom->createElementNS('uri:MeetingResponse', 'Status', $result['status'])); - + if (isset($result['calendarId'])) { $resultElement->appendChild($this->_outputDom->createElementNS('uri:MeetingResponse', 'CalendarId', $result['calendarId'])); } - + $meetingResponse->appendChild($resultElement); - } - + } + return $this->_outputDom; } } diff --git a/lib/ext/Syncroton/Command/MoveItems.php b/lib/ext/Syncroton/Command/MoveItems.php index 3f89b34..9c92469 100644 --- a/lib/ext/Syncroton/Command/MoveItems.php +++ b/lib/ext/Syncroton/Command/MoveItems.php @@ -1,97 +1,97 @@ * @author Aleksander Machniak */ /** * class to handle ActiveSync MoveItems command * * @package Syncroton * @subpackage Command */ class Syncroton_Command_MoveItems extends Syncroton_Command_Wbxml { - const STATUS_SUCCESS = 3; + public const STATUS_SUCCESS = 3; protected $_defaultNameSpace = 'uri:Move'; protected $_documentElement = 'MoveItems'; /** * list of items to move * * @var array */ - protected $_moves = array(); + protected $_moves = []; /** * parse MoveItems request */ public function handle() { $xml = simplexml_import_dom($this->_requestBody); foreach ($xml->Move as $move) { - $this->_moves[] = array( + $this->_moves[] = [ 'srcMsgId' => (string)$move->SrcMsgId, 'srcFldId' => (string)$move->SrcFldId, - 'dstFldId' => (string)$move->DstFldId - ); + 'dstFldId' => (string)$move->DstFldId, + ]; } } /** * generate MoveItems response */ public function getResponse() { $moves = $this->_outputDom->documentElement; foreach ($this->_moves as $move) { $response = $moves->appendChild($this->_outputDom->createElementNS('uri:Move', 'Response')); $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'SrcMsgId', $move['srcMsgId'])); try { if ($move['srcFldId'] === $move['dstFldId']) { throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::SAME_FOLDER); } try { $sourceFolder = $this->_folderBackend->getFolder($this->_device, $move['srcFldId']); } catch (Syncroton_Exception_NotFound $e) { throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_SOURCE); } try { $destinationFolder = $this->_folderBackend->getFolder($this->_device, $move['dstFldId']); } catch (Syncroton_Exception_NotFound $senf) { throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_DESTINATION); } $dataController = Syncroton_Data_Factory::factory($sourceFolder->class, $this->_device, $this->_syncTimeStamp); $newId = $dataController->moveItem($move['srcFldId'], $move['srcMsgId'], $move['dstFldId']); if (!$newId) { throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_SOURCE); } $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'Status', Syncroton_Command_MoveItems::STATUS_SUCCESS)); $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'DstMsgId', $newId)); } catch (Syncroton_Exception_Status $e) { $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'Status', $e->getCode())); } catch (Exception $e) { $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'Status', Syncroton_Exception_Status::SERVER_ERROR)); } } return $this->_outputDom; } } diff --git a/lib/ext/Syncroton/Command/Options.php b/lib/ext/Syncroton/Command/Options.php index 415ff6b..cd47e6b 100644 --- a/lib/ext/Syncroton/Command/Options.php +++ b/lib/ext/Syncroton/Command/Options.php @@ -1,34 +1,34 @@ */ /** * class to handle ActiveSync http options request * * @package Syncroton * @subpackage Command */ class Syncroton_Command_Options { /** * this function generates the response for the client * * @return array */ public function getHeaders() { // same header like Exchange 2xxx??? - return array( + return [ 'MS-Server-ActiveSync' => '14.00.0536.000', 'MS-ASProtocolVersions' => '2.5,12.0,12.1,14.0,14.1', - 'MS-ASProtocolCommands' => 'FolderCreate,FolderDelete,FolderSync,FolderUpdate,GetAttachment,GetItemEstimate,ItemOperations,MeetingResponse,MoveItems,Provision,ResolveRecipients,Ping,SendMail,Search,Settings,SmartForward,SmartReply,Sync,ValidateCert' - ); + 'MS-ASProtocolCommands' => 'FolderCreate,FolderDelete,FolderSync,FolderUpdate,GetAttachment,GetItemEstimate,ItemOperations,MeetingResponse,MoveItems,Provision,ResolveRecipients,Ping,SendMail,Search,Settings,SmartForward,SmartReply,Sync,ValidateCert', + ]; } } diff --git a/lib/ext/Syncroton/Command/Ping.php b/lib/ext/Syncroton/Command/Ping.php index ca6227d..d7abf59 100644 --- a/lib/ext/Syncroton/Command/Ping.php +++ b/lib/ext/Syncroton/Command/Ping.php @@ -1,280 +1,294 @@ */ /** * class to handle ActiveSync Ping command * * @package Syncroton * @subpackage Command */ -class Syncroton_Command_Ping extends Syncroton_Command_Wbxml +class Syncroton_Command_Ping extends Syncroton_Command_Wbxml { - const STATUS_NO_CHANGES_FOUND = 1; - const STATUS_CHANGES_FOUND = 2; - const STATUS_MISSING_PARAMETERS = 3; - const STATUS_REQUEST_FORMAT_ERROR = 4; - const STATUS_INTERVAL_TO_GREAT_OR_SMALL = 5; - const STATUS_TOO_MANY_FOLDERS = 6; - const STATUS_FOLDER_NOT_FOUND = 7; - const STATUS_GENERAL_ERROR = 8; - - const MAX_PING_INTERVAL = 3540; // 59 minutes limit defined in Activesync protocol spec. - + public const STATUS_NO_CHANGES_FOUND = 1; + public const STATUS_CHANGES_FOUND = 2; + public const STATUS_MISSING_PARAMETERS = 3; + public const STATUS_REQUEST_FORMAT_ERROR = 4; + public const STATUS_INTERVAL_TO_GREAT_OR_SMALL = 5; + public const STATUS_TOO_MANY_FOLDERS = 6; + public const STATUS_FOLDER_NOT_FOUND = 7; + public const STATUS_GENERAL_ERROR = 8; + + public const MAX_PING_INTERVAL = 3540; // 59 minutes limit defined in Activesync protocol spec. + protected $_defaultNameSpace = 'uri:Ping'; protected $_documentElement = 'Ping'; protected $_skipValidatePolicyKey = true; protected $_changesDetected = false; - protected $_foldersWithChanges = array(); - + protected $_foldersWithChanges = []; + /** - * process the XML file and add, change, delete or fetches data + * process the XML file and add, change, delete or fetches data * * @todo can we get rid of LIBXML_NOWARNING * @todo we need to stored the initial data for folders and lifetime as the phone is sending them only when they change */ public function handle() { $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); $xml->registerXPathNamespace('Ping', 'Ping'); if(isset($xml->HeartbeatInterval)) { $this->_device->pinglifetime = (int)$xml->HeartbeatInterval; } - + if (isset($xml->Folders->Folder)) { $maxCollections = Syncroton_Registry::getMaxCollections(); if ($maxCollections && count($xml->Folders->Folder) > $maxCollections) { $ping = $this->_outputDom->documentElement; $ping->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Status', self::STATUS_TOO_MANY_FOLDERS)); $ping->appendChild($this->_outputDom->createElementNS('uri:Ping', 'MaxFolders', $maxCollections)); return; } - $folders = array(); + $folders = []; foreach ($xml->Folders->Folder as $folderXml) { try { // does the folder exist? $folder = $this->_folderBackend->getFolder($this->_device, (string)$folderXml->Id); - + $folders[$folder->id] = $folder; } catch (Syncroton_Exception_NotFound $senf) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " " . $senf->getMessage()); + } $status = self::STATUS_FOLDER_NOT_FOUND; break; } } $this->_device->pingfolder = serialize(array_keys($folders)); } } - + $this->_device->lastping = new DateTime('now', new DateTimeZone('UTC')); if ($status == self::STATUS_NO_CHANGES_FOUND) { $this->_device = $this->_deviceBackend->update($this->_device); // @phpstan-ignore-line } - + $lifeTime = $this->_device->pinglifetime; $maxInterval = Syncroton_Registry::getPingInterval(); if ($maxInterval <= 0 || $maxInterval > Syncroton_Server::MAX_HEARTBEAT_INTERVAL) { $maxInterval = Syncroton_Server::MAX_HEARTBEAT_INTERVAL; } if ($lifeTime > $maxInterval) { $ping = $this->_outputDom->documentElement; $ping->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Status', self::STATUS_INTERVAL_TO_GREAT_OR_SMALL)); $ping->appendChild($this->_outputDom->createElementNS('uri:Ping', 'HeartbeatInterval', $maxInterval)); return; } - + $intervalEnd = $intervalStart + $lifeTime; $secondsLeft = $intervalEnd; - - $folders = $this->_device->pingfolder ? unserialize($this->_device->pingfolder) : array(); - + + $folders = $this->_device->pingfolder ? unserialize($this->_device->pingfolder) : []; + if ($status === self::STATUS_NO_CHANGES_FOUND && (!is_array($folders) || count($folders) == 0)) { $status = self::STATUS_MISSING_PARAMETERS; } - - if ($this->_logger instanceof Zend_Log) + + 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) { $sleepCallback = Syncroton_Registry::getSleepCallback(); $wakeupCallback = Syncroton_Registry::getWakeupCallback(); do { // take a break to save battery lifetime call_user_func($sleepCallback); sleep(Syncroton_Registry::getPingTimeout()); // make sure the connection is still alive, abort otherwise if (connection_aborted()) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " Exiting on aborted connection"); + } exit; } // reconnect external connections, etc. call_user_func($wakeupCallback); // Calculate secondsLeft before any loop break just to have a correct value // for logging purposes in case we breaked from the loop early $secondsLeft = $intervalEnd - time(); try { /** @var Syncroton_Model_Device $device */ $device = $this->_deviceBackend->get($this->_device->id); } catch (Syncroton_Exception_NotFound $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " " . $e->getMessage()); + } $status = self::STATUS_FOLDER_NOT_FOUND; break; } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->err(__METHOD__ . '::' . __LINE__ . " " . $e->getMessage()); + } // do nothing, maybe temporal issue, should we stop? continue; } // if another Ping command updated lastping property, we can stop processing this Ping command request if ((isset($device->lastping) && $device->lastping instanceof DateTime) && $device->pingfolder === $this->_device->pingfolder && $device->lastping->getTimestamp() > $this->_device->lastping->getTimestamp() ) { break; } // If folders hierarchy changed, break the loop and ask the client for FolderSync try { if ($this->_folderBackend->hasHierarchyChanges($this->_device)) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . ' Detected changes in folders hierarchy'); + } $status = self::STATUS_FOLDER_NOT_FOUND; break; } } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->err(__METHOD__ . '::' . __LINE__ . " " . $e->getMessage()); + } // do nothing, maybe temporal issue, should we stop? continue; } $now = new DateTime('now', new DateTimeZone('UTC')); - + foreach ($folders as $folderId) { try { /** @var Syncroton_Model_Folder $folder */ $folder = $this->_folderBackend->get($folderId); $dataController = Syncroton_Data_Factory::factory($folder->class, $this->_device, $this->_syncTimeStamp); - + } catch (Syncroton_Exception_NotFound $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " " . $e->getMessage()); + } $status = self::STATUS_FOLDER_NOT_FOUND; - + break; - + } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->err(__METHOD__ . '::' . __LINE__ . " " . $e->getMessage()); - + } + // do nothing, maybe temporal issue, should we stop? continue; } 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 Syncroton_Registry::getQuietTime() seconds ago if (($now->getTimestamp() - $syncState->lastsync->getTimestamp()) < Syncroton_Registry::getQuietTime()) { continue; } - + $foundChanges = $dataController->hasChanges($this->_contentStateBackend, $folder, $syncState); - + } catch (Syncroton_Exception_NotFound $e) { // folder got never synchronized to client - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " " . $e->getMessage()); - if ($this->_logger instanceof Zend_Log) + } + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' syncstate not found. enforce sync for folder: ' . $folder->serverId); - + } + $foundChanges = true; } - + if ($foundChanges == true) { $this->_foldersWithChanges[] = $folder; $status = self::STATUS_CHANGES_FOUND; } } - + if ($status != self::STATUS_NO_CHANGES_FOUND) { break; } // Update secondsLeft (again) $secondsLeft = $intervalEnd - time(); - - if ($this->_logger instanceof Zend_Log) + + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " DeviceId: " . $this->_device->deviceid . " seconds left: " . $secondsLeft); - - // See: http://www.tine20.org/forum/viewtopic.php?f=12&t=12146 - // - // break if there are less than PingTimeout + 10 seconds left for the next loop - // otherwise the response will be returned after the client has finished his Ping - // request already maybe + } + + // See: http://www.tine20.org/forum/viewtopic.php?f=12&t=12146 + // + // break if there are less than PingTimeout + 10 seconds left for the next loop + // otherwise the response will be returned after the client has finished his Ping + // request already maybe } while (Syncroton_Server::validateSession() && $secondsLeft > (Syncroton_Registry::getPingTimeout() + 10)); } - - if ($this->_logger instanceof Zend_Log) + + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " DeviceId: " . $this->_device->deviceid . " Lifetime: $lifeTime SecondsLeft: $secondsLeft Status: $status)"); - + } + $ping = $this->_outputDom->documentElement; $ping->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Status', $status)); if($status === self::STATUS_CHANGES_FOUND) { $folders = $ping->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Folders')); - + foreach($this->_foldersWithChanges as $changedFolder) { $folder = $folders->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Folder', $changedFolder->serverId)); - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " DeviceId: " . $this->_device->deviceid . " changes in folder: " . $changedFolder->serverId); + } } } } - + /** * generate ping command response * */ public function getResponse() { return $this->_outputDom; } } diff --git a/lib/ext/Syncroton/Command/Provision.php b/lib/ext/Syncroton/Command/Provision.php index ae07cd7..2259e0d 100644 --- a/lib/ext/Syncroton/Command/Provision.php +++ b/lib/ext/Syncroton/Command/Provision.php @@ -1,199 +1,203 @@ */ /** * class to handle ActiveSync Provision command * * @package Syncroton * @subpackage Command */ class Syncroton_Command_Provision extends Syncroton_Command_Wbxml { protected $_defaultNameSpace = 'uri:Provision'; protected $_documentElement = 'Provision'; - - const POLICYTYPE_WBXML = 'MS-EAS-Provisioning-WBXML'; - - const STATUS_SUCCESS = 1; - const STATUS_PROTOCOL_ERROR = 2; - 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; - + + public const POLICYTYPE_WBXML = 'MS-EAS-Provisioning-WBXML'; + + public const STATUS_SUCCESS = 1; + public const STATUS_PROTOCOL_ERROR = 2; + public const STATUS_GENERAL_SERVER_ERROR = 3; + public const STATUS_DEVICE_MANAGED_EXTERNALLY = 4; + + public const STATUS_POLICY_SUCCESS = 1; + public const STATUS_POLICY_NOPOLICY = 2; + public const STATUS_POLICY_UNKNOWNTYPE = 3; + public const STATUS_POLICY_CORRUPTED = 4; + public const STATUS_POLICY_WRONGPOLICYKEY = 5; + + public const REMOTEWIPE_REQUESTED = 1; + public const REMOTEWIPE_CONFIRMED = 2; + protected $_skipValidatePolicyKey = true; - + protected $_policyType; protected $_sendPolicyKey; - + /** * @var Syncroton_Model_DeviceInformation */ protected $_deviceInformation; - + /** - * process the XML file and add, change, delete or fetches data + * process the XML file and add, change, delete or fetches data */ public function handle() { $xml = simplexml_import_dom($this->_requestBody); - + $this->_policyType = isset($xml->Policies->Policy->PolicyType) ? (string) $xml->Policies->Policy->PolicyType : null; - $this->_sendPolicyKey = isset($xml->Policies->Policy->PolicyKey) ? (int) $xml->Policies->Policy->PolicyKey : null; - + $this->_sendPolicyKey = isset($xml->Policies->Policy->PolicyKey) ? (int) $xml->Policies->Policy->PolicyKey : null; + if ($this->_device->remotewipe == self::REMOTEWIPE_REQUESTED && isset($xml->RemoteWipe->Status) && (int)$xml->RemoteWipe->Status == self::STATUS_SUCCESS) { $this->_device->remotewipe = self::REMOTEWIPE_CONFIRMED; } - - // try to fetch element from Settings namespace + + // try to fetch element from Settings namespace $settings = $xml->children('uri:Settings'); if (isset($settings->DeviceInformation) && isset($settings->DeviceInformation->Set)) { $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->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; } if ($this->_device->isDirty()) { $this->_device = $this->_deviceBackend->update($this->_device); // @phpstan-ignore-line } } - + /** * generate search command response * */ 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(); } else { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . ' PolicyType: ' . $this->_policyType . ' PolicyKey: ' . $this->_sendPolicyKey); - + } + if (!$this->_sendPolicyKey) { $this->_sendPolicy(); } elseif ($this->_sendPolicyKey == $this->_device->policykey) { $this->_acknowledgePolicy(); - } - } - + } + } + return $this->_outputDom; } - + /** * function the send policy to client - * + * * 4131 (Enforce password on device) 0: enabled 1: disabled * 4133 (Unlock from computer) 0: disabled 1: enabled * AEFrequencyType 0: no inactivity time 1: inactivity time is set * AEFrequencyValue inactivity time in minutes * DeviceWipeThreshold after how many worng password to device should get wiped * CodewordFrequency validate every 3 wrong passwords, that a person is using the device which is able to read and write. should be half of DeviceWipeThreshold * MinimumPasswordLength minimum password length * PasswordComplexity 0: Require alphanumeric 1: Require only numeric, 2: anything goes * */ protected function _sendPolicy() { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' send policy to device'); - + } + $provision = $sync = $this->_outputDom->documentElement; $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)); } - + // 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)); - + 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')); - + /** @var Syncroton_Model_Policy $_policy */ $_policy = $this->_policyBackend->get($this->_device->policyId); $_policy->appendXML($easProvisionDoc, $this->_device); - + $this->_deviceBackend->update($this->_device); } } - + /** * function the send remote wipe command */ protected function _sendRemoteWipe() { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . ' send remote wipe to device'); - + } + $provision = $sync = $this->_outputDom->documentElement; $provision->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Status', 1)); $provision->appendChild($this->_outputDom->createElementNS('uri:Provision', 'RemoteWipe')); } - + protected function _acknowledgePolicy() { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' acknowledge policy'); - + } + /** @var Syncroton_Model_Policy $_policy */ $_policy = $this->_policyBackend->get($this->_device->policyId); - + $provision = $sync = $this->_outputDom->documentElement; $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', $_policy->policyKey)); $this->_device->policykey = $_policy->policyKey; $this->_deviceBackend->update($this->_device); } /** * generate a random string used as PolicyKey */ public static function generatePolicyKey() { return mt_rand(1, 2147483647); } } diff --git a/lib/ext/Syncroton/Command/Search.php b/lib/ext/Syncroton/Command/Search.php index 191892a..7888d91 100644 --- a/lib/ext/Syncroton/Command/Search.php +++ b/lib/ext/Syncroton/Command/Search.php @@ -1,88 +1,91 @@ */ /** * class to handle ActiveSync Search command * * @package Syncroton * @subpackage Command */ class Syncroton_Command_Search extends Syncroton_Command_Wbxml { - const STATUS_SUCCESS = 1; - const STATUS_SERVER_ERROR = 3; + public const STATUS_SUCCESS = 1; + public const STATUS_SERVER_ERROR = 3; protected $_defaultNameSpace = 'uri:Search'; protected $_documentElement = 'Search'; /** * store data * * @var Syncroton_Model_StoreRequest */ protected $_store; /** * parse search command request * * @throws Syncroton_Exception_UnexpectedValue */ public function handle() { if (! $this->_requestBody instanceof DOMDocument) { throw new Syncroton_Exception_UnexpectedValue( - 'request body is no DOMDocument. got: ' . print_r($this->_requestBody, true)); + 'request body is no DOMDocument. got: ' . print_r($this->_requestBody, true) + ); } $xml = simplexml_import_dom($this->_requestBody); $this->_store = new Syncroton_Model_StoreRequest($xml->Store); } /** * generate search command response * */ 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'); + + if (! $dataController instanceof Syncroton_Data_IDataSearch) { + throw new RuntimeException('class must be instanceof Syncroton_Data_IDataSearch'); } - + try { // Search $storeResponse = $dataController->search($this->_store); $storeResponse->status = self::STATUS_SUCCESS; } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " search exception: " . $e->getMessage()); - if ($this->_logger instanceof Zend_Log) + } + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " saerch exception trace : " . $e->getTraceAsString()); - - $storeResponse = new Syncroton_Model_StoreResponse(array( - 'status' => self::STATUS_SERVER_ERROR - )); + } + + $storeResponse = new Syncroton_Model_StoreResponse([ + 'status' => self::STATUS_SERVER_ERROR, + ]); } $search = $this->_outputDom->documentElement; $search->appendChild($this->_outputDom->createElementNS($this->_defaultNameSpace, 'Status', self::STATUS_SUCCESS)); $response = $search->appendChild($this->_outputDom->createElementNS($this->_defaultNameSpace, 'Response')); $store = $response->appendChild($this->_outputDom->createElementNS($this->_defaultNameSpace, 'Store')); $storeResponse->appendXML($store, $this->_device); return $this->_outputDom; } } diff --git a/lib/ext/Syncroton/Command/SendMail.php b/lib/ext/Syncroton/Command/SendMail.php index e025c97..b378c5c 100644 --- a/lib/ext/Syncroton/Command/SendMail.php +++ b/lib/ext/Syncroton/Command/SendMail.php @@ -1,126 +1,129 @@ * @author Aleksander Machniak */ /** * class to handle ActiveSync SendMail command * * @package Syncroton * @subpackage Command */ class Syncroton_Command_SendMail extends Syncroton_Command_Wbxml { protected $_defaultNameSpace = 'uri:ComposeMail'; protected $_documentElement = 'SendMail'; protected $_mime; protected $_saveInSent; protected $_source; protected $_replaceMime = false; /** * Process the XML file and add, change, delete or fetches data */ public function handle() { if (isset($this->_requestParameters['contentType']) && $this->_requestParameters['contentType'] === 'message/rfc822') { $this->_mime = $this->_requestBody; $this->_saveInSent = $this->_requestParameters['saveInSent']; $this->_replaceMime = false; - $this->_source = array( + $this->_source = [ 'collectionId' => $this->_requestParameters['collectionId'], 'itemId' => $this->_requestParameters['itemId'], - 'instanceId' => null - ); + 'instanceId' => null, + ]; - } else if ($this->_requestBody) { + } elseif ($this->_requestBody) { $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)) { + if (isset($xml->Source)) { if ($xml->Source->LongId) { $this->_source = (string)$xml->Source->LongId; } else { - $this->_source = array( + $this->_source = [ 'collectionId' => (string)$xml->Source->FolderId, 'itemId' => (string)$xml->Source->ItemId, - 'instanceId' => isset($xml->Source->InstanceId) ? (string)$xml->Source->InstanceId : null - ); + 'instanceId' => isset($xml->Source->InstanceId) ? (string)$xml->Source->InstanceId : null, + ]; } } } if (empty($this->_mime)) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " Sending email failed: Empty input"); + } if (version_compare($this->_device->acsversion, '14.0', '<')) { header("HTTP/1.1 400 Invalid content"); die; } $response_type = 'Syncroton_Model_' . $this->_documentElement; - $response = new $response_type(array( + $response = new $response_type([ 'status' => Syncroton_Exception_Status::INVALID_CONTENT, - )); + ]); $response->appendXML($this->_outputDom->documentElement, $this->_device); return $this->_outputDom; } - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " saveInSent: " . (int)$this->_saveInSent); + } } /** * this function generates the response for the client * * @return void|DOMDocument */ public function getResponse() { $dataController = Syncroton_Data_Factory::factory(Syncroton_Data_Factory::CLASS_EMAIL, $this->_device, $this->_syncTimeStamp); try { $this->sendMail($dataController); } catch (Syncroton_Exception_Status $ses) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " Sending email failed: " . $ses->getMessage()); + } $response_type = 'Syncroton_Model_' . $this->_documentElement; - $response = new $response_type(array( + $response = new $response_type([ 'status' => $ses->getCode(), - )); + ]); $response->appendXML($this->_outputDom->documentElement, $this->_device); return $this->_outputDom; } } /** * Execute email sending method of data controller * To be overwritten by SmartForward and SmartReply command handlers */ protected function sendMail($dataController) { $dataController->sendEmail($this->_mime, $this->_saveInSent); } } diff --git a/lib/ext/Syncroton/Command/Settings.php b/lib/ext/Syncroton/Command/Settings.php index bc74fbe..1faa24d 100644 --- a/lib/ext/Syncroton/Command/Settings.php +++ b/lib/ext/Syncroton/Command/Settings.php @@ -1,159 +1,159 @@ */ /** * class to handle ActiveSync Settings command * * @package Syncroton * @subpackage Command */ -class Syncroton_Command_Settings extends Syncroton_Command_Wbxml +class Syncroton_Command_Settings extends Syncroton_Command_Wbxml { - const STATUS_SUCCESS = 1; - + public const STATUS_SUCCESS = 1; + protected $_defaultNameSpace = 'uri:Settings'; protected $_documentElement = 'Settings'; - + /** * @var Syncroton_Model_DeviceInformation */ protected $_deviceInformation; protected $_userInformationRequested = false; protected $_OofGet; protected $_OofSet; - - + + /** - * process the XML file and add, change, delete or fetches data + * process the XML file and add, change, delete or fetches data * */ public function handle() { $xml = simplexml_import_dom($this->_requestBody); - + if (isset($xml->DeviceInformation->Set)) { - $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->_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; if ($this->_device->isDirty()) { // @phpstan-ignore-next-line $this->_device = $this->_deviceBackend->update($this->_device); } } - + if (isset($xml->UserInformation->Get)) { $this->_userInformationRequested = true; } if (isset($xml->Oof)) { if (isset($xml->Oof->Get)) { - $this->_OofGet = array('bodyType' => $xml->Oof->Get->BodyType); - } else if (isset($xml->Oof->Set)) { + $this->_OofGet = ['bodyType' => $xml->Oof->Get->BodyType]; + } elseif (isset($xml->Oof->Set)) { $this->_OofSet = new Syncroton_Model_Oof($xml->Oof->Set); } } } - + /** * this function generates the response for the client * */ public function getResponse() { $settings = $this->_outputDom->documentElement; - + $settings->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Status', self::STATUS_SUCCESS)); - + 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)); } - + if ($this->_userInformationRequested === true) { $userInformation = $settings->appendChild($this->_outputDom->createElementNS('uri:Settings', 'UserInformation')); $userInformation->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Status', self::STATUS_SUCCESS)); $get = $userInformation->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Get')); -/* - $smtpAddresses = array(); - if (!empty($smtpAddresses)) { - $emailAddresses = $get->appendChild($this->_outputDom->createElementNS('uri:Settings', 'EmailAddresses')); - foreach($smtpAddresses as $smtpAddress) { - $emailAddresses->appendChild($this->_outputDom->createElementNS('uri:Settings', 'SMTPAddress', $smtpAddress)); - } - } -*/ + /* + $smtpAddresses = array(); + if (!empty($smtpAddresses)) { + $emailAddresses = $get->appendChild($this->_outputDom->createElementNS('uri:Settings', 'EmailAddresses')); + foreach($smtpAddresses as $smtpAddress) { + $emailAddresses->appendChild($this->_outputDom->createElementNS('uri:Settings', 'SMTPAddress', $smtpAddress)); + } + } + */ $userAccounts = $this->_deviceBackend->userAccounts($this->_device); if (!empty($userAccounts)) { $accounts = $get->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Accounts')); foreach ((array) $userAccounts as $account) { $element = $accounts->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Account')); $account->appendXML($element, $this->_device); } } } // Out-of-Office if (!empty($this->_OofGet)) { $OofGet = null; try { $OofGet = $this->_deviceBackend->getOOF($this->_OofGet); $OofStatus = self::STATUS_SUCCESS; } catch (Exception $e) { if ($e instanceof Syncroton_Exception_Status) { $OofStatus = $e->getCode(); } else { $OofStatus = Syncroton_Exception_Status::SERVER_ERROR; } if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " Setting OOF failed: " . $e->getMessage()); } } // expected empty result if OOF is not supported by the server if ($OofGet instanceof Syncroton_Model_Oof) { $Oof = $settings->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Oof')); $Oof->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Status', $OofStatus)); $Get = $Oof->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Get')); $OofGet->appendXML($Get, $this->_device); } - } else if (!empty($this->_OofSet)) { + } elseif (!empty($this->_OofSet)) { try { $this->_deviceBackend->setOOF($this->_OofSet); $OofStatus = self::STATUS_SUCCESS; } catch (Exception $e) { if ($e instanceof Syncroton_Exception_Status) { $OofStatus = $e->getCode(); } else { $OofStatus = Syncroton_Exception_Status::SERVER_ERROR; } if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " Setting OOF failed: " . $e->getMessage()); } } $Oof = $settings->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Oof')); $Oof->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Status', $OofStatus)); } return $this->_outputDom; } } diff --git a/lib/ext/Syncroton/Command/Sync.php b/lib/ext/Syncroton/Command/Sync.php index ca50a7f..5c240fb 100644 --- a/lib/ext/Syncroton/Command/Sync.php +++ b/lib/ext/Syncroton/Command/Sync.php @@ -1,1230 +1,1277 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Command */ -class Syncroton_Command_Sync extends Syncroton_Command_Wbxml +class Syncroton_Command_Sync extends Syncroton_Command_Wbxml { - const STATUS_SUCCESS = 1; - const STATUS_PROTOCOL_VERSION_MISMATCH = 2; - const STATUS_INVALID_SYNC_KEY = 3; - const STATUS_PROTOCOL_ERROR = 4; - const STATUS_SERVER_ERROR = 5; - const STATUS_ERROR_IN_CLIENT_SERVER_CONVERSION = 6; - const STATUS_CONFLICT_MATCHING_THE_CLIENT_AND_SERVER_OBJECT = 7; - const STATUS_OBJECT_NOT_FOUND = 8; - const STATUS_USER_ACCOUNT_MAYBE_OUT_OF_DISK_SPACE = 9; - const STATUS_ERROR_SETTING_NOTIFICATION_GUID = 10; - const STATUS_DEVICE_NOT_PROVISIONED_FOR_NOTIFICATIONS = 11; - const STATUS_FOLDER_HIERARCHY_HAS_CHANGED = 12; - const STATUS_RESEND_FULL_XML = 13; - const STATUS_WAIT_INTERVAL_OUT_OF_RANGE = 14; - const STATUS_TOO_MANY_COLLECTIONS = 15; - - const CONFLICT_OVERWRITE_SERVER = 0; - const CONFLICT_OVERWRITE_PIM = 1; - - const MIMESUPPORT_DONT_SEND_MIME = 0; - const MIMESUPPORT_SMIME_ONLY = 1; - const MIMESUPPORT_SEND_MIME = 2; - - const BODY_TYPE_PLAIN_TEXT = 1; - const BODY_TYPE_HTML = 2; - const BODY_TYPE_RTF = 3; - const BODY_TYPE_MIME = 4; - + public const STATUS_SUCCESS = 1; + public const STATUS_PROTOCOL_VERSION_MISMATCH = 2; + public const STATUS_INVALID_SYNC_KEY = 3; + public const STATUS_PROTOCOL_ERROR = 4; + public const STATUS_SERVER_ERROR = 5; + public const STATUS_ERROR_IN_CLIENT_SERVER_CONVERSION = 6; + public const STATUS_CONFLICT_MATCHING_THE_CLIENT_AND_SERVER_OBJECT = 7; + public const STATUS_OBJECT_NOT_FOUND = 8; + public const STATUS_USER_ACCOUNT_MAYBE_OUT_OF_DISK_SPACE = 9; + public const STATUS_ERROR_SETTING_NOTIFICATION_GUID = 10; + public const STATUS_DEVICE_NOT_PROVISIONED_FOR_NOTIFICATIONS = 11; + public const STATUS_FOLDER_HIERARCHY_HAS_CHANGED = 12; + public const STATUS_RESEND_FULL_XML = 13; + public const STATUS_WAIT_INTERVAL_OUT_OF_RANGE = 14; + public const STATUS_TOO_MANY_COLLECTIONS = 15; + + public const CONFLICT_OVERWRITE_SERVER = 0; + public const CONFLICT_OVERWRITE_PIM = 1; + + public const MIMESUPPORT_DONT_SEND_MIME = 0; + public const MIMESUPPORT_SMIME_ONLY = 1; + public const MIMESUPPORT_SEND_MIME = 2; + + public const BODY_TYPE_PLAIN_TEXT = 1; + public const BODY_TYPE_HTML = 2; + public const BODY_TYPE_RTF = 3; + public const BODY_TYPE_MIME = 4; + /** * truncate types */ - const TRUNCATE_ALL = 0; - const TRUNCATE_4096 = 1; - const TRUNCATE_5120 = 2; - const TRUNCATE_7168 = 3; - const TRUNCATE_10240 = 4; - const TRUNCATE_20480 = 5; - const TRUNCATE_51200 = 6; - const TRUNCATE_102400 = 7; - const TRUNCATE_NOTHING = 8; - + public const TRUNCATE_ALL = 0; + public const TRUNCATE_4096 = 1; + public const TRUNCATE_5120 = 2; + public const TRUNCATE_7168 = 3; + public const TRUNCATE_10240 = 4; + public const TRUNCATE_20480 = 5; + public const TRUNCATE_51200 = 6; + public const TRUNCATE_102400 = 7; + public const TRUNCATE_NOTHING = 8; + /** * filter types */ - const FILTER_NOTHING = 0; - const FILTER_1_DAY_BACK = 1; - const FILTER_3_DAYS_BACK = 2; - const FILTER_1_WEEK_BACK = 3; - const FILTER_2_WEEKS_BACK = 4; - const FILTER_1_MONTH_BACK = 5; - const FILTER_3_MONTHS_BACK = 6; - const FILTER_6_MONTHS_BACK = 7; - const FILTER_INCOMPLETE = 8; - - + public const FILTER_NOTHING = 0; + public const FILTER_1_DAY_BACK = 1; + public const FILTER_3_DAYS_BACK = 2; + public const FILTER_1_WEEK_BACK = 3; + public const FILTER_2_WEEKS_BACK = 4; + public const FILTER_1_MONTH_BACK = 5; + public const FILTER_3_MONTHS_BACK = 6; + public const FILTER_6_MONTHS_BACK = 7; + public const FILTER_INCOMPLETE = 8; + + protected $_defaultNameSpace = 'uri:AirSync'; protected $_documentElement = 'Sync'; - + /** * list of collections * * @var array */ - protected $_collections = array(); - - protected $_modifications = array(); - + protected $_collections = []; + + protected $_modifications = []; + /** * the global WindowSize * * @var integer */ protected $_globalWindowSize; - + /** * there are more entries than WindowSize available * the MoreAvailable tag hot added to the xml output * * @var boolean */ protected $_moreAvailable = false; - + protected $_maxWindowSize = 100; - + protected $_heartbeatInterval = null; - + /** - * process the XML file and add, change, delete or fetches data + * process the XML file and add, change, delete or fetches data */ public function handle() { // input xml $requestXML = simplexml_import_dom($this->_mergeSyncRequest($this->_requestBody, $this->_device)); - + if (! isset($requestXML->Collections)) { $this->_outputDom->documentElement->appendChild( $this->_outputDom->createElementNS('uri:AirSync', 'Status', self::STATUS_RESEND_FULL_XML) ); - + return $this->_outputDom; } $intervalDiv = 1; if (isset($requestXML->HeartbeatInterval)) { $intervalDiv = 1; $this->_heartbeatInterval = (int)$requestXML->HeartbeatInterval; - } else if (isset($requestXML->Wait)) { + } elseif (isset($requestXML->Wait)) { $intervalDiv = 60; $this->_heartbeatInterval = (int)$requestXML->Wait * $intervalDiv; } - + $maxInterval = Syncroton_Registry::getPingInterval(); if ($maxInterval <= 0 || $maxInterval > Syncroton_Server::MAX_HEARTBEAT_INTERVAL) { $maxInterval = Syncroton_Server::MAX_HEARTBEAT_INTERVAL; } - + if ($this->_heartbeatInterval && $this->_heartbeatInterval > $maxInterval) { $sync = $this->_outputDom->documentElement; $sync->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Status', self::STATUS_WAIT_INTERVAL_OUT_OF_RANGE)); - $sync->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Limit', floor($maxInterval/$intervalDiv))); + $sync->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Limit', floor($maxInterval / $intervalDiv))); $this->_heartbeatInterval = null; return; } - + $this->_globalWindowSize = isset($requestXML->WindowSize) ? (int)$requestXML->WindowSize : 100; if (!$this->_globalWindowSize || $this->_globalWindowSize > 512) { $this->_globalWindowSize = 512; } - + if ($this->_globalWindowSize > $this->_maxWindowSize) { $this->_globalWindowSize = $this->_maxWindowSize; } - + // load options from lastsynccollection - $lastSyncCollection = array('options' => array()); + $lastSyncCollection = ['options' => []]; if (!empty($this->_device->lastsynccollection)) { $lastSyncCollection = Zend_Json::decode($this->_device->lastsynccollection); if (!array_key_exists('options', $lastSyncCollection) || !is_array($lastSyncCollection['options'])) { - $lastSyncCollection['options'] = array(); + $lastSyncCollection['options'] = []; } } $maxCollections = Syncroton_Registry::getMaxCollections(); if ($maxCollections && count($requestXML->Collections->Collection) > $maxCollections) { $sync = $this->_outputDom->documentElement; $sync->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Status', self::STATUS_TOO_MANY_COLLECTIONS)); $sync->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Limit', $maxCollections)); return; } - $collections = array(); - + $collections = []; + foreach ($requestXML->Collections->Collection as $xmlCollection) { $collectionId = (string)$xmlCollection->CollectionId; - + $collections[$collectionId] = new Syncroton_Model_SyncCollection($xmlCollection); - + // do we have to reuse the options from the previous request? if (!isset($xmlCollection->Options) && array_key_exists($collectionId, $lastSyncCollection['options'])) { $collections[$collectionId]->options = $lastSyncCollection['options'][$collectionId]; - if ($this->_logger instanceof Zend_Log) - $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " restored options to " . print_r($collections[$collectionId]->options, TRUE)); + if ($this->_logger instanceof Zend_Log) { + $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " restored options to " . print_r($collections[$collectionId]->options, true)); + } } - + // store current options for next Sync command request (sticky options) $lastSyncCollection['options'][$collectionId] = $collections[$collectionId]->options; } - + $this->_device->lastsynccollection = Zend_Json::encode($lastSyncCollection); - + if ($this->_device->isDirty()) { Syncroton_Registry::getDeviceBackend()->update($this->_device); } - + foreach ($collections as $collectionData) { // has the folder been synchronised to the device already try { $collectionData->folder = $this->_folderBackend->getFolder($this->_device, $collectionData->collectionId); - + } catch (Syncroton_Exception_NotFound $senf) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " folder {$collectionData->collectionId} not found"); - + } + // trigger INVALID_SYNCKEY instead of OBJECT_NOTFOUND when synckey is higher than 0 // to avoid a syncloop for the iPhone if ($collectionData->syncKey > 0) { - $collectionData->folder = new Syncroton_Model_Folder(array( + $collectionData->folder = new Syncroton_Model_Folder([ 'deviceId' => $this->_device, - 'serverId' => $collectionData->collectionId - )); + 'serverId' => $collectionData->collectionId, + ]); } - + $this->_collections[$collectionData->collectionId] = $collectionData; - + continue; } - - if ($this->_logger instanceof Zend_Log) + + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " SyncKey is {$collectionData->syncKey} Class: {$collectionData->folder->class} CollectionId: {$collectionData->collectionId}"); - + } + // initial synckey if($collectionData->syncKey === 0) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " initial client synckey 0 provided"); - + } + // reset sync state for this folder $this->_syncStateBackend->resetState($this->_device, $collectionData->folder); $this->_contentStateBackend->resetState($this->_device, $collectionData->folder); - - $collectionData->syncState = new Syncroton_Model_SyncState(array( + + $collectionData->syncState = new Syncroton_Model_SyncState([ 'device_id' => $this->_device, 'counter' => 0, 'type' => $collectionData->folder, - 'lastsync' => $this->_syncTimeStamp - )); - + 'lastsync' => $this->_syncTimeStamp, + ]); + $this->_collections[$collectionData->collectionId] = $collectionData; - + continue; } - + $syncKeyReused = $this->_syncStateBackend->haveNext($this->_device, $collectionData->folder, $collectionData->syncKey); if ($syncKeyReused) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " already known synckey {$collectionData->syncKey} provided"); + } } // check for invalid synckey if(($collectionData->syncState = $this->_syncStateBackend->validate($this->_device, $collectionData->folder, $collectionData->syncKey)) === false) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " invalid synckey {$collectionData->syncKey} provided"); - + } + // reset sync state for this folder $this->_syncStateBackend->resetState($this->_device, $collectionData->folder); $this->_contentStateBackend->resetState($this->_device, $collectionData->folder); - + $this->_collections[$collectionData->collectionId] = $collectionData; - + continue; } - + $dataController = Syncroton_Data_Factory::factory($collectionData->folder->class, $this->_device, $this->_syncTimeStamp); - + switch($collectionData->folder->class) { case Syncroton_Data_Factory::CLASS_CALENDAR: $dataClass = 'Syncroton_Model_Event'; break; - + case Syncroton_Data_Factory::CLASS_CONTACTS: $dataClass = 'Syncroton_Model_Contact'; break; - + case Syncroton_Data_Factory::CLASS_EMAIL: $dataClass = 'Syncroton_Model_Email'; break; - + case Syncroton_Data_Factory::CLASS_NOTES: $dataClass = 'Syncroton_Model_Note'; break; case Syncroton_Data_Factory::CLASS_TASKS: $dataClass = 'Syncroton_Model_Task'; break; - + default: throw new Syncroton_Exception_UnexpectedValue('invalid class provided'); } - - $clientModifications = array( - 'added' => array(), - 'changed' => array(), - 'deleted' => array(), - 'forceAdd' => array(), - 'forceChange' => array(), - 'toBeFetched' => array(), - ); - + + $clientModifications = [ + 'added' => [], + 'changed' => [], + 'deleted' => [], + 'forceAdd' => [], + 'forceChange' => [], + 'toBeFetched' => [], + ]; + // handle incoming data if($collectionData->hasClientAdds()) { $adds = $collectionData->getClientAdds(); - - if ($this->_logger instanceof Zend_Log) + + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " found " . count($adds) . " entries to be added to server"); - + } + $clientIdMap = []; if ($syncKeyReused && $collectionData->syncState->clientIdMap) { $clientIdMap = Zend_Json::decode($collectionData->syncState->clientIdMap); } foreach ($adds as $add) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " add entry with clientId " . (string) $add->ClientId); + } try { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " adding entry as new"); - + } + $clientId = (string)$add->ClientId; // If the sync key was reused, but we don't have a $clientId mapping, // this means the client sent a new item with the same sync_key. if ($syncKeyReused && array_key_exists($clientId, $clientIdMap)) { // We don't normally store the clientId, so if a command with Add's is resent, // we have to look-up the corresponding serverId using a cached clientId => serverId mapping, // otherwise we would duplicate all added items on resend. $serverId = $clientIdMap[$clientId]; - $clientModifications['added'][$serverId] = array( + $clientModifications['added'][$serverId] = [ 'clientId' => (string)$add->ClientId, 'serverId' => $serverId, 'status' => self::STATUS_SUCCESS, - 'contentState' => null - ); + 'contentState' => null, + ]; } else { $serverId = $dataController->createEntry($collectionData->collectionId, new $dataClass($add->ApplicationData)); - $clientModifications['added'][$serverId] = array( + $clientModifications['added'][$serverId] = [ 'clientId' => (string)$add->ClientId, 'serverId' => $serverId, 'status' => self::STATUS_SUCCESS, - 'contentState' => $this->_contentStateBackend->create(new Syncroton_Model_Content(array( + 'contentState' => $this->_contentStateBackend->create(new Syncroton_Model_Content([ 'device_id' => $this->_device, 'folder_id' => $collectionData->folder, 'contentid' => $serverId, 'creation_time' => $this->_syncTimeStamp, - 'creation_synckey' => $collectionData->syncKey + 1 - ))) - ); + 'creation_synckey' => $collectionData->syncKey + 1, + ])), + ]; } - + } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " failed to add entry " . $e->getMessage()); - $clientModifications['added'][] = array( + } + $clientModifications['added'][] = [ 'clientId' => (string)$add->ClientId, - 'status' => self::STATUS_SERVER_ERROR - ); + 'status' => self::STATUS_SERVER_ERROR, + ]; } } } - + // handle changes, but only if not first sync if(!$syncKeyReused && $collectionData->syncKey > 1 && $collectionData->hasClientChanges()) { $changes = $collectionData->getClientChanges(); - - if ($this->_logger instanceof Zend_Log) + + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " found " . count($changes) . " entries to be updated on server"); - + } + foreach ($changes as $change) { $serverId = (string)$change->ServerId; - + try { $dataController->updateEntry($collectionData->collectionId, $serverId, new $dataClass($change->ApplicationData)); $clientModifications['changed'][$serverId] = self::STATUS_SUCCESS; - + } catch (Syncroton_Exception_AccessDenied $e) { $clientModifications['changed'][$serverId] = self::STATUS_CONFLICT_MATCHING_THE_CLIENT_AND_SERVER_OBJECT; $clientModifications['forceChange'][$serverId] = $serverId; - + } catch (Syncroton_Exception_NotFound $e) { // entry does not exist anymore, will get deleted automaticaly $clientModifications['changed'][$serverId] = self::STATUS_OBJECT_NOT_FOUND; - + } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " failed to update entry " . $e); + } // something went wrong while trying to update the entry $clientModifications['changed'][$serverId] = self::STATUS_SERVER_ERROR; } } } - + // handle deletes, but only if not first sync if(!$syncKeyReused && $collectionData->hasClientDeletes()) { $deletes = $collectionData->getClientDeletes(); - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " found " . count($deletes) . " entries to be deleted on server"); - + } + foreach ($deletes as $delete) { $serverId = (string)$delete->ServerId; - + try { // check if we have sent this entry to the phone $state = $this->_contentStateBackend->getContentState($this->_device, $collectionData->folder, $serverId); - + try { $dataController->deleteEntry($collectionData->collectionId, $serverId, $collectionData); - + } catch(Syncroton_Exception_NotFound $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->crit(__METHOD__ . '::' . __LINE__ . ' tried to delete entry ' . $serverId . ' but entry was not found'); - + } + } catch (Syncroton_Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' tried to delete entry ' . $serverId . ' but a error occured: ' . $e->getMessage()); + } $clientModifications['forceAdd'][$serverId] = $serverId; } $this->_contentStateBackend->delete($state); - + } catch (Syncroton_Exception_NotFound $senf) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' ' . $serverId . ' should have been removed from client already'); + } // should we send a special status??? //$collectionData->deleted[$serverId] = self::STATUS_SUCCESS; } - + $clientModifications['deleted'][$serverId] = self::STATUS_SUCCESS; } } - + // handle fetches, but only if not first sync if($collectionData->syncKey > 1 && $collectionData->hasClientFetches()) { // the default value for GetChanges is 1. If the phone don't want the changes it must set GetChanges to 0 // some prevoius versions of iOS did not set GetChanges to 0 for fetches. Let's enforce getChanges to false here. $collectionData->getChanges = false; - + $fetches = $collectionData->getClientFetches(); - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " found " . count($fetches) . " entries to be fetched from server"); - - $toBeFetched = array(); - + } + + $toBeFetched = []; + foreach ($fetches as $fetch) { $serverId = (string)$fetch->ServerId; - + $toBeFetched[$serverId] = $serverId; } - + $collectionData->toBeFetched = $toBeFetched; } - + $this->_collections[$collectionData->collectionId] = $collectionData; $this->_modifications[$collectionData->collectionId] = $clientModifications; } } - + /** * (non-PHPdoc) * @see Syncroton_Command_Wbxml::getResponse() */ public function getResponse() { $sync = $this->_outputDom->documentElement; - + $collections = $this->_outputDom->createElementNS('uri:AirSync', 'Collections'); $totalChanges = 0; // Detect devices that do not support empty Sync reponse $emptySyncSupported = !preg_match('/(meego|nokian800)/i', $this->_device->useragent); - + // continue only if there are changes or no time is left if ($this->_heartbeatInterval > 0) { $intervalStart = time(); $sleepCallback = Syncroton_Registry::getSleepCallback(); $wakeupCallback = Syncroton_Registry::getWakeupCallback(); - + do { // take a break to save battery lifetime $sleepCallback(); sleep(Syncroton_Registry::getPingTimeout()); // make sure the connection is still alive, abort otherwise if (connection_aborted()) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " Exiting on aborted connection"); + } exit; } $wakeupCallback(); - + $now = new DateTime('now', new DateTimeZone('UTC')); foreach($this->_collections as $collectionData) { - // continue immediately if folder does not exist + // continue immediately if folder does not exist if (! ($collectionData->folder instanceof Syncroton_Model_IFolder)) { break 2; - - // countinue immediately if syncstate is invalid + + // countinue immediately if syncstate is invalid } elseif (! ($collectionData->syncState instanceof Syncroton_Model_ISyncState)) { break 2; - + } else { if ($collectionData->getChanges !== true) { continue; } - + try { // just check if the folder still exists $this->_folderBackend->get($collectionData->folder); } catch (Syncroton_Exception_NotFound $senf) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " collection does not exist anymore: " . $collectionData->collectionId); - + } + $collectionData->getChanges = false; - + // make sure this is the last while loop // no break 2 here, as we like to check the other folders too $intervalStart -= $this->_heartbeatInterval; } - + // check that the syncstate still exists and is still valid try { $syncState = $this->_syncStateBackend->getSyncState($this->_device, $collectionData->folder); - + // another process synchronized data of this folder already. let's skip it if ($syncState->id !== $collectionData->syncState->id) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " syncstate changed during heartbeat interval for collection: " . $collectionData->folder->serverId); - + } + $collectionData->getChanges = false; - + // make sure this is the last while loop // no break 2 here, as we like to check the other folders too $intervalStart -= $this->_heartbeatInterval; } } catch (Syncroton_Exception_NotFound $senf) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " no syncstate found anymore for collection: " . $collectionData->folder->serverId); - + } + $collectionData->syncState = null; - + // make sure this is the last while loop // no break 2 here, as we like to check the other folders too $intervalStart -= $this->_heartbeatInterval; } - - + + // safe battery time by skipping folders which got synchronied less than Syncroton_Command_Ping::$quietTime seconds ago - if ( ! $collectionData->syncState instanceof Syncroton_Model_SyncState || + if (! $collectionData->syncState instanceof Syncroton_Model_SyncState || ($now->getTimestamp() - $collectionData->syncState->lastsync->getTimestamp()) < Syncroton_Registry::getQuietTime()) { continue; } - - $dataController = Syncroton_Data_Factory::factory($collectionData->folder->class , $this->_device, $this->_syncTimeStamp); - + + $dataController = Syncroton_Data_Factory::factory($collectionData->folder->class, $this->_device, $this->_syncTimeStamp); + // countinue immediately if there are any changes available if($dataController->hasChanges($this->_contentStateBackend, $collectionData->folder, $collectionData->syncState)) { break 2; } } } - - // See: http://www.tine20.org/forum/viewtopic.php?f=12&t=12146 - // - // break if there are less than PingTimeout + 10 seconds left for the next loop - // otherwise the response will be returned after the client has finished his Ping - // request already maybe + + // See: http://www.tine20.org/forum/viewtopic.php?f=12&t=12146 + // + // break if there are less than PingTimeout + 10 seconds left for the next loop + // otherwise the response will be returned after the client has finished his Ping + // request already maybe } while (Syncroton_Server::validateSession() && time() - $intervalStart < $this->_heartbeatInterval - (Syncroton_Registry::getPingTimeout() + 10)); } // First check for folders hierarchy changes foreach ($this->_collections as $collectionData) { if (! ($collectionData->folder instanceof Syncroton_Model_IFolder)) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " Detected a folder hierarchy change on {$collectionData->collectionId}."); + } $sync->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Status', self::STATUS_FOLDER_HIERARCHY_HAS_CHANGED)); return $this->_outputDom; } } foreach ($this->_collections as $collectionData) { $collectionChanges = 0; - + /** * keep track of entries added on server side */ - $newContentStates = array(); - + $newContentStates = []; + /** * keep track of entries deleted on server side */ - $deletedContentStates = array(); + $deletedContentStates = []; // invalid synckey provided if (! ($collectionData->syncState instanceof Syncroton_Model_ISyncState)) { // set synckey to 0 $collection = $collections->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Collection')); $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'SyncKey', 0)); $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'CollectionId', $collectionData->collectionId)); $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Status', self::STATUS_INVALID_SYNC_KEY)); - - // initial sync + + // initial sync } elseif ($collectionData->syncState->counter === 0) { $collectionData->syncState->counter++; // initial sync // send back a new SyncKey only $collection = $collections->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Collection')); if (!empty($collectionData->folder->class)) { $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Class', $collectionData->folder->class)); } $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'SyncKey', $collectionData->syncState->counter)); $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'CollectionId', $collectionData->collectionId)); $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Status', self::STATUS_SUCCESS)); } else { - $dataController = Syncroton_Data_Factory::factory($collectionData->folder->class , $this->_device, $this->_syncTimeStamp); + $dataController = Syncroton_Data_Factory::factory($collectionData->folder->class, $this->_device, $this->_syncTimeStamp); $clientModifications = $this->_modifications[$collectionData->collectionId]; - $serverModifications = array( - 'added' => array(), - 'changed' => array(), - 'deleted' => array(), - ); + $serverModifications = [ + 'added' => [], + 'changed' => [], + 'deleted' => [], + ]; $status = self::STATUS_SUCCESS; $hasChanges = 0; if ($collectionData->getChanges === true) { // continue sync session? if(is_array($collectionData->syncState->pendingdata)) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " restored from sync state "); + } $serverModifications = $collectionData->syncState->pendingdata; } else { try { $hasChanges = $dataController->hasChanges($this->_contentStateBackend, $collectionData->folder, $collectionData->syncState); } catch (Syncroton_Exception_NotFound $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " Folder changes checking failed (not found): " . $e->getTraceAsString()); + } $status = self::STATUS_FOLDER_HIERARCHY_HAS_CHANGED; } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->crit(__METHOD__ . '::' . __LINE__ . " Folder changes checking failed: " . $e->getMessage()); + } // Prevent from removing client entries when getServerEntries() fails // @todo: should we break the loop here? $status = self::STATUS_SERVER_ERROR; } } if ($hasChanges) { // update _syncTimeStamp as $dataController->hasChanges might have spent some time $this->_syncTimeStamp = new DateTime('now', new DateTimeZone('UTC')); try { // fetch entries added since last sync $allClientEntries = $this->_contentStateBackend->getFolderState( $this->_device, $collectionData->folder, $collectionData->syncState->counter ); // fetch entries changed since last sync $allChangedEntries = $dataController->getChangedEntries( $collectionData->collectionId, $collectionData->syncState, $collectionData->options['filterType'] ); // fetch all entries $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) + 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); // entries changed since last sync $serverModifications['changed'] = array_merge($allChangedEntries, $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); + 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) + elseif (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) + if ($this->_logger instanceof Zend_Log) { $this->_logger->crit(__METHOD__ . '::' . __LINE__ . " Folder state checking failed: " . $e->getMessage()); - if ($this->_logger instanceof Zend_Log) + } + 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 break the loop here? $status = self::STATUS_SERVER_ERROR; } - 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'); + 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 = $this->_outputDom->createElementNS('uri:AirSync', 'Collection'); if (!empty($collectionData->folder->class)) { $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Class', $collectionData->folder->class)); } - + $syncKeyElement = $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'SyncKey')); - + $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'CollectionId', $collectionData->collectionId)); $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Status', $status)); - + $responses = $this->_outputDom->createElementNS('uri:AirSync', 'Responses'); - + // send reponse for newly added entries if(!empty($clientModifications['added'])) { foreach($clientModifications['added'] as $entryData) { $add = $responses->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Add')); $add->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ClientId', $entryData['clientId'])); // we have no serverId if the add failed if(isset($entryData['serverId'])) { $add->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ServerId', $entryData['serverId'])); } $add->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Status', $entryData['status'])); } } - + // send reponse for changed entries if(!empty($clientModifications['changed'])) { foreach($clientModifications['changed'] as $serverId => $status) { if ($status !== Syncroton_Command_Sync::STATUS_SUCCESS) { $change = $responses->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Change')); $change->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ServerId', $serverId)); $change->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Status', $status)); } } } - + // send response for to be fetched entries if(!empty($collectionData->toBeFetched)) { // unset all truncation settings as entries are not allowed to be truncated during fetch $fetchCollectionData = clone $collectionData; - + // unset truncationSize if (isset($fetchCollectionData->options['bodyPreferences']) && is_array($fetchCollectionData->options['bodyPreferences'])) { foreach($fetchCollectionData->options['bodyPreferences'] as $key => $bodyPreference) { unset($fetchCollectionData->options['bodyPreferences'][$key]['truncationSize']); } } $fetchCollectionData->options['mimeTruncation'] = Syncroton_Command_Sync::TRUNCATE_NOTHING; - + foreach($collectionData->toBeFetched as $serverId) { $fetch = $responses->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Fetch')); $fetch->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ServerId', $serverId)); - + try { $applicationData = $this->_outputDom->createElementNS('uri:AirSync', 'ApplicationData'); - + $dataController ->getEntry($fetchCollectionData, $serverId) ->appendXML($applicationData, $this->_device); - + $fetch->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Status', self::STATUS_SUCCESS)); - + $fetch->appendChild($applicationData); } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " unable to convert entry to xml: " . $e->getMessage()); - if ($this->_logger instanceof Zend_Log) + } + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " unable to convert entry to xml: " . $e->getTraceAsString()); + } $fetch->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Status', self::STATUS_OBJECT_NOT_FOUND)); } } } - + if ($responses->hasChildNodes() === true) { $collection->appendChild($responses); } - + $commands = $this->_outputDom->createElementNS('uri:AirSync', 'Commands'); - + foreach($serverModifications['added'] as $id => $serverId) { if($collectionChanges == $collectionData->windowSize || $totalChanges + $collectionChanges >= $this->_globalWindowSize) { break; } try { $add = $this->_outputDom->createElementNS('uri:AirSync', 'Add'); $add->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ServerId', $serverId)); - + $applicationData = $add->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ApplicationData')); - - $dataController - ->getEntry($collectionData, $serverId) - ->appendXML($applicationData, $this->_device); - + + $dataController + ->getEntry($collectionData, $serverId) + ->appendXML($applicationData, $this->_device); + $commands->appendChild($add); - - $newContentStates[] = new Syncroton_Model_Content(array( + + $newContentStates[] = new Syncroton_Model_Content([ 'device_id' => $this->_device, 'folder_id' => $collectionData->folder, 'contentid' => $serverId, 'creation_time' => $this->_syncTimeStamp, - 'creation_synckey' => $collectionData->syncState->counter + 1 - )); + 'creation_synckey' => $collectionData->syncState->counter + 1, + ]); $collectionChanges++; } catch (Syncroton_Exception_MemoryExhausted $seme) { // continue to next entry, as there is not enough memory left for the current entry // this will lead to MoreAvailable at the end and the entry will be synced during the next Sync command - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " memory exhausted for entry: " . $serverId); - + } + break; - + } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " unable to convert entry to xml: " . $e->getMessage()); - if ($this->_logger instanceof Zend_Log) + } + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " unable to convert entry to xml: " . $e->getTraceAsString()); + } // We bump collectionChanges anyways to make sure the windowSize still applies. $collectionChanges++; } - - // mark as sent to the client, even the conversion to xml might have failed + + // mark as sent to the client, even the conversion to xml might have failed unset($serverModifications['added'][$id]); } /** * process entries changed on server side */ foreach($serverModifications['changed'] as $id => $serverId) { 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)); - + $applicationData = $change->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ApplicationData')); - - $dataController - ->getEntry($collectionData, $serverId) - ->appendXML($applicationData, $this->_device); - + + $dataController + ->getEntry($collectionData, $serverId) + ->appendXML($applicationData, $this->_device); + $commands->appendChild($change); - + $collectionChanges++; } catch (Syncroton_Exception_MemoryExhausted $seme) { // continue to next entry, as there is not enough memory left for the current entry // this will lead to MoreAvailable at the end and the entry will be synced during the next Sync command - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " memory exhausted for entry: " . $serverId); - + } + break; - + } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " unable to convert entry to xml: " . $e->getMessage()); + } // We bump collectionChanges anyways to make sure the windowSize still applies. $collectionChanges++; } - unset($serverModifications['changed'][$id]); + unset($serverModifications['changed'][$id]); } foreach($serverModifications['deleted'] as $id => $serverId) { 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); - + $delete = $this->_outputDom->createElementNS('uri:AirSync', 'Delete'); $delete->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ServerId', $serverId)); - + $deletedContentStates[] = $state; - + $commands->appendChild($delete); - + $collectionChanges++; } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " unable to convert entry to xml: " . $e->getMessage()); + } // We bump collectionChanges anyways to make sure the windowSize still applies. $collectionChanges++; } - + unset($serverModifications['deleted'][$id]); } - - $countOfPendingChanges = (count($serverModifications['added']) + count($serverModifications['changed']) + count($serverModifications['deleted'])); + + $countOfPendingChanges = (count($serverModifications['added']) + count($serverModifications['changed']) + count($serverModifications['deleted'])); if ($countOfPendingChanges > 0) { - if ($this->_logger instanceof Zend_Log) - $this->_logger->info(__METHOD__ . '::' . __LINE__ . " there are ". $countOfPendingChanges . " more items available"); + if ($this->_logger instanceof Zend_Log) { + $this->_logger->info(__METHOD__ . '::' . __LINE__ . " there are " . $countOfPendingChanges . " more items available"); + } $collection->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'MoreAvailable')); } else { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " there are no more items available"); + } $serverModifications = null; } - + if ($commands->hasChildNodes() === true) { $collection->appendChild($commands); } - + $totalChanges += $collectionChanges; // If the client resent an old sync-key, we should still respond with the latest sync key if (isset($collectionData->syncState->counterNext)) { - //TODO we're not resending the changes in between, but I'm not sure we have to. + //TODO we're not resending the changes in between, but I'm not sure we have to. $collectionData->syncState->counter = $collectionData->syncState->counterNext; } - + // increase SyncKey if needed if (( - // sent the clients updates... ? - !empty($clientModifications['added']) || - !empty($clientModifications['changed']) || - !empty($clientModifications['deleted']) - ) || ( - // is the server sending updates to the client... ? - $commands->hasChildNodes() === true - ) || ( - // changed the pending data... ? - $collectionData->syncState->pendingdata != $serverModifications - ) + // sent the clients updates... ? + !empty($clientModifications['added']) || + !empty($clientModifications['changed']) || + !empty($clientModifications['deleted']) + ) || ( + // is the server sending updates to the client... ? + $commands->hasChildNodes() === true + ) || ( + // changed the pending data... ? + $collectionData->syncState->pendingdata != $serverModifications + ) ) { - // ...then increase SyncKey - $collectionData->syncState->counter++; - } + // ...then increase SyncKey + $collectionData->syncState->counter++; + } $syncKeyElement->appendChild($this->_outputDom->createTextNode($collectionData->syncState->counter)); - - if ($this->_logger instanceof Zend_Log) - $this->_logger->info(__METHOD__ . '::' . __LINE__ . " current synckey is ". $collectionData->syncState->counter); - + + if ($this->_logger instanceof Zend_Log) { + $this->_logger->info(__METHOD__ . '::' . __LINE__ . " current synckey is " . $collectionData->syncState->counter); + } + if (!$emptySyncSupported || $collection->childNodes->length > 4 || $collectionData->syncState->counter != $collectionData->syncKey) { - $collections->appendChild($collection); + $collections->appendChild($collection); } //Store next $collectionData->syncState->extraData = $dataController->getExtraData($collectionData->folder); } - - if (isset($collectionData->syncState) && + + if (isset($collectionData->syncState) && $collectionData->syncState instanceof Syncroton_Model_ISyncState && - $collectionData->syncState->counter != $collectionData->syncKey + $collectionData->syncState->counter != $collectionData->syncKey ) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " update syncState for collection: " . $collectionData->collectionId); - + } + // store pending data in sync state when needed if (isset($countOfPendingChanges) && $countOfPendingChanges > 0) { - $collectionData->syncState->pendingdata = array( + $collectionData->syncState->pendingdata = [ 'added' => $serverModifications['added'] ?? [], 'changed' => $serverModifications['changed'] ?? [], - 'deleted' => $serverModifications['deleted'] ?? [] - ); + 'deleted' => $serverModifications['deleted'] ?? [], + ]; } else { $collectionData->syncState->pendingdata = null; } - + $collectionData->syncState->lastsync = clone $this->_syncTimeStamp; // increment sync timestamp by 1 second $collectionData->syncState->lastsync->modify('+1 sec'); if (!empty($clientModifications['added'])) { // Store a client id mapping in case we encounter a reused sync_key in a future request. $newClientIdMap = []; foreach($clientModifications['added'] as $entryData) { // No serverId if we failed to add if ($entryData['status'] == self::STATUS_SUCCESS) { $newClientIdMap[$entryData['clientId']] = $entryData['serverId']; } } $collectionData->syncState->clientIdMap = Zend_Json::encode($newClientIdMap); } - + //Retry in case of deadlock $retryCounter = 0; - while (True) { + while (true) { try { $transactionId = Syncroton_Registry::getTransactionManager()->startTransaction(Syncroton_Registry::getDatabase()); // store new synckey $this->_syncStateBackend->create($collectionData->syncState, true); // @phpstan-ignore-line - + // store contentstates for new entries added to client foreach($newContentStates as $state) { try { //This can happen if we rerun a previous sync-key $state = $this->_contentStateBackend->getContentState($state->device_id, $state->folder_id, $state->contentid); $this->_contentStateBackend->update($state); } catch(Exception $zdse) { $this->_contentStateBackend->create($state); } } - + // remove contentstates for entries to be deleted on client foreach($deletedContentStates as $state) { $this->_contentStateBackend->delete($state); } Syncroton_Registry::getTransactionManager()->commitTransaction($transactionId); break; } catch (Syncroton_Exception_DeadlockDetected $zdse) { $retryCounter++; if ($retryCounter > 60) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . ' exception while storing new synckey. Aborting after 5 retries.'); + } // something went wrong // maybe another parallel request added a new synckey // we must remove data added from client if (!empty($clientModifications['added']) && isset($dataController)) { foreach ($clientModifications['added'] as $added) { $this->_contentStateBackend->delete($added['contentState']); $dataController->deleteEntry($collectionData->collectionId, $added['serverId']); } } - + Syncroton_Registry::getTransactionManager()->rollBack(); - + throw $zdse; } Syncroton_Registry::getTransactionManager()->rollBack(); // Give the other transactions some time before we try again sleep(1); - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . ' error during transaction, trying again.'); + } } catch (Exception $zdse) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . ' exception while storing new synckey.'); + } // something went wrong // maybe another parallel request added a new synckey // we must remove data added from client if (!empty($clientModifications['added']) && isset($dataController)) { foreach ($clientModifications['added'] as $added) { $this->_contentStateBackend->delete($added['contentState']); $dataController->deleteEntry($collectionData->collectionId, $added['serverId']); } } - + Syncroton_Registry::getTransactionManager()->rollBack(); - + throw $zdse; } } } - + // store current filter type try { /** @var Syncroton_Model_Folder $folderState */ $folderState = $this->_folderBackend->get($collectionData->folder); $folderState->lastfiltertype = $collectionData->options['filterType']; if ($folderState->isDirty()) { $this->_folderBackend->update($folderState); } } catch (Syncroton_Exception_NotFound $senf) { // failed to get folderstate => should not happen but is also no problem in this state - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . ' failed to get folder state for: ' . $collectionData->collectionId); + } } } - + if ($collections->hasChildNodes() === true) { $sync->appendChild($collections); } - + if ($sync->hasChildNodes()) { return $this->_outputDom; } - + return null; } - + /** * remove Commands and Supported from collections XML tree - * + * * @param DOMDocument $document * @return DOMDocument */ protected function _cleanUpXML(DOMDocument $document) { $cleanedDocument = clone $document; - + $xpath = new DomXPath($cleanedDocument); $xpath->registerNamespace('AirSync', 'uri:AirSync'); - + $collections = $xpath->query("//AirSync:Sync/AirSync:Collections/AirSync:Collection"); - + // remove Commands and Supported elements foreach ($collections as $collection) { - foreach (array('Commands', 'Supported') as $element) { + foreach (['Commands', 'Supported'] as $element) { /** @var DOMElement $collection */ $childrenToRemove = $collection->getElementsByTagName($element); - + foreach ($childrenToRemove as $childToRemove) { $collection->removeChild($childToRemove); } } } - + return $cleanedDocument; } - + /** * merge a partial XML document with the XML document from the previous request - * + * * @param DOMDocument|null $requestBody * @return DOMDocument */ protected function _mergeSyncRequest($requestBody, Syncroton_Model_Device $device) { - $lastSyncCollection = array(); - + $lastSyncCollection = []; + if (!empty($device->lastsynccollection)) { $lastSyncCollection = Zend_Json::decode($device->lastsynccollection); if (!empty($lastSyncCollection['lastXML'])) { $lastXML = new DOMDocument(); $lastXML->loadXML($lastSyncCollection['lastXML']); } } - + if (! $requestBody instanceof DOMDocument) { if (!empty($lastXML)) { $requestBody = $lastXML; } else { throw new Syncroton_Exception_UnexpectedValue('no xml body found'); } } - + if ($requestBody->getElementsByTagName('Partial')->length > 0) { $partialBody = clone $requestBody; $requestBody = $lastXML ?? (new DOMDocument()); - + $xpath = new DomXPath($requestBody); $xpath->registerNamespace('AirSync', 'uri:AirSync'); - + foreach ($partialBody->documentElement->childNodes as $child) { if (! $child instanceof DOMElement) { continue; } /** @var DOMElement $child */ if ($child->tagName == 'Partial') { continue; } - + if ($child->tagName == 'Collections') { foreach ($child->getElementsByTagName('Collection') as $updatedCollection) { $collectionId = $updatedCollection->getElementsByTagName('CollectionId')->item(0)->nodeValue; - + $existingCollections = $xpath->query("//AirSync:Sync/AirSync:Collections/AirSync:Collection[AirSync:CollectionId='$collectionId']"); - + if ($existingCollections->length > 0) { /** @var DOMElement $existingCollection */ $existingCollection = $existingCollections->item(0); foreach ($updatedCollection->childNodes as $updatedCollectionChild) { if (! $updatedCollectionChild instanceof DOMElement) { continue; } $duplicateChild = $existingCollection->getElementsByTagName($updatedCollectionChild->tagName); - + if ($duplicateChild->length > 0) { - $existingCollection->replaceChild($requestBody->importNode($updatedCollectionChild, TRUE), $duplicateChild->item(0)); + $existingCollection->replaceChild($requestBody->importNode($updatedCollectionChild, true), $duplicateChild->item(0)); } else { - $existingCollection->appendChild($requestBody->importNode($updatedCollectionChild, TRUE)); + $existingCollection->appendChild($requestBody->importNode($updatedCollectionChild, true)); } } } else { - $importedCollection = $requestBody->importNode($updatedCollection, TRUE); + $importedCollection = $requestBody->importNode($updatedCollection, true); } } - + } else { $duplicateChild = $xpath->query("//AirSync:Sync/AirSync:{$child->tagName}"); - + if ($duplicateChild->length > 0) { - $requestBody->documentElement->replaceChild($requestBody->importNode($child, TRUE), $duplicateChild->item(0)); + $requestBody->documentElement->replaceChild($requestBody->importNode($child, true), $duplicateChild->item(0)); } else { - $requestBody->documentElement->appendChild($requestBody->importNode($child, TRUE)); + $requestBody->documentElement->appendChild($requestBody->importNode($child, true)); } } } } - + $lastSyncCollection['lastXML'] = $this->_cleanUpXML($requestBody)->saveXML(); - + $device->lastsynccollection = Zend_Json::encode($lastSyncCollection); - + return $requestBody; } } diff --git a/lib/ext/Syncroton/Command/Wbxml.php b/lib/ext/Syncroton/Command/Wbxml.php index fc32dbf..10af53d 100644 --- a/lib/ext/Syncroton/Command/Wbxml.php +++ b/lib/ext/Syncroton/Command/Wbxml.php @@ -1,222 +1,223 @@ */ /** * abstract class for all commands using wbxml encoded content * * @package Syncroton * @subpackage Command */ - + abstract class Syncroton_Command_Wbxml implements Syncroton_Command_ICommand { /** * informations about the currently device * * @var Syncroton_Model_IDevice */ protected $_device; - + /** * informations about the currently device * * @var Syncroton_Backend_IDevice */ protected $_deviceBackend; - + /** * informations about the currently device * * @var Syncroton_Backend_IFolder */ protected $_folderBackend; - + /** * @var Syncroton_Backend_ISyncState */ protected $_syncStateBackend; - + /** * @var Syncroton_Backend_IContent */ protected $_contentStateBackend; - + /** * @var Syncroton_Backend_Policy */ protected $_policyBackend; - + /** * the domDocument containing the xml response from the server * * @var DOMDocument */ protected $_outputDom; - + /** * the domDocucment containing the xml request from the client * * @var DOMDocument */ protected $_requestBody; - + /** * the default namespace * * @var ?string */ protected $_defaultNameSpace; - + /** * the main xml tag * * @var ?string */ protected $_documentElement; - + /** * @var array */ protected $_requestParameters; - + /** * @var Syncroton_Model_SyncState */ protected $_syncState; - + protected $_skipValidatePolicyKey = false; - + /** * timestamp to use for all sync requests * * @var DateTime */ protected $_syncTimeStamp; - + /** * @var string */ protected $_transactionId; - + /** * @var string */ protected $_policyKey; - + /** * @var Zend_Log */ protected $_logger; - + /** * list of part streams - * + * * @var array */ - protected $_parts = array(); - + protected $_parts = []; + /** * list of headers - * + * * @var array */ - protected $_headers = array(); - + protected $_headers = []; + /** * the constructor * * @param mixed $requestBody * @param Syncroton_Model_Device $device * @param array $requestParameters */ public function __construct($requestBody, Syncroton_Model_IDevice $device, $requestParameters = []) { $this->_requestBody = $requestBody; $this->_device = $device; $this->_requestParameters = $requestParameters; - $this->_policyKey = isset($requestParameters['policyKey']) ? $requestParameters['policyKey'] : null; + $this->_policyKey = $requestParameters['policyKey'] ?? null; $this->_deviceBackend = Syncroton_Registry::getDeviceBackend(); $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'); } - + $this->_syncTimeStamp = new DateTime('now', new DateTimeZone('UTC')); - + // set default content type $this->_headers['Content-Type'] = 'application/vnd.ms-sync.wbxml'; - - if ($this->_logger instanceof Zend_Log) + + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " sync timestamp: " . $this->_syncTimeStamp->format('Y-m-d H:i:s')); - + } + if (isset($this->_defaultNameSpace) && isset($this->_documentElement)) { // Creates an instance of the DOMImplementation class $imp = new DOMImplementation(); - + // Creates a DOMDocumentType instance $dtd = $imp->createDocumentType('AirSync', "-//AIRSYNC//DTD AirSync//EN", "http://www.microsoft.com/"); - + // Creates a DOMDocument instance $this->_outputDom = $imp->createDocument($this->_defaultNameSpace, $this->_documentElement, $dtd); $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Syncroton', 'uri:Syncroton'); $this->_outputDom->formatOutput = false; $this->_outputDom->encoding = 'utf-8'; } - + if ($this->_skipValidatePolicyKey != true) { if (!empty($this->_device->policyId)) { /** @var Syncroton_Model_Policy $policy */ $policy = $this->_policyBackend->get($this->_device->policyId); if ((int) $policy->policyKey != (int) $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; } } } } - + /** * (non-PHPdoc) * @see Syncroton_Command_ICommand::getHeaders() */ public function getHeaders() { return $this->_headers; } /** * return array of part streams - * + * * @return array */ public function getParts() { return $this->_parts; } } diff --git a/lib/ext/Syncroton/Data/AData.php b/lib/ext/Syncroton/Data/AData.php index 39ca19a..85a395a 100644 --- a/lib/ext/Syncroton/Data/AData.php +++ b/lib/ext/Syncroton/Data/AData.php @@ -1,384 +1,383 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Data */ abstract class Syncroton_Data_AData implements Syncroton_Data_IData { - const LONGID_DELIMITER = "\xe2\x87\x94"; // UTF-8 character ⇔ + public const LONGID_DELIMITER = "\xe2\x87\x94"; // UTF-8 character ⇔ /** @var DateTime */ protected $_timeStamp; /** @var Syncroton_Model_IDevice */ protected $_device; /** @var Zend_Db_Adapter_Abstract */ protected $_db; /** @var string */ protected $_tablePrefix; /** @var string */ protected $_ownerId; /** @var array */ protected $_supportedFolderTypes = []; /** * the constructor - * + * * @param Syncroton_Model_IDevice $_device * @param DateTime $_timeStamp */ public function __construct(Syncroton_Model_IDevice $_device, DateTime $_timeStamp) { $this->_device = $_device; $this->_timeStamp = $_timeStamp; $this->_db = Syncroton_Registry::getDatabase(); $this->_tablePrefix = 'Syncroton_'; $this->_ownerId = '1234'; } - + /** * return one folder identified by id - * + * * @param string $id * @throws Syncroton_Exception_NotFound * @return Syncroton_Model_Folder */ public function getFolder($id) { $select = $this->_db->select() ->from($this->_tablePrefix . 'data_folder') ->where('owner_id = ?', $this->_ownerId) ->where('id = ?', $id); - + $stmt = $this->_db->query($select); $folder = $stmt->fetch(); $stmt = null; # see https://bugs.php.net/bug.php?id=44081 - + if ($folder === false) { throw new Syncroton_Exception_NotFound("folder $id not found"); } - - return new Syncroton_Model_Folder(array( + + return new Syncroton_Model_Folder([ 'serverId' => $folder['id'], 'displayName' => $folder['name'], 'type' => $folder['type'], - 'parentId' => !empty($folder['parent_id']) ? $folder['parent_id'] : null - )); + 'parentId' => !empty($folder['parent_id']) ? $folder['parent_id'] : null, + ]); } - + /** * (non-PHPdoc) * @see Syncroton_Data_IData::createFolder() */ public function createFolder(Syncroton_Model_IFolder $folder) { if (!in_array($folder->type, $this->_supportedFolderTypes)) { throw new Syncroton_Exception_UnexpectedValue(); } - - $id = !empty($folder->serverId) ? $folder->serverId : sha1(mt_rand(). microtime()); - - $this->_db->insert($this->_tablePrefix . 'data_folder', array( + + $id = !empty($folder->serverId) ? $folder->serverId : sha1(mt_rand() . microtime()); + + $this->_db->insert($this->_tablePrefix . 'data_folder', [ 'id' => $id, 'type' => $folder->type, 'name' => $folder->displayName, 'owner_id' => $this->_ownerId, 'parent_id' => $folder->parentId, - 'creation_time' => $this->_timeStamp->format("Y-m-d H:i:s") - )); - + 'creation_time' => $this->_timeStamp->format("Y-m-d H:i:s"), + ]); + return $this->getFolder($id); } - + /** * (non-PHPdoc) * @see Syncroton_Data_IData::createEntry() */ - public function createEntry($_folderId, Syncroton_Model_IEntry $_entry) - { - $id = sha1(mt_rand(). microtime()); - - $this->_db->insert($this->_tablePrefix . 'data', array( - 'id' => $id, + public function createEntry($_folderId, Syncroton_Model_IEntry $_entry) + { + $id = sha1(mt_rand() . microtime()); + + $this->_db->insert($this->_tablePrefix . 'data', [ + 'id' => $id, 'class' => get_class($_entry), 'folder_id' => $_folderId, 'creation_time' => $this->_timeStamp->format("Y-m-d H:i:s"), - 'data' => serialize($_entry) - )); - - return $id; - } - + 'data' => serialize($_entry), + ]); + + return $id; + } + /** * (non-PHPdoc) * @see Syncroton_Data_IData::deleteEntry() */ public function deleteEntry($_folderId, $_serverId, $_collectionData = null) { $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->serverId : $_folderId; - - $result = $this->_db->delete($this->_tablePrefix . 'data', array('id = ?' => $_serverId)); - + + $result = $this->_db->delete($this->_tablePrefix . 'data', ['id = ?' => $_serverId]); + return (bool) $result; } - + /** * (non-PHPdoc) * @see Syncroton_Data_IData::deleteFolder() */ public function deleteFolder($_folderId) { $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->serverId : $_folderId; - - $result = $this->_db->delete($this->_tablePrefix . 'data', array('folder_id = ?' => $folderId)); - $result = $this->_db->delete($this->_tablePrefix . 'data_folder', array('id = ?' => $folderId)); - + + $result = $this->_db->delete($this->_tablePrefix . 'data', ['folder_id = ?' => $folderId]); + $result = $this->_db->delete($this->_tablePrefix . 'data_folder', ['id = ?' => $folderId]); + return (bool) $result; } - + /** * (non-PHPdoc) * @see Syncroton_Data_IData::emptyFolderContents() */ public function emptyFolderContents($folderId, $options) { return true; } - + /** * (non-PHPdoc) * @see Syncroton_Data_IData::getAllFolders() */ public function getAllFolders() { $select = $this->_db->select() ->from($this->_tablePrefix . 'data_folder') ->where('type IN (?)', $this->_supportedFolderTypes) ->where('owner_id = ?', $this->_ownerId); - + $stmt = $this->_db->query($select); $folders = $stmt->fetchAll(); $stmt = null; # see https://bugs.php.net/bug.php?id=44081 - - $result = array(); - + + $result = []; + foreach ((array) $folders as $folder) { - $result[$folder['id']] = new Syncroton_Model_Folder(array( + $result[$folder['id']] = new Syncroton_Model_Folder([ 'serverId' => $folder['id'], 'displayName' => $folder['name'], 'type' => $folder['type'], - 'parentId' => $folder['parent_id'] - )); + 'parentId' => $folder['parent_id'], + ]); } - + return $result; } - + /** * (non-PHPdoc) * @see Syncroton_Data_IData::getChangedEntries() */ - public function getChangedEntries($_folderId, Syncroton_Model_ISyncState $syncState, $filterType = NULL) + public function getChangedEntries($_folderId, Syncroton_Model_ISyncState $syncState, $filterType = null) { $_startTimeStamp = $syncState->lastsync; $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId; - + $select = $this->_db->select() - ->from($this->_tablePrefix . 'data', array('id')) + ->from($this->_tablePrefix . 'data', ['id']) ->where('folder_id = ?', $_folderId) ->where('last_modified_time > ?', $_startTimeStamp->format("Y-m-d H:i:s")); - - $ids = array(); - + + $ids = []; + $stmt = $this->_db->query($select); while ($id = $stmt->fetchColumn()) { $ids[] = $id; } - + return $ids; } - + /** * retrieve folders which were modified since last sync - * + * * @param DateTime $startTimeStamp * @param DateTime $endTimeStamp * @return array list of Syncroton_Model_Folder */ public function getChangedFolders(DateTime $startTimeStamp, DateTime $endTimeStamp) { $select = $this->_db->select() ->from($this->_tablePrefix . 'data_folder') ->where('type IN (?)', $this->_supportedFolderTypes) ->where('owner_id = ?', $this->_ownerId) ->where('last_modified_time > ?', $startTimeStamp->format('Y-m-d H:i:s')) ->where('last_modified_time <= ?', $endTimeStamp->format('Y-m-d H:i:s')); - + $stmt = $this->_db->query($select); $folders = $stmt->fetchAll(); $stmt = null; # see https://bugs.php.net/bug.php?id=44081 - - $result = array(); - + + $result = []; + foreach ((array) $folders as $folder) { - $result[$folder['id']] = new Syncroton_Model_Folder(array( + $result[$folder['id']] = new Syncroton_Model_Folder([ 'serverId' => $folder['id'], 'displayName' => $folder['name'], 'type' => $folder['type'], - 'parentId' => $folder['parent_id'] - )); + 'parentId' => $folder['parent_id'], + ]); } - + return $result; } - + /** * @param Syncroton_Model_IFolder|string $_folderId * @param string $_filter * @return array */ public function getServerEntries($_folderId, $_filter) { $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId; - - $select = $this->_db->select() - ->from($this->_tablePrefix . 'data', array('id')) - ->where('folder_id = ?', $_folderId); - - $ids = array(); - - $stmt = $this->_db->query($select); + + $select = $this->_db->select() + ->from($this->_tablePrefix . 'data', ['id']) + ->where('folder_id = ?', $_folderId); + + $ids = []; + + $stmt = $this->_db->query($select); while ($id = $stmt->fetchColumn()) { $ids[] = $id; - } - - return $ids; + } + + return $ids; } - + /** * (non-PHPdoc) * @see Syncroton_Data_IData::getCountOfChanges() */ 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->serverId, $folder->lastfiltertype); - + $addedEntries = array_diff($allServerEntries, $allClientEntries); $deletedEntries = array_diff($allClientEntries, $allServerEntries); $changedEntries = $this->getChangedEntries($folder->serverId, $syncState, $folder->lastfiltertype); - + return count($addedEntries) + count($deletedEntries) + count($changedEntries); } - + /** * (non-PHPdoc) * @see Syncroton_Data_IData::getFileReference() */ - public function getFileReference($fileReference) - { - throw new Syncroton_Exception_NotFound('filereference not found'); - } - + public function getFileReference($fileReference) + { + throw new Syncroton_Exception_NotFound('filereference not found'); + } + /** * (non-PHPdoc) * @see Syncroton_Data_IData::getEntry() */ - public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId) - { + public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId) + { $select = $this->_db->select() - ->from($this->_tablePrefix . 'data', array('data')) + ->from($this->_tablePrefix . 'data', ['data']) ->where('id = ?', $serverId); - + $stmt = $this->_db->query($select); $entry = $stmt->fetchColumn(); if ($entry === false) { throw new Syncroton_Exception_NotFound("entry $serverId not found in folder {$collection->collectionId}"); } - + return unserialize($entry); - } + } /** * (non-PHPdoc) * @see Syncroton_Data_IData::hasChanges() */ public function hasChanges(Syncroton_Backend_IContent $contentBackend, Syncroton_Model_IFolder $folder, Syncroton_Model_ISyncState $syncState) { return !!$this->getCountOfChanges($contentBackend, $folder, $syncState); } - + /** * (non-PHPdoc) * @see Syncroton_Data_IData::moveItem() */ public function moveItem($_srcFolderId, $_serverId, $_dstFolderId) { - $this->_db->update($this->_tablePrefix . 'data', array( - 'folder_id' => $_dstFolderId, - ), array( - 'id = ?' => $_serverId - )); - + $this->_db->update($this->_tablePrefix . 'data', [ + 'folder_id' => $_dstFolderId, + ], [ + 'id = ?' => $_serverId, + ]); + return $_serverId; } - + /** * (non-PHPdoc) * @see Syncroton_Data_IData::updateEntry() */ - public function updateEntry($_folderId, $_serverId, Syncroton_Model_IEntry $_entry) + public function updateEntry($_folderId, $_serverId, Syncroton_Model_IEntry $_entry) { - $this->_db->update($this->_tablePrefix . 'data', array( + $this->_db->update($this->_tablePrefix . 'data', [ 'folder_id' => $_folderId, 'last_modified_time' => $this->_timeStamp->format("Y-m-d H:i:s"), - 'data' => serialize($_entry) - ), array( - 'id = ?' => $_serverId - )); + 'data' => serialize($_entry), + ], [ + 'id = ?' => $_serverId, + ]); return $_serverId; } - + /** * (non-PHPdoc) * @see Syncroton_Data_IData::updateFolder() - */ - public function updateFolder(Syncroton_Model_IFolder $folder) - { - $this->_db->update($this->_tablePrefix . 'data_folder', array( + */ + public function updateFolder(Syncroton_Model_IFolder $folder) + { + $this->_db->update($this->_tablePrefix . 'data_folder', [ 'name' => $folder->displayName, 'parent_id' => $folder->parentId, 'last_modified_time' => $this->_timeStamp->format("Y-m-d H:i:s"), - ), array( + ], [ 'id = ?' => $folder->serverId, - 'owner_id = ?' => $this->_ownerId - )); - + 'owner_id = ?' => $this->_ownerId, + ]); + return $this->getFolder($folder->serverId); - } + } public function getExtraData(Syncroton_Model_IFolder $folder) { return null; } } - diff --git a/lib/ext/Syncroton/Data/Calendar.php b/lib/ext/Syncroton/Data/Calendar.php index bf6d224..952d188 100644 --- a/lib/ext/Syncroton/Data/Calendar.php +++ b/lib/ext/Syncroton/Data/Calendar.php @@ -1,37 +1,36 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Data */ class Syncroton_Data_Calendar extends Syncroton_Data_AData implements Syncroton_Data_IDataCalendar { - protected $_supportedFolderTypes = array( + protected $_supportedFolderTypes = [ Syncroton_Command_FolderSync::FOLDERTYPE_CALENDAR, - Syncroton_Command_FolderSync::FOLDERTYPE_CALENDAR_USER_CREATED - ); - + Syncroton_Command_FolderSync::FOLDERTYPE_CALENDAR_USER_CREATED, + ]; + /** * set attendee status for meeting - * + * * @param Syncroton_Model_MeetingResponse $response The meeting response * * @return string ID of new calendar entry */ public function setAttendeeStatus(Syncroton_Model_MeetingResponse $response) { return $response->requestId; } } - diff --git a/lib/ext/Syncroton/Data/Contacts.php b/lib/ext/Syncroton/Data/Contacts.php index e593d9b..4f82744 100644 --- a/lib/ext/Syncroton/Data/Contacts.php +++ b/lib/ext/Syncroton/Data/Contacts.php @@ -1,84 +1,83 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Data */ class Syncroton_Data_Contacts extends Syncroton_Data_AData implements Syncroton_Data_IDataSearch { - protected $_supportedFolderTypes = array( + protected $_supportedFolderTypes = [ Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT, - Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT_USER_CREATED - ); - + Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT_USER_CREATED, + ]; + /** * (non-PHPdoc) * @see Syncroton_Data_IDataSearch::getSearchEntry() */ public function getSearchEntry($longId, $options) { - list($collectionId, $serverId) = explode(Syncroton_Data_AData::LONGID_DELIMITER, $longId, 2); + [$collectionId, $serverId] = explode(Syncroton_Data_AData::LONGID_DELIMITER, $longId, 2); /** @var Syncroton_Model_Contact $contact */ - $contact = $this->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $collectionId)), $serverId); - - return new Syncroton_Model_GAL(array( + $contact = $this->getEntry(new Syncroton_Model_SyncCollection(['collectionId' => $collectionId]), $serverId); + + return new Syncroton_Model_GAL([ 'firstName' => $contact->firstName, 'lastName' => $contact->lastName, - 'picture' => new Syncroton_Model_GALPicture(array('status' => 1, 'data' => 'abc')) - )); + 'picture' => new Syncroton_Model_GALPicture(['status' => 1, 'data' => 'abc']), + ]); } - + /** * (non-PHPdoc) * @see Syncroton_Data_IDataSearch::search() */ public function search(Syncroton_Model_StoreRequest $store) { $storeResponse = new Syncroton_Model_StoreResponse(); - + $serverIds = $this->getServerEntries('addressbookFolderId', Syncroton_Command_Sync::FILTER_NOTHING); - + $total = 0; - $found = array(); - + $found = []; + foreach ($serverIds as $serverId) { /** @var Syncroton_Model_Contact $contact */ - $contact = $this->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => 'addressbookFolderId')), $serverId); - + $contact = $this->getEntry(new Syncroton_Model_SyncCollection(['collectionId' => 'addressbookFolderId']), $serverId); + if ($contact->firstName == $store->query) { $total++; - - if (count($found) == $store->options['range'][1]+1) { + + if (count($found) == $store->options['range'][1] + 1) { continue; } - $found[] = new Syncroton_Model_StoreResponseResult(array( - 'longId' => 'addressbookFolderId' . Syncroton_Data_AData::LONGID_DELIMITER . $serverId, - 'properties' => $this->getSearchEntry('addressbookFolderId' . Syncroton_Data_AData::LONGID_DELIMITER . $serverId, $store->options) - )); + $found[] = new Syncroton_Model_StoreResponseResult([ + 'longId' => 'addressbookFolderId' . Syncroton_Data_AData::LONGID_DELIMITER . $serverId, + 'properties' => $this->getSearchEntry('addressbookFolderId' . Syncroton_Data_AData::LONGID_DELIMITER . $serverId, $store->options), + ]); } } - + if (count($found) > 0) { $storeResponse->result = $found; - $storeResponse->range = array(0, count($found) - 1); + $storeResponse->range = [0, count($found) - 1]; $storeResponse->total = $total; } else { - $storeResponse->total = $total; + $storeResponse->total = $total; } - + return $storeResponse; } } - diff --git a/lib/ext/Syncroton/Data/Email.php b/lib/ext/Syncroton/Data/Email.php index 6ca78ef..ffe1978 100644 --- a/lib/ext/Syncroton/Data/Email.php +++ b/lib/ext/Syncroton/Data/Email.php @@ -1,88 +1,87 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Data */ class Syncroton_Data_Email extends Syncroton_Data_AData implements Syncroton_Data_IDataEmail { - protected $_supportedFolderTypes = array( + protected $_supportedFolderTypes = [ Syncroton_Command_FolderSync::FOLDERTYPE_DELETEDITEMS, Syncroton_Command_FolderSync::FOLDERTYPE_DRAFTS, Syncroton_Command_FolderSync::FOLDERTYPE_INBOX, Syncroton_Command_FolderSync::FOLDERTYPE_MAIL_USER_CREATED, Syncroton_Command_FolderSync::FOLDERTYPE_OUTBOX, - Syncroton_Command_FolderSync::FOLDERTYPE_SENTMAIL - ); - + Syncroton_Command_FolderSync::FOLDERTYPE_SENTMAIL, + ]; + /** * (non-PHPdoc) * @see Syncroton_Data_IDataEmail::forwardEmail() */ public function forwardEmail($source, $inputStream, $saveInSent, $replaceMime) { - if ($inputStream == 'triggerException') { - throw new Syncroton_Exception_Status(Syncroton_Exception_Status::MAILBOX_SERVER_OFFLINE); - } - + if ($inputStream == 'triggerException') { + throw new Syncroton_Exception_Status(Syncroton_Exception_Status::MAILBOX_SERVER_OFFLINE); + } + // forward email } - + /** * (non-PHPdoc) * @see Syncroton_Data_AData::getFileReference() */ - public function getFileReference($fileReference) - { - list($messageId, $partId) = explode(Syncroton_Data_AData::LONGID_DELIMITER, $fileReference, 2); - - // example code - return new Syncroton_Model_FileReference(array( - 'contentType' => 'text/plain', - 'data' => 'Lars' - )); + public function getFileReference($fileReference) + { + [$messageId, $partId] = explode(Syncroton_Data_AData::LONGID_DELIMITER, $fileReference, 2); + + // example code + return new Syncroton_Model_FileReference([ + 'contentType' => 'text/plain', + 'data' => 'Lars', + ]); } - + /** * (non-PHPdoc) * @see Syncroton_Data_IDataEmail::replyEmail() - */ - public function replyEmail($source, $inputStream, $saveInSent, $replaceMime) - { - // forward email - } - + */ + public function replyEmail($source, $inputStream, $saveInSent, $replaceMime) + { + // forward email + } + /** * (non-PHPdoc) * @see Syncroton_Data_AData::updateEntry() */ public function updateEntry($_folderId, $_serverId, Syncroton_Model_IEntry $_entry) { // not used by email return ''; } - + /** * (non-PHPdoc) * @see Syncroton_Data_IDataEmail::sendEmail() */ public function sendEmail($inputStream, $saveInSent) { if ($inputStream == 'triggerException') { throw new Syncroton_Exception_Status(Syncroton_Exception_Status::MAILBOX_SERVER_OFFLINE); } // send email } } - diff --git a/lib/ext/Syncroton/Data/Factory.php b/lib/ext/Syncroton/Data/Factory.php index e9be6c4..6042f30 100644 --- a/lib/ext/Syncroton/Data/Factory.php +++ b/lib/ext/Syncroton/Data/Factory.php @@ -1,79 +1,79 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Data */ class Syncroton_Data_Factory { - const CLASS_CALENDAR = 'Calendar'; - const CLASS_CONTACTS = 'Contacts'; - const CLASS_EMAIL = 'Email'; - const CLASS_NOTES = 'Notes'; - const CLASS_TASKS = 'Tasks'; - const STORE_EMAIL = 'Mailbox'; - const STORE_GAL = 'GAL'; - - protected static $_classMap = array(); - + public const CLASS_CALENDAR = 'Calendar'; + public const CLASS_CONTACTS = 'Contacts'; + public const CLASS_EMAIL = 'Email'; + public const CLASS_NOTES = 'Notes'; + public const CLASS_TASKS = 'Tasks'; + public const STORE_EMAIL = 'Mailbox'; + public const STORE_GAL = 'GAL'; + + protected static $_classMap = []; + /** * @param string $_classFactory * @param Syncroton_Model_IDevice $_device * @param DateTime $_timeStamp * * @throws InvalidArgumentException * @return Syncroton_Data_IData */ public static function factory($_classFactory, Syncroton_Model_IDevice $_device, DateTime $_timeStamp) { switch ($_classFactory) { case self::CLASS_CALENDAR: $className = Syncroton_Registry::get(Syncroton_Registry::CALENDAR_DATA_CLASS); break; - + case self::CLASS_CONTACTS: $className = Syncroton_Registry::get(Syncroton_Registry::CONTACTS_DATA_CLASS); break; - + case self::STORE_EMAIL: case self::CLASS_EMAIL: $className = Syncroton_Registry::get(Syncroton_Registry::EMAIL_DATA_CLASS); break; - + case self::CLASS_NOTES: $className = Syncroton_Registry::get(Syncroton_Registry::NOTES_DATA_CLASS); break; case self::CLASS_TASKS: $className = Syncroton_Registry::get(Syncroton_Registry::TASKS_DATA_CLASS); break; case self::STORE_GAL: $className = Syncroton_Registry::get(Syncroton_Registry::GAL_DATA_CLASS); break; default: throw new Syncroton_Exception_UnexpectedValue('invalid class type provided'); } $class = new $className($_device, $_timeStamp); if (! $class instanceof Syncroton_Data_IData) { throw new RuntimeException('class must be instanceof Syncroton_Data_IData'); } return $class; } } diff --git a/lib/ext/Syncroton/Data/IData.php b/lib/ext/Syncroton/Data/IData.php index 2c1642b..61fefbf 100644 --- a/lib/ext/Syncroton/Data/IData.php +++ b/lib/ext/Syncroton/Data/IData.php @@ -1,134 +1,133 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Data */ interface Syncroton_Data_IData { /** * create new entry - * + * * @param string $folderId * @param Syncroton_Model_IEntry $entry * @return string id of created entry */ public function createEntry($folderId, Syncroton_Model_IEntry $entry); - + /** * create a new folder in backend - * + * * @param Syncroton_Model_IFolder $folder * @return Syncroton_Model_IFolder */ public function createFolder(Syncroton_Model_IFolder $folder); - + /** * delete entry in backend - * + * * @param string $_folderId * @param string $_serverId * @param ?Syncroton_Model_SyncCollection $_collectionData */ public function deleteEntry($_folderId, $_serverId, $_collectionData = null); - + /** * delete folder - * + * * @param string $folderId */ public function deleteFolder($folderId); - + /** * empty folder * * @param string $folderId * @param array $options */ public function emptyFolderContents($folderId, $options); - + /** * return list off all folders * @return array of Syncroton_Model_IFolder */ public function getAllFolders(); - - public function getChangedEntries($folderId, Syncroton_Model_ISyncState $syncState, $filterType = NULL); + + public function getChangedEntries($folderId, Syncroton_Model_ISyncState $syncState, $filterType = null); /** * Retrieve extra data that is stored with the sync key * @return string|null **/ public function getExtraData(Syncroton_Model_IFolder $folder); - - + + /** * retrieve folders which were modified since last sync - * + * * @param DateTime $startTimeStamp * @param DateTime $endTimeStamp */ public function getChangedFolders(DateTime $startTimeStamp, DateTime $endTimeStamp); - + public function getCountOfChanges(Syncroton_Backend_IContent $contentBackend, Syncroton_Model_IFolder $folder, Syncroton_Model_ISyncState $syncState); - + /** - * + * * @param Syncroton_Model_SyncCollection $collection * @param string $serverId * @return Syncroton_Model_IXMLEntry */ public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId); - + /** - * + * * @param string $fileReference * @return Syncroton_Model_FileReference */ public function getFileReference($fileReference); - + /** - * return array of all id's stored in folder - * - * @param Syncroton_Model_IFolder|string $folderId - * @param string $filter - * @return array - */ + * return array of all id's stored in folder + * + * @param Syncroton_Model_IFolder|string $folderId + * @param string $filter + * @return array + */ public function getServerEntries($folderId, $filter); /** * return true if any data got modified in the backend - * + * * @param Syncroton_Backend_IContent $contentBackend * @param Syncroton_Model_IFolder $folder * @param Syncroton_Model_ISyncState $syncState * @return bool */ public function hasChanges(Syncroton_Backend_IContent $contentBackend, Syncroton_Model_IFolder $folder, Syncroton_Model_ISyncState $syncState); - + public function moveItem($srcFolderId, $serverId, $dstFolderId); - + /** * update existing entry - * + * * @param string $folderId * @param string $serverId * @param Syncroton_Model_IEntry $entry * @return string id of updated entry */ public function updateEntry($folderId, $serverId, Syncroton_Model_IEntry $entry); - + public function updateFolder(Syncroton_Model_IFolder $folder); } - diff --git a/lib/ext/Syncroton/Data/IDataCalendar.php b/lib/ext/Syncroton/Data/IDataCalendar.php index da04671..4169428 100644 --- a/lib/ext/Syncroton/Data/IDataCalendar.php +++ b/lib/ext/Syncroton/Data/IDataCalendar.php @@ -1,28 +1,27 @@ */ /** * interface for extended calendar backend * * @package Syncroton * @subpackage Data */ interface Syncroton_Data_IDataCalendar { /** * set attendee status for meeting - * + * * @param Syncroton_Model_MeetingResponse $request the meeting response * @return string id of new calendar entry */ public function setAttendeeStatus(Syncroton_Model_MeetingResponse $request); } - diff --git a/lib/ext/Syncroton/Data/IDataEmail.php b/lib/ext/Syncroton/Data/IDataEmail.php index ed067d2..b9c5adc 100644 --- a/lib/ext/Syncroton/Data/IDataEmail.php +++ b/lib/ext/Syncroton/Data/IDataEmail.php @@ -1,46 +1,45 @@ */ /** * interface for extended email backend * * @package Syncroton * @subpackage Data */ interface Syncroton_Data_IDataEmail { /** * send an email - * + * * @param resource $inputStream * @param boolean $saveInSent */ public function sendEmail($inputStream, $saveInSent); - + /** * forward an email - * + * * @param string|array $source is either a string(LongId) or an array with following properties collectionId, itemId and instanceId * @param string $inputStream * @param string $saveInSent */ public function forwardEmail($source, $inputStream, $saveInSent, $replaceMime); /** * reply to an email - * + * * @param string|array $source is either a string(LongId) or an array with following properties collectionId, itemId and instanceId * @param string $inputStream * @param string $saveInSent */ public function replyEmail($source, $inputStream, $saveInSent, $replaceMime); } - diff --git a/lib/ext/Syncroton/Data/Notes.php b/lib/ext/Syncroton/Data/Notes.php index 0ca89ad..52c9dc8 100644 --- a/lib/ext/Syncroton/Data/Notes.php +++ b/lib/ext/Syncroton/Data/Notes.php @@ -1,24 +1,24 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Data */ class Syncroton_Data_Notes extends Syncroton_Data_AData { - protected $_supportedFolderTypes = array( + protected $_supportedFolderTypes = [ Syncroton_Command_FolderSync::FOLDERTYPE_NOTE, - Syncroton_Command_FolderSync::FOLDERTYPE_NOTE_USER_CREATED - ); + Syncroton_Command_FolderSync::FOLDERTYPE_NOTE_USER_CREATED, + ]; } diff --git a/lib/ext/Syncroton/Data/Tasks.php b/lib/ext/Syncroton/Data/Tasks.php index e44feaf..4ad93ba 100644 --- a/lib/ext/Syncroton/Data/Tasks.php +++ b/lib/ext/Syncroton/Data/Tasks.php @@ -1,25 +1,24 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Data */ class Syncroton_Data_Tasks extends Syncroton_Data_AData { - protected $_supportedFolderTypes = array( + protected $_supportedFolderTypes = [ Syncroton_Command_FolderSync::FOLDERTYPE_TASK, - Syncroton_Command_FolderSync::FOLDERTYPE_TASK_USER_CREATED - ); + Syncroton_Command_FolderSync::FOLDERTYPE_TASK_USER_CREATED, + ]; } - diff --git a/lib/ext/Syncroton/Exception/Status.php b/lib/ext/Syncroton/Exception/Status.php index 5ae96a1..b41494e 100644 --- a/lib/ext/Syncroton/Exception/Status.php +++ b/lib/ext/Syncroton/Exception/Status.php @@ -1,219 +1,219 @@ * @author Aleksander Machniak */ /** * Exception for Status element * * @package Syncroton * @subpackage Exception */ class Syncroton_Exception_Status extends Syncroton_Exception { // http://msdn.microsoft.com/en-us/library/ee218647%28v=exchg.80%29 - const INVALID_CONTENT = 101; - const INVALID_WBXML = 102; - const INVALID_XML = 103; - const INVALID_DATE_TIME = 104; - const INVALID_COMBINATION_OF_IDS = 105; - const INVALID_IDS = 106; - const INVALID_MIME = 107; - const DEVICE_MISSING_OR_INVALID = 108; - const DEVICE_TYPE_MISSING_OR_INVALID = 109; - const SERVER_ERROR = 110; - const SERVER_ERROR_RETRY_LATER = 111; - const ACTIVE_DIRECTORY_ACCESS_DENIED = 112; - const MAILBOX_QUOTA_EXCEEDED = 113; - const MAILBOX_SERVER_OFFLINE = 114; - const SEND_QUOTA_EXCEEDED = 115; - const MESSAGE_RECIPIENT_UNRESOLVED = 116; - const MESSAGE_REPLY_NOT_ALLOWED = 117; - const MESSAGE_PREVIOUSLY_SENT = 118; - const MESSAGE_HAS_NO_RECIPIENT = 119; - const MAIL_SUBMISSION_FAILED = 120; - const MESSAGE_REPLY_FAILED = 121; - const ATTACHMENT_IS_TOO_LARGE = 122; - const USER_HAS_NO_MAILBOX = 123; - const USER_CANNOT_BE_ANONYMOUS = 124; - const USER_PRINCIPAL_COULD_NOT_BE_FOUND = 125; - const USER_DISABLED_FOR_SYNC = 126; - const USER_ON_NEW_MAILBOX_CANNOT_SYNC = 127; - const USER_ON_LEGACY_MAILBOX_CANNOT_SYNC = 128; - const DEVICE_IS_BLOCKED_FOR_THIS_USER = 129; - const ACCESS_DENIED = 130; - const ACCOUNT_DISABLED = 131; - const SYNC_STATE_NOT_FOUND = 132; - const SYNC_STATE_LOCKED = 133; - const SYNC_STATE_CORRUPT = 134; - const SYNC_STATE_ALREADY_EXISTS = 135; - const SYNC_STATE_VERSION_INVALID = 136; - const COMMAND_NOT_SUPPORTED = 137; - const VERSION_NOT_SUPPORTED = 138; - const DEVICE_NOT_FULLY_PROVISIONABLE = 139; - const REMOTE_WIPE_REQUESTED = 140; - const LEGACY_DEVICE_ON_STRICT_POLICY = 141; - const DEVICE_NOT_PROVISIONED = 142; - const POLICY_REFRESH = 143; - const INVALID_POLICY_KEY = 144; - const EXTERNALLY_MANAGED_DEVICES_NOT_ALLOWED = 145; - const NO_RECURRENCE_IN_CALENDAR = 146; - const UNEXPECTED_ITEM_CLASS = 147; - const REMOTE_SERVER_HAS_NO_SSL = 148; - const INVALID_STORED_REQUEST = 149; - const ITEM_NOT_FOUND = 150; - const TOO_MANY_FOLDERS = 151; - const NO_FOLDERS_FOUND = 152; - const ITEMS_LOST_AFTER_MOVE = 153; - const FAILURE_IN_MOVE_OPERATION = 154; - const MOVE_COMMAND_DISALLOWED = 155; - const MOVE_COMMAND_INVALID_DESTINATION = 156; - const AVAILABILITY_TO_MANY_RECIPIENTS = 160; - const AVAILABILITY_DL_LIMIT_REACHED = 161; - const AVAILABILITY_TRANSIENT_FAILURE = 162; - const AVAILABILITY_FAILURE = 163; - const BODY_PART_PREFERENCE_TYPE_NOT_SUPPORTED = 164; - const DEVICE_INFORMATION_REQUIRED = 165; - const INVALID_ACCOUNT_ID = 166; - const ACCOUNT_SEND_DISABLED = 167; - CONST IRM_FEATURE_DISABLED = 168; - const IRM_TRANSIENT_ERROR = 169; - const IRM_PERMANENT_ERROR = 170; - const IRM_INVALID_TEMPLATE_ID = 171; - const IRM_OPERATION_NOT_PERMITTED = 172; - const NO_PICTURE = 173; - const PICTURE_TO_LARGE = 174; - const PICTURE_LIMIT_REACHED = 175; - const BODY_PART_CONVERSATION_TOO_LARGE = 176; - const MAXIMUM_DEVICES_REACHED = 177; + public const INVALID_CONTENT = 101; + public const INVALID_WBXML = 102; + public const INVALID_XML = 103; + public const INVALID_DATE_TIME = 104; + public const INVALID_COMBINATION_OF_IDS = 105; + public const INVALID_IDS = 106; + public const INVALID_MIME = 107; + public const DEVICE_MISSING_OR_INVALID = 108; + public const DEVICE_TYPE_MISSING_OR_INVALID = 109; + public const SERVER_ERROR = 110; + public const SERVER_ERROR_RETRY_LATER = 111; + public const ACTIVE_DIRECTORY_ACCESS_DENIED = 112; + public const MAILBOX_QUOTA_EXCEEDED = 113; + public const MAILBOX_SERVER_OFFLINE = 114; + public const SEND_QUOTA_EXCEEDED = 115; + public const MESSAGE_RECIPIENT_UNRESOLVED = 116; + public const MESSAGE_REPLY_NOT_ALLOWED = 117; + public const MESSAGE_PREVIOUSLY_SENT = 118; + public const MESSAGE_HAS_NO_RECIPIENT = 119; + public const MAIL_SUBMISSION_FAILED = 120; + public const MESSAGE_REPLY_FAILED = 121; + public const ATTACHMENT_IS_TOO_LARGE = 122; + public const USER_HAS_NO_MAILBOX = 123; + public const USER_CANNOT_BE_ANONYMOUS = 124; + public const USER_PRINCIPAL_COULD_NOT_BE_FOUND = 125; + public const USER_DISABLED_FOR_SYNC = 126; + public const USER_ON_NEW_MAILBOX_CANNOT_SYNC = 127; + public const USER_ON_LEGACY_MAILBOX_CANNOT_SYNC = 128; + public const DEVICE_IS_BLOCKED_FOR_THIS_USER = 129; + public const ACCESS_DENIED = 130; + public const ACCOUNT_DISABLED = 131; + public const SYNC_STATE_NOT_FOUND = 132; + public const SYNC_STATE_LOCKED = 133; + public const SYNC_STATE_CORRUPT = 134; + public const SYNC_STATE_ALREADY_EXISTS = 135; + public const SYNC_STATE_VERSION_INVALID = 136; + public const COMMAND_NOT_SUPPORTED = 137; + public const VERSION_NOT_SUPPORTED = 138; + public const DEVICE_NOT_FULLY_PROVISIONABLE = 139; + public const REMOTE_WIPE_REQUESTED = 140; + public const LEGACY_DEVICE_ON_STRICT_POLICY = 141; + public const DEVICE_NOT_PROVISIONED = 142; + public const POLICY_REFRESH = 143; + public const INVALID_POLICY_KEY = 144; + public const EXTERNALLY_MANAGED_DEVICES_NOT_ALLOWED = 145; + public const NO_RECURRENCE_IN_CALENDAR = 146; + public const UNEXPECTED_ITEM_CLASS = 147; + public const REMOTE_SERVER_HAS_NO_SSL = 148; + public const INVALID_STORED_REQUEST = 149; + public const ITEM_NOT_FOUND = 150; + public const TOO_MANY_FOLDERS = 151; + public const NO_FOLDERS_FOUND = 152; + public const ITEMS_LOST_AFTER_MOVE = 153; + public const FAILURE_IN_MOVE_OPERATION = 154; + public const MOVE_COMMAND_DISALLOWED = 155; + public const MOVE_COMMAND_INVALID_DESTINATION = 156; + public const AVAILABILITY_TO_MANY_RECIPIENTS = 160; + public const AVAILABILITY_DL_LIMIT_REACHED = 161; + public const AVAILABILITY_TRANSIENT_FAILURE = 162; + public const AVAILABILITY_FAILURE = 163; + public const BODY_PART_PREFERENCE_TYPE_NOT_SUPPORTED = 164; + public const DEVICE_INFORMATION_REQUIRED = 165; + public const INVALID_ACCOUNT_ID = 166; + public const ACCOUNT_SEND_DISABLED = 167; + public const IRM_FEATURE_DISABLED = 168; + public const IRM_TRANSIENT_ERROR = 169; + public const IRM_PERMANENT_ERROR = 170; + public const IRM_INVALID_TEMPLATE_ID = 171; + public const IRM_OPERATION_NOT_PERMITTED = 172; + public const NO_PICTURE = 173; + public const PICTURE_TO_LARGE = 174; + public const PICTURE_LIMIT_REACHED = 175; + public const BODY_PART_CONVERSATION_TOO_LARGE = 176; + public const MAXIMUM_DEVICES_REACHED = 177; /** * Common error messages assigned to error codes * * @var array */ - protected $_commonMessages = array( + protected $_commonMessages = [ self::INVALID_CONTENT => "Invalid request body", self::INVALID_WBXML => "Invalid WBXML request", self::INVALID_XML => "Invalid XML request", self::INVALID_DATE_TIME => "Invalid datetime string", self::INVALID_COMBINATION_OF_IDS => "Invalid combination of parameters", self::INVALID_IDS => "Invalid one or more IDs", self::INVALID_MIME => "Invalid MIME content", self::DEVICE_MISSING_OR_INVALID => "Device ID invalid or missing", self::DEVICE_TYPE_MISSING_OR_INVALID => "Device type invalid or missing", self::SERVER_ERROR => "Unknown server error", self::SERVER_ERROR_RETRY_LATER => "Unknown server error. Device should retry later", self::ACTIVE_DIRECTORY_ACCESS_DENIED => "No access to an object in the directory service", self::MAILBOX_QUOTA_EXCEEDED => "The mailbox quota size exceeded", self::MAILBOX_SERVER_OFFLINE => "The mailbox server is offline", self::SEND_QUOTA_EXCEEDED => "The request would exceed the send quota", self::MESSAGE_RECIPIENT_UNRESOLVED => "Recipient could not be resolved to an e-mail address", self::MESSAGE_REPLY_NOT_ALLOWED => "The mailbox server doesn't allow a reply of this message", self::MESSAGE_PREVIOUSLY_SENT => "The message was already sent in a previous request", self::MESSAGE_HAS_NO_RECIPIENT => "The message being sent contains no recipient", self::MAIL_SUBMISSION_FAILED => "The server failed to submit the message for delivery", self::MESSAGE_REPLY_FAILED => "The server failed to create a reply message", self::ATTACHMENT_IS_TOO_LARGE => "The attachment is too large", self::USER_HAS_NO_MAILBOX => "A mailbox could not be found for the user", self::USER_CANNOT_BE_ANONYMOUS => "The request was sent without credentials. Anonymous requests are not allowed", self::USER_PRINCIPAL_COULD_NOT_BE_FOUND => "The user was not found in the directory service", self::USER_DISABLED_FOR_SYNC => "This user is not allowed to use ActiveSync", self::USER_ON_NEW_MAILBOX_CANNOT_SYNC => "The server is configured to prevent users from syncing", self::USER_ON_LEGACY_MAILBOX_CANNOT_SYNC => "The server is configured to prevent users on legacy servers from syncing", self::DEVICE_IS_BLOCKED_FOR_THIS_USER => "This device is not the allowed device", self::ACCESS_DENIED => "The user is not allowed to perform that request", self::ACCOUNT_DISABLED => "The user's account is disabled", self::SYNC_STATE_NOT_FOUND => "Missing data file that contains the state of the client", self::SYNC_STATE_LOCKED => "Locked data file that contains the state of the client", self::SYNC_STATE_CORRUPT => "Corrupted data file that contains the state of the client", self::SYNC_STATE_ALREADY_EXISTS => "The data file that contains the state of the client already exists", self::SYNC_STATE_VERSION_INVALID => "Version of the data file that contains the state of the client is invalid", self::COMMAND_NOT_SUPPORTED => "The command is not supported by this server", self::VERSION_NOT_SUPPORTED => "The command is not supported in the protocol version specified", self::DEVICE_NOT_FULLY_PROVISIONABLE => "The device uses a protocol version that cannot send all the policy settings the admin enabled", self::REMOTE_WIPE_REQUESTED => "A remote wipe was requested", self::LEGACY_DEVICE_ON_STRICT_POLICY => "A policy is in place but the device is not provisionable", self::DEVICE_NOT_PROVISIONED => "There is a policy in place", self::POLICY_REFRESH => "The policy is configured to be refreshed every few hours", self::INVALID_POLICY_KEY => "The device's policy key is invalid", self::EXTERNALLY_MANAGED_DEVICES_NOT_ALLOWED => "The server doesn't allow externally managed devices to sync", self::NO_RECURRENCE_IN_CALENDAR => "The request tried to forward an occurrence of a meeting that has no recurrence", self::UNEXPECTED_ITEM_CLASS => "The request tried to operate on a type of items unknown to the server", self::REMOTE_SERVER_HAS_NO_SSL => "Remote server doesn't have SSL enabled", self::INVALID_STORED_REQUEST => "The stored result is invalid. The device should send the full request again", self::ITEM_NOT_FOUND => "Item not found", self::TOO_MANY_FOLDERS => "The mailbox contains too many folders", self::NO_FOLDERS_FOUND => "The mailbox contains no folders", self::ITEMS_LOST_AFTER_MOVE => "Items lost after move", self::FAILURE_IN_MOVE_OPERATION => "The mailbox server returned an unknown error while moving items", self::MOVE_COMMAND_DISALLOWED => "An ItemOperations command request to move a conversation is missing the MoveAlways element", self::MOVE_COMMAND_INVALID_DESTINATION => "The destination folder for the move is invalid", self::AVAILABILITY_TO_MANY_RECIPIENTS => "The command has reached the maximum number of recipients that it can request availability for", self::AVAILABILITY_DL_LIMIT_REACHED => "The size of the distribution list is larger than the availability service is configured to process", self::AVAILABILITY_TRANSIENT_FAILURE => "Availability service request failed with a transient error", self::AVAILABILITY_FAILURE => "Availability service request failed with an error", self::BODY_PART_PREFERENCE_TYPE_NOT_SUPPORTED => "The BodyPartPreference node has an unsupported Type element", self::DEVICE_INFORMATION_REQUIRED => "The required DeviceInformation element is missing in the Provision request", self::INVALID_ACCOUNT_ID => "Invalid AccountId value", self::ACCOUNT_SEND_DISABLED => "The AccountId value specified in the request does not support sending e-mail", self::IRM_FEATURE_DISABLED => "The Information Rights Management feature is disabled", self::IRM_TRANSIENT_ERROR => "Information Rights Management encountered a transient error", self::IRM_PERMANENT_ERROR => "Information Rights Management encountered a permanent error", self::IRM_INVALID_TEMPLATE_ID => "The Template ID value is not valid", self::IRM_OPERATION_NOT_PERMITTED => "Information Rights Management does not support the specified operation", self::NO_PICTURE => "The user does not have a contact photo", self::PICTURE_TO_LARGE => "The contact photo exceeds the size limit set by the MaxSize element", self::PICTURE_LIMIT_REACHED => "The number of contact photos returned exceeds the size limit set by the MaxPictures element", self::BODY_PART_CONVERSATION_TOO_LARGE => "The conversation is too large to compute the body parts", self::MAXIMUM_DEVICES_REACHED => "The user's account has too many device partnerships", - ); + ]; /** * Error messages assigned to class-specific error codes * * @var array */ - protected $_errorMessages = array(); + protected $_errorMessages = []; /** * Constructor */ - function __construct() + public function __construct() { $args = func_get_args(); if (isset($args[1])) { $code = $args[1]; $message = $args[0]; } elseif (is_int($args[0])) { $code = $args[0]; $message = null; } else { $message = $args[0]; } if (empty($code)) { $code = self::SERVER_ERROR; } if (!$message) { if (isset($this->_errorMessages[$code])) { $message = $this->_errorMessages[$code]; } elseif (isset($this->_commonMessages[$code])) { $message = $this->_commonMessages[$code]; } } parent::__construct($message, $code); } } diff --git a/lib/ext/Syncroton/Exception/Status/Autodiscover.php b/lib/ext/Syncroton/Exception/Status/Autodiscover.php index de33bf3..cd6c450 100644 --- a/lib/ext/Syncroton/Exception/Status/Autodiscover.php +++ b/lib/ext/Syncroton/Exception/Status/Autodiscover.php @@ -1,32 +1,32 @@ * @author Aleksander Machniak */ /** * exception for Status element in Autodiscover response * * @package Syncroton * @subpackage Exception */ class Syncroton_Exception_Status_Autodiscover extends Syncroton_Exception_Status { - const PROTOCOL_ERROR = 2; + public const PROTOCOL_ERROR = 2; /** * Error messages assigned to error codes * * @var array */ - protected $_errorMessages = array( + protected $_errorMessages = [ self::PROTOCOL_ERROR => "Protocol error", - ); + ]; } diff --git a/lib/ext/Syncroton/Exception/Status/FolderCreate.php b/lib/ext/Syncroton/Exception/Status/FolderCreate.php index 708e2e1..9c7cf0b 100644 --- a/lib/ext/Syncroton/Exception/Status/FolderCreate.php +++ b/lib/ext/Syncroton/Exception/Status/FolderCreate.php @@ -1,46 +1,46 @@ * @author Aleksander Machniak */ /** * exception for Status element in FolderCreate response * * @package Syncroton * @subpackage Exception */ class Syncroton_Exception_Status_FolderCreate extends Syncroton_Exception_Status { - const FOLDER_EXISTS = 2; - const SPECIAL_FOLDER = 3; - const PARENT_NOT_FOUND = 5; - const FOLDER_SERVER_ERROR = 6; - const INVALID_SYNCKEY = 9; - const INVALID_REQUEST = 10; - const UNKNOWN_ERROR = 11; - const UNKNOWN_CODE = 12; + public const FOLDER_EXISTS = 2; + public const SPECIAL_FOLDER = 3; + public const PARENT_NOT_FOUND = 5; + public const FOLDER_SERVER_ERROR = 6; + public const INVALID_SYNCKEY = 9; + public const INVALID_REQUEST = 10; + public const UNKNOWN_ERROR = 11; + public const UNKNOWN_CODE = 12; /** * Error messages assigned to error codes * * @var array */ - protected $_errorMessages = array( + protected $_errorMessages = [ self::FOLDER_EXISTS => "A folder that has this name already exists", self::SPECIAL_FOLDER => "The specified folder is a special system folder", self::PARENT_NOT_FOUND => "The specified parent folder was not found", self::FOLDER_SERVER_ERROR => "An error occurred on the server", self::INVALID_SYNCKEY => "Synchronization key mismatch or invalid synchronization key", self::INVALID_REQUEST => "Malformed request", self::UNKNOWN_ERROR => "An unknown error occurred", self::UNKNOWN_CODE => "Unusual back-end issue", - ); + ]; } diff --git a/lib/ext/Syncroton/Exception/Status/FolderDelete.php b/lib/ext/Syncroton/Exception/Status/FolderDelete.php index c8a3a4b..b0236ce 100644 --- a/lib/ext/Syncroton/Exception/Status/FolderDelete.php +++ b/lib/ext/Syncroton/Exception/Status/FolderDelete.php @@ -1,42 +1,42 @@ * @author Aleksander Machniak */ /** * exception for Status element in FolderDelete response * * @package Syncroton * @subpackage Exception */ class Syncroton_Exception_Status_FolderDelete extends Syncroton_Exception_Status { - const SPECIAL_FOLDER = 3; - const FOLDER_NOT_FOUND = 4; - const FOLDER_SERVER_ERROR = 6; - const INVALID_SYNCKEY = 9; - const INVALID_REQUEST = 10; - const UNKNOWN_ERROR = 11; + public const SPECIAL_FOLDER = 3; + public const FOLDER_NOT_FOUND = 4; + public const FOLDER_SERVER_ERROR = 6; + public const INVALID_SYNCKEY = 9; + public const INVALID_REQUEST = 10; + public const UNKNOWN_ERROR = 11; /** * Error messages assigned to error codes * * @var array */ - protected $_errorMessages = array( + protected $_errorMessages = [ self::SPECIAL_FOLDER => "The specified folder is a special system folder", self::FOLDER_NOT_FOUND => "The specified folder doesn't exist", self::FOLDER_SERVER_ERROR => "An error occurred on the server", self::INVALID_SYNCKEY => "Synchronization key mismatch or invalid synchronization key", self::INVALID_REQUEST => "Malformed request", self::UNKNOWN_ERROR => "An unknown error occurred", - ); + ]; } diff --git a/lib/ext/Syncroton/Exception/Status/FolderSync.php b/lib/ext/Syncroton/Exception/Status/FolderSync.php index bcd2418..67c1856 100644 --- a/lib/ext/Syncroton/Exception/Status/FolderSync.php +++ b/lib/ext/Syncroton/Exception/Status/FolderSync.php @@ -1,40 +1,40 @@ * @author Aleksander Machniak */ /** * exception for Status element in FolderSync response * * @package Syncroton * @subpackage Exception */ class Syncroton_Exception_Status_FolderSync extends Syncroton_Exception_Status { - const FOLDER_SERVER_ERROR = 6; - const INVALID_SYNCKEY = 9; - const INVALID_REQUEST = 10; - const UNKNOWN_ERROR = 11; - const UNKNOWN_CODE = 12; + public const FOLDER_SERVER_ERROR = 6; + public const INVALID_SYNCKEY = 9; + public const INVALID_REQUEST = 10; + public const UNKNOWN_ERROR = 11; + public const UNKNOWN_CODE = 12; /** * Error messages assigned to error codes * * @var array */ - protected $_errorMessages = array( + protected $_errorMessages = [ self::FOLDER_SERVER_ERROR => "An error occurred on the server", self::INVALID_SYNCKEY => "Synchronization key mismatch or invalid synchronization key", self::INVALID_REQUEST => "Malformed request", self::UNKNOWN_ERROR => "An unknown error occurred", self::UNKNOWN_CODE => "Unusual back-end issue", - ); + ]; } diff --git a/lib/ext/Syncroton/Exception/Status/FolderUpdate.php b/lib/ext/Syncroton/Exception/Status/FolderUpdate.php index 63c629c..9270e0c 100644 --- a/lib/ext/Syncroton/Exception/Status/FolderUpdate.php +++ b/lib/ext/Syncroton/Exception/Status/FolderUpdate.php @@ -1,46 +1,46 @@ * @author Aleksander Machniak */ /** * exception for Status element in FolderUpdate response * * @package Syncroton * @subpackage Exception */ class Syncroton_Exception_Status_FolderUpdate extends Syncroton_Exception_Status { - const FOLDER_EXISTS = 2; - const SPECIAL_FOLDER = 3; - const FOLDER_NOT_FOUND = 4; - const PARENT_NOT_FOUND = 5; - const FOLDER_SERVER_ERROR = 6; - const INVALID_SYNCKEY = 9; - const INVALID_REQUEST = 10; - const UNKNOWN_ERROR = 11; + public const FOLDER_EXISTS = 2; + public const SPECIAL_FOLDER = 3; + public const FOLDER_NOT_FOUND = 4; + public const PARENT_NOT_FOUND = 5; + public const FOLDER_SERVER_ERROR = 6; + public const INVALID_SYNCKEY = 9; + public const INVALID_REQUEST = 10; + public const UNKNOWN_ERROR = 11; /** * Error messages assigned to error codes * * @var array */ - protected $_errorMessages = array( + protected $_errorMessages = [ self::FOLDER_EXISTS => "A folder that has this name already exists or is a special folder", self::SPECIAL_FOLDER => "The specified folder is the Recipient information folder which cannot be updated", self::FOLDER_NOT_FOUND => "The specified folder doesn't exist", self::PARENT_NOT_FOUND => "The specified parent folder was not found", self::FOLDER_SERVER_ERROR => "An error occurred on the server", self::INVALID_SYNCKEY => "Synchronization key mismatch or invalid synchronization key", self::INVALID_REQUEST => "Malformed request", self::UNKNOWN_ERROR => "An unknown error occurred", - ); + ]; } diff --git a/lib/ext/Syncroton/Exception/Status/GetItemEstimate.php b/lib/ext/Syncroton/Exception/Status/GetItemEstimate.php index d4b5685..b6b7325 100644 --- a/lib/ext/Syncroton/Exception/Status/GetItemEstimate.php +++ b/lib/ext/Syncroton/Exception/Status/GetItemEstimate.php @@ -1,36 +1,36 @@ * @author Aleksander Machniak */ /** * Exception for Status element in GetItemEstimate response * * @package Syncroton * @subpackage Exception */ class Syncroton_Exception_Status_GetItemEstimate extends Syncroton_Exception_Status { - const INVALID_COLLECTION = 2; - const SYNCSTATE_NOT_PRIMED = 3; - const INVALID_SYNCKEY = 4; + public const INVALID_COLLECTION = 2; + public const SYNCSTATE_NOT_PRIMED = 3; + public const INVALID_SYNCKEY = 4; /** * Error messages assigned to error codes * * @var array */ - protected $_errorMessages = array( + protected $_errorMessages = [ self::INVALID_COLLECTION => "A collection was invalid or one of the specified collection IDs was invalid", self::SYNCSTATE_NOT_PRIMED => "The synchronization state has not been primed", self::INVALID_SYNCKEY => "The specified synchronization key was invalid", - ); + ]; } diff --git a/lib/ext/Syncroton/Exception/Status/ItemOperations.php b/lib/ext/Syncroton/Exception/Status/ItemOperations.php index 94aa1fe..f074f2f 100644 --- a/lib/ext/Syncroton/Exception/Status/ItemOperations.php +++ b/lib/ext/Syncroton/Exception/Status/ItemOperations.php @@ -1,62 +1,62 @@ * @author Aleksander Machniak */ /** * Exception for Status element in ItemOperations response * * @package Syncroton * @subpackage Exception */ class Syncroton_Exception_Status_ItemOperations extends Syncroton_Exception_Status { - const PROTOCOL_ERROR = 2; - const ITEM_SERVER_ERROR = 3; - const DOCLIB_INVALID_URI = 4; - const DOCLIB_ACCESS_DENIED = 5; - const DOCLIB_NOT_FOUND = 6; - const DOCLIB_CONN_FAILED = 7; - const INVALID_BYTE_RANGE = 8; - const UNKNOWN_STORE = 9; - const FILE_EMPTY = 10; - const DATA_TOO_LARGE = 11; - const FILE_IO_ERROR = 12; - const CONVERSION_ERROR = 14; - const INVALID_ATTACHMENT = 15; - const RESOURCE_ACCESS_DENIED = 16; - const PARTIAL_SUCCESS = 17; - const CREDENTIALS_REQUIRED = 18; + public const PROTOCOL_ERROR = 2; + public const ITEM_SERVER_ERROR = 3; + public const DOCLIB_INVALID_URI = 4; + public const DOCLIB_ACCESS_DENIED = 5; + public const DOCLIB_NOT_FOUND = 6; + public const DOCLIB_CONN_FAILED = 7; + public const INVALID_BYTE_RANGE = 8; + public const UNKNOWN_STORE = 9; + public const FILE_EMPTY = 10; + public const DATA_TOO_LARGE = 11; + public const FILE_IO_ERROR = 12; + public const CONVERSION_ERROR = 14; + public const INVALID_ATTACHMENT = 15; + public const RESOURCE_ACCESS_DENIED = 16; + public const PARTIAL_SUCCESS = 17; + public const CREDENTIALS_REQUIRED = 18; /** * Error messages assigned to error codes * * @var array */ - protected $_errorMessages = array( + protected $_errorMessages = [ self::PROTOCOL_ERROR => "Protocol error - protocol violation/XML validation error", self::ITEM_SERVER_ERROR => "Server error", self::DOCLIB_INVALID_URI => "Document library access - The specified URI is bad", self::DOCLIB_ACCESS_DENIED => "Document library - Access denied", self::DOCLIB_NOT_FOUND => "Document library - The object was not found or access denied", self::DOCLIB_CONN_FAILED => "Document library - Failed to connect to the server", self::INVALID_BYTE_RANGE => "The byte-range is invalid or too large", self::UNKNOWN_STORE => "The store is unknown or unsupported", self::FILE_EMPTY => "The file is empty", self::DATA_TOO_LARGE => "The requested data size is too large", self::FILE_IO_ERROR => "Failed to download file because of input/output (I/O) failure", self::CONVERSION_ERROR => "Mailbox fetch provider - The item failed conversion", self::INVALID_ATTACHMENT => "Attachment fetch provider - Attachment or attachment ID is invalid", self::RESOURCE_ACCESS_DENIED => "Access to the resource is denied", self::PARTIAL_SUCCESS => "Partial success; the command completed partially", self::CREDENTIALS_REQUIRED => "Credentials required", - ); + ]; } diff --git a/lib/ext/Syncroton/Exception/Status/MeetingResponse.php b/lib/ext/Syncroton/Exception/Status/MeetingResponse.php index 34eb6e0..c12e97b 100644 --- a/lib/ext/Syncroton/Exception/Status/MeetingResponse.php +++ b/lib/ext/Syncroton/Exception/Status/MeetingResponse.php @@ -1,36 +1,36 @@ * @author Aleksander Machniak */ /** * exception for Status element in MeetingResponse response * * @package Syncroton * @subpackage Exception */ class Syncroton_Exception_Status_MeetingResponse extends Syncroton_Exception_Status { - const INVALID_REQUEST = 2; - const MEETING_SERVER_ERROR = 3; - const MEETING_ERROR = 4; + public const INVALID_REQUEST = 2; + public const MEETING_SERVER_ERROR = 3; + public const MEETING_ERROR = 4; /** * Error messages assigned to error codes * * @var array */ - protected $_errorMessages = array( + protected $_errorMessages = [ self::INVALID_REQUEST => "Invalid meeting request", self::MEETING_SERVER_ERROR => "An error occurred on the server mailbox", self::MEETING_ERROR => "An error occurred on the server", - ); + ]; } diff --git a/lib/ext/Syncroton/Exception/Status/MoveItems.php b/lib/ext/Syncroton/Exception/Status/MoveItems.php index c03efea..24ca962 100644 --- a/lib/ext/Syncroton/Exception/Status/MoveItems.php +++ b/lib/ext/Syncroton/Exception/Status/MoveItems.php @@ -1,40 +1,40 @@ * @author Aleksander Machniak */ /** * exception for Status element in MoveItems response * * @package Syncroton * @subpackage Exception */ class Syncroton_Exception_Status_MoveItems extends Syncroton_Exception_Status { - const INVALID_SOURCE = 1; - const INVALID_DESTINATION = 2; - const SAME_FOLDER = 4; - const ITEM_EXISTS_OR_LOCKED = 5; - const FOLDER_LOCKED = 7; + public const INVALID_SOURCE = 1; + public const INVALID_DESTINATION = 2; + public const SAME_FOLDER = 4; + public const ITEM_EXISTS_OR_LOCKED = 5; + public const FOLDER_LOCKED = 7; /** * Error messages assigned to error codes * * @var array */ - protected $_errorMessages = array( + protected $_errorMessages = [ self::INVALID_SOURCE => "Invalid source collection ID or item ID", self::INVALID_DESTINATION => "Invalid destination collection ID", self::SAME_FOLDER => "Source and destination collection IDs are the same", self::ITEM_EXISTS_OR_LOCKED => "The item cannot be moved to more than one item at a time, or the source or destination item was locked", self::FOLDER_LOCKED => "Source or destination item was locked", - ); + ]; } diff --git a/lib/ext/Syncroton/Exception/Status/Settings.php b/lib/ext/Syncroton/Exception/Status/Settings.php index 898d569..981e0f6 100644 --- a/lib/ext/Syncroton/Exception/Status/Settings.php +++ b/lib/ext/Syncroton/Exception/Status/Settings.php @@ -1,42 +1,42 @@ * @author Aleksander Machniak */ /** * Exception for Status element in Settings response * * @package Syncroton * @subpackage Exception */ class Syncroton_Exception_Status_Settings extends Syncroton_Exception_Status { - const PROTOCOL_ERROR = 2; - const ACCESS_DENIED = 3; - const SERVICE_UNAVAILABLE = 4; - const INVALID_ARGUMENTS = 5; - const CONFLICTING_ARGUMENTS = 6; - const DENIED_BY_POLICY = 7; + public const PROTOCOL_ERROR = 2; + public const ACCESS_DENIED = 3; + public const SERVICE_UNAVAILABLE = 4; + public const INVALID_ARGUMENTS = 5; + public const CONFLICTING_ARGUMENTS = 6; + public const DENIED_BY_POLICY = 7; /** * Error messages assigned to error codes * * @var array */ - protected $_errorMessages = array( + protected $_errorMessages = [ self::PROTOCOL_ERROR => "Protocol error", self::ACCESS_DENIED => "Access denied", self::SERVICE_UNAVAILABLE => "Server unavailable", self::INVALID_ARGUMENTS => "Invalid arguments", self::CONFLICTING_ARGUMENTS => "Conflicting arguments", self::DENIED_BY_POLICY => "Denied by policy. Disabled by administrator", - ); + ]; } diff --git a/lib/ext/Syncroton/Exception/Status/Sync.php b/lib/ext/Syncroton/Exception/Status/Sync.php index 12998c4..f49caec 100644 --- a/lib/ext/Syncroton/Exception/Status/Sync.php +++ b/lib/ext/Syncroton/Exception/Status/Sync.php @@ -1,54 +1,54 @@ * @author Aleksander Machniak */ /** * exception for Status element in Sync response * * @package Syncroton * @subpackage Exception */ class Syncroton_Exception_Status_Sync extends Syncroton_Exception_Status { - const INVALID_SYNCKEY = 3; - const PROTOCOL_ERROR = 4; - const SYNC_SERVER_ERROR = 5; - const INVALID_ITEM = 6; - const OBJECT_CONFLICT = 7; - const OBJECT_NOT_FOUND = 8; - const SYNC_ERROR = 9; - const HIERARCHY_CHANGED = 12; - const INCOMPLETE_REQUEST = 13; - const INVALID_INTERVAL = 14; - const INVALID_REQUEST = 15; - const SYNC_RETRY = 16; + public const INVALID_SYNCKEY = 3; + public const PROTOCOL_ERROR = 4; + public const SYNC_SERVER_ERROR = 5; + public const INVALID_ITEM = 6; + public const OBJECT_CONFLICT = 7; + public const OBJECT_NOT_FOUND = 8; + public const SYNC_ERROR = 9; + public const HIERARCHY_CHANGED = 12; + public const INCOMPLETE_REQUEST = 13; + public const INVALID_INTERVAL = 14; + public const INVALID_REQUEST = 15; + public const SYNC_RETRY = 16; /** * Error messages assigned to error codes * * @var array */ - protected $_errorMessages = array( + protected $_errorMessages = [ self::INVALID_SYNCKEY => "Invalid synchronization key", self::PROTOCOL_ERROR => "Protocol error", self::SYNC_SERVER_ERROR => "Server error", self::INVALID_ITEM => "Error in client/server conversion", self::OBJECT_CONFLICT => "Conflict matching the client and server object", self::OBJECT_NOT_FOUND => "Object not found", self::SYNC_ERROR => "The Sync command cannot be completed", self::HIERARCHY_CHANGED => "The folder hierarchy has changed", self::INCOMPLETE_REQUEST => "The Sync command request is not complete", self::INVALID_INTERVAL => "Invalid Wait or HeartbeatInterval value", self::INVALID_REQUEST => "Too many collections are included in the Sync request", self::SYNC_RETRY => "Something on the server caused a retriable error", - ); + ]; } diff --git a/lib/ext/Syncroton/Model/AEntry.php b/lib/ext/Syncroton/Model/AEntry.php index bf79769..77e8d19 100644 --- a/lib/ext/Syncroton/Model/AEntry.php +++ b/lib/ext/Syncroton/Model/AEntry.php @@ -1,106 +1,106 @@ */ /** * abstract class to handle ActiveSync entry * * @package Syncroton * @subpackage Model */ abstract class Syncroton_Model_AEntry implements Syncroton_Model_IEntry, IteratorAggregate, Countable { - protected $_elements = array(); - + protected $_elements = []; + protected $_isDirty; - + /** * (non-PHPdoc) * @see Syncroton_Model_IEntry::__construct() */ public function __construct($properties = null) { if (is_array($properties)) { $this->setFromArray($properties); } - + $this->_isDirty = false; } - - + + /** * (non-PHPdoc) * @see Countable::count() - */ + */ #[\ReturnTypeWillChange] public function count() { return count($this->_elements); } - + /** * (non-PHPdoc) * @see IteratorAggregate::getIterator() */ #[\ReturnTypeWillChange] - public function getIterator() - { - return new ArrayIterator($this->_elements); + public function getIterator() + { + return new ArrayIterator($this->_elements); } - + /** * (non-PHPdoc) * @see Syncroton_Model_IEntry::isDirty() */ public function isDirty() { return $this->_isDirty; } - + /** * (non-PHPdoc) * @see Syncroton_Model_IEntry::setFromArray() */ public function setFromArray(array $properties) { foreach($properties as $key => $value) { try { $this->$key = $value; //echo __LINE__ . PHP_EOL; } catch (InvalidArgumentException $iae) { //ignore invalid properties //echo __LINE__ . PHP_EOL; echo $iae->getMessage(); echo $iae->getTraceAsString(); } } } - - public function &__get($name) - { - return $this->_elements[$name]; - } - - public function __set($name, $value) + + public function &__get($name) + { + return $this->_elements[$name]; + } + + public function __set($name, $value) { if (!array_key_exists($name, $this->_elements) || $this->_elements[$name] != $value) { $this->_elements[$name] = $value; - + $this->_isDirty = true; - } - } - - public function __isset($name) - { - return isset($this->_elements[$name]); - } - - public function __unset($name) - { - unset($this->_elements[$name]); + } + } + + public function __isset($name) + { + return isset($this->_elements[$name]); + } + + public function __unset($name) + { + unset($this->_elements[$name]); } -} \ No newline at end of file +} diff --git a/lib/ext/Syncroton/Model/AXMLEntry.php b/lib/ext/Syncroton/Model/AXMLEntry.php index c23aa02..f204dce 100644 --- a/lib/ext/Syncroton/Model/AXMLEntry.php +++ b/lib/ext/Syncroton/Model/AXMLEntry.php @@ -1,328 +1,328 @@ */ /** * abstract class to handle ActiveSync entry * * @package Syncroton * @subpackage Model */ abstract class Syncroton_Model_AXMLEntry extends Syncroton_Model_AEntry implements Syncroton_Model_IXMLEntry { protected $_xmlBaseElement; - - protected $_properties = array(); - + + protected $_properties = []; + protected $_dateTimeFormat = "Y-m-d\TH:i:s.000\Z"; - + /** * (non-PHPdoc) * @see Syncroton_Model_IEntry::__construct() */ public function __construct($properties = null) { if ($properties instanceof SimpleXMLElement) { $this->setFromSimpleXMLElement($properties); } elseif (is_array($properties)) { $this->setFromArray($properties); } - + $this->_isDirty = false; } - + /** * (non-PHPdoc) * @see Syncroton_Model_IEntry::appendXML() */ public function appendXML(DOMElement $domParrent, Syncroton_Model_IDevice $device) { $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; - } - - $elementVersion = isset($elementProperties['supportedSince']) ? $elementProperties['supportedSince'] : '12.0'; - + + [$nameSpace, $elementProperties] = $this->_getElementProperties($elementName); + + if ($nameSpace == 'Internal') { + continue; + } + + $elementVersion = $elementProperties['supportedSince'] ?? '12.0'; + if (version_compare($device->acsversion, $elementVersion, '<')) { continue; } - + $nameSpace = 'uri:' . $nameSpace; - + if (isset($elementProperties['childElement'])) { $element = $domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementName)); foreach($value as $subValue) { $subElement = $domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementProperties['childElement'])); $this->_appendXMLElement($device, $subElement, $elementProperties, $subValue); $element->appendChild($subElement); } $domParrent->appendChild($element); - } else if ($elementProperties['type'] == 'container' && !empty($elementProperties['multiple'])) { + } elseif ($elementProperties['type'] == 'container' && !empty($elementProperties['multiple'])) { foreach ($value as $element) { $container = $domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementName)); $element->appendXML($container, $device); $domParrent->appendChild($container); } - } else if ($elementProperties['type'] == 'none') { + } elseif ($elementProperties['type'] == 'none') { if ($value) { $element = $domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementName)); $domParrent->appendChild($element); } } else { $element = $domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementName)); $this->_appendXMLElement($device, $element, $elementProperties, $value); $domParrent->appendChild($element); } } } - + /** * (non-PHPdoc) * @see Syncroton_Model_IEntry::getProperties() */ public function getProperties($selectedNamespace = null) { - $properties = array(); - + $properties = []; + foreach($this->_properties as $namespace => $namespaceProperties) { if ($selectedNamespace !== null && $namespace != $selectedNamespace) { continue; } - $properties = array_merge($properties, array_keys($namespaceProperties)); + $properties = array_merge($properties, array_keys($namespaceProperties)); } - + return $properties; - + } - - /** - * set properties from SimpleXMLElement object - * + + /** + * set properties from SimpleXMLElement object + * * @param SimpleXMLElement $properties - * @throws InvalidArgumentException - */ - public function setFromSimpleXMLElement(SimpleXMLElement $properties) - { + * @throws InvalidArgumentException + */ + public function setFromSimpleXMLElement(SimpleXMLElement $properties) + { if (!in_array($properties->getName(), (array) $this->_xmlBaseElement)) { - throw new InvalidArgumentException('Unexpected element name: ' . $properties->getName()); - } - + throw new InvalidArgumentException('Unexpected element name: ' . $properties->getName()); + } + foreach (array_keys($this->_properties) as $namespace) { if ($namespace == 'Internal') { continue; } - - $this->_parseNamespace($namespace, $properties); - } - - return; + + $this->_parseNamespace($namespace, $properties); + } + + return; } /** * add needed xml namespaces to DomDocument - * + * * @param DOMElement $domParent */ protected function _addXMLNamespaces(DOMElement $domParent) { foreach ($this->_properties as $namespace => $namespaceProperties) { // don't add default namespace again - if ($domParent->ownerDocument->documentElement->namespaceURI != 'uri:'.$namespace) { - $domParent->ownerDocument->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:'.$namespace, 'uri:'.$namespace); + if ($domParent->ownerDocument->documentElement->namespaceURI != 'uri:' . $namespace) { + $domParent->ownerDocument->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $namespace, 'uri:' . $namespace); } } } protected function _appendXMLElement(Syncroton_Model_IDevice $device, DOMElement $element, $elementProperties, $value) { - if ($value instanceof Syncroton_Model_IEntry) { + if ($value instanceof Syncroton_Model_IEntry) { $value->appendXML($element, $device); // @phpstan-ignore-line - } else { - if ($value instanceof DateTime) { + } else { + if ($value instanceof DateTime) { $value = $value->format($this->_dateTimeFormat); - - } elseif (isset($elementProperties['encoding']) && $elementProperties['encoding'] == 'base64') { - if (is_resource($value)) { + + } elseif (isset($elementProperties['encoding']) && $elementProperties['encoding'] == 'base64') { + if (is_resource($value)) { rewind($value); - $value = stream_get_contents($value); - } - $value = base64_encode($value); - } - + $value = stream_get_contents($value); + } + $value = base64_encode($value); + } + if ($elementProperties['type'] == 'byteArray') { $element->setAttributeNS('uri:Syncroton', 'Syncroton:encoding', 'opaque'); // encode to base64; the wbxml encoder will base64_decode it again // this way we can also transport data, which would break the xmlparser otherwise $element->appendChild($element->ownerDocument->createCDATASection(base64_encode($value))); } else { // strip off any non printable control characters if (!ctype_print((string)$value)) { $value = $this->_removeControlChars($value); } - + $element->appendChild($element->ownerDocument->createTextNode($this->_enforceUTF8($value))); - } - } + } + } } - + /** * remove control chars from a string which are not allowed in XML values * * @param string $dirty An input string * @return string Cleaned up string */ protected function _removeControlChars($dirty) { // Replace non-character UTF-8 sequences that cause XML Parser to fail // https://git.kolab.org/T1311 - $dirty = str_replace(array("\xEF\xBF\xBE", "\xEF\xBF\xBF"), '', $dirty); + $dirty = str_replace(["\xEF\xBF\xBE", "\xEF\xBF\xBF"], '', $dirty); // Replace ASCII control-characters return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', '', $dirty); } - + /** * enforce >valid< utf-8 encoding - * + * * @param string $dirty the string with maybe invalid utf-8 data * @return string string with valid utf-8 */ protected function _enforceUTF8($dirty) { if (function_exists('iconv')) { if (($clean = @iconv('UTF-8', 'UTF-8//IGNORE', $dirty)) !== false) { return $clean; } } - + if (function_exists('mb_convert_encoding')) { if (($clean = mb_convert_encoding($dirty, 'UTF-8', 'UTF-8')) !== false) { return $clean; } } - + return $dirty; } - + /** - * + * * @param string $element * @throws InvalidArgumentException * @return array */ - protected function _getElementProperties($element) + protected function _getElementProperties($element) { 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 " . get_class($this)); + if (array_key_exists($element, $namespaceProperties)) { + return [$namespace, $namespaceProperties[$element]]; + } + } + + throw new InvalidArgumentException("$element is no valid property of " . get_class($this)); } - + protected function _parseNamespace($nameSpace, SimpleXMLElement $properties) { - // fetch data from Contacts namespace - $children = $properties->children("uri:$nameSpace"); - + // fetch data from Contacts namespace + $children = $properties->children("uri:$nameSpace"); + foreach ($children as $elementName => $xmlElement) { $elementName = lcfirst($elementName); - + if (!isset($this->_properties[$nameSpace][$elementName])) { continue; } - - list (, $elementProperties) = $this->_getElementProperties($elementName); - + + [, $elementProperties] = $this->_getElementProperties($elementName); + switch ($elementProperties['type']) { case 'container': if (!empty($elementProperties['multiple'])) { $property = (array) $this->$elementName; - + if (isset($elementProperties['class'])) { $property[] = new $elementProperties['class']($xmlElement); } else { $property[] = (string) $xmlElement; } - } else if (isset($elementProperties['childElement'])) { - $property = array(); - + } elseif (isset($elementProperties['childElement'])) { + $property = []; + $childElement = ucfirst($elementProperties['childElement']); - + foreach ($xmlElement->$childElement as $subXmlElement) { if (isset($elementProperties['class'])) { $property[] = new $elementProperties['class']($subXmlElement); } else { $property[] = (string) $subXmlElement; } } } else { - $subClassName = isset($elementProperties['class']) ? $elementProperties['class'] : get_class($this) . ucfirst($elementName); - - $property = new $subClassName($xmlElement); + $subClassName = $elementProperties['class'] ?? get_class($this) . ucfirst($elementName); + + $property = new $subClassName($xmlElement); } - + break; - + case 'datetime': $property = new DateTime((string) $xmlElement, new DateTimeZone('UTC')); break; case 'number': $property = (int) $xmlElement; break; default: $property = (string) $xmlElement; break; } if (isset($elementProperties['encoding']) && $elementProperties['encoding'] == 'base64') { $property = base64_decode($property); } - + $this->$elementName = $property; - } + } + } + + public function &__get($name) + { + $this->_getElementProperties($name); + + return $this->_elements[$name]; } - - public function &__get($name) - { - $this->_getElementProperties($name); - - return $this->_elements[$name]; - } - - public function __set($name, $value) - { - list ($nameSpace, $properties) = $this->_getElementProperties($name); - - if ($properties['type'] == 'datetime' && !$value instanceof DateTime) { - throw new InvalidArgumentException("value for $name must be an instance of DateTime"); - } - - if (!array_key_exists($name, $this->_elements) || $this->_elements[$name] != $value) { + + public function __set($name, $value) + { + [$nameSpace, $properties] = $this->_getElementProperties($name); + + if ($properties['type'] == 'datetime' && !$value instanceof DateTime) { + throw new InvalidArgumentException("value for $name must be an instance of DateTime"); + } + + if (!array_key_exists($name, $this->_elements) || $this->_elements[$name] != $value) { $this->_elements[$name] = $value; - + $this->_isDirty = true; - } - } -} \ No newline at end of file + } + } +} diff --git a/lib/ext/Syncroton/Model/Account.php b/lib/ext/Syncroton/Model/Account.php index 11b6453..eeada9b 100644 --- a/lib/ext/Syncroton/Model/Account.php +++ b/lib/ext/Syncroton/Model/Account.php @@ -1,76 +1,76 @@ */ /** * class to handle (Settings/UserInformation/Get/Accounts/) Account element * * @package Syncroton * @subpackage Model * @property string $accountId * @property string $accountName * @property string $userDisplayName * @property bool $sendDisabled * @property string $primaryAddress * @property array $addresses */ class Syncroton_Model_Account extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'Account'; - protected $_properties = array( - 'Settings' => array( - 'accountId' => array('type' => 'string'), - 'accountName' => array('type' => 'string'), - 'userDisplayName' => array('type' => 'string'), - 'sendDisabled' => array('type' => 'number'), + protected $_properties = [ + 'Settings' => [ + 'accountId' => ['type' => 'string'], + 'accountName' => ['type' => 'string'], + 'userDisplayName' => ['type' => 'string'], + 'sendDisabled' => ['type' => 'number'], // 'emailAddresses' => array('type' => 'container'), - ), - 'Internal' => array( - 'primaryAddress' => array('type' => 'string'), - 'addresses' => array('type' => 'array'), - ), - ); + ], + 'Internal' => [ + 'primaryAddress' => ['type' => 'string'], + 'addresses' => ['type' => 'array'], + ], + ]; /** * (non-PHPdoc) * @see Syncroton_Model_AXMLEntry::appendXML() */ public function appendXML(DOMElement $_domParent, Syncroton_Model_IDevice $device) { parent::appendXML($_domParent, $device); $nameSpace = 'uri:Settings'; $document = $_domParent->ownerDocument; // handle EmailAddresses element $list = $document->createElementNS($nameSpace, 'EmailAddresses'); if (!empty($this->_elements['primaryAddress'])) { $element = $document->createElementNS($nameSpace, 'PrimarySmtpAddress', $this->_elements['primaryAddress']); $list->appendChild($element); } foreach ((array)$this->_elements['addresses'] as $address) { // skip empty values if (empty($address)) { continue; } $element = $document->createElementNS($nameSpace, 'SMTPAddress', $address); $list->appendChild($element); } if ($list->hasChildNodes()) { $_domParent->appendChild($list); } } } diff --git a/lib/ext/Syncroton/Model/Contact.php b/lib/ext/Syncroton/Model/Contact.php index 8fb77d4..dc586cc 100644 --- a/lib/ext/Syncroton/Model/Contact.php +++ b/lib/ext/Syncroton/Model/Contact.php @@ -1,104 +1,104 @@ */ /** * class to handle ActiveSync contact * * @package Syncroton * @subpackage Model * @property string $alias * @property DateTime $anniversary * @property string $assistantName * @property string $assistantPhoneNumber * @property DateTime $birthday * @property string $business2PhoneNumber * @property string $businessAddressCity * @property Syncroton_Model_EmailBody $body * @property string $firstName * @property string $lastName */ class Syncroton_Model_Contact extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'ApplicationData'; - - protected $_properties = array( - 'AirSyncBase' => array( - 'body' => array('type' => 'container', 'class' => 'Syncroton_Model_EmailBody') - ), - 'Contacts' => array( - 'alias' => array('type' => 'string', 'supportedSince' => '14.0'), - 'anniversary' => array('type' => 'datetime'), - 'assistantName' => array('type' => 'string'), - 'assistantPhoneNumber' => array('type' => 'string'), - 'birthday' => array('type' => 'datetime'), - 'business2PhoneNumber' => array('type' => 'string'), - 'businessAddressCity' => array('type' => 'string'), - 'businessAddressCountry' => array('type' => 'string'), - 'businessAddressPostalCode' => array('type' => 'string'), - 'businessAddressState' => array('type' => 'string'), - 'businessAddressStreet' => array('type' => 'string'), - 'businessFaxNumber' => array('type' => 'string'), - 'businessPhoneNumber' => array('type' => 'string'), - 'carPhoneNumber' => array('type' => 'string'), - 'categories' => array('type' => 'container', 'childElement' => 'category'), - 'children' => array('type' => 'container', 'childElement' => 'child'), - 'companyName' => array('type' => 'string'), - 'department' => array('type' => 'string'), - 'email1Address' => array('type' => 'string'), - 'email2Address' => array('type' => 'string'), - 'email3Address' => array('type' => 'string'), - 'fileAs' => array('type' => 'string'), - 'firstName' => array('type' => 'string'), - 'home2PhoneNumber' => array('type' => 'string'), - 'homeAddressCity' => array('type' => 'string'), - 'homeAddressCountry' => array('type' => 'string'), - 'homeAddressPostalCode' => array('type' => 'string'), - 'homeAddressState' => array('type' => 'string'), - 'homeAddressStreet' => array('type' => 'string'), - 'homeFaxNumber' => array('type' => 'string'), - 'homePhoneNumber' => array('type' => 'string'), - 'jobTitle' => array('type' => 'string'), - 'lastName' => array('type' => 'string'), - 'middleName' => array('type' => 'string'), - 'mobilePhoneNumber' => array('type' => 'string'), - 'officeLocation' => array('type' => 'string'), - 'otherAddressCity' => array('type' => 'string'), - 'otherAddressCountry' => array('type' => 'string'), - 'otherAddressPostalCode' => array('type' => 'string'), - 'otherAddressState' => array('type' => 'string'), - 'otherAddressStreet' => array('type' => 'string'), - 'pagerNumber' => array('type' => 'string'), - 'picture' => array('type' => 'string', 'encoding' => 'base64'), - 'padioPhoneNumber' => array('type' => 'string'), - 'rtf' => array('type' => 'string'), - 'spouse' => array('type' => 'string'), - 'suffix' => array('type' => 'string'), - 'title' => array('type' => 'string'), - 'webPage' => array('type' => 'string'), - 'weightedRank' => array('type' => 'string', 'supportedSince' => '14.0'), - 'yomiCompanyName' => array('type' => 'string'), - 'yomiFirstName' => array('type' => 'string'), - 'yomiLastName' => array('type' => 'string'), - ), - 'Contacts2' => array( - 'accountName' => array('type' => 'string'), - 'companyMainPhone' => array('type' => 'string'), - 'customerId' => array('type' => 'string'), - 'governmentId' => array('type' => 'string'), - 'iMAddress' => array('type' => 'string'), - 'iMAddress2' => array('type' => 'string'), - 'iMAddress3' => array('type' => 'string'), - 'managerName' => array('type' => 'string'), - 'mMS' => array('type' => 'string'), - 'nickName' => array('type' => 'string'), - ) - ); -} \ No newline at end of file + + protected $_properties = [ + 'AirSyncBase' => [ + 'body' => ['type' => 'container', 'class' => 'Syncroton_Model_EmailBody'], + ], + 'Contacts' => [ + 'alias' => ['type' => 'string', 'supportedSince' => '14.0'], + 'anniversary' => ['type' => 'datetime'], + 'assistantName' => ['type' => 'string'], + 'assistantPhoneNumber' => ['type' => 'string'], + 'birthday' => ['type' => 'datetime'], + 'business2PhoneNumber' => ['type' => 'string'], + 'businessAddressCity' => ['type' => 'string'], + 'businessAddressCountry' => ['type' => 'string'], + 'businessAddressPostalCode' => ['type' => 'string'], + 'businessAddressState' => ['type' => 'string'], + 'businessAddressStreet' => ['type' => 'string'], + 'businessFaxNumber' => ['type' => 'string'], + 'businessPhoneNumber' => ['type' => 'string'], + 'carPhoneNumber' => ['type' => 'string'], + 'categories' => ['type' => 'container', 'childElement' => 'category'], + 'children' => ['type' => 'container', 'childElement' => 'child'], + 'companyName' => ['type' => 'string'], + 'department' => ['type' => 'string'], + 'email1Address' => ['type' => 'string'], + 'email2Address' => ['type' => 'string'], + 'email3Address' => ['type' => 'string'], + 'fileAs' => ['type' => 'string'], + 'firstName' => ['type' => 'string'], + 'home2PhoneNumber' => ['type' => 'string'], + 'homeAddressCity' => ['type' => 'string'], + 'homeAddressCountry' => ['type' => 'string'], + 'homeAddressPostalCode' => ['type' => 'string'], + 'homeAddressState' => ['type' => 'string'], + 'homeAddressStreet' => ['type' => 'string'], + 'homeFaxNumber' => ['type' => 'string'], + 'homePhoneNumber' => ['type' => 'string'], + 'jobTitle' => ['type' => 'string'], + 'lastName' => ['type' => 'string'], + 'middleName' => ['type' => 'string'], + 'mobilePhoneNumber' => ['type' => 'string'], + 'officeLocation' => ['type' => 'string'], + 'otherAddressCity' => ['type' => 'string'], + 'otherAddressCountry' => ['type' => 'string'], + 'otherAddressPostalCode' => ['type' => 'string'], + 'otherAddressState' => ['type' => 'string'], + 'otherAddressStreet' => ['type' => 'string'], + 'pagerNumber' => ['type' => 'string'], + 'picture' => ['type' => 'string', 'encoding' => 'base64'], + 'padioPhoneNumber' => ['type' => 'string'], + 'rtf' => ['type' => 'string'], + 'spouse' => ['type' => 'string'], + 'suffix' => ['type' => 'string'], + 'title' => ['type' => 'string'], + 'webPage' => ['type' => 'string'], + 'weightedRank' => ['type' => 'string', 'supportedSince' => '14.0'], + 'yomiCompanyName' => ['type' => 'string'], + 'yomiFirstName' => ['type' => 'string'], + 'yomiLastName' => ['type' => 'string'], + ], + 'Contacts2' => [ + 'accountName' => ['type' => 'string'], + 'companyMainPhone' => ['type' => 'string'], + 'customerId' => ['type' => 'string'], + 'governmentId' => ['type' => 'string'], + 'iMAddress' => ['type' => 'string'], + 'iMAddress2' => ['type' => 'string'], + 'iMAddress3' => ['type' => 'string'], + 'managerName' => ['type' => 'string'], + 'mMS' => ['type' => 'string'], + 'nickName' => ['type' => 'string'], + ], + ]; +} diff --git a/lib/ext/Syncroton/Model/Content.php b/lib/ext/Syncroton/Model/Content.php index 5df9826..4051971 100644 --- a/lib/ext/Syncroton/Model/Content.php +++ b/lib/ext/Syncroton/Model/Content.php @@ -1,21 +1,20 @@ */ /** * model for content sent to device * * @package Syncroton * @subpackage Model */ class Syncroton_Model_Content extends Syncroton_Model_AEntry implements Syncroton_Model_IContent { } - diff --git a/lib/ext/Syncroton/Model/Device.php b/lib/ext/Syncroton/Model/Device.php index b7b062d..1a207f4 100644 --- a/lib/ext/Syncroton/Model/Device.php +++ b/lib/ext/Syncroton/Model/Device.php @@ -1,52 +1,52 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Model */ class Syncroton_Model_Device extends Syncroton_Model_AEntry implements Syncroton_Model_IDevice { - const TYPE_IPHONE = 'iphone'; - const TYPE_WEBOS = 'webos'; - const TYPE_ANDROID = 'android'; - const TYPE_ANDROID_40 = 'android40'; - const TYPE_SMASUNGGALAXYS2 = 'samsunggti9100'; // Samsung Galaxy S-3 - const TYPE_BLACKBERRY = 'blackberry'; + public const TYPE_IPHONE = 'iphone'; + public const TYPE_WEBOS = 'webos'; + public const TYPE_ANDROID = 'android'; + public const TYPE_ANDROID_40 = 'android40'; + public const TYPE_SMASUNGGALAXYS2 = 'samsunggti9100'; // Samsung Galaxy S-3 + public const TYPE_BLACKBERRY = 'blackberry'; /** * Returns major firmware version of this device * * @return int|string */ public function getMajorVersion() { switch (strtolower($this->devicetype)) { case Syncroton_Model_Device::TYPE_BLACKBERRY: if (preg_match('/(.+)\/(.+)/', $this->useragent, $matches)) { - list(, $name, $version) = $matches; + [, $name, $version] = $matches; return $version; } break; case Syncroton_Model_Device::TYPE_IPHONE: if (preg_match('/(.+)\/(\d+)\.(\d+)/', $this->useragent, $matches)) { - list(, $name, $majorVersion, $minorVersion) = $matches; + [, $name, $majorVersion, $minorVersion] = $matches; return $majorVersion; } break; } return 0; } } diff --git a/lib/ext/Syncroton/Model/DeviceInformation.php b/lib/ext/Syncroton/Model/DeviceInformation.php index 7eb040d..c073778 100644 --- a/lib/ext/Syncroton/Model/DeviceInformation.php +++ b/lib/ext/Syncroton/Model/DeviceInformation.php @@ -1,42 +1,42 @@ */ /** * class to handle ActiveSync device information * * @package Syncroton * @subpackage Model * @property string $friendlyName * @property string $iMEI * @property string $mobileOperator * @property string $model * @property string $oS * @property string $oSLanguage * @property string $phoneNumber */ class Syncroton_Model_DeviceInformation extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'Set'; - - protected $_properties = array( - 'Settings' => array( - 'enableOutboundSMS' => array('type' => 'number'), - 'friendlyName' => array('type' => 'string'), - 'iMEI' => array('type' => 'string'), - 'mobileOperator' => array('type' => 'string'), - 'model' => array('type' => 'string'), - 'oS' => array('type' => 'string'), - 'oSLanguage' => array('type' => 'string'), - 'phoneNumber' => array('type' => 'string') - ), - ); -} \ No newline at end of file + + protected $_properties = [ + 'Settings' => [ + 'enableOutboundSMS' => ['type' => 'number'], + 'friendlyName' => ['type' => 'string'], + 'iMEI' => ['type' => 'string'], + 'mobileOperator' => ['type' => 'string'], + 'model' => ['type' => 'string'], + 'oS' => ['type' => 'string'], + 'oSLanguage' => ['type' => 'string'], + 'phoneNumber' => ['type' => 'string'], + ], + ]; +} diff --git a/lib/ext/Syncroton/Model/Email.php b/lib/ext/Syncroton/Model/Email.php index 3e980e7..96f15b7 100644 --- a/lib/ext/Syncroton/Model/Email.php +++ b/lib/ext/Syncroton/Model/Email.php @@ -1,90 +1,90 @@ */ /** * class to handle ActiveSync email * * @package Syncroton * @subpackage Model * @property array $attachments * @property string $contentType * @property array $flag * @property Syncroton_Model_EmailBody $body * @property array $cc * @property array $to * @property int $lastVerbExecuted * @property DateTime $lastVerbExecutionTime * @property int $read */ class Syncroton_Model_Email extends Syncroton_Model_AXMLEntry { - const LASTVERB_UNKNOWN = 0; - const LASTVERB_REPLYTOSENDER = 1; - const LASTVERB_REPLYTOALL = 2; - const LASTVERB_FORWARD = 3; - + public const LASTVERB_UNKNOWN = 0; + public const LASTVERB_REPLYTOSENDER = 1; + public const LASTVERB_REPLYTOALL = 2; + public const LASTVERB_FORWARD = 3; + protected $_xmlBaseElement = 'ApplicationData'; - - protected $_properties = array( - 'AirSyncBase' => array( - 'attachments' => array('type' => 'container', 'childElement' => 'attachment', 'class' => 'Syncroton_Model_EmailAttachment'), - 'contentType' => array('type' => 'string'), - 'body' => array('type' => 'container', 'class' => 'Syncroton_Model_EmailBody'), - 'nativeBodyType' => array('type' => 'number'), - ), - 'Email' => array( - 'busyStatus' => array('type' => 'number'), - 'categories' => array('type' => 'container', 'childElement' => 'category', 'supportedSince' => '14.0'), - 'cc' => array('type' => 'string'), - 'completeTime' => array('type' => 'datetime'), - 'contentClass' => array('type' => 'string'), - 'dateReceived' => array('type' => 'datetime'), - 'disallowNewTimeProposal' => array('type' => 'number'), - 'displayTo' => array('type' => 'string'), - 'dTStamp' => array('type' => 'datetime'), - 'endTime' => array('type' => 'datetime'), - 'flag' => array('type' => 'container', 'class' => 'Syncroton_Model_EmailFlag'), - 'from' => array('type' => 'string'), - 'globalObjId' => array('type' => 'string'), - 'importance' => array('type' => 'number'), - 'instanceType' => array('type' => 'number'), - 'internetCPID' => array('type' => 'string'), - 'location' => array('type' => 'string'), - 'meetingRequest' => array('type' => 'container', 'class' => 'Syncroton_Model_EmailMeetingRequest'), - 'messageClass' => array('type' => 'string'), - 'organizer' => array('type' => 'string'), - 'read' => array('type' => 'number'), - 'recurrences' => array('type' => 'container'), - 'reminder' => array('type' => 'number'), - 'replyTo' => array('type' => 'string'), - 'responseRequested' => array('type' => 'number'), - 'sensitivity' => array('type' => 'number'), - 'startTime' => array('type' => 'datetime'), - 'status' => array('type' => 'number'), - 'subject' => array('type' => 'string'), - 'threadTopic' => array('type' => 'string'), - 'timeZone' => array('type' => 'timezone'), - 'to' => array('type' => 'string'), - ), - 'Email2' => array( - 'accountId' => array('type' => 'string', 'supportedSince' => '14.1'), - 'conversationId' => array('type' => 'byteArray', 'supportedSince' => '14.0'), - 'conversationIndex' => array('type' => 'byteArray', 'supportedSince' => '14.0'), - 'lastVerbExecuted' => array('type' => 'number', 'supportedSince' => '14.0'), - 'lastVerbExecutionTime' => array('type' => 'datetime', 'supportedSince' => '14.0'), - 'meetingMessageType' => array('type' => 'number', 'supportedSince' => '14.1'), - 'receivedAsBcc' => array('type' => 'number', 'supportedSince' => '14.0'), - 'sender' => array('type' => 'string', 'supportedSince' => '14.0'), - 'umCallerID' => array('type' => 'string', 'supportedSince' => '14.0'), - 'umUserNotes' => array('type' => 'string', 'supportedSince' => '14.0'), - ), - ); + + protected $_properties = [ + 'AirSyncBase' => [ + 'attachments' => ['type' => 'container', 'childElement' => 'attachment', 'class' => 'Syncroton_Model_EmailAttachment'], + 'contentType' => ['type' => 'string'], + 'body' => ['type' => 'container', 'class' => 'Syncroton_Model_EmailBody'], + 'nativeBodyType' => ['type' => 'number'], + ], + 'Email' => [ + 'busyStatus' => ['type' => 'number'], + 'categories' => ['type' => 'container', 'childElement' => 'category', 'supportedSince' => '14.0'], + 'cc' => ['type' => 'string'], + 'completeTime' => ['type' => 'datetime'], + 'contentClass' => ['type' => 'string'], + 'dateReceived' => ['type' => 'datetime'], + 'disallowNewTimeProposal' => ['type' => 'number'], + 'displayTo' => ['type' => 'string'], + 'dTStamp' => ['type' => 'datetime'], + 'endTime' => ['type' => 'datetime'], + 'flag' => ['type' => 'container', 'class' => 'Syncroton_Model_EmailFlag'], + 'from' => ['type' => 'string'], + 'globalObjId' => ['type' => 'string'], + 'importance' => ['type' => 'number'], + 'instanceType' => ['type' => 'number'], + 'internetCPID' => ['type' => 'string'], + 'location' => ['type' => 'string'], + 'meetingRequest' => ['type' => 'container', 'class' => 'Syncroton_Model_EmailMeetingRequest'], + 'messageClass' => ['type' => 'string'], + 'organizer' => ['type' => 'string'], + 'read' => ['type' => 'number'], + 'recurrences' => ['type' => 'container'], + 'reminder' => ['type' => 'number'], + 'replyTo' => ['type' => 'string'], + 'responseRequested' => ['type' => 'number'], + 'sensitivity' => ['type' => 'number'], + 'startTime' => ['type' => 'datetime'], + 'status' => ['type' => 'number'], + 'subject' => ['type' => 'string'], + 'threadTopic' => ['type' => 'string'], + 'timeZone' => ['type' => 'timezone'], + 'to' => ['type' => 'string'], + ], + 'Email2' => [ + 'accountId' => ['type' => 'string', 'supportedSince' => '14.1'], + 'conversationId' => ['type' => 'byteArray', 'supportedSince' => '14.0'], + 'conversationIndex' => ['type' => 'byteArray', 'supportedSince' => '14.0'], + 'lastVerbExecuted' => ['type' => 'number', 'supportedSince' => '14.0'], + 'lastVerbExecutionTime' => ['type' => 'datetime', 'supportedSince' => '14.0'], + 'meetingMessageType' => ['type' => 'number', 'supportedSince' => '14.1'], + 'receivedAsBcc' => ['type' => 'number', 'supportedSince' => '14.0'], + 'sender' => ['type' => 'string', 'supportedSince' => '14.0'], + 'umCallerID' => ['type' => 'string', 'supportedSince' => '14.0'], + 'umUserNotes' => ['type' => 'string', 'supportedSince' => '14.0'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/EmailAttachment.php b/lib/ext/Syncroton/Model/EmailAttachment.php index 53446b5..c3bb784 100644 --- a/lib/ext/Syncroton/Model/EmailAttachment.php +++ b/lib/ext/Syncroton/Model/EmailAttachment.php @@ -1,43 +1,43 @@ */ /** * class to handle ActiveSync event * * @package Syncroton * @subpackage Model * @property string $class * @property string $collectionId * @property bool $deletesAsMoves * @property bool $getChanges * @property string $syncKey * @property int $windowSize */ class Syncroton_Model_EmailAttachment extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'Attachment'; - - protected $_properties = array( - 'AirSyncBase' => array( - 'contentId' => array('type' => 'string'), - 'contentLocation' => array('type' => 'string'), - 'displayName' => array('type' => 'string'), - 'estimatedDataSize' => array('type' => 'string'), - 'fileReference' => array('type' => 'string'), - 'isInline' => array('type' => 'number'), - 'method' => array('type' => 'string'), - ), - 'Email2' => array( - 'umAttDuration' => array('type' => 'number', 'supportedSince' => '14.0'), - 'umAttOrder' => array('type' => 'number', 'supportedSince' => '14.0'), - ), - ); -} \ No newline at end of file + + protected $_properties = [ + 'AirSyncBase' => [ + 'contentId' => ['type' => 'string'], + 'contentLocation' => ['type' => 'string'], + 'displayName' => ['type' => 'string'], + 'estimatedDataSize' => ['type' => 'string'], + 'fileReference' => ['type' => 'string'], + 'isInline' => ['type' => 'number'], + 'method' => ['type' => 'string'], + ], + 'Email2' => [ + 'umAttDuration' => ['type' => 'number', 'supportedSince' => '14.0'], + 'umAttOrder' => ['type' => 'number', 'supportedSince' => '14.0'], + ], + ]; +} diff --git a/lib/ext/Syncroton/Model/EmailBody.php b/lib/ext/Syncroton/Model/EmailBody.php index f274838..11550bb 100644 --- a/lib/ext/Syncroton/Model/EmailBody.php +++ b/lib/ext/Syncroton/Model/EmailBody.php @@ -1,44 +1,44 @@ */ /** * class to handle AirSyncBase:Body * * @package Syncroton * @subpackage Model * @property int $estimatedDataSize * @property string $data * @property string $part * @property string $preview * @property bool $truncated * @property string $type */ class Syncroton_Model_EmailBody extends Syncroton_Model_AXMLEntry { - const TYPE_PLAINTEXT = 1; - const TYPE_HTML = 2; - const TYPE_RTF = 3; - const TYPE_MIME = 4; - + public const TYPE_PLAINTEXT = 1; + public const TYPE_HTML = 2; + public const TYPE_RTF = 3; + public const TYPE_MIME = 4; + protected $_xmlBaseElement = 'Body'; - - protected $_properties = array( - 'AirSyncBase' => array( - 'type' => array('type' => 'string'), - 'estimatedDataSize' => array('type' => 'string'), - 'data' => array('type' => 'string'), - 'truncated' => array('type' => 'number'), - 'part' => array('type' => 'number'), - 'preview' => array('type' => 'string', 'supportedSince' => '14.0'), - ), - ); -} \ No newline at end of file + + protected $_properties = [ + 'AirSyncBase' => [ + 'type' => ['type' => 'string'], + 'estimatedDataSize' => ['type' => 'string'], + 'data' => ['type' => 'string'], + 'truncated' => ['type' => 'number'], + 'part' => ['type' => 'number'], + 'preview' => ['type' => 'string', 'supportedSince' => '14.0'], + ], + ]; +} diff --git a/lib/ext/Syncroton/Model/EmailFlag.php b/lib/ext/Syncroton/Model/EmailFlag.php index 55c2bf5..5302e20 100644 --- a/lib/ext/Syncroton/Model/EmailFlag.php +++ b/lib/ext/Syncroton/Model/EmailFlag.php @@ -1,60 +1,60 @@ * @author Aleksander Machniak */ /** * class to handle ActiveSync Flag element * * @package Syncroton * @subpackage Model * @property DateTime $completeTime * @property DateTime $dateCompleted * @property DateTime $dueDate * @property string $flagType * @property DateTime $ordinalDate * @property int $reminderSet * @property DateTime $reminderTime * @property DateTime $startDate * @property string $status * @property string $subject * @property string $subOrdinalDate * @property DateTime $utcDueDate * @property DateTime $utcStartDate */ class Syncroton_Model_EmailFlag extends Syncroton_Model_AXMLEntry { - const STATUS_CLEARED = 0; - const STATUS_COMPLETE = 1; - const STATUS_ACTIVE = 2; + public const STATUS_CLEARED = 0; + public const STATUS_COMPLETE = 1; + public const STATUS_ACTIVE = 2; protected $_xmlBaseElement = 'Flag'; - protected $_properties = array( - 'Email' => array( - 'completeTime' => array('type' => 'datetime'), - 'flagType' => array('type' => 'string'), - 'status' => array('type' => 'number'), - ), - 'Tasks' => array( - 'dateCompleted' => array('type' => 'datetime'), - 'dueDate' => array('type' => 'datetime'), - 'ordinalDate' => array('type' => 'datetime'), - 'reminderSet' => array('type' => 'number'), - 'reminderTime' => array('type' => 'datetime'), - 'startDate' => array('type' => 'datetime'), - 'subject' => array('type' => 'string'), - 'subOrdinalDate' => array('type' => 'string'), - 'utcStartDate' => array('type' => 'datetime'), - 'utcDueDate' => array('type' => 'datetime'), - ), - ); + protected $_properties = [ + 'Email' => [ + 'completeTime' => ['type' => 'datetime'], + 'flagType' => ['type' => 'string'], + 'status' => ['type' => 'number'], + ], + 'Tasks' => [ + 'dateCompleted' => ['type' => 'datetime'], + 'dueDate' => ['type' => 'datetime'], + 'ordinalDate' => ['type' => 'datetime'], + 'reminderSet' => ['type' => 'number'], + 'reminderTime' => ['type' => 'datetime'], + 'startDate' => ['type' => 'datetime'], + 'subject' => ['type' => 'string'], + 'subOrdinalDate' => ['type' => 'string'], + 'utcStartDate' => ['type' => 'datetime'], + 'utcDueDate' => ['type' => 'datetime'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/EmailMeetingRequest.php b/lib/ext/Syncroton/Model/EmailMeetingRequest.php index ece7755..1904260 100644 --- a/lib/ext/Syncroton/Model/EmailMeetingRequest.php +++ b/lib/ext/Syncroton/Model/EmailMeetingRequest.php @@ -1,96 +1,96 @@ */ /** * class to handle Email:MeetingRequest * * @package Syncroton * @subpackage Model * @property bool $allDayEvent * @property int $busyStatus * @property int $disallowNewTimeProposal * @property DateTime $dtStamp * @property DateTime $endTime * @property string $globalObjId * @property int $instanceType * @property int $meetingMessageType * @property string $organizer * @property string $recurrenceId * @property array $recurrences * @property int $reminder * @property int $responseRequested * @property int $sensitivity * @property DateTime $startTime * @property string $timezone */ class Syncroton_Model_EmailMeetingRequest extends Syncroton_Model_AXMLEntry { /** * busy status constants */ - const BUSY_STATUS_FREE = 0; - const BUSY_STATUS_TENATTIVE = 1; - const BUSY_STATUS_BUSY = 2; - const BUSY_STATUS_OUT = 3; + public const BUSY_STATUS_FREE = 0; + public const BUSY_STATUS_TENATTIVE = 1; + public const BUSY_STATUS_BUSY = 2; + public const BUSY_STATUS_OUT = 3; /** * sensitivity constants */ - const SENSITIVITY_NORMAL = 0; - const SENSITIVITY_PERSONAL = 1; - const SENSITIVITY_PRIVATE = 2; - const SENSITIVITY_CONFIDENTIAL = 3; + public const SENSITIVITY_NORMAL = 0; + public const SENSITIVITY_PERSONAL = 1; + public const SENSITIVITY_PRIVATE = 2; + public const SENSITIVITY_CONFIDENTIAL = 3; /** * instanceType constants */ - const TYPE_NORMAL = 0; - const TYPE_RECURRING_MASTER = 1; - const TYPE_RECURRING_SINGLE = 2; - const TYPE_RECURRING_EXCEPTION = 3; + public const TYPE_NORMAL = 0; + public const TYPE_RECURRING_MASTER = 1; + public const TYPE_RECURRING_SINGLE = 2; + public const TYPE_RECURRING_EXCEPTION = 3; /** * messageType constants */ - const MESSAGE_TYPE_NORMAL = 0; - const MESSAGE_TYPE_REQUEST = 1; - const MESSAGE_TYPE_FULL_UPDATE = 2; - const MESSAGE_TYPE_INFO_UPDATE = 3; - const MESSAGE_TYPE_OUTDATED = 4; - const MESSAGE_TYPE_COPY = 5; - const MESSAGE_TYPE_DELEGATED = 6; + public const MESSAGE_TYPE_NORMAL = 0; + public const MESSAGE_TYPE_REQUEST = 1; + public const MESSAGE_TYPE_FULL_UPDATE = 2; + public const MESSAGE_TYPE_INFO_UPDATE = 3; + public const MESSAGE_TYPE_OUTDATED = 4; + public const MESSAGE_TYPE_COPY = 5; + public const MESSAGE_TYPE_DELEGATED = 6; protected $_xmlBaseElement = 'MeetingRequest'; - protected $_properties = array( - 'Email' => array( - 'allDayEvent' => array('type' => 'number'), - 'busyStatus' => array('type' => 'number'), - 'disallowNewTimeProposal' => array('type' => 'number'), - 'dtStamp' => array('type' => 'datetime'), - 'endTime' => array('type' => 'datetime'), - 'globalObjId' => array('type' => 'string'), - 'instanceType' => array('type' => 'number'), - 'location' => array('type' => 'string'), - 'organizer' => array('type' => 'string'), //e-mail address - 'recurrenceId' => array('type' => 'datetime'), - 'recurrences' => array('type' => 'container'), - 'reminder' => array('type' => 'number'), - 'responseRequested' => array('type' => 'number'), - 'sensitivity' => array('type' => 'number'), - 'startTime' => array('type' => 'datetime'), - 'timeZone' => array('type' => 'timezone'), - ), - 'Email2' => array( - 'meetingMessageType' => array('type' => 'number'), - ), - ); + protected $_properties = [ + 'Email' => [ + 'allDayEvent' => ['type' => 'number'], + 'busyStatus' => ['type' => 'number'], + 'disallowNewTimeProposal' => ['type' => 'number'], + 'dtStamp' => ['type' => 'datetime'], + 'endTime' => ['type' => 'datetime'], + 'globalObjId' => ['type' => 'string'], + 'instanceType' => ['type' => 'number'], + 'location' => ['type' => 'string'], + 'organizer' => ['type' => 'string'], //e-mail address + 'recurrenceId' => ['type' => 'datetime'], + 'recurrences' => ['type' => 'container'], + 'reminder' => ['type' => 'number'], + 'responseRequested' => ['type' => 'number'], + 'sensitivity' => ['type' => 'number'], + 'startTime' => ['type' => 'datetime'], + 'timeZone' => ['type' => 'timezone'], + ], + 'Email2' => [ + 'meetingMessageType' => ['type' => 'number'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/EmailRecurrence.php b/lib/ext/Syncroton/Model/EmailRecurrence.php index 698cb28..c318c29 100644 --- a/lib/ext/Syncroton/Model/EmailRecurrence.php +++ b/lib/ext/Syncroton/Model/EmailRecurrence.php @@ -1,73 +1,73 @@ */ /** * class to handle Email::Recurrence * * @package Syncroton * @subpackage Model * @property int $calendarType * @property int $dayOfMonth * @property int $dayOfWeek * @property int $firstDayOfWeek * @property int $interval * @property int $isLeapMonth * @property int $monthOfYear * @property int $occurrences * @property int $type * @property DateTime $until * @property int $weekOfMonth */ class Syncroton_Model_EmailRecurrence extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'Recurrence'; /** * recur types */ - const TYPE_DAILY = 0; // Recurs daily - const TYPE_WEEKLY = 1; // Recurs weekly - const TYPE_MONTHLY = 3; // Recurs monthly - const TYPE_MONTHLY_DAYN = 2; // Recurs monthly on the nth day - const TYPE_YEARLY = 5; // Recurs yearly on the nth day of the nth month each year - const TYPE_YEARLY_DAYN = 6; // Recurs yearly on the nth day of the week of the nth month + public const TYPE_DAILY = 0; // Recurs daily + public const TYPE_WEEKLY = 1; // Recurs weekly + public const TYPE_MONTHLY = 3; // Recurs monthly + public const TYPE_MONTHLY_DAYN = 2; // Recurs monthly on the nth day + public const TYPE_YEARLY = 5; // Recurs yearly on the nth day of the nth month each year + public const TYPE_YEARLY_DAYN = 6; // Recurs yearly on the nth day of the week of the nth month /** * day of week constants */ - const RECUR_DOW_SUNDAY = 1; - const RECUR_DOW_MONDAY = 2; - const RECUR_DOW_TUESDAY = 4; - const RECUR_DOW_WEDNESDAY = 8; - const RECUR_DOW_THURSDAY = 16; - const RECUR_DOW_FRIDAY = 32; - const RECUR_DOW_SATURDAY = 64; + public const RECUR_DOW_SUNDAY = 1; + public const RECUR_DOW_MONDAY = 2; + public const RECUR_DOW_TUESDAY = 4; + public const RECUR_DOW_WEDNESDAY = 8; + public const RECUR_DOW_THURSDAY = 16; + public const RECUR_DOW_FRIDAY = 32; + public const RECUR_DOW_SATURDAY = 64; protected $_dateTimeFormat = "Ymd\THis\Z"; - protected $_properties = array( - 'Email' => array( - 'dayOfMonth' => array('type' => 'number'), - 'dayOfWeek' => array('type' => 'number'), - 'interval' => array('type' => 'number'), // 1 or 2 - 'monthOfYear' => array('type' => 'number'), - 'occurrences' => array('type' => 'number'), - 'type' => array('type' => 'number'), - 'until' => array('type' => 'datetime'), - 'weekOfMonth' => array('type' => 'number'), - ), - 'Email2' => array( - 'calendarType' => array('type' => 'number'), - 'firstDayOfWeek' => array('type' => 'number'), - 'isLeapMonth' => array('type' => 'number'), - ) - ); + protected $_properties = [ + 'Email' => [ + 'dayOfMonth' => ['type' => 'number'], + 'dayOfWeek' => ['type' => 'number'], + 'interval' => ['type' => 'number'], // 1 or 2 + 'monthOfYear' => ['type' => 'number'], + 'occurrences' => ['type' => 'number'], + 'type' => ['type' => 'number'], + 'until' => ['type' => 'datetime'], + 'weekOfMonth' => ['type' => 'number'], + ], + 'Email2' => [ + 'calendarType' => ['type' => 'number'], + 'firstDayOfWeek' => ['type' => 'number'], + 'isLeapMonth' => ['type' => 'number'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/Event.php b/lib/ext/Syncroton/Model/Event.php index 55879f2..5a488fe 100644 --- a/lib/ext/Syncroton/Model/Event.php +++ b/lib/ext/Syncroton/Model/Event.php @@ -1,130 +1,130 @@ */ /** * class to handle ActiveSync event * * @package Syncroton * @subpackage Model * * @property bool $allDayEvent * @property string $class * @property string $collectionId * @property bool $deletesAsMoves * @property DateTime $endTime * @property bool $getChanges * @property DateTime $startTime * @property string $syncKey * @property int $windowSize */ class Syncroton_Model_Event extends Syncroton_Model_AXMLEntry { - /** - * busy status constants - */ - const BUSY_STATUS_FREE = 0; - const BUSY_STATUS_TENATTIVE = 1; - const BUSY_STATUS_BUSY = 2; - - protected $_dateTimeFormat = "Ymd\THis\Z"; - + /** + * busy status constants + */ + public const BUSY_STATUS_FREE = 0; + public const BUSY_STATUS_TENATTIVE = 1; + public const BUSY_STATUS_BUSY = 2; + + protected $_dateTimeFormat = "Ymd\THis\Z"; + protected $_xmlBaseElement = 'ApplicationData'; - - protected $_properties = array( - 'AirSyncBase' => array( - 'body' => array('type' => 'container', 'class' => 'Syncroton_Model_EmailBody') - ), - 'Calendar' => array( - 'allDayEvent' => array('type' => 'number'), - 'appointmentReplyTime' => array('type' => 'datetime'), - 'attendees' => array('type' => 'container', 'childElement' => 'attendee', 'class' => 'Syncroton_Model_EventAttendee'), - 'busyStatus' => array('type' => 'number'), - 'categories' => array('type' => 'container', 'childElement' => 'category'), - 'disallowNewTimeProposal' => array('type' => 'number'), - 'dtStamp' => array('type' => 'datetime'), - 'endTime' => array('type' => 'datetime'), - 'exceptions' => array('type' => 'container', 'childElement' => 'exception', 'class' => 'Syncroton_Model_EventException'), - 'location' => array('type' => 'string'), - 'meetingStatus' => array('type' => 'number'), - 'onlineMeetingConfLink' => array('type' => 'string'), - 'onlineMeetingExternalLink' => array('type' => 'string'), - 'organizerEmail' => array('type' => 'string'), - 'organizerName' => array('type' => 'string'), - 'recurrence' => array('type' => 'container'), - 'reminder' => array('type' => 'number'), - 'responseRequested' => array('type' => 'number'), - 'responseType' => array('type' => 'number'), - 'sensitivity' => array('type' => 'number'), - 'startTime' => array('type' => 'datetime'), - 'subject' => array('type' => 'string'), - 'timezone' => array('type' => 'timezone'), - 'uID' => array('type' => 'string'), - ) - ); - + + protected $_properties = [ + 'AirSyncBase' => [ + 'body' => ['type' => 'container', 'class' => 'Syncroton_Model_EmailBody'], + ], + 'Calendar' => [ + 'allDayEvent' => ['type' => 'number'], + 'appointmentReplyTime' => ['type' => 'datetime'], + 'attendees' => ['type' => 'container', 'childElement' => 'attendee', 'class' => 'Syncroton_Model_EventAttendee'], + 'busyStatus' => ['type' => 'number'], + 'categories' => ['type' => 'container', 'childElement' => 'category'], + 'disallowNewTimeProposal' => ['type' => 'number'], + 'dtStamp' => ['type' => 'datetime'], + 'endTime' => ['type' => 'datetime'], + 'exceptions' => ['type' => 'container', 'childElement' => 'exception', 'class' => 'Syncroton_Model_EventException'], + 'location' => ['type' => 'string'], + 'meetingStatus' => ['type' => 'number'], + 'onlineMeetingConfLink' => ['type' => 'string'], + 'onlineMeetingExternalLink' => ['type' => 'string'], + 'organizerEmail' => ['type' => 'string'], + 'organizerName' => ['type' => 'string'], + 'recurrence' => ['type' => 'container'], + 'reminder' => ['type' => 'number'], + 'responseRequested' => ['type' => 'number'], + 'responseType' => ['type' => 'number'], + 'sensitivity' => ['type' => 'number'], + 'startTime' => ['type' => 'datetime'], + 'subject' => ['type' => 'string'], + 'timezone' => ['type' => 'timezone'], + 'uID' => ['type' => 'string'], + ], + ]; + /** * (non-PHPdoc) * @see Syncroton_Model_IEntry::appendXML() * @todo handle Attendees element */ public function appendXML(DOMElement $domParrent, Syncroton_Model_IDevice $device) { parent::appendXML($domParrent, $device); $exceptionElements = $domParrent->getElementsByTagName('Exception'); - $parentFields = array('AllDayEvent'/*, 'Attendees'*/, 'Body', 'BusyStatus'/*, 'Categories'*/, 'DtStamp', 'EndTime', 'Location', 'MeetingStatus', 'Reminder', 'ResponseType', 'Sensitivity', 'StartTime', 'Subject'); + $parentFields = ['AllDayEvent'/*, 'Attendees'*/, 'Body', 'BusyStatus'/*, 'Categories'*/, 'DtStamp', 'EndTime', 'Location', 'MeetingStatus', 'Reminder', 'ResponseType', 'Sensitivity', 'StartTime', 'Subject']; if ($exceptionElements->length > 0) { $mainEventElement = $exceptionElements->item(0)->parentNode->parentNode; foreach ($mainEventElement->childNodes as $childNode) { if (in_array($childNode->localName, $parentFields)) { foreach ($exceptionElements as $exception) { $elementsToLeftOut = $exception->getElementsByTagName($childNode->localName); foreach ($elementsToLeftOut as $elementToLeftOut) { if ($elementToLeftOut->nodeValue == $childNode->nodeValue) { $exception->removeChild($elementToLeftOut); } } } } } } } - + /** - * some elements of an exception can be left out, if they have the same value + * some elements of an exception can be left out, if they have the same value * like the main event - * + * * this function copies these elements to the exception for backends which need * this elements in the exceptions too. Tine 2.0 needs this for example. */ public function copyFieldsFromParent() { - if (isset($this->_elements['exceptions']) && is_array($this->_elements['exceptions'])) { - foreach ($this->_elements['exceptions'] as $exception) { - // no need to update deleted exceptions - if ($exception->deleted == 1) { - continue; - } - - $parentFields = array('allDayEvent', 'attendees', 'body', 'busyStatus', 'categories', 'dtStamp', 'endTime', 'location', 'meetingStatus', 'reminder', 'responseType', 'sensitivity', 'startTime', 'subject'); - - foreach ($parentFields as $field) { - if (!isset($exception->$field) && isset($this->_elements[$field])) { - $exception->$field = $this->_elements[$field]; - } - } - } - } + if (isset($this->_elements['exceptions']) && is_array($this->_elements['exceptions'])) { + foreach ($this->_elements['exceptions'] as $exception) { + // no need to update deleted exceptions + if ($exception->deleted == 1) { + continue; + } + + $parentFields = ['allDayEvent', 'attendees', 'body', 'busyStatus', 'categories', 'dtStamp', 'endTime', 'location', 'meetingStatus', 'reminder', 'responseType', 'sensitivity', 'startTime', 'subject']; + + foreach ($parentFields as $field) { + if (!isset($exception->$field) && isset($this->_elements[$field])) { + $exception->$field = $this->_elements[$field]; + } + } + } + } } -} \ No newline at end of file +} diff --git a/lib/ext/Syncroton/Model/EventAttendee.php b/lib/ext/Syncroton/Model/EventAttendee.php index 27328b0..f2149b9 100644 --- a/lib/ext/Syncroton/Model/EventAttendee.php +++ b/lib/ext/Syncroton/Model/EventAttendee.php @@ -1,52 +1,52 @@ */ /** * class to handle ActiveSync event * * @package Syncroton * @subpackage Model * @property string $class * @property string $collectionId * @property bool $deletesAsMoves * @property bool $getChanges * @property string $syncKey * @property int $windowSize */ class Syncroton_Model_EventAttendee extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'Attendee'; - - /** - * attendee status - */ - const ATTENDEE_STATUS_UNKNOWN = 0; - const ATTENDEE_STATUS_TENTATIVE = 2; - const ATTENDEE_STATUS_ACCEPTED = 3; - const ATTENDEE_STATUS_DECLINED = 4; - const ATTENDEE_STATUS_NOTRESPONDED = 5; - - /** - * attendee types - */ - const ATTENDEE_TYPE_REQUIRED = 1; - const ATTENDEE_TYPE_OPTIONAL = 2; - const ATTENDEE_TYPE_RESOURCE = 3; - - protected $_properties = array( - 'Calendar' => array( - 'attendeeStatus' => array('type' => 'number'), - 'attendeeType' => array('type' => 'number'), - 'email' => array('type' => 'string'), - 'name' => array('type' => 'string'), - ) - ); -} \ No newline at end of file + + /** + * attendee status + */ + public const ATTENDEE_STATUS_UNKNOWN = 0; + public const ATTENDEE_STATUS_TENTATIVE = 2; + public const ATTENDEE_STATUS_ACCEPTED = 3; + public const ATTENDEE_STATUS_DECLINED = 4; + public const ATTENDEE_STATUS_NOTRESPONDED = 5; + + /** + * attendee types + */ + public const ATTENDEE_TYPE_REQUIRED = 1; + public const ATTENDEE_TYPE_OPTIONAL = 2; + public const ATTENDEE_TYPE_RESOURCE = 3; + + protected $_properties = [ + 'Calendar' => [ + 'attendeeStatus' => ['type' => 'number'], + 'attendeeType' => ['type' => 'number'], + 'email' => ['type' => 'string'], + 'name' => ['type' => 'string'], + ], + ]; +} diff --git a/lib/ext/Syncroton/Model/EventException.php b/lib/ext/Syncroton/Model/EventException.php index 9b82e15..4b5bfde 100644 --- a/lib/ext/Syncroton/Model/EventException.php +++ b/lib/ext/Syncroton/Model/EventException.php @@ -1,57 +1,57 @@ */ /** * class to handle ActiveSync event * * @package Syncroton * @subpackage Model * * @property bool $allDayEvent * @property string $class * @property string $collectionId * @property bool $deletesAsMoves * @property DateTime $endTime * @property bool $getChanges * @property DateTime $startTime * @property string $syncKey * @property int $windowSize */ class Syncroton_Model_EventException extends Syncroton_Model_AXMLEntry -{ +{ protected $_xmlBaseElement = 'Exception'; - + protected $_dateTimeFormat = "Ymd\THis\Z"; - - protected $_properties = array( - 'AirSyncBase' => array( - 'body' => array('type' => 'container', 'class' => 'Syncroton_Model_EmailBody') - ), - 'Calendar' => array( - 'allDayEvent' => array('type' => 'number'), - 'appointmentReplyTime' => array('type' => 'datetime'), - 'attendees' => array('type' => 'container', 'childElement' => 'attendee', 'class' => 'Syncroton_Model_EventAttendee'), - 'busyStatus' => array('type' => 'number'), - 'categories' => array('type' => 'container', 'childElement' => 'category'), - 'deleted' => array('type' => 'number'), - 'dtStamp' => array('type' => 'datetime'), - 'endTime' => array('type' => 'datetime'), - 'exceptionStartTime' => array('type' => 'datetime'), - 'location' => array('type' => 'string'), - 'meetingStatus' => array('type' => 'number'), - 'reminder' => array('type' => 'number'), - 'responseType' => array('type' => 'number'), - 'sensitivity' => array('type' => 'number'), - 'startTime' => array('type' => 'datetime'), - 'subject' => array('type' => 'string'), - ) - ); -} \ No newline at end of file + + protected $_properties = [ + 'AirSyncBase' => [ + 'body' => ['type' => 'container', 'class' => 'Syncroton_Model_EmailBody'], + ], + 'Calendar' => [ + 'allDayEvent' => ['type' => 'number'], + 'appointmentReplyTime' => ['type' => 'datetime'], + 'attendees' => ['type' => 'container', 'childElement' => 'attendee', 'class' => 'Syncroton_Model_EventAttendee'], + 'busyStatus' => ['type' => 'number'], + 'categories' => ['type' => 'container', 'childElement' => 'category'], + 'deleted' => ['type' => 'number'], + 'dtStamp' => ['type' => 'datetime'], + 'endTime' => ['type' => 'datetime'], + 'exceptionStartTime' => ['type' => 'datetime'], + 'location' => ['type' => 'string'], + 'meetingStatus' => ['type' => 'number'], + 'reminder' => ['type' => 'number'], + 'responseType' => ['type' => 'number'], + 'sensitivity' => ['type' => 'number'], + 'startTime' => ['type' => 'datetime'], + 'subject' => ['type' => 'string'], + ], + ]; +} diff --git a/lib/ext/Syncroton/Model/EventRecurrence.php b/lib/ext/Syncroton/Model/EventRecurrence.php index 80c3bb0..747cb3f 100644 --- a/lib/ext/Syncroton/Model/EventRecurrence.php +++ b/lib/ext/Syncroton/Model/EventRecurrence.php @@ -1,71 +1,71 @@ */ /** * class to handle ActiveSync event * * @package Syncroton * @subpackage Model * @property int $calendarType * @property int $dayOfMonth * @property int $dayOfWeek * @property int $firstDayOfWeek * @property int $interval * @property int $isLeapMonth * @property int $monthOfYear * @property int $occurrences * @property int $type * @property DateTime $until * @property int $weekOfMonth */ class Syncroton_Model_EventRecurrence extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'Recurrence'; - - /** - * recur types - */ - const TYPE_DAILY = 0; // Recurs daily. - const TYPE_WEEKLY = 1; // Recurs weekly - const TYPE_MONTHLY = 2; // Recurs monthly - const TYPE_MONTHLY_DAYN = 3; // Recurs monthly on the nth day - const TYPE_YEARLY = 5; // Recurs yearly - const TYPE_YEARLY_DAYN = 6; // Recurs yearly on the nth day - - /** - * day of week constants - */ - const RECUR_DOW_SUNDAY = 1; - const RECUR_DOW_MONDAY = 2; - const RECUR_DOW_TUESDAY = 4; - const RECUR_DOW_WEDNESDAY = 8; - const RECUR_DOW_THURSDAY = 16; - const RECUR_DOW_FRIDAY = 32; - const RECUR_DOW_SATURDAY = 64; - + + /** + * recur types + */ + public const TYPE_DAILY = 0; // Recurs daily. + public const TYPE_WEEKLY = 1; // Recurs weekly + public const TYPE_MONTHLY = 2; // Recurs monthly + public const TYPE_MONTHLY_DAYN = 3; // Recurs monthly on the nth day + public const TYPE_YEARLY = 5; // Recurs yearly + public const TYPE_YEARLY_DAYN = 6; // Recurs yearly on the nth day + + /** + * day of week constants + */ + public const RECUR_DOW_SUNDAY = 1; + public const RECUR_DOW_MONDAY = 2; + public const RECUR_DOW_TUESDAY = 4; + public const RECUR_DOW_WEDNESDAY = 8; + public const RECUR_DOW_THURSDAY = 16; + public const RECUR_DOW_FRIDAY = 32; + public const RECUR_DOW_SATURDAY = 64; + protected $_dateTimeFormat = "Ymd\THis\Z"; - - protected $_properties = array( - 'Calendar' => array( - 'calendarType' => array('type' => 'number'), - 'dayOfMonth' => array('type' => 'number'), - 'dayOfWeek' => array('type' => 'number'), - 'firstDayOfWeek' => array('type' => 'number'), - 'interval' => array('type' => 'number'), - 'isLeapMonth' => array('type' => 'number'), - 'monthOfYear' => array('type' => 'number'), - 'occurrences' => array('type' => 'number'), - 'type' => array('type' => 'number'), - 'until' => array('type' => 'datetime'), - 'weekOfMonth' => array('type' => 'number'), - ) - ); -} \ No newline at end of file + + protected $_properties = [ + 'Calendar' => [ + 'calendarType' => ['type' => 'number'], + 'dayOfMonth' => ['type' => 'number'], + 'dayOfWeek' => ['type' => 'number'], + 'firstDayOfWeek' => ['type' => 'number'], + 'interval' => ['type' => 'number'], + 'isLeapMonth' => ['type' => 'number'], + 'monthOfYear' => ['type' => 'number'], + 'occurrences' => ['type' => 'number'], + 'type' => ['type' => 'number'], + 'until' => ['type' => 'datetime'], + 'weekOfMonth' => ['type' => 'number'], + ], + ]; +} diff --git a/lib/ext/Syncroton/Model/FileReference.php b/lib/ext/Syncroton/Model/FileReference.php index 7302aad..56b7c32 100644 --- a/lib/ext/Syncroton/Model/FileReference.php +++ b/lib/ext/Syncroton/Model/FileReference.php @@ -1,45 +1,45 @@ */ /** * class to handle ActiveSync event * * @package Syncroton * @subpackage Model * @property string $contentType * @property string $data * @property int $part */ class Syncroton_Model_FileReference extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'ApplicationData'; - protected $_properties = array( - 'AirSyncBase' => array( - 'contentType' => array('type' => 'string'), - ), - 'ItemOperations' => array( - 'data' => array('type' => 'string', 'encoding' => 'base64'), - 'part' => array('type' => 'number') - ) - ); + protected $_properties = [ + 'AirSyncBase' => [ + 'contentType' => ['type' => 'string'], + ], + 'ItemOperations' => [ + 'data' => ['type' => 'string', 'encoding' => 'base64'], + 'part' => ['type' => 'number'], + ], + ]; /** * * @param SimpleXMLElement $properties * @throws InvalidArgumentException */ public function setFromSimpleXMLElement(SimpleXMLElement $properties) { // do nothing return; } } diff --git a/lib/ext/Syncroton/Model/Folder.php b/lib/ext/Syncroton/Model/Folder.php index 4da0a97..e57b427 100644 --- a/lib/ext/Syncroton/Model/Folder.php +++ b/lib/ext/Syncroton/Model/Folder.php @@ -1,39 +1,39 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Model */ class Syncroton_Model_Folder extends Syncroton_Model_AXMLEntry implements Syncroton_Model_IFolder { - protected $_xmlBaseElement = array('FolderUpdate', 'FolderCreate'); - - 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'), - 'ownerId' => array('type' => 'string'), - 'class' => array('type' => 'string'), - 'creationTime' => array('type' => 'datetime'), - 'lastfiltertype' => array('type' => 'number') - ), - ); + protected $_xmlBaseElement = ['FolderUpdate', 'FolderCreate']; + + protected $_properties = [ + 'FolderHierarchy' => [ + 'parentId' => ['type' => 'string'], + 'serverId' => ['type' => 'string'], + 'displayName' => ['type' => 'string'], + 'type' => ['type' => 'number'], + ], + 'Internal' => [ + 'id' => ['type' => 'string'], + 'deviceId' => ['type' => 'string'], + 'ownerId' => ['type' => 'string'], + 'class' => ['type' => 'string'], + 'creationTime' => ['type' => 'datetime'], + 'lastfiltertype' => ['type' => 'number'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/GAL.php b/lib/ext/Syncroton/Model/GAL.php index 3a9807d..edca5ef 100644 --- a/lib/ext/Syncroton/Model/GAL.php +++ b/lib/ext/Syncroton/Model/GAL.php @@ -1,51 +1,51 @@ * @author Aleksander Machniak */ /** * class to handle ActiveSync GAL result * * @package Syncroton * @subpackage Model * * @property string $alias * @property string $company * @property string $displayName * @property string $emailAddress * @property string $firstName * @property string $lastName * @property string $mobilePhone * @property string $office * @property string $phone * @property string $picture * @property string $title */ class Syncroton_Model_GAL extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'ApplicationData'; - protected $_properties = array( - 'GAL' => array( - 'alias' => array('type' => 'string', 'supportedSince' => '2.5'), - 'company' => array('type' => 'string', 'supportedSince' => '2.5'), - 'displayName' => array('type' => 'string', 'supportedSince' => '2.5'), - 'emailAddress' => array('type' => 'string', 'supportedSince' => '2.5'), - 'firstName' => array('type' => 'string', 'supportedSince' => '2.5'), - 'lastName' => array('type' => 'string', 'supportedSince' => '2.5'), - 'mobilePhone' => array('type' => 'string', 'supportedSince' => '2.5'), - 'office' => array('type' => 'string', 'supportedSince' => '2.5'), - 'phone' => array('type' => 'string', 'supportedSince' => '2.5'), - 'picture' => array('type' => 'container', 'supportedSince' => '14.0'), - 'title' => array('type' => 'string', 'supportedSince' => '2.5'), - ) - ); + protected $_properties = [ + 'GAL' => [ + 'alias' => ['type' => 'string', 'supportedSince' => '2.5'], + 'company' => ['type' => 'string', 'supportedSince' => '2.5'], + 'displayName' => ['type' => 'string', 'supportedSince' => '2.5'], + 'emailAddress' => ['type' => 'string', 'supportedSince' => '2.5'], + 'firstName' => ['type' => 'string', 'supportedSince' => '2.5'], + 'lastName' => ['type' => 'string', 'supportedSince' => '2.5'], + 'mobilePhone' => ['type' => 'string', 'supportedSince' => '2.5'], + 'office' => ['type' => 'string', 'supportedSince' => '2.5'], + 'phone' => ['type' => 'string', 'supportedSince' => '2.5'], + 'picture' => ['type' => 'container', 'supportedSince' => '14.0'], + 'title' => ['type' => 'string', 'supportedSince' => '2.5'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/GALPicture.php b/lib/ext/Syncroton/Model/GALPicture.php index f6801a1..4b50744 100644 --- a/lib/ext/Syncroton/Model/GALPicture.php +++ b/lib/ext/Syncroton/Model/GALPicture.php @@ -1,40 +1,40 @@ * @author Aleksander Machniak */ /** * class to handle ActiveSync GAL Picture element * * @package Syncroton * @subpackage Model * * @property string $status * @property string $data */ class Syncroton_Model_GALPicture extends Syncroton_Model_AXMLEntry { - const STATUS_SUCCESS = 1; - const STATUS_NOPHOTO = 173; - const STATUS_TOOLARGE = 174; - const STATUS_OVERLIMIT = 175; + public const STATUS_SUCCESS = 1; + public const STATUS_NOPHOTO = 173; + public const STATUS_TOOLARGE = 174; + public const STATUS_OVERLIMIT = 175; protected $_xmlBaseElement = 'ApplicationData'; - protected $_properties = array( - 'AirSync' => array( - 'status' => array('type' => 'number'), - ), - 'GAL' => array( - 'data' => array('type' => 'byteArray'), - ), - ); + protected $_properties = [ + 'AirSync' => [ + 'status' => ['type' => 'number'], + ], + 'GAL' => [ + 'data' => ['type' => 'byteArray'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/IContent.php b/lib/ext/Syncroton/Model/IContent.php index 2aa29af..0cbc82f 100644 --- a/lib/ext/Syncroton/Model/IContent.php +++ b/lib/ext/Syncroton/Model/IContent.php @@ -1,28 +1,27 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Model * @property string $id * @property string $device_id * @property string $folder_id * @property string $contentid * @property DateTime $creation_time * @property string $creation_synckey * @property string $is_deleted */ interface Syncroton_Model_IContent { } - diff --git a/lib/ext/Syncroton/Model/IEntry.php b/lib/ext/Syncroton/Model/IEntry.php index 528121e..822a418 100644 --- a/lib/ext/Syncroton/Model/IEntry.php +++ b/lib/ext/Syncroton/Model/IEntry.php @@ -1,42 +1,42 @@ */ /** * class to handle ActiveSync entry * * @package Syncroton * @subpackage Model * @property string $class * @property string $collectionId * @property bool $deletesAsMoves * @property bool $getChanges * @property string $syncKey * @property int $windowSize */ interface Syncroton_Model_IEntry { /** - * + * * @param SimpleXMLElement|array|null $properties */ public function __construct($properties = null); - + /** * return true if data have got changed after initial data got loaded via constructor */ public function isDirty(); - + /** - * + * * @param array $properties - */ - public function setFromArray(array $properties); -} \ No newline at end of file + */ + public function setFromArray(array $properties); +} diff --git a/lib/ext/Syncroton/Model/IFolder.php b/lib/ext/Syncroton/Model/IFolder.php index 14f2851..39aee4c 100644 --- a/lib/ext/Syncroton/Model/IFolder.php +++ b/lib/ext/Syncroton/Model/IFolder.php @@ -1,30 +1,29 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Model * @property string $id * @property string $deviceId * @property string $class * @property string $serverId * @property string $parentId * @property string $displayName * @property DateTime $creationTime * @property int $lastfiltertype * @property int $type */ interface Syncroton_Model_IFolder { } - diff --git a/lib/ext/Syncroton/Model/IPolicy.php b/lib/ext/Syncroton/Model/IPolicy.php index 416cf71..10e3139 100644 --- a/lib/ext/Syncroton/Model/IPolicy.php +++ b/lib/ext/Syncroton/Model/IPolicy.php @@ -1,32 +1,31 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage 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/ISyncState.php b/lib/ext/Syncroton/Model/ISyncState.php index 418de85..516a630 100644 --- a/lib/ext/Syncroton/Model/ISyncState.php +++ b/lib/ext/Syncroton/Model/ISyncState.php @@ -1,29 +1,28 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Model * @property string $deviceId * @property string $type * @property int $counter * @property DateTime $lastsync * @property string $id * @property ?array $pendingdata * @property string $clientIdMap JSON-encoded array * @property string $extraData JSON-encoded array */ interface Syncroton_Model_ISyncState { } - diff --git a/lib/ext/Syncroton/Model/IXMLEntry.php b/lib/ext/Syncroton/Model/IXMLEntry.php index 2233f9b..23d4b59 100644 --- a/lib/ext/Syncroton/Model/IXMLEntry.php +++ b/lib/ext/Syncroton/Model/IXMLEntry.php @@ -1,40 +1,40 @@ */ /** * class to handle ActiveSync contact * * @package Syncroton * @subpackage Model */ interface Syncroton_Model_IXMLEntry extends Syncroton_Model_IEntry { /** - * + * * @param DOMElement $_domParent * @param Syncroton_Model_IDevice $device */ public function appendXML(DOMElement $_domParent, Syncroton_Model_IDevice $device); - + /** * return array of valid properties - * + * * @return array */ public function getProperties($selectedNamespace = null); - + /** - * + * * @param SimpleXMLElement $properties * @throws InvalidArgumentException */ public function setFromSimpleXMLElement(SimpleXMLElement $properties); -} \ No newline at end of file +} diff --git a/lib/ext/Syncroton/Model/MeetingResponse.php b/lib/ext/Syncroton/Model/MeetingResponse.php index d3b120d..a35ccab 100644 --- a/lib/ext/Syncroton/Model/MeetingResponse.php +++ b/lib/ext/Syncroton/Model/MeetingResponse.php @@ -1,47 +1,47 @@ */ /** * class to handle MeetingResponse request * * @package Syncroton * @subpackage Model * @property int $userResponse * @property string $collectionId * @property string $calendarId * @property string $requestId * @property string $instanceId * @property string $longId */ class Syncroton_Model_MeetingResponse extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'Request'; - - /** - * attendee status - */ - const RESPONSE_ACCEPTED = 1; - const RESPONSE_TENTATIVE = 2; - const RESPONSE_DECLINED = 3; - - protected $_properties = array( - 'MeetingResponse' => array( - 'userResponse' => array('type' => 'number'), - 'collectionId' => array('type' => 'string'), - 'calendarId' => array('type' => 'string'), - 'requestId' => array('type' => 'string'), - 'instanceId' => array('type' => 'datetime'), - ), - 'Search' => array( - 'longId' => array('type' => 'string') - ) - ); -} \ No newline at end of file + + /** + * attendee status + */ + public const RESPONSE_ACCEPTED = 1; + public const RESPONSE_TENTATIVE = 2; + public const RESPONSE_DECLINED = 3; + + protected $_properties = [ + 'MeetingResponse' => [ + 'userResponse' => ['type' => 'number'], + 'collectionId' => ['type' => 'string'], + 'calendarId' => ['type' => 'string'], + 'requestId' => ['type' => 'string'], + 'instanceId' => ['type' => 'datetime'], + ], + 'Search' => [ + 'longId' => ['type' => 'string'], + ], + ]; +} diff --git a/lib/ext/Syncroton/Model/Note.php b/lib/ext/Syncroton/Model/Note.php index 4425391..283883a 100644 --- a/lib/ext/Syncroton/Model/Note.php +++ b/lib/ext/Syncroton/Model/Note.php @@ -1,38 +1,38 @@ */ /** * class to handle ActiveSync note * * @package Syncroton * @subpackage Model * @property Syncroton_Model_EmailBody $body * @property array $categories * @property DateTime $lastModifiedDate * @property string $messageClass * @property string $subject */ class Syncroton_Model_Note extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'ApplicationData'; - protected $_properties = array( - 'AirSyncBase' => array( - 'body' => array('type' => 'container', 'class' => 'Syncroton_Model_EmailBody') - ), - 'Notes' => array( - 'categories' => array('type' => 'container', 'childElement' => 'category'), - 'lastModifiedDate' => array('type' => 'datetime'), - 'messageClass' => array('type' => 'string'), - 'subject' => array('type' => 'string'), - ) - ); -} \ No newline at end of file + protected $_properties = [ + 'AirSyncBase' => [ + 'body' => ['type' => 'container', 'class' => 'Syncroton_Model_EmailBody'], + ], + 'Notes' => [ + 'categories' => ['type' => 'container', 'childElement' => 'category'], + 'lastModifiedDate' => ['type' => 'datetime'], + 'messageClass' => ['type' => 'string'], + 'subject' => ['type' => 'string'], + ], + ]; +} diff --git a/lib/ext/Syncroton/Model/Oof.php b/lib/ext/Syncroton/Model/Oof.php index 8a6c1fc..bf7d8ac 100644 --- a/lib/ext/Syncroton/Model/Oof.php +++ b/lib/ext/Syncroton/Model/Oof.php @@ -1,40 +1,40 @@ */ /** * Class to handle ActiveSync Settings/Oof/Get|Set element * * @package Syncroton * @subpackage Model * * @property DateTime $endTime * @property Syncroton_Model_OofMessage $oofMessage * @property int $oofState * @property DateTime $startTime */ class Syncroton_Model_Oof extends Syncroton_Model_AXMLEntry { - const STATUS_DISABLED = 0; - const STATUS_GLOBAL = 1; - const STATUS_TIME_BASED = 2; + public const STATUS_DISABLED = 0; + public const STATUS_GLOBAL = 1; + public const STATUS_TIME_BASED = 2; - protected $_xmlBaseElement = array('Get', 'Set'); + protected $_xmlBaseElement = ['Get', 'Set']; - protected $_properties = array( - 'Settings' => array( - 'endTime' => array('type' => 'datetime'), - 'oofMessage' => array('type' => 'container', 'multiple' => true, 'class' => 'Syncroton_Model_OofMessage'), - 'oofState' => array('type' => 'number'), - 'startTime' => array('type' => 'datetime'), - ) - ); + protected $_properties = [ + 'Settings' => [ + 'endTime' => ['type' => 'datetime'], + 'oofMessage' => ['type' => 'container', 'multiple' => true, 'class' => 'Syncroton_Model_OofMessage'], + 'oofState' => ['type' => 'number'], + 'startTime' => ['type' => 'datetime'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/OofMessage.php b/lib/ext/Syncroton/Model/OofMessage.php index 7c6c67a..38048c6 100644 --- a/lib/ext/Syncroton/Model/OofMessage.php +++ b/lib/ext/Syncroton/Model/OofMessage.php @@ -1,33 +1,33 @@ */ /** * Class to handle ActiveSync OofMessage element * * @package Syncroton * @subpackage Model */ class Syncroton_Model_OofMessage extends Syncroton_Model_AXMLEntry { - protected $_xmlBaseElement = array('OofMessage'); + protected $_xmlBaseElement = ['OofMessage']; - protected $_properties = array( - 'Settings' => array( - 'appliesToInternal' => array('type' => 'none'), - 'appliesToExternalKnown' => array('type' => 'none'), - 'appliesToExternalUnknown' => array('type' => 'none'), - 'bodyType' => array('type' => 'string'), - 'enabled' => array('type' => 'string'), - 'replyMessage' => array('type' => 'string'), - ) - ); + protected $_properties = [ + 'Settings' => [ + 'appliesToInternal' => ['type' => 'none'], + 'appliesToExternalKnown' => ['type' => 'none'], + 'appliesToExternalUnknown' => ['type' => 'none'], + 'bodyType' => ['type' => 'string'], + 'enabled' => ['type' => 'string'], + 'replyMessage' => ['type' => 'string'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/Policy.php b/lib/ext/Syncroton/Model/Policy.php index b292de4..7d0142e 100644 --- a/lib/ext/Syncroton/Model/Policy.php +++ b/lib/ext/Syncroton/Model/Policy.php @@ -1,74 +1,74 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Model */ class Syncroton_Model_Policy extends Syncroton_Model_AXMLEntry 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'), - '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') - ) - ); + + protected $_properties = [ + 'Internal' => [ + 'id' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'policyKey' => ['type' => 'string'], + ], + 'Provision' => [ + 'allowBluetooth' => ['type' => 'number'], + 'allowBrowser' => ['type' => 'number'], + 'allowCamera' => ['type' => 'number'], + 'allowConsumerEmail' => ['type' => 'number'], + 'allowDesktopSync' => ['type' => 'number'], + 'allowHTMLEmail' => ['type' => 'number'], + 'allowInternetSharing' => ['type' => 'number'], + 'allowIrDA' => ['type' => 'number'], + 'allowPOPIMAPEmail' => ['type' => 'number'], + 'allowRemoteDesktop' => ['type' => 'number'], + 'allowSimpleDevicePassword' => ['type' => 'number'], + 'allowSMIMEEncryptionAlgorithmNegotiation' => ['type' => 'number'], + 'allowSMIMESoftCerts' => ['type' => 'number'], + 'allowStorageCard' => ['type' => 'number'], + 'allowTextMessaging' => ['type' => 'number'], + 'allowUnsignedApplications' => ['type' => 'number'], + 'allowUnsignedInstallationPackages' => ['type' => 'number'], + 'allowWifi' => ['type' => 'number'], + 'alphanumericDevicePasswordRequired' => ['type' => 'number'], + 'approvedApplicationList' => ['type' => 'container', 'childName' => 'Hash'], + 'attachmentsEnabled' => ['type' => 'number'], + 'devicePasswordEnabled' => ['type' => 'number'], + 'devicePasswordExpiration' => ['type' => 'number'], + 'devicePasswordHistory' => ['type' => 'number'], + 'maxAttachmentSize' => ['type' => 'number'], + 'maxCalendarAgeFilter' => ['type' => 'number'], + 'maxDevicePasswordFailedAttempts' => ['type' => 'number'], + 'maxEmailAgeFilter' => ['type' => 'number'], + 'maxEmailBodyTruncationSize' => ['type' => 'number'], + 'maxEmailHTMLBodyTruncationSize' => ['type' => 'number'], + 'maxInactivityTimeDeviceLock' => ['type' => 'number'], + 'minDevicePasswordComplexCharacters' => ['type' => 'number'], + 'minDevicePasswordLength' => ['type' => 'number'], + 'passwordRecoveryEnabled' => ['type' => 'number'], + 'requireDeviceEncryption' => ['type' => 'number'], + 'requireEncryptedSMIMEMessages' => ['type' => 'number'], + 'requireEncryptionSMIMEAlgorithm' => ['type' => 'number'], + 'requireManualSyncWhenRoaming' => ['type' => 'number'], + 'requireSignedSMIMEAlgorithm' => ['type' => 'number'], + 'requireSignedSMIMEMessages' => ['type' => 'number'], + 'requireStorageCardEncryption' => ['type' => 'number'], + 'unapprovedInROMApplicationList' => ['type' => 'container', 'childName' => 'ApplicationName'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/SendMail.php b/lib/ext/Syncroton/Model/SendMail.php index 337a7be..dbc2887 100644 --- a/lib/ext/Syncroton/Model/SendMail.php +++ b/lib/ext/Syncroton/Model/SendMail.php @@ -1,34 +1,34 @@ * @author Aleksander Machniak */ /** * Class to handle ActiveSync SendMail element * * @package Syncroton * @subpackage Model */ class Syncroton_Model_SendMail extends Syncroton_Model_AXMLEntry { - protected $_properties = array( - 'ComposeMail' => array( - 'accountId' => array('type' => 'string'), - 'clientId' => array('type' => 'string'), - 'mime' => array('type' => 'byteArray'), - 'saveInSentItems' => array('type' => 'string'), - 'status' => array('type' => 'number'), - ), - 'RightsManagement' => array( - 'templateID' => array('type' => 'string'), - ) - ); + protected $_properties = [ + 'ComposeMail' => [ + 'accountId' => ['type' => 'string'], + 'clientId' => ['type' => 'string'], + 'mime' => ['type' => 'byteArray'], + 'saveInSentItems' => ['type' => 'string'], + 'status' => ['type' => 'number'], + ], + 'RightsManagement' => [ + 'templateID' => ['type' => 'string'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/SmartForward.php b/lib/ext/Syncroton/Model/SmartForward.php index a403824..621e2b0 100644 --- a/lib/ext/Syncroton/Model/SmartForward.php +++ b/lib/ext/Syncroton/Model/SmartForward.php @@ -1,36 +1,36 @@ * @author Aleksander Machniak */ /** * Class to handle ActiveSync SmartForward element * * @package Syncroton * @subpackage Model */ class Syncroton_Model_SmartForward extends Syncroton_Model_AXMLEntry { - protected $_properties = array( - 'ComposeMail' => array( - 'accountId' => array('type' => 'string'), - 'clientId' => array('type' => 'string'), - 'mime' => array('type' => 'byteArray'), - 'replaceMime' => array('type' => 'string'), - 'saveInSentItems' => array('type' => 'string'), - 'source' => array('type' => 'container'), // or string - 'status' => array('type' => 'number'), - ), - 'RightsManagement' => array( - 'templateID' => array('type' => 'string'), - ) - ); + protected $_properties = [ + 'ComposeMail' => [ + 'accountId' => ['type' => 'string'], + 'clientId' => ['type' => 'string'], + 'mime' => ['type' => 'byteArray'], + 'replaceMime' => ['type' => 'string'], + 'saveInSentItems' => ['type' => 'string'], + 'source' => ['type' => 'container'], // or string + 'status' => ['type' => 'number'], + ], + 'RightsManagement' => [ + 'templateID' => ['type' => 'string'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/SmartReply.php b/lib/ext/Syncroton/Model/SmartReply.php index f8493a5..a8870f3 100644 --- a/lib/ext/Syncroton/Model/SmartReply.php +++ b/lib/ext/Syncroton/Model/SmartReply.php @@ -1,36 +1,36 @@ * @author Aleksander Machniak */ /** * Class to handle ActiveSync SmartReply element * * @package Syncroton * @subpackage Model */ class Syncroton_Model_SmartReply extends Syncroton_Model_AXMLEntry { - protected $_properties = array( - 'ComposeMail' => array( - 'accountId' => array('type' => 'string'), - 'clientId' => array('type' => 'string'), - 'mime' => array('type' => 'byteArray'), - 'replaceMime' => array('type' => 'string'), - 'saveInSentItems' => array('type' => 'string'), - 'source' => array('type' => 'container'), // or string - 'status' => array('type' => 'number'), - ), - 'RightsManagement' => array( - 'templateID' => array('type' => 'string'), - ) - ); + protected $_properties = [ + 'ComposeMail' => [ + 'accountId' => ['type' => 'string'], + 'clientId' => ['type' => 'string'], + 'mime' => ['type' => 'byteArray'], + 'replaceMime' => ['type' => 'string'], + 'saveInSentItems' => ['type' => 'string'], + 'source' => ['type' => 'container'], // or string + 'status' => ['type' => 'number'], + ], + 'RightsManagement' => [ + 'templateID' => ['type' => 'string'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/StoreRequest.php b/lib/ext/Syncroton/Model/StoreRequest.php index a04db19..afcc4ca 100644 --- a/lib/ext/Syncroton/Model/StoreRequest.php +++ b/lib/ext/Syncroton/Model/StoreRequest.php @@ -1,247 +1,247 @@ * @author Aleksander Machniak */ /** * class to handle ActiveSync Search Store request * * @package Syncroton * @subpackage Model * @property string $name * @property array $options * @property array $query */ class Syncroton_Model_StoreRequest { - protected $_store = array(); + protected $_store = []; protected $_xmlStore; public function __construct($properties = null) { if ($properties instanceof SimpleXMLElement) { $this->setFromSimpleXMLElement($properties); } elseif (is_array($properties)) { $this->setFromArray($properties); } } public function setFromArray(array $properties) { - $this->_store = array( - 'options' => array( + $this->_store = [ + 'options' => [ 'mimeSupport' => Syncroton_Command_Sync::MIMESUPPORT_DONT_SEND_MIME, - 'bodyPreferences' => array() - ), - ); + 'bodyPreferences' => [], + ], + ]; foreach ($properties as $key => $value) { try { $this->$key = $value; //echo __LINE__ . PHP_EOL; } catch (InvalidArgumentException $iae) { //ignore invalid properties //echo __LINE__ . PHP_EOL; } } } /** * * @param SimpleXMLElement $xmlStore * @throws InvalidArgumentException */ public function setFromSimpleXMLElement(SimpleXMLElement $xmlStore) { if ($xmlStore->getName() !== 'Store') { throw new InvalidArgumentException('Unexpected element name: ' . $xmlStore->getName()); } $this->_xmlStore = $xmlStore; - $this->_store = array( + $this->_store = [ 'name' => (string) $xmlStore->Name, - 'options' => array( + 'options' => [ 'mimeSupport' => Syncroton_Command_Sync::MIMESUPPORT_DONT_SEND_MIME, - 'bodyPreferences' => array(), - ), - ); + 'bodyPreferences' => [], + ], + ]; // Process Query if ($this->_store['name'] == 'GAL') { // @FIXME: In GAL search request Query is a string: // GALstring0-11 if (isset($xmlStore->Query)) { $this->_store['query'] = (string) $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; } if (isset($xmlStore->Query->And->ConversationId)) { $this->_store['query']['and']['conversationId'] = (string) $xmlStore->Query->And->ConversationId; } // Protocol specification defines Value as string and DateReceived as datetime, but // PocketPC device I tested sends XML as follows: // // // 2012-08-02T16:54:11.000Z // if (isset($xmlStore->Query->And->GreaterThan)) { if (isset($xmlStore->Query->And->GreaterThan->Value)) { $value = (string) $xmlStore->Query->And->GreaterThan->Value; $this->_store['query']['and']['greaterThan']['value'] = new DateTime($value, new DateTimeZone('UTC')); } $email = $xmlStore->Query->And->GreaterThan->children('uri:Email'); if (isset($email->DateReceived)) { $this->_store['query']['and']['greaterThan']['dateReceived'] = true; } } if (isset($xmlStore->Query->And->LessThan)) { if (isset($xmlStore->Query->And->LessThan->Value)) { $value = (string) $xmlStore->Query->And->LessThan->Value; $this->_store['query']['and']['lessThan']['value'] = new DateTime($value, new DateTimeZone('UTC')); } $email = $xmlStore->Query->And->LessThan->children('uri:Email'); if (isset($email->DateReceived)) { $this->_store['query']['and']['leasThan']['dateReceived'] = true; } } $airSync = $xmlStore->Query->And->children('uri:AirSync'); foreach ($airSync as $name => $value) { if ($name == 'Class') { $this->_store['query']['and']['classes'][] = (string) $value; } elseif ($name == 'CollectionId') { $this->_store['query']['and']['collections'][] = (string) $value; } } } if (isset($xmlStore->Query->EqualTo)) { if (isset($xmlStore->Query->EqualTo->Value)) { $this->_store['query']['equalTo']['value'] = (string) $xmlStore->Query->EqualTo->Value; } $doclib = $xmlStore->Query->EqualTo->children('uri:DocumentLibrary'); if (isset($doclib->LinkId)) { $this->_store['query']['equalTo']['linkId'] = (string) $doclib->LinkId; } } } // Process options if (isset($xmlStore->Options)) { // optional parameters if (isset($xmlStore->Options->DeepTraversal)) { $this->_store['options']['deepTraversal'] = true; } if (isset($xmlStore->Options->RebuildResults)) { $this->_store['options']['rebuildResults'] = true; } if (isset($xmlStore->Options->UserName)) { $this->_store['options']['userName'] = (string) $xmlStore->Options->UserName; } if (isset($xmlStore->Options->Password)) { $this->_store['options']['password'] = (string) $xmlStore->Options->Password; } if (isset($xmlStore->Options->Picture)) { if (isset($xmlStore->Options->Picture->MaxSize)) { $this->_store['options']['picture']['maxSize'] = (int) $xmlStore->Options->Picture->MaxSize; } if (isset($xmlStore->Options->Picture->MaxPictures)) { $this->_store['options']['picture']['maxPictures'] = (int) $xmlStore->Options->Picture->MaxPictures; } } if (!empty($xmlStore->Options->Range)) { $this->_store['options']['range'] = (string) $xmlStore->Options->Range; } else { switch ($this->_store['name']) { - case 'DocumentLibrary': - case 'Document Library': //? - $this->_store['options']['range'] = '0-999'; - break; - case 'Mailbox': - case 'GAL': - default: - $this->_store['options']['range'] = '0-99'; - break; + case 'DocumentLibrary': + case 'Document Library': //? + $this->_store['options']['range'] = '0-999'; + break; + case 'Mailbox': + case 'GAL': + default: + $this->_store['options']['range'] = '0-99'; + break; } } $this->_store['options']['range'] = explode('-', $this->_store['options']['range']); if (isset($xmlStore->Options->MIMESupport)) { $this->_store['options']['mimeSupport'] = (int) $xmlStore->Options->MIMESupport; } -/* - if (isset($xmlStore->Options->MIMETruncation)) { - $this->_store['options']['mimeTruncation'] = (int)$xmlStore->Options->MIMETruncation; - } -*/ + /* + if (isset($xmlStore->Options->MIMETruncation)) { + $this->_store['options']['mimeTruncation'] = (int)$xmlStore->Options->MIMETruncation; + } + */ // try to fetch element from AirSyncBase:BodyPreference $airSyncBase = $xmlStore->Options->children('uri:AirSyncBase'); if (isset($airSyncBase->BodyPreference)) { foreach ($airSyncBase->BodyPreference as $bodyPreference) { $type = (int) $bodyPreference->Type; - $this->_store['options']['bodyPreferences'][$type] = array( - 'type' => $type - ); + $this->_store['options']['bodyPreferences'][$type] = [ + 'type' => $type, + ]; // optional if (isset($bodyPreference->TruncationSize)) { $this->_store['options']['bodyPreferences'][$type]['truncationSize'] = (int) $bodyPreference->TruncationSize; } } } if (isset($airSyncBase->BodyPartPreference)) { // process BodyPartPreference elements } } } public function &__get($name) { if (array_key_exists($name, $this->_store)) { return $this->_store[$name]; } //echo $name . PHP_EOL; return null; } public function __set($name, $value) { $this->_store[$name] = $value; } public function __isset($name) { return isset($this->_store[$name]); } public function __unset($name) { unset($this->_store[$name]); } -} \ No newline at end of file +} diff --git a/lib/ext/Syncroton/Model/StoreResponse.php b/lib/ext/Syncroton/Model/StoreResponse.php index eeb14eb..af2d3f0 100644 --- a/lib/ext/Syncroton/Model/StoreResponse.php +++ b/lib/ext/Syncroton/Model/StoreResponse.php @@ -1,93 +1,94 @@ */ /** * Class to handle ActiveSync Search/Response/Store element * * @package Syncroton * @subpackage Model * * @property int $status * @property array $result * @property array $range * @property int $total */ class Syncroton_Model_StoreResponse extends Syncroton_Model_AXMLEntry { /** * status constants */ - const STATUS_SUCCESS = 1; - const STATUS_INVALIDREQUEST = 2; - const STATUS_SERVERERROR = 3; - const STATUS_BADLINK = 4; - const STATUS_ACCESSDENIED = 5; - const STATUS_NOTFOUND = 6; - const STATUS_CONNECTIONFAILED = 7; - const STATUS_TOOCOMPLEX = 8; - const STATUS_TIMEDOUT = 10; - const STATUS_FOLDERSYNCREQUIRED = 11; - const STATUS_ENDOFRANGE = 12; - const STATUS_ACCESSBLOCKED = 13; - const STATUS_CREDENTIALSREQUIRED = 14; + public const STATUS_SUCCESS = 1; + public const STATUS_INVALIDREQUEST = 2; + public const STATUS_SERVERERROR = 3; + public const STATUS_BADLINK = 4; + public const STATUS_ACCESSDENIED = 5; + public const STATUS_NOTFOUND = 6; + public const STATUS_CONNECTIONFAILED = 7; + public const STATUS_TOOCOMPLEX = 8; + public const STATUS_TIMEDOUT = 10; + public const STATUS_FOLDERSYNCREQUIRED = 11; + public const STATUS_ENDOFRANGE = 12; + public const STATUS_ACCESSBLOCKED = 13; + public const STATUS_CREDENTIALSREQUIRED = 14; protected $_xmlBaseElement = 'Store'; - protected $_properties = array( - 'Search' => array( - 'status' => array('type' => 'number'), - 'result' => array('type' => 'container', 'multiple' => true), - 'range' => array('type' => 'string'), - 'total' => array('type' => 'number'), - ) - ); + protected $_properties = [ + 'Search' => [ + 'status' => ['type' => 'number'], + 'result' => ['type' => 'container', 'multiple' => true], + 'range' => ['type' => 'string'], + 'total' => ['type' => 'number'], + ], + ]; /** * (non-PHPdoc) * @see Syncroton_Model_AXMLEntry::appendXML() */ public function appendXML(DOMElement $_domParrent, Syncroton_Model_IDevice $device) { $this->_addXMLNamespaces($_domParrent); foreach ($this->_elements as $elementName => $value) { // skip empty values if ($value === null || $value === '') { continue; } - list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName); + [$nameSpace, $elementProperties] = $this->_getElementProperties($elementName); $nameSpace = 'uri:' . $nameSpace; switch ($elementName) { case 'result': foreach ($value as $result) { $element = $_domParrent->ownerDocument->createElementNS($nameSpace, 'Result'); $result->appendXML($element, $device); $_domParrent->appendChild($element); } break; case 'range': if (is_array($value) && count($value) == 2) { $value = implode('-', $value); } + // no break default: $element = $_domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementName)); $element->appendChild($_domParrent->ownerDocument->createTextNode($value)); $_domParrent->appendChild($element); } } } } diff --git a/lib/ext/Syncroton/Model/StoreResponseResult.php b/lib/ext/Syncroton/Model/StoreResponseResult.php index 2405d54..696b970 100644 --- a/lib/ext/Syncroton/Model/StoreResponseResult.php +++ b/lib/ext/Syncroton/Model/StoreResponseResult.php @@ -1,32 +1,32 @@ */ /** * class to handle ActiveSync Search/Response/Store/Result elements * * @package Syncroton * @subpackage Model */ class Syncroton_Model_StoreResponseResult extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'Result'; - protected $_properties = array( - 'AirSync' => array( - 'class' => array('type' => 'string'), - 'collectionId' => array('type' => 'string'), - ), - 'Search' => array( - 'longId' => array('type' => 'string', 'supportedSince' => '2.5'), - 'properties' => array('type' => 'container', 'supportedSince' => '2.5'), - ) - ); + protected $_properties = [ + 'AirSync' => [ + 'class' => ['type' => 'string'], + 'collectionId' => ['type' => 'string'], + ], + 'Search' => [ + 'longId' => ['type' => 'string', 'supportedSince' => '2.5'], + 'properties' => ['type' => 'container', 'supportedSince' => '2.5'], + ], + ]; } diff --git a/lib/ext/Syncroton/Model/SyncCollection.php b/lib/ext/Syncroton/Model/SyncCollection.php index 0cbd0fb..9680ae0 100644 --- a/lib/ext/Syncroton/Model/SyncCollection.php +++ b/lib/ext/Syncroton/Model/SyncCollection.php @@ -1,323 +1,323 @@ */ /** * class to handle ActiveSync Sync collection * * @package Syncroton * @subpackage Model * * @property string $class * @property string $collectionId * @property bool $deletesAsMoves * @property Syncroton_Model_IFolder $folder * @property bool $getChanges * @property array $options * @property int $syncKey * @property ?Syncroton_Model_ISyncState $syncState * @property array $toBeFetched * @property int $windowSize */ class Syncroton_Model_SyncCollection extends Syncroton_Model_AXMLEntry { - protected $_elements = array( + protected $_elements = [ 'syncState' => null, - 'folder' => null - ); - + 'folder' => null, + ]; + protected $_xmlCollection; - + protected $_xmlBaseElement = 'Collection'; - - public function __construct($properties = null) - { - if ($properties instanceof SimpleXMLElement) { - $this->setFromSimpleXMLElement($properties); - } elseif (is_array($properties)) { - $this->setFromArray($properties); + + public function __construct($properties = null) + { + if ($properties instanceof SimpleXMLElement) { + $this->setFromSimpleXMLElement($properties); + } elseif (is_array($properties)) { + $this->setFromArray($properties); } - + if (!isset($this->_elements['options'])) { - $this->_elements['options'] = array(); + $this->_elements['options'] = []; } if (!isset($this->_elements['options']['filterType'])) { $this->_elements['options']['filterType'] = Syncroton_Command_Sync::FILTER_NOTHING; } if (!isset($this->_elements['options']['mimeSupport'])) { $this->_elements['options']['mimeSupport'] = Syncroton_Command_Sync::MIMESUPPORT_DONT_SEND_MIME; } if (!isset($this->_elements['options']['mimeTruncation'])) { $this->_elements['options']['mimeTruncation'] = Syncroton_Command_Sync::TRUNCATE_NOTHING; } - if (!isset($this->_elements['options']['bodyPreferences'])) { - $this->_elements['options']['bodyPreferences'] = array(); + if (!isset($this->_elements['options']['bodyPreferences'])) { + $this->_elements['options']['bodyPreferences'] = []; } - } - + } + /** * return XML element which holds all client Add commands - * + * * @return SimpleXMLElement */ public function getClientAdds() { if (! $this->_xmlCollection instanceof SimpleXMLElement) { throw new InvalidArgumentException('no collection xml element set'); } - + return $this->_xmlCollection->Commands->Add; } - + /** * return XML element which holds all client Change commands - * + * * @return SimpleXMLElement */ public function getClientChanges() { if (! $this->_xmlCollection instanceof SimpleXMLElement) { throw new InvalidArgumentException('no collection xml element set'); } - + return $this->_xmlCollection->Commands->Change; } - + /** * return XML element which holds all client Delete commands - * + * * @return SimpleXMLElement */ public function getClientDeletes() { if (! $this->_xmlCollection instanceof SimpleXMLElement) { throw new InvalidArgumentException('no collection xml element set'); } - + return $this->_xmlCollection->Commands->Delete; } - + /** * return XML element which holds all client Fetch commands - * + * * @return SimpleXMLElement */ public function getClientFetches() { if (! $this->_xmlCollection instanceof SimpleXMLElement) { throw new InvalidArgumentException('no collection xml element set'); } - + return $this->_xmlCollection->Commands->Fetch; } - + /** * check if client sent a Add command - * + * * @throws InvalidArgumentException * @return bool */ public function hasClientAdds() { if (! $this->_xmlCollection instanceof SimpleXMLElement) { return false; } - + return isset($this->_xmlCollection->Commands->Add); } - + /** * check if client sent a Change command - * + * * @throws InvalidArgumentException * @return bool */ public function hasClientChanges() { if (! $this->_xmlCollection instanceof SimpleXMLElement) { return false; } - + return isset($this->_xmlCollection->Commands->Change); } - + /** * check if client sent a Delete command - * + * * @throws InvalidArgumentException * @return bool */ public function hasClientDeletes() { if (! $this->_xmlCollection instanceof SimpleXMLElement) { return false; } - + return isset($this->_xmlCollection->Commands->Delete); } - + /** * check if client sent a Fetch command - * + * * @throws InvalidArgumentException * @return bool */ public function hasClientFetches() { if (! $this->_xmlCollection instanceof SimpleXMLElement) { return false; } - + return isset($this->_xmlCollection->Commands->Fetch); } - + /** * this functions does not only set from SimpleXMLElement but also does merge from SimpleXMLElement * to support partial sync requests - * + * * @param SimpleXMLElement $properties * @throws InvalidArgumentException */ public function setFromSimpleXMLElement(SimpleXMLElement $properties) { if (!in_array($properties->getName(), (array) $this->_xmlBaseElement)) { throw new InvalidArgumentException('Unexpected element name: ' . $properties->getName()); } - + $this->_xmlCollection = $properties; - + if (isset($properties->CollectionId)) { $this->_elements['collectionId'] = (string)$properties->CollectionId; } - + if (isset($properties->SyncKey)) { $this->_elements['syncKey'] = (int)$properties->SyncKey; } - + if (isset($properties->Class)) { $this->_elements['class'] = (string)$properties->Class; } elseif (!array_key_exists('class', $this->_elements)) { $this->_elements['class'] = null; } - + if (isset($properties->WindowSize)) { $this->_elements['windowSize'] = (string)$properties->WindowSize; } elseif (!array_key_exists('windowSize', $this->_elements)) { $this->_elements['windowSize'] = 100; } - + if (isset($properties->DeletesAsMoves)) { if ((string)$properties->DeletesAsMoves === '0') { $this->_elements['deletesAsMoves'] = false; } else { $this->_elements['deletesAsMoves'] = true; } } elseif (!array_key_exists('deletesAsMoves', $this->_elements)) { $this->_elements['deletesAsMoves'] = true; } - + if (isset($properties->ConversationMode)) { if ((string)$properties->ConversationMode === '0') { $this->_elements['conversationMode'] = false; } else { $this->_elements['conversationMode'] = true; } } elseif (!array_key_exists('conversationMode', $this->_elements)) { $this->_elements['conversationMode'] = true; } - + if (isset($properties->GetChanges)) { if ((string)$properties->GetChanges === '0') { $this->_elements['getChanges'] = false; } else { $this->_elements['getChanges'] = true; } } elseif (!array_key_exists('getChanges', $this->_elements)) { $this->_elements['getChanges'] = true; } - + if (isset($properties->Supported)) { // @todo collect supported elements } - - // process options + + // process options if (isset($properties->Options)) { - $this->_elements['options'] = array(); - - // optional parameters - if (isset($properties->Options->FilterType)) { - $this->_elements['options']['filterType'] = (int)$properties->Options->FilterType; - } - if (isset($properties->Options->MIMESupport)) { - $this->_elements['options']['mimeSupport'] = (int)$properties->Options->MIMESupport; - } - if (isset($properties->Options->MIMETruncation)) { - $this->_elements['options']['mimeTruncation'] = (int)$properties->Options->MIMETruncation; + $this->_elements['options'] = []; + + // optional parameters + if (isset($properties->Options->FilterType)) { + $this->_elements['options']['filterType'] = (int)$properties->Options->FilterType; + } + if (isset($properties->Options->MIMESupport)) { + $this->_elements['options']['mimeSupport'] = (int)$properties->Options->MIMESupport; } - if (isset($properties->Options->Class)) { - $this->_elements['options']['class'] = (string)$properties->Options->Class; - } - - // try to fetch element from AirSyncBase:BodyPreference - $airSyncBase = $properties->Options->children('uri:AirSyncBase'); - - if (isset($airSyncBase->BodyPreference)) { - - foreach ($airSyncBase->BodyPreference as $bodyPreference) { - $type = (int) $bodyPreference->Type; - $this->_elements['options']['bodyPreferences'][$type] = array( - 'type' => $type - ); - - // optional - if (isset($bodyPreference->TruncationSize)) { - $this->_elements['options']['bodyPreferences'][$type]['truncationSize'] = (int) $bodyPreference->TruncationSize; + if (isset($properties->Options->MIMETruncation)) { + $this->_elements['options']['mimeTruncation'] = (int)$properties->Options->MIMETruncation; + } + if (isset($properties->Options->Class)) { + $this->_elements['options']['class'] = (string)$properties->Options->Class; + } + + // try to fetch element from AirSyncBase:BodyPreference + $airSyncBase = $properties->Options->children('uri:AirSyncBase'); + + if (isset($airSyncBase->BodyPreference)) { + + foreach ($airSyncBase->BodyPreference as $bodyPreference) { + $type = (int) $bodyPreference->Type; + $this->_elements['options']['bodyPreferences'][$type] = [ + 'type' => $type, + ]; + + // optional + if (isset($bodyPreference->TruncationSize)) { + $this->_elements['options']['bodyPreferences'][$type]['truncationSize'] = (int) $bodyPreference->TruncationSize; + } + + // optional + if (isset($bodyPreference->Preview)) { + $this->_elements['options']['bodyPreferences'][$type]['preview'] = (int) $bodyPreference->Preview; } - - // optional - if (isset($bodyPreference->Preview)) { - $this->_elements['options']['bodyPreferences'][$type]['preview'] = (int) $bodyPreference->Preview; - } } } - + if (isset($airSyncBase->BodyPartPreference)) { // process BodyPartPreference elements } - } + } } - + public function toArray() { - $result = array(); - - foreach (array('syncKey', 'collectionId', 'deletesAsMoves', 'conversationMode', 'getChanges', 'windowSize', 'class', 'options') as $key) { + $result = []; + + foreach (['syncKey', 'collectionId', 'deletesAsMoves', 'conversationMode', 'getChanges', 'windowSize', 'class', 'options'] as $key) { if (isset($this->$key)) { $result[$key] = $this->$key; } } - + return $result; } - + public function &__get($name) { - if (array_key_exists($name, $this->_elements)) { - return $this->_elements[$name]; + if (array_key_exists($name, $this->_elements)) { + return $this->_elements[$name]; } echo $name . PHP_EOL; - return null; + return null; } - + public function __set($name, $value) { $this->_elements[$name] = $value; } -} \ No newline at end of file +} diff --git a/lib/ext/Syncroton/Model/SyncState.php b/lib/ext/Syncroton/Model/SyncState.php index 41e64fb..edef56f 100644 --- a/lib/ext/Syncroton/Model/SyncState.php +++ b/lib/ext/Syncroton/Model/SyncState.php @@ -1,21 +1,20 @@ */ /** * class to handle ActiveSync Sync command * * @package Syncroton * @subpackage Model */ class Syncroton_Model_SyncState extends Syncroton_Model_AEntry implements Syncroton_Model_ISyncState { } - diff --git a/lib/ext/Syncroton/Model/Task.php b/lib/ext/Syncroton/Model/Task.php index da2a93b..a4c9bd1 100644 --- a/lib/ext/Syncroton/Model/Task.php +++ b/lib/ext/Syncroton/Model/Task.php @@ -1,50 +1,50 @@ */ /** * class to handle ActiveSync task * * @package Syncroton * @subpackage Model * @property string $class * @property string $collectionId * @property bool $deletesAsMoves * @property bool $getChanges * @property string $syncKey * @property DateTime $utcDueDate * @property DateTime $utcStartDate * @property int $windowSize */ class Syncroton_Model_Task extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'ApplicationData'; - - protected $_properties = array( - 'AirSyncBase' => array( - 'body' => array('type' => 'container', 'class' => 'Syncroton_Model_EmailBody') - ), - 'Tasks' => array( - 'categories' => array('type' => 'container', 'childElement' => 'category'), - 'complete' => array('type' => 'number'), - 'dateCompleted' => array('type' => 'datetime'), - 'dueDate' => array('type' => 'datetime'), - 'importance' => array('type' => 'number'), - 'recurrence' => array('type' => 'container'), - 'reminderSet' => array('type' => 'number'), - 'reminderTime' => array('type' => 'datetime'), - 'sensitivity' => array('type' => 'number'), - 'startDate' => array('type' => 'datetime'), - 'subject' => array('type' => 'string'), - 'utcDueDate' => array('type' => 'datetime'), - 'utcStartDate' => array('type' => 'datetime'), - ) - ); -} \ No newline at end of file + + protected $_properties = [ + 'AirSyncBase' => [ + 'body' => ['type' => 'container', 'class' => 'Syncroton_Model_EmailBody'], + ], + 'Tasks' => [ + 'categories' => ['type' => 'container', 'childElement' => 'category'], + 'complete' => ['type' => 'number'], + 'dateCompleted' => ['type' => 'datetime'], + 'dueDate' => ['type' => 'datetime'], + 'importance' => ['type' => 'number'], + 'recurrence' => ['type' => 'container'], + 'reminderSet' => ['type' => 'number'], + 'reminderTime' => ['type' => 'datetime'], + 'sensitivity' => ['type' => 'number'], + 'startDate' => ['type' => 'datetime'], + 'subject' => ['type' => 'string'], + 'utcDueDate' => ['type' => 'datetime'], + 'utcStartDate' => ['type' => 'datetime'], + ], + ]; +} diff --git a/lib/ext/Syncroton/Model/TaskRecurrence.php b/lib/ext/Syncroton/Model/TaskRecurrence.php index d8c0713..71c7480 100644 --- a/lib/ext/Syncroton/Model/TaskRecurrence.php +++ b/lib/ext/Syncroton/Model/TaskRecurrence.php @@ -1,67 +1,67 @@ */ /** * class to handle ActiveSync event * * @package Syncroton * @subpackage Model * @property string $class * @property string $collectionId * @property bool $deletesAsMoves * @property bool $getChanges * @property string $syncKey * @property int $windowSize */ class Syncroton_Model_TaskRecurrence extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'Recurrence'; - + /** * recur types */ - const TYPE_DAILY = 0; // Recurs daily. - const TYPE_WEEKLY = 1; // Recurs weekly - const TYPE_MONTHLY = 2; // Recurs monthly - const TYPE_MONTHLY_DAYN = 3; // Recurs monthly on the nth day - const TYPE_YEARLY = 5; // Recurs yearly - const TYPE_YEARLY_DAYN = 6; // Recurs yearly on the nth day - + public const TYPE_DAILY = 0; // Recurs daily. + public const TYPE_WEEKLY = 1; // Recurs weekly + public const TYPE_MONTHLY = 2; // Recurs monthly + public const TYPE_MONTHLY_DAYN = 3; // Recurs monthly on the nth day + public const TYPE_YEARLY = 5; // Recurs yearly + public const TYPE_YEARLY_DAYN = 6; // Recurs yearly on the nth day + /** * day of week constants */ - const RECUR_DOW_SUNDAY = 1; - const RECUR_DOW_MONDAY = 2; - const RECUR_DOW_TUESDAY = 4; - const RECUR_DOW_WEDNESDAY = 8; - const RECUR_DOW_THURSDAY = 16; - const RECUR_DOW_FRIDAY = 32; - const RECUR_DOW_SATURDAY = 64; - - protected $_properties = array( - 'Tasks' => array( - 'calendarType' => array('type' => 'number'), - 'dayOfMonth' => array('type' => 'number'), - 'dayOfWeek' => array('type' => 'number'), - 'deadOccur' => array('type' => 'number'), - 'firstDayOfWeek' => array('type' => 'number'), - 'interval' => array('type' => 'number'), - 'isLeapMonth' => array('type' => 'number'), - 'monthOfYear' => array('type' => 'number'), - 'occurrences' => array('type' => 'number'), - 'regenerate' => array('type' => 'number'), - 'start' => array('type' => 'datetime'), - 'type' => array('type' => 'number'), - 'until' => array('type' => 'datetime'), - 'weekOfMonth' => array('type' => 'number'), - ) - ); -} \ No newline at end of file + public const RECUR_DOW_SUNDAY = 1; + public const RECUR_DOW_MONDAY = 2; + public const RECUR_DOW_TUESDAY = 4; + public const RECUR_DOW_WEDNESDAY = 8; + public const RECUR_DOW_THURSDAY = 16; + public const RECUR_DOW_FRIDAY = 32; + public const RECUR_DOW_SATURDAY = 64; + + protected $_properties = [ + 'Tasks' => [ + 'calendarType' => ['type' => 'number'], + 'dayOfMonth' => ['type' => 'number'], + 'dayOfWeek' => ['type' => 'number'], + 'deadOccur' => ['type' => 'number'], + 'firstDayOfWeek' => ['type' => 'number'], + 'interval' => ['type' => 'number'], + 'isLeapMonth' => ['type' => 'number'], + 'monthOfYear' => ['type' => 'number'], + 'occurrences' => ['type' => 'number'], + 'regenerate' => ['type' => 'number'], + 'start' => ['type' => 'datetime'], + 'type' => ['type' => 'number'], + 'until' => ['type' => 'datetime'], + 'weekOfMonth' => ['type' => 'number'], + ], + ]; +} diff --git a/lib/ext/Syncroton/Registry.php b/lib/ext/Syncroton/Registry.php index 3f2641a..884d86d 100644 --- a/lib/ext/Syncroton/Registry.php +++ b/lib/ext/Syncroton/Registry.php @@ -1,521 +1,521 @@ offsetExists($index)) { require_once 'Zend/Exception.php'; throw new Zend_Exception("No entry is registered for key '$index'"); } return $instance->offsetGet($index); } - + /** * returns content state backend - * + * * creates Syncroton_Backend_Content on the fly if not before via * Syncroton_Registry::set(self::CONTENTSTATEBACKEND, $backend); - * + * * @return Syncroton_Backend_IContent */ public static function getContentStateBackend() { if (!self::isRegistered(self::CONTENTSTATEBACKEND)) { self::set(self::CONTENTSTATEBACKEND, new Syncroton_Backend_Content(self::getDatabase())); } - + return self::get(self::CONTENTSTATEBACKEND); } /** * returns device backend - * + * * creates Syncroton_Backend_Device on the fly if not before via * Syncroton_Registry::set(self::DEVICEBACKEND, $backend); - * + * * @return Syncroton_Backend_IDevice */ public static function getDeviceBackend() { if (!self::isRegistered(self::DEVICEBACKEND)) { self::set(self::DEVICEBACKEND, new Syncroton_Backend_Device(self::getDatabase())); } - + return self::get(self::DEVICEBACKEND); } /** * returns folder backend - * + * * creates Syncroton_Backend_Folder on the fly if not before via * Syncroton_Registry::set(self::FOLDERBACKEND, $backend); - * + * * @return Syncroton_Backend_IFolder */ public static function getFolderBackend() { if (!self::isRegistered(self::FOLDERBACKEND)) { self::set(self::FOLDERBACKEND, new Syncroton_Backend_Folder(self::getDatabase())); } - + return self::get(self::FOLDERBACKEND); } - + /** * Return maximum ping interval (HeartbeatInterval) value (in seconds) * * @return int */ public static function getPingInterval() { if (!self::isRegistered(self::PING_INTERVAL)) { return 3540; // 59 minutes limit defined in Activesync protocol spec. } return self::get(self::PING_INTERVAL); } - + /** /** * Return maximum ping interval (HeartbeatInterval) value (in seconds) * * @return int */ public static function getMaxPingInterval() { if (!self::isRegistered(self::MAX_PING_INTERVAL)) { return Syncroton_Command_Ping::MAX_PING_INTERVAL; } return self::get(self::MAX_PING_INTERVAL); } /** - * return ping timeout - * - * sleep "ping timeout" seconds between folder checks in Ping and Sync command - * + * return ping timeout + * + * sleep "ping timeout" seconds between folder checks in Ping and Sync command + * * @return int */ public static function getPingTimeout() { if (!self::isRegistered(self::PING_TIMEOUT)) { return 60; } - + return self::get(self::PING_TIMEOUT); } - + /** * Return maximum number of collections in Sync/Ping request * * @return int */ public static function getMaxCollections() { return self::get(self::MAX_COLLECTIONS); } /** * returns policy backend - * + * * creates Syncroton_Backend_Policy on the fly if not set before via * Syncroton_Registry::set(self::POLICYBACKEND, $backend); - * + * * @return Syncroton_Backend_Policy */ public static function getPolicyBackend() { if (!self::isRegistered(self::POLICYBACKEND)) { self::set(self::POLICYBACKEND, new Syncroton_Backend_Policy(self::getDatabase())); } - + return self::get(self::POLICYBACKEND); } /** - * return quiet time - * - * don't check folders if last sync was "quiet time" seconds ago - * + * return quiet time + * + * don't check folders if last sync was "quiet time" seconds ago + * * @return int */ public static function getQuietTime() { if (!self::isRegistered(self::QUIET_TIME)) { return 180; } - + return self::get(self::QUIET_TIME); } - + /** * Returns sleep callback function * * This function is used in long running requests like ping & sync to * close connections to external sources (e.g. database) before we * call sleep() to wait some time for next iteration. * Callback should throw exceptions on errors. * * @return callable */ public static function getSleepCallback() { if (!self::isRegistered(self::SLEEP_CALLBACK)) { - self::set(self::SLEEP_CALLBACK, function() {}); + self::set(self::SLEEP_CALLBACK, function () {}); } return self::get(self::SLEEP_CALLBACK); } /** * Returns wakeup callback function * * This function is used in long running requests like ping & sync to * re-connect to external sources (e.g. database) closed by sleep callback. * Callback should throw exceptions on errors. * * @return callable */ public static function getWakeupCallback() { if (!self::isRegistered(self::WAKEUP_CALLBACK)) { - self::set(self::WAKEUP_CALLBACK, function() {}); + self::set(self::WAKEUP_CALLBACK, function () {}); } return self::get(self::WAKEUP_CALLBACK); } /** * return session validation function * * This function is used in long running requests like ping & sync to * validate user session. Returns false if session is not valid any longer * * @return callable */ public static function getSessionValidator() { if (!self::isRegistered(self::SESSION_VALIDATOR)) { - self::set(self::SESSION_VALIDATOR, function() { + self::set(self::SESSION_VALIDATOR, function () { return true; }); } return self::get(self::SESSION_VALIDATOR); } /** * returns syncstate backend - * + * * creates Syncroton_Backend_SyncState on the fly if not before via * Syncroton_Registry::set(self::SYNCSTATEBACKEND, $backend); - * + * * @return Syncroton_Backend_ISyncState */ public static function getSyncStateBackend() { if (!self::isRegistered(self::SYNCSTATEBACKEND)) { self::set(self::SYNCSTATEBACKEND, new Syncroton_Backend_SyncState(self::getDatabase())); } - + return self::get(self::SYNCSTATEBACKEND); } /** * setter method, basically same as offsetSet(). * * This method can be called from an object of type Syncroton_Registry, or it * can be called statically. In the latter case, it uses the default * static instance stored in the class. * * @param string $index The location in the ArrayObject in which to store * the value. * @param mixed $value The object to store in the ArrayObject. * @return void */ public static function set($index, $value) { $instance = self::getInstance(); $instance->offsetSet($index, $value); } public static function setDatabase(Zend_Db_Adapter_Abstract $db) { self::set(self::DATABASE, $db); } - + public static function setCalendarDataClass($className) { if (!class_exists($className)) { throw new InvalidArgumentException('invalid $_className provided'); } - + self::set(self::CALENDAR_DATA_CLASS, $className); } - + public static function setContactsDataClass($className) { if (!class_exists($className)) { throw new InvalidArgumentException('invalid $_className provided'); } - + self::set(self::CONTACTS_DATA_CLASS, $className); } - + public static function setEmailDataClass($className) { if (!class_exists($className)) { throw new InvalidArgumentException('invalid $_className provided'); } - + self::set(self::EMAIL_DATA_CLASS, $className); } - + public static function setNotesDataClass($className) { if (!class_exists($className)) { throw new InvalidArgumentException('invalid $_className provided'); } self::set(self::NOTES_DATA_CLASS, $className); } public static function setTasksDataClass($className) { if (!class_exists($className)) { throw new InvalidArgumentException('invalid $_className provided'); } - + self::set(self::TASKS_DATA_CLASS, $className); } public static function setGALDataClass($className) { if (!class_exists($className)) { throw new InvalidArgumentException('invalid $_className provided'); } self::set(self::GAL_DATA_CLASS, $className); } public static function setTransactionManager($manager) { self::set(self::TRANSACTIONMANAGER, $manager); } - + /** * Returns TRUE if the $index is a named value in the registry, * or FALSE if $index was not found in the registry. * * @param string $index * @return boolean */ public static function isRegistered($index) { if (self::$_registry === null) { return false; } return self::$_registry->offsetExists($index); } /** * Constructs a parent ArrayObject with default * ARRAY_AS_PROPS to allow acces as an object * * @param array $array data array * @param integer $flags ArrayObject flags */ - public function __construct($array = array(), $flags = parent::ARRAY_AS_PROPS) + public function __construct($array = [], $flags = parent::ARRAY_AS_PROPS) { parent::__construct($array, $flags); } } diff --git a/lib/ext/Syncroton/Server.php b/lib/ext/Syncroton/Server.php index 24f0ff6..8bb3160 100644 --- a/lib/ext/Syncroton/Server.php +++ b/lib/ext/Syncroton/Server.php @@ -1,463 +1,472 @@ */ /** * class to handle incoming http ActiveSync requests - * + * * @package Syncroton */ class Syncroton_Server { - const PARAMETER_ATTACHMENTNAME = 0; - const PARAMETER_COLLECTIONID = 1; - const PARAMETER_ITEMID = 3; - const PARAMETER_OPTIONS = 7; - const MAX_HEARTBEAT_INTERVAL = 3540; // 59 minutes - + public const PARAMETER_ATTACHMENTNAME = 0; + public const PARAMETER_COLLECTIONID = 1; + public const PARAMETER_ITEMID = 3; + public const PARAMETER_OPTIONS = 7; + public const MAX_HEARTBEAT_INTERVAL = 3540; // 59 minutes + protected $_body; - + /** * informations about the currently device * * @var Syncroton_Backend_IDevice */ protected $_deviceBackend; - + /** * @var Zend_Log */ protected $_logger; - + /** * @var Zend_Controller_Request_Http */ protected $_request; - + protected $_userId; - + public function __construct($userId, Zend_Controller_Request_Http $request = null, $body = null) { if (Syncroton_Registry::isRegistered('loggerBackend')) { $this->_logger = Syncroton_Registry::get('loggerBackend'); } - + $this->_userId = $userId; $this->_request = $request instanceof Zend_Controller_Request_Http ? $request : new Zend_Controller_Request_Http(); $this->_body = $body !== null ? $body : fopen('php://input', 'r'); - + $this->_deviceBackend = Syncroton_Registry::getDeviceBackend(); - + } - + public function handle() { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . ' REQUEST METHOD: ' . $this->_request->getMethod()); - + } + switch($this->_request->getMethod()) { case 'OPTIONS': $this->_handleOptions(); break; - + case 'POST': $this->_handlePost(); break; - + case 'GET': echo "It works!
Your userid is: {$this->_userId} and your IP address is: {$_SERVER['REMOTE_ADDR']}."; break; } } - + /** * handle options request */ protected function _handleOptions() { $command = new Syncroton_Command_Options(); - + $this->_sendHeaders($command->getHeaders()); } - + protected function _sendHeaders(array $headers) { foreach ($headers as $name => $value) { header($name . ': ' . $value); } - } - + } + /** * handle post request */ protected function _handlePost() { $requestParameters = $this->_getRequestParameters($this->_request); - - if ($this->_logger instanceof Zend_Log) + + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . ' REQUEST ' . print_r($requestParameters, true)); - + } + $className = 'Syncroton_Command_' . $requestParameters['command']; - + if (!class_exists($className)) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->notice(__METHOD__ . '::' . __LINE__ . " command not supported: " . $requestParameters['command']); - + } + header("HTTP/1.1 501 not implemented"); - + return; } - + // get user device $device = $this->_getUserDevice($this->_userId, $requestParameters); - + 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); $requestBody = $decoder->decode(); if ($this->_logger instanceof Zend_Log) { $this->_logDomDocument($requestBody, 'request', __METHOD__, __LINE__); } } catch(Syncroton_Wbxml_Exception_UnexpectedEndOfFile $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " unexpected end of file."); - $requestBody = NULL; + } + $requestBody = null; } } else { $requestBody = $this->_body; } - + header("MS-Server-ActiveSync: 14.00.0536.000"); // avoid sending HTTP header "Content-Type: text/html" for empty sync responses ini_set('default_mimetype', 'application/vnd.ms-sync.wbxml'); - + try { $command = new $className($requestBody, $device, $requestParameters); - + $response = $command->handle(); if (!$response) { $response = $command->getResponse(); } } catch (Syncroton_Exception_ProvisioningNeeded $sepn) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " provisioning needed"); - + } + header("HTTP/1.1 449 Retry after sending a PROVISION command"); - + if (version_compare($device->acsversion, '14.0', '>=')) { $response = $sepn->domDocument; } else { // pre 14.0 method return; } - + } catch (Exception $e) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->err(__METHOD__ . '::' . __LINE__ . " unexpected exception occured: " . get_class($e)); - if ($this->_logger instanceof Zend_Log) + } + if ($this->_logger instanceof Zend_Log) { $this->_logger->err(__METHOD__ . '::' . __LINE__ . " exception message: " . $e->getMessage()); - if ($this->_logger instanceof Zend_Log) + } + if ($this->_logger instanceof Zend_Log) { $this->_logger->err(__METHOD__ . '::' . __LINE__ . " " . $e->getTraceAsString()); - + } + header("HTTP/1.1 500 Internal server error"); - + return; } - + if ($response instanceof DOMDocument) { if ($this->_logger instanceof Zend_Log) { $this->_logDomDocument($response, 'response', __METHOD__, __LINE__); } - + if (isset($command) && $command instanceof Syncroton_Command_ICommand) { $this->_sendHeaders($command->getHeaders()); } - + $outputStream = fopen("php://temp", 'r+'); - + $encoder = new Syncroton_Wbxml_Encoder($outputStream, 'UTF-8', 3); - + try { - $encoder->encode($response); + $encoder->encode($response); } catch (Syncroton_Wbxml_Exception $swe) { if ($this->_logger instanceof Zend_Log) { $this->_logger->err(__METHOD__ . '::' . __LINE__ . " Could not encode output: " . $swe); } - + header("HTTP/1.1 500 Internal server error"); - + return; } - + if ($requestParameters['acceptMultipart'] == true && isset($command)) { $parts = $command->getParts(); - + // output multipartheader $bodyPartCount = 1 + count($parts); - + // number of parts (4 bytes) $header = pack('i', $bodyPartCount); - + $partOffset = 4 + (($bodyPartCount * 2) * 4); - + // wbxml body start and length $streamStat = fstat($outputStream); $header .= pack('ii', $partOffset, $streamStat['size']); - + $partOffset += $streamStat['size']; - + // calculate start and length of parts foreach ($parts as $partId => $partStream) { rewind($partStream); $streamStat = fstat($partStream); - + // part start and length $header .= pack('ii', $partOffset, $streamStat['size']); $partOffset += $streamStat['size']; } - + echo $header; } - + // output body rewind($outputStream); fpassthru($outputStream); - + // output multiparts if (isset($parts)) { foreach ($parts as $partStream) { rewind($partStream); fpassthru($partStream); } } } } - + /** * write (possible big) DOMDocument in smaller chunks to log file - * + * * @param DOMDocument $dom * @param string $action * @param string $method * @param int $line */ protected function _logDomDocument(DOMDocument $dom, $action, $method, $line) { if (method_exists($this->_logger, 'hasDebug') && !$this->_logger->hasDebug()) { return; } $tempStream = tmpfile(); $meta_data = stream_get_meta_data($tempStream); $filename = $meta_data["uri"]; - + $dom->formatOutput = true; $dom->save($filename); $dom->formatOutput = false; - + rewind($tempStream); $loops = 0; while (!feof($tempStream)) { $this->_logger->debug("{$method}::{$line} xml {$action} ({$loops}):\n" . fread($tempStream, 1048576)); $loops++; } - + fclose($tempStream); } - + /** * return request params - * + * * @return array */ protected function _getRequestParameters(Zend_Controller_Request_Http $request) { if (strpos($request->getRequestUri(), '&') === false) { - $commands = array( + $commands = [ 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' - ); - + 22 => 'ValidateCert', + ]; + $requestParameters = substr($request->getRequestUri(), strpos($request->getRequestUri(), '?')); $stream = fopen("php://temp", 'r+'); fwrite($stream, base64_decode($requestParameters)); rewind($stream); // unpack the first 4 bytes $unpacked = unpack('CprotocolVersion/Ccommand/vlocale', fread($stream, 4)); - + // 140 => 14.0 $protocolVersion = substr($unpacked['protocolVersion'], 0, -1) . '.' . substr($unpacked['protocolVersion'], -1); $command = $commands[$unpacked['command']]; $locale = $unpacked['locale']; $deviceId = null; - + // unpack deviceId $length = ord(fread($stream, 1)); if ($length > 0) { $toUnpack = fread($stream, $length); - + $unpacked = unpack("H" . ($length * 2) . "string", $toUnpack); $deviceId = $unpacked['string']; } - + // 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']; } - + while (! feof($stream)) { $tag = ord(fread($stream, 1)); $length = ord(fread($stream, 1)); // If the stream is at the end we'll get a 0-length if (!$length) { continue; } switch ($tag) { case self::PARAMETER_ATTACHMENTNAME: $unpacked = unpack('A' . $length . 'string', fread($stream, $length)); - + $attachmentName = $unpacked['string']; break; - + case self::PARAMETER_COLLECTIONID: $unpacked = unpack('A' . $length . 'string', fread($stream, $length)); - + $collectionId = $unpacked['string']; break; - + case self::PARAMETER_ITEMID: $unpacked = unpack('A' . $length . 'string', fread($stream, $length)); - + $itemId = $unpacked['string']; break; - + case self::PARAMETER_OPTIONS: $options = ord(fread($stream, 1)); - - $saveInSent = !!($options & 0x01); + + $saveInSent = !!($options & 0x01); $acceptMultiPart = !!($options & 0x02); break; - + default: - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->crit(__METHOD__ . '::' . __LINE__ . " found unhandled command parameters"); - + } + } } - - $result = array( + + $result = [ 'protocolVersion' => $protocolVersion, 'command' => $command, 'deviceId' => $deviceId, - '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, - 'acceptMultipart' => isset($acceptMultiPart) ? $acceptMultiPart : false - ); + 'deviceType' => $deviceType ?? null, + 'policyKey' => $policyKey ?? null, + 'saveInSent' => $saveInSent ?? false, + 'collectionId' => $collectionId ?? null, + 'itemId' => $itemId ?? null, + 'attachmentName' => $attachmentName ?? null, + 'acceptMultipart' => $acceptMultiPart ?? false, + ]; } else { - $result = array( + $result = [ 'protocolVersion' => $request->getServer('HTTP_MS_ASPROTOCOLVERSION'), 'command' => $request->getQuery('Cmd'), 'deviceId' => $request->getQuery('DeviceId'), 'deviceType' => $request->getQuery('DeviceType'), 'policyKey' => $request->getServer('HTTP_X_MS_POLICYKEY'), 'saveInSent' => $request->getQuery('SaveInSent') == 'T', 'collectionId' => $request->getQuery('CollectionId'), 'itemId' => $request->getQuery('ItemId'), 'attachmentName' => $request->getQuery('AttachmentName'), - 'acceptMultipart' => $request->getServer('HTTP_MS_ASACCEPTMULTIPART') == 'T' - ); + 'acceptMultipart' => $request->getServer('HTTP_MS_ASACCEPTMULTIPART') == 'T', + ]; } - + $result['userAgent'] = $request->getServer('HTTP_USER_AGENT', $result['deviceType']); $result['contentType'] = $request->getServer('CONTENT_TYPE'); - + return $result; } - + /** * get existing device of owner or create new device for owner * * @param string $ownerId * @param array $requestParameters * * @return Syncroton_Model_IDevice */ protected function _getUserDevice($ownerId, $requestParameters) { try { $device = $this->_deviceBackend->getUserDevice($ownerId, $requestParameters['deviceId']); - + $device->useragent = $requestParameters['userAgent']; $device->acsversion = $requestParameters['protocolVersion']; $device->devicetype = $requestParameters['deviceType']; - + if ($device->isDirty()) { $device = $this->_deviceBackend->update($device); } - + } catch (Syncroton_Exception_NotFound $senf) { - $device = $this->_deviceBackend->create(new Syncroton_Model_Device(array( + $device = $this->_deviceBackend->create(new Syncroton_Model_Device([ 'owner_id' => $ownerId, 'deviceid' => $requestParameters['deviceId'], 'devicetype' => $requestParameters['deviceType'], 'useragent' => $requestParameters['userAgent'], 'acsversion' => $requestParameters['protocolVersion'], - 'policyId' => Syncroton_Registry::isRegistered(Syncroton_Registry::DEFAULT_POLICY) ? Syncroton_Registry::get(Syncroton_Registry::DEFAULT_POLICY) : null - ))); + 'policyId' => Syncroton_Registry::isRegistered(Syncroton_Registry::DEFAULT_POLICY) ? Syncroton_Registry::get(Syncroton_Registry::DEFAULT_POLICY) : null, + ])); } /** @var Syncroton_Model_Device $device */ return $device; } public static function validateSession() { $validatorFunction = Syncroton_Registry::getSessionValidator(); return $validatorFunction(); } } diff --git a/lib/ext/Syncroton/TransactionManager.php b/lib/ext/Syncroton/TransactionManager.php index 3f3690c..f8ca11e 100644 --- a/lib/ext/Syncroton/TransactionManager.php +++ b/lib/ext/Syncroton/TransactionManager.php @@ -1,168 +1,175 @@ */ /** * Transaction Manger for Syncroton - * + * * This is the central class, all transactions within Syncroton must be handled with. - * For each supported transactionable (backend) this class start a real transaction on + * For each supported transactionable (backend) this class start a real transaction on * the first startTransaction request. - * + * * Transactions of all transactionable will be commited at once when all requested transactions * are being commited using this class. - * + * * Transactions of all transactionable will be roll back when one rollBack is requested * using this class. - * + * * @package Syncroton */ class Syncroton_TransactionManager implements Syncroton_TransactionManagerInterface { /** * @var array holds all transactionables with open transactions */ - protected $_openTransactionables = array(); - + protected $_openTransactionables = []; + /** * @var array list of all open (not commited) transactions */ - protected $_openTransactions = array(); + protected $_openTransactions = []; /** * @var ?Syncroton_TransactionManager */ - private static $_instance = NULL; - + private static $_instance = null; + /** * @var Zend_Log */ protected $_logger; - + /** * don't clone. Use the singleton. */ private function __clone() { - + } /** * constructor */ private function __construct() { if (Syncroton_Registry::isRegistered('loggerBackend')) { $this->_logger = Syncroton_Registry::get('loggerBackend'); } } - + /** * @return Syncroton_TransactionManager */ - public static function getInstance() + public static function getInstance() { - if (self::$_instance === NULL) { - self::$_instance = new Syncroton_TransactionManager; + if (self::$_instance === null) { + self::$_instance = new Syncroton_TransactionManager(); } - + return self::$_instance; } - + /** * starts a transaction * * @param mixed $_transactionable * @return string transactionId * @throws Exception */ public function startTransaction($_transactionable) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " startTransaction request"); - + } + if (! in_array($_transactionable, $this->_openTransactionables)) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " new transactionable. Starting transaction on this resource"); - + } + if ($_transactionable instanceof Zend_Db_Adapter_Abstract) { #Tinebase_Backend_Sql_Command::setAutocommit($_transactionable,false); $_transactionable->beginTransaction(); } else { $this->rollBack(); throw new Syncroton_Exception_UnexpectedValue('Unsupported transactionable!'); } - + array_push($this->_openTransactionables, $_transactionable); } - - $transactionId = sha1(mt_rand(). microtime()); + + $transactionId = sha1(mt_rand() . microtime()); array_push($this->_openTransactions, $transactionId); - - if ($this->_logger instanceof Zend_Log) + + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " queued transaction with id $transactionId"); - + } + return $transactionId; } - + /** * commits a transaction * * @param string $_transactionId * @return void */ public function commitTransaction($_transactionId) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " commitTransaction request for $_transactionId"); - + } + $transactionIdx = array_search($_transactionId, $this->_openTransactions); if ($transactionIdx !== false) { unset($this->_openTransactions[$transactionIdx]); } - + $numOpenTransactions = count($this->_openTransactions); - + if ($numOpenTransactions === 0) { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " no more open transactions in queue commiting all transactionables"); + } foreach ($this->_openTransactionables as $transactionableIdx => $transactionable) { if ($transactionable instanceof Zend_Db_Adapter_Abstract) { $transactionable->commit(); #Tinebase_Backend_Sql_Command::setAutocommit($transactionable,true); } } - $this->_openTransactionables = array(); - $this->_openTransactions = array(); + $this->_openTransactionables = []; + $this->_openTransactions = []; } else { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " commiting defered, as there are still $numOpenTransactions in the queue"); + } } } - + /** * perform rollBack on all transactionables with open transactions - * + * * @return void */ public function rollBack() { - if ($this->_logger instanceof Zend_Log) + if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " rollBack request, rollBack all transactionables"); - + } + foreach ($this->_openTransactionables as $transactionable) { if ($transactionable instanceof Zend_Db_Adapter_Abstract) { $transactionable->rollBack(); #Tinebase_Backend_Sql_Command::setAutocommit($transactionable,true); } } - - $this->_openTransactionables = array(); - $this->_openTransactions = array(); + + $this->_openTransactionables = []; + $this->_openTransactions = []; } } diff --git a/lib/ext/Syncroton/TransactionManagerInterface.php b/lib/ext/Syncroton/TransactionManagerInterface.php index 7ea94d3..44110b5 100644 --- a/lib/ext/Syncroton/TransactionManagerInterface.php +++ b/lib/ext/Syncroton/TransactionManagerInterface.php @@ -1,56 +1,56 @@ */ /** * Transaction Manger for Syncroton - * + * * This is the central class, all transactions within Syncroton must be handled with. - * For each supported transactionable (backend) this class start a real transaction on + * For each supported transactionable (backend) this class start a real transaction on * the first startTransaction request. - * + * * Transactions of all transactionable will be commited at once when all requested transactions * are being commited using this class. - * + * * Transactions of all transactionable will be roll back when one rollBack is requested * using this class. - * + * * @package Syncroton */ interface Syncroton_TransactionManagerInterface { /** * @return mixed */ public static function getInstance(); - + /** * starts a transaction * * @param mixed $_transactionable * @return string transactionId * @throws Exception */ public function startTransaction($_transactionable); - + /** * commits a transaction * * @param string $_transactionId * @return void */ public function commitTransaction($_transactionId); - + /** * perform rollBack on all transactionables with open transactions - * + * * @return void */ public function rollBack(); } diff --git a/lib/ext/Syncroton/Wbxml/Abstract.php b/lib/ext/Syncroton/Wbxml/Abstract.php index 13656f8..8af7d7b 100644 --- a/lib/ext/Syncroton/Wbxml/Abstract.php +++ b/lib/ext/Syncroton/Wbxml/Abstract.php @@ -1,256 +1,256 @@ * @version $Id:Abstract.php 4968 2008-10-17 09:09:33Z l.kneschke@metaways.de $ */ /** * class documentation * * @package Wbxml * @subpackage Wbxml */ - + abstract class Syncroton_Wbxml_Abstract { /** * stream containing the wbxml encoded data * * @var resource */ protected $_stream; - + /** * the wbxml version * * @var int */ protected $_version; - + /** - * the Document Public Identifier + * the Document Public Identifier * * @var string */ protected $_dpi; - + /** * the current active dtd * * @var Syncroton_Wbxml_Dtd_ActiveSync */ protected $_dtd; - + /** * the charSet used in the wbxml file * * @var string */ protected $_charSet; - + /** * currently active code page * * @var Syncroton_Wbxml_Dtd_ActiveSync_Abstract */ protected $_codePage; - + /** * see section 5.5 * */ - const DPI_WELLKNOWN = 'WELLKNOWN'; - + public const DPI_WELLKNOWN = 'WELLKNOWN'; + /** * see section 5.5 * */ - const DPI_STRINGTABLE = 'STRINGTABLE'; - - const SWITCH_PAGE = 0x00; - const END = 0x01; - const ENTITY = 0x02; - const STR_I = 0x03; - const LITERAL = 0x04; - const EXT_I_0 = 0x40; - const EXT_I_1 = 0x41; - const EXT_I_2 = 0x42; - const PI = 0x43; - const LITERAL_C = 0x44; - const EXT_T_0 = 0x80; - const EXT_T_1 = 0x81; - const EXT_T_2 = 0x82; - const STR_T = 0x83; - const LITERAL_A = 0x84; - const EXT_0 = 0xC0; - const EXT_1 = 0xC1; - const EXT_2 = 0xC2; - const OPAQUE = 0xC3; - const LITERAL_AC = 0xC4; - + public const DPI_STRINGTABLE = 'STRINGTABLE'; + + public const SWITCH_PAGE = 0x00; + public const END = 0x01; + public const ENTITY = 0x02; + public const STR_I = 0x03; + public const LITERAL = 0x04; + public const EXT_I_0 = 0x40; + public const EXT_I_1 = 0x41; + public const EXT_I_2 = 0x42; + public const PI = 0x43; + public const LITERAL_C = 0x44; + public const EXT_T_0 = 0x80; + public const EXT_T_1 = 0x81; + public const EXT_T_2 = 0x82; + public const STR_T = 0x83; + public const LITERAL_A = 0x84; + public const EXT_0 = 0xC0; + public const EXT_1 = 0xC1; + public const EXT_2 = 0xC2; + public const OPAQUE = 0xC3; + public const LITERAL_AC = 0xC4; + /** * the real name for this DPI is "unknown" * But Microsoft is using them for their ActiveSync stuff * instead defining their own DPI like the sycnml creators did * */ - const DPI_1 = '-//AIRSYNC//DTD AirSync//EN'; - + public const DPI_1 = '-//AIRSYNC//DTD AirSync//EN'; + /** * return wellknown identifiers * * @param integer $_uInt * @todo add well known identifiers from section 7.2 * @return string */ public function getDPI($_uInt = 0) { if(!defined('Syncroton_Wbxml_Abstract::DPI_' . $_uInt)) { throw new Syncroton_Wbxml_Exception('unknown wellknown identifier: ' . $_uInt); } - + $dpi = constant('Syncroton_Wbxml_Abstract::DPI_' . $_uInt); - + return $dpi; } - + /** * return multibyte integer * * @return integer */ protected function _getMultibyteUInt() { $uInt = 0; - + do { $byte = $this->_getByte(); $uInt <<= 7; $uInt += ($byte & 127); } while (($byte & 128) != 0); - + return $uInt; } - + protected function _getByte() { $byte = fread($this->_stream, 1); - + if($byte === false) { throw new Syncroton_Wbxml_Exception("failed reading one byte"); } - + return ord($byte); } - + protected function _getOpaque($_length) { $string = ''; // it might happen that not complete data is read from stream. // loop until all data is read or EOF while ($_length) { $chunk = fread($this->_stream, $_length); if ($chunk === false) { throw new Syncroton_Wbxml_Exception("failed reading opaque data"); } if ($len = strlen($chunk)) { $string .= $chunk; $_length -= $len; } - + if (feof($this->_stream)) { break; } } return $string; } - + /** * get a 0 terminated string * * @return string */ protected function _getTerminatedString() { $string = ''; - + while (($byte = $this->_getByte()) != 0) { $string .= chr($byte); - } - + } + return $string; } - + protected function _writeByte($_byte) { fwrite($this->_stream, chr($_byte)); } - + protected function _writeMultibyteUInt($_integer) { - $multibyte = NULL; + $multibyte = null; $remainder = $_integer; - + do { $byte = ($remainder & 127); $remainder >>= 7; - if($multibyte === NULL) { + if($multibyte === null) { $multibyte = chr($byte); } else { $multibyte = chr($byte | 128) . $multibyte; } } while ($remainder != 0); fwrite($this->_stream, $multibyte); } - + protected function _writeString($_string) { fwrite($this->_stream, $_string); } - + /** * write opaque string to stream - * + * * @param string|resource $_string * @throws Syncroton_Wbxml_Exception */ protected function _writeOpaqueString($_string) { if (is_resource($_string)) { $stream = $_string; } else { $stream = fopen("php://temp", 'r+'); fwrite($stream, $_string); } $length = ftell($stream); rewind($stream); - - $this->_writeByte(Syncroton_Wbxml_Abstract::OPAQUE); + + $this->_writeByte(Syncroton_Wbxml_Abstract::OPAQUE); $this->_writeMultibyteUInt($length); - $writenBytes = stream_copy_to_stream($stream, $this->_stream); - - if($writenBytes !== $length) { - throw new Syncroton_Wbxml_Exception('blow'); + $writenBytes = stream_copy_to_stream($stream, $this->_stream); + + if($writenBytes !== $length) { + throw new Syncroton_Wbxml_Exception('blow'); } - + fclose($stream); } - + protected function _writeTerminatedString($_string) { $this->_writeByte(Syncroton_Wbxml_Abstract::STR_I); fwrite($this->_stream, $_string); fwrite($this->_stream, chr(0)); } -} \ No newline at end of file +} diff --git a/lib/ext/Syncroton/Wbxml/Decoder.php b/lib/ext/Syncroton/Wbxml/Decoder.php index 99dfbf1..ec5f80c 100644 --- a/lib/ext/Syncroton/Wbxml/Decoder.php +++ b/lib/ext/Syncroton/Wbxml/Decoder.php @@ -1,304 +1,304 @@ * @version $Id:Decoder.php 4968 2008-10-17 09:09:33Z l.kneschke@metaways.de $ */ /** * class to convert WBXML to XML * * @package Wbxml * @subpackage Wbxml */ - + class Syncroton_Wbxml_Decoder extends Syncroton_Wbxml_Abstract { /** - * type of Document Public Identifier + * type of Document Public Identifier * * @var string the type can be Syncroton_Wbxml_Abstract::DPI_STRINGTABLE or Syncroton_Wbxml_Abstract::DPI_WELLKNOWN */ protected $_dpiType; - + /** * the string table * * @var array */ - protected $_stringTable = array(); - + protected $_stringTable = []; + /** * the xml document * * @var DOMDocument */ protected $_dom; - + /** * the main name space / aka the namespace of first tag * * @var string */ protected $_mainNameSpace; /** * the constructor will try to read all data until the first tag * * @param resource $_stream */ - public function __construct($_stream, $_dpi = NULL) + public function __construct($_stream, $_dpi = null) { if(!is_resource($_stream) || get_resource_type($_stream) != 'stream') { throw new Syncroton_Wbxml_Exception('$_stream must be a stream'); } - if($_dpi !== NULL) { + if($_dpi !== null) { $this->_dpi = $_dpi; } - + $this->_stream = $_stream; - + $this->_version = $this->_getByte(); - + if(feof($this->_stream)) { throw new Syncroton_Wbxml_Exception_UnexpectedEndOfFile(); } - + $this->_getDPI(); - + $this->_getCharset(); - + $this->_getStringTable(); - + // resolve DPI as we have read the stringtable now // this->_dpi contains the string table index if($this->_dpiType === Syncroton_Wbxml_Abstract::DPI_STRINGTABLE) { $this->_dpi = $this->_stringTable[$this->_dpi]; } - + #$this->_dtd = Syncroton_Wbxml_Dtd_Factory::factory($this->_dpi); $this->_dtd = Syncroton_Wbxml_Dtd_Factory::factory(Syncroton_Wbxml_Dtd_Factory::ACTIVESYNC); } - + /** * return the Document Public Identifier * * @param integer $_uInt unused param, needed to satisfy abstract class method signature * @return string */ public function getDPI($_uInt = 0) { return $this->_dpi; } - + /** * return the wbxml version * * @return int */ public function getVersion() { return $this->_version; } - + /** - * decodes the tags + * decodes the tags * * @return DOMDocument the decoded xml */ public function decode() { - $openTags = NULL; - $node = NULL; + $openTags = null; + $node = null; $this->_codePage = $this->_dtd->getCurrentCodePage(); - + while (!feof($this->_stream)) { $byte = $this->_getByte(); - + switch($byte) { case Syncroton_Wbxml_Abstract::END: $node = $node->parentNode; $openTags--; break; - + case Syncroton_Wbxml_Abstract::OPAQUE: $length = $this->_getMultibyteUInt(); if($length > 0) { $opaque = $this->_getOpaque($length); try { // let see if we can decode it. maybe the opaque data is wbxml encoded content $opaqueDataStream = fopen("php://temp", 'r+'); - fputs($opaqueDataStream, $opaque); + fwrite($opaqueDataStream, $opaque); rewind($opaqueDataStream); - + $opaqueContentDecoder = new Syncroton_Wbxml_Decoder($opaqueDataStream); $dom = $opaqueContentDecoder->decode(); - + fclose($opaqueDataStream); - + foreach($dom->childNodes as $newNode) { if($newNode instanceof DOMElement) { $newNode = $this->_dom->importNode($newNode, true); $node->appendChild($newNode); } } } catch (Exception $e) { // if not, just treat it as a string - $node->appendChild($this->_dom->createTextNode($opaque)); + $node->appendChild($this->_dom->createTextNode($opaque)); } } break; - + case Syncroton_Wbxml_Abstract::STR_I: $string = $this->_getTerminatedString(); - $node->appendChild($this->_dom->createTextNode($string)); + $node->appendChild($this->_dom->createTextNode($string)); break; - + case Syncroton_Wbxml_Abstract::SWITCH_PAGE: $page = $this->_getByte(); $this->_codePage = $this->_dtd->switchCodePage($page); #echo "switched to codepage $page\n"; break; - + default: $tagHasAttributes = (($byte & 0x80) != 0); $tagHasContent = (($byte & 0x40) != 0); // get rid of bit 7+8 $tagHexCode = $byte & 0x3F; try { $tag = $this->_codePage->getTag($tagHexCode); } catch (Syncroton_Wbxml_Exception $swe) { // tag can not be converted to ASCII name $tag = sprintf('unknown tag 0x%x', $tagHexCode); } $nameSpace = $this->_codePage->getNameSpace(); $codePageName = $this->_codePage->getCodePageName(); - + #echo "Tag: $nameSpace:$tag\n"; - - if ($node === NULL) { + + if ($node === null) { // create the domdocument $node = $this->_createDomDocument($nameSpace, $tag); $newNode = $node->documentElement; } else { if (!$this->_dom->isDefaultNamespace($nameSpace)) { $this->_dom->documentElement->setAttribute('xmlns:' . $codePageName, $nameSpace); } $newNode = $node->appendChild($this->_dom->createElementNS('uri:' . $codePageName, $tag)); } - + if ($tagHasAttributes) { $attributes = $this->_getAttributes(); } - + if ($tagHasContent == true) { $node = $newNode; $openTags++; } - + break; } } return $this->_dom; } - + /** * creates the root of the xml document * * @return DOMDocument */ protected function _createDomDocument($_nameSpace, $_tag) { $this->_dom = $this->_dtd->getDomDocument($_nameSpace, $_tag); - + return $this->_dom; } /** * read the attributes of the current tag * * @todo implement logic */ protected function _getAttributes() { die("fetching attributes not yet implemented!\n"); } /** * get document public identifier * * the identifier can be all welknown identifier (see section 7.2) or a string from the stringtable */ protected function _getDPI() { $uInt = $this->_getMultibyteUInt(); - + if($uInt == 0) { // get identifier from stringtable $this->_dpiType = Syncroton_Wbxml_Abstract::DPI_STRINGTABLE; // string table identifier, can be resolved only after reading string table $this->_dpi = $this->_getByte(); } else { // wellknown identifier $this->_dpiType = Syncroton_Wbxml_Abstract::DPI_WELLKNOWN; $this->_dpi = Syncroton_Wbxml_Abstract::getDPI($uInt); } } - + /** * see http://www.iana.org/assignments/character-sets (MIBenum) * 106: UTF-8 */ protected function _getCharset() { $uInt = $this->_getMultibyteUInt(); - + switch($uInt) { case 106: $this->_charSet = 'UTF-8'; break; default: throw new Syncroton_Wbxml_Exception('unsuported charSet: ' . $uInt); } } - + /** * get string table and store strings indexed by start * * @todo validate spliting at 0 value */ protected function _getStringTable() { $length = $this->_getMultibyteUInt(); - + if($length > 0) { $rawStringTable = $this->_getOpaque($length); - $index = NULL; - $string = NULL; - + $index = null; + $string = null; + for($i = 0; $i < strlen($rawStringTable); $i++) { - if($index === NULL) { + if($index === null) { $index = $i; } if(ord($rawStringTable[$i]) != 0) { $string .= $rawStringTable[$i]; } - + // either the string has ended or we reached a \0 - if($i+1 == strlen($rawStringTable) || ord($rawStringTable[$i]) == 0){ + if($i + 1 == strlen($rawStringTable) || ord($rawStringTable[$i]) == 0) { $this->_stringTable[$index] = $string; - $index = NULL; - $string = NULL; + $index = null; + $string = null; } } } - } -} \ No newline at end of file + } +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync.php index fb4768e..c8ba69f 100755 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync.php @@ -1,110 +1,110 @@ * @version $Id:Factory.php 4968 2008-10-17 09:09:33Z l.kneschke@metaways.de $ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ class Syncroton_Wbxml_Dtd_ActiveSync { - const CODEPAGE_AIRSYNC = 0; - const CODEPAGE_CONTACTS = 1; - const CODEPAGE_EMAIL = 2; - const CODEPAGE_AIRNOTIFY = 3; - const CODEPAGE_CALENDAR = 4; - const CODEPAGE_MOVE = 5; - const CODEPAGE_ITEMESTIMATE = 6; - const CODEPAGE_FOLDERHIERARCHY = 7; - const CODEPAGE_MEETINGRESPONSE = 8; - const CODEPAGE_TASKS = 9; - const CODEPAGE_RESOLVERECIPIENTS = 10; - const CODEPAGE_VALIDATECERT = 11; - const CODEPAGE_CONTACTS2 = 12; - const CODEPAGE_PING = 13; - const CODEPAGE_PROVISION = 14; - const CODEPAGE_SEARCH = 15; - const CODEPAGE_GAL = 16; - const CODEPAGE_AIRSYNCBASE = 17; - const CODEPAGE_SETTINGS = 18; - const CODEPAGE_DOCUMENTLIBRARY = 19; - const CODEPAGE_ITEMOPERATIONS = 20; - const CODEPAGE_COMPOSEMAIL = 21; - const CODEPAGE_EMAIL2 = 22; - const CODEPAGE_NOTES = 23; - const CODEPAGE_RIGHTSMANAGEMENT = 24; - + public const CODEPAGE_AIRSYNC = 0; + public const CODEPAGE_CONTACTS = 1; + public const CODEPAGE_EMAIL = 2; + public const CODEPAGE_AIRNOTIFY = 3; + public const CODEPAGE_CALENDAR = 4; + public const CODEPAGE_MOVE = 5; + public const CODEPAGE_ITEMESTIMATE = 6; + public const CODEPAGE_FOLDERHIERARCHY = 7; + public const CODEPAGE_MEETINGRESPONSE = 8; + public const CODEPAGE_TASKS = 9; + public const CODEPAGE_RESOLVERECIPIENTS = 10; + public const CODEPAGE_VALIDATECERT = 11; + public const CODEPAGE_CONTACTS2 = 12; + public const CODEPAGE_PING = 13; + public const CODEPAGE_PROVISION = 14; + public const CODEPAGE_SEARCH = 15; + public const CODEPAGE_GAL = 16; + public const CODEPAGE_AIRSYNCBASE = 17; + public const CODEPAGE_SETTINGS = 18; + public const CODEPAGE_DOCUMENTLIBRARY = 19; + public const CODEPAGE_ITEMOPERATIONS = 20; + public const CODEPAGE_COMPOSEMAIL = 21; + public const CODEPAGE_EMAIL2 = 22; + public const CODEPAGE_NOTES = 23; + public const CODEPAGE_RIGHTSMANAGEMENT = 24; + /** * variable to hold currently active codepage * * @var Syncroton_Wbxml_Dtd_ActiveSync_Abstract */ protected $_currentCodePage; - + /** * the constructor * */ public function __construct() { $this->_currentCodePage = new Syncroton_Wbxml_Dtd_ActiveSync_CodePage0(); } - + /** * returns reference to current codepage * * @return Syncroton_Wbxml_Dtd_ActiveSync_Abstract */ - public function getCurrentCodePage() + public function getCurrentCodePage() { return $this->_currentCodePage; } - + /** * switch to another codepage * * @param integer $_codePageId id of the codepage * @return Syncroton_Wbxml_Dtd_ActiveSync_Abstract */ public function switchCodePage($_codePageId) { $className = 'Syncroton_Wbxml_Dtd_ActiveSync_CodePage' . $_codePageId; - + $this->_currentCodePage = new $className(); - + return $this->_currentCodePage; } - + /** * get initial dom document * * @return DOMDocument */ public function getDomDocument($_nameSpace, $_tag) { // Creates an instance of the DOMImplementation class $imp = new DOMImplementation(); - + // Creates a DOMDocumentType instance $dtd = $imp->createDocumentType('AirSync', "-//AIRSYNC//DTD AirSync//EN", "http://www.microsoft.com/"); // Creates a DOMDocument instance $dom = $imp->createDocument($_nameSpace, $_tag, $dtd); - + $dom->encoding = 'utf-8'; $dom->formatOutput = false; - + return $dom; } -} +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/Abstract.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/Abstract.php index 60734ef..a2b7a17 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/Abstract.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/Abstract.php @@ -1,114 +1,114 @@ * @version $Id:AirSync.php 4968 2008-10-17 09:09:33Z l.kneschke@metaways.de $ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + abstract class Syncroton_Wbxml_Dtd_ActiveSync_Abstract { /** * codepage number * * @var ?integer */ - protected $_codePageNumber = NULL; - + protected $_codePageNumber = null; + /** * codepage name * * @var ?string */ - protected $_codePageName = NULL; + protected $_codePageName = null; /** * document page identifier * not needed for ActiveSync * * @var ?integer */ - protected $_dpi = NULL; - + protected $_dpi = null; + /** * mapping of tags to id's * * @var array */ - protected $_tags = array(); - + protected $_tags = []; + /** * return document page identifier * is always NULL for activesync * * @return int|null */ public function getDPI() { return $this->_dpi; } - + /** * get codepage name * * @return string */ public function getCodePageName() { return $this->_codePageName; } - + /** * get namespace identifier * * @return string */ public function getNameSpace() { return 'uri:' . $this->_codePageName; } - + /** * get tag identifier * * @param string $_tag the tag name * @return integer */ public function getIdentity($_tag) { if(!isset($this->_tags[$_tag])) { //var_dump($this->_tags); throw new Syncroton_Wbxml_Exception("tag $_tag not found"); } return $this->_tags[$_tag]; } - + /** * return tag by given identity * * @param int $_identity * @return mixed */ public function getTag($_identity) { $tag = array_search($_identity, $this->_tags); - + if($tag === false) { throw new Syncroton_Wbxml_Exception("identity $_identity not found"); } - + return $tag; } -} \ No newline at end of file +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage0.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage0.php index e039cee..8af1ead 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage0.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage0.php @@ -1,64 +1,64 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage0 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 0; - + protected $_codePageName = 'AirSync'; - - protected $_tags = array( + + protected $_tags = [ 'Sync' => 0x05, 'Responses' => 0x06, 'Add' => 0x07, 'Change' => 0x08, 'Delete' => 0x09, 'Fetch' => 0x0a, 'SyncKey' => 0x0b, 'ClientId' => 0x0c, 'ServerId' => 0x0d, 'Status' => 0x0e, 'Collection' => 0x0f, 'Class' => 0x10, 'Version' => 0x11, 'CollectionId' => 0x12, 'GetChanges' => 0x13, 'MoreAvailable' => 0x14, 'WindowSize' => 0x15, 'Commands' => 0x16, 'Options' => 0x17, 'FilterType' => 0x18, 'Truncation' => 0x19, 'RtfTruncation' => 0x1a, 'Conflict' => 0x1b, 'Collections' => 0x1c, 'ApplicationData' => 0x1d, 'DeletesAsMoves' => 0x1e, 'NotifyGUID' => 0x1f, 'Supported' => 0x20, 'SoftDelete' => 0x21, 'MIMESupport' => 0x22, 'MIMETruncation' => 0x23, 'Wait' => 0x24, 'Limit' => 0x25, 'Partial' => 0x26, 'ConversationMode' => 0x27, 'MaxItems' => 0x28, - 'HeartbeatInterval' => 0x29 - ); -} \ No newline at end of file + 'HeartbeatInterval' => 0x29, + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage1.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage1.php index 699638e..e5ea39f 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage1.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage1.php @@ -1,85 +1,85 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage1 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 1; - + protected $_codePageName = 'Contacts'; - - protected $_tags = array( + + protected $_tags = [ 'Anniversary' => 0x05, 'AssistantName' => 0x06, 'AssistantPhoneNumber' => 0x07, 'Birthday' => 0x08, 'Body' => 0x09, 'BodySize' => 0x0a, 'BodyTruncated' => 0x0b, 'Business2PhoneNumber' => 0x0c, 'BusinessAddressCity' => 0x0d, 'BusinessAddressCountry' => 0x0e, 'BusinessAddressPostalCode' => 0x0f, 'BusinessAddressState' => 0x10, 'BusinessAddressStreet' => 0x11, 'BusinessFaxNumber' => 0x12, 'BusinessPhoneNumber' => 0x13, 'CarPhoneNumber' => 0x14, 'Categories' => 0x15, 'Category' => 0x16, 'Children' => 0x17, 'Child' => 0x18, 'CompanyName' => 0x19, 'Department' => 0x1a, 'Email1Address' => 0x1b, 'Email2Address' => 0x1c, 'Email3Address' => 0x1d, 'FileAs' => 0x1e, 'FirstName' => 0x1f, 'Home2PhoneNumber' => 0x20, 'HomeAddressCity' => 0x21, 'HomeAddressCountry' => 0x22, 'HomeAddressPostalCode' => 0x23, 'HomeAddressState' => 0x24, 'HomeAddressStreet' => 0x25, 'HomeFaxNumber' => 0x26, 'HomePhoneNumber' => 0x27, 'JobTitle' => 0x28, 'LastName' => 0x29, 'MiddleName' => 0x2a, 'MobilePhoneNumber' => 0x2b, 'OfficeLocation' => 0x2c, 'OtherAddressCity' => 0x2d, 'OtherAddressCountry' => 0x2e, 'OtherAddressPostalCode' => 0x2f, 'OtherAddressState' => 0x30, 'OtherAddressStreet' => 0x31, 'PagerNumber' => 0x32, 'RadioPhoneNumber' => 0x33, 'Spouse' => 0x34, 'Suffix' => 0x35, 'Title' => 0x36, 'WebPage' => 0x37, 'YomiCompanyName' => 0x38, 'YomiFirstName' => 0x39, 'YomiLastName' => 0x3a, 'Rtf' => 0x3b, 'Picture' => 0x3c, 'Alias' => 0x3d, - 'WeightedRank' => 0x3e - ); -} \ No newline at end of file + 'WeightedRank' => 0x3e, + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage10.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage10.php index 52ea5cf..0aed7f3 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage10.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage10.php @@ -1,52 +1,52 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage10 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 10; - + protected $_codePageName = 'ResolveRecipients'; - - protected $_tags = array( + + protected $_tags = [ 'ResolveRecipients' => 0x05, 'Response' => 0x06, 'Status' => 0x07, 'Type' => 0x08, 'Recipient' => 0x09, 'DisplayName' => 0x0a, 'EmailAddress' => 0x0b, 'Certificates' => 0x0c, 'Certificate' => 0x0d, 'MiniCertificate' => 0x0e, 'Options' => 0x0f, 'To' => 0x10, 'CertificateRetrieval' => 0x11, 'RecipientCount' => 0x12, 'MaxCertificates' => 0x13, 'MaxAmbiguousRecipients' => 0x14, 'CertificateCount' => 0x15, 'Availability' => 0x16, 'StartTime' => 0x17, 'EndTime' => 0x18, 'MergedFreeBusy' => 0x19, 'Picture' => 0x1a, 'MaxSize' => 0x1b, 'Data' => 0x1c, - 'MaxPictures' => 0x1d - ); -} \ No newline at end of file + 'MaxPictures' => 0x1d, + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage11.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage11.php index 02e6171..06aab6b 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage11.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage11.php @@ -1,33 +1,33 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage11 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 11; - + protected $_codePageName = 'ValidateCert'; - - protected $_tags = array( + + protected $_tags = [ 'ValidateCert' => 0x05, 'Certificates' => 0x06, 'Certificate' => 0x07, 'CertificateChain' => 0x08, 'CheckCRL' => 0x09, - 'Status' => 0x0a - ); -} \ No newline at end of file + 'Status' => 0x0a, + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage12.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage12.php index 2607aa6..e0275a4 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage12.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage12.php @@ -1,37 +1,37 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage12 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 12; - + protected $_codePageName = 'Contacts2'; - - protected $_tags = array( + + protected $_tags = [ 'CustomerId' => 0x05, 'GovernmentId' => 0x06, 'IMAddress' => 0x07, 'IMAddress2' => 0x08, 'IMAddress3' => 0x09, 'ManagerName' => 0x0a, 'CompanyMainPhone' => 0x0b, 'AccountName' => 0x0c, 'NickName' => 0x0d, - 'MMS' => 0x0e - ); -} \ No newline at end of file + 'MMS' => 0x0e, + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage13.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage13.php index 6b909f3..f20ded3 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage13.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage13.php @@ -1,35 +1,35 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ class Syncroton_Wbxml_Dtd_ActiveSync_CodePage13 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 13; protected $_codePageName = 'Ping'; - protected $_tags = array( + protected $_tags = [ 'Ping' => 0x05, 'AutdState' => 0x06, //unused 'Status' => 0x07, 'HeartbeatInterval' => 0x08, 'Folders' => 0x09, 'Folder' => 0x0a, 'Id' => 0x0b, 'Class' => 0x0c, - 'MaxFolders' => 0x0d - ); + 'MaxFolders' => 0x0d, + ]; } diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage14.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage14.php index f34442b..d30ea51 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage14.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage14.php @@ -1,82 +1,82 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync * @todo add missing tags */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage14 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 14; - + protected $_codePageName = 'Provision'; - - protected $_tags = array( + + protected $_tags = [ 'Provision' => 0x05, 'Policies' => 0x06, 'Policy' => 0x07, 'PolicyType' => 0x08, 'PolicyKey' => 0x09, 'Data' => 0x0a, 'Status' => 0x0b, 'RemoteWipe' => 0x0c, 'EASProvisionDoc' => 0x0d, 'DevicePasswordEnabled' => 0x0e, 'AlphanumericDevicePasswordRequired' => 0x0f, 'RequireStorageCardEncryption' => 0x10, 'PasswordRecoveryEnabled' => 0x11, 'DocumentBrowseEnabled' => 0x12, 'AttachmentsEnabled' => 0x13, 'MinDevicePasswordLength' => 0x14, 'MaxInactivityTimeDeviceLock' => 0x15, 'MaxDevicePasswordFailedAttempts' => 0x16, 'MaxAttachmentSize' => 0x17, 'AllowSimpleDevicePassword' => 0x18, 'DevicePasswordExpiration' => 0x19, 'DevicePasswordHistory' => 0x1a, 'AllowStorageCard' => 0x1b, 'AllowCamera' => 0x1c, 'RequireDeviceEncryption' => 0x1d, 'AllowUnsignedApplications' => 0x1e, 'AllowUnsignedInstallationPackages' => 0x1f, 'MinDevicePasswordComplexCharacters' => 0x20, 'AllowWiFi' => 0x21, 'AllowTextMessaging' => 0x22, 'AllowPOPIMAPEmail' => 0x23, 'AllowBluetooth' => 0x24, 'AllowIrDA' => 0x25, 'RequireManualSyncWhenRoaming' => 0x26, 'AllowDesktopSync' => 0x27, 'MaxCalendarAgeFilter' => 0x28, 'AllowHTMLEmail' => 0x29, 'MaxEmailAgeFilter' => 0x2a, 'MaxEmailBodyTruncationSize' => 0x2b, 'MaxEmailHTMLBodyTruncationSize' => 0x2c, 'RequireSignedSMIMEMessages' => 0x2d, 'RequireEncryptedSMIMEMessages' => 0x2e, 'RequireSignedSMIMEAlgorithm' => 0x2F, 'RequireEncryptionSMIMEAlgorithm' => 0x30, 'AllowSMIMEEncryptionAlgorithmNegotiation' => 0x31, 'AllowSMIMESoftCerts' => 0x32, 'AllowBrowser' => 0x33, 'AllowConsumerEmail' => 0x34, 'AllowRemoteDesktop' => 0x35, 'AllowInternetSharing' => 0x36, 'UnapprovedInROMApplicationList' => 0x37, 'ApplicationName' => 0x38, 'ApprovedApplicationList' => 0x39, 'Hash' => 0x3a, - ); + ]; } diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage15.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage15.php index 57d3a91..7e1ea08 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage15.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage15.php @@ -1,56 +1,56 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage15 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 15; - + protected $_codePageName = 'Search'; - - protected $_tags = array( + + protected $_tags = [ 'Search' => 0x05, 'Store' => 0x07, 'Name' => 0x08, 'Query' => 0x09, 'Options' => 0x0a, 'Range' => 0x0b, 'Status' => 0x0c, 'Response' => 0x0d, 'Result' => 0x0e, 'Properties' => 0x0f, 'Total' => 0x10, 'EqualTo' => 0x11, 'Value' => 0x12, 'And' => 0x13, 'Or' => 0x14, 'FreeText' => 0x15, 'DeepTraversal' => 0x17, 'LongId' => 0x18, 'RebuildResults' => 0x19, 'LessThan' => 0x1a, 'GreaterThan' => 0x1b, 'Schema' => 0x1c, 'Supported' => 0x1d, 'UserName' => 0x1e, 'Password' => 0x1f, 'ConversationId' => 0x20, 'Picture' => 0x21, 'MaxSize' => 0x22, - 'MaxPictures' => 0x23 - ); -} \ No newline at end of file + 'MaxPictures' => 0x23, + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage16.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage16.php index 6df3b03..722e9cc 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage16.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage16.php @@ -1,41 +1,41 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage16 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 16; - + protected $_codePageName = 'GAL'; - - protected $_tags = array( + + protected $_tags = [ 'DisplayName' => 0x05, 'Phone' => 0x06, 'Office' => 0x07, 'Title' => 0x08, 'Company' => 0x09, 'Alias' => 0x0a, 'FirstName' => 0x0b, 'LastName' => 0x0c, 'HomePhone' => 0x0d, 'MobilePhone' => 0x0e, 'EmailAddress' => 0x0f, 'Picture' => 0x10, 'Status' => 0x11, 'Data' => 0x12, - ); -} \ No newline at end of file + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage17.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage17.php index 00527d8..e2e7dc0 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage17.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage17.php @@ -1,49 +1,49 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage17 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 17; - + protected $_codePageName = 'AirSyncBase'; - - protected $_tags = array( + + protected $_tags = [ 'BodyPreference' => 0x05, 'Type' => 0x06, 'TruncationSize' => 0x07, 'AllOrNone' => 0x08, 'Body' => 0x0a, 'Data' => 0x0b, 'EstimatedDataSize' => 0x0c, 'Truncated' => 0x0d, 'Attachments' => 0x0e, 'Attachment' => 0x0f, 'DisplayName' => 0x10, 'FileReference' => 0x11, 'Method' => 0x12, 'ContentId' => 0x13, 'ContentLocation' => 0x14, 'IsInline' => 0x15, 'NativeBodyType' => 0x16, 'ContentType' => 0x17, 'Preview' => 0x18, 'BodyPartReference' => 0x19, 'BodyPart' => 0x1a, 'Status' => 0x1b, - ); -} \ No newline at end of file + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage18.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage18.php index 0bd3383..ceba040 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage18.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage18.php @@ -1,65 +1,65 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage18 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 18; - + protected $_codePageName = 'Settings'; - - protected $_tags = array( + + protected $_tags = [ 'Settings' => 0x05, 'Status' => 0x06, 'Get' => 0x07, 'Set' => 0x08, 'Oof' => 0x09, 'OofState' => 0x0a, 'StartTime' => 0x0b, 'EndTime' => 0x0c, 'OofMessage' => 0x0d, 'AppliesToInternal' => 0x0e, 'AppliesToExternalKnown' => 0x0f, 'AppliesToExternalUnknown' => 0x10, 'Enabled' => 0x11, 'ReplyMessage' => 0x12, 'BodyType' => 0x13, 'DevicePassword' => 0x14, 'Password' => 0x15, 'DeviceInformation' => 0x16, 'Model' => 0x17, 'IMEI' => 0x18, 'FriendlyName' => 0x19, 'OS' => 0x1a, 'OSLanguage' => 0x1b, 'PhoneNumber' => 0x1c, 'UserInformation' => 0x1d, 'EmailAddresses' => 0x1e, 'SMTPAddress' => 0x1f, 'UserAgent' => 0x20, 'EnableOutboundSMS' => 0x21, 'MobileOperator' => 0x22, 'PrimarySmtpAddress' => 0x23, 'Accounts' => 0x24, 'Account' => 0x25, 'AccountId' => 0x26, 'AccountName' => 0x27, 'UserDisplayName' => 0x28, 'SendDisabled' => 0x29, 'RightsManagementInformation' => 0x2b, - ); + ]; } diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage19.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage19.php index 219f419..18f4bfd 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage19.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage19.php @@ -1,35 +1,35 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage19 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 19; - + protected $_codePageName = 'DocumentLibrary'; - - protected $_tags = array( + + protected $_tags = [ 'LinkId' => 0x05, 'DisplayName' => 0x06, 'IsFolder' => 0x07, 'CreationDate' => 0x08, 'LastModifiedDate' => 0x09, 'IsHidden' => 0x0a, 'ContentLength' => 0x0b, - 'ContentType' => 0x0c - ); -} \ No newline at end of file + 'ContentType' => 0x0c, + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage2.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage2.php index bca834c..85afdae 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage2.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage2.php @@ -1,86 +1,86 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage2 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 2; - + protected $_codePageName = 'Email'; - - protected $_tags = array( + + protected $_tags = [ 'Attachment' => 0x05, 'Attachments' => 0x06, 'AttName' => 0x07, 'AttSize' => 0x08, 'Att0Id' => 0x09, 'AttMethod' => 0x0a, 'AttRemoved' => 0x0b, 'Body' => 0x0c, 'BodySize' => 0x0d, 'BodyTruncated' => 0x0e, 'DateReceived' => 0x0f, 'DisplayName' => 0x10, 'DisplayTo' => 0x11, 'Importance' => 0x12, 'MessageClass' => 0x13, 'Subject' => 0x14, 'Read' => 0x15, 'To' => 0x16, 'Cc' => 0x17, 'From' => 0x18, 'ReplyTo' => 0x19, 'AllDayEvent' => 0x1a, 'Categories' => 0x1b, 'Category' => 0x1c, 'DTStamp' => 0x1d, 'EndTime' => 0x1e, 'InstanceType' => 0x1f, 'BusyStatus' => 0x20, 'Location' => 0x21, 'MeetingRequest' => 0x22, 'Organizer' => 0x23, 'RecurrenceId' => 0x24, 'Reminder' => 0x25, 'ResponseRequested' => 0x26, 'Recurrences' => 0x27, 'Recurrence' => 0x28, 'Type' => 0x29, 'Until' => 0x2a, 'Occurrences' => 0x2b, 'Interval' => 0x2c, 'DayOfWeek' => 0x2d, 'DayOfMonth' => 0x2e, 'WeekOfMonth' => 0x2f, 'MonthOfYear' => 0x30, 'StartTime' => 0x31, 'Sensitivity' => 0x32, 'TimeZone' => 0x33, 'GlobalObjId' => 0x34, 'ThreadTopic' => 0x35, 'MIMEData' => 0x36, 'MIMETruncated' => 0x37, 'MIMESize' => 0x38, 'InternetCPID' => 0x39, 'Flag' => 0x3a, 'Status' => 0x3b, 'ContentClass' => 0x3c, 'FlagType' => 0x3d, 'CompleteTime' => 0x3e, - 'DisallowNewTimeProposal' => 0x3f - ); -} \ No newline at end of file + 'DisallowNewTimeProposal' => 0x3f, + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage20.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage20.php index d10cc39..84f002f 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage20.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage20.php @@ -1,48 +1,48 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage20 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 20; - + protected $_codePageName = 'ItemOperations'; - - protected $_tags = array( + + protected $_tags = [ 'ItemOperations' => 0x05, 'Fetch' => 0x06, 'Store' => 0x07, 'Options' => 0x08, 'Range' => 0x09, 'Total' => 0x0a, 'Properties' => 0x0b, 'Data' => 0x0c, 'Status' => 0x0d, 'Response' => 0x0e, 'Version' => 0x0f, 'Schema' => 0x10, 'Part' => 0x11, 'EmptyFolderContents' => 0x12, 'DeleteSubFolders' => 0x13, 'UserName' => 0x14, 'Password' => 0x15, 'Move' => 0x16, 'DstFldId' => 0x17, 'ConversationId' => 0x18, 'MoveAlways' => 0x19, - ); -} \ No newline at end of file + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage21.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage21.php index 4b9a2fd..cc0bf47 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage21.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage21.php @@ -1,41 +1,41 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage21 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 21; - + protected $_codePageName = 'ComposeMail'; - - protected $_tags = array( + + protected $_tags = [ 'SendMail' => 0x05, 'SmartForward' => 0x06, 'SmartReply' => 0x07, 'SaveInSentItems' => 0x08, 'ReplaceMime' => 0x09, 'Source' => 0x0b, 'FolderId' => 0x0c, 'ItemId' => 0x0d, 'LongId' => 0x0e, 'InstanceId' => 0x0f, 'Mime' => 0x10, 'ClientId' => 0x11, 'Status' => 0x12, 'AccountId' => 0x13, - ); -} \ No newline at end of file + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage22.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage22.php index 7894eaf..083026b 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage22.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage22.php @@ -1,42 +1,42 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage22 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 22; - + protected $_codePageName = 'Email2'; - - protected $_tags = array( + + protected $_tags = [ 'UmCallerID' => 0x05, 'UmUserNotes' => 0x06, 'UmAttDuration' => 0x07, 'UmAttOrder' => 0x08, 'ConversationId' => 0x09, 'ConversationIndex' => 0x0a, 'LastVerbExecuted' => 0x0b, 'LastVerbExecutionTime' => 0x0c, 'ReceivedAsBcc' => 0x0d, 'Sender' => 0x0e, 'CalendarType' => 0x0f, 'IsLeapMonth' => 0x10, 'AccountId' => 0x11, 'FirstDayOfWeek' => 0x12, 'MeetingMessageType' => 0x13, - ); -} \ No newline at end of file + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage23.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage23.php index 993cd70..a646f9c 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage23.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage23.php @@ -1,32 +1,32 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage23 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 23; - + protected $_codePageName = 'Notes'; - - protected $_tags = array( + + protected $_tags = [ 'Subject' => 0x05, 'MessageClass' => 0x06, 'LastModifiedDate' => 0x07, 'Categories' => 0x08, 'Category' => 0x09, - ); -} \ No newline at end of file + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage24.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage24.php index 58d5fb9..ce9e12c 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage24.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage24.php @@ -1,48 +1,48 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage24 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 24; - + protected $_codePageName = 'RightsManagement'; - - protected $_tags = array( + + protected $_tags = [ 'RightsManagementSupport' => 0x05, 'RightsManagementTemplates' => 0x06, 'RightsManagementTemplate' => 0x07, 'RightsManagementLicense' => 0x08, 'ReplyAllowed' => 0x09, 'EditAllowed' => 0x0a, 'ReplyAllAllowed' => 0x0b, 'ForwardAllowed' => 0x0c, 'ModifyRecipientsAllowed' => 0x0d, 'ExtractAllowed' => 0x0e, 'PrintAllowed' => 0x0f, 'ExportAllowed' => 0x10, 'ProgrammaticAccessAllowed' => 0x11, 'RMOwner' => 0x12, 'ContentExpiryDate' => 0x13, 'TemplateName' => 0x14, 'TemplateID' => 0x15, 'TemplateDescription' => 0x16, 'ContentOwner' => 0x17, - 'RemoveRightsManagementDistribution' => 0x18 - ); - -} \ No newline at end of file + 'RemoveRightsManagementDistribution' => 0x18, + ]; + +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage254.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage254.php index 07ca1d9..e94a1ac 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage254.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage254.php @@ -1,31 +1,31 @@ */ /** * class documentation * * @link http://msdn.microsoft.com/en-us/live/jj572363.aspx * @package Wbxml * @subpackage ActiveSync */ class Syncroton_Wbxml_Dtd_ActiveSync_CodePage254 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 254; - + protected $_codePageName = 'WindowsLive'; - - protected $_tags = array( + + protected $_tags = [ 'Annotations' => 0x05, 'Annotation' => 0x06, 'Name' => 0x07, - 'Value' => 0x08 - ); -} \ No newline at end of file + 'Value' => 0x08, + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage3.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage3.php index 9fe04d3..c35be32 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage3.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage3.php @@ -1,49 +1,49 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage3 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 3; - + protected $_codePageName = 'AirNotify'; - - protected $_tags = array( + + protected $_tags = [ 'Notify' => 0x05, 'Notification' => 0x06, 'Version' => 0x07, 'Lifetime' => 0x08, 'DeviceInfo' => 0x09, 'Enable' => 0x0a, 'Folder' => 0x0b, 'ServerId' => 0x0c, 'DeviceAddress' => 0x0d, 'ValidCarrierProfiles' => 0x0e, 'CarrierProfile' => 0x0f, 'Status' => 0x10, 'Responses' => 0x11, 'Devices' => 0x12, 'Device' => 0x13, 'Id' => 0x14, 'Expiry' => 0x15, 'NotifyGUID' => 0x16, - 'DeivceFriendlyName' => 0x17 - ); + 'DeivceFriendlyName' => 0x17, + ]; // attribute page #"Version='1.1'" => 0x05, -} \ No newline at end of file +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage4.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage4.php index 6bee32c..77c6fe1 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage4.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage4.php @@ -1,74 +1,74 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage4 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 4; - + protected $_codePageName = 'Calendar'; - - protected $_tags = array( + + protected $_tags = [ 'Timezone' => 0x05, 'AllDayEvent' => 0x06, 'Attendees' => 0x07, 'Attendee' => 0x08, 'Email' => 0x09, 'Name' => 0x0a, 'Body' => 0x0b, 'BodyTruncated' => 0x0c, 'BusyStatus' => 0x0d, 'Categories' => 0x0e, 'Category' => 0x0f, 'Rtf' => 0x10, 'DtStamp' => 0x11, 'EndTime' => 0x12, 'Exception' => 0x13, 'Exceptions' => 0x14, 'Deleted' => 0x15, 'ExceptionStartTime' => 0x16, 'Location' => 0x17, 'MeetingStatus' => 0x18, 'OrganizerEmail' => 0x19, 'OrganizerName' => 0x1a, 'Recurrence' => 0x1b, 'Type' => 0x1c, 'Until' => 0x1d, 'Occurrences' => 0x1e, 'Interval' => 0x1f, 'DayOfWeek' => 0x20, 'DayOfMonth' => 0x21, 'WeekOfMonth' => 0x22, 'MonthOfYear' => 0x23, 'Reminder' => 0x24, 'Sensitivity' => 0x25, 'Subject' => 0x26, 'StartTime' => 0x27, 'UID' => 0x28, 'AttendeeStatus' => 0x29, 'AttendeeType' => 0x2a, 'DisallowNewTimeProposal' => 0x33, 'ResponseRequested' => 0x34, 'AppointmentReplyTime' => 0x35, 'ResponseType' => 0x36, 'CalendarType' => 0x37, 'IsLeapMonth' => 0x38, 'FirstDayOfWeek' => 0x39, 'OnlineMeetingConfLink' => 0x3a, - 'OnlineMeetingExternalLink' => 0x3b - ); -} \ No newline at end of file + 'OnlineMeetingExternalLink' => 0x3b, + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage5.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage5.php index 346ba4c..0972b1e 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage5.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage5.php @@ -1,35 +1,35 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage5 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 5; protected $_codePageName = 'Move'; - protected $_tags = array( + protected $_tags = [ 'MoveItems' => 0x05, 'Move' => 0x06, 'SrcMsgId' => 0x07, 'SrcFldId' => 0x08, 'DstFldId' => 0x09, 'Response' => 0x0a, 'Status' => 0x0b, - 'DstMsgId' => 0x0c - ); -} \ No newline at end of file + 'DstMsgId' => 0x0c, + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage6.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage6.php index 54e3b7c..e2c6f04 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage6.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage6.php @@ -1,37 +1,37 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage6 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 6; - + protected $_codePageName = 'ItemEstimate'; - - protected $_tags = array( + + protected $_tags = [ 'GetItemEstimate' => 0x05, 'Version' => 0x06, 'Collections' => 0x07, 'Collection' => 0x08, 'Class' => 0x09, 'CollectionId' => 0x0a, 'DateTime' => 0x0b, 'Estimate' => 0x0c, 'Response' => 0x0d, - 'Status' => 0x0e - ); -} \ No newline at end of file + 'Status' => 0x0e, + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage7.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage7.php index 62833af..11327f6 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage7.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage7.php @@ -1,47 +1,47 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage7 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 7; - + protected $_codePageName = 'FolderHierarchy'; - - protected $_tags = array( + + protected $_tags = [ 'Folders' => 0x05, 'Folder' => 0x06, 'DisplayName' => 0x07, 'ServerId' => 0x08, 'ParentId' => 0x09, 'Type' => 0x0a, 'Response' => 0x0b, 'Status' => 0x0c, 'ContentClass' => 0x0d, 'Changes' => 0x0e, 'Add' => 0x0f, 'Delete' => 0x10, 'Update' => 0x11, 'SyncKey' => 0x12, 'FolderCreate' => 0x13, 'FolderDelete' => 0x14, 'FolderUpdate' => 0x15, 'FolderSync' => 0x16, 'Count' => 0x17, - 'Version' => 0x18 // not used anymore - ); -} \ No newline at end of file + 'Version' => 0x18, // not used anymore + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage8.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage8.php index 6c8e61c..839cd3b 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage8.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage8.php @@ -1,37 +1,37 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage8 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 8; - + protected $_codePageName = 'MeetingResponse'; - - protected $_tags = array( + + protected $_tags = [ 'CalendarId' => 0x05, 'CollectionId' => 0x06, 'MeetingResponse' => 0x07, 'RequestId' => 0x08, 'Request' => 0x09, 'Result' => 0x0a, 'Status' => 0x0b, 'UserResponse' => 0x0c, 'Version' => 0x0d, // not used anymore - 'InstanceId' => 0x0e - ); -} \ No newline at end of file + 'InstanceId' => 0x0e, + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage9.php b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage9.php index 7d33bc6..4d66b8f 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage9.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage9.php @@ -1,61 +1,61 @@ */ /** * class documentation * * @package Wbxml * @subpackage ActiveSync */ - + class Syncroton_Wbxml_Dtd_ActiveSync_CodePage9 extends Syncroton_Wbxml_Dtd_ActiveSync_Abstract { protected $_codePageNumber = 9; - + protected $_codePageName = 'Tasks'; - - protected $_tags = array( + + protected $_tags = [ 'Body' => 0x05, 'BodySize' => 0x06, 'BodyTruncated' => 0x07, 'Categories' => 0x08, 'Category' => 0x09, 'Complete' => 0x0a, 'DateCompleted' => 0x0b, 'DueDate' => 0x0c, 'UtcDueDate' => 0x0d, 'Importance' => 0x0e, 'Recurrence' => 0x0f, 'Type' => 0x10, 'Start' => 0x11, 'Until' => 0x12, 'Occurrences' => 0x13, 'Interval' => 0x14, 'DayOfWeek' => 0x16, 'DayOfMonth' => 0x15, 'WeekOfMonth' => 0x17, 'MonthOfYear' => 0x18, 'Regenerate' => 0x19, 'DeadOccur' => 0x1a, 'ReminderSet' => 0x1b, 'ReminderTime' => 0x1c, 'Sensitivity' => 0x1d, 'StartDate' => 0x1e, 'UtcStartDate' => 0x1f, 'Subject' => 0x20, 'Rtf' => 0x21, 'OrdinalDate' => 0x22, 'SubOrdinalDate' => 0x23, 'CalendarType' => 0x24, 'IsLeapMonth' => 0x25, 'FirstDayOfWeek' => 0x26, - ); -} \ No newline at end of file + ]; +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/Exception/CodePageNotFound.php b/lib/ext/Syncroton/Wbxml/Dtd/Exception/CodePageNotFound.php index 9cc436c..bbcfbad 100644 --- a/lib/ext/Syncroton/Wbxml/Dtd/Exception/CodePageNotFound.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/Exception/CodePageNotFound.php @@ -1,22 +1,22 @@ * @version $Id:CodePageNotFound.php 4968 2008-10-17 09:09:33Z l.kneschke@metaways.de $ */ /** * class documentation * * @package Wbxml * @subpackage Wbxml */ - - class Syncroton_Wbxml_Dtd_Exception_CodePageNotFound extends Exception - { - } \ No newline at end of file + +class Syncroton_Wbxml_Dtd_Exception_CodePageNotFound extends Exception +{ +} diff --git a/lib/ext/Syncroton/Wbxml/Dtd/Factory.php b/lib/ext/Syncroton/Wbxml/Dtd/Factory.php index b517316..9e0ef1d 100755 --- a/lib/ext/Syncroton/Wbxml/Dtd/Factory.php +++ b/lib/ext/Syncroton/Wbxml/Dtd/Factory.php @@ -1,43 +1,43 @@ * @version $Id:Factory.php 4968 2008-10-17 09:09:33Z l.kneschke@metaways.de $ */ /** * class documentation * * @package Wbxml * @subpackage Wbxml */ class Syncroton_Wbxml_Dtd_Factory { - const ACTIVESYNC = 'AirSync'; - const SYNCML = 'SyncML'; + public const ACTIVESYNC = 'AirSync'; + public const SYNCML = 'SyncML'; /** * factory function to return a selected contacts backend class * * @param string $type * @return Syncroton_Wbxml_Dtd_ActiveSync */ - static public function factory($type) + public static function factory($type) { switch ($type) { case self::ACTIVESYNC: $instance = new Syncroton_Wbxml_Dtd_ActiveSync(); break; default: throw new Syncroton_Wbxml_Exception('unsupported DTD: ' . $type); } return $instance; } } diff --git a/lib/ext/Syncroton/Wbxml/Encoder.php b/lib/ext/Syncroton/Wbxml/Encoder.php index ef2144c..c7eeac1 100644 --- a/lib/ext/Syncroton/Wbxml/Encoder.php +++ b/lib/ext/Syncroton/Wbxml/Encoder.php @@ -1,244 +1,245 @@ * @version $Id:Encoder.php 4968 2008-10-17 09:09:33Z l.kneschke@metaways.de $ */ /** * class to convert XML to WBXML * * @package Wbxml * @subpackage Wbxml */ - + class Syncroton_Wbxml_Encoder extends Syncroton_Wbxml_Abstract { /** * count level of tags * * @var int */ protected $_level = 0; - + /** * the constructor * * @param resource $_stream * @param string $_charSet * @param int $_version */ public function __construct($_stream, $_charSet = 'UTF-8', $_version = 2) { $this->_stream = $_stream; $this->_charSet = $_charSet; $this->_version = $_version; } /** * initialize internal variables and write wbxml header to stream * * @param DOMDocument $_dom * @todo check if dpi > 0, instead checking the urn */ protected function _initialize($_dom) { $this->_dtd = Syncroton_Wbxml_Dtd_Factory::factory($_dom->doctype->name); $this->_codePage = $this->_dtd->getCurrentCodePage(); - + // the WBXML version $this->_writeByte($this->_version); - - if($this->_codePage->getDPI() === NULL) { + + if($this->_codePage->getDPI() === null) { // the document public identifier $this->_writeMultibyteUInt(1); } else { // the document public identifier // defined in string table $this->_writeMultibyteUInt(0); // the offset of the DPI in the string table $this->_writeByte(0); - } - + } + // write the charSet $this->_writeCharSet($this->_charSet); - - if($this->_codePage->getDPI() === NULL) { + + if($this->_codePage->getDPI() === null) { // the length of the string table $this->_writeMultibyteUInt(0); } else { // the length of the string table $this->_writeMultibyteUInt(strlen($this->_codePage->getDPI())); // the dpi - $this->_writeString($this->_codePage->getDPI()); - } + $this->_writeString($this->_codePage->getDPI()); + } } - + /** * write charset to stream * * @param string $_charSet * @todo add charset lookup table. currently only utf-8 is supported */ protected function _writeCharSet($_charSet) { switch(strtoupper($_charSet)) { case 'UTF-8': $this->_writeMultibyteUInt(106); break; - + default: throw new Syncroton_Wbxml_Exception('unsuported charSet ' . strtoupper($_charSet)); } } - + /** * start encoding of xml to wbxml * * @param DOMDocument $_dom the DOM document */ public function encode(DOMDocument $_dom) { $_dom->formatOutput = false; - + $this->_initialize($_dom); $this->_traverseDom($_dom); } private function getAttributes($node) { - $attributes = array(); + $attributes = []; if ($node->attributes) { for ($i = 0; $i < $node->attributes->length; ++$i) { $attributes[$node->attributes->item($i)->name] = $node->attributes->item($i)->value; } } return $attributes; } - private function writeNode($node, $withContent = false, $data = null) { + private function writeNode($node, $withContent = false, $data = null) + { if($this->_codePage->getNameSpace() != $node->namespaceURI) { $this->_switchCodePage($node->namespaceURI); } $this->_writeTag($node->localName, $this->getAttributes($node), $withContent, $data); } protected function _traverseDom($_dom) { if ($_dom->childNodes->length == 0) { return false; } // print(str_pad("", $this->_level, " ") . "traversing {$_dom->nodeName}" . "\n"); $this->_level++; $prevNode = $_dom; $foundElementNode = false; foreach ($_dom->childNodes as $node) { if ($node->nodeType == XML_ELEMENT_NODE) { $foundElementNode = true; if ($prevNode && $this->_level > 1) { // print(str_pad("", $this->_level, " ") . "{$node->nodeName} creating parent {$prevNode->nodeName}" . "\n"); $this->writeNode($prevNode, true); $prevNode = null; } if (!$this->_traverseDom($node)) { // print(str_pad("", $this->_level, " ") . "{$node->nodeName} content {$node->nodeValue}" . "\n"); $data = $node->nodeValue; if (strlen($data) == 0) { $this->writeNode($node); } else { $this->writeNode($node, true, $data); $this->_writeByte(Syncroton_Wbxml_Abstract::END); // print("Closing tag after writing tag\n"); } } else { $this->_writeByte(Syncroton_Wbxml_Abstract::END); // print("Closing tag\n"); } } } $this->_level--; return $foundElementNode; } /** * strip uri: from nameSpace * * @param string $_nameSpace * * @return string */ protected function _stripNameSpace($_nameSpace) { return substr($_nameSpace, 4); } - + /** * writes tag with data to stream * * @param string $_tag * @param array $_attributes * @param bool $_hasContent * @param string $_data */ - protected function _writeTag($_tag, $_attributes=NULL, $_hasContent=false, $_data=NULL) + protected function _writeTag($_tag, $_attributes = null, $_hasContent = false, $_data = null) { - if($_hasContent == false && $_data !== NULL) { + if($_hasContent == false && $_data !== null) { throw new Syncroton_Wbxml_Exception('$_hasContent can not be false, when $_data !== NULL'); } - + // handle the tag $identity = $this->_codePage->getIdentity($_tag); - + if (is_array($_attributes) && isset($_attributes['uri:Syncroton;encoding'])) { $encoding = 'opaque'; unset($_attributes['uri:Syncroton;encoding']); } else { $encoding = 'termstring'; } - + if(!empty($_attributes)) { $identity |= 0x80; } - + if($_hasContent == true) { $identity |= 0x40; } - + $this->_writeByte($identity); - + // handle the data - if($_data !== NULL) { + if($_data !== null) { if ($encoding == 'opaque') { - $this->_writeOpaqueString(base64_decode($_data)); + $this->_writeOpaqueString(base64_decode($_data)); } else { $this->_writeTerminatedString($_data); } } } /** * switch code page * * @param string $_nameSpace */ protected function _switchCodePage($_nameSpace) { $codePageName = $this->_stripNameSpace($_nameSpace); - if(!defined('Syncroton_Wbxml_Dtd_ActiveSync::CODEPAGE_'. strtoupper($codePageName))) { + if(!defined('Syncroton_Wbxml_Dtd_ActiveSync::CODEPAGE_' . strtoupper($codePageName))) { throw new Syncroton_Wbxml_Exception('codepage ' . $codePageName . ' not found'); } // switch to another codepage // no need to write the wbxml header again - $codePageId = constant('Syncroton_Wbxml_Dtd_ActiveSync::CODEPAGE_'. strtoupper($codePageName)); + $codePageId = constant('Syncroton_Wbxml_Dtd_ActiveSync::CODEPAGE_' . strtoupper($codePageName)); $this->_codePage = $this->_dtd->switchCodePage($codePageId); - + $this->_writeByte(Syncroton_Wbxml_Abstract::SWITCH_PAGE); $this->_writeByte($codePageId); } } diff --git a/lib/ext/Syncroton/Wbxml/Exception.php b/lib/ext/Syncroton/Wbxml/Exception.php index 5efdcb1..ac4b9f3 100644 --- a/lib/ext/Syncroton/Wbxml/Exception.php +++ b/lib/ext/Syncroton/Wbxml/Exception.php @@ -1,23 +1,23 @@ * @version $Id:Factory.php 4968 2008-10-17 09:09:33Z l.kneschke@metaways.de $ */ /** * class documentation * * @package Wbxml * @subpackage Wbxml */ -class Syncroton_Wbxml_Exception extends Exception +class Syncroton_Wbxml_Exception extends Exception { protected $message = 'wbxml exception'; -} \ No newline at end of file +}