Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2513293
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
36 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/kolab_sync_backend_state.php b/lib/kolab_sync_backend_state.php
index c8fe5ab..87cc46c 100644
--- a/lib/kolab_sync_backend_state.php
+++ b/lib/kolab_sync_backend_state.php
@@ -1,224 +1,224 @@
<?php
/**
* sql backend class for the folder state
*
* @package Syncroton
* @subpackage Backend
*/
class kolab_sync_backend_state implements Syncroton_Backend_ISyncState
{
/**
* the database adapter
*
* @var rcube_mdb2
*/
protected $db;
public function __construct()
{
$this->db = rcube::get_instance()->get_dbh();
}
/**
* create new sync state
*
* @param Syncroton_Model_ISyncState $_syncState
* @return Syncroton_Model_SyncState
*/
public function create(Syncroton_Model_ISyncState $_syncState, $_keepPreviousSyncState = true)
{
$id = sha1(mt_rand(). microtime());
$deviceId = $_syncState->device_id instanceof Syncroton_Model_IDevice ? $_syncState->device_id->id : $_syncState->device_id;
$type = $_syncState->type instanceof Syncroton_Model_IFolder ? $_syncState->type->id : $_syncState->type;
$data = is_array($_syncState->pendingdata) ? json_encode($_syncState->pendingdata) : null;
$insert[$this->db->quote_identifier('id')] = $this->db->quote($id);
$insert[$this->db->quote_identifier('device_id')] = $this->db->quote($deviceId);
$insert[$this->db->quote_identifier('type')] = $this->db->quote($type);
$insert[$this->db->quote_identifier('counter')] = $this->db->quote($_syncState->counter);
$insert[$this->db->quote_identifier('lastsync')] = $this->db->quote($_syncState->lastsync->format('Y-m-d H:i:s'));
$insert[$this->db->quote_identifier('pendingdata')] = $data ? $this->db->quote($data) : 'NULL';
$this->db->query('INSERT INTO syncroton_synckey'
. ' (' . implode(', ', array_keys($insert)) . ')' . ' VALUES(' . implode(', ', $insert) . ')');
$state = $this->get($id);
if ($_keepPreviousSyncState !== true) {
// remove all other synckeys
$this->_deleteOtherStates($state);
}
return $state;
}
protected function _deleteOtherStates(Syncroton_Model_ISyncState $_state)
{
// remove all other synckeys
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($_state->device_id);
$where[] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($_state->type);
$where[] = $this->db->quote_identifier('counter') . ' <> ' . $this->db->quote($_state->counter);
$this->db->query('DELETE FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
return true;
}
/**
* @param string $_id
* @throws Syncroton_Exception_NotFound
* @return Syncroton_Model_SyncState
*/
public function get($_id)
{
$select = $this->db->query('SELECT * FROM syncroton_synckey WHERE id = ?', array($_id));
if ($state = $this->db->fetch_assoc($select)) {
$state = new Syncroton_Model_SyncState($state);
}
if (! $state instanceof Syncroton_Model_ISyncState) {
throw new Syncroton_Exception_NotFound('id not found');
}
$this->_convertFields($state);
return $state;
}
protected function _convertFields(Syncroton_Model_SyncState $state)
{
if (!empty($state->lastsync)) {
$state->lastsync = new DateTime($state->lastsync, new DateTimeZone('utc'));
}
if ($state->pendingdata) {
$state->pendingdata = json_decode($state->pendingdata);
}
}
/**
* always returns the latest syncstate
*
* @param Syncroton_Model_IDevice|string $_deviceId
* @param Syncroton_Model_IFolder|string $_folderId
* @return Syncroton_Model_SyncState
*/
public function getSyncState($_deviceId, $_folderId)
{
$deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
$folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where[] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folderId);
$select = $this->db->limitquery('SELECT * FROM syncroton_synckey WHERE ' . implode(' AND ', $where)
.' ORDER BY counter DESC', 0, 1);
if ($state = $this->db->fetch_assoc($select)) {
$state = new Syncroton_Model_SyncState($state);
}
if (! $state instanceof Syncroton_Model_ISyncState) {
throw new Syncroton_Exception_NotFound('id not found');
}
$this->_convertFields($state);
return $state;
}
/**
* 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[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where[] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folderId);
$this->db->query('DELETE FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
}
public function update(Syncroton_Model_ISyncState $_syncState)
{
$data = is_array($_syncState->pendingdata) ? json_encode($_syncState->pendingdata) : 'null';
$this->db->query('UPDATE syncroton_synckey SET counter = ?, lastsync = ?, pendingdata = ? WHERE id = ?',
array($_syncState->counter, $_syncState->lastsync->format('Y-m-d H:i:s'), $data, $_syncState->id));
return $this->get($_syncState->id);
}
/**
* get array of ids which got send to the client for a given class
*
* @param Syncroton_Model_IDevice|string $_deviceId
* @param Syncroton_Model_IFolder|string $_folderId
*
* @return Syncroton_Model_SyncState
*/
public function validate($_deviceId, $_folderId, $_syncKey)
{
$deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
$folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
$where['device_id'] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where['type'] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folderId);
$where['counter'] = $this->db->quote_identifier('counter') . ' = ' . $this->db->quote($_syncKey);
$select = $this->db->query('SELECT * FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
if ($state = $this->db->fetch_assoc($select)) {
$state = new Syncroton_Model_SyncState($state);
}
if (! $state instanceof Syncroton_Model_ISyncState) {
return false;
}
$this->_convertFields($state);
// check if this was the latest syncKey
$where['counter'] = $this->db->quote_identifier('counter') . ' = ' . $this->db->quote($_syncKey + 1);
$select = $this->db->query('SELECT * FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
if ($moreRecentState = $this->db->fetch_assoc($select)) {
$moreRecentState = new Syncroton_Model_SyncState($moreRecentState);
}
$where = array();
$where['device_id'] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where['folder_id'] = $this->db->quote_identifier('folder_id') . ' = ' . $this->db->quote($folderId);
$where['is_deleted'] = $this->db->quote_identifier('is_deleted') . ' = 1';
- // found more recent synckey => the last sync repsone got not received by the client
+ // found more recent synckey => the last sync repsonse got not received by the client
if ($moreRecentState instanceof Syncroton_Model_ISyncState) {
$where['synckey'] = $this->db->quote_identifier('creation_synckey') . ' = ' . $this->db->quote($state->counter);
// undelete entries marked as deleted in Syncroton_content table
$this->db->query('UPDATE syncroton_content SET is_deleted = 0 WHERE ' . implode(' AND ', $where));
// remove entries added during latest sync in Syncroton_content table
unset($where['is_deleted']);
$where['synckey'] = $this->db->quote_identifier('creation_synckey') . ' > ' . $this->db->quote($state->counter);
$this->db->query('DELETE FROM syncroton_content WHERE ' . implode(' AND ', $where));
}
else {
// finaly delete all entries marked for removal in Syncroton_content table
$this->db->query('DELETE FROM syncroton_content WHERE ' . implode(' AND ', $where));
}
// remove all other synckeys
$this->_deleteOtherStates($state);
return $state;
}
}
diff --git a/lib/kolab_sync_data.php b/lib/kolab_sync_data.php
index 2deb85e..d664eae 100644
--- a/lib/kolab_sync_data.php
+++ b/lib/kolab_sync_data.php
@@ -1,939 +1,939 @@
<?php
abstract class kolab_sync_data implements Syncroton_Data_IData
{
/**
* ActiveSync protocol version
*
* @var int
*/
protected $asversion = 0;
/**
* information about the current device
*
* @var Syncroton_Model_IDevice
*/
protected $device;
/**
* timestamp to use for all sync requests
*
* @var DateTime
*/
protected $syncTimeStamp;
/**
* name of model to use
*
* @var string
*/
protected $modelName;
/**
* type of the default folder
*
* @var int
*/
protected $defaultFolderType;
/**
* default container for new entries
*
* @var string
*/
protected $defaultFolder;
/**
* type of user created folders
*
* @var int
*/
protected $folderType;
/**
* Default namespace
*
* @var string
*/
protected $defaultNS = 'Calendar';
/**
* field to sort search results by
*
* @var string
*/
protected $sortField;
/**
* Internal cache for kolab_storage folder objects
*
* @var array
*/
protected $folders = array();
/**
* Timezone
*
* @var string
*/
protected $timezone;
const RESULT_OBJECT = 0;
const RESULT_UID = 1;
const RESULT_COUNT = 2;
/**
* the constructor
*
* @param Syncroton_Model_IDevice $device
* @param DateTime $syncTimeStamp
*/
public function __construct(Syncroton_Model_IDevice $device, DateTime $syncTimeStamp)
{
$this->backend = kolab_sync_backend::get_instance();
$this->device = $device;
$this->asversion = floatval($device->acsversion);
$this->syncTimeStamp = $syncTimeStamp;
$this->defaultRootFolder = $this->defaultFolder . '::Syncroton';
// set internal timezone of kolab_format to user timezone
try {
$this->timezone = rcube::get_instance()->config->get('timezone', 'GMT');
kolab_format::$timezone = new DateTimeZone($this->timezone);
}
catch (Exception $e) {
//rcube::raise_error($e, true);
$this->timezone = 'GMT';
kolab_format::$timezone = new DateTimeZone('GMT');
}
}
/**
* return list of supported folders for this backend
*
* @return array
*/
public function getAllFolders()
{
$list = array();
// device supports multiple folders ?
if (in_array(strtolower($this->device->devicetype), array('iphone', 'ipad', 'thundertine', 'windowsphone'))) {
// get the folders the user has access to
$list = $this->backend->folders_list($this->device->deviceid, $this->modelName);
}
if ($default = $this->getDefaultFolder()) {
$list = array($default['folderid'] => $default);
}
foreach ($list as $idx => $folder) {
$list[$idx] = new Syncroton_Model_Folder($folder);
}
return $list;
}
/**
* Returns default folder for current class type.
*/
protected function getDefaultFolder()
{
// Check if there's any folder configured for sync
$folders = $this->backend->folders_list($this->device->deviceid, $this->modelName);
if (empty($folders)) {
return null;
}
foreach ($folders as $folder) {
if ($folder['type'] == $this->defaultFolderType) {
$default = $folder;
break;
}
}
// Return first on the list if there's no default
if (empty($default)) {
$default = $folders[key($folders)];
}
// Remember real folder ID and set ID/name to root folder
$default['realid'] = $default['folderid'];
$default['folderid'] = $this->defaultRootFolder;
$default['displayname'] = $this->defaultFolder;
return $default;
}
/**
* Creates a folder
*/
public function createFolder(Syncroton_Model_IFolder $folder)
{
$parentid = $folder->parentid;
$type = $folder->type;
$display_name = $folder->displayname;
if ($parentid) {
$parent = $this->backend->folder_id2name($parentid, $this->device->deviceid);
}
$name = rcube_charset::convert($display_name, kolab_sync::CHARSET, 'UTF7-IMAP');
if ($parent !== null) {
$rcube = rcube::get_instance();
$storage = $rcube->get_storage();
$delim = $storage->get_hierarchy_delimiter();
$name = $parent . $delim . $name;
}
// Create IMAP folder
$result = $this->backend->folder_create($name, $type, $this->device->deviceid);
if ($result) {
$folder->folderid = $this->backend->folder_id($name);
return $folder;
}
// @TODO: throw exception
}
/**
* Updates a folder
*/
public function updateFolder(Syncroton_Model_IFolder $folder)
{
$parentid = $folder->parentid;
$type = $folder->type;
$display_name = $folder->displayname;
$old_name = $this->backend->folder_id2name($folder->folderid, $this->device->deviceid);
if ($parentid) {
$parent = $this->backend->folder_id2name($parentid, $this->device->deviceid);
}
$name = rcube_charset::convert($display_name, kolab_sync::CHARSET, 'UTF7-IMAP');
if ($parent !== null) {
$rcube = rcube::get_instance();
$storage = $rcube->get_storage();
$delim = $storage->get_hierarchy_delimiter();
$name = $parent . $delim . $name;
}
// Rename/move IMAP folder
if ($name == $old_name) {
$result = true;
// @TODO: folder type change?
}
else {
$result = $this->backend->folder_rename($old_name, $name, $type, $this->device->deviceid);
}
if ($result) {
$folder->folderid = $this->backend->folder_id($name);
return $folder;
}
// @TODO: throw exception
}
/**
* Deletes a folder
*/
public function deleteFolder($folder)
{
if ($folder instanceof Syncroton_Model_IFolder) {
$folder = $folder->folderid;
}
$name = $this->backend->folder_id2name($folder, $this->device->deviceid);
// @TODO: throw exception
return $this->backend->folder_delete($name, $this->device->deviceid);
}
public function moveItem($srcFolderId, $serverId, $dstFolderId)
{
$item = $this->getObject($srcFolderId, $serverId, $folder);
if ($item && $folder) {
$dstname = $this->backend->folder_id2name($dstFolderId, $this->device->deviceid);
if ($dstname === null) {
return;
}
if (!$folder->move($serverId, $dstname)) {
return;
}
}
return $item['uid'];
}
/**
* add entry from xml data
*
* @param string $folderId
* @param SimpleXMLElement $entry
* @return array
*/
public function createEntry($folderId, Syncroton_Model_IEntry $entry)
{
$entry = $this->toKolab($entry, $folderId);
$entry = $this->createObject($folderId, $entry);
return $entry['uid'];
}
/**
* update existing entry
*
* @param string $folderId
* @param string $serverId
* @param SimpleXMLElement $entry
* @return array
*/
public function updateEntry($folderId, $serverId, Syncroton_Model_IEntry $entry)
{
$oldEntry = $this->getObject($folderId, $serverId);
if (empty($oldEntry)) {
throw new Syncroton_Exception_NotFound('id not found');
}
$entry = $this->toKolab($entry, $folderId, $oldEntry);
$entry = $this->updateObject($folderId, $serverId, $entry);
return $entry['uid'];
}
/**
* delete entry
*
* @param string $folderId
* @param string $serverId
* @param array $collectionData
*/
public function deleteEntry($folderId, $serverId, $collectionData)
{
$this->deleteObject($folderId, $serverId);
}
public function getFileReference($fileReference)
{
}
/**
* Search for existing entries
*
* @param string $folderid
* @param array $filter
* @param int $result_type Type of the result (see RESULT_* constants)
*
* @return array|int Search result as count or array of uids/objects
*/
public function search($folderid, $filter = array(), $result_type = self::RESULT_UID)
{
if ($folderid == $this->defaultRootFolder) {
$folders = $this->backend->folders_list($this->device->deviceid, $this->modelName);
$folders = array_keys($folders);
}
else {
$folders = array($folderid);
}
// there's a PHP Warning from kolab_storage if $filter isn't an array
if (empty($filter)) {
$filter = array();
}
$result = $result_type == self::RESULT_COUNT ? 0 : array();
foreach ($folders as $folderid) {
$foldername = $this->backend->folder_id2name($folderid, $this->device->deviceid);
if ($foldername === null) {
continue;
}
$folder = $this->getFolderObject($foldername);
if (!$folder) {
continue;
}
switch ($result_type) {
case self::RESULT_COUNT:
$result += (int) $folder->count($filter);
break;
case self::RESULT_UID:
if ($uids = $folder->get_uids($filter)) {
$result = array_merge($result, $uids);
}
break;
case self::RESULT_OBJECT:
default:
if ($objects = $folder->select($filter)) {
$result = array_merge($result, $objects);
}
}
}
return $result;
}
/**
* Returns filter query array according to specified ActiveSync FilterType
*
* @param int $filter_type Filter type
*
* @param array Filter query
*/
protected function filter($filter_type = 0)
{
/*
From Syncroton_Command_Sync:
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;
Doc: MS-ASCMD 2.2.3.64.2 FilterType (Sync)
*/
// overwrite by child class according to specified type
return array();
}
/**
* get all entries changed between to dates
*
* @param string $folderId
* @param DateTime $startTimeStamp
* @param DateTime $endTimeStamp
* @return array
*/
public function getChangedEntries($folderId, DateTime $startTimeStamp, DateTime $endTimeStamp = null)
{
$start = ($startTimeStamp instanceof DateTime) ? $startTimeStamp->format('Y-m-d H:i:s') : $startTimeStamp;
$end = ($endTimeStamp instanceof DateTime) ? $endTimeStamp->format('Y-m-d H:i:s') : $endTimeStamp;
$filter = array();
$filter[] = array('changed', '>', $start);
if ($end) {
$filter[] = array('changed', '<=', $end);
}
$result = $this->search($folderId, $filter, self::RESULT_UID);
return $result;
}
/**
* get count of entries changed between two dates
*
* @param string $folderId
* @param DateTime $startTimeStamp
* @param DateTime $endTimeStamp
*
* @return int
*/
public function getChangedEntriesCount($folderId, DateTime $startTimeStamp, DateTime $endTimeStamp = null)
{
$start = ($startTimeStamp instanceof DateTime) ? $startTimeStamp->format('Y-m-d H:i:s') : $startTimeStamp;
$end = ($endTimeStamp instanceof DateTime) ? $endTimeStamp->format('Y-m-d H:i:s') : $endTimeStamp;
$filter = array();
$filter[] = array('changed', '>', $start);
if ($end) {
$filter[] = array('changed', '<=', $end);
}
$result = $this->search($folderId, $filter, self::RESULT_COUNT);
return $result;
}
/**
* get id's of all entries available on the server
*
* @param string $folderId
* @param int $filterType
*
* @return array
*/
public function getServerEntries($folder_id, $filter_type)
{
// @TODO: sorting? 'sort' => $this->sortField
$filter = $this->filter($filter_type);
$result = $this->search($folder_id, $filter, self::RESULT_UID);
return $result;
}
/**
* get count of all entries available on the server
*
* @param string $folderId
* @param int $filterType
*
* @return int
*/
public function getServerEntriesCount($folder_id, $filter_type)
{
$filter = $this->filter($filter_type);
$result = $this->search($folder_id, $filter, self::RESULT_COUNT);
return $result;
}
public function getCountOfChanges(Syncroton_Backend_IContent $contentBackend, Syncroton_Model_IFolder $folder, Syncroton_Model_ISyncState $syncState)
{
$allClientEntries = $contentBackend->getFolderState($this->device, $folder);
// @TODO: Consider looping over all folders here, not in getServerEntries() and
// getChangesEntriesCount(). This way we could break the loop and not check all folders (see @TODO below)
// or at least skip redundant cache sync of the same folder
$allServerEntries = $this->getServerEntries($folder->folderid, $folder->lastfiltertype);
$addedEntries = array_diff($allServerEntries, $allClientEntries);
$deletedEntries = array_diff($allClientEntries, $allServerEntries);
// @TODO: Count is needed only for GetItemEstimate command
// in Ping command we need only information that anything is changed/added/deleted
// so in case when count($addedEntries) + count($deletedEntries) != 0 we don't need
// to count changed entries here. We could also revert the order in such case
// and execute getChangedEntriesCount() before
$changedEntries = $this->getChangedEntriesCount($folder->folderid, $syncState->lastsync);
return count($addedEntries) + count($deletedEntries) + $changedEntries;
}
/**
* Fetches the entry from the backend
*/
protected function getObject($folderid, $entryid, &$folder = null)
{
if ($folderid instanceof Syncroton_Model_IFolder) {
$folderid = $folderid->folderid;
}
if ($folderid == $this->defaultRootFolder) {
$folders = $this->backend->folders_list($this->device->deviceid, $this->modelName);
$folders = array_keys($folders);
}
else {
$folders = array($folderid);
}
foreach ($folders as $folderid) {
$foldername = $this->backend->folder_id2name($folderid, $this->device->deviceid);
if ($foldername === null) {
continue;
}
$folder = $this->getFolderObject($foldername);
if ($object = $folder->get_object($entryid)) {
$object['_folderid'] = $folderid;
return $object;
}
}
}
/**
* Saves the entry on the backend
*/
protected function createObject($folderid, $data)
{
if ($folderid == $this->defaultRootFolder) {
$default = $this->getDefaultFolder();
$folderid = isset($default['realid']) ? $default['realid'] : $default['folderid'];
}
$foldername = $this->backend->folder_id2name($folderid, $this->device->deviceid);
$folder = $this->getFolderObject($foldername);
if ($folder->save($data)) {
return $data;
}
}
/**
* Updates the entry on the backend
*/
protected function updateObject($folderid, $entryid, $data)
{
$object = $this->getObject($folderid, $entryid);
if ($object) {
$folder = $this->getFolderObject($object['_mailbox']);
if ($folder->save($data)) {
return $data;
}
}
}
/**
* Removes the entry from the backend
*/
protected function deleteObject($folderid, $entryid)
{
$object = $this->getObject($folderid, $entryid);
if ($object) {
$folder = $this->getFolderObject($object['_mailbox']);
return $folder->delete($entryid);
}
}
/**
* Returns Folder object (uses internal cache)
*
* @param string $name Folder name (UTF7-IMAP)
*
* @return kolab_storage_folder Folder object
*/
protected function getFolderObject($name)
{
if (!isset($this->folders[$name])) {
$this->folders[$name] = kolab_storage::get_folder($name);
}
return $this->folders[$name];
}
/**
* Returns ActiveSync settings of specified folder
*
* @param string $name Folder name (UTF7-IMAP)
*
* @return array Folder settings
*/
protected function getFolderConfig($name)
{
$metadata = $this->backend->folder_meta();
$deviceid = $this->device->deviceid;
$config = $metadata[$name]['FOLDER'][$deviceid];
return array(
'ALARMS' => $config['S'] == 2,
);
}
/**
* Convert contact from xml to kolab format
*
* @param Syncroton_Model_IEntry $data Contact data
* @param string $folderId Folder identifier
* @param array $entry Old Contact data for merge
*
* @return array
*/
abstract public function toKolab(Syncroton_Model_IEntry $data, $folderId, $entry = null);
/**
* Removes control chars from string which are not allowed in ActiveSync
*
* @param string $value Text
*
* @return string Text
* @deprecated
*/
public static function quote($value)
{
if ($value && !ctype_print($value)) {
$value = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', null, $value);
}
return $value;
}
/**
* Extracts data from kolab data array
*/
protected function getKolabDataItem($data, $name)
{
$name_items = explode('.', $name);
$count = count($name_items);
// multi-level array (e.g. address, phone)
if ($count == 3) {
$name = $name_items[0];
$type = $name_items[1];
$key_name = $name_items[2];
if (!empty($data[$name]) && is_array($data[$name])) {
foreach ($data[$name] as $element) {
if ($element['type'] == $type) {
return $element[$key_name];
}
}
}
return null;
}
/*
// hash array e.g. organizer
else if ($count == 2) {
$name = $name_items[0];
$type = $name_items[1];
$key_name = $name_items[2];
if (!empty($data[$name]) && is_array($data[$name])) {
foreach ($data[$name] as $element) {
if ($element['type'] == $type) {
return $element[$key_name];
}
}
}
return null;
}
*/
$name_items = explode(':', $name);
$name = $name_items[0];
if (empty($data[$name])) {
return null;
}
// simple array (e.g. email)
if (count($name_items) == 2) {
return $data[$name][$name_items[1]];
}
return $data[$name];
}
/**
* Saves data in kolab data array
*/
protected function setKolabDataItem(&$data, $name, $value)
{
if (empty($value)) {
return $this->unsetKolabDataItem($data, $name);
}
$name_items = explode('.', $name);
// multi-level array (e.g. address, phone)
if (count($name_items) == 3) {
$name = $name_items[0];
$type = $name_items[1];
$key_name = $name_items[2];
if (!isset($data[$name])) {
$data[$name] = array();
}
foreach ($data[$name] as $idx => $element) {
if ($element['type'] == $type) {
$found = $idx;
break;
}
}
if (!isset($found)) {
- $keys = array_keys($data[$name]);
- $found = !empty($keys) ? max($keys) + 1 : 0;
- $data[$name][$found] = array();
+ $data[$name] = array_values($data[$name]);
+ $found = count($data[$name]);
+ $data[$name][$found] = array('type' => $type);
}
$data[$name][$found][$key_name] = $value;
return;
}
$name_items = explode(':', $name);
$name = $name_items[0];
// simple array (e.g. email)
if (count($name_items) == 2) {
$data[$name][$name_items[1]] = $value;
return;
}
$data[$name] = $value;
}
/**
* Unsets data item in kolab data array
*/
protected function unsetKolabDataItem(&$data, $name)
{
$name_items = explode('.', $name);
// multi-level array (e.g. address, phone)
if (count($name_items) == 3) {
$name = $name_items[0];
$type = $name_items[1];
$key_name = $name_items[2];
if (!isset($data[$name])) {
return;
}
foreach ($data[$name] as $idx => $element) {
if ($element['type'] == $type) {
$found = $idx;
break;
}
}
if (!isset($found)) {
return;
}
unset($data[$name][$found][$key_name]);
if (empty($data[$name][$found])) {
unset($data[$name][$found]);
}
if (empty($data[$name])) {
unset($data[$name]);
}
return;
}
$name_items = explode(':', $name);
$name = $name_items[0];
// simple array (e.g. email)
if (count($name_items) == 2) {
unset($data[$name][$name_items[1]]);
if (empty($data[$name])) {
unset($data[$name]);
}
return;
}
unset($data[$name]);
}
/**
* Setter for Body attribute according to client version
*
* @param string $value Attribute value
*/
protected function setBody($value)
{
if (empty($value)) {
return;
}
$body = array(
'Type' => 1,
'Data' => $value,
);
return new Syncroton_Model_EmailBody($body);
/*
// strip off any non printable control characters
$value = self::quote($value);
if ($this->asversion >= 12) {
$body = $domParent->appendChild(new DOMElement('Body', null, 'uri:AirSyncBase'));
$body->appendChild(new DOMElement('Type', 1, 'uri:AirSyncBase'));
$dataTag = new DOMElement('Data', null, 'uri:AirSyncBase');
// ... append it to parent node aka append it to the document ...
$body->appendChild($dataTag);
// ... and now add the content (DomText takes care of special chars)
$dataTag->appendChild(new DOMText($value));
} else {
// create a new DOMElement ...
$node = new DOMElement('Body', null, 'uri:' . $this->defaultNS);
// ... append it to parent node aka append it to the document ...
$domParent->appendChild($node);
// ... and now add the content (DomText takes care of special chars)
$node->appendChild(new DOMText($value));
}
*/
}
/**
* Getter for Body attribute value according to client version
*
* @param mixed $data Data element
*/
protected function getBody($data)
{
if ($data && $data->Data) {
return $data->Data;
}
/*
if ($this->asversion >= 12) {
$airSyncBase = $data->children('uri:AirSyncBase');
if (isset($airSyncBase->Body)) {
return (string)$airSyncBase->Body->Data;
}
}
else if (isset($classData->Body)) {
return (string) $classData->Body;
}
*/
}
/**
* Converts PHP DateTime, date (YYYY-MM-DD) or unixtimestamp into PHP DateTime in UTC
*
* @param DateTime|int|string $date Unix timestamp, date (YYYY-MM-DD) or PHP DateTime object
*
* @return DateTime Datetime object
*/
protected static function date_from_kolab($date)
{
if (!empty($date)) {
if (is_numeric($date)) {
$date = new DateTime('@' . $date);
}
else if (is_string($date)) {
$date = new DateTime($date, new DateTimeZone('UTC'));
}
else {
$date = clone $date;
$tz = $date->getTimezone();
$tz_name = $tz->getName();
// convert to UTC if needed
if ($tz_name != 'UTC') {
$date->setTimezone(new DateTimeZone('UTC'));
}
}
return $date;
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Apr 18, 10:36 AM (10 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
436219
Default Alt Text
(36 KB)
Attached To
Mode
R4 syncroton
Attached
Detach File
Event Timeline
Log In to Comment