Page MenuHomePhorge

No OneTemporary

Size
36 KB
Referenced Files
None
Subscribers
None
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

Mime Type
text/x-diff
Expires
Sat, Apr 18, 10:36 AM (12 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
436219
Default Alt Text
(36 KB)

Event Timeline