Projects
Kolab:3.4:Updates
kolab-syncroton
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 54
View file
kolab-syncroton.spec
Changed
@@ -27,20 +27,19 @@ %global _ap_sysconfdir %{_sysconfdir}/%{httpd_name} Name: kolab-syncroton -Version: 2.2.5 -Release: 2%{?dist} +Version: 2.3 +Release: 0.1.dev20140626.gitf6985b56%{?dist} Summary: ActiveSync for Kolab Groupware Group: Applications/Internet License: LGPLv2 URL: http://www.syncroton.org +# From f6985b56305a1ecb845ee758579fb8e2bb51f15f Source0: http://mirror.kolabsys.com/pub/releases/%{name}-%{version}.tar.gz Source1: kolab-syncroton.logrotate -Patch1: kolab-syncroton-2.2.5-fix-from-header.patch - BuildArch: noarch # Use this build requirement to make sure we are using @@ -78,8 +77,6 @@ %prep %setup -q -n %{name}-%{version} -%patch1 -p1 - rm -rf \ lib/ext/Auth/ \ lib/ext/MDB2/ \
View file
kolab-syncroton-2.2.5-fix-from-header.patch
Deleted
@@ -1,47 +0,0 @@ -commit b2c0912d038584ef92267023045b7c72f74f5517 -Author: Aleksander Machniak <alec@alec.pl> -Date: Mon Feb 3 12:49:22 2014 +0100 - - Added option (activesync_fix_from) to enables adding sender name into the From: header - of send email when a device uses email address only (e.g. iOS devices) - $config['activesync_fix_from'] = false - -diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist -index 2ebe75d..c792377 100644 ---- a/config/main.inc.php.dist -+++ b/config/main.inc.php.dist -@@ -79,3 +79,7 @@ $config['activesync_quiet_time'] = 180; - // 16 - all subscribed folders in shared namespace - // 32 - all folders in shared namespace - $config['activesync_init_subscriptions'] = 0; -+ -+// Enables adding sender name in the From: header of send email -+// when a device uses email address only (e.g. iOS devices) -+$config['activesync_fix_from'] = false; -diff --git a/lib/kolab_sync_message.php b/lib/kolab_sync_message.php -index 026d557..c8b0a47 100644 ---- a/lib/kolab_sync_message.php -+++ b/lib/kolab_sync_message.php -@@ -169,6 +169,22 @@ class kolab_sync_message - if (empty($headers['From'])) { - $headers['From'] = $this->get_identity(); - } -+ // make sure there's sender name in From: -+ else if ($rcube->config->get('activesync_fix_from') -+ && preg_match('/^<?((\S+|("[^"]+"))@\S+)>?$/', trim($headers['From']), $m) -+ ) { -+ $identities = kolab_sync::get_instance()->user->list_identities(); -+ $email = $m[1]; -+ -+ foreach ((array) $identities as $ident) { -+ if ($ident['email'] == $email) { -+ if ($ident['name']) { -+ $headers['From'] = format_email_recipient($email, $ident['name']); -+ } -+ break; -+ } -+ } -+ } - - if (empty($headers['Message-ID'])) { - $headers['Message-ID'] = $rcube->gen_message_id();
View file
debian.changelog
Changed
@@ -1,3 +1,9 @@ +kolab-syncroton (2.3-0~kolab1) unstable; urgency=low + + * New git master head snapshot + + -- Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> Thu, 26 Jun 2014 15:13:40 +0200 + kolab-syncroton (2.2.5-0~kolab2) unstable; urgency=low * Include fix for From: header display name off iOS devices
View file
kolab-syncroton-2.2.5.tar.gz/config/main.inc.php.dist -> kolab-syncroton-2.3.tar.gz/config/main.inc.php.dist
Changed
@@ -79,3 +79,7 @@ // 16 - all subscribed folders in shared namespace // 32 - all folders in shared namespace $config['activesync_init_subscriptions'] = 0; + +// Enables adding sender name in the From: header of send email +// when a device uses email address only (e.g. iOS devices) +$config['activesync_fix_from'] = false;
View file
kolab-syncroton-2.2.5.tar.gz/docs/SQL/mysql.initial.sql -> kolab-syncroton-2.3.tar.gz/docs/SQL/mysql.initial.sql
Changed
@@ -26,6 +26,7 @@ `remotewipe` int(11) DEFAULT '0', `pingfolder` longblob, `lastsynccollection` longblob DEFAULT NULL, + `lastping` datetime DEFAULT NULL, `contactsfilter_id` varchar(40) DEFAULT NULL, `calendarfilter_id` varchar(40) DEFAULT NULL, `tasksfilter_id` varchar(40) DEFAULT NULL, @@ -112,4 +113,4 @@ PRIMARY KEY(`name`) ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */; -INSERT INTO `system` (`name`, `value`) VALUES ('syncroton-version', '2013040900'); +INSERT INTO `system` (`name`, `value`) VALUES ('syncroton-version', '2013100800');
View file
kolab-syncroton-2.3.tar.gz/docs/SQL/mysql/2013100800.sql
Added
@@ -0,0 +1,1 @@ +ALTER TABLE `syncroton_device` ADD `lastping` datetime DEFAULT NULL;
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Backend/ABackend.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Backend/ABackend.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Command + * @package Syncroton + * @subpackage Backend * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync Sync command * - * @package Backend + * @package Syncroton + * @subpackage Backend */ abstract class Syncroton_Backend_ABackend implements Syncroton_Backend_IBackend { @@ -164,6 +166,18 @@ } /** + * 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(); + } + + /** * convert from camelCase to camel_case * @param string $string * @return string
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Backend/Device.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Backend/Device.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Command + * @package Syncroton + * @subpackage Backend * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,9 +12,9 @@ /** * class to handle ActiveSync Sync command * - * @package Backend + * @package Syncroton + * @subpackage Backend */ - class Syncroton_Backend_Device extends Syncroton_Backend_ABackend implements Syncroton_Backend_IDevice { protected $_tableName = 'device';
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Backend/IBackend.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Backend/IBackend.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Command + * @package Syncroton + * @subpackage Backend * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,9 +12,9 @@ /** * class to handle ActiveSync Sync command * - * @package Backend + * @package Syncroton + * @subpackage Backend */ - interface Syncroton_Backend_IBackend { /** @@ -46,5 +47,14 @@ * @param Syncroton_Model_IDevice $_device * @return Syncroton_Model_IDevice */ - public function update($model); + public function update($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); }
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Backend/IDevice.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Backend/IDevice.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Command + * @package Syncroton + * @subpackage Backend * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,9 +12,9 @@ /** * class to handle ActiveSync Sync command * - * @package Backend + * @package Syncroton + * @subpackage Backend */ - interface Syncroton_Backend_IDevice extends Syncroton_Backend_IBackend { /**
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Backend/Policy.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Backend/Policy.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Command + * @package Syncroton + * @subpackage Backend * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,9 +12,9 @@ /** * class to handle ActiveSync Sync command * - * @package Backend + * @package Syncroton + * @subpackage Backend */ - class Syncroton_Backend_Policy extends Syncroton_Backend_ABackend #implements Syncroton_Backend_IDevice { protected $_tableName = 'policy';
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Command/AutoDiscover.php
Added
@@ -0,0 +1,126 @@ +<?php +/** + * Syncroton + * + * @package Syncroton + * @subpackage Command + * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 + * @copyright Copyright (c) 2013-2013 Metaways Infosystems GmbH (http://www.metaways.de) + * @author Lars Kneschke <l.kneschke@metaways.de> + */ + +/** + * class to handle AutoDiscover command + * + * @package Syncroton + * @subpackage Command + */ +class Syncroton_Command_AutoDiscover implements Syncroton_Command_ICommand +{ + /** + * the domDocucment containing the xml request from the client + * + * @var DOMDocument + */ + protected $requestBody; + + protected $emailAddress; + + public $mobileSyncUrl; + + public $certEnrollUrl; + + /** + * constructor of this class + * + * @param DOMDocument $_requestBody + * @param Syncroton_Model_IDevice $_device + * @param string $_policyKey + */ + public function __construct($requestBody, Syncroton_Model_IDevice $device = null, $policyKey = null) + { + $this->requestBody = $requestBody; + } + + /** + * 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('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('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' + ); + } +}
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Command/FolderCreate.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Command/FolderCreate.php
Changed
@@ -60,6 +60,10 @@ 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;
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Command/FolderSync.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Command/FolderSync.php
Changed
@@ -48,7 +48,7 @@ const FOLDERTYPE_CONTACT_USER_CREATED = 14; const FOLDERTYPE_TASK_USER_CREATED = 15; const FOLDERTYPE_JOURNAL_USER_CREATED = 16; - const FOLDERTYPE_NOTES_USER_CREATED = 17; + const FOLDERTYPE_NOTE_USER_CREATED = 17; const FOLDERTYPE_UNKOWN = 18; protected $_defaultNameSpace = 'uri:FolderHierarchy'; @@ -58,6 +58,7 @@ 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 );
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Command/Options.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Command/Options.php
Changed
@@ -19,7 +19,7 @@ { /** * this function generates the response for the client - * + * * @return void */ public function getHeaders() @@ -28,7 +28,7 @@ return array( 'MS-Server-ActiveSync' => '14.00.0536.000', 'MS-ASProtocolVersions' => '2.5,12.0,12.1,14.0,14.1', - 'MS-ASProtocolCommands' => 'CreateCollection,DeleteCollection,FolderCreate,FolderDelete,FolderSync,FolderUpdate,GetAttachment,GetHierarchy,GetItemEstimate,ItemOperations,MeetingResponse,MoveCollection,MoveItems,Provision,ResolveRecipients,Ping,SendMail,Search,Settings,SmartForward,SmartReply,Sync,ValidateCert' + 'MS-ASProtocolCommands' => 'FolderCreate,FolderDelete,FolderSync,FolderUpdate,GetAttachment,GetItemEstimate,ItemOperations,MeetingResponse,MoveItems,Provision,ResolveRecipients,Ping,SendMail,Search,Settings,SmartForward,SmartReply,Sync,ValidateCert' ); - } + } }
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Command/Ping.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Command/Ping.php
Changed
@@ -78,10 +78,12 @@ } $this->_device->pingfolder = serialize(array_keys($folders)); } + } - if ($this->_device->isDirty() && $status == self::STATUS_NO_CHANGES_FOUND) { - $this->_device = $this->_deviceBackend->update($this->_device); - } + $this->_device->lastping = new DateTime('now', new DateTimeZone('utc')); + + if ($status == self::STATUS_NO_CHANGES_FOUND) { + $this->_device = $this->_deviceBackend->update($this->_device); } $lifeTime = $this->_device->pinglifetime; @@ -100,42 +102,66 @@ $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " Folders to monitor($lifeTime / $intervalStart / $intervalEnd / $status): " . print_r($folders, true)); if ($status === self::STATUS_NO_CHANGES_FOUND) { - - $folderWithChanges = array(); - do { // take a break to save battery lifetime sleep(Syncroton_Registry::getPingTimeout()); - + + try { + $device = $this->_deviceBackend->get($this->_device->id); + } catch (Syncroton_Exception_NotFound $e) { + 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) + $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; + } + $now = new DateTime('now', new DateTimeZone('utc')); foreach ($folders as $folderId) { try { $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) $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " " . $e->getMessage()); $status = self::STATUS_FOLDER_NOT_FOUND; + break; + } catch (Exception $e) { 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) { + + // 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; + + // 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);
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Command/Settings.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Command/Settings.php
Changed
@@ -82,18 +82,28 @@ $set->appendChild($this->_outputDom->createElementNS('uri:Settings', 'Status', self::STATUS_SUCCESS)); } - if($this->_userInformationRequested === true) { - $smtpAddresses = array(); - + 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')); - if(!empty($smtpAddresses)) { +/* + $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); + } + } } return $this->_outputDom;
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Command/Sync.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Command/Sync.php
Changed
@@ -235,27 +235,26 @@ 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'); - break; } @@ -780,6 +779,8 @@ } catch (Exception $e) { 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) + $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " unable to convert entry to xml: " . $e->getTraceAsString()); } // mark as sent to the client, even the conversion to xml might have failed
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Command/Wbxml.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Command/Wbxml.php
Changed
@@ -61,14 +61,14 @@ * @var DOMDocument */ protected $_outputDom; - + /** * the domDocucment containing the xml request from the client * * @var DOMDocument */ protected $_requestBody; - + /** * the default namespace *
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Data/AData.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Data/AData.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Data * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,22 +12,17 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Data */ - abstract class Syncroton_Data_AData implements Syncroton_Data_IData { - const LONGID_DELIMITER = "\xe2\x87\x94"; # UTF8 ⇔ - - /** - * used by unit tests only to simulated added folders - */ - public static $changedEntries = array(); + const LONGID_DELIMITER = "\xe2\x87\x94"; # UTF-8 character ⇔ /** - * used by unit tests only to simulated exhausted memory + * @var DateTime */ - public static $exhaustedEntries = array(); + protected $_timeStamp; /** * the constructor @@ -37,7 +33,7 @@ public function __construct(Syncroton_Model_IDevice $_device, DateTime $_timeStamp) { $this->_device = $_device; - $this->_timestamp = $_timeStamp; + $this->_timeStamp = $_timeStamp; $this->_db = Syncroton_Registry::getDatabase(); $this->_tablePrefix = 'Syncroton_'; $this->_ownerId = '1234'; @@ -86,12 +82,12 @@ $id = !empty($folder->serverId) ? $folder->serverId : sha1(mt_rand(). microtime()); $this->_db->insert($this->_tablePrefix . 'data_folder', array( - 'id' => $id, - 'type' => $folder->type, + '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); @@ -106,10 +102,11 @@ $id = sha1(mt_rand(). microtime()); $this->_db->insert($this->_tablePrefix . 'data', array( - 'id' => $id, - 'class' => get_class($_entry), - 'folder_id' => $_folderId, - 'data' => serialize($_entry) + '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; @@ -186,11 +183,25 @@ */ public function getChangedEntries($_folderId, DateTime $_startTimeStamp, DateTime $_endTimeStamp = NULL, $filterType = NULL) { - if (!isset(Syncroton_Data_AData::$changedEntries[get_class($this)])) { - return array(); - } else { - return Syncroton_Data_AData::$changedEntries[get_class($this)]; + $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId; + + $select = $this->_db->select() + ->from($this->_tablePrefix . 'data', array('id')) + ->where('folder_id = ?', $_folderId) + ->where('last_modified_time > ?', $_startTimeStamp->format("Y-m-d H:i:s")); + + if ($_endTimeStamp instanceof DateTime) { + $select->where('last_modified_time < ?', $_endTimeStamp->format("Y-m-d H:i:s")); } + + $ids = array(); + + $stmt = $this->_db->query($select); + while ($id = $stmt->fetchColumn()) { + $ids[] = $id; + } + + return $ids; } /** @@ -229,7 +240,7 @@ /** * @param Syncroton_Model_IFolder|string $_folderId - * @param string $_filter + * @param string $_filter * @return array */ public function getServerEntries($_folderId, $_filter) @@ -280,15 +291,12 @@ * @see Syncroton_Data_IData::getEntry() */ public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId) - { - if (isset(self::$exhaustedEntries[get_class($this)]) && is_array(self::$exhaustedEntries[get_class($this)]) && in_array($serverId, self::$exhaustedEntries[get_class($this)])) { - throw new Syncroton_Exception_MemoryExhausted('memory exchausted for ' . $serverId); - } + { $select = $this->_db->select() ->from($this->_tablePrefix . 'data', array('data')) ->where('id = ?', $serverId); - $stmt = $this->_db->query($select); + $stmt = $this->_db->query($select); $entry = $stmt->fetchColumn(); if ($entry === false) { @@ -327,10 +335,11 @@ * @see Syncroton_Data_IData::updateEntry() */ public function updateEntry($_folderId, $_serverId, Syncroton_Model_IEntry $_entry) - { + { $this->_db->update($this->_tablePrefix . 'data', array( - 'folder_id' => $_folderId, - 'data' => serialize($_entry) + 'folder_id' => $_folderId, + 'last_modified_time' => $this->_timeStamp->format("Y-m-d H:i:s"), + 'data' => serialize($_entry) ), array( 'id = ?' => $_serverId )); @@ -345,7 +354,7 @@ $this->_db->update($this->_tablePrefix . 'data_folder', array( 'name' => $folder->displayName, 'parent_id' => $folder->parentId, - 'last_modified_time' => $this->_timestamp->format('Y-m-d H:i:s') + 'last_modified_time' => $this->_timeStamp->format("Y-m-d H:i:s"), ), array( 'id = ?' => $folder->serverId, 'owner_id = ?' => $this->_ownerId
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Data/Calendar.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Data/Calendar.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Data * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Data */ class Syncroton_Data_Calendar extends Syncroton_Data_AData implements Syncroton_Data_IDataCalendar {
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Data/Contacts.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Data/Contacts.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Data * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Data */ class Syncroton_Data_Contacts extends Syncroton_Data_AData implements Syncroton_Data_IDataSearch
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Data/Email.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Data/Email.php
Changed
@@ -12,7 +12,8 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Data */ class Syncroton_Data_Email extends Syncroton_Data_AData implements Syncroton_Data_IDataEmail {
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Data/Factory.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Data/Factory.php
Changed
@@ -1,9 +1,9 @@ <?php - /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Data * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -12,7 +12,8 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Data */ class Syncroton_Data_Factory @@ -20,6 +21,7 @@ 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'; @@ -49,6 +51,10 @@ $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;
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Data/IData.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Data/IData.php
Changed
@@ -1,9 +1,9 @@ <?php - /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Data * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -12,9 +12,9 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Data */ - interface Syncroton_Data_IData { /**
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Data/IDataCalendar.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Data/IDataCalendar.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Data * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * interface for extended calendar backend * - * @package Model + * @package Syncroton + * @subpackage Data */ interface Syncroton_Data_IDataCalendar {
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Data/IDataEmail.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Data/IDataEmail.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Data * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * interface for extended email backend * - * @package Model + * @package Syncroton + * @subpackage Data */ interface Syncroton_Data_IDataEmail {
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Data/IDataSearch.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Data/IDataSearch.php
Changed
@@ -1,9 +1,9 @@ <?php - /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Data * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @copyright Copyright (c) 2012 Kolab SYstems AG (http://www.kolabsys.com) @@ -14,7 +14,8 @@ /** * class to handle ActiveSync Search command * - * @package Model + * @package Syncroton + * @subpackage Data */ interface Syncroton_Data_IDataSearch {
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Data/Notes.php
Added
@@ -0,0 +1,24 @@ +<?php +/** + * Syncroton + * + * @package Syncroton + * @subpackage Data + * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 + * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) + * @author Lars Kneschke <l.kneschke@metaways.de> + */ + +/** + * class to handle ActiveSync Sync command + * + * @package Syncroton + * @subpackage Data + */ +class Syncroton_Data_Notes extends Syncroton_Data_AData +{ + protected $_supportedFolderTypes = array( + Syncroton_Command_FolderSync::FOLDERTYPE_NOTE, + Syncroton_Command_FolderSync::FOLDERTYPE_NOTE_USER_CREATED + ); +}
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Data/Tasks.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Data/Tasks.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Data * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,9 +12,9 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Data */ - class Syncroton_Data_Tasks extends Syncroton_Data_AData { protected $_supportedFolderTypes = array(
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/Account.php
Added
@@ -0,0 +1,76 @@ +<?php +/** + * Syncroton + * + * @package Syncroton + * @subpackage Model + * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 + * @copyright Copyright (c) 2012-2014 Kolab Systems AG + * @author Aleksander Machniak <machniak@kolabsys.com> + */ + +/** + * 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'), +// 'emailAddresses' => array('type' => 'container'), + ), + 'Internal' => array( + 'primaryAddress' => array('type' => 'string'), + 'addresses' => array('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); + } + } + +}
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/Device.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/Device.php
Changed
@@ -1,9 +1,9 @@ <?php - /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -12,7 +12,8 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Model */ class Syncroton_Model_Device extends Syncroton_Model_AEntry implements Syncroton_Model_IDevice { @@ -21,6 +22,7 @@ const TYPE_ANDROID = 'android'; const TYPE_ANDROID_40 = 'android40'; const TYPE_SMASUNGGALAXYS2 = 'samsunggti9100'; // Samsung Galaxy S-3 + const TYPE_BLACKBERRY = 'blackberry'; /** * Returns major firmware version of this device @@ -29,15 +31,20 @@ */ public function getMajorVersion() { - switch ($this->devicetype) { + switch (strtolower($this->devicetype)) { + case Syncroton_Model_Device::TYPE_BLACKBERRY: + if (preg_match('/(.+)\/(.+)/', $this->useragent, $matches)) { + list(, $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; return $majorVersion; } break; - default: - break; } return 0;
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/DeviceInformation.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/DeviceInformation.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync device information * - * @package Model + * @package Syncroton + * @subpackage Model * @property string friendlyName * @property string iMEI * @property string mobileOperator
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/Email.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/Email.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync email * - * @package Model + * @package Syncroton + * @subpackage Model * @property array attachments * @property string contentType * @property array flag
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/EmailAttachment.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/EmailAttachment.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync event * - * @package Model + * @package Syncroton + * @subpackage Model * @property string class * @property string collectionId * @property bool deletesAsMoves
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/EmailBody.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/EmailBody.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle AirSyncBase:Body * - * @package Model + * @package Syncroton + * @subpackage Model * @property int EstimatedDataSize * @property string Data * @property string Part
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/EmailFlag.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/EmailFlag.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @copyright Copyright (c) 2012-2012 Kolab Systems AG (http://www.kolabsys.com) @@ -13,7 +14,8 @@ /** * class to handle ActiveSync Flag element * - * @package Model + * @package Syncroton + * @subpackage Model * @property DateTime CompleteTime * @property DateTime DateCompleted * @property DateTime DueDate
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/EmailMeetingRequest.php
Added
@@ -0,0 +1,98 @@ +<?php +/** + * Syncroton + * + * @package Syncroton + * @subpackage Model + * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 + * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) + * @author Lars Kneschke <l.kneschke@metaways.de> + */ + +/** + * 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; + + /** + * sensitivity constants + */ + const SENSITIVITY_NORMAL = 0; + const SENSITIVITY_PERSONAL = 1; + const SENSITIVITY_PRIVATE = 2; + 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; + + /** + * 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; + + protected $_dateTimeFormat = "Ymd\THis\Z"; + + 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' => 'datetime'), + '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'), + ), + ); +}
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/EmailRecurrence.php
Added
@@ -0,0 +1,74 @@ +<?php +/** + * Syncroton + * + * @package Syncroton + * @subpackage Model + * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 + * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) + * @author Lars Kneschke <l.kneschke@metaways.de> + */ + +/** + * 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 + + /** + * 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 $_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'), + ) + ); +}
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/Event.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/Event.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync event * - * @package Model + * @package Syncroton + * @subpackage Model * @property string class * @property string collectionId * @property bool deletesAsMoves
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/EventAttendee.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/EventAttendee.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync event * - * @package Model + * @package Syncroton + * @subpackage Model * @property string class * @property string collectionId * @property bool deletesAsMoves
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/EventException.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/EventException.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync event * - * @package Model + * @package Syncroton + * @subpackage Model * @property string class * @property string collectionId * @property bool deletesAsMoves
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/EventRecurrence.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/EventRecurrence.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync event * - * @package Model + * @package Syncroton + * @subpackage Model * @property int CalendarType * @property int DayOfMonth * @property int DayOfWeek
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/FileReference.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/FileReference.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync event * - * @package Model + * @package Syncroton + * @subpackage Model * @property string ContentType * @property string Data */
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/Folder.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/Folder.php
Changed
@@ -3,7 +3,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -12,9 +13,9 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Model */ - class Syncroton_Model_Folder extends Syncroton_Model_AXMLEntry implements Syncroton_Model_IFolder { protected $_xmlBaseElement = array('FolderUpdate', 'FolderCreate');
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/IContent.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/IContent.php
Changed
@@ -1,9 +1,9 @@ <?php - /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -12,7 +12,8 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Model * @property string id * @property string device_id * @property string folder_id @@ -21,7 +22,6 @@ * @property string creation_synckey * @property string is_deleted */ - interface Syncroton_Model_IContent { }
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/IDevice.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/IDevice.php
Changed
@@ -1,9 +1,9 @@ <?php - /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -12,7 +12,8 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Model * @property string id * @property string deviceid * @property string devicetype @@ -37,6 +38,7 @@ * @property string tasksfilter_id * @property string emailfilter_id * @property string lastsynccollection + * @property DateTime lastping */ interface Syncroton_Model_IDevice extends Syncroton_Model_IEntry { @@ -46,6 +48,5 @@ * @return int/string */ public function getMajorVersion(); - }
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/IEntry.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/IEntry.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync contact * - * @package Model + * @package Syncroton + * @subpackage Model * @property string class * @property string collectionId * @property bool deletesAsMoves @@ -19,7 +21,6 @@ * @property string syncKey * @property int windowSize */ - interface Syncroton_Model_IEntry { /**
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/IFolder.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/IFolder.php
Changed
@@ -1,9 +1,9 @@ <?php - /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -12,7 +12,8 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Model * @property string id * @property string deviceId * @property string class @@ -23,9 +24,7 @@ * @property string lastfiltertype * @property string type */ - interface Syncroton_Model_IFolder { - }
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/IPolicy.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/IPolicy.php
Changed
@@ -1,9 +1,9 @@ <?php - /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -12,7 +12,8 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Model * @property string id * @property string deviceid * @property string devicetype @@ -25,7 +26,6 @@ * @property string remotewipe * @property string useragent */ - interface Syncroton_Model_IPolicy { }
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/ISyncState.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/ISyncState.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,14 +12,14 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Model * @property string device_id * @property string type * @property string counter * @property DateTime lastsync * @property string pendingdata */ - interface Syncroton_Model_ISyncState { }
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/IXMLEntry.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/IXMLEntry.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2013 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,9 +12,9 @@ /** * class to handle ActiveSync contact * - * @package Model + * @package Syncroton + * @subpackage Model */ - interface Syncroton_Model_IXMLEntry extends Syncroton_Model_IEntry { /**
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/MeetingResponse.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/MeetingResponse.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle MeetingResponse request * - * @package Model + * @package Syncroton + * @subpackage Model * @property int userResponse * @property string collectionId * @property string calendarId @@ -19,7 +21,6 @@ * @property string instanceId * @property string longId */ - class Syncroton_Model_MeetingResponse extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'Request';
View file
kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/Note.php
Added
@@ -0,0 +1,38 @@ +<?php +/** + * Syncroton + * + * @package Syncroton + * @subpackage Model + * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 + * @copyright Copyright (c) 2014 Kolab Systems AG (http://www.kolabsys.com) + * @author Aleksander Machniak <machniak@kolabsys.com> + */ + +/** + * 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
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/Policy.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/Policy.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,9 +12,9 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Model */ - class Syncroton_Model_Policy extends Syncroton_Model_AXMLEntry implements Syncroton_Model_IPolicy { protected $_xmlBaseElement = 'EASProvisionDoc';
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/SendMail.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/SendMail.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @copyright Copyright (c) 2012-2012 Kolab SYstems AG (http://www.kolabsys.com)
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/SmartForward.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/SmartForward.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @copyright Copyright (c) 2012-2012 KolabSYstems AG (http://www.kolabsys.com)
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/SmartReply.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/SmartReply.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @copyright Copyright (c) 2012-2012 Kolab Systems AG (http://www.kolabsys.com)
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/StoreRequest.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/StoreRequest.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @copyright Copyright (c) 2012 Kolab Systems AG (http://kolabsys.com) @@ -13,7 +14,8 @@ /** * class to handle ActiveSync Search Store request * - * @package Model + * @package Syncroton + * @subpackage Model * @property string name * @property array options * @property array query
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/StoreResponseResult.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/StoreResponseResult.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de>
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/SyncCollection.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/SyncCollection.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync Sync collection * - * @package Model + * @package Syncroton + * @subpackage Model * @property string class * @property string collectionId * @property bool deletesAsMoves
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/SyncState.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/SyncState.php
Changed
@@ -1,9 +1,9 @@ <?php - /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -12,9 +12,9 @@ /** * class to handle ActiveSync Sync command * - * @package Model + * @package Syncroton + * @subpackage Model */ - class Syncroton_Model_SyncState extends Syncroton_Model_AEntry implements Syncroton_Model_ISyncState { }
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/Task.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/Task.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync task * - * @package Model + * @package Syncroton + * @subpackage Model * @property string class * @property string collectionId * @property bool deletesAsMoves
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Model/TaskRecurrence.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Model/TaskRecurrence.php
Changed
@@ -2,7 +2,8 @@ /** * Syncroton * - * @package Model + * @package Syncroton + * @subpackage Model * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3 * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de) * @author Lars Kneschke <l.kneschke@metaways.de> @@ -11,7 +12,8 @@ /** * class to handle ActiveSync event * - * @package Model + * @package Syncroton + * @subpackage Model * @property string class * @property string collectionId * @property bool deletesAsMoves @@ -19,7 +21,6 @@ * @property string syncKey * @property int windowSize */ - class Syncroton_Model_TaskRecurrence extends Syncroton_Model_AXMLEntry { protected $_xmlBaseElement = 'Recurrence';
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Registry.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Registry.php
Changed
@@ -12,8 +12,7 @@ * obtain it through the world-wide-web, please send an email * to license@zend.com so we can send you a copy immediately. * - * @category Syncroton - * @package Syncroton_Registry + * @package Syncroton * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id: Registry.php 10020 2009-08-18 14:34:09Z j.fischer@metaways.de $ @@ -22,8 +21,7 @@ /** * Generic storage class helps to manage global data. * - * @category Syncroton - * @package Syncroton_Registry + * @package Syncroton * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -32,6 +30,7 @@ const CALENDAR_DATA_CLASS = 'calendar_data_class'; const CONTACTS_DATA_CLASS = 'contacts_data_class'; const EMAIL_DATA_CLASS = 'email_data_class'; + const NOTES_DATA_CLASS = 'notes_data_class'; const TASKS_DATA_CLASS = 'tasks_data_class'; const GAL_DATA_CLASS = 'gal_data_class'; @@ -358,6 +357,15 @@ 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)) {
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage0.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage0.php
Changed
@@ -22,7 +22,7 @@ protected $_codePageName = 'AirSync'; - protected $_tags = array( + protected $_tags = array( 'Sync' => 0x05, 'Responses' => 0x06, 'Add' => 0x07,
View file
kolab-syncroton-2.2.5.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage18.php -> kolab-syncroton-2.3.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage18.php
Changed
@@ -49,7 +49,7 @@ 'PhoneNumber' => 0x1c, 'UserInformation' => 0x1d, 'EmailAddresses' => 0x1e, - 'SmtpAddress' => 0x1f, + 'SMTPAddress' => 0x1f, 'UserAgent' => 0x20, 'EnableOutboundSMS' => 0x21, 'MobileOperator' => 0x22,
View file
kolab-syncroton-2.2.5.tar.gz/lib/kolab_sync.php -> kolab-syncroton-2.3.tar.gz/lib/kolab_sync.php
Changed
@@ -43,7 +43,7 @@ public $user; const CHARSET = 'UTF-8'; - const VERSION = "2.2.5"; + const VERSION = "2.3"; /** @@ -149,6 +149,7 @@ Syncroton_Registry::setContactsDataClass('kolab_sync_data_contacts'); Syncroton_Registry::setCalendarDataClass('kolab_sync_data_calendar'); Syncroton_Registry::setEmailDataClass('kolab_sync_data_email'); + Syncroton_Registry::setNotesDataClass('kolab_sync_data_notes'); Syncroton_Registry::setTasksDataClass('kolab_sync_data_tasks'); Syncroton_Registry::setGALDataClass('kolab_sync_data_gal');
View file
kolab-syncroton-2.2.5.tar.gz/lib/kolab_sync_backend.php -> kolab-syncroton-2.3.tar.gz/lib/kolab_sync_backend.php
Changed
@@ -61,6 +61,7 @@ Syncroton_Data_Factory::CLASS_CALENDAR => 'event', Syncroton_Data_Factory::CLASS_CONTACTS => 'contact', Syncroton_Data_Factory::CLASS_EMAIL => 'mail', + Syncroton_Data_Factory::CLASS_NOTES => 'note', Syncroton_Data_Factory::CLASS_TASKS => 'task', ); @@ -251,18 +252,17 @@ */ public function folder_rename($old_name, $new_name, $type, $deviceid) { - $moved = kolab_storage::folder_rename($old_name, $new_name); + $this->folder_meta = null; - if ($moved) { - // UnSet ActiveSync subscription flag - $this->folder_set($old_name, $deviceid, 0); - // Set ActiveSync subscription flag - $this->folder_set($new_name, $deviceid, 1); + $type = self::type_activesync2kolab($type); - return true; + // don't use kolab_storage for moving mail folders + if (preg_match('/^mail/', $type)) { + return $this->storage->rename_folder($old_name, $new_name); + } + else { + return kolab_storage::folder_rename($old_name, $new_name); } - - return false; } @@ -521,9 +521,11 @@ 'mail.outbox', 'event.default', 'contact.default', + 'note.default', 'task.default', 'event', 'contact', + 'note', 'task' );
View file
kolab-syncroton-2.2.5.tar.gz/lib/kolab_sync_backend_common.php -> kolab-syncroton-2.3.tar.gz/lib/kolab_sync_backend_common.php
Changed
@@ -180,6 +180,18 @@ } /** + * Returns list of user accounts + * + * @param Syncroton_Model_Device $device The current device + * + * @return array List of Syncroton_Model_Account objects + */ + public function userAccounts($device) + { + // this method is overwritten by kolab_sync_backend class + } + + /** * Convert array into model object */ protected function get_object($data)
View file
kolab-syncroton-2.2.5.tar.gz/lib/kolab_sync_backend_device.php -> kolab-syncroton-2.3.tar.gz/lib/kolab_sync_backend_device.php
Changed
@@ -122,4 +122,44 @@ return $device; } + + /** + * Returns list of user accounts + * + * @param Syncroton_Model_Device $device The device + * + * @return array List of Syncroton_Model_Account objects + */ + public function userAccounts($device) + { + $engine = kolab_sync::get_instance(); + $identities = $engine->user->list_identities(); + $email = $engine->get_user_email(); + $addresses = array(); + + // read email addresses and display name (default ident comes first) + foreach ((array)$identities as $ident) { + if ($ident['name'] && !isset($displayname)) { + $displayname = $ident['name']; + } + + $addresses[] = $ident['email']; + } + + if (empty($displayname) && empty($email) && empty($addresses)) { + return array(); + } + + $account = new Syncroton_Model_Account; + + if ($email) { + $addresses = array_diff($addresses, array($email)); + } + + $account->userDisplayName = $displayname; + $account->primaryAddress = $email; + $account->addresses = array_unique($addresses); + + return array($account); + } }
View file
kolab-syncroton-2.2.5.tar.gz/lib/kolab_sync_data.php -> kolab-syncroton-2.3.tar.gz/lib/kolab_sync_data.php
Changed
@@ -576,17 +576,6 @@ $result = array_merge($result, $uids); } break; - - case self::RESULT_OBJECT: - default: - $objects = $folder->select($filter); - - if (!is_array($objects)) { - $error = true; - } - else { - $result = array_merge($result, $objects); - } } if ($error) { @@ -1157,7 +1146,7 @@ * * @param mixed $body Body element * @param int $type Result data type (to which the body will be converted, if specified). - * One of Syncroton_Model_EmailBody constants. + * One or array of Syncroton_Model_EmailBody constants. * * @return string Body value */ @@ -1167,16 +1156,73 @@ $data = $body->data; } + if (!$data || empty($type)) { + return; + } + + $type = (array) $type; + // Convert to specified type - if ($data && $type && $body->type != $type) { + if (!in_array($body->type, $type)) { $converter = new kolab_sync_body_converter($data, $body->type); - $data = $converter->convert($type); + $data = $converter->convert($type[0]); } return $data; } /** + * Converts text (plain or html) into ActiveSync Body element. + * Takes bodyPreferences into account and detects if the text is plain or html. + */ + protected function body_from_kolab($body, $collection) + { + if (empty($body)) { + return; + } + + $opts = $collection->options; + $prefs = $opts['bodyPreferences']; + $html_type = Syncroton_Command_Sync::BODY_TYPE_HTML; + $type = Syncroton_Command_Sync::BODY_TYPE_PLAIN_TEXT; + $params = array(); + + // HTML? check for opening and closing <html> or <body> tags + $is_html = preg_match('/<(html|body)(\s+[a-z]|>)/', $body, $m) && strpos($body, '</'.$m[1].'>') > 0; + + // here we assume that all devices support plain text + if ($is_html) { + // device supports HTML... + if (!empty($prefs[$html_type])) { + $type = $html_type; + } + // ...else convert to plain text + else { + $txt = new rcube_html2text($body, false, true); + $body = $txt->get_text(); + } + } + + // strip out any non utf-8 characters + $body = rcube_charset::clean($body); + $real_length = $body_length = strlen($body); + + // truncate the body if needed + if (($trucateAt = $prefs[$type]['truncationSize']) && $body_length > $truncateAt) { + $body = mb_strcut($body, 0, $truncateAt); + $body_length = strlen($body); + + $params['truncated'] = 1; + $params['estimatedDataSize'] = $real_length; + } + + $params['type'] = $type; + + return $this->setBody($body, $params); + } + + + /** * 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
View file
kolab-syncroton-2.2.5.tar.gz/lib/kolab_sync_data_calendar.php -> kolab-syncroton-2.3.tar.gz/lib/kolab_sync_data_calendar.php
Changed
@@ -242,7 +242,7 @@ break; case 'description': - $value = $this->setBody($value); + $value = $this->body_from_kolab($value, $collection); break; }
View file
kolab-syncroton-2.2.5.tar.gz/lib/kolab_sync_data_contacts.php -> kolab-syncroton-2.3.tar.gz/lib/kolab_sync_data_contacts.php
Changed
@@ -156,7 +156,7 @@ break; case 'notes': - $value = $this->setBody($value); + $value = $this->body_from_kolab($value, $collection); break; }
View file
kolab-syncroton-2.2.5.tar.gz/lib/kolab_sync_data_email.php -> kolab-syncroton-2.3.tar.gz/lib/kolab_sync_data_email.php
Changed
@@ -872,13 +872,6 @@ $result = array_merge($result, $uids); } break; -/* - case self::RESULT_OBJECT: - default: - if ($objects = $folder->select($filter)) { - $result = array_merge($result, $objects); - } -*/ } }
View file
kolab-syncroton-2.3.tar.gz/lib/kolab_sync_data_notes.php
Added
@@ -0,0 +1,153 @@ +<?php + +/** + +--------------------------------------------------------------------------+ + | Kolab Sync (ActiveSync for Kolab) | + | | + | Copyright (C) 2011-2014, Kolab Systems AG <contact@kolabsys.com> | + | | + | This program is free software: you can redistribute it and/or modify | + | it under the terms of the GNU Affero General Public License as published | + | by the Free Software Foundation, either version 3 of the License, or | + | (at your option) any later version. | + | | + | This program is distributed in the hope that it will be useful, | + | but WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | + | GNU Affero General Public License for more details. | + | | + | You should have received a copy of the GNU Affero General Public License | + | along with this program. If not, see <http://www.gnu.org/licenses/> | + +--------------------------------------------------------------------------+ + | Author: Aleksander Machniak <machniak@kolabsys.com> | + +--------------------------------------------------------------------------+ +*/ + +/** + * Notes data class for Syncroton + */ +class kolab_sync_data_notes extends kolab_sync_data +{ + /** + * Mapping from ActiveSync Calendar namespace fields + */ + protected $mapping = array( + 'body' => 'description', + 'categories' => 'categories', + 'lastModifiedDate' => 'changed', + //'messageClass' => 'messageClass', + 'subject' => 'title', + ); + + + + /** + * Kolab object type + * + * @var string + */ + protected $modelName = 'note'; + + /** + * Type of the default folder + * + * @var int + */ + protected $defaultFolderType = Syncroton_Command_FolderSync::FOLDERTYPE_NOTE; + + /** + * Default container for new entries + * + * @var string + */ + protected $defaultFolder = 'Notes'; + + /** + * Type of user created folders + * + * @var int + */ + protected $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_NOTE_USER_CREATED; + + + /** + * Appends note data to xml element + * + * @param Syncroton_Model_SyncCollection $collection Collection data + * @param string $serverId Local entry identifier + * @param boolean $as_array Return entry as an array + * + * @return array|Syncroton_Model_Note|array Note object + */ + public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId, $as_array = false) + { + $note = is_array($serverId) ? $serverId : $this->getObject($collection->collectionId, $serverId); + $config = $this->getFolderConfig($note['_mailbox']); + $result = array(); + + // Calendar namespace fields + foreach ($this->mapping as $key => $name) { + $value = $this->getKolabDataItem($note, $name); + + switch ($name) { + case 'changed': + $value = self::date_from_kolab($value); + break; + + case 'description': + $value = $this->body_from_kolab($value, $collection); + break; + } + + if (empty($value) || is_array($value)) { + continue; + } + + $result[$key] = $value; + } + + $result['messageClass'] = 'IPM.StickyNote'; + + return $as_array ? $result : new Syncroton_Model_Note($result); + } + + /** + * convert note from xml to libkolab array + * + * @param Syncroton_Model_IEntry $data Note to convert + * @param string $folderid Folder identifier + * @param array $entry Existing entry + * + * @return array + */ + public function toKolab(Syncroton_Model_IEntry $data, $folderid, $entry = null) + { + $note = !empty($entry) ? $entry : array(); + $foldername = isset($note['_mailbox']) ? $note['_mailbox'] : $this->getFolderName($folderid); + $config = $this->getFolderConfig($foldername); + + // Calendar namespace fields + foreach ($this->mapping as $key => $name) { + $value = $data->$key; + + switch ($name) { + case 'description': + $supported_body_types = array( + Syncroton_Model_EmailBody::TYPE_HTML, + Syncroton_Model_EmailBody::TYPE_PLAINTEXT, + ); + $value = $this->getBody($value, $supported_body_types); + + // If description isn't specified keep old description + if ($value === null) { + continue 2; + } + break; + } + + $this->setKolabDataItem($note, $name, $value); + } + + return $note; + } +}
View file
kolab-syncroton-2.2.5.tar.gz/lib/kolab_sync_data_tasks.php -> kolab-syncroton-2.3.tar.gz/lib/kolab_sync_data_tasks.php
Changed
@@ -113,7 +113,7 @@ $result = array(); // Completion status (required) - $result['complete'] = intval(!empty($task['status']) && $task['status'] == 'COMPLETED'); + $result['complete'] = intval($task['status'] == 'COMPLETED' || $task['complete'] == 100); // Calendar namespace fields foreach ($this->mapping as $key => $name) { @@ -132,7 +132,7 @@ break; case 'description': - $value = $this->setBody($value); + $value = $this->body_from_kolab($value, $collection); break; case 'sensitivity': @@ -204,6 +204,10 @@ $task['status'] = 'COMPLETED'; $task['complete'] = 100; } + else if (isset($data->complete) && ($task['status'] == 'COMPLETED' || $task['complete'] == 100)) { + $task['status'] = ''; + $task['complete'] = 0; + } // recurrence $task['recurrence'] = $this->recurrence_to_kolab($data, $folderid, null);
View file
kolab-syncroton-2.2.5.tar.gz/lib/kolab_sync_message.php -> kolab-syncroton-2.3.tar.gz/lib/kolab_sync_message.php
Changed
@@ -169,6 +169,22 @@ if (empty($headers['From'])) { $headers['From'] = $this->get_identity(); } + // make sure there's sender name in From: + else if ($rcube->config->get('activesync_fix_from') + && preg_match('/^<?((\S+|("[^"]+"))@\S+)>?$/', trim($headers['From']), $m) + ) { + $identities = kolab_sync::get_instance()->user->list_identities(); + $email = $m[1]; + + foreach ((array) $identities as $ident) { + if ($ident['email'] == $email) { + if ($ident['name']) { + $headers['From'] = format_email_recipient($email, $ident['name']); + } + break; + } + } + } if (empty($headers['Message-ID'])) { $headers['Message-ID'] = $rcube->gen_message_id();
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_auth/kolab_auth.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_auth/kolab_auth.php
Changed
@@ -37,6 +37,8 @@ { $rcmail = rcube::get_instance(); + $this->load_config(); + $this->add_hook('authenticate', array($this, 'authenticate')); $this->add_hook('startup', array($this, 'startup')); $this->add_hook('user_create', array($this, 'user_create')); @@ -54,20 +56,28 @@ // Hook to modify some configuration, e.g. ldap $this->add_hook('config_get', array($this, 'config_get')); - $this->add_hook('write_log', array($this, 'write_log')); + // Enable debug logs per-user, this enables logging only after + // user has logged in + if (!empty($_SESSION['username']) && $rcmail->config->get('kolab_auth_auditlog')) { + $this->add_hook('write_log', array($this, 'write_log')); - // TODO: This section does not actually seem to work - if ($rcmail->config->get('kolab_auth_auditlog', false)) { $rcmail->config->set('debug_level', 1); $rcmail->config->set('devel_mode', true); $rcmail->config->set('smtp_log', true); $rcmail->config->set('log_logins', true); $rcmail->config->set('log_session', true); - $rcmail->config->set('sql_debug', true); $rcmail->config->set('memcache_debug', true); $rcmail->config->set('imap_debug', true); $rcmail->config->set('ldap_debug', true); $rcmail->config->set('smtp_debug', true); + $rcmail->config->set('sql_debug', true); + + // SQL debug need to be set directly on DB object + // setting config variable will not work here because + // the object is already initialized/configured + if ($db = $rcmail->get_dbh()) { + $db->set_debug(true); + } } } @@ -86,8 +96,6 @@ // Replaces ldap_vars (%dc, etc) in public kolab ldap addressbooks // config based on the users base_dn. (for multi domain support) if ($args['name'] == 'ldap_public' && !empty($args['result'])) { - $this->load_config(); - $rcmail = rcube::get_instance(); $kolab_books = (array) $rcmail->config->get('kolab_auth_ldap_addressbooks'); @@ -118,8 +126,6 @@ } $rcmail = rcube::get_instance(); - $this->load_config(); - // Example 'kolab_auth_role_plugins' = // @@ -223,52 +229,48 @@ } } + /** + * Logging method replacement to print debug/errors into + * a separate (sub)folder for each user + */ public function write_log($args) { $rcmail = rcube::get_instance(); - if (!$rcmail->config->get('kolab_auth_auditlog', false)) { - return $args; - } - - $args['abort'] = true; - if ($rcmail->config->get('log_driver') == 'syslog') { - $prio = $args['name'] == 'errors' ? LOG_ERR : LOG_INFO; - syslog($prio, $args['line']); return $args; } - else { - $line = sprintf("[%s]: %s\n", $args['date'], $args['line']); - // log_driver == 'file' is assumed here - $log_dir = $rcmail->config->get('log_dir', INSTALL_PATH . 'logs'); - $log_path = $log_dir.'/'.strtolower($_SESSION['kolab_auth_admin']).'/'.strtolower($_SESSION['username']); + $line = sprintf("[%s]: %s\n", $args['date'], $args['line']); - // Append original username + target username - if (!is_dir($log_path)) { - // Attempt to create the directory - if (@mkdir($log_path, 0750, true)) { - $log_dir = $log_path; - } - } - else { + // log_driver == 'file' is assumed here + $log_dir = $rcmail->config->get('log_dir', RCUBE_INSTALL_PATH . 'logs'); + $log_path = $log_dir.'/'.strtolower($_SESSION['kolab_auth_admin']).'/'.strtolower($_SESSION['username']); + + // Append original username + target username + if (!is_dir($log_path)) { + // Attempt to create the directory + if (@mkdir($log_path, 0750, true)) { $log_dir = $log_path; } + } + else { + $log_dir = $log_path; + } - // try to open specific log file for writing - $logfile = $log_dir.'/'.$args['name']; + // try to open specific log file for writing + $logfile = $log_dir.'/'.$args['name']; - if ($fp = fopen($logfile, 'a')) { - fwrite($fp, $line); - fflush($fp); - fclose($fp); - return $args; - } - else { - trigger_error("Error writing to log file $logfile; Please check permissions", E_USER_WARNING); - } + if ($fp = fopen($logfile, 'a')) { + fwrite($fp, $line); + fflush($fp); + fclose($fp); } + else { + trigger_error("Error writing to log file $logfile; Please check permissions", E_USER_WARNING); + } + + $args['abort'] = true; return $args; } @@ -312,7 +314,6 @@ */ public function login_form($args) { - $this->load_config(); $this->add_texts('localization/'); $rcmail = rcube::get_instance(); @@ -401,12 +402,12 @@ $_SESSION['user_roledns'] = (array)($record[$role_attr]); } - if (!empty($imap_attr) && !empty($record[$role_attr])) { + if (!empty($imap_attr) && !empty($record[$imap_attr])) { $default_host = $rcmail->config->get('default_host'); if (!empty($default_host)) { rcube::write_log("errors", "Both default host and kolab_auth_mailhost set. Incompatible."); } else { - $args['host'] = "tls://" . $record[$role_attr]; + $args['host'] = "tls://" . $record[$imap_attr]; } } @@ -640,18 +641,7 @@ return self::$ldap; } - $rcmail = rcube::get_instance(); - - // $this->load_config(); - // we're in static method, load config manually - $fpath = $rcmail->plugins->dir . '/kolab_auth/config.inc.php'; - if (is_file($fpath) && !$rcmail->config->load_from_file($fpath)) { - rcube::raise_error(array( - 'code' => 527, 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Failed to load config from $fpath"), true, false); - } - + $rcmail = rcube::get_instance(); $addressbook = $rcmail->config->get('kolab_auth_addressbook'); if (!is_array($addressbook)) {
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_auth/localization/de_CH.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_auth/localization/de_CH.inc
Changed
@@ -1,5 +1,3 @@ <?php - $labels['loginas'] = 'Anmelden als'; - ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_auth/localization/de_DE.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_auth/localization/de_DE.inc
Changed
@@ -1,5 +1,3 @@ <?php - $labels['loginas'] = 'Anmelden als'; - ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_auth/localization/es_ES.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_auth/localization/es_ES.inc
Changed
@@ -1,5 +1,2 @@ <?php - -$labels['loginas'] = 'Login As'; - ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_auth/localization/et_EE.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_auth/localization/et_EE.inc
Changed
@@ -1,5 +1,2 @@ <?php - -$labels['loginas'] = 'Login As'; - ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_auth/localization/fr_FR.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_auth/localization/fr_FR.inc
Changed
@@ -1,5 +1,3 @@ <?php - $labels['loginas'] = 'Se connecter en tant que'; - ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_auth/localization/ja_JP.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_auth/localization/ja_JP.inc
Changed
@@ -1,5 +1,3 @@ <?php - -$labels['loginas'] = 'Login As'; - +$labels['loginas'] = 'ログイン'; ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_auth/localization/nl_NL.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_auth/localization/nl_NL.inc
Changed
@@ -1,5 +1,3 @@ <?php - $labels['loginas'] = 'Log in als'; - ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_auth/localization/pl_PL.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_auth/localization/pl_PL.inc
Changed
@@ -1,5 +1,3 @@ <?php - $labels['loginas'] = 'Zaloguj jako'; - ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_auth/localization/ru_RU.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_auth/localization/ru_RU.inc
Changed
@@ -1,5 +1,3 @@ <?php - $labels['loginas'] = 'Войти как'; - ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_folders/kolab_folders.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_folders/kolab_folders.php
Changed
@@ -26,8 +26,9 @@ { public $task = '?(?!login).*'; - public $types = array('mail', 'event', 'journal', 'task', 'note', 'contact', 'configuration', 'file', 'freebusy'); + public $types = array('mail', 'event', 'journal', 'task', 'note', 'contact', 'configuration', 'file', 'freebusy'); public $mail_types = array('inbox', 'drafts', 'sentitems', 'outbox', 'wastebasket', 'junkemail'); + public $act_types = array('event', 'task'); private $rc; private static $instance; @@ -86,7 +87,7 @@ // Create default folders if ($args['root'] == '' && $args['name'] = '*') { - $this->create_default_folders($folders, $args['filter'], $folderdata); + $this->create_default_folders($folders, $args['filter'], $folderdata, $args['mode'] == 'LSUB'); } $args['folders'] = $folders; @@ -476,7 +477,7 @@ /** * Creates default folders if they doesn't exist */ - private function create_default_folders(&$folders, $filter, $folderdata = null) + private function create_default_folders(&$folders, $filter, $folderdata = null, $lsub = false) { $storage = $this->rc->get_storage(); $namespace = $storage->get_namespace(); @@ -530,25 +531,54 @@ } list($type1, $type2) = explode('.', $type); - $exists = !empty($folderdata[$foldername]) || $foldername == 'INBOX'; + + $activate = in_array($type1, $this->act_types); + $exists = false; + $result = false; + + // check if folder exists + if (!empty($folderdata[$foldername]) || $foldername == 'INBOX') { + $exists = true; + } + else if ((!$filter || $filter == $type1) && in_array($foldername, $folders)) { + // this assumes also that subscribed folder exists + $exists = true; + } + else { + $exists = $storage->folder_exists($foldername); + } // create folder - if (!$exists && !$storage->folder_exists($foldername)) { - $storage->create_folder($foldername); - $storage->subscribe($foldername); + if (!$exists) { + $exists = $storage->create_folder($foldername); } - // set type - $result = $this->set_folder_type($foldername, $type); + // set type + subscribe + activate + if ($exists) { + if ($result = kolab_storage::set_folder_type($foldername, $type)) { + // check if folder is subscribed + if ((!$filter || $filter == $type1) && $lsub && in_array($foldername, $folders)) { + // already subscribed + $subscribed = true; + } + else { + $subscribed = $storage->subscribe($foldername); + } + + // activate folder + if ($activate) { + kolab_storage::set_state($foldername, true); + } + } + } // add new folder to the result - if ($result && (!$filter || $filter == $type1)) { + if ($result && (!$filter || $filter == $type1) && (!$lsub || $subscribed)) { $folders[] = $foldername; } } } - /** * Static getter for default folder of the given type *
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_folders/localization/de_CH.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_folders/localization/de_CH.inc
Changed
@@ -1,16 +1,14 @@ <?php - -$labels = array(); - $labels['folderctype'] = 'Ordnerinhalt'; $labels['foldertypemail'] = 'E-Mail'; -$labels['foldertypeevent'] = 'Kalender'; // Termine? +$labels['foldertypeevent'] = 'Kalender'; // Events? $labels['foldertypejournal'] = 'Journal'; $labels['foldertypetask'] = 'Aufgaben'; $labels['foldertypenote'] = 'Notizen'; $labels['foldertypecontact'] = 'Kontakte'; $labels['foldertypeconfiguration'] = 'Konfiguration'; - +$labels['foldertypefile'] = 'Dateien'; +$labels['foldertypefreebusy'] = 'Frei-Besetzt'; $labels['default'] = 'Standard'; $labels['inbox'] = 'Posteingang'; $labels['drafts'] = 'Entwürfe'; @@ -18,7 +16,5 @@ $labels['outbox'] = 'Postausgang'; $labels['wastebasket'] = 'Gelöscht'; $labels['junkemail'] = 'Spam'; - $messages['defaultfolderexists'] = 'Es existiert bereits ein Standardordner für den angegebenen Typ'; - ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_folders/localization/de_DE.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_folders/localization/de_DE.inc
Changed
@@ -1,24 +1,20 @@ <?php - -$labels = array(); - $labels['folderctype'] = 'Ordnerinhalt'; $labels['foldertypemail'] = 'E-Mail'; -$labels['foldertypeevent'] = 'Kalender'; // Termine? +$labels['foldertypeevent'] = 'Kalender'; // Events? $labels['foldertypejournal'] = 'Journal'; $labels['foldertypetask'] = 'Aufgaben'; $labels['foldertypenote'] = 'Notizen'; $labels['foldertypecontact'] = 'Kontakte'; $labels['foldertypeconfiguration'] = 'Konfiguration'; - +$labels['foldertypefile'] = 'Dateien'; +$labels['foldertypefreebusy'] = 'Frei/Belegt'; $labels['default'] = 'Standard'; $labels['inbox'] = 'Posteingang'; $labels['drafts'] = 'Entwürfe'; $labels['sentitems'] = 'Gesendet'; $labels['outbox'] = 'Postausgang'; -$labels['wastebasket'] = 'Gelöscht'; +$labels['wastebasket'] = 'Mülleimer'; $labels['junkemail'] = 'Spam'; - -$messages['defaultfolderexists'] = 'Es existiert bereits ein Standardordner für den angegebenen Typ'; - +$messages['defaultfolderexists'] = 'Es gibt bereits einen Standardordner dieses Typs'; ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_folders/localization/es_ES.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_folders/localization/es_ES.inc
Changed
@@ -1,26 +1,7 @@ <?php - -$labels = array(); - -$labels['folderctype'] = 'Content type'; -$labels['foldertypemail'] = 'Mail'; -$labels['foldertypeevent'] = 'Calendar'; // Events? -$labels['foldertypejournal'] = 'Journal'; +$labels['foldertypeevent'] = ''; // Events? $labels['foldertypetask'] = 'Tareas'; $labels['foldertypenote'] = 'Notas'; $labels['foldertypecontact'] = 'Contactos'; $labels['foldertypeconfiguration'] = 'Configuración'; -$labels['foldertypefile'] = 'Files'; -$labels['foldertypefreebusy'] = 'Free-Busy'; - -$labels['default'] = 'Default'; -$labels['inbox'] = 'Inbox'; -$labels['drafts'] = 'Drafts'; -$labels['sentitems'] = 'Sent'; -$labels['outbox'] = 'Outbox'; -$labels['wastebasket'] = 'Trash'; -$labels['junkemail'] = 'Junk'; - -$messages['defaultfolderexists'] = 'There is already default folder of specified type'; - ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_folders/localization/et_EE.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_folders/localization/et_EE.inc
Changed
@@ -1,26 +1,3 @@ <?php - -$labels = array(); - -$labels['folderctype'] = 'Content type'; -$labels['foldertypemail'] = 'Mail'; -$labels['foldertypeevent'] = 'Calendar'; // Events? -$labels['foldertypejournal'] = 'Journal'; -$labels['foldertypetask'] = 'Tasks'; -$labels['foldertypenote'] = 'Notes'; -$labels['foldertypecontact'] = 'Contacts'; -$labels['foldertypeconfiguration'] = 'Configuration'; -$labels['foldertypefile'] = 'Files'; -$labels['foldertypefreebusy'] = 'Free-Busy'; - -$labels['default'] = 'Default'; -$labels['inbox'] = 'Inbox'; -$labels['drafts'] = 'Drafts'; -$labels['sentitems'] = 'Sent'; -$labels['outbox'] = 'Outbox'; -$labels['wastebasket'] = 'Trash'; -$labels['junkemail'] = 'Junk'; - -$messages['defaultfolderexists'] = 'There is already default folder of specified type'; - +$labels['foldertypeevent'] = ''; // Events? ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_folders/localization/fr_FR.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_folders/localization/fr_FR.inc
Changed
@@ -1,7 +1,4 @@ <?php - -$labels = array(); - $labels['folderctype'] = 'Type de contenu'; $labels['foldertypemail'] = 'Courriel'; $labels['foldertypeevent'] = 'Calendrier'; // Events? @@ -12,7 +9,6 @@ $labels['foldertypeconfiguration'] = 'Configuration'; $labels['foldertypefile'] = 'Fichiers'; $labels['foldertypefreebusy'] = 'Disponible/Occupé'; - $labels['default'] = 'Par Défaut'; $labels['inbox'] = 'Courrier entrant'; $labels['drafts'] = 'Brouillons'; @@ -20,7 +16,5 @@ $labels['outbox'] = 'Courrier sortant'; $labels['wastebasket'] = 'Corbeille'; $labels['junkemail'] = 'Indésirables'; - $messages['defaultfolderexists'] = 'Il existe déjà un répertoire par défaut pour le type spécifié'; - ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_folders/localization/ja_JP.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_folders/localization/ja_JP.inc
Changed
@@ -1,26 +1,20 @@ <?php - -$labels = array(); - -$labels['folderctype'] = 'Content type'; -$labels['foldertypemail'] = 'Mail'; -$labels['foldertypeevent'] = 'Calendar'; // Events? -$labels['foldertypejournal'] = 'Journal'; -$labels['foldertypetask'] = 'Tasks'; -$labels['foldertypenote'] = 'Notes'; -$labels['foldertypecontact'] = 'Contacts'; +$labels['folderctype'] = 'コンテンツタイプ'; +$labels['foldertypemail'] = 'メール'; +$labels['foldertypeevent'] = 'カレンダー'; // Events? +$labels['foldertypejournal'] = 'ジャーナル'; +$labels['foldertypetask'] = 'タスク'; +$labels['foldertypenote'] = 'ノート'; +$labels['foldertypecontact'] = 'コンタクト'; $labels['foldertypeconfiguration'] = '設定'; -$labels['foldertypefile'] = 'Files'; -$labels['foldertypefreebusy'] = 'Free-Busy'; - -$labels['default'] = 'Default'; -$labels['inbox'] = 'Inbox'; -$labels['drafts'] = 'Drafts'; -$labels['sentitems'] = 'Sent'; -$labels['outbox'] = 'Outbox'; -$labels['wastebasket'] = 'Trash'; -$labels['junkemail'] = 'Junk'; - -$messages['defaultfolderexists'] = 'There is already default folder of specified type'; - +$labels['foldertypefile'] = 'ファイル'; +$labels['foldertypefreebusy'] = '空状況'; +$labels['default'] = 'デフォルト'; +$labels['inbox'] = '受信箱'; +$labels['drafts'] = '下書き'; +$labels['sentitems'] = '送信済'; +$labels['outbox'] = '送信箱'; +$labels['wastebasket'] = 'ごみ箱'; +$labels['junkemail'] = '迷惑メール'; +$messages['defaultfolderexists'] = '指定したタイプの初期フォルダは既にあります。'; ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_folders/localization/nl_NL.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_folders/localization/nl_NL.inc
Changed
@@ -1,7 +1,4 @@ <?php - -$labels = array(); - $labels['folderctype'] = 'Inhoudstype'; $labels['foldertypemail'] = 'Mail'; $labels['foldertypeevent'] = 'Agenda'; // Events? @@ -12,7 +9,6 @@ $labels['foldertypeconfiguration'] = 'Configuratie'; $labels['foldertypefile'] = 'Bestanden'; $labels['foldertypefreebusy'] = 'Free/Busy'; - $labels['default'] = 'Standaard'; $labels['inbox'] = 'Inbox'; $labels['drafts'] = 'Concepten'; @@ -20,7 +16,5 @@ $labels['outbox'] = 'Te versturen'; $labels['wastebasket'] = 'Prullenbak'; $labels['junkemail'] = 'Ongewenst'; - $messages['defaultfolderexists'] = 'Er is reeds een standaard map voor dit type inhoud'; - ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_folders/localization/pl_PL.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_folders/localization/pl_PL.inc
Changed
@@ -1,23 +1,20 @@ <?php - -$labels = array(); -$labels['folderctype'] = 'Zawartość'; +$labels['folderctype'] = 'Typ treści'; $labels['foldertypemail'] = 'Poczta'; -$labels['foldertypeevent'] = 'Kalendarz'; +$labels['foldertypeevent'] = 'Kalendarz'; // Events? $labels['foldertypejournal'] = 'Dziennik'; $labels['foldertypetask'] = 'Zadania'; $labels['foldertypenote'] = 'Notatki'; $labels['foldertypecontact'] = 'Kontakty'; $labels['foldertypeconfiguration'] = 'Konfiguracja'; $labels['foldertypefile'] = 'Pliki'; -$labels['foldertypefreebusy'] = 'Free-Busy'; +$labels['foldertypefreebusy'] = 'Wolny-Zajęty'; $labels['default'] = 'Domyślny'; $labels['inbox'] = 'Odebrane'; -$labels['drafts'] = 'Szkice'; +$labels['drafts'] = 'Kopie robocze'; $labels['sentitems'] = 'Wysłane'; -$labels['outbox'] = 'Wychodzące'; +$labels['outbox'] = 'Poczta wychodząca'; $labels['wastebasket'] = 'Kosz'; $labels['junkemail'] = 'Spam'; -$messages['defaultfolderexists'] = 'Folder domyślny dla podanego typu już istnieje'; - +$messages['defaultfolderexists'] = 'Folder domyślny wybranego typu już istnieje'; ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/kolab_folders/localization/ru_RU.inc -> kolab-syncroton-2.3.tar.gz/lib/plugins/kolab_folders/localization/ru_RU.inc
Changed
@@ -1,7 +1,4 @@ <?php - -$labels = array(); - $labels['folderctype'] = 'Тип ящика'; $labels['foldertypemail'] = 'Почта'; $labels['foldertypeevent'] = 'Календарь'; // Events? @@ -12,7 +9,6 @@ $labels['foldertypeconfiguration'] = 'Настройки'; $labels['foldertypefile'] = 'Файлы'; $labels['foldertypefreebusy'] = 'Занят/Свободен'; - $labels['default'] = 'По умолчанию'; $labels['inbox'] = 'Входящие'; $labels['drafts'] = 'Черновики'; @@ -20,7 +16,5 @@ $labels['outbox'] = 'Исходящие'; $labels['wastebasket'] = 'Корзина'; $labels['junkemail'] = 'Спам'; - $messages['defaultfolderexists'] = 'Уже назначен ящик по умолчанию для указанного типа'; - ?>
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/SQL/mysql.initial.sql -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/SQL/mysql.initial.sql
Changed
@@ -30,7 +30,7 @@ `created` DATETIME DEFAULT NULL, `changed` DATETIME DEFAULT NULL, `data` TEXT NOT NULL, - `xml` LONGTEXT NOT NULL, + `xml` LONGBLOB NOT NULL, `tags` VARCHAR(255) NOT NULL, `words` TEXT NOT NULL, `type` VARCHAR(32) CHARACTER SET ascii NOT NULL, @@ -49,7 +49,7 @@ `created` DATETIME DEFAULT NULL, `changed` DATETIME DEFAULT NULL, `data` TEXT NOT NULL, - `xml` TEXT NOT NULL, + `xml` LONGBLOB NOT NULL, `tags` VARCHAR(255) NOT NULL, `words` TEXT NOT NULL, `dtstart` DATETIME, @@ -68,7 +68,7 @@ `created` DATETIME DEFAULT NULL, `changed` DATETIME DEFAULT NULL, `data` TEXT NOT NULL, - `xml` TEXT NOT NULL, + `xml` LONGBLOB NOT NULL, `tags` VARCHAR(255) NOT NULL, `words` TEXT NOT NULL, `dtstart` DATETIME, @@ -87,7 +87,7 @@ `created` DATETIME DEFAULT NULL, `changed` DATETIME DEFAULT NULL, `data` TEXT NOT NULL, - `xml` TEXT NOT NULL, + `xml` LONGBLOB NOT NULL, `tags` VARCHAR(255) NOT NULL, `words` TEXT NOT NULL, `dtstart` DATETIME, @@ -106,7 +106,7 @@ `created` DATETIME DEFAULT NULL, `changed` DATETIME DEFAULT NULL, `data` TEXT NOT NULL, - `xml` TEXT NOT NULL, + `xml` LONGBLOB NOT NULL, `tags` VARCHAR(255) NOT NULL, `words` TEXT NOT NULL, CONSTRAINT `fk_kolab_cache_note_folder` FOREIGN KEY (`folder_id`) @@ -123,7 +123,7 @@ `created` DATETIME DEFAULT NULL, `changed` DATETIME DEFAULT NULL, `data` TEXT NOT NULL, - `xml` TEXT NOT NULL, + `xml` LONGBLOB NOT NULL, `tags` VARCHAR(255) NOT NULL, `words` TEXT NOT NULL, `filename` varchar(255) DEFAULT NULL, @@ -142,7 +142,7 @@ `created` DATETIME DEFAULT NULL, `changed` DATETIME DEFAULT NULL, `data` TEXT NOT NULL, - `xml` TEXT NOT NULL, + `xml` LONGBLOB NOT NULL, `tags` VARCHAR(255) NOT NULL, `words` TEXT NOT NULL, `type` VARCHAR(32) CHARACTER SET ascii NOT NULL, @@ -161,7 +161,7 @@ `created` DATETIME DEFAULT NULL, `changed` DATETIME DEFAULT NULL, `data` TEXT NOT NULL, - `xml` TEXT NOT NULL, + `xml` LONGBLOB NOT NULL, `tags` VARCHAR(255) NOT NULL, `words` TEXT NOT NULL, `dtstart` DATETIME, @@ -172,4 +172,4 @@ ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */; -INSERT INTO `system` (`name`, `value`) VALUES ('libkolab-version', '2013110400'); +INSERT INTO `system` (`name`, `value`) VALUES ('libkolab-version', '2013121100');
View file
kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/SQL/mysql/2013121100.sql
Added
@@ -0,0 +1,13 @@ +-- well, these deletes are really optional +-- we can clear all caches or only contacts/events/tasks +-- the issue we're fixing here was about contacts (Bug #2662) +DELETE FROM `kolab_folders` WHERE `type` IN ('contact', 'event', 'task'); + +ALTER TABLE `kolab_cache_contact` CHANGE `xml` `xml` LONGBLOB NOT NULL; +ALTER TABLE `kolab_cache_event` CHANGE `xml` `xml` LONGBLOB NOT NULL; +ALTER TABLE `kolab_cache_task` CHANGE `xml` `xml` LONGBLOB NOT NULL; +ALTER TABLE `kolab_cache_journal` CHANGE `xml` `xml` LONGBLOB NOT NULL; +ALTER TABLE `kolab_cache_note` CHANGE `xml` `xml` LONGBLOB NOT NULL; +ALTER TABLE `kolab_cache_file` CHANGE `xml` `xml` LONGBLOB NOT NULL; +ALTER TABLE `kolab_cache_configuration` CHANGE `xml` `xml` LONGBLOB NOT NULL; +ALTER TABLE `kolab_cache_freebusy` CHANGE `xml` `xml` LONGBLOB NOT NULL;
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/lib/kolab_date_recurrence.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_date_recurrence.php
Changed
@@ -101,7 +101,7 @@ /** * Get the end date of the occurence of this recurrence cycle * - * @return mixed Timestamp with end date of the last event or False if recurrence exceeds limit + * @return DateTime|bool End datetime of the last event or False if recurrence exceeds limit */ public function end() { @@ -109,25 +109,25 @@ // recurrence end date is given if ($event['recurrence']['UNTIL'] instanceof DateTime) { - return $event['recurrence']['UNTIL']->format('U'); + return $event['recurrence']['UNTIL']; } // let libkolab do the work if ($this->engine && ($cend = $this->engine->getLastOccurrence()) && ($end_dt = kolab_format::php_datetime(new cDateTime($cend)))) { - return $end_dt->format('U'); + return $end_dt; } // determine a reasonable end date if none given - if (!$event['recurrence']['COUNT']) { + if (!$event['recurrence']['COUNT'] && $event['end'] instanceof DateTime) { switch ($event['recurrence']['FREQ']) { case 'YEARLY': $intvl = 'P100Y'; break; case 'MONTHLY': $intvl = 'P20Y'; break; default: $intvl = 'P10Y'; break; } - $end_dt = clone $event['start']; + $end_dt = clone $event['end']; $end_dt->add(new DateInterval($intvl)); - return $end_dt->format('U'); + return $end_dt; } return false;
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/lib/kolab_format.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_format.php
Changed
@@ -45,7 +45,7 @@ protected $version = '3.0'; const KTYPE_PREFIX = 'application/x-vnd.kolab.'; - const PRODUCT_ID = 'Roundcube-libkolab-0.9'; + const PRODUCT_ID = 'Roundcube-libkolab-0.9'; /** * Factory method to instantiate a kolab_format object of the given type and version @@ -123,7 +123,7 @@ if (!$dateonly) $result->setTime($datetime->format('G'), $datetime->format('i'), $datetime->format('s')); - if ($tz && in_array($tz->getName(), array('UTC','GMT','+00:00'))) + if ($tz && in_array($tz->getName(), array('UTC', 'GMT', '+00:00', 'Z'))) $result->setUTC(true); else if ($tz !== false) $result->setTimezone($tz->getName()); @@ -242,7 +242,8 @@ break; case kolabformat::Warning: $ret = false; - $log = "Warning"; + $uid = is_object($this->obj) ? $this->obj->uid() : $this->data['uid']; + $log = "Warning @ $uid"; break; default: $ret = true; @@ -496,4 +497,50 @@ { return array(); } + + protected function get_attachments(&$object) + { + // handle attachments + $vattach = $this->obj->attachments(); + for ($i=0; $i < $vattach->size(); $i++) { + $attach = $vattach->get($i); + + // skip cid: attachments which are mime message parts handled by kolab_storage_folder + if (substr($attach->uri(), 0, 4) != 'cid:' && $attach->label()) { + $name = $attach->label(); + $content = $attach->data(); + $object['_attachments'][$name] = array( + 'name' => $name, + 'mimetype' => $attach->mimetype(), + 'size' => strlen($content), + 'content' => $content, + ); + } + else if (substr($attach->uri(), 0, 4) == 'http') { + $object['links'][] = $attach->uri(); + } + } + } + + protected function set_attachments($object) + { + // save attachments + $vattach = new vectorattachment; + foreach ((array) $object['_attachments'] as $cid => $attr) { + if (empty($attr)) + continue; + $attach = new Attachment; + $attach->setLabel((string)$attr['name']); + $attach->setUri('cid:' . $cid, $attr['mimetype']); + $vattach->push($attach); + } + + foreach ((array) $object['links'] as $link) { + $attach = new Attachment; + $attach->setUri($link, 'unknown'); + $vattach->push($attach); + } + + $this->obj->setAttachments($vattach); + } }
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/lib/kolab_format_contact.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_format_contact.php
Changed
@@ -107,8 +107,8 @@ if (isset($object['nickname'])) $this->obj->setNickNames(self::array2vector($object['nickname'])); - if (isset($object['profession'])) - $this->obj->setTitles(self::array2vector($object['profession'])); + if (isset($object['jobtitle'])) + $this->obj->setTitles(self::array2vector($object['jobtitle'])); // organisation related properties (affiliation) $org = new Affiliation; @@ -117,17 +117,17 @@ $org->setOrganisation($object['organization']); if ($object['department']) $org->setOrganisationalUnits(self::array2vector($object['department'])); - if ($object['jobtitle']) - $org->setRoles(self::array2vector($object['jobtitle'])); + if ($object['profession']) + $org->setRoles(self::array2vector($object['profession'])); $rels = new vectorrelated; - if ($object['manager']) { - foreach ((array)$object['manager'] as $manager) - $rels->push(new Related(Related::Text, $manager, Related::Manager)); - } - if ($object['assistant']) { - foreach ((array)$object['assistant'] as $assistant) - $rels->push(new Related(Related::Text, $assistant, Related::Assistant)); + foreach (array('manager','assistant') as $field) { + if (!empty($object[$field])) { + $reltype = $this->relatedmap[$field]; + foreach ((array)$object[$field] as $value) { + $rels->push(new Related(Related::Text, $value, $reltype)); + } + } } $org->setRelateds($rels); @@ -219,12 +219,13 @@ // spouse and children are relateds $rels = new vectorrelated; - if ($object['spouse']) { - $rels->push(new Related(Related::Text, $object['spouse'], Related::Spouse)); - } - if ($object['children']) { - foreach ((array)$object['children'] as $child) - $rels->push(new Related(Related::Text, $child, Related::Child)); + foreach (array('spouse','children') as $field) { + if (!empty($object[$field])) { + $reltype = $this->relatedmap[$field]; + foreach ((array)$object[$field] as $value) { + $rels->push(new Related(Related::Text, $value, $reltype)); + } + } } $this->obj->setRelateds($rels); @@ -296,7 +297,7 @@ $object['prefix'] = join(' ', self::vector2array($nc->prefixes())); $object['suffix'] = join(' ', self::vector2array($nc->suffixes())); $object['nickname'] = join(' ', self::vector2array($this->obj->nickNames())); - $object['profession'] = join(' ', self::vector2array($this->obj->titles())); + $object['jobtitle'] = join(' ', self::vector2array($this->obj->titles())); $object['categories'] = self::vector2array($this->obj->categories()); // organisation related properties (affiliation) @@ -304,7 +305,7 @@ if ($orgs->size()) { $org = $orgs->get(0); $object['organization'] = $org->organisation(); - $object['jobtitle'] = join(' ', self::vector2array($org->roles())); + $object['profession'] = join(' ', self::vector2array($org->roles())); $object['department'] = join(' ', self::vector2array($org->organisationalUnits())); $this->read_relateds($org->relateds(), $object); } @@ -347,10 +348,10 @@ $object['freebusyurl'] = $this->obj->freeBusyUrl(); if ($bday = self::php_datetime($this->obj->bDay())) - $object['birthday'] = $bday->format('c'); + $object['birthday'] = $bday; if ($anniversary = self::php_datetime($this->obj->anniversary())) - $object['anniversary'] = $anniversary->format('c'); + $object['anniversary'] = $anniversary; $gendermap = array_flip($this->gendermap); if (($g = $this->obj->gender()) && $gendermap[$g]) @@ -407,6 +408,22 @@ } /** + * Callback for kolab_storage_cache to get object specific tags to cache + * + * @return array List of tags to save in cache + */ + public function get_tags() + { + $tags = array(); + + if (!empty($this->data['birthday'])) { + $tags[] = 'x-has-birthday'; + } + + return $tags; + } + + /** * Helper method to copy contents of an Address vector to the contact data object */ private function read_addresses($addresses, &$object, $type = null)
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/lib/kolab_format_distributionlist.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_format_distributionlist.php
Changed
@@ -44,17 +44,29 @@ $this->obj->setName($object['name']); + $seen = array(); $members = new vectorcontactref; - foreach ((array)$object['member'] as $member) { - if ($member['uid']) + foreach ((array)$object['member'] as $i => $member) { + if ($member['uid']) { + $key = 'uid:' . $member['uid']; $m = new ContactReference(ContactReference::UidReference, $member['uid']); - else if ($member['email']) + } + else if ($member['email']) { + $key = 'mailto:' . $member['email']; $m = new ContactReference(ContactReference::EmailReference, $member['email']); - else + $m->setName($member['name']); + } + else { continue; - - $m->setName($member['name']); - $members->push($m); + } + + if (!$seen[$key]++) { + $members->push($m); + } + else { + // remove dupes for caching + unset($object['member'][$i]); + } } $this->obj->setMembers($members);
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/lib/kolab_format_note.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_format_note.php
Changed
@@ -31,6 +31,11 @@ protected $read_func = 'readNote'; protected $write_func = 'writeNote'; + protected $sensitivity_map = array( + 'public' => kolabformat::ClassPublic, + 'private' => kolabformat::ClassPrivate, + 'confidential' => kolabformat::ClassConfidential, + ); /** * Set properties to the kolabformat object @@ -42,7 +47,12 @@ // set common object properties parent::set($object); - // TODO: set object propeties + $this->obj->setSummary($object['title']); + $this->obj->setDescription($object['description']); + $this->obj->setClassification($this->sensitivity_map[$object['sensitivity']]); + $this->obj->setCategories(self::array2vector($object['categories'])); + + $this->set_attachments($object); // cache this data $this->data = $object; @@ -73,10 +83,35 @@ // read common object props into local data object $object = parent::to_array($data); - // TODO: read object properties + $sensitivity_map = array_flip($this->sensitivity_map); - $this->data = $object; - return $this->data; + // read object properties + $object += array( + 'sensitivity' => $sensitivity_map[$this->obj->classification()], + 'categories' => self::vector2array($this->obj->categories()), + 'title' => $this->obj->summary(), + 'description' => $this->obj->description(), + ); + + $this->get_attachments($object); + + return $this->data = $object; + } + + /** + * Callback for kolab_storage_cache to get object specific tags to cache + * + * @return array List of tags to save in cache + */ + public function get_tags() + { + $tags = array(); + + foreach ((array) $this->data['categories'] as $cat) { + $tags[] = rcube_utils::normalize_string($cat); + } + + return $tags; } }
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/lib/kolab_format_task.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_format_task.php
Changed
@@ -43,9 +43,14 @@ $this->obj->setPercentComplete(intval($object['complete'])); - if (isset($object['start'])) - $this->obj->setStart(self::get_datetime($object['start'], null, $object['start']->_dateonly)); - + $status = kolabformat::StatusUndefined; + if ($object['complete'] == 100) + $status = kolabformat::StatusCompleted; + else if ($object['status'] && array_key_exists($object['status'], $this->status_map)) + $status = $this->status_map[$object['status']]; + $this->obj->setStatus($status); + + $this->obj->setStart(self::get_datetime($object['start'], null, $object['start']->_dateonly)); $this->obj->setDue(self::get_datetime($object['due'], null, $object['due']->_dateonly)); $related = new vectors; @@ -114,7 +119,7 @@ if ($this->data['priority'] == 1) $tags[] = 'x-flagged'; - if (!empty($this->data['alarms'])) + if (!empty($this->data['valarms'])) $tags[] = 'x-has-alarms'; if ($this->data['parent_id'])
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/lib/kolab_format_xcal.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_format_xcal.php
Changed
@@ -76,7 +76,7 @@ 'AUDIO' => Alarm::AudioAlarm, ); - private $status_map = array( + protected $status_map = array( 'NEEDS-ACTION' => kolabformat::StatusNeedsAction, 'IN-PROCESS' => kolabformat::StatusInProcess, 'COMPLETED' => kolabformat::StatusCompleted, @@ -137,6 +137,16 @@ $attendee = $attvec->get($i); $cr = $attendee->contact(); if ($cr->email() != $object['organizer']['email']) { + $delegators = $delegatees = array(); + $vdelegators = $attendee->delegatedFrom(); + for ($j=0; $j < $vdelegators->size(); $j++) { + $delegators[] = $vdelegators->get($j)->email(); + } + $vdelegatees = $attendee->delegatedTo(); + for ($j=0; $j < $vdelegatees->size(); $j++) { + $delegatees[] = $vdelegatees->get($j)->email(); + } + $object['attendees'][] = array( 'role' => $role_map[$attendee->role()], 'cutype' => $cutype_map[$attendee->cutype()], @@ -144,6 +154,8 @@ 'rsvp' => $attendee->rsvp(), 'email' => $cr->email(), 'name' => $cr->name(), + 'delegated-from' => $delegators, + 'delegated-to' => $delegatees, ); } } @@ -191,6 +203,13 @@ } } + if ($rdates = $this->obj->recurrenceDates()) { + for ($i=0; $i < $rdates->size(); $i++) { + if ($rdate = self::php_datetime($rdates->get($i))) + $object['recurrence']['RDATE'][] = $rdate; + } + } + // read alarm $valarms = $this->obj->alarms(); $alarm_types = array_flip($this->alarm_type_map); @@ -218,26 +237,7 @@ } } - // handle attachments - $vattach = $this->obj->attachments(); - for ($i=0; $i < $vattach->size(); $i++) { - $attach = $vattach->get($i); - - // skip cid: attachments which are mime message parts handled by kolab_storage_folder - if (substr($attach->uri(), 0, 4) != 'cid:' && $attach->label()) { - $name = $attach->label(); - $content = $attach->data(); - $object['_attachments'][$name] = array( - 'name' => $name, - 'mimetype' => $attach->mimetype(), - 'size' => strlen($content), - 'content' => $content, - ); - } - else if (substr($attach->uri(), 0, 4) == 'http') { - $object['links'][] = $attach->uri(); - } - } + $this->get_attachments($object); return $object; } @@ -287,6 +287,21 @@ $att->setCutype($this->cutype_map[$attendee['cutype']] ? $this->cutype_map[$attendee['cutype']] : kolabformat::CutypeIndividual); $att->setRSVP((bool)$attendee['rsvp']); + if (!empty($attendee['delegated-from'])) { + $vdelegators = new vectorcontactref; + foreach ((array)$attendee['delegated-from'] as $delegator) { + $vdelegators->push(new ContactReference(ContactReference::EmailReference, $delegator)); + } + $att->setDelegatedFrom($vdelegators); + } + if (!empty($attendee['delegated-to'])) { + $vdelegatees = new vectorcontactref; + foreach ((array)$attendee['delegated-to'] as $delegatee) { + $vdelegatees->push(new ContactReference(ContactReference::EmailReference, $delegatee)); + } + $att->setDelegatedTo($vdelegatees); + } + if ($att->isValid()) { $attendees->push($att); } @@ -311,7 +326,7 @@ $rr = new RecurrenceRule; $rr->setFrequency(RecurrenceRule::FreqNone); - if ($object['recurrence']) { + if ($object['recurrence'] && !empty($object['recurrence']['FREQ'])) { $rr->setFrequency($this->rrule_type_map[$object['recurrence']['FREQ']]); if ($object['recurrence']['INTERVAL']) @@ -368,6 +383,14 @@ $this->obj->setRecurrenceRule($rr); + // save recurrence dates (aka RDATE) + if (!empty($object['recurrence']['RDATE'])) { + $rdates = new vectordatetime; + foreach ((array)$object['recurrence']['RDATE'] as $rdate) + $rdates->push(self::get_datetime($rdate, null, true)); + $this->obj->setRecurrenceDates($rdates); + } + // save alarm $valarms = new vectoralarm; if ($object['alarms']) { @@ -401,24 +424,7 @@ } $this->obj->setAlarms($valarms); - // save attachments - $vattach = new vectorattachment; - foreach ((array)$object['_attachments'] as $cid => $attr) { - if (empty($attr)) - continue; - $attach = new Attachment; - $attach->setLabel((string)$attr['name']); - $attach->setUri('cid:' . $cid, $attr['mimetype']); - $vattach->push($attach); - } - - foreach ((array)$object['links'] as $link) { - $attach = new Attachment; - $attach->setUri($link, 'unknown'); - $vattach->push($attach); - } - - $this->obj->setAttachments($vattach); + $this->set_attachments($object); } /**
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/lib/kolab_storage.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_storage.php
Changed
@@ -433,13 +433,14 @@ // get username $pos = strpos($folder, $delim); if ($pos) { - $prefix = '('.substr($folder, 0, $pos).') '; + $prefix = '('.substr($folder, 0, $pos).')'; $folder = substr($folder, $pos+1); } else { - $prefix = '('.$folder.')'; + $prefix = $folder; $folder = ''; } + $found = true; $folder_ns = 'other'; break; @@ -467,7 +468,7 @@ $folder = str_replace(html::quote($delim), ' » ', $folder); if ($prefix) - $folder = html::quote($prefix) . ' ' . $folder; + $folder = html::quote($prefix) . ($folder !== '' ? ' ' . $folder : ''); if (!$folder_ns) $folder_ns = 'personal'; @@ -492,7 +493,8 @@ } /** - * Helper method to generate a truncated folder name to display + * Helper method to generate a truncated folder name to display. + * Note: $origname is a string returned by self::object_name() */ public static function folder_displayname($origname, &$names) { @@ -504,10 +506,29 @@ $length = strlen($names[$i] . ' » '); $prefix = substr($name, 0, $length); $count = count(explode(' » ', $prefix)); - $name = str_repeat(' ', $count-1) . '» ' . substr($name, $length); + $diff = 1; + + // check if prefix folder is in other users namespace + for ($n = count($names)-1; $n >= 0; $n--) { + if (strpos($prefix, '(' . $names[$n] . ') ') === 0) { + $diff = 0; + break; + } + } + + $name = str_repeat(' ', $count - $diff) . '» ' . substr($name, $length); + break; + } + // other users namespace and parent folder exists + else if (strpos($name, '(' . $names[$i] . ') ') === 0) { + $length = strlen('(' . $names[$i] . ') '); + $prefix = substr($name, 0, $length); + $count = count(explode(' » ', $prefix)); + $name = str_repeat(' ', $count) . '» ' . substr($name, $length); break; } } + $names[] = $origname; return $name; @@ -525,8 +546,8 @@ */ public static function folder_selector($type, $attrs, $current = '') { - // get all folders of specified type - $folders = self::get_folders($type, false); + // get all folders of specified type (sorted) + $folders = self::get_folders($type, true); $delim = self::$imap->get_hierarchy_delimiter(); $names = array(); @@ -540,13 +561,15 @@ // Filter folders list foreach ($folders as $c_folder) { $name = $c_folder->name; + // skip current folder and it's subfolders if ($len && ($name == $current || strpos($name, $current.$delim) === 0)) { continue; } // always show the parent of current folder - if ($p_len && $name == $parent) { } + if ($p_len && $name == $parent) { + } // skip folders where user have no rights to create subfolders else if ($c_folder->get_owner() != $_SESSION['username']) { $rights = $c_folder->get_myrights(); @@ -555,17 +578,14 @@ } } - $names[$name] = self::object_name($name); - } + // Make sure parent folder is listed (might be skipped e.g. if it's namespace root) + if ($p_len && !isset($names[$parent]) && strpos($name, $parent.$delim) === 0) { + $names[$parent] = self::object_name($parent); + } - // Make sure parent folder is listed (might be skipped e.g. if it's namespace root) - if ($p_len && !isset($names[$parent])) { - $names[$parent] = self::object_name($parent); + $names[$name] = self::object_name($name); } - // Sort folders list - asort($names, SORT_LOCALE_STRING); - // Build SELECT field of parent folder $attrs['is_escaped'] = true; $select = new html_select($attrs); @@ -643,7 +663,8 @@ unset($folderdata[$folder]); } } - return array_keys($folderdata); + + return self::$imap->sort_folder_list(array_keys($folderdata), true); } // Get folders list @@ -683,26 +704,74 @@ */ public static function sort_folders($folders) { - $pad = ' '; + $pad = ' '; + $out = array(); $nsnames = array('personal' => array(), 'shared' => array(), 'other' => array()); + foreach ($folders as $folder) { $folders[$folder->name] = $folder; $ns = $folder->get_namespace(); $nsnames[$ns][$folder->name] = strtolower(html_entity_decode(self::object_name($folder->name, $ns), ENT_COMPAT, RCUBE_CHARSET)) . $pad; // decode » } - $names = array(); - foreach ($nsnames as $ns => $dummy) { - asort($nsnames[$ns], SORT_LOCALE_STRING); - $names += $nsnames[$ns]; + // $folders is a result of get_folders() we can assume folders were already sorted + foreach (array_keys($nsnames) as $ns) { + // asort($nsnames[$ns], SORT_LOCALE_STRING); + foreach (array_keys($nsnames[$ns]) as $utf7name) { + $out[] = $folders[$utf7name]; + } } - $out = array(); - foreach ($names as $utf7name => $name) { - $out[] = $folders[$utf7name]; + return $out; + } + + + /** + * Check the folder tree and add the missing parents as virtual folders + * + * @param array $folders Folders list + * + * @return array Folders list + */ + public static function folder_hierarchy($folders) + { + $_folders = array(); + $existing = array_map(function($folder){ return $folder->get_name(); }, $folders); + $delim = rcube::get_instance()->get_storage()->get_hierarchy_delimiter(); + + foreach ($folders as $idx => $folder) { + $path = explode($delim, $folder->name); + array_pop($path); + + // skip top folders or ones with a custom displayname + if (count($path) <= 1 || kolab_storage::custom_displayname($folder->name)) { + } + else { + $parents = array(); + + while (count($path) > 1 && ($parent = join($delim, $path))) { + $name = kolab_storage::object_name($parent, $folder->get_namespace()); + if (!in_array($name, $existing)) { + $parents[$parent] = new virtual_kolab_storage_folder($parent, $name, $folder->get_namespace()); + $existing[] = $name; + } + + array_pop($path); + } + + if (!empty($parents)) { + $parents = array_reverse(array_values($parents)); + foreach ($parents as $parent) { + $_folders[] = $parent; + } + } + } + + $_folders[] = $folder; + unset($folders[$idx]); } - return $out; + return $_folders; } @@ -1047,3 +1116,33 @@ } } + +/** + * Helper class that represents a virtual IMAP folder + * with a subset of the kolab_storage_folder API. + */ +class virtual_kolab_storage_folder +{ + public $id; + public $name; + public $namespace; + public $virtual = true; + + public function __construct($realname, $name, $ns) + { + $this->id = kolab_storage::folder_id($realname); + $this->name = $name; + $this->namespace = $ns; + } + + public function get_namespace() + { + return $this->namespace; + } + + public function get_name() + { + // this is already kolab_storage::object_name() result + return $this->name; + } +}
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/lib/kolab_storage_cache.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_storage_cache.php
Changed
@@ -24,12 +24,13 @@ class kolab_storage_cache { + const DB_DATE_FORMAT = 'Y-m-d H:i:s'; + protected $db; protected $imap; protected $folder; protected $uid2msg; protected $objects; - protected $index = array(); protected $metadata = array(); protected $folder_id; protected $resource_uri; @@ -43,6 +44,8 @@ protected $max_sync_lock_time = 600; protected $binary_items = array(); protected $extra_cols = array(); + protected $order_by = null; + protected $limit = null; /** @@ -58,8 +61,10 @@ rcube::raise_error(array( 'code' => 900, 'type' => 'php', - 'message' => "No kolab_storage_cache class found for folder of type " . $storage_folder->type + 'message' => "No kolab_storage_cache class found for folder '$storage_folder->name' of type '$storage_folder->type'" ), true); + + return new kolab_storage_cache($storage_folder); } } @@ -85,6 +90,24 @@ $this->set_folder($storage_folder); } + /** + * Direct access to cache by folder_id + * (only for internal use) + */ + public function select_by_id($folder_id) + { + $folders_table = $this->db->table_name('kolab_folders'); + $sql_arr = $this->db->fetch_assoc($this->db->query("SELECT * FROM $folders_table WHERE folder_id=?", $folder_id)); + if ($sql_arr) { + $this->metadata = $sql_arr; + $this->folder_id = $sql_arr['folder_id']; + $this->folder = new StdClass; + $this->folder->type = $sql_arr['type']; + $this->resource_uri = $sql_arr['resource']; + $this->cache_table = $this->db->table_name('kolab_cache_' . $sql_arr['type']); + $this->ready = true; + } + } /** * Connect cache with a storage folder @@ -104,7 +127,7 @@ $this->resource_uri = $this->folder->get_resource_uri(); $this->folders_table = $this->db->table_name('kolab_folders'); $this->cache_table = $this->db->table_name('kolab_cache_' . $this->folder->type); - $this->ready = $this->enabled; + $this->ready = $this->enabled && !empty($this->folder->type); $this->folder_id = null; } @@ -117,6 +140,15 @@ } /** + * Getter for the numeric ID used in cache tables + */ + public function get_folder_id() + { + $this->_read_folder_data(); + return $this->folder_id; + } + + /** * Synchronize local cache data with remote */ public function synchronize() @@ -128,64 +160,71 @@ // increase time limit @set_time_limit($this->max_sync_lock_time); - // read cached folder metadata - $this->_read_folder_data(); - - // check cache status hash first ($this->metadata is set in _read_folder_data()) - if ($this->metadata['ctag'] != $this->folder->get_ctag()) { - // lock synchronization for this folder or wait if locked - $this->_sync_lock(); + if (!$this->ready) { + // kolab cache is disabled, synchronize IMAP mailbox cache only + $this->imap->folder_sync($this->folder->name); + } + else { + // read cached folder metadata + $this->_read_folder_data(); - // disable messages cache if configured to do so - $this->bypass(true); + // check cache status hash first ($this->metadata is set in _read_folder_data()) + if ($this->metadata['ctag'] != $this->folder->get_ctag()) { + // lock synchronization for this folder or wait if locked + $this->_sync_lock(); - // synchronize IMAP mailbox cache - $this->imap->folder_sync($this->folder->name); + // disable messages cache if configured to do so + $this->bypass(true); - // compare IMAP index with object cache index - $imap_index = $this->imap->index($this->folder->name, null, null, true, true); - $this->index = $imap_index->get(); + // synchronize IMAP mailbox cache + $this->imap->folder_sync($this->folder->name); - // determine objects to fetch or to invalidate - if ($this->ready) { - // read cache index - $sql_result = $this->db->query( - "SELECT msguid, uid FROM $this->cache_table WHERE folder_id=?", - $this->folder_id - ); + // compare IMAP index with object cache index + $imap_index = $this->imap->index($this->folder->name, null, null, true, true); - $old_index = array(); - while ($sql_arr = $this->db->fetch_assoc($sql_result)) { - $old_index[] = $sql_arr['msguid']; - $this->uid2msg[$sql_arr['uid']] = $sql_arr['msguid']; - } + // determine objects to fetch or to invalidate + if (!$imap_index->is_error()) { + $imap_index = $imap_index->get(); - // fetch new objects from imap - foreach (array_diff($this->index, $old_index) as $msguid) { - if ($object = $this->folder->read_object($msguid, '*')) { - $this->_extended_insert($msguid, $object); - } - } - $this->_extended_insert(0, null); - - // delete invalid entries from local DB - $del_index = array_diff($old_index, $this->index); - if (!empty($del_index)) { - $quoted_ids = join(',', array_map(array($this->db, 'quote'), $del_index)); - $this->db->query( - "DELETE FROM $this->cache_table WHERE folder_id=? AND msguid IN ($quoted_ids)", + // read cache index + $sql_result = $this->db->query( + "SELECT msguid, uid FROM $this->cache_table WHERE folder_id=?", $this->folder_id ); - } - // update ctag value (will be written to database in _sync_unlock()) - $this->metadata['ctag'] = $this->folder->get_ctag(); - } + $old_index = array(); + while ($sql_arr = $this->db->fetch_assoc($sql_result)) { + $old_index[] = $sql_arr['msguid']; + $this->uid2msg[$sql_arr['uid']] = $sql_arr['msguid']; + } + + // fetch new objects from imap + foreach (array_diff($imap_index, $old_index) as $msguid) { + if ($object = $this->folder->read_object($msguid, '*')) { + $this->_extended_insert($msguid, $object); + } + } + $this->_extended_insert(0, null); + + // delete invalid entries from local DB + $del_index = array_diff($old_index, $imap_index); + if (!empty($del_index)) { + $quoted_ids = join(',', array_map(array($this->db, 'quote'), $del_index)); + $this->db->query( + "DELETE FROM $this->cache_table WHERE folder_id=? AND msguid IN ($quoted_ids)", + $this->folder_id + ); + } - $this->bypass(false); + // update ctag value (will be written to database in _sync_unlock()) + $this->metadata['ctag'] = $this->folder->get_ctag(); + } - // remove lock - $this->_sync_unlock(); + $this->bypass(false); + + // remove lock + $this->_sync_unlock(); + } } $this->synched = time(); @@ -220,14 +259,14 @@ ); if ($sql_arr = $this->db->fetch_assoc($sql_result)) { - $this->objects[$msguid] = $this->_unserialize($sql_arr); + $this->objects = array($msguid => $this->_unserialize($sql_arr)); // store only this object in memory (#2827) } } // fetch from IMAP if not present in cache if (empty($this->objects[$msguid])) { $result = $this->_fetch(array($msguid), $type, $foldername); - $this->objects[$msguid] = $result[0]; + $this->objects = array($msguid => $result[0]); // store only this object in memory (#2827) } } @@ -263,7 +302,7 @@ if ($object) { // insert new object data... - $this->insert($msguid, $object); + $this->save($msguid, $object); } else { // ...or set in-memory cache to false @@ -273,41 +312,48 @@ /** - * Insert a cache entry + * Insert (or update) a cache entry * - * @param string Related IMAP message UID + * @param int Related IMAP message UID * @param mixed Hash array with object properties to save or false to delete the cache entry + * @param int Optional old message UID (for update) */ - public function insert($msguid, $object) + public function save($msguid, $object, $olduid = null) { // write to cache if ($this->ready) { $this->_read_folder_data(); $sql_data = $this->_serialize($object); + $sql_data['folder_id'] = $this->folder_id; + $sql_data['msguid'] = $msguid; + $sql_data['uid'] = $object['uid']; - $extra_cols = $this->extra_cols ? ', ' . join(', ', $this->extra_cols) : ''; - $extra_fields = $this->extra_cols ? str_repeat(', ?', count($this->extra_cols)) : ''; + $args = array(); + $cols = array('folder_id', 'msguid', 'uid', 'changed', 'data', 'xml', 'tags', 'words'); + $cols = array_merge($cols, $this->extra_cols); - $args = array( - "INSERT INTO $this->cache_table ". - " (folder_id, msguid, uid, created, changed, data, xml, tags, words $extra_cols)". - " VALUES (?, ?, ?, " . $this->db->now() . ", ?, ?, ?, ?, ? $extra_fields)", - $this->folder_id, - $msguid, - $object['uid'], - $sql_data['changed'], - $sql_data['data'], - $sql_data['xml'], - $sql_data['tags'], - $sql_data['words'], - ); + foreach ($cols as $idx => $col) { + $cols[$idx] = $this->db->quote_identifier($col); + $args[] = $sql_data[$col]; + } - foreach ($this->extra_cols as $col) { - $args[] = $sql_data[$col]; + if ($olduid) { + foreach ($cols as $idx => $col) { + $cols[$idx] = "$col = ?"; + } + + $query = "UPDATE $this->cache_table SET " . implode(', ', $cols) + . " WHERE folder_id = ? AND msguid = ?"; + $args[] = $this->folder_id; + $args[] = $olduid; + } + else { + $query = "INSERT INTO $this->cache_table (created, " . implode(', ', $cols) + . ") VALUES (" . $this->db->now() . str_repeat(', ?', count($cols)) . ")"; } - $result = call_user_func_array(array($this->db, 'query'), $args); + $result = $this->db->query($query, $args); if (!$this->db->affected_rows($result)) { rcube::raise_error(array( @@ -332,22 +378,27 @@ */ public function move($msguid, $uid, $target_folder) { - $target = kolab_storage::get_folder($target_folder); + if ($this->ready) { + $target = kolab_storage::get_folder($target_folder); - // resolve new message UID in target folder - if ($new_msguid = $target->cache->uid2msguid($uid)) { - $this->_read_folder_data(); + // resolve new message UID in target folder + if ($new_msguid = $target->cache->uid2msguid($uid)) { + $this->_read_folder_data(); - $this->db->query( - "UPDATE $this->cache_table SET folder_id=?, msguid=? ". - "WHERE folder_id=? AND msguid=?", - $target->folder_id, - $new_msguid, - $this->folder_id, - $msguid - ); + $this->db->query( + "UPDATE $this->cache_table SET folder_id=?, msguid=? ". + "WHERE folder_id=? AND msguid=?", + $target->cache->get_folder_id(), + $new_msguid, + $this->folder_id, + $msguid + ); + + $result = $this->db->affected_rows(); + } } - else { + + if (empty($result)) { // just clear cache entry $this->set($msguid, false); } @@ -361,12 +412,17 @@ */ public function purge($type = null) { + if (!$this->ready) { + return true; + } + $this->_read_folder_data(); $result = $this->db->query( "DELETE FROM $this->cache_table WHERE folder_id=?", $this->folder_id ); + return $this->db->affected_rows($result); } @@ -377,6 +433,10 @@ */ public function rename($new_folder) { + if (!$this->ready) { + return; + } + $target = kolab_storage::get_folder($new_folder); // resolve new message UID in target folder @@ -398,51 +458,67 @@ */ public function select($query = array(), $uids = false) { - $result = array(); + $result = $uids ? array() : new kolab_storage_dataset($this); // read from local cache DB (assume it to be synchronized) if ($this->ready) { $this->_read_folder_data(); - $sql_result = $this->db->query( - "SELECT " . ($uids ? 'msguid, uid' : '*') . " FROM $this->cache_table ". - "WHERE folder_id=? " . $this->_sql_where($query), - $this->folder_id - ); + // fetch full object data on one query if a small result set is expected + $fetchall = !$uids && ($this->limit ? $this->limit[0] : $this->count($query)) < 500; + $sql_query = "SELECT " . ($fetchall ? '*' : 'msguid AS _msguid, uid') . " FROM $this->cache_table ". + "WHERE folder_id=? " . $this->_sql_where($query); + if (!empty($this->order_by)) { + $sql_query .= ' ORDER BY ' . $this->order_by; + } + $sql_result = $this->limit ? + $this->db->limitquery($sql_query, $this->limit[1], $this->limit[0], $this->folder_id) : + $this->db->query($sql_query, $this->folder_id); if ($this->db->is_error($sql_result)) { - return null; + if ($uids) { + return null; + } + $result->set_error(true); + return $result; } while ($sql_arr = $this->db->fetch_assoc($sql_result)) { if ($uids) { - $this->uid2msg[$sql_arr['uid']] = $sql_arr['msguid']; + $this->uid2msg[$sql_arr['uid']] = $sql_arr['_msguid']; $result[] = $sql_arr['uid']; } - else if ($object = $this->_unserialize($sql_arr)) { + else if ($fetchall && ($object = $this->_unserialize($sql_arr))) { $result[] = $object; } + else { + // only add msguid to dataset index + $result[] = $sql_arr; + } } } + // use IMAP else { - // extract object type from query parameter $filter = $this->_query2assoc($query); - // use 'list' for folder's default objects - if ($filter['type'] == $this->type) { - $index = $this->index; - } - else { // search by object type + if ($filter['type']) { $search = 'UNDELETED HEADER X-Kolab-Type ' . kolab_format::KTYPE_PREFIX . $filter['type']; - $index = $this->imap->search_once($this->folder->name, $search)->get(); + $index = $this->imap->search_once($this->folder->name, $search); + } + else { + $index = $this->imap->index($this->folder->name, null, null, true, true); } if ($index->is_error()) { - return null; + if ($uids) { + return null; + } + $result->set_error(true); + return $result; } - // fetch all messages in $index from IMAP - $result = $uids ? $this->_fetch_uids($index, $filter['type']) : $this->_fetch($index, $filter['type']); + $index = $index->get(); + $result = $uids ? $index : $this->_fetch($index, $filter['type']); // TODO: post-filter result according to query } @@ -452,7 +528,7 @@ if (!$uids && count($result) == 1) { if ($msguid = $result[0]['_msguid']) { $this->uid2msg[$result[0]['uid']] = $msguid; - $this->objects[$msguid] = $result[0]; + $this->objects = array($msguid => $result[0]); } } @@ -468,8 +544,8 @@ */ public function count($query = array()) { - // cache is in sync, we can count records in local DB - if ($this->synched) { + // read from local cache DB (assume it to be synchronized) + if ($this->ready) { $this->_read_folder_data(); $sql_result = $this->db->query( @@ -485,22 +561,50 @@ $sql_arr = $this->db->fetch_assoc($sql_result); $count = intval($sql_arr['numrows']); } + // use IMAP else { - // search IMAP by object type $filter = $this->_query2assoc($query); - $ctype = kolab_format::KTYPE_PREFIX . $filter['type']; - $index = $this->imap->search_once($this->folder->name, 'UNDELETED HEADER X-Kolab-Type ' . $ctype); + + if ($filter['type']) { + $search = 'UNDELETED HEADER X-Kolab-Type ' . kolab_format::KTYPE_PREFIX . $filter['type']; + $index = $this->imap->search_once($this->folder->name, $search); + } + else { + $index = $this->imap->index($this->folder->name, null, null, true, true); + } if ($index->is_error()) { return null; } + // TODO: post-filter result according to query + $count = $index->count(); } return $count; } + /** + * Define ORDER BY clause for cache queries + */ + public function set_order_by($sortcols) + { + if (!empty($sortcols)) { + $this->order_by = join(', ', (array)$sortcols); + } + else { + $this->order_by = null; + } + } + + /** + * Define LIMIT clause for cache queries + */ + public function set_limit($length, $offset = 0) + { + $this->limit = array($length, $offset); + } /** * Helper method to compose a valid SQL query from pseudo filter triplets @@ -571,7 +675,7 @@ */ protected function _fetch($index, $type = null, $folder = null) { - $results = array(); + $results = new kolab_storage_dataset($this); foreach ((array)$index as $msguid) { if ($object = $this->folder->read_object($msguid, $type, $folder)) { $results[] = $object; @@ -582,43 +686,6 @@ return $results; } - - /** - * Fetch object UIDs (aka message subjects) from IMAP - * - * @param array List of message UIDs to fetch - * @param string Requested object type or * for all - * @param string IMAP folder to read from - * @return array List of parsed Kolab objects - */ - protected function _fetch_uids($index, $type = null) - { - if (!$type) - $type = $this->folder->type; - - $this->bypass(true); - - $results = array(); - $headers = $this->imap->fetch_headers($this->folder->name, $index, false); - - $this->bypass(false); - - foreach ((array)$headers as $msguid => $headers) { - $object_type = kolab_format::mime2object_type($headers->others['x-kolab-type']); - - // check object type header and abort on mismatch - if ($type != '*' && $object_type != $type) - return false; - - $uid = $headers->subject; - $this->uid2msg[$uid] = $msguid; - $results[] = $uid; - } - - return $results; - } - - /** * Helper method to convert the given Kolab object into a dataset to be written to cache */ @@ -659,7 +726,9 @@ } } - $sql_data['data'] = serialize($data); + // use base64 encoding (Bug #1912, #2662) + $sql_data['data'] = base64_encode(serialize($data)); + return $sql_data; } @@ -668,8 +737,23 @@ */ protected function _unserialize($sql_arr) { + // check if data is a base64-encoded string, for backward compat. + if (strpos(substr($sql_arr['data'], 0, 64), ':') === false) { + $sql_arr['data'] = base64_decode($sql_arr['data']); + } + $object = unserialize($sql_arr['data']); + // de-serialization failed + if ($object === false) { + rcube::raise_error(array( + 'code' => 900, 'type' => 'php', + 'message' => "Malformed data for {$this->resource_uri}/{$sql_arr['msguid']} object." + ), true); + + return null; + } + // decode binary properties foreach ($this->binary_items as $key => $regexp) { if (!empty($object[$key]) && preg_match($regexp, $sql_arr['xml'], $m)) { @@ -678,10 +762,10 @@ } // add meta data - $object['_type'] = $sql_arr['type'] ?: $this->folder->type; - $object['_msguid'] = $sql_arr['msguid']; - $object['_mailbox'] = $this->folder->name; - $object['_size'] = strlen($sql_arr['xml']); + $object['_type'] = $sql_arr['type'] ?: $this->folder->type; + $object['_msguid'] = $sql_arr['msguid']; + $object['_mailbox'] = $this->folder->name; + $object['_size'] = strlen($sql_arr['xml']); $object['_formatobj'] = kolab_format::factory($object['_type'], 3.0, $sql_arr['xml']); return $object; @@ -757,7 +841,7 @@ protected function _read_folder_data() { // already done - if (!empty($this->folder_id)) + if (!empty($this->folder_id) || !$this->ready) return; $sql_arr = $this->db->fetch_assoc($this->db->query("SELECT folder_id, synclock, ctag FROM $this->folders_table WHERE resource=?", $this->resource_uri));
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/lib/kolab_storage_cache_contact.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_storage_cache_contact.php
Changed
@@ -23,7 +23,7 @@ class kolab_storage_cache_contact extends kolab_storage_cache { - protected $extra_cols = array('type'); + protected $extra_cols = array('type','name','firstname','surname','email'); protected $binary_items = array( 'photo' => '|<photo><uri>[^;]+;base64,([^<]+)</uri></photo>|i', 'pgppublickey' => '|<key><uri>date:application/pgp-keys;base64,([^<]+)</uri></key>|i', @@ -40,6 +40,20 @@ $sql_data = parent::_serialize($object); $sql_data['type'] = $object['_type']; + // columns for sorting + $sql_data['name'] = rcube_charset::clean($object['name'] . $object['prefix']); + $sql_data['firstname'] = rcube_charset::clean($object['firstname'] . $object['middlename'] . $object['surname']); + $sql_data['surname'] = rcube_charset::clean($object['surname'] . $object['firstname'] . $object['middlename']); + $sql_data['email'] = rcube_charset::clean(is_array($object['email']) ? $object['email'][0] : $object['email']); + + if (is_array($sql_data['email'])) { + $sql_data['email'] = $sql_data['email']['address']; + } + // avoid value being null + if (empty($sql_data['email'])) { + $sql_data['email'] = ''; + } + return $sql_data; } } \ No newline at end of file
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/lib/kolab_storage_cache_event.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_storage_cache_event.php
Changed
@@ -34,14 +34,14 @@ { $sql_data = parent::_serialize($object); - // database runs in server's timezone so using date() is what we want - $sql_data['dtstart'] = date('Y-m-d H:i:s', is_object($object['start']) ? $object['start']->format('U') : $object['start']); - $sql_data['dtend'] = date('Y-m-d H:i:s', is_object($object['end']) ? $object['end']->format('U') : $object['end']); + $sql_data['dtstart'] = is_object($object['start']) ? $object['start']->format(self::DB_DATE_FORMAT) : date(self::DB_DATE_FORMAT, $object['start']); + $sql_data['dtend'] = is_object($object['end']) ? $object['end']->format(self::DB_DATE_FORMAT) : date(self::DB_DATE_FORMAT, $object['end']); // extend date range for recurring events if ($object['recurrence'] && $object['_formatobj']) { $recurrence = new kolab_date_recurrence($object['_formatobj']); - $sql_data['dtend'] = date('Y-m-d 23:59:59', $recurrence->end() ?: strtotime('now +10 years')); + $dtend = $recurrence->end() ?: new DateTime('now +10 years'); + $sql_data['dtend'] = $dtend->format(self::DB_DATE_FORMAT); } return $sql_data;
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/lib/kolab_storage_cache_task.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_storage_cache_task.php
Changed
@@ -35,9 +35,9 @@ $sql_data = parent::_serialize($object) + array('dtstart' => null, 'dtend' => null); if ($object['start']) - $sql_data['dtstart'] = date('Y-m-d H:i:s', is_object($object['start']) ? $object['start']->format('U') : $object['start']); + $sql_data['dtstart'] = is_object($object['start']) ? $object['start']->format(self::DB_DATE_FORMAT) : date(self::DB_DATE_FORMAT, $object['start']); if ($object['due']) - $sql_data['dtend'] = date('Y-m-d H:i:s', is_object($object['due']) ? $object['due']->format('U') : $object['due']); + $sql_data['dtend'] = is_object($object['due']) ? $object['due']->format(self::DB_DATE_FORMAT) : date(self::DB_DATE_FORMAT, $object['due']); return $sql_data; }
View file
kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_storage_dataset.php
Added
@@ -0,0 +1,154 @@ +<?php + +/** + * Dataset class providing the results of a select operation on a kolab_storage_folder. + * + * Can be used as a normal array as well as an iterator in foreach() loops. + * + * @version @package_version@ + * @author Thomas Bruederli <bruederli@kolabsys.com> + * + * Copyright (C) 2014, Kolab Systems AG <contact@kolabsys.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +class kolab_storage_dataset implements Iterator, ArrayAccess, Countable +{ + private $cache; // kolab_storage_cache instance to use for fetching data + private $memlimit = 0; + private $buffer = false; + private $index = array(); + private $data = array(); + private $iteratorkey = 0; + private $error = null; + + /** + * Default constructor + * + * @param object kolab_storage_cache instance to be used for fetching objects upon access + */ + public function __construct($cache) + { + $this->cache = $cache; + + // enable in-memory buffering up until 1/5 of the available memory + if (function_exists('memory_get_usage')) { + $this->memlimit = parse_bytes(ini_get('memory_limit')) / 5; + $this->buffer = true; + } + } + + /** + * Return error state + */ + public function is_error() + { + return !empty($this->error); + } + + /** + * Set error state + */ + public function set_error($err) + { + $this->error = $err; + } + + + /*** Implement PHP Countable interface ***/ + + public function count() + { + return count($this->index); + } + + + /*** Implement PHP ArrayAccess interface ***/ + + public function offsetSet($offset, $value) + { + $uid = $value['_msguid']; + + if (is_null($offset)) { + $offset = count($this->index); + $this->index[] = $uid; + } + else { + $this->index[$offset] = $uid; + } + + // keep full payload data in memory if possible + if ($this->memlimit && $this->buffer && isset($value['_mailbox'])) { + $this->data[$offset] = $value; + + // check memory usage and stop buffering + if ($offset % 10 == 0) { + $this->buffer = memory_get_usage() < $this->memlimit; + } + } + } + + public function offsetExists($offset) + { + return isset($this->index[$offset]); + } + + public function offsetUnset($offset) + { + unset($this->index[$offset]); + } + + public function offsetGet($offset) + { + if (isset($this->data[$offset])) { + return $this->data[$offset]; + } + else if ($msguid = $this->index[$offset]) { + return $this->cache->get($msguid); + } + + return null; + } + + + /*** Implement PHP Iterator interface ***/ + + public function current() + { + return $this->offsetGet($this->iteratorkey); + } + + public function key() + { + return $this->iteratorkey; + } + + public function next() + { + $this->iteratorkey++; + return $this->valid(); + } + + public function rewind() + { + $this->iteratorkey = 0; + } + + public function valid() + { + return !empty($this->index[$this->iteratorkey]); + } + +}
View file
kolab-syncroton-2.2.5.tar.gz/lib/plugins/libkolab/lib/kolab_storage_folder.php -> kolab-syncroton-2.3.tar.gz/lib/plugins/libkolab/lib/kolab_storage_folder.php
Changed
@@ -74,9 +74,9 @@ * @param string The folder name/path * @param string Optional folder type if known */ - public function set_folder($name, $ftype = null) + public function set_folder($name, $type = null) { - $this->type_annotation = $ftype ? $ftype : kolab_storage::folder_type($name); + $this->type_annotation = $type ? $type : kolab_storage::folder_type($name); $oldtype = $this->type; list($this->type, $suffix) = explode('.', $this->type_annotation); @@ -92,7 +92,6 @@ $this->cache->set_folder($this); } - /** * */ @@ -280,7 +279,7 @@ } // generate a folder UID and set it to IMAP - $uid = rtrim(chunk_split(md5($this->name . $this->get_owner()), 12, '-'), '-'); + $uid = rtrim(chunk_split(md5($this->name . $this->get_owner() . uniqid('-', true)), 12, '-'), '-'); $this->set_uid($uid); return $uid; @@ -424,6 +423,21 @@ return $this->cache->select($this->_prepare_query($query), true); } + /** + * Setter for ORDER BY and LIMIT parameters for cache queries + * + * @param array List of columns to order by + * @param integer Limit result set to this length + * @param integer Offset row + */ + public function set_order_and_limit($sortcols, $length = null, $offset = 0) + { + $this->cache->set_order_by($sortcols); + + if ($length !== null) { + $this->cache->set_limit($length, $offset); + } + } /** * Helper method to sanitize query arguments @@ -753,24 +767,27 @@ $result = $this->imap->save_message($this->name, $raw_msg, null, false, null, null, $binary); - // delete old message - if ($result && !empty($object['_msguid']) && !empty($object['_mailbox'])) { - $this->cache->bypass(true); - $this->imap->delete_message($object['_msguid'], $object['_mailbox']); - $this->cache->bypass(false); - $this->cache->set($object['_msguid'], false, $object['_mailbox']); - } - // update cache with new UID if ($result) { + $old_uid = $object['_msguid']; + $object['_msguid'] = $result; $object['_mailbox'] = $this->name; - $this->cache->insert($result, $object); - // remove temp file - if ($body_file) { - @unlink($body_file); + if ($old_uid) { + // delete old message + $this->cache->bypass(true); + $this->imap->delete_message($old_uid, $object['_mailbox']); + $this->cache->bypass(false); } + + // insert/update message in cache + $this->cache->save($result, $object, $old_uid); + } + + // remove temp file + if ($body_file) { + @unlink($body_file); } } @@ -806,7 +823,7 @@ $recurrence = new kolab_date_recurrence($object['_formatobj']); if ($end = $recurrence->end()) { unset($exception['recurrence']['COUNT']); - $exception['recurrence']['UNTIL'] = new DateTime('@'.$end); + $exception['recurrence']['UNTIL'] = $end; } }
View file
kolab-syncroton.dsc
Changed
@@ -2,7 +2,7 @@ Source: kolab-syncroton Binary: kolab-syncroton Architecture: all -Version: 2.2.5-0~kolab2 +Version: 2.3~dev20140626-0~kolab1 Maintainer: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> Uploaders: Paul Klos <kolab@klos2day.nl> Homepage: http://www.kolab.org/ @@ -12,5 +12,5 @@ Package-List: kolab-syncroton deb utils extra Files: - 00000000000000000000000000000000 0 kolab-syncroton-2.2.5.tar.gz + 00000000000000000000000000000000 0 kolab-syncroton-2.3.tar.gz 00000000000000000000000000000000 0 debian.tar.gz
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.