Projects
Kolab:16:Testing:Candidate
kolab-syncroton
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 36
View file
kolab-syncroton.spec
Changed
@@ -37,7 +37,7 @@ %global upstream_version 2.4.2 Name: kolab-syncroton -Version: 2.4.2.10 +Version: 2.4.2.11 Release: 1%{?dist} Summary: ActiveSync for Kolab Groupware
View file
debian.changelog
Changed
@@ -1,4 +1,4 @@ -kolab-syncroton (2.4.2.10-0~kolab1) unstable; urgency=low +kolab-syncroton (2.4.2.11-0~kolab1) unstable; urgency=low * Release version 2.4.2
View file
kolab-syncroton-2.4.2.tar.gz/.php-cs-fixer.php
Added
@@ -0,0 +1,47 @@ +<?php + +declare(strict_types=1); + +use PhpCsFixer\Config; +use PhpCsFixer\Finder; + +$finder = Finder::create() + ->in(__DIR__) + ->exclude( + 'lib/ext', + 'lib/plugins', + 'vendor', + ) + ->ignoreDotFiles(false) + ->name('*.php.dist'); + +return (new Config()) + ->setRiskyAllowed(true) + ->setRules( + '@PHP74Migration' => true, + '@PHP74Migration:risky' => true, + '@PHP80Migration' => true, + '@PSR1' => true, + '@PSR12' => true, + + 'concat_space' => + 'spacing' => 'one', + , + + 'declare_strict_types' => false, + 'phpdoc_add_missing_param_annotation' => false, + 'use_arrow_functions' => false, + 'void_return' => false, + + 'yoda_style' => + 'equal' => false, + 'identical' => false, + , + + // TODO - risky + 'no_unset_on_property' => false, + 'random_api_migration' => false, + 'strict_param' => false, + ) + ->setFinder($finder) + ->setCacheFile(sys_get_temp_dir() . '/php-cs-fixer.' . md5(__DIR__) . '.cache');
View file
kolab-syncroton-2.4.2.tar.gz/README.md
Changed
@@ -41,5 +41,33 @@ package as document root as well as the /Microsoft-Server-ActiveSync alias. See docs/kolab-syncroton.conf for an example Apache config. + +FOR DEVELOPERS (TESTING) +======================== + +Steps 1-5 from the installation procedure need to be done. + +To check code quality run: `vendor/bin/phpstan analyse` + +To check code style run: `vendor/bin/php-cs-fixer fix --dry-run --diff --verbose` + +To run the Unit test suite goto `tests/` and run `../vendor/bin/phpunit --testsuite=Unit` + +To run the integration tests you have to follow these steps: + +1. Prepare a test account on the Kolab server and add this to config/config.inc.php: +``` +$config'activesync_test_username' = 'user@domain.tld'; +$config'activesync_test_password' = 'password'; +``` + + Don't forget to configure also `imap_host`, `activesync_dav_server` and `activesync_storage`. + All other options should use the default values. + +2. Start the syncroton server: `php -S localhost:8000` + +3. Goto `tests/` and run `../vendor/bin/phpunit --testsuite=Sync` + + 1: http://getcomposer.org 2: https://github.com/roundcube/roundcubemail/blob/master/program/lib/Roundcube/README.md)
View file
kolab-syncroton-2.4.2.tar.gz/composer.json-dist
Changed
@@ -2,27 +2,28 @@ "name": "kolab/syncroton", "description": "The ActiveSync Service for Kolab", "license": "AGPL-3.0+", - "repositories": - { - "type": "vcs", - "url": "https://git.kolab.org/diffusion/PNL/php-net_ldap.git" - } - , "require": { - "php": ">=5.4.0", + "php": ">=7.2.0", + "kolab/net_ldap3": "dev-master", "pear/pear-core-minimal": "~1.10.1", "pear/net_socket": "~1.2.1", "pear/auth_sasl": "~1.1.0", + "pear/http_request2": "~2.5.0", "pear/net_idna2": "~0.2.0", "pear/mail_mime": "~1.10.0", "pear/net_smtp": "~1.7.1", "pear/net_ldap2": "~2.2.0", "pear/net_sieve": "~1.4.0", - "kolab/net_ldap3": "dev-master", + "roundcube/rtf-html-php": "~2.1", + "sabre/vobject": "~4.5.1", + "zf1s/zend-controller": "~1.12.20", "zf1s/zend-json": "~1.12.20", "zf1s/zend-log": "~1.12.20" }, "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.7 || ^6 || ^7 || ^9" + "friendsofphp/php-cs-fixer": "^3.0", + "guzzlehttp/guzzle": "^7.3.0", + "phpstan/phpstan": "^1.2", + "phpunit/phpunit": "^8 || ^9" } }
View file
kolab-syncroton-2.4.2.tar.gz/config/config.inc.php.dist
Changed
@@ -27,7 +27,7 @@ // List of global addressbooks (GAL) // Note: If empty 'autocomplete_addressbooks' setting will be used -$config'activesync_addressbooks' = array(); +$config'activesync_addressbooks' = ; // ActiveSync => Roundcube contact fields map for GAL search /* Default: array( @@ -67,10 +67,10 @@ // List of Roundcube plugins // WARNING: Not all plugins used in Roundcube can be listed here -$config'activesync_plugins' = array( +$config'activesync_plugins' = 'libcalendaring', - 'libkolab' -); + 'libkolab', +; // Defines for how many seconds we'll sleep between every // action for detecting changes in folders. Default: 60 @@ -106,7 +106,7 @@ // When set to an array folder hierarchies are used on all devices not listed here. // When set to null an old whitelist approach will be used where we do opposite // action and enable folder hierarchies only on device types known to support it. -$config'activesync_multifolder_blacklist' = array(); +$config'activesync_multifolder_blacklist' = ; // Blacklist overwrites for specified object type. If set to an array // it will have a precedence over 'activesync_multifolder_blacklist' list only for that type. @@ -114,7 +114,7 @@ // in that case use $config'activesync_multifolder_blacklist_contact' = array('windowsoutlook'); $config'activesync_multifolder_blacklist_mail' = null; $config'activesync_multifolder_blacklist_event' = null; -$config'activesync_multifolder_blacklist_contact' = array('windowsoutlook'); +$config'activesync_multifolder_blacklist_contact' = 'windowsoutlook'; $config'activesync_multifolder_blacklist_note' = null; $config'activesync_multifolder_blacklist_task' = null;
View file
kolab-syncroton-2.4.2.tar.gz/docs/SQL/mysql.initial.sql
Changed
@@ -59,6 +59,7 @@ `counter` int(11) NOT NULL DEFAULT '0', `lastsync` datetime DEFAULT NULL, `pendingdata` longblob, + `client_id_map` longblob DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `device_id--type--counter` (`device_id`,`type`,`counter`), CONSTRAINT `syncroton_synckey::device_id--syncroton_device::id` FOREIGN KEY (`device_id`) REFERENCES `syncroton_device` (`id`) ON DELETE CASCADE ON UPDATE CASCADE @@ -123,4 +124,4 @@ PRIMARY KEY(`name`) ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */; -INSERT INTO `system` (`name`, `value`) VALUES ('syncroton-version', '2014101300'); +INSERT INTO `system` (`name`, `value`) VALUES ('syncroton-version', '2023100500');
View file
kolab-syncroton-2.4.2.tar.gz/docs/SQL/oracle
Deleted
-(directory)
View file
kolab-syncroton-2.4.2.tar.gz/docs/SQL/oracle.initial.sql
Deleted
@@ -1,113 +0,0 @@ -CREATE TABLE "syncroton_policy" ( - "id" varchar(40) NOT NULL PRIMARY KEY, - "name" varchar(255) NOT NULL, - "description" varchar(255) DEFAULT NULL, - "policy_key" varchar(64) NOT NULL, - "json_policy" clob DEFAULT NULL -); - -CREATE TABLE "syncroton_device" ( - "id" varchar(40) NOT NULL PRIMARY KEY, - "deviceid" varchar(64) NOT NULL, - "devicetype" varchar(64) NOT NULL, - "owner_id" varchar(40) NOT NULL, - "acsversion" varchar(40) NOT NULL, - "policykey" varchar(64) DEFAULT NULL, - "policy_id" varchar(40) DEFAULT NULL, - "useragent" varchar(255) DEFAULT NULL, - "imei" varchar(255) DEFAULT NULL, - "model" varchar(255) DEFAULT NULL, - "friendlyname" varchar(255) DEFAULT NULL, - "os" varchar(255) DEFAULT NULL, - "oslanguage" varchar(255) DEFAULT NULL, - "phonenumber" varchar(255) DEFAULT NULL, - "pinglifetime" integer DEFAULT NULL, - "remotewipe" integer DEFAULT 0, - "pingfolder" clob DEFAULT NULL, - "lastsynccollection" clob DEFAULT NULL, - "lastping" timestamp DEFAULT NULL, - "contactsfilter_id" varchar(40) DEFAULT NULL, - "calendarfilter_id" varchar(40) DEFAULT NULL, - "tasksfilter_id" varchar(40) DEFAULT NULL, - "emailfilter_id" varchar(40) DEFAULT NULL -); - -CREATE UNIQUE INDEX "syncroton_device_owner_id_idx" ON "syncroton_device" ("owner_id", "deviceid"); - - -CREATE TABLE "syncroton_folder" ( - "id" varchar(40) NOT NULL PRIMARY KEY, - "device_id" varchar(40) NOT NULL - REFERENCES "syncroton_device" ("id") ON DELETE CASCADE, - "class" varchar(64) NOT NULL, - "folderid" varchar(254) NOT NULL, - "parentid" varchar(254) DEFAULT NULL, - "displayname" varchar(254) NOT NULL, - "type" integer NOT NULL, - "creation_time" timestamp NOT NULL, - "lastfiltertype" integer DEFAULT NULL, - "supportedfields" clob DEFAULT NULL -); - -CREATE UNIQUE INDEX "syncroton_folder_device_id_idx" ON "syncroton_folder" ("device_id", "class", "folderid"); - - -CREATE TABLE "syncroton_synckey" ( - "id" varchar(40) NOT NULL PRIMARY KEY, - "device_id" varchar(40) NOT NULL - REFERENCES "syncroton_device" ("id") ON DELETE CASCADE, - "type" varchar(64) DEFAULT NULL, - "counter" integer DEFAULT 0 NOT NULL, - "lastsync" timestamp DEFAULT NULL, - "pendingdata" clob -); - -CREATE UNIQUE INDEX "syncroton_synckey_device_idx" ON "syncroton_synckey" ("device_id", "type", "counter"); - -CREATE TABLE "syncroton_content" ( - "id" varchar(40) NOT NULL PRIMARY KEY, - "device_id" varchar(40) NOT NULL - REFERENCES "syncroton_device" ("id") ON DELETE CASCADE, - "folder_id" varchar(40) NOT NULL, - "contentid" varchar(128) NOT NULL, - "creation_time" timestamp DEFAULT NULL, - "creation_synckey" integer NOT NULL, - "is_deleted" smallint DEFAULT 0 -); - -CREATE UNIQUE INDEX "syncroton_content_device_idx" ON "syncroton_content" ("device_id", "folder_id", "contentid"); - -CREATE TABLE "syncroton_data" ( - "id" varchar(40) NOT NULL PRIMARY KEY, - "class" varchar(40) NOT NULL, - "folder_id" varchar(40) NOT NULL, - "data" clob -); - -CREATE TABLE "syncroton_data_folder" ( - "id" varchar(40) NOT NULL PRIMARY KEY, - "type" integer NOT NULL, - "name" varchar(255) NOT NULL, - "owner_id" varchar(40) NOT NULL, - "parent_id" varchar(40) DEFAULT NULL -); - -CREATE TABLE "syncroton_modseq" ( - "device_id" varchar(40) NOT NULL - REFERENCES "syncroton_device" ("id") ON DELETE CASCADE, - "folder_id" varchar(40) NOT NULL, - "synctime" timestamp NOT NULL, - "data" clob, - PRIMARY KEY ("device_id", "folder_id", "synctime") -); - -CREATE TABLE "syncroton_relations_state" ( - "device_id" varchar(40) NOT NULL - REFERENCES "syncroton_device" ("id") ON DELETE CASCADE, - "folder_id" varchar(40) NOT NULL, - "synctime" timestamp NOT NULL, - "data" clob, - PRIMARY KEY ("device_id", "folder_id", "synctime") -); - -INSERT INTO "system" ("name", "value") VALUES ('syncroton-version', '2014101300');
View file
kolab-syncroton-2.4.2.tar.gz/docs/SQL/oracle/2014101300.sql
Deleted
@@ -1,8 +0,0 @@ -CREATE TABLE "syncroton_relations_state" ( - "device_id" varchar(40) NOT NULL - REFERENCES "syncroton_device" ("id") ON DELETE CASCADE, - "folder_id" varchar(40) NOT NULL, - "synctime" timestamp NOT NULL, - "data" clob, - PRIMARY KEY ("device_id", "folder_id", "synctime") -);
View file
kolab-syncroton-2.4.2.tar.gz/index.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | |
View file
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/IDevice.php
Changed
@@ -20,8 +20,9 @@ interface Syncroton_Backend_IDevice extends Syncroton_Backend_IBackend { /** - * @param unknown_type $userId - * @param unknown_type $deviceId + * @param string $userId + * @param string $deviceId + * * @return Syncroton_Model_IDevice */ public function getUserDevice($userId, $deviceId); @@ -40,7 +41,7 @@ * * @param array $request Oof/Get request data * - * @return Syncroton_Model_Oof Response object or NULL if OOF is not supported + * @return Syncroton_Model_Oof|null Response object or NULL if OOF is not supported * @throws Syncroton_Exception_Status */ public function getOOF($request);
View file
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/ISyncState.php
Changed
@@ -42,7 +42,8 @@ * * @param Syncroton_Model_Device $_deviceId * @param string $_class - * @return array + * + * @return Syncroton_Model_SyncState|false */ public function validate($_deviceId, $_syncKey, $_type); }
View file
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/SyncState.php
Changed
@@ -138,7 +138,8 @@ * * @param Syncroton_Model_IDevice|string $deviceId * @param Syncroton_Model_IFolder|string $folderId - * @return Syncroton_Model_SyncState + * + * @return Syncroton_Model_SyncState|false */ public function validate($deviceId, $folderId, $syncKey) {
View file
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/FolderDelete.php
Changed
@@ -26,11 +26,6 @@ protected $_folder; /** - * @var Syncroton_Model_ISyncState - */ - protected $_syncState; - - /** * parse FolderDelete request */ public function handle()
View file
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/FolderSync.php
Changed
@@ -66,10 +66,9 @@ * @var string */ protected $_syncKey; - + /** - * parse FolderSync request - * + * Parse FolderSync request */ public function handle() {
View file
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/Sync.php
Changed
@@ -99,11 +99,6 @@ */ protected $_moreAvailable = false; - /** - * @var Syncroton_Model_SyncState - */ - protected $_syncState; - protected $_maxWindowSize = 100; protected $_heartbeatInterval = null; @@ -969,6 +964,12 @@ } $totalChanges += $collectionChanges; + + // If the client resent an old sync-key, we should still respond with the latest sync key + if (isset($collectionData->syncState->counterNext)) { + //TODO we're not resending the changes in between, but I'm not sure we have to. + $collectionData->syncState->counter = $collectionData->syncState->counterNext; + } // increase SyncKey if needed if (( @@ -1069,7 +1070,7 @@ if (!empty($clientModifications'added')) { foreach ($clientModifications'added' as $added) { $this->_contentStateBackend->delete($added'contentState'); - $dataController->deleteEntry($collectionData->collectionId, $added'serverId', array()); + $dataController->deleteEntry($collectionData->collectionId, $added'serverId'); } } @@ -1092,7 +1093,7 @@ if (!empty($clientModifications'added')) { foreach ($clientModifications'added' as $added) { $this->_contentStateBackend->delete($added'contentState'); - $dataController->deleteEntry($collectionData->collectionId, $added'serverId', array()); + $dataController->deleteEntry($collectionData->collectionId, $added'serverId'); } }
View file
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/IData.php
Changed
@@ -37,11 +37,11 @@ /** * delete entry in backend * - * @param string $_folderId - * @param string $_serverId - * @param unknown_type $_collectionData + * @param string $_folderId + * @param string $_serverId + * @param ?Syncroton_Model_SyncCollection $_collectionData */ - public function deleteEntry($_folderId, $_serverId, $_collectionData); + public function deleteEntry($_folderId, $_serverId, $_collectionData = null); /** * delete folder @@ -86,7 +86,7 @@ /** * - * @param unknown_type $fileReference + * @param string $fileReference * @return Syncroton_Model_FileReference */ public function getFileReference($fileReference);
View file
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Server.php
Changed
@@ -421,11 +421,9 @@ /** * get existing device of owner or create new device for owner * - * @param unknown_type $ownerId - * @param unknown_type $deviceId - * @param unknown_type $deviceType - * @param unknown_type $userAgent - * @param unknown_type $protocolVersion + * @param string $ownerId + * @param array $requestParameters + * * @return Syncroton_Model_Device */ protected function _getUserDevice($ownerId, $requestParameters) @@ -435,6 +433,7 @@ $device->useragent = $requestParameters'userAgent'; $device->acsversion = $requestParameters'protocolVersion'; + $device->devicetype = $requestParameters'deviceType'; if ($device->isDirty()) { $device = $this->_deviceBackend->update($device);
View file
kolab-syncroton-2.4.2.tar.gz/lib/ext/rtf.php
Deleted
@@ -1,705 +0,0 @@ -<?php -/* - This class contains code from rtfclass.php that was written by Markus Fischer and placed by him under - GPLv2 License. - - =======================================NOTES FROM ORIGINAL AUTHOR==================================== - Rich Text Format - Parsing Class - ================================ - - (c) 2000 Markus Fischer - <mfischer@josefine.ben.tuwien.ac.at> - http://josefine.ben.tuwien.ac.at/~mfischer/ - - Latest versions of this class can always be found at - http://josefine.ben.tuwien.ac.at/~mfischer/developing/php/rtf/rtfclass.phps - Testing suite is available at - http://josefine.ben.tuwien.ac.at/~mfischer/developing/php/rtf/ - - License: GPLv2 - - Specification: - http://msdn.microsoft.com/library/default.asp?URL=/library/specs/rtfspec.htm - - General Notes: - ============== - Unknown or unspupported control symbols are silently gnored - - Group stacking is still not supported :( - group stack logic implemented; however not really used yet - ===================================================================================================== - - It was modified by me (Andreas Brodowski) to allow compressed RTF being uncompressed by code I ported from - Java to PHP and adapted according the needs of Z-Push. - - Currently it is being used to detect empty RTF Streams from Nokia Phones in MfE Clients - - It needs to be used by other backend writers that needs to have notes in calendar, appointment or tasks - objects to be written to their databases since devices send them usually in RTF Format... With Zarafa - you can write them directly to DB and Zarafa is doing the conversion job. Other Groupware systems usually - don't have this possibility... - - Aleksander Machniak <machniak@kolabsys.com> fixed some deprecated function usage and some small issues - -*/ - - -class rtf { - var $LZRTF_HDR_DATA = "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscript \\fdecor MS Sans SerifSymbolArialTimes New RomanCourier{\\colortbl\\red0\\green0\\blue0\n\r\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab\\tx"; - var $LZRTF_HDR_LEN = 207; - var $CRC32_TABLE = array( 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3, - 0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91, - 0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7, - 0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5, - 0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B, - 0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59, - 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F, - 0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D, - 0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433, - 0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01, - 0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457, - 0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65, - 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB, - 0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9, - 0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F, - 0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD, - 0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683, - 0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1, - 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7, - 0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5, - 0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B, - 0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79, - 0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F, - 0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D, - 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713, - 0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21, - 0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777, - 0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45, - 0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB, - 0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9, - 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF, - 0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D, - ); - - var $rtf; // rtf core stream - var $rtf_len; // length in characters of the stream (get performace due avoiding calling strlen everytime) - var $err = array(); // array of error message, no entities on no error - - var $wantXML; // convert to XML - var $wantHTML; // convert to HTML - var $wantASCII; // convert to HTML - - // the only variable which should be accessed from the outside - var $out; // output data stream (depends on which $wantXXXXX is set to true - var $outstyles; // htmlified styles (generated after parsing if wantHTML - var $styles = array(); // if wantHTML, stylesheet definitions are put in here - - // internal parser variables -------------------------------- - // control word variables - var $cword; // holds the current (or last) control word, depending on $cw - var $cw; // are we currently parsing a control word ? - var $cfirst; // could this be the first character ? so watch out for control symbols - - var $flags = array(); // parser flags - var $fonttable = array(); - - var $queue; // every character which is no sepcial char, not belongs to a control word/symbol; is generally considered being 'plain' - - var $stack = array(); // group stack - - /* keywords which don't follw the specification (used by Word '97 - 2000) */ - // not yet used - var $control_exception = array( - "clFitText", - "clftsWidth(-?0-9+)?", - "clNoWrap(-?0-9+)?", - "clwWidth(-?0-9+)?", - "tdfrmtxtBottom(-?0-9+)?", - "tdfrmtxtLeft(-?0-9+)?", - "tdfrmtxtRight(-?0-9+)?", - "tdfrmtxtTop(-?0-9+)?", - "trftsWidthA(-?0-9+)?", - "trftsWidthB(-?0-9+)?", - "trftsWidth(-?0-9+)?", - "trwWithA(-?0-9+)?", - "trwWithB(-?0-9+)?", - "trwWith(-?0-9+)?", - "spectspecifygen(-?0-9+)?", - ); - - var $charset_table = array( - "0" => "ANSI", - "1" => "Default", - "2" => "Symbol", - "77" => "Mac", - "128" => "Shift Jis", - "129" => "Hangul", - "130" => "Johab", - "134" => "GB2312", - "136" => "Big5", - "161" => "Greek", - "162" => "Turkish", - "163" => "Vietnamese", - "177" => "Hebrew", - "178" => "Arabic", - "179" => "Arabic Traditional", - "180" => "Arabic user", - "181" => "Hebrew user", - "186" => "Baltic", - "204" => "Russian", - "222" => "Thai", - "238" => "Eastern European", - "255" => "PC 437", - "255" => "OEM", - ); - - /* note: the only conversion table used */ - var $fontmodifier_table = array( - "bold" => "b", - "italic" => "i", - "underlined" => "u", - "strikethru" => "strike", - ); - - - function __construct() { - $this->rtf_len = 0; - $this->rtf = ''; - - $this->out = ''; - } - - // loadrtf - load the raw rtf data to be converted by this class - // data = the raw rtf - function loadrtf($data) { - if (($this->rtf = $this->uncompress($data))) { - $this->rtf_len = strlen($this->rtf); - }; - if($this->rtf_len == 0) { - debugLog("No data in stream found"); - return false; - }; - return true; - } - - function output($typ) { - switch($typ) { - case "ascii": $this->wantASCII = true; break; - case "xml": $this->wantXML = true; break; - case "html": $this->wantHTML = true; break; - default: break; - } - } - - // uncompress - uncompress compressed rtf data - // src = the compressed raw rtf in LZRTF format - function uncompress($src) { - $header = unpack("LcSize/LuSize/Lmagic/Lcrc32",substr($src,0,16)); - $in = 16; - if ($header'cSize' != strlen($src)-4) {
View file
kolab-syncroton-2.4.2.tar.gz/lib/init.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | |
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -28,28 +28,23 @@ */ class kolab_sync extends rcube { - /** - * Application name - * - * @var string - */ + /** @var string Application name */ public $app_name = 'ActiveSync for Kolab'; // no double quotes inside - /** - * Current user - * - * @var rcube_user - */ - public $user; - + /** @var string|null Request user name */ public $username; + + /** @var string|null Request user password */ public $password; - public $task = null; + public $task; + protected $per_user_log_dir; + protected $log_dir; + protected $logger; - const CHARSET = 'UTF-8'; - const VERSION = "2.4.2"; + public const CHARSET = 'UTF-8'; + public const VERSION = "2.4.2"; /** @@ -60,7 +55,7 @@ * * @return kolab_sync The one and only instance */ - static function get_instance($mode = 0, $env = '') + public static function get_instance($mode = 0, $env = '') { if (!self::$instance || !is_a(self::$instance, 'kolab_sync')) { self::$instance = new kolab_sync(); @@ -77,15 +72,16 @@ public function startup() { // Initialize Syncroton Logger - $debug_mode = $this->config->get('activesync_debug') ? kolab_sync_logger::DEBUG : kolab_sync_logger::WARN; - $this->logger = new kolab_sync_logger($debug_mode); + $debug_mode = $this->config->get('activesync_debug') ? kolab_sync_logger::DEBUG : kolab_sync_logger::WARN; + $this->logger = new kolab_sync_logger($debug_mode); + $this->log_dir = $this->config->get('log_dir'); // Get list of plugins // WARNING: We can use only plugins that are prepared for this - // e.g. are not using output or rcmail objects or - // doesn't throw errors when using them - $plugins = (array)$this->config->get('activesync_plugins', array('kolab_auth')); - $plugins = array_unique(array_merge($plugins, array('libkolab', 'libcalendaring'))); + // e.g. are not using output or rcmail objects and + // do not throw errors when using them + $plugins = (array)$this->config->get('activesync_plugins', 'kolab_auth'); + $plugins = array_unique(array_merge($plugins, 'libkolab', 'libcalendaring')); // Initialize/load plugins $this->plugins = kolab_sync_plugin_api::get_instance(); @@ -118,7 +114,7 @@ } if (isset($basicAuthData) && !empty($basicAuthData)) { - list($_SERVER'PHP_AUTH_USER', $_SERVER'PHP_AUTH_PW') = explode(":", $basicAuthData); + $_SERVER'PHP_AUTH_USER', $_SERVER'PHP_AUTH_PW' = explode(":", $basicAuthData); } } @@ -132,34 +128,37 @@ } } + // Set log directory per-user + $this->set_log_dir($_SERVER'PHP_AUTH_USER'); + // Authenticate the user $userid = $this->authenticate($_SERVER'PHP_AUTH_USER', $_SERVER'PHP_AUTH_PW'); } if (empty($userid)) { - header('WWW-Authenticate: Basic realm="' . $this->app_name .'"'); + header('WWW-Authenticate: Basic realm="' . $this->app_name . '"'); header('HTTP/1.1 401 Unauthorized'); exit; } - $this->plugins->exec_hook('ready', array('task' => 'syncroton')); + $this->plugins->exec_hook('ready', 'task' => 'syncroton'); - // Set log directory per-user + // Set log directory per-user (again, in case the username changed above) $this->set_log_dir(); // Save user password for Roundcube Framework $this->password = $_SERVER'PHP_AUTH_PW'; // Register Syncroton backends/callbacks - Syncroton_Registry::set(Syncroton_Registry::LOGGERBACKEND, $this->logger); - Syncroton_Registry::set(Syncroton_Registry::DATABASE, $this->get_dbh()); - Syncroton_Registry::set(Syncroton_Registry::TRANSACTIONMANAGER, kolab_sync_transaction_manager::getInstance()); - Syncroton_Registry::set(Syncroton_Registry::DEVICEBACKEND, new kolab_sync_backend_device); - Syncroton_Registry::set(Syncroton_Registry::FOLDERBACKEND, new kolab_sync_backend_folder); - Syncroton_Registry::set(Syncroton_Registry::SYNCSTATEBACKEND, new kolab_sync_backend_state); - Syncroton_Registry::set(Syncroton_Registry::CONTENTSTATEBACKEND, new kolab_sync_backend_content); - Syncroton_Registry::set(Syncroton_Registry::POLICYBACKEND, new kolab_sync_backend_policy); - Syncroton_Registry::set(Syncroton_Registry::SLEEP_CALLBACK, array($this, 'sleep')); + Syncroton_Registry::set(Syncroton_Registry::LOGGERBACKEND, $this->logger); + Syncroton_Registry::set(Syncroton_Registry::DATABASE, $this->get_dbh()); + Syncroton_Registry::set(Syncroton_Registry::TRANSACTIONMANAGER, kolab_sync_transaction_manager::getInstance()); + Syncroton_Registry::set(Syncroton_Registry::DEVICEBACKEND, new kolab_sync_backend_device()); + Syncroton_Registry::set(Syncroton_Registry::FOLDERBACKEND, new kolab_sync_backend_folder()); + Syncroton_Registry::set(Syncroton_Registry::SYNCSTATEBACKEND, new kolab_sync_backend_state()); + Syncroton_Registry::set(Syncroton_Registry::CONTENTSTATEBACKEND, new kolab_sync_backend_content()); + Syncroton_Registry::set(Syncroton_Registry::POLICYBACKEND, new kolab_sync_backend_policy()); + Syncroton_Registry::set(Syncroton_Registry::SLEEP_CALLBACK, $this, 'sleep'); Syncroton_Registry::setContactsDataClass('kolab_sync_data_contacts'); Syncroton_Registry::setCalendarDataClass('kolab_sync_data_calendar'); @@ -169,9 +168,9 @@ Syncroton_Registry::setGALDataClass('kolab_sync_data_gal'); // Configuration - Syncroton_Registry::set(Syncroton_Registry::PING_TIMEOUT, (int) $this->config->get('activesync_ping_timeout', 60)); - Syncroton_Registry::set(Syncroton_Registry::PING_INTERVAL, (int) $this->config->get('activesync_ping_interval', 15 * 60)); - Syncroton_Registry::set(Syncroton_Registry::QUIET_TIME, (int) $this->config->get('activesync_quiet_time', 3 * 60)); + Syncroton_Registry::set(Syncroton_Registry::PING_TIMEOUT, (int) $this->config->get('activesync_ping_timeout', 60)); + Syncroton_Registry::set(Syncroton_Registry::PING_INTERVAL, (int) $this->config->get('activesync_ping_interval', 15 * 60)); + Syncroton_Registry::set(Syncroton_Registry::QUIET_TIME, (int) $this->config->get('activesync_quiet_time', 3 * 60)); Syncroton_Registry::set(Syncroton_Registry::MAX_COLLECTIONS, (int) $this->config->get('activesync_max_folders', 100)); // Run Syncroton @@ -186,7 +185,7 @@ * @param string $username User name * @param string $password User password * - * @param int User ID + * @return null|int User ID */ public function authenticate($username, $password) { @@ -196,44 +195,42 @@ $cache_key = sha1($username . '::' . $host); if (!$cache || !($auth = $cache->get($cache_key))) { - $auth = $this->plugins->exec_hook('authenticate', array( + $auth = $this->plugins->exec_hook('authenticate', 'host' => $host, 'user' => $username, 'pass' => $password, - )); + ); if (!$auth'abort' && $cache) { - $cache->set($cache_key, array( + $cache->set($cache_key, 'user' => $auth'user', 'host' => $auth'host', - )); + ); } // LDAP server failure... send 503 error - if ($auth'kolab_ldap_error' ?? null) { + if (!empty($auth'kolab_ldap_error')) { self::server_error(); } // Close LDAP connection from kolab_auth plugin if (class_exists('kolab_auth', false)) { - if (method_exists('kolab_auth', 'ldap_close')) { - kolab_auth::ldap_close(); - } + kolab_auth::ldap_close(); } - } - else { + } else { $auth'pass' = $password; }
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_backend.php
Deleted
@@ -1,1057 +0,0 @@ -<?php - -/** - +--------------------------------------------------------------------------+ - | Kolab Sync (ActiveSync for Kolab) | - | | - | Copyright (C) 2011-2012, 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> | - +--------------------------------------------------------------------------+ -*/ - -class kolab_sync_backend -{ - /** - * Singleton instace of kolab_sync_backend - * - * @var kolab_sync_backend - */ - static protected $instance; - - protected $storage; - protected $folder_meta; - protected $folder_uids; - protected $root_meta; - - static protected $types = array( - 1 => '', - 2 => 'mail.inbox', - 3 => 'mail.drafts', - 4 => 'mail.wastebasket', - 5 => 'mail.sentitems', - 6 => 'mail.outbox', - 7 => 'task.default', - 8 => 'event.default', - 9 => 'contact.default', - 10 => 'note.default', - 11 => 'journal.default', - 12 => 'mail', - 13 => 'event', - 14 => 'contact', - 15 => 'task', - 16 => 'journal', - 17 => 'note', - ); - - static protected $classes = array( - 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', - ); - - const ROOT_MAILBOX = 'INBOX'; -// const ROOT_MAILBOX = ''; - const ASYNC_KEY = '/private/vendor/kolab/activesync'; - const UID_KEY = '/shared/vendor/cmu/cyrus-imapd/uniqueid'; - - - /** - * This implements the 'singleton' design pattern - * - * @return kolab_sync_backend The one and only instance - */ - static function get_instance() - { - if (!self::$instance) { - self::$instance = new kolab_sync_backend; - self::$instance->startup(); // init AFTER object was linked with self::$instance - } - - return self::$instance; - } - - - /** - * Class initialization - */ - public function startup() - { - $this->storage = rcube::get_instance()->get_storage(); - - // @TODO: reset cache? if we do this for every request the cache would be useless - // There's no session here - //$this->storage->clear_cache('mailboxes.', true); - - // set additional header used by libkolab - $this->storage->set_options(array( - // @TODO: there can be Roundcube plugins defining additional headers, - // we maybe would need to add them here - 'fetch_headers' => 'X-KOLAB-TYPE X-KOLAB-MIME-VERSION', - 'skip_deleted' => true, - 'threading' => false, - )); - - // Disable paging - $this->storage->set_pagesize(999999); - } - - - /** - * List known devices - * - * @return array Device list as hash array - */ - public function devices_list() - { - if ($this->root_meta === null) { - // @TODO: consider server annotation instead of INBOX - if ($meta = $this->storage->get_metadata(self::ROOT_MAILBOX, self::ASYNC_KEY)) { - $this->root_meta = $this->unserialize_metadata($metaself::ROOT_MAILBOXself::ASYNC_KEY); - } - else { - $this->root_meta = array(); - } - } - - if (!empty($this->root_meta'DEVICE') && is_array($this->root_meta'DEVICE')) { - return $this->root_meta'DEVICE'; - } - - return array(); - } - - - /** - * Get list of folders available for sync - * - * @param string $deviceid Device identifier - * @param string $type Folder type - * @param bool $flat_mode Enables flat-list mode - * - * @return array|bool List of mailbox folders, False on backend failure - */ - public function folders_list($deviceid, $type, $flat_mode = false) - { - // get all folders of specified type - $folders = kolab_storage::list_folders('', '*', $type, false, $typedata); - - // get folders activesync config - $folderdata = $this->folder_meta(); - - if (!is_array($folders) || !is_array($folderdata)) { - return false; - } - - $folders_list = array(); - - // check if folders are "subscribed" for activesync - foreach ($folderdata as $folder => $meta) { - if (empty($meta'FOLDER') || empty($meta'FOLDER'$deviceid) - || empty($meta'FOLDER'$deviceid'S') - ) { - continue; - } - - // force numeric folder name to be a string (T1283) - $folder = (string) $folder; - - if (!empty($type) && !in_array($folder, $folders)) { - continue; - } - - // Activesync folder identifier (serverId) - $folder_type = !empty($typedata$folder) ? $typedata$folder : 'mail'; - $folder_id = self::folder_id($folder, $folder_type); - - $folders_list$folder_id = $this->folder_data($folder, $folder_type); - } - - if ($flat_mode) { - $folders_list = $this->folders_list_flat($folders_list, $type, $typedata); - } - - return $folders_list; - } - - /** - * Converts list of folders to a "flat" list - */ - private function folders_list_flat($folders, $type, $typedata) - { - $delim = $this->storage->get_hierarchy_delimiter(); - - foreach ($folders as $idx => $folder) {
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_backend_common.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -61,13 +61,13 @@ * * @var array */ - protected $cache = array(); + protected $cache = ; /** * Constructor */ - function __construct() + public function __construct() { $this->db = rcube::get_instance()->get_dbh(); @@ -79,9 +79,9 @@ /** * Creates new Syncroton object in database * - * @param Syncroton_Model_* $object Object + * @param object $object Object * - * @return Syncroton_Model_* Object + * @return object Object * @throws InvalidArgumentException|Syncroton_Exception_DeadlockDetected|Exception */ public function create($object) @@ -91,15 +91,16 @@ } $data = $this->object_to_array($object); - $cols = array(); + $cols = ; - $data'id' = $object->id = sha1(mt_rand(). microtime()); + $data'id' = $object->id = sha1(mt_rand() . microtime()); foreach (array_keys($data) as $key) { $cols = $this->db->quote_identifier($key); } - $result = $this->db->query('INSERT INTO `' . $this->table_name . '`' . ' (' . implode(', ', $cols) . ')' + $result = $this->db->query( + 'INSERT INTO `' . $this->table_name . '`' . ' (' . implode(', ', $cols) . ')' . ' VALUES(' . implode(', ', array_fill(0, count($cols), '?')) . ')', array_values($data) ); @@ -119,16 +120,17 @@ /** * Returns Syncroton data object * - * @param string $id + * @param string $id + * * @throws Syncroton_Exception_NotFound - * @return Syncroton_Model_* + * @return object */ public function get($id) { $id = $id instanceof $this->interface_name ? $id->id : $id; if ($id) { - $select = $this->db->query('SELECT * FROM `' . $this->table_name . '` WHERE `id` = ?', array($id)); + $select = $this->db->query('SELECT * FROM `' . $this->table_name . '` WHERE `id` = ?', $id); $data = $this->db->fetch_assoc($select); } @@ -142,7 +144,7 @@ /** * Deletes Syncroton data object * - * @param string|Syncroton_Model_* $id Object or identifier + * @param string|object $id Object or identifier * * @return bool True on success, False on failure * @throws Syncroton_Exception_DeadlockDetected|Exception @@ -155,14 +157,14 @@ return false; } - $result = $this->db->query('DELETE FROM `' . $this->table_name .'` WHERE `id` = ?', array($id)); + $result = $this->db->query('DELETE FROM `' . $this->table_name . '` WHERE `id` = ?', $id); if ($err = $this->db->is_error($result)) { $err = "Failed to delete instance of {$this->interface_name}: {$err}"; if ($this->db->error_info()0 == '40001') { throw new Syncroton_Exception_DeadlockDetected($err); } else { - throw new Exception($rr); + throw new Exception($err); } } @@ -172,9 +174,9 @@ /** * Updates Syncroton data object * - * @param Syncroton_Model_* $object + * @param object $object * - * @return Syncroton_Model_* Object + * @return object Object * @throws InvalidArgumentException|Syncroton_Exception_DeadlockDetected|Exception */ public function update($object) @@ -184,7 +186,7 @@ } $data = $this->object_to_array($object); - $set = array(); + $set = ; foreach (array_keys($data) as $key) { $set = $this->db->quote_identifier($key) . ' = ?'; @@ -215,6 +217,7 @@ public function userAccounts($device) { // this method is overwritten by kolab_sync_backend class + return ; } /** @@ -240,7 +243,7 @@ */ protected function object_to_array($object) { - $data = array(); + $data = ; foreach ($object as $key => $value) { if ($value instanceof DateTime) {
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_backend_content.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -42,7 +42,7 @@ { $id = $id instanceof Syncroton_Model_IContent ? $id->id : $id; - $result = $this->db->query("UPDATE `{$this->table_name}` SET `is_deleted` = 1 WHERE `id` = ?", array($id)); + $result = $this->db->query("UPDATE `{$this->table_name}` SET `is_deleted` = 1 WHERE `id` = ?", $id); if ($result = (bool) $this->db->affected_rows($result)) { unset($this->cache'content_folderstate'); @@ -107,7 +107,7 @@ } $select = $this->db->query("SELECT `contentid` FROM `{$this->table_name}` WHERE " . implode(' AND ', $where)); - $result = array(); + $result = ; while ($state = $this->db->fetch_assoc($select)) { $result = $state'contentid';
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_backend_device.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -32,9 +32,9 @@ protected $interface_name = 'Syncroton_Model_IDevice'; /** - * Kolab Sync backend + * Kolab Sync storage backend * - * @var kolab_sync_backend + * @var kolab_sync_storage */ protected $backend; @@ -45,7 +45,7 @@ public function __construct() { parent::__construct(); - $this->backend = kolab_sync_backend::get_instance(); + $this->backend = kolab_sync::storage(); } /** @@ -60,11 +60,11 @@ $device = parent::create($device); // Create device entry in kolab backend - $created = $this->backend->device_create(array( + $created = $this->backend->device_create( 'ID' => $device->id, 'TYPE' => $device->devicetype, 'ALIAS' => $device->friendlyname, - ), $device->deviceid); + , $device->deviceid); if (!$created) { throw new Syncroton_Exception_NotFound('Device creation failed'); @@ -135,7 +135,8 @@ $engine = kolab_sync::get_instance(); $identities = $engine->user->list_identities(); $email = $engine->get_user_email(); - $addresses = array(); + $addresses = ; + $displayname = null; // read email addresses and display name (default ident comes first) foreach ((array)$identities as $ident) { @@ -147,20 +148,20 @@ } if (empty($displayname) && empty($email) && empty($addresses)) { - return array(); + return ; } - $account = new Syncroton_Model_Account; + $account = new Syncroton_Model_Account(); if ($email) { - $addresses = array_diff($addresses, array($email)); + $addresses = array_diff($addresses, $email); } $account->userDisplayName = $displayname; $account->primaryAddress = $email; $account->addresses = array_unique($addresses); - return array($account); + return $account; } /** @@ -168,14 +169,14 @@ * * @param array $request Oof/Get request data * - * @return Syncroton_Model_Oof Response object or NULL if OOF is not supported + * @return Syncroton_Model_Oof|null Response object or NULL if OOF is not supported * @throws Syncroton_Exception_Status */ public function getOOF($request) { $vacation_engine = $this->vacation_engine(); if (!$vacation_engine) { - return; + return null; } $vacation = $vacation_engine->get_vacation(); @@ -183,8 +184,7 @@ if (!$vacation'enabled') { $status = Syncroton_Model_Oof::STATUS_DISABLED; $vacation'start' = $vacation'end' = null; - } - else if ($vacation'start' || $vacation'end') { + } elseif ($vacation'start' || $vacation'end') { // in Activesync both or none time are required if (!$vacation'start' && $vacation'end') { $vacation'start' = new DateTime('1970-01-01', new DateTimeZone('UTC')); @@ -202,15 +202,14 @@ } $status = Syncroton_Model_Oof::STATUS_TIME_BASED; - } - else { + } else { $status = Syncroton_Model_Oof::STATUS_GLOBAL; } $message = null; if ($vacation'message') { - $message = array(); + $message = ; // convert message format, Roundcube supports plain text only if ($request'bodyType' == 'HTML') { @@ -218,22 +217,22 @@ $vacation'message' = $text2html->get_html(); } - foreach (array('Internal', 'ExternalKnown', 'ExternalUnknown') as $type) { - $message = new Syncroton_Model_OofMessage(array( + foreach ('Internal', 'ExternalKnown', 'ExternalUnknown' as $type) { + $message = new Syncroton_Model_OofMessage( "appliesTo$type" => true, 'enabled' => 1, 'bodyType' => 'Text', 'replyMessage' => rcube_charset::clean($vacation'message'), - )); + ); } } - return new Syncroton_Model_Oof(array( + return new Syncroton_Model_Oof( 'oofState' => $status, 'startTime' => $vacation'start', 'endTime' => $vacation'end', 'oofMessage' => $message, - )); + ); } /** @@ -261,8 +260,7 @@ if (empty($vacation'start') || empty($vacation'end')) { throw new Syncroton_Exception_Status_Settings(Syncroton_Exception_Status_Settings::INVALID_ARGUMENTS); } - } - else { + } else { $vacation'start' = $vacation'end' = null; } @@ -291,7 +289,7 @@ $vacation_engine->set_vacation($vacation); } // disable out-of-office - else if (isset($request->oofState)) { + elseif (isset($request->oofState)) { if ($vacation'enabled') { $vacation'enabled' = false; @@ -310,7 +308,7 @@ if (class_exists('managesieve')) { $plugin = $engine->plugins->get_plugin('managesieve'); - $vacation = $plugin->get_engine('vacation'); + $vacation = $plugin->get_engine('vacation'); // @phpstan-ignore-line if ($vacation->connect($engine->username, $engine->password)) { throw new Exception("Connection to managesieve server failed");
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_backend_folder.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -58,10 +58,10 @@ $device_id = $deviceid instanceof Syncroton_Model_IDevice ? $deviceid->id : $deviceid; $where = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id); - $where = $this->db->quote_identifier('class') . ' = ' . $this->db->quote($class); + $where = $this->db->quote_identifier('class') . ' = ' . $this->db->quote($class); - $select = $this->db->query('SELECT * FROM `' . $this->table_name .'` WHERE ' . implode(' AND ', $where)); - $result = array(); + $select = $this->db->query('SELECT * FROM `' . $this->table_name . '` WHERE ' . implode(' AND ', $where)); + $result = ; while ($folder = $this->db->fetch_assoc($select)) { $result$folder'folderid' = $this->get_object($folder); @@ -83,7 +83,7 @@ $device_id = $deviceid instanceof Syncroton_Model_IDevice ? $deviceid->id : $deviceid; $where = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id); - $where = $this->db->quote_identifier('folderid') . ' = ' . $this->db->quote($folderid); + $where = $this->db->quote_identifier('folderid') . ' = ' . $this->db->quote($folderid); $select = $this->db->query('SELECT * FROM `' . $this->table_name . '` WHERE ' . implode(' AND ', $where)); $folder = $this->db->fetch_assoc($select); @@ -107,15 +107,15 @@ $timestamp = new DateTime('now', new DateTimeZone('utc')); $client_crc = ''; $server_crc = ''; - $client_folders = array(); - $server_folders = array(); - $folder_classes = array( + $client_folders = ; + $server_folders = ; + $folder_classes = Syncroton_Data_Factory::CLASS_CALENDAR, Syncroton_Data_Factory::CLASS_CONTACTS, Syncroton_Data_Factory::CLASS_EMAIL, Syncroton_Data_Factory::CLASS_NOTES, - Syncroton_Data_Factory::CLASS_TASKS - ); + Syncroton_Data_Factory::CLASS_TASKS, + ; // Reset imap cache so we work with up-to-date folders list rcube::get_instance()->get_storage()->clear_cache('mailboxes', true); @@ -125,8 +125,7 @@ // retrieve all folders available in data backend $dataController = Syncroton_Data_Factory::factory($class, $device, $timestamp); $server_folders = array_merge($server_folders, $dataController->getAllFolders()); - } - catch (Exception $e) { + } catch (Exception $e) { rcube::raise_error($e, true, false); // This is server error, returning True might cause infinite sync loops return false; @@ -164,15 +163,10 @@ case 'displayName': case 'parentId': return strtolower($string); - break; - case 'serverId': return 'folderid'; - break; - default: return parent::from_camelcase($string); - break; } } @@ -185,19 +179,12 @@ switch ($string) { case 'displayname': return 'displayName'; - break; - case 'parentid': return 'parentId'; - break; - case 'folderid': return 'serverId'; - break; - default: return parent::to_camelcase($string, $ucFirst); - break; } } }
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_backend_policy.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | |
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_backend_state.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -41,6 +41,7 @@ */ public function create($object, $keep_previous_state = true) { + unset($object->counterNext); $object = parent::create($object); if ($keep_previous_state !== true) { @@ -57,9 +58,9 @@ protected function _deleteOtherStates(Syncroton_Model_ISyncState $state) { // remove all other synckeys - $where = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($state->deviceId); - $where = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($state->type); - $where = $this->db->quote_identifier('counter') . ' <> ' . $this->db->quote($state->counter); + $where = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($state->deviceId); + $where = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($state->type); + $where = $this->db->quote_identifier('counter') . ' <> ' . $this->db->quote($state->counter); $this->db->query("DELETE FROM `{$this->table_name}` WHERE " . implode(' AND ', $where)); } @@ -109,7 +110,7 @@ $folder_id = $folderid instanceof Syncroton_Model_IFolder ? $folderid->id : $folderid; $where = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id); - $where = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folder_id); + $where = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folder_id); $select = $this->db->limitquery("SELECT * FROM `{$this->table_name}` WHERE " . implode(' AND ', $where) . " ORDER BY `counter` DESC", 0, 1); @@ -135,7 +136,7 @@ $folder_id = $folderid instanceof Syncroton_Model_IFolder ? $folderid->id : $folderid; $where = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id); - $where = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folder_id); + $where = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folder_id); $this->db->query("DELETE FROM `{$this->table_name}` WHERE " . implode(' AND ', $where)); } @@ -147,19 +148,19 @@ * @param Syncroton_Model_IFolder|string $folderid Folder object or identifier * @param int $sync_key State key * - * @return Syncroton_Model_SyncState + * @return Syncroton_Model_SyncState|false */ public function validate($deviceid, $folderid, $sync_key) { $device_id = $deviceid instanceof Syncroton_Model_IDevice ? $deviceid->id : $deviceid; $folder_id = $folderid instanceof Syncroton_Model_IFolder ? $folderid->id : $folderid; - $states = array(); + $states = ; // get sync data // we'll get all records, thanks to this we'll be able to // skip _deleteOtherStates() call below (one DELETE query less) $where'device_id' = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id); - $where'type' = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folder_id); + $where'type' = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folder_id); $select = $this->db->query("SELECT * FROM `{$this->table_name}` WHERE " . implode(' AND ', $where)); @@ -175,20 +176,20 @@ $state = $states$sync_key; $next = max(array_keys($states)); - $where = array(); - $where'device_id' = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id); - $where'folder_id' = $this->db->quote_identifier('folder_id') . ' = ' . $this->db->quote($folder_id); + $where = ; + $where'device_id' = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id); + $where'folder_id' = $this->db->quote_identifier('folder_id') . ' = ' . $this->db->quote($folder_id); $where'is_deleted' = $this->db->quote_identifier('is_deleted') . ' = 1'; // found more recent synckey => the last sync response was not received by the client if ($next > $sync_key) { // We store the clientIdMap with the "next" sync state, so we need to copy it back. $state->clientIdMap = $states$next->clientIdMap; - } - else { + $state->counterNext = $next; + } else { // finally delete all entries marked for removal in syncroton_content table $retryCounter = 0; - while(True) { + while (true) { $result = $this->db->query("DELETE FROM `syncroton_content` WHERE " . implode(' AND ', $where)); if ($this->db->is_error($result)) { $retryCounter++; @@ -218,8 +219,8 @@ $folder_id = $folderid instanceof Syncroton_Model_IFolder ? $folderid->id : $folderid; $where'device_id' = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id); - $where'type' = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folder_id); - $where'counter' = $this->db->quote_identifier('counter') . ' > ' . $this->db->quote($sync_key); + $where'type' = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folder_id); + $where'counter' = $this->db->quote_identifier('counter') . ' > ' . $this->db->quote($sync_key); $select = $this->db->query("SELECT id FROM `{$this->table_name}` WHERE " . implode(' AND ', $where)); return $this->db->num_rows($select) > 0;
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_body_converter.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -60,14 +60,14 @@ // ActiveSync types: TYPE_PLAINTEXT, TYPE_HTML, TYPE_RTF, TYPE_MIME switch ($this->type) { - case Syncroton_Model_EmailBody::TYPE_PLAINTEXT: - return $this->convert_text_plain($type); - case Syncroton_Model_EmailBody::TYPE_HTML: - return $this->convert_text_html($type); - case Syncroton_Model_EmailBody::TYPE_RTF: - return $this->convert_rtf($type); - default: - return $this->text; + case Syncroton_Model_EmailBody::TYPE_PLAINTEXT: + return $this->convert_plain($type); + case Syncroton_Model_EmailBody::TYPE_HTML: + return $this->convert_html($type); + case Syncroton_Model_EmailBody::TYPE_RTF: + return $this->convert_rtf($type); + default: + return $this->text; } } @@ -79,16 +79,16 @@ * * @return string Body value */ - protected function convert_text_plain($type) + protected function convert_plain($type) { $data = $this->text; switch ($type) { - case Syncroton_Model_EmailBody::TYPE_HTML: - return '<pre>' . htmlspecialchars($data, ENT_COMPAT, kolab_sync::CHARSET) . '</pre>'; - case Syncroton_Model_EmailBody::TYPE_RTF: - // @TODO - return ''; + case Syncroton_Model_EmailBody::TYPE_HTML: + return '<pre>' . htmlspecialchars($data, ENT_COMPAT, kolab_sync::CHARSET) . '</pre>'; + case Syncroton_Model_EmailBody::TYPE_RTF: + // @TODO + return ''; } return $data; @@ -102,17 +102,17 @@ * * @return string Body value */ - protected function convert_text_html($type) + protected function convert_html($type) { switch ($type) { - case Syncroton_Model_EmailBody::TYPE_PLAINTEXT: - $txt = new rcube_html2text($this->text, false, true); - return $txt->get_text(); - case Syncroton_Model_EmailBody::TYPE_RTF: - // @TODO - return ''; - case Syncroton_Model_EmailBody::TYPE_MIME: - return ''; + case Syncroton_Model_EmailBody::TYPE_PLAINTEXT: + $txt = new rcube_html2text($this->text, false, true); + return $txt->get_text(); + case Syncroton_Model_EmailBody::TYPE_RTF: + // @TODO + return ''; + case Syncroton_Model_EmailBody::TYPE_MIME: + return ''; } return $this->text; @@ -128,20 +128,28 @@ */ protected function convert_rtf($type) { - $rtf = new rtf(); - $rtf->loadrtf($this->text); - switch ($type) { - case Syncroton_Model_EmailBody::TYPE_PLAINTEXT: - $rtf->output('ascii'); - $rtf->parse(); - return $rtf->out; - case Syncroton_Model_EmailBody::TYPE_HTML: - // @TODO: Conversion to HTML is broken, - // convert to text and use <PRE> tags - $rtf->output('ascii'); - $rtf->parse(); - return '<pre>' . trim($rtf->out) . '</pre>'; + case Syncroton_Model_EmailBody::TYPE_PLAINTEXT: + try { + $document = new RtfHtmlPhp\Document($this->text); + $formatter = new RtfHtmlPhp\Html\HtmlFormatter(RCUBE_CHARSET); + $txt = new rcube_html2text($formatter->format($document), false, true); + return $txt->get_text(); + } catch (Exception $e) { + $logger = Syncroton_Registry::get('loggerBackend'); + $logger->warn("Failed to convert RTF content"); + return ''; + } + case Syncroton_Model_EmailBody::TYPE_HTML: + try { + $document = new RtfHtmlPhp\Document($this->text); + $formatter = new RtfHtmlPhp\Html\HtmlFormatter(RCUBE_CHARSET); + return $formatter->format($document); + } catch (Exception $e) { + $logger = Syncroton_Registry::get('loggerBackend'); + $logger->warn("Failed to convert RTF content"); + return ''; + } } return $this->text;
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -31,11 +31,18 @@ /** * ActiveSync protocol version * - * @var int + * @var float */ protected $asversion = 0; /** + * The storage backend + * + * @var kolab_sync_storage + */ + protected $backend; + + /** * information about the current device * * @var Syncroton_Model_IDevice @@ -71,6 +78,13 @@ protected $defaultFolder; /** + * default root folder + * + * @var string + */ + protected $defaultRootFolder; + + /** * type of user created folders * * @var int @@ -78,24 +92,17 @@ protected $folderType; /** - * Internal cache for kolab_storage folder objects + * Internal cache for storage folders list * * @var array */ - protected $folders = array(); + protected $folders = ; /** - * Internal cache for IMAP folders list + * Logger instance. * - * @var array + * @var kolab_sync_logger */ - protected $imap_folders = array(); - - /** - * Logger instance. - * - * @var kolab_sync_logger - */ protected $logger; /** @@ -110,7 +117,7 @@ * * @var array */ - protected $ext_devices = array( + protected $ext_devices = 'iphone', 'ipad', 'thundertine', @@ -118,47 +125,50 @@ 'wp', 'wp8', 'playbook', - ); + ; - const RESULT_OBJECT = 0; - const RESULT_UID = 1; - const RESULT_COUNT = 2; + protected $lastsync_folder = null; + protected $lastsync_time = null; + + public const RESULT_OBJECT = 0; + public const RESULT_UID = 1; + public const RESULT_COUNT = 2; /** * Recurrence types */ - const RECUR_TYPE_DAILY = 0; // Recurs daily. - const RECUR_TYPE_WEEKLY = 1; // Recurs weekly - const RECUR_TYPE_MONTHLY = 2; // Recurs monthly - const RECUR_TYPE_MONTHLY_DAYN = 3; // Recurs monthly on the nth day - const RECUR_TYPE_YEARLY = 5; // Recurs yearly - const RECUR_TYPE_YEARLY_DAYN = 6; // Recurs yearly on the nth day + public const RECUR_TYPE_DAILY = 0; // Recurs daily. + public const RECUR_TYPE_WEEKLY = 1; // Recurs weekly + public const RECUR_TYPE_MONTHLY = 2; // Recurs monthly + public const RECUR_TYPE_MONTHLY_DAYN = 3; // Recurs monthly on the nth day + public const RECUR_TYPE_YEARLY = 5; // Recurs yearly + public const RECUR_TYPE_YEARLY_DAYN = 6; // Recurs yearly on the nth day /** * Day of week constants */ - const RECUR_DOW_SUNDAY = 1; - const RECUR_DOW_MONDAY = 2; - const RECUR_DOW_TUESDAY = 4; - const RECUR_DOW_WEDNESDAY = 8; - const RECUR_DOW_THURSDAY = 16; - const RECUR_DOW_FRIDAY = 32; - const RECUR_DOW_SATURDAY = 64; - const RECUR_DOW_LAST = 127; // The last day of the month. Used as a special value in monthly or yearly recurrences. + public const RECUR_DOW_SUNDAY = 1; + public const RECUR_DOW_MONDAY = 2; + public const RECUR_DOW_TUESDAY = 4; + public const RECUR_DOW_WEDNESDAY = 8; + public const RECUR_DOW_THURSDAY = 16; + public const RECUR_DOW_FRIDAY = 32; + public const RECUR_DOW_SATURDAY = 64; + public const RECUR_DOW_LAST = 127; // The last day of the month. Used as a special value in monthly or yearly recurrences. /** * Mapping of recurrence types * * @var array */ - protected $recurTypeMap = array( + protected $recurTypeMap = self::RECUR_TYPE_DAILY => 'DAILY', self::RECUR_TYPE_WEEKLY => 'WEEKLY', self::RECUR_TYPE_MONTHLY => 'MONTHLY', self::RECUR_TYPE_MONTHLY_DAYN => 'MONTHLY', self::RECUR_TYPE_YEARLY => 'YEARLY', self::RECUR_TYPE_YEARLY_DAYN => 'YEARLY', - ); + ; /** * Mapping of weekdays @@ -166,7 +176,7 @@ * * @var array */ - protected $recurDayMap = array( + protected $recurDayMap = 'SU' => self::RECUR_DOW_SUNDAY, 'MO' => self::RECUR_DOW_MONDAY, 'TU' => self::RECUR_DOW_TUESDAY, @@ -174,7 +184,7 @@ 'TH' => self::RECUR_DOW_THURSDAY, 'FR' => self::RECUR_DOW_FRIDAY, 'SA' => self::RECUR_DOW_SATURDAY, - ); + ; /** @@ -185,10 +195,10 @@ */ public function __construct(Syncroton_Model_IDevice $device, DateTime $syncTimeStamp) { - $this->backend = kolab_sync_backend::get_instance(); + $this->backend = kolab_sync::storage(); $this->device = $device; $this->asversion = floatval($device->acsversion); - $this->syncTimeStamp = $syncTimeStamp; + $this->syncTimeStamp = $this->backend->syncTimeStamp = $syncTimeStamp; $this->logger = Syncroton_Registry::get(Syncroton_Registry::LOGGERBACKEND); $this->defaultRootFolder = $this->defaultFolder . '::Syncroton'; @@ -197,8 +207,7 @@ try { $this->timezone = rcube::get_instance()->config->get('timezone', 'GMT'); kolab_format::$timezone = new DateTimeZone($this->timezone); - } - catch (Exception $e) { + } catch (Exception $e) { //rcube::raise_error($e, true); $this->timezone = 'GMT'; kolab_format::$timezone = new DateTimeZone('GMT'); @@ -212,15 +221,14 @@ */ public function getAllFolders() { - $list = array(); + $list = ; // device supports multiple folders ?
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data_calendar.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -31,7 +31,7 @@ /** * Mapping from ActiveSync Calendar namespace fields */ - protected $mapping = array( + protected $mapping = 'allDayEvent' => 'allday', 'startTime' => 'start', // keep it before endTime here //'attendees' => 'attendees', @@ -54,7 +54,7 @@ 'subject' => 'title', //'timezone' => 'timezone', 'uID' => 'uid', - ); + ; /** * Kolab object type @@ -87,51 +87,59 @@ /** * attendee status */ - const ATTENDEE_STATUS_UNKNOWN = 0; - const ATTENDEE_STATUS_TENTATIVE = 2; - const ATTENDEE_STATUS_ACCEPTED = 3; - const ATTENDEE_STATUS_DECLINED = 4; - const ATTENDEE_STATUS_NOTRESPONDED = 5; + public const ATTENDEE_STATUS_UNKNOWN = 0; + public const ATTENDEE_STATUS_TENTATIVE = 2; + public const ATTENDEE_STATUS_ACCEPTED = 3; + public const ATTENDEE_STATUS_DECLINED = 4; + public const ATTENDEE_STATUS_NOTRESPONDED = 5; /** * attendee types */ - const ATTENDEE_TYPE_REQUIRED = 1; - const ATTENDEE_TYPE_OPTIONAL = 2; - const ATTENDEE_TYPE_RESOURCE = 3; + public const ATTENDEE_TYPE_REQUIRED = 1; + public const ATTENDEE_TYPE_OPTIONAL = 2; + public const ATTENDEE_TYPE_RESOURCE = 3; /** * busy status constants */ - const BUSY_STATUS_FREE = 0; - const BUSY_STATUS_TENTATIVE = 1; - const BUSY_STATUS_BUSY = 2; - const BUSY_STATUS_OUTOFOFFICE = 3; + public const BUSY_STATUS_FREE = 0; + public const BUSY_STATUS_TENTATIVE = 1; + public const BUSY_STATUS_BUSY = 2; + public const BUSY_STATUS_OUTOFOFFICE = 3; /** * Sensitivity values */ - const SENSITIVITY_NORMAL = 0; - const SENSITIVITY_PERSONAL = 1; - const SENSITIVITY_PRIVATE = 2; - const SENSITIVITY_CONFIDENTIAL = 3; + public const SENSITIVITY_NORMAL = 0; + public const SENSITIVITY_PERSONAL = 1; + public const SENSITIVITY_PRIVATE = 2; + public const SENSITIVITY_CONFIDENTIAL = 3; + + /** + * Internal iTip states + */ + public const ITIP_ACCEPTED = 'ACCEPTED'; + public const ITIP_DECLINED = 'DECLINED'; + public const ITIP_TENTATIVE = 'TENTATIVE'; + public const ITIP_CANCELLED = 'CANCELLED'; - const KEY_DTSTAMP = 'x-custom.X-ACTIVESYNC-DTSTAMP'; - const KEY_REPLYTIME = 'x-custom.X-ACTIVESYNC-REPLYTIME'; + public const KEY_DTSTAMP = 'x-custom.X-ACTIVESYNC-DTSTAMP'; + public const KEY_REPLYTIME = 'x-custom.X-ACTIVESYNC-REPLYTIME'; /** * Mapping of attendee status * * @var array */ - protected $attendeeStatusMap = array( + protected $attendeeStatusMap = 'UNKNOWN' => self::ATTENDEE_STATUS_UNKNOWN, 'TENTATIVE' => self::ATTENDEE_STATUS_TENTATIVE, 'ACCEPTED' => self::ATTENDEE_STATUS_ACCEPTED, 'DECLINED' => self::ATTENDEE_STATUS_DECLINED, 'DELEGATED' => self::ATTENDEE_STATUS_UNKNOWN, 'NEEDS-ACTION' => self::ATTENDEE_STATUS_NOTRESPONDED, - ); + ; /** * Mapping of attendee type @@ -139,35 +147,35 @@ * NOTE: recurrences need extra handling! * @var array */ - protected $attendeeTypeMap = array( + protected $attendeeTypeMap = 'REQ-PARTICIPANT' => self::ATTENDEE_TYPE_REQUIRED, 'OPT-PARTICIPANT' => self::ATTENDEE_TYPE_OPTIONAL, // 'NON-PARTICIPANT' => self::ATTENDEE_TYPE_RESOURCE, // 'CHAIR' => self::ATTENDEE_TYPE_RESOURCE, - ); + ; /** * Mapping of busy status * * @var array */ - protected $busyStatusMap = array( + protected $busyStatusMap = 'free' => self::BUSY_STATUS_FREE, 'tentative' => self::BUSY_STATUS_TENTATIVE, 'busy' => self::BUSY_STATUS_BUSY, 'outofoffice' => self::BUSY_STATUS_OUTOFOFFICE, - ); + ; /** * mapping of sensitivity * * @var array */ - protected $sensitivityMap = array( + protected $sensitivityMap = 'public' => self::SENSITIVITY_PERSONAL, 'private' => self::SENSITIVITY_PRIVATE, 'confidential' => self::SENSITIVITY_CONFIDENTIAL, - ); + ; /** @@ -175,17 +183,18 @@ * * @param Syncroton_Model_SyncCollection $collection Collection data * @param string $serverId Local entry identifier - * @param boolean $as_array Return entry as array + * @param bool $as_array Return entry as array * - * @return array|Syncroton_Model_Event|array Event object + * @return array|Syncroton_Model_Event Event object */ public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId, $as_array = false) { $event = is_array($serverId) ? $serverId : $this->getObject($collection->collectionId, $serverId); - $config = $this->getFolderConfig($event'_mailbox'); - $result = array(); - $is_outlook = stripos($this->device->devicetype, 'outlook') !== false; - $is_android = stripos($this->device->devicetype, 'android') !== false; + $config = $this->getFolderConfig($event'folderId'); + $result = ; + + $is_outlook = stripos($this->device->devicetype, 'outlook') !== false; + $is_android = stripos($this->device->devicetype, 'android') !== false; // Kolab Format 3.0 and xCal does support timezone per-date, but ActiveSync allows // only one timezone per-event. We'll use timezone of the start date @@ -196,51 +205,50 @@ $value = $this->getKolabDataItem($event, $name); switch ($name) { - case 'changed': - case 'end': - case 'start': - // For all-day events Kolab uses different times - // At least Android doesn't display such event as all-day event - if ($value && is_a($value, 'DateTime')) { - $date = clone $value; - if ($event'allday') { - // need this for self::date_from_kolab() - $date->_dateonly = false; + case 'changed': + case 'end': + case 'start': + // For all-day events Kolab uses different times + // At least Android doesn't display such event as all-day event + if ($value && is_a($value, 'DateTime')) { + $date = clone $value; + if (!empty($event'allday')) { + // need this for self::date_from_kolab() + $date->_dateonly = false; // @phpstan-ignore-line + + if ($name == 'start') { + $date->setTime(0, 0, 0);
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data_contacts.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -31,7 +31,7 @@ /** * Mapping from ActiveSync Contacts namespace fields */ - protected $mapping = array( + protected $mapping = 'anniversary' => 'anniversary', 'assistantName' => 'assistant:0', //'assistantPhoneNumber' => 'assistantphonenumber', @@ -94,7 +94,7 @@ 'managerName' => 'manager:0', //'mMS' => 'mms', 'nickName' => 'nickname', - ); + ; /** * Kolab object type @@ -149,11 +149,13 @@ * * @param Syncroton_Model_SyncCollection $collection Collection data * @param string $serverId Local entry identifier + * + * @return array|Syncroton_Model_Contact Contact object */ public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId) { $data = is_array($serverId) ? $serverId : $this->getObject($collection->collectionId, $serverId); - $result = array(); + $result = ; if (empty($data)) { throw new Syncroton_Exception_NotFound("Contact $serverId not found"); @@ -164,23 +166,23 @@ $value = $this->getKolabDataItem($data, $name); switch ($name) { - case 'photo': - if ($value) { - // ActiveSync limits photo size to 48KB (of base64 encoded string) - if (strlen($value) * 1.33 > 48 * 1024) { - continue 2; + case 'photo': + if ($value) { + // ActiveSync limits photo size to 48KB (of base64 encoded string) + if (strlen($value) * 1.33 > 48 * 1024) { + continue 2; + } } - } - break; + break; - case 'birthday': - case 'anniversary': - $value = self::date_from_kolab($value); - break; + case 'birthday': + case 'anniversary': + $value = self::date_from_kolab($value); + break; - case 'notes': - $value = $this->body_from_kolab($value, $collection); - break; + case 'notes': + $value = $this->body_from_kolab($value, $collection); + break; } if (empty($value) || is_array($value)) { @@ -191,14 +193,14 @@ } // email address(es): email1Address, email2Address, email3Address - for ($x=0; $x<3; $x++) { + for ($x = 0; $x < 3; $x++) { if (!empty($data'email'$x)) { $email = $data'email'$x; if (is_array($email)) { $email = $email'address'; } if ($email) { - $result'email' . ($x+1) . 'Address' = $email; + $result'email' . ($x + 1) . 'Address' = $email; } } } @@ -209,67 +211,67 @@ /** * convert contact from xml to libkolab array * - * @param Syncroton_Model_IEntry $data Contact to convert - * @param string $folderId Folder identifier - * @param array $entry Existing entry + * @param Syncroton_Model_Contact $data Contact to convert + * @param string $folderId Folder identifier + * @param array $entry Existing entry * * @return array Kolab object array */ - public function toKolab(Syncroton_Model_IEntry $data, $folderId, $entry = null) + public function toKolab($data, $folderId, $entry = null) { - $contact = !empty($entry) ? $entry : array(); + $contact = !empty($entry) ? $entry : ; // Contacts namespace fields foreach ($this->mapping as $key => $name) { $value = $data->$key; switch ($name) { - case 'address.work.street': - if (strtolower($this->device->devicetype) == 'palm') { - // palm pre sends the whole address in the <Contacts:BusinessStreet> tag - $value = null; - } - break; + case 'address.work.street': + if (strtolower($this->device->devicetype) == 'palm') { + // palm pre sends the whole address in the <Contacts:BusinessStreet> tag + $value = null; + } + break; - case 'website.homepage.url': - // remove facebook urls - if (preg_match('/^fb:\/\//', $value)) { - $value = null; - } - break; + case 'website.homepage.url': + // remove facebook urls + if (preg_match('/^fb:\/\//', $value)) { + $value = null; + } + break; - case 'notes': - $value = $this->getBody($value, Syncroton_Model_EmailBody::TYPE_PLAINTEXT); - // If note isn't specified keep old note - if ($value === null) { - continue 2; - } - break; + case 'notes': + $value = $this->getBody($value, Syncroton_Model_EmailBody::TYPE_PLAINTEXT); + // If note isn't specified keep old note + if ($value === null) { + continue 2; + } + break; - case 'photo': - // If photo isn't specified keep old photo - if ($value === null) { - continue 2; - } - break; - - case 'birthday': - case 'anniversary': - if ($value) { - // convert date to string format, so libkolab will store - // it with no time and timezone what could be incorrectly re-calculated (#2555) - $value = $value->format('Y-m-d'); - } - break; + case 'photo': + // If photo isn't specified keep old photo + if ($value === null) { + continue 2; + } + break; + + case 'birthday': + case 'anniversary': + if ($value) { + // convert date to string format, so libkolab will store + // it with no time and timezone what could be incorrectly re-calculated (#2555) + $value = $value->format('Y-m-d'); + } + break; } $this->setKolabDataItem($contact, $name, $value); } // email address(es): email1Address, email2Address, email3Address - $emails = array(); - for ($x=0; $x<3; $x++) { - $key = 'email' . ($x+1) . 'Address';
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data_email.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -28,12 +28,12 @@ */ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_IDataSearch { - const MAX_SEARCH_RESULT = 200; + public const MAX_SEARCH_RESULT = 200; /** * Mapping from ActiveSync Email namespace fields */ - protected $mapping = array( + protected $mapping = 'cc' => 'cc', //'contentClass' => 'contentclass', 'dateReceived' => 'internaldate', @@ -48,22 +48,22 @@ 'subject' => 'subject', //'threadTopic' => 'threadtopic', 'to' => 'to', - ); + ; - static $memory_accumulated = 0; + public static $memory_accumulated = 0; /** * Special folder type/name map * * @var array */ - protected $folder_types = array( + protected $folder_types = 2 => 'Inbox', 3 => 'Drafts', 4 => 'Deleted Items', 5 => 'Sent Items', 6 => 'Outbox', - ); + ; /** * Kolab object type @@ -93,8 +93,7 @@ */ protected $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_MAIL_USER_CREATED; - private $lastsync_folder = null; - private $lastsync_time = null; + protected $storage; /** @@ -111,10 +110,6 @@ // Outlook 2013 support multi-folder $this->ext_devices = 'windowsoutlook15'; - - if ($this->asversion >= 14) { - $this->tag_categories = true; - } } /** @@ -151,7 +146,7 @@ /** * Decode a globalObjId according to https://interoperability.blob.core.windows.net/files/MS-ASEMAIL/%5bMS-ASEMAIL%5d-150526.pdf 2.2.2.3 * - * @param string the encoded globalObjId + * @param string $globalObjId The encoded globalObjId * * @return array An array with the decoded data */ @@ -191,31 +186,31 @@ $value = null; switch ($name) { - case 'internaldate': - $value = self::date_from_kolab(rcube_utils::strtotime($headers->internaldate)); - break; + case 'internaldate': + $value = self::date_from_kolab(rcube_utils::strtotime($headers->internaldate)); + break; - case 'cc': - case 'to': - case 'replyto': - case 'from': - $addresses = rcube_mime::decode_address_list($headers->$name, null, true, $headers->charset); + case 'cc': + case 'to': + case 'replyto': + case 'from': + $addresses = rcube_mime::decode_address_list($headers->$name, null, true, $headers->charset); - foreach ($addresses as $idx => $part) { - // @FIXME: set name + address or address only? - $addresses$idx = format_email_recipient($part'mailto', $part'name'); - } + foreach ($addresses as $idx => $part) { + // @FIXME: set name + address or address only? + $addresses$idx = format_email_recipient($part'mailto', $part'name'); + } - $value = implode(',', $addresses); - break; + $value = implode(',', $addresses); + break; - case 'subject': - $value = $headers->get('subject'); - break; + case 'subject': + $value = $headers->get('subject'); + break; - case 'charset': - $value = self::charset_to_cp($headers->charset); - break; + case 'charset': + $value = self::charset_to_cp($headers->charset); + break; } if (empty($value) || is_array($value)) { @@ -229,8 +224,8 @@ $result$key = $value; } -// $result'ConversationId' = 'FF68022058BD485996BE15F6F6D99320'; -// $result'ConversationIndex' = 'CA2CFA8A23'; + // $result'ConversationId' = 'FF68022058BD485996BE15F6F6D99320'; + // $result'ConversationIndex' = 'CA2CFA8A23'; // Read flag $result'read' = intval(!empty($headers->flags'SEEN')); @@ -238,10 +233,10 @@ // Flagged message if (!empty($headers->flags'FLAGGED')) { // Use FollowUp flag which is used in Android when message is marked with a star - $result'flag' = new Syncroton_Model_EmailFlag(array( + $result'flag' = new Syncroton_Model_EmailFlag( 'flagType' => 'FollowUp', 'status' => Syncroton_Model_EmailFlag::STATUS_ACTIVE, - )); + ); } else { $result'flag' = new Syncroton_Model_EmailFlag(); } @@ -250,9 +245,8 @@ if ($headers->priority) { if ($headers->priority < 3) { $result'importance' = 2; // High - } - else if ($headers->priority > 3) { - $result'importance' = 0; // Low + } elseif ($headers->priority > 3) { + $result'importance' = 0; // Low } } @@ -267,44 +261,42 @@ if (isset($prefsSyncroton_Command_Sync::BODY_TYPE_MIME'truncationSize')) { $truncateAt = $prefsSyncroton_Command_Sync::BODY_TYPE_MIME'truncationSize'; - } - else if (isset($opts'mimeTruncation') && $opts'mimeTruncation' < Syncroton_Command_Sync::TRUNCATE_NOTHING) { + } elseif (isset($opts'mimeTruncation') && $opts'mimeTruncation' < Syncroton_Command_Sync::TRUNCATE_NOTHING) { switch ($opts'mimeTruncation') { - case Syncroton_Command_Sync::TRUNCATE_ALL: - $truncateAt = 0; - break; - case Syncroton_Command_Sync::TRUNCATE_4096: - $truncateAt = 4096; - break; - case Syncroton_Command_Sync::TRUNCATE_5120: - $truncateAt = 5120; - break; - case Syncroton_Command_Sync::TRUNCATE_7168: - $truncateAt = 7168; - break; - case Syncroton_Command_Sync::TRUNCATE_10240: - $truncateAt = 10240; - break; - case Syncroton_Command_Sync::TRUNCATE_20480: - $truncateAt = 20480; - break; - case Syncroton_Command_Sync::TRUNCATE_51200: - $truncateAt = 51200; - break; - case Syncroton_Command_Sync::TRUNCATE_102400: - $truncateAt = 102400; - break;
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data_gal.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -28,26 +28,26 @@ */ class kolab_sync_data_gal extends kolab_sync_data implements Syncroton_Data_IDataSearch { - const MAX_SEARCH_RESULT = 100; + public const MAX_SEARCH_RESULT = 100; /** * LDAP search result * * @var array */ - protected $result = array(); + protected $result = ; /** * LDAP address books list * * @var array */ - public static $address_books = array(); + public static $address_books = ; /** * Mapping from ActiveSync Contacts namespace fields */ - protected $mapping = array( + protected $mapping = 'alias' => 'nickname', 'company' => 'organization', 'displayName' => 'name', @@ -59,7 +59,7 @@ 'picture' => 'photo', 'phone' => 'phone', 'title' => 'jobtitle', - ); + ; /** * Kolab object type @@ -103,8 +103,9 @@ // Use configured fields mapping $rcube = rcube::get_instance(); $fieldmap = (array) $rcube->config->get('activesync_gal_fieldmap'); + if (!empty($fieldmap)) { - $fieldmap = array_intersec_key($fieldmap, array_keys($this->mapping)); + $fieldmap = array_intersect_key($fieldmap, array_keys($this->mapping)); $this->mapping = array_merge($this->mapping, $fieldmap); } } @@ -112,15 +113,19 @@ /** * Not used but required by parent class */ - public function toKolab(Syncroton_Model_IEntry $data, $folderId, $entry = null) + public function toKolab($data, $folderId, $entry = null) { + return ; } /** * Not used but required by parent class + * + * @return array|Syncroton_Model_Contact Contact object */ public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId) { + throw new Syncroton_Exception_NotFound("getEntry() on GAL is not implemented"); } /** @@ -133,7 +138,7 @@ */ public function getSearchEntry($data, $options) { - $result = array(); + $result = ; // Contacts namespace fields foreach ($this->mapping as $key => $name) { @@ -144,24 +149,24 @@ } switch ($name) { - case 'photo': - // @TODO: MaxPictures option - // ActiveSync limits photo size of GAL contact to 100KB - $maxsize = 102400; - if (!empty($options'picture''maxSize')) { - $maxsize = min($maxsize, $options'picture''maxSize'); - } - - if (strlen($value) > $maxsize) { - continue 2; - } - - $value = new Syncroton_Model_GALPicture(array( - 'data' => $value, // binary - 'status' => Syncroton_Model_GALPicture::STATUS_SUCCESS, - )); - - break; + case 'photo': + // @TODO: MaxPictures option + // ActiveSync limits photo size of GAL contact to 100KB + $maxsize = 102400; + if (!empty($options'picture''maxSize')) { + $maxsize = min($maxsize, $options'picture''maxSize'); + } + + if (strlen($value) > $maxsize) { + continue 2; + } + + $value = new Syncroton_Model_GALPicture( + 'data' => $value, // binary + 'status' => Syncroton_Model_GALPicture::STATUS_SUCCESS, + ); + + break; } $result$key = $value; @@ -188,7 +193,7 @@ throw new Exception('Empty/invalid search request'); } - $records = array(); + $records = ; $rcube = rcube::get_instance(); // @TODO: caching with Options->RebuildResults support @@ -220,7 +225,7 @@ // get records $result = $book->list_records(); - while ($row = $result->next()) { + foreach ($result as $row) { $row'sourceid' = $idx; // make sure 'email' item is there, convert all email:* into one @@ -255,22 +260,22 @@ $start = $total; } if ($limit > $total) { - $limit = max($start+1, $total); + $limit = max($start + 1, $total); } if ($start > 0 || $limit < $total) { - $records = array_slice($records, $start, $limit-$start); + $records = array_slice($records, $start, $limit - $start); } - $response->range = array($start, $start + count($records) - 1); + $response->range = $start, $start + count($records) - 1; } // Build result array, convert to ActiveSync format foreach ($records as $idx => $rec) { - $response->result = new Syncroton_Model_StoreResponseResult(array( + $response->result = new Syncroton_Model_StoreResponseResult( 'longId' => $rec'ID', 'properties' => $this->getSearchEntry($rec, $options), - )); + ); unset($records$idx); } @@ -282,7 +287,7 @@ * * @param string $id Address book identifier * - * @return rcube_contacts Address book object + * @return rcube_addressbook|null Address book object */ public static function get_address_book($id) { @@ -292,26 +297,31 @@ // use existing instance if (isset(self::$address_books$id) && (self::$address_books$id instanceof rcube_addressbook)) { $book = self::$address_books$id; - } - else if ($id && $ldap_config$id) { - $book = new rcube_ldap($ldap_config$id, $config->get('ldap_debug'), - $config->mail_domain($_SESSION'storage_host')); + } elseif ($id && $ldap_config$id) { + $book = new rcube_ldap( + $ldap_config$id, + $config->get('ldap_debug'), + $config->mail_domain($_SESSION'storage_host')
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data_notes.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -31,13 +31,13 @@ /** * Mapping from ActiveSync Calendar namespace fields */ - protected $mapping = array( + protected $mapping = 'body' => 'description', 'categories' => 'categories', 'lastModifiedDate' => 'changed', //'messageClass' => 'messageClass', 'subject' => 'title', - ); + ; /** * Kolab object type @@ -67,11 +67,6 @@ */ protected $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_NOTE_USER_CREATED; - /** - * Enable mapping Activesync categories into Kolab tags (relations) - */ - protected $tag_categories = true; - /** * Appends note data to xml element @@ -85,21 +80,20 @@ 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(); + $result = ; // 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 'changed': + $value = self::date_from_kolab($value); + break; - case 'description': - $value = $this->body_from_kolab($value, $collection); - break; + case 'description': + $value = $this->body_from_kolab($value, $collection); + break; } if (empty($value) || is_array($value)) { @@ -111,44 +105,39 @@ $result'messageClass' = 'IPM.StickyNote'; - // convert kolab tags into categories - $result'categories' = $this->getKolabTags($note'uid', $result'categories'); - 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 + * @param Syncroton_Model_Note $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) + public function toKolab($data, $folderid, $entry = null) { - $note = !empty($entry) ? $entry : array(); - $foldername = isset($note'_mailbox') ? $note'_mailbox' : $this->getFolderName($folderid); -// $config = $this->getFolderConfig($foldername); + $note = !empty($entry) ? $entry : ; // 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; + case 'description': + $supported_body_types = + 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);
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data_tasks.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -31,7 +31,7 @@ /** * Mapping from ActiveSync Calendar namespace fields */ - protected $mapping = array( + protected $mapping = 'body' => 'description', 'categories' => 'categories', //'complete' => 'complete', // handled separately @@ -46,26 +46,26 @@ 'subject' => 'title', 'utcDueDate' => 'due', 'utcStartDate' => 'start', - ); + ; /** * Sensitivity values */ - const SENSITIVITY_NORMAL = 0; - const SENSITIVITY_PERSONAL = 1; - const SENSITIVITY_PRIVATE = 2; - const SENSITIVITY_CONFIDENTIAL = 3; + public const SENSITIVITY_NORMAL = 0; + public const SENSITIVITY_PERSONAL = 1; + public const SENSITIVITY_PRIVATE = 2; + public const SENSITIVITY_CONFIDENTIAL = 3; /** * mapping of sensitivity * * @var array */ - protected $sensitivityMap = array( + protected $sensitivityMap = 'public' => self::SENSITIVITY_PERSONAL, 'private' => self::SENSITIVITY_PRIVATE, 'confidential' => self::SENSITIVITY_CONFIDENTIAL, - ); + ; /** * Kolab object type @@ -95,11 +95,6 @@ */ protected $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_TASK_USER_CREATED; - /** - * Enable mapping Activesync categories into Kolab tags (relations) - */ - protected $tag_categories = true; - /** * Appends contact data to xml element @@ -113,41 +108,40 @@ public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId, $as_array = false) { $task = is_array($serverId) ? $serverId : $this->getObject($collection->collectionId, $serverId); -// $config = $this->getFolderConfig($task'_mailbox'); - $result = array(); + $result = ; // Completion status (required) - $result'complete' = intval($task'status' ?? null == 'COMPLETED' || $task'complete' ?? null == 100); + $result'complete' = intval(($task'status' ?? null) == 'COMPLETED' || ($task'complete' ?? null) == 100); // Calendar namespace fields foreach ($this->mapping as $key => $name) { $value = $this->getKolabDataItem($task, $name); switch ($name) { - case 'due': - case 'start': - if (preg_match('/^UTC/i', $key)) { - $value = self::date_from_kolab($value); - } - break; - - case 'changed': - $value = $result'complete' ? self::date_from_kolab($value) : null; - break; - - case 'description': - $value = $this->body_from_kolab($value, $collection); - break; - - case 'sensitivity': - if (!empty($value)) { - $value = intval($this->sensitivityMap$value); - } - break; - - case 'priority': - $value = $this->prio_to_importance($value); - break; + case 'due': + case 'start': + if (preg_match('/^UTC/i', $key)) { + $value = self::date_from_kolab($value); + } + break; + + case 'changed': + $value = $result'complete' ? self::date_from_kolab($value) : null; + break; + + case 'description': + $value = $this->body_from_kolab($value, $collection); + break; + + case 'sensitivity': + if (!empty($value)) { + $value = intval($this->sensitivityMap$value); + } + break; + + case 'priority': + $value = $this->prio_to_importance($value); + break; } if (empty($value) || is_array($value)) { @@ -157,19 +151,12 @@ $result$key = $value; } - // convert kolab tags into categories - if (!empty($result'categories')) { - $result'categories' = $this->getKolabTags($task'uid', $result'categories'); - } - // Recurrence $this->recurrence_from_kolab($collection, $task, $result, 'Task'); return $as_array ? $result : new Syncroton_Model_Task($result); } - - /** * Apply a timezone matching the utc offset. */ @@ -188,17 +175,15 @@ /** * convert contact from xml to libkolab array * - * @param Syncroton_Model_IEntry $data Contact to convert - * @param string $folderid Folder identifier - * @param array $entry Existing entry + * @param Syncroton_Model_Task $data Contact to convert + * @param string $folderid Folder identifier + * @param array $entry Existing entry * * @return array */ - public function toKolab(Syncroton_Model_IEntry $data, $folderid, $entry = null) + public function toKolab($data, $folderid, $entry = null) { - $task = !empty($entry) ? $entry : array(); - $foldername = isset($task'_mailbox') ? $task'_mailbox' : $this->getFolderName($folderid); -// $config = $this->getFolderConfig($foldername); + $task = !empty($entry) ? $entry : ; $task'allday' = 0; @@ -208,38 +193,38 @@ switch ($name) { - case 'due': - case 'start': - // We expect to always get regular and utc variants, so we only need to take one into account. - if ($key == 'utcStartDate' || $key == 'utcDueDate') { - continue 2; - } - if ($value) { - if ($name =='due' && $data->utcDueDate) { - $value = static::applyTimezone($value, $data->utcDueDate); + case 'due': + case 'start': + // We expect to always get regular and utc variants, so we only need to take one into account. + if ($key == 'utcStartDate' || $key == 'utcDueDate') { + continue 2; + } + if ($value) { + if ($name == 'due' && $data->utcDueDate) { + $value = self::applyTimezone($value, $data->utcDueDate); + } + if ($name == 'start' && $data->utcStartDate) { + $value = self::applyTimezone($value, $data->utcStartDate); + }
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_logger.php
Changed
@@ -1,4 +1,5 @@ <?php + /* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | @@ -37,7 +38,7 @@ /** * Constructor */ - function __construct($mode = null) + public function __construct($mode = null) { $rcube = rcube::get_instance(); @@ -80,8 +81,7 @@ if (is_numeric($method)) { $mode = $method; $method = array_search($method, $this->_priorities); - } - else { + } else { $mode = $this->_priorities$method; } @@ -103,14 +103,14 @@ // otherwise use separate file for info/debug and warning/error if (!$logfile) { switch ($mode) { - case self::DEBUG: - case self::INFO: - case self::NOTICE: - $file = 'console'; - break; - default: - $file = 'errors'; - break; + case self::DEBUG: + case self::INFO: + case self::NOTICE: + $file = 'console'; + break; + default: + $file = 'errors'; + break; } $logfile = $log_dir . DIRECTORY_SEPARATOR . $file; @@ -118,8 +118,7 @@ if (version_compare(version_parse(RCUBE_VERSION), '1.4.0') >= 0) { $logfile .= $rcube->config->get('log_file_ext', '.log'); } - } - else if ($logfile0 != '/') { + } elseif ($logfile0 != '/') { $logfile = $log_dir . DIRECTORY_SEPARATOR . $logfile; } @@ -129,8 +128,8 @@ // add user/request information to the log if ($mode <= self::WARN) { - $device = array(); - $params = array('cmd' => 'Cmd', 'device' => 'DeviceId', 'type' => 'DeviceType'); + $device = ; + $params = 'cmd' => 'Cmd', 'device' => 'DeviceId', 'type' => 'DeviceType'; if (!empty($this->username)) { $device'user' = $this->username;
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_message.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -25,17 +25,17 @@ class kolab_sync_message { - protected $headers = array(); + protected $headers = ; protected $body; protected $ctype; - protected $ctype_params = array(); + protected $ctype_params = ; /** * Constructor * * @param string|resource $source MIME message source */ - function __construct($source) + public function __construct($source) { $this->parse_mime($source); } @@ -52,7 +52,7 @@ public function source() { - $headers = array(); + $headers = ; // Build the message back foreach ($this->headers as $header => $header_value) { @@ -89,22 +89,22 @@ * Adds attachment to the message * * @param string $body Attachment body (not encoded) - * @param string $params Attachment parameters (Mail_mimePart format) + * @param array $params Attachment parameters (Mail_mimePart format) */ - public function add_attachment($body, $params = array()) + public function add_attachment($body, $params = ) { // convert the message into multipart/mixed if ($this->ctype != 'multipart/mixed') { $boundary = '_' . md5(rand() . microtime()); $this->body = "--$boundary\r\n" - ."Content-Type: " . $this->headers'Content-Type'."\r\n" - ."Content-Transfer-Encoding: " . $this->headers'Content-Transfer-Encoding'."\r\n" - ."\r\n" . trim($this->body) . "\r\n" - ."--$boundary\r\n"; + . "Content-Type: " . $this->headers'Content-Type' . "\r\n" + . "Content-Transfer-Encoding: " . $this->headers'Content-Transfer-Encoding' . "\r\n" + . "\r\n" . trim($this->body) . "\r\n" + . "--$boundary\r\n"; $this->ctype = 'multipart/mixed'; - $this->ctype_params = array('boundary' => $boundary); + $this->ctype_params = 'boundary' => $boundary; unset($this->headers'Content-Transfer-Encoding'); $this->save_content_type($this->ctype, $this->ctype_params); } @@ -128,8 +128,8 @@ // add the attachment to the end of the message $this->body .= "\r\n" - .implode("\r\n", $body'headers') . "\r\n\r\n" - .$body'body' . "\r\n--$boundary--\r\n"; + . implode("\r\n", $body'headers') . "\r\n\r\n" + . $body'body' . "\r\n--$boundary--\r\n"; } /** @@ -153,11 +153,11 @@ * @param array $smtp_error SMTP error array (reference) * @param array $smtp_opts SMTP options (e.g. DSN request) * - * @return boolean Send status. + * @return bool Send status. */ public function send(&$smtp_error = null, $smtp_opts = null) { - $rcube = rcube::get_instance(); + $rcube = kolab_sync::get_instance(); $headers = $this->headers; $mailto = $headers'To'; @@ -170,7 +170,7 @@ $headers'From' = $this->get_identity(); } // make sure there's sender name in From: - else if ($rcube->config->get('activesync_fix_from') + elseif ($rcube->config->get('activesync_fix_from') && preg_match('/^<?((\S+|("^"+"))@\S+)>?$/', trim($headers'From'), $m) ) { $identities = kolab_sync::get_instance()->user->list_identities(); @@ -196,14 +196,17 @@ $smtp_headers = $headers; // generate list of recipients - $recipients = array(); + $recipients = ; - if (!empty($headers'To')) + if (!empty($headers'To')) { $recipients = $headers'To'; - if (!empty($headers'Cc')) + } + if (!empty($headers'Cc')) { $recipients = $headers'Cc'; - if (!empty($headers'Bcc')) + } + if (!empty($headers'Bcc')) { $recipients = $headers'Bcc'; + } if (empty($headers'To') && empty($headers'Cc')) { $headers'To' = 'undisclosed-recipients:;'; @@ -223,13 +226,13 @@ // log error if (!$sent) { - rcube::raise_error(array('code' => 800, 'type' => 'smtp', + rcube::raise_error('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__, - 'message' => "SMTP error: ".join("\n", $smtp_response)), true, false); + 'message' => "SMTP error: " . implode("\n", $smtp_response), true, false); } if ($sent) { - $rcube->plugins->exec_hook('message_sent', array('headers' => $headers, 'body' => $this->body)); + $rcube->plugins->exec_hook('message_sent', 'headers' => $headers, 'body' => $this->body); // remove MDN headers after sending unset($headers'Return-Receipt-To', $headers'Disposition-Notification-To'); @@ -238,12 +241,16 @@ // get all recipient addresses $mailto = rcube_mime::decode_address_list(implode(',', $recipients), null, false, null, true); - rcube::write_log('sendmail', sprintf("User %s %s; Message %s for %s; %s", - $rcube->get_user_name(), - rcube_utils::remote_addr(), - $headers'Message-ID', - implode(', ', $mailto), - !empty($smtp_response) ? implode('; ', $smtp_response) : '') + rcube::write_log( + 'sendmail', + sprintf( + "User %s %s; Message %s for %s; %s", + $rcube->get_user_name(), + rcube_utils::remote_addr(), + $headers'Message-ID', + implode(', ', $mailto), + !empty($smtp_response) ? implode('; ', $smtp_response) : '' + ) ); } } @@ -269,7 +276,7 @@ $message = stream_get_contents($message); } - list($headers, $message) = array_pad(preg_split('/\r?\n\r?\n/', $message, 2, PREG_SPLIT_NO_EMPTY), 2, ''); + $headers, $message = array_pad(preg_split('/\r?\n\r?\n/', $message, 2, PREG_SPLIT_NO_EMPTY), 2, ''); $hdrs = self::parse_headers($headers); @@ -278,11 +285,11 @@ $boundary = '--' . $matches1; $message = explode($boundary, $message); - for ($x=1, $parts = count($message) - 1; $x<$parts; $x++) { + for ($x = 1, $parts = count($message) - 1; $x < $parts; $x++) { $message$x = "\r\n" . self::recode_message(ltrim($message$x)); } - return $headers . "\r\n\r\n" . implode($boundary , $message); + return $headers . "\r\n\r\n" . implode($boundary, $message); } // single part @@ -331,10 +338,7 @@ /** * MIME message parser * - * @param string|resource $message MIME message source - * @param bool $decode_body Enables body decoding - * - * @return array Message headers array and message body + * @param string|resource $message MIME message source */ protected function parse_mime($message) { @@ -343,7 +347,7 @@
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_plugin_api.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -35,7 +35,7 @@ * * @return rcube_plugin_api The one and only instance if this class */ - static function get_instance() + public static function get_instance() { if (!self::$instance) { self::$instance = new kolab_sync_plugin_api(); @@ -44,22 +44,20 @@ return self::$instance; } - /** * Initialize plugin engine * * This has to be done after rcmail::load_gui() or rcmail::json_init() * was called because plugins need to have access to rcmail->output * - * @param object rcube Instance of the rcube base class - * @param string Current application task (used for conditional plugin loading) + * @param rcube $app Instance of the rcube base class + * @param string $task Current application task (used for conditional plugin loading) */ public function init($app, $task = '') { $this->task = $task; } - /** * Register a handler function for template objects * @@ -72,7 +70,6 @@ // empty } - /** * Register this plugin to be responsible for a specific task * @@ -84,7 +81,6 @@ $this->tasks$task = $owner; } - /** * Include a plugin script file in the current HTML page * @@ -95,7 +91,6 @@ //empty } - /** * Include a plugin stylesheet in the current HTML page *
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_storage.php
Added
@@ -0,0 +1,2064 @@ +<?php + +/* + +--------------------------------------------------------------------------+ + | Kolab Sync (ActiveSync for Kolab) | + | | + | Copyright (C) 2011-2012, 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> | + +--------------------------------------------------------------------------+ +*/ + +/** + * Storage handling class with basic Kolab support (everything stored in IMAP) + */ +class kolab_sync_storage +{ + public const INIT_SUB_PERSONAL = 1; // all subscribed folders in personal namespace + public const INIT_ALL_PERSONAL = 2; // all folders in personal namespace + public const INIT_SUB_OTHER = 4; // all subscribed folders in other users namespace + public const INIT_ALL_OTHER = 8; // all folders in other users namespace + public const INIT_SUB_SHARED = 16; // all subscribed folders in shared namespace + public const INIT_ALL_SHARED = 32; // all folders in shared namespace + + public const MODEL_CALENDAR = 'event'; + public const MODEL_CONTACTS = 'contact'; + public const MODEL_EMAIL = 'mail'; + public const MODEL_NOTES = 'note'; + public const MODEL_TASKS = 'task'; + + public const ROOT_MAILBOX = 'INBOX'; + public const ASYNC_KEY = '/private/vendor/kolab/activesync'; + public const UID_KEY = '/shared/vendor/cmu/cyrus-imapd/uniqueid'; + + public const CTYPE_KEY = '/shared/vendor/kolab/folder-type'; + public const CTYPE_KEY_PRIVATE = '/private/vendor/kolab/folder-type'; + + public $syncTimeStamp; + + protected $storage; + protected $folder_meta; + protected $folder_uids; + protected $folders = ; + protected $modseq = ; + protected $root_meta; + protected $relations = ; + protected $relationSupport = true; + protected $tag_rts = ; + + protected static $instance; + + protected static $types = + 1 => '', + 2 => 'mail.inbox', + 3 => 'mail.drafts', + 4 => 'mail.wastebasket', + 5 => 'mail.sentitems', + 6 => 'mail.outbox', + 7 => 'task.default', + 8 => 'event.default', + 9 => 'contact.default', + 10 => 'note.default', + 11 => 'journal.default', + 12 => 'mail', + 13 => 'event', + 14 => 'contact', + 15 => 'task', + 16 => 'journal', + 17 => 'note', + ; + + + /** + * This implements the 'singleton' design pattern + * + * @return kolab_sync_storage The one and only instance + */ + public static function get_instance() + { + if (!self::$instance) { + self::$instance = new kolab_sync_storage(); + self::$instance->startup(); // init AFTER object was linked with self::$instance + } + + return self::$instance; + } + + /** + * Class initialization + */ + public function startup() + { + $this->storage = kolab_sync::get_instance()->get_storage(); + + // set additional header used by libkolab + $this->storage->set_options( + // @TODO: there can be Roundcube plugins defining additional headers, + // we maybe would need to add them here + 'fetch_headers' => 'X-KOLAB-TYPE X-KOLAB-MIME-VERSION', + 'skip_deleted' => true, + 'threading' => false, + ); + + // Disable paging + $this->storage->set_pagesize(999999); + } + + /** + * Clear internal cache state + */ + public function reset() + { + $this->folders = ; + } + + /** + * List known devices + * + * @return array Device list as hash array + */ + public function devices_list() + { + if ($this->root_meta === null) { + // @TODO: consider server annotation instead of INBOX + if ($meta = $this->storage->get_metadata(self::ROOT_MAILBOX, self::ASYNC_KEY)) { + $this->root_meta = $this->unserialize_metadata($metaself::ROOT_MAILBOXself::ASYNC_KEY); + } else { + $this->root_meta = ; + } + } + + if (!empty($this->root_meta'DEVICE') && is_array($this->root_meta'DEVICE')) { + return $this->root_meta'DEVICE'; + } + + return ; + } + + /** + * Get list of folders available for sync + * + * @param string $deviceid Device identifier + * @param string $type Folder type + * @param bool $flat_mode Enables flat-list mode + * + * @return array|bool List of mailbox folders, False on backend failure + */ + public function folders_list($deviceid, $type, $flat_mode = false) + { + // get all folders of specified type + $folders = kolab_storage::list_folders('', '*', $type, false, $typedata); + + // get folders activesync config + $folderdata = $this->folder_meta(); + + if (!is_array($folders) || !is_array($folderdata)) { + return false; + } + + $folders_list = ; + + // check if folders are "subscribed" for activesync + foreach ($folderdata as $folder => $meta) { + if (empty($meta'FOLDER') || empty($meta'FOLDER'$deviceid) + || empty($meta'FOLDER'$deviceid'S') + ) { + continue; + } + + // force numeric folder name to be a string (T1283) + $folder = (string) $folder; + + if (!empty($type) && !in_array($folder, $folders)) { + continue; + } + + // Activesync folder identifier (serverId) + $folder_type = !empty($typedata$folder) ? $typedata$folder : 'mail'; + $folder_id = $this->folder_id($folder, $folder_type); + + $folders_list$folder_id = $this->folder_data($folder, $folder_type); + } + + if ($flat_mode) { + $folders_list = $this->folders_list_flat($folders_list, $type, $typedata); + }
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_storage_kolab4.php
Added
@@ -0,0 +1,563 @@ +<?php + +/* + +--------------------------------------------------------------------------+ + | Kolab Sync (ActiveSync for Kolab) | + | | + | Copyright (C) 2011-2023, Apheleia IT AG <contact@apheleia-it.ch> | + | | + | 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> | + +--------------------------------------------------------------------------+ +*/ + +/** + * Storage handling class with Kolab 4 support (IMAP + CalDAV + CardDAV) + */ +class kolab_sync_storage_kolab4 extends kolab_sync_storage +{ + protected $davStorage = null; + protected $relationSupport = false; + + /** + * This implements the 'singleton' design pattern + * + * @return kolab_sync_storage_kolab4 The one and only instance + */ + public static function get_instance() + { + if (!self::$instance) { + self::$instance = new kolab_sync_storage_kolab4(); + self::$instance->startup(); // init AFTER object was linked with self::$instance + } + + return self::$instance; + } + + /** + * Class initialization + */ + public function startup() + { + $sync = kolab_sync::get_instance(); + + if ($sync->username === null || $sync->password === null) { + throw new Exception("Unsupported storage handler use!"); + } + + $url = $sync->config->get('activesync_dav_server', 'http://localhost'); + + if (strpos($url, '://') === false) { + $url = 'http://' . $url; + } + + // Inject user+password to the URL, there's no other way to pass it to the DAV client + $url = str_replace('://', '://' . rawurlencode($sync->username) . ':' . rawurlencode($sync->password) . '@', $url); + + $this->davStorage = new kolab_storage_dav($url); // DAV + $this->storage = $sync->get_storage(); // IMAP + + // set additional header used by libkolab + $this->storage->set_options( + 'skip_deleted' => true, + 'threading' => false, + ); + + // Disable paging + $this->storage->set_pagesize(999999); + } + + /** + * Get list of folders available for sync + * + * @param string $deviceid Device identifier + * @param string $type Folder (class) type + * @param bool $flat_mode Enables flat-list mode + * + * @return array|bool List of mailbox folders, False on backend failure + */ + public function folders_list($deviceid, $type, $flat_mode = false) + { + $list = ; + + // get mail folders subscribed for sync + if ($type === self::MODEL_EMAIL) { + $folderdata = $this->folder_meta(); + + if (!is_array($folderdata)) { + return false; + } + + $special_folders = $this->storage->get_special_folders(true); + $type_map = + 'drafts' => 3, + 'trash' => 4, + 'sent' => 5, + ; + + // Get the folders "subscribed" for activesync + foreach ($folderdata as $folder => $meta) { + if (empty($meta'FOLDER') || empty($meta'FOLDER'$deviceid) + || empty($meta'FOLDER'$deviceid'S') + ) { + continue; + } + + // Force numeric folder name to be a string (T1283) + $folder = (string) $folder; + + // Activesync folder properties + $folder_data = $this->folder_data($folder, 'mail'); + + // Set proper type for special folders + if (($type = array_search($folder, $special_folders)) && isset($type_map$type)) { + $folder_data'type' = $type_map$type; + } + + $list$folder_data'serverId' = $folder_data; + } + } elseif (in_array($type, self::MODEL_CONTACTS, self::MODEL_CALENDAR, self::MODEL_TASKS)) { + if (!empty($this->folders)) { + foreach ($this->folders as $unique_key => $folder) { + if (strpos($unique_key, "DAV:$type:") === 0) { + $folder_data = $this->folder_data($folder, $type); + $list$folder_data'serverId' = $folder_data; + } + } + } + + // TODO: For now all DAV folders are subscribed + + if (empty($list)) { + foreach ($this->davStorage->get_folders($type) as $folder) { + $folder_data = $this->folder_data($folder, $type); + $list$folder_data'serverId' = $folder_data; + + // Store all folder objects in internal cache, otherwise + // Any access to the folder (or list) will invoke excessive DAV requests + $unique_key = $folder_data'serverId' . ":$deviceid:$type"; + $this->folders$unique_key = $folder; + } + } + } + /* + // TODO + if ($flat_mode) { + $list = $this->folders_list_flat($list, $type, $typedata); + } + */ + return $list; + } + + /** + * Creates folder and subscribes to the device + * + * @param string $name Folder name (UTF8) + * @param int $type Folder (ActiveSync) type + * @param string $deviceid Device identifier + * @param ?string $parentid Parent folder identifier + * + * @return string|false New folder identifier on success, False on failure + */ + public function folder_create($name, $type, $deviceid, $parentid = null) + { + // Mail folder + if ($type <= 6 || $type == 12) { + $parent = null; + $name = rcube_charset::convert($name, kolab_sync::CHARSET, 'UTF7-IMAP'); + + if ($parentid) { + $parent = $this->folder_id2name($parentid, $deviceid); + + if ($parent === null) { + throw new Syncroton_Exception_Status_FolderCreate(Syncroton_Exception_Status_FolderCreate::PARENT_NOT_FOUND); + } + } + + if ($parent !== null) { + $delim = $this->storage->get_hierarchy_delimiter(); + $name = $parent . $delim . $name; + } + + if ($this->storage->folder_exists($name)) { + throw new Syncroton_Exception_Status_FolderCreate(Syncroton_Exception_Status_FolderCreate::FOLDER_EXISTS); + } + + // TODO: Support setting folder types? +
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_timezone_converter.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -33,11 +33,11 @@ /** * holds the instance of the singleton * - * @var kolab_sync_timezone_onverter + * @var ?kolab_sync_timezone_converter */ - private static $_instance = NULL; + private static $_instance; - protected $_startDate = array(); + protected $_startDate = ; /** * If set then the timezone guessing results will be cached. @@ -51,19 +51,19 @@ * array of offsets known by ActiceSync clients, but unknown by php * @var array */ - protected $_knownTimezones = array( - '0AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==' => array( - 'Pacific/Kwajalein' => 'MHT' - ) - ); + protected $_knownTimezones = + '0AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==' => + 'Pacific/Kwajalein' => 'MHT', + , + ; - protected $_legacyTimezones = array( + protected $_legacyTimezones = // This is an outdated timezone that outlook keeps sending because of an outdate timezone database on windows - 'Lv///0kAcgBhAG4AIABTAHQAYQBuAGQAYQByAGQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkABAADABcAOwA7AOcDAAAAAEkAcgBhAG4AIABEAGEAeQBsAGkAZwBoAHQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAwAEAAAAAAAAAAAAxP///w==' => array( - 'Asia/Tehran' => '+0330' - ) - ); + 'Lv///0kAcgBhAG4AIABTAHQAYQBuAGQAYQByAGQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkABAADABcAOwA7AOcDAAAAAEkAcgBhAG4AIABEAGEAeQBsAGkAZwBoAHQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAwAEAAAAAAAAAAAAxP///w==' => + 'Asia/Tehran' => '+0330', + , + ; /** * don't use the constructor. Use the singleton. @@ -88,7 +88,7 @@ */ public static function getInstance() { - if (self::$_instance === NULL) { + if (self::$_instance === null) { self::$_instance = new kolab_sync_timezone_converter(); } @@ -147,22 +147,20 @@ { if (is_string($_offsets) && isset($this->_knownTimezones$_offsets)) { $timezones = $this->_knownTimezones$_offsets; - } - elseif (is_string($_offsets) && isset($this->_legacyTimezones$_offsets)) { + } elseif (is_string($_offsets) && isset($this->_legacyTimezones$_offsets)) { $timezones = $this->_legacyTimezones$_offsets; - } - else { + } else { if (is_string($_offsets)) { // unpack timezone info to array $_offsets = $this->_unpackTimezoneInfo($_offsets); } if (!$this->_validateOffsets($_offsets)) { - return array(); + return ; } $this->_setDefaultStartDateIfEmpty($_offsets); - $timezones = array(); + $timezones = ; foreach (DateTimeZone::listIdentifiers() as $timezoneIdentifier) { $timezone = new DateTimeZone($timezoneIdentifier); if (false !== ($matchingTransition = $this->_checkTimezone($timezone, $_offsets))) { @@ -180,7 +178,7 @@ * If {@see $_expectedTimezone} is set then the method will return this timezone if it matches. * * @param string|array $_offsets Activesync timezone definition - * @param string $_expectedTomezone Expected timezone name + * @param string $_expectedTimezone Expected timezone name * * @return string Expected timezone name */ @@ -190,8 +188,7 @@ if ($_expectedTimezone && isset($timezones$_expectedTimezone)) { return $_expectedTimezone; - } - else { + } else { return key($timezones); } } @@ -223,20 +220,21 @@ * * @param DateTime $date The date with the timezone to encode * - * @return string encoded timezone + * @return string|null Timezone name */ public static function encodeTimezoneFromDate($date) { if ($date instanceof DateTime) { $timezone = $date->getTimezone(); - if ($timezone && ($tz_name = $timezone->getName()) != 'UTC') { + if (($tz_name = $timezone->getName()) != 'UTC') { $tzc = self::getInstance(); if ($tz_name = $tzc->encodeTimezone($tz_name, $date->format('Y-m-d'))) { return $tz_name; } } } + return null; } @@ -246,7 +244,7 @@ * @param string $_timezone Timezone identifier * @param string|int $_startDate Start date * - * @return array Timezone offsets + * @return array|null Timezone offsets */ public function getOffsetsForTimezone($_timezone, $_startDate = null) { @@ -256,15 +254,14 @@ try { $timezone = new DateTimeZone($_timezone); - } - catch (Exception $e) { + } catch (Exception $e) { return null; } - list($standardTransition, $daylightTransition) = $this->_getTransitionsForTimezoneAndYear($timezone, $this->_startDate'year'); + $standardTransition, $daylightTransition = $this->_getTransitionsForTimezoneAndYear($timezone, $this->_startDate'year'); if ($standardTransition) { - $offsets'bias' = $standardTransition'offset'/60*-1; + $offsets'bias' = $standardTransition'offset' / 60 * -1; if ($daylightTransition) { $offsets = $this->_generateOffsetsForTransition($offsets, $standardTransition, 'standard', $timezone); $offsets = $this->_generateOffsetsForTransition($offsets, $daylightTransition, 'daylight', $timezone); @@ -272,7 +269,7 @@ //@todo how do we get the standardBias (is usually 0)? //$offsets'standardBias' = ... - $offsets'daylightBias' = ($daylightTransition'offset' - $standardTransition'offset')/60*-1; + $offsets'daylightBias' = ($daylightTransition'offset' - $standardTransition'offset') / 60 * -1; $offsets'standardHour' -= $offsets'daylightBias' / 60; $offsets'daylightHour' += $offsets'daylightBias' / 60; } @@ -304,7 +301,7 @@ $_offsets$_type . 'Minute' = (int) $transitionDate->format('i'); $_offsets$_type . 'Hour' = (int) $transitionDate->format('G'); - for ($i=5; $i>0; $i--) { + for ($i = 5; $i > 0; $i--) { if ($this->_isNthOcurrenceOfWeekdayInMonth($transitionDate, $i)) { $_offsets$_type . 'Week' = $i; break; @@ -359,8 +356,10 @@ * Check if the given {@param $_standardTransition} and {@param $_daylightTransition} * match to the object property {@see $_offsets} * - * @param array $standardTransition - * @param array $daylightTransition + * @param array $_standardTransition + * @param array $_daylightTransition + * @param array $_offsets + * @param DateTimeZone $tz * * @return bool */ @@ -383,7 +382,7 @@ $daylightOffset = ($_offsets'bias' + $_offsets'daylightBias') * 60 * -1; // the milestone is sending a positive value for daylightBias while it should send a negative value - $daylightOffsetMilestone = ($_offsets'bias' + ($_offsets'daylightBias' * -1) ) * 60 * -1; + $daylightOffsetMilestone = ($_offsets'bias' + ($_offsets'daylightBias' * -1)) * 60 * -1; if ( !empty($_daylightTransition)
View file
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_transaction_manager.php
Changed
@@ -1,6 +1,6 @@ <?php -/** +/* +--------------------------------------------------------------------------+ | Kolab Sync (ActiveSync for Kolab) | | | @@ -43,17 +43,17 @@ /** * @var array holds all transactionables with open transactions */ - protected $_openTransactionables = array(); + protected $_openTransactionables = ; /** * @var array list of all open (not commited) transactions */ - protected $_openTransactions = array(); + protected $_openTransactions = ; /** - * @var Syncroton_TransactionManager + * @var ?self */ - private static $_instance = NULL; + private static $_instance; /** * @var Zend_Log @@ -78,12 +78,12 @@ } /** - * @return Tinebase_TransactionManager + * @return self */ public static function getInstance() { - if (self::$_instance === NULL) { - self::$_instance = new kolab_sync_transaction_manager; + if (self::$_instance === null) { + self::$_instance = new kolab_sync_transaction_manager(); } return self::$_instance; @@ -92,9 +92,10 @@ /** * starts a transaction * - * @param mixed $_transactionable - * @return string transactionId - * @throws Tinebase_Exception_UnexpectedValue + * @param mixed $_transactionable + * + * @return string Transaction Id + * @throws Exception */ public function startTransaction($_transactionable) { @@ -105,8 +106,7 @@ if (! in_array($_transactionable, $this->_openTransactionables)) { if ($_transactionable instanceof rcube_db) { $_transactionable->startTransaction(); - } - else { + } else { $this->rollBack(); throw new Syncroton_Exception_UnexpectedValue('Unsupported transactionable!'); } @@ -114,7 +114,7 @@ array_push($this->_openTransactionables, $_transactionable); } - $transactionId = sha1(mt_rand(). microtime()); + $transactionId = sha1(mt_rand() . microtime()); array_push($this->_openTransactions, $transactionId); return $transactionId; @@ -146,10 +146,9 @@ } } - $this->_openTransactionables = array(); - $this->_openTransactions = array(); - } - else { + $this->_openTransactionables = ; + $this->_openTransactions = ; + } else { if ($this->_logger instanceof Zend_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " commiting defered, as there are still $numOpenTransactions in the queue"); } @@ -173,7 +172,7 @@ } } - $this->_openTransactionables = array(); - $this->_openTransactions = array(); + $this->_openTransactionables = ; + $this->_openTransactions = ; } }
View file
kolab-syncroton-2.4.2.tar.gz/phpstan.bootstrap.php
Added
@@ -0,0 +1,12 @@ +<?php + +// environment initialization + +require_once 'lib/init.php'; + +set_include_path(implode(PATH_SEPARATOR, + 'lib/plugins/libkolab/lib', + 'lib/plugins/libcalendaring', + 'lib/plugins/libcalendaring/lib', + ini_get('include_path'), +));
View file
kolab-syncroton-2.4.2.tar.gz/phpstan.neon
Added
@@ -0,0 +1,25 @@ +parameters: + bootstrapFiles: + - phpstan.bootstrap.php + + excludePaths: + - vendor + - lib/plugins + - lib/ext/Roundcube + - lib/ext/Syncroton + + ignoreErrors: + - |Access to an undefined property Syncroton_Model_.*| + - |Access to offset .* on an unknown class An.| + - |Property rcube::\$user .*| + + paths: + - lib + - tests + + level: 4 + + scanDirectories: + - lib/ext + + treatPhpDocTypesAsCertain: false
View file
kolab-syncroton-2.4.2.tar.gz/tests/Sync
Added
+(directory)
View file
kolab-syncroton-2.4.2.tar.gz/tests/Sync/FoldersTest.php
Added
@@ -0,0 +1,389 @@ +<?php + +class FoldersTest extends Tests\SyncTestCase +{ + /** + * Test FolderSync command + */ + public function testFolderSync() + { + // Note: We essentially assume the test account is in an initial state, extra folders may break tests + // Anyway, we first remove folders that might have been created during tests in this file + $this->deleteTestFolder('Test Folder', 'mail'); + $this->deleteTestFolder('Test Folder New', 'mail'); + $this->deleteTestFolder('Test Contacts Folder', 'contact'); + $this->deleteTestFolder('Test Contacts New', 'contact'); + + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <FolderSync xmlns="uri:FolderHierarchy"> + <SyncKey>0</SyncKey> + </FolderSync> + EOF; + + $response = $this->request($request, 'FolderSync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + // Note: We're expecting activesync_init_subscriptions=0 here. + if ($this->isStorageDriver('kolab4')) { + $folders = + 'Calendar', Syncroton_Command_FolderSync::FOLDERTYPE_CALENDAR, + 'Contacts', Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT, + 'INBOX', Syncroton_Command_FolderSync::FOLDERTYPE_INBOX, + 'Drafts', Syncroton_Command_FolderSync::FOLDERTYPE_DRAFTS, + 'Sent', Syncroton_Command_FolderSync::FOLDERTYPE_SENTMAIL, + 'Trash', Syncroton_Command_FolderSync::FOLDERTYPE_DELETEDITEMS, + 'Tasks', Syncroton_Command_FolderSync::FOLDERTYPE_TASK, + ; + + } else { + $folders = + 'Calendar', Syncroton_Command_FolderSync::FOLDERTYPE_CALENDAR, + 'Contacts', Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT, + 'INBOX', Syncroton_Command_FolderSync::FOLDERTYPE_INBOX, + 'Drafts', Syncroton_Command_FolderSync::FOLDERTYPE_DRAFTS, + 'Sent', Syncroton_Command_FolderSync::FOLDERTYPE_SENTMAIL, + 'Trash', Syncroton_Command_FolderSync::FOLDERTYPE_DELETEDITEMS, + 'Notes', Syncroton_Command_FolderSync::FOLDERTYPE_NOTE, + 'Tasks', Syncroton_Command_FolderSync::FOLDERTYPE_TASK, + ; + } + + $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue); + $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:SyncKey")->item(0)->nodeValue); + $this->assertSame(strval(count($folders)), $xpath->query("//ns:FolderSync/ns:Changes/ns:Count")->item(0)->nodeValue); + + foreach ($folders as $idx => $folder) { + $this->assertSame($folder0, $xpath->query("//ns:FolderSync/ns:Changes/ns:Add/ns:DisplayName")->item($idx)->nodeValue); + $this->assertSame((string) $folder1, $xpath->query("//ns:FolderSync/ns:Changes/ns:Add/ns:Type")->item($idx)->nodeValue); + $this->assertSame('0', $xpath->query("//ns:FolderSync/ns:Changes/ns:Add/ns:ParentId")->item($idx)->nodeValue); + } + + // Test with multi-folder support enabled + self::$deviceType = 'iphone'; + + $response = $this->request($request, 'FolderSync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + if ($this->isStorageDriver('kolab4')) { + $folders = + 'Calendar', Syncroton_Command_FolderSync::FOLDERTYPE_CALENDAR_USER_CREATED, + // Note: Kolab 4 with Cyrus DAV uses Addressbook, but Kolab 3 with iRony would use 'Contacts' + '/^(Contacts|Addressbook)$/', Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT_USER_CREATED, + 'INBOX', Syncroton_Command_FolderSync::FOLDERTYPE_INBOX, + 'Drafts', Syncroton_Command_FolderSync::FOLDERTYPE_DRAFTS, + 'Sent', Syncroton_Command_FolderSync::FOLDERTYPE_SENTMAIL, + 'Trash', Syncroton_Command_FolderSync::FOLDERTYPE_DELETEDITEMS, + // Note: For now Kolab 4 uses the same Calendar folder for calendar and tasks + '/^(Tasks|Calendar)$/', Syncroton_Command_FolderSync::FOLDERTYPE_TASK_USER_CREATED, + ; + } + + $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue); + $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:SyncKey")->item(0)->nodeValue); + $this->assertSame(strval(count($folders)), $xpath->query("//ns:FolderSync/ns:Changes/ns:Count")->item(0)->nodeValue); + + foreach ($folders as $idx => $folder) { + $displayName = $xpath->query("//ns:FolderSync/ns:Changes/ns:Add/ns:DisplayName")->item($idx)->nodeValue; + if (str_starts_with($folder0, '/')) { + $this->assertMatchesRegularExpression($folder0, $displayName); + } else { + $this->assertSame($folder0, $displayName); + } + $this->assertSame((string) $folder1, $xpath->query("//ns:FolderSync/ns:Changes/ns:Add/ns:Type")->item($idx)->nodeValue); + $this->assertSame('0', $xpath->query("//ns:FolderSync/ns:Changes/ns:Add/ns:ParentId")->item($idx)->nodeValue); + $idx++; + } + + // After we switched to multi-folder supported mode we expect next FolderSync + // to delete the old "collective" folders + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <FolderSync xmlns="uri:FolderHierarchy"> + <SyncKey>1</SyncKey> + </FolderSync> + EOF; + + $response = $this->request($request, 'FolderSync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $deleted = $this->isStorageDriver('kolab4') ? 3 : 4; // No Notes folder in Kolab4 + $syncKey = 2; + + $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue); + $this->assertSame(strval($syncKey), $xpath->query("//ns:FolderSync/ns:SyncKey")->item(0)->nodeValue); + $this->assertSame(strval($deleted), $xpath->query("//ns:FolderSync/ns:Changes/ns:Count")->item(0)->nodeValue); + $this->assertSame($deleted, $xpath->query("//ns:FolderSync/ns:Changes/ns:Delete")->length); + + return $syncKey; + } + + /** + * Test FolderCreate command + * + * @depends testFolderSync + */ + public function testFolderCreate($syncKey) + { + // Multi-folder mode + self::$deviceType = 'iphone'; + + // Create a mail folder + $folderName1 = 'Test Folder'; + $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_MAIL_USER_CREATED; + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <FolderCreate xmlns="uri:FolderHierarchy"> + <SyncKey>{$syncKey}</SyncKey> + <ParentId>0</ParentId> + <DisplayName>{$folderName1}</DisplayName> + <Type>{$folderType}</Type> + </FolderCreate> + EOF; + + $response = $this->request($request, 'FolderCreate'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $this->assertSame('1', $xpath->query("//ns:FolderCreate/ns:Status")->item(0)->nodeValue); + $this->assertSame(strval(++$syncKey), $xpath->query("//ns:FolderCreate/ns:SyncKey")->item(0)->nodeValue); + $this->assertSame(1, $xpath->query("//ns:FolderCreate/ns:ServerId")->count()); + $folder1 = $xpath->query("//ns:FolderCreate/ns:ServerId")->item(0)->nodeValue; + + // Note: After FolderCreate there are no changes in the following FolderSync expected + + // Create a contacts folder + $folderName2 = 'Test Contacts Folder'; + $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT_USER_CREATED; + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <FolderCreate xmlns="uri:FolderHierarchy"> + <SyncKey>{$syncKey}</SyncKey> + <ParentId>0</ParentId> + <DisplayName>{$folderName2}</DisplayName> + <Type>{$folderType}</Type> + </FolderCreate> + EOF; + + $response = $this->request($request, 'FolderCreate'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $this->assertSame('1', $xpath->query("//ns:FolderCreate/ns:Status")->item(0)->nodeValue); + $this->assertSame(strval(++$syncKey), $xpath->query("//ns:FolderCreate/ns:SyncKey")->item(0)->nodeValue); + $this->assertSame(1, $xpath->query("//ns:FolderCreate/ns:ServerId")->count()); + $folder2 = $xpath->query("//ns:FolderCreate/ns:ServerId")->item(0)->nodeValue; + + // Note: After FolderCreate there are no changes in the following FolderSync expected
View file
kolab-syncroton-2.4.2.tar.gz/tests/Sync/ItemOperationsTest.php
Added
@@ -0,0 +1,81 @@ +<?php + +class ItemOperationsTest extends Tests\SyncTestCase +{ + /** + * Test ItemOperations::EmptyFolderContents request + */ + public function testEmptyFolderContents() + { + $this->registerDevice(); + + // TODO: Test invalid folder ID + $collectionId = 'AAAAAAAAAAAA'; + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <ItemOperations xmlns="uri:ItemOperations" xmlns:AirSync="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"> + <EmptyFolderContents> + <AirSync:CollectionId>{$collectionId}</AirSync:CollectionId> + <Options><DeleteSubFolders/></Options> + </EmptyFolderContents> + </ItemOperations> + EOF; + + $response = $this->request($request, 'ItemOperations'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $this->assertSame('1', $xpath->query("//ns:ItemOperations/ns:Status")->item(0)->nodeValue); + $this->assertSame( + strval(Syncroton_Exception_Status_ItemOperations::ITEM_SERVER_ERROR), + $xpath->query("//ns:ItemOperations/ns:Response/ns:EmptyFolderContents/ns:Status")->item(0)->nodeValue + ); + $this->assertSame( + $collectionId, + $xpath->query("//ns:ItemOperations/ns:Response/ns:EmptyFolderContents/AirSync:CollectionId")->item(0)->nodeValue + ); + + // Test Trash folder + $collectionId = array_search('Trash', $this->folders); + $this->assertIsString($collectionId); + + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <ItemOperations xmlns="uri:ItemOperations" xmlns:AirSync="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"> + <EmptyFolderContents> + <AirSync:CollectionId>{$collectionId}</AirSync:CollectionId> + <Options><DeleteSubFolders/></Options> + </EmptyFolderContents> + </ItemOperations> + EOF; + + $response = $this->request($request, 'ItemOperations'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $this->assertSame('1', $xpath->query("//ns:ItemOperations/ns:Status")->item(0)->nodeValue); + $this->assertSame('1', $xpath->query("//ns:ItemOperations/ns:Response/ns:EmptyFolderContents/ns:Status")->item(0)->nodeValue); + $this->assertSame($collectionId, $xpath->query("//ns:ItemOperations/ns:Response/ns:EmptyFolderContents/AirSync:CollectionId")->item(0)->nodeValue); + + // TODO: Test DAV folder + // TODO: Test a folder with subfolders + // TODO: Test non-empty folder and assert that all objects are gone + $this->markTestIncomplete(); + } + + /** + * Test ItemOperations::Fetch request + */ + public function testFetch() + { + $this->markTestIncomplete(); + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/Sync/MeetingResponseTest.php
Added
@@ -0,0 +1,131 @@ +<?php + +namespace Tests\Sync; + +class MeetingResponseTest extends \Tests\SyncTestCase +{ + /** + * Test MeetingResponse command + */ + public function testAcceptingInvitation() + { + $this->emptyTestFolder($davFolder = 'Calendar', 'event'); + $this->emptyTestFolder('INBOX', 'mail'); + + $this->registerDevice(); + + // Do the initial INBOX sync + $folderId = '38b950ebd62cd9a66929c89615d0fc04'; // INBOX + $syncKey = 0; + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync"> + <Collections> + <Collection> + <SyncKey>{$syncKey}</SyncKey> + <CollectionId>{$folderId}</CollectionId> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $this->assertSame('1', $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:Status")->item(0)->nodeValue); + $this->assertSame(strval(++$syncKey), $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:SyncKey")->item(0)->nodeValue); + + // Append an invitation email, and sync it + $sync = \kolab_sync::get_instance(); + $replace = + '$from' => 'test.test@domain.tld', + '$to' => $sync->config->get('activesync_test_username'), + ; + $this->appendMail('INBOX', 'mail.itip1', $replace); + + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync"> + <Collections> + <Collection> + <SyncKey>{$syncKey}</SyncKey> + <CollectionId>{$folderId}</CollectionId> + <DeletesAsMoves>1</DeletesAsMoves> + <GetChanges>1</GetChanges> + <WindowSize>1</WindowSize> + <Options> + <FilterType>0</FilterType> + <Conflict>1</Conflict> + <BodyPreference xmlns="uri:AirSyncBase"> + <Type>2</Type> + <TruncationSize>51200</TruncationSize> + <AllOrNone>0</AllOrNone> + </BodyPreference> + </Options> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $root = $xpath->query("//ns:Sync/ns:Collections/ns:Collection")->item(0); + $this->assertSame('1', $xpath->query("ns:Status", $root)->item(0)->nodeValue); + $this->assertSame(strval(++$syncKey), $xpath->query("ns:SyncKey", $root)->item(0)->nodeValue); + $this->assertSame(1, $xpath->query("ns:Commands/ns:Add", $root)->count()); + + $serverId = $xpath->query("ns:Commands/ns:Add/ns:ServerId", $root)->item(0)->nodeValue; + + $root = $xpath->query("ns:Commands/ns:Add/ns:ApplicationData", $root)->item(0); + $this->assertSame('You\'ve been invited to "Test"', $xpath->query("Email:Subject", $root)->item(0)->nodeValue); + $this->assertSame('Organizer <test.test@domain.tld>', $xpath->query("Email:From", $root)->item(0)->nodeValue); + $this->assertSame($replace'$to', $xpath->query("Email:To", $root)->item(0)->nodeValue); + $this->assertSame('0', $xpath->query("Email:Read", $root)->item(0)->nodeValue); + $this->assertSame('IPM.Schedule.Meeting.Request', $xpath->query("Email:MessageClass", $root)->item(0)->nodeValue); + $this->assertSame('urn:content-classes:calendarmessage', $xpath->query("Email:ContentClass", $root)->item(0)->nodeValue); + $root = $xpath->query("Email:MeetingRequest", $root)->item(0); + $this->assertSame('0', $xpath->query("Email:AllDayEvent", $root)->item(0)->nodeValue); + $this->assertSame('2023-12-07T13:00:00.000Z', $xpath->query("Email:StartTime", $root)->item(0)->nodeValue); + $this->assertSame('2023-12-07T13:30:00.000Z', $xpath->query("Email:EndTime", $root)->item(0)->nodeValue); + $this->assertSame('test.test@domain.tld', $xpath->query("Email:Organizer", $root)->item(0)->nodeValue); + $this->assertSame('1', $xpath->query("Email:ResponseRequested", $root)->item(0)->nodeValue); + $this->assertSame('1', $xpath->query("Email:DisallowNewTimeProposal", $root)->item(0)->nodeValue); + + // Accept the invitation + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <MeetingResponse xmlns="uri:MeetingResponse" xmlns:Search="uri:Search"> + <Request> + <UserResponse>1</UserResponse> + <CollectionId>{$folderId}</CollectionId> + <RequestId>{$serverId}</RequestId> + </Request> + </MeetingResponse> + EOF; + + $response = $this->request($request, 'MeetingResponse'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + $xpath->registerNamespace('MeetingResponse', 'uri:MeetingResponse'); + + $root = $xpath->query("//MeetingResponse:MeetingResponse/MeetingResponse:Result")->item(0); + $this->assertSame('1', $xpath->query("ns:Status", $root)->item(0)->nodeValue); + $this->assertSame($serverId, $xpath->query("ns:RequestId", $root)->item(0)->nodeValue); + $this->assertStringMatchesFormat("CRC%s", $xpath->query("ns:CalendarId", $root)->item(0)->nodeValue); + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/Sync/MoveItemsTest.php
Added
@@ -0,0 +1,334 @@ +<?php + +class MoveItemsTest extends Tests\SyncTestCase +{ + /** + * Test moving an email message + */ + public function testMoveEmail() + { + $this->emptyTestFolder('INBOX', 'mail'); + $this->emptyTestFolder('Trash', 'mail'); + $uid = $this->appendMail('INBOX', 'mail.sync1'); + $this->registerDevice(); + + $inbox = array_search('INBOX', $this->folders); + $trash = array_search('Trash', $this->folders); + + // Initial sync + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync"> + <Collections> + <Collection> + <SyncKey>0</SyncKey> + <CollectionId>{$inbox}</CollectionId> + </Collection> + <Collection> + <SyncKey>0</SyncKey> + <CollectionId>{$trash}</CollectionId> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + // Sync mail from INBOX and Trash + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"> + <Collections> + <Collection> + <SyncKey>1</SyncKey> + <CollectionId>{$inbox}</CollectionId> + <GetChanges>1</GetChanges> + </Collection> + <Collection> + <SyncKey>1</SyncKey> + <CollectionId>{$trash}</CollectionId> + <GetChanges>1</GetChanges> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $this->assertSame(1, $xpath->query("//ns:Sync/ns:Collections/ns:Collection")->count()); + $root = $xpath->query("//ns:Sync/ns:Collections/ns:Collection")->item(0); + $this->assertSame(1, $xpath->query("ns:Commands/ns:Add", $root)->count()); + $root = $xpath->query("ns:Commands/ns:Add", $root)->item(0); + $this->assertSame('test sync', $xpath->query("ns:ApplicationData/Email:Subject", $root)->item(0)->nodeValue); + + // Move the message to $trash + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <MoveItems xmlns="uri:Move"> + <Move> + <SrcMsgId>{$inbox}::{$uid}</SrcMsgId> + <SrcFldId>{$inbox}</SrcFldId> + <DstFldId>{$trash}</DstFldId> + </Move> + </MoveItems> + EOF; + + $response = $this->request($request, 'MoveItems'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + $xpath->registerNamespace('Move', 'uri:Move'); + + $root = $xpath->query("//Move:MoveItems/Move:Response")->item(0); + $this->assertSame('3', $xpath->query("Move:Status", $root)->item(0)->nodeValue); + $this->assertSame("{$inbox}::{$uid}", $xpath->query("Move:SrcMsgId", $root)->item(0)->nodeValue); + $serverId = $xpath->query("Move:DstMsgId", $root)->item(0)->nodeValue; + + // Sync mail from INBOX and Trash + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"> + <Collections> + <Collection> + <SyncKey>2</SyncKey> + <CollectionId>{$inbox}</CollectionId> + <GetChanges>1</GetChanges> + </Collection> + <Collection> + <SyncKey>1</SyncKey> + <CollectionId>{$trash}</CollectionId> + <GetChanges>1</GetChanges> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $root = $xpath->query("//ns:Sync/ns:Collections/ns:Collection")->item(0); // INBOX + $this->assertSame($inbox, $xpath->query("ns:CollectionId", $root)->item(0)->nodeValue); + $this->assertSame(1, $xpath->query("ns:Commands/ns:Delete", $root)->count()); + $this->assertSame("$inbox::$uid", $xpath->query("ns:Commands/ns:Delete/ns:ServerId", $root)->item(0)->nodeValue); + + $root = $xpath->query("//ns:Sync/ns:Collections/ns:Collection")->item(1); // Trash + $this->assertSame($trash, $xpath->query("ns:CollectionId", $root)->item(0)->nodeValue); + $this->assertSame(1, $xpath->query("ns:Commands/ns:Add", $root)->count()); + $this->assertSame('test sync', $xpath->query("ns:Commands/ns:Add/ns:ApplicationData/Email:Subject", $root)->item(0)->nodeValue); + } + + /** + * Test moving a contact + */ + public function testMoveContact() + { + // Test with multi-folder support enabled + self::$deviceType = 'iphone'; + + $davFolder = $this->isStorageDriver('kolab') ? 'Contacts' : 'Addressbook'; + $this->emptyTestFolder($davFolder, 'contact'); + $this->deleteTestFolder($folderName = 'Test Contacts Folder', 'contact'); + $this->appendObject($davFolder, 'contact.vcard1', 'contact'); + + $this->registerDevice(); + + $srcFolderId = array_search($davFolder, $this->folders); + + // Create a contacts folder + $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT_USER_CREATED; + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <FolderCreate xmlns="uri:FolderHierarchy"> + <SyncKey>1</SyncKey> + <ParentId>0</ParentId> + <DisplayName>{$folderName}</DisplayName> + <Type>{$folderType}</Type> + </FolderCreate> + EOF; + + $response = $this->request($request, 'FolderCreate'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $dstFolderId = $xpath->query("//ns:FolderCreate/ns:ServerId")->item(0)->nodeValue; + + // Sync both folders + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"> + <Collections> + <Collection> + <Class>Contacts</Class> + <SyncKey>0</SyncKey> + <CollectionId>{$srcFolderId}</CollectionId> + </Collection> + <Collection> + <Class>Contacts</Class> + <SyncKey>0</SyncKey> + <CollectionId>{$dstFolderId}</CollectionId> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); +
View file
kolab-syncroton-2.4.2.tar.gz/tests/Sync/OptionsTest.php
Added
@@ -0,0 +1,16 @@ +<?php + +class OptionsTest extends Tests\SyncTestCase +{ + /** + * Test Options command/request + */ + public function testOptions() + { + $response = self::$client->request('OPTIONS', ''); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertStringContainsString('14', $response->getHeader('MS-Server-ActiveSync')0); + $this->assertStringContainsString('14.1', $response->getHeader('MS-ASProtocolVersions')0); + $this->assertStringContainsString('FolderSync', $response->getHeader('MS-ASProtocolCommands')0); + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/Sync/ProvisionTest.php
Added
@@ -0,0 +1,45 @@ +<?php + +class ProvisionTest extends Tests\SyncTestCase +{ + /** + * Test Provision command + */ + public function testProvision() + { + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Provision xmlns="uri:Provision" xmlns:Settings="uri:Settings"> + <DeviceInformation xmlns="uri:Settings"> + <Set> + <Model>moto e(6) plus</Model> + <IMEI>000000000000000</IMEI> + <FriendlyName>pokerp_reteu_64</FriendlyName> + <OS>Android 9.58-8</OS> + <OSLanguage>Polish (Poland)</OSLanguage> + <MobileOperator/> + </Set> + </DeviceInformation> + <Policies> + <Policy> + <PolicyType>MS-EAS-Provisioning-WBXML</PolicyType> + </Policy> + </Policies> + </Provision> + EOF; + + $response = $this->request($request, 'Provision'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $this->assertSame('1', $xpath->query("//ns:Provision/ns:Status")->item(0)->nodeValue); + $this->assertSame('1', $xpath->query("//ns:Provision/Settings:DeviceInformation/Settings:Status")->item(0)->nodeValue); + $this->assertSame('2', $xpath->query("//ns:Provision/ns:Policies/ns:Policy/ns:Status")->item(0)->nodeValue); + + // TODO: Assert the properties have been set + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/Sync/SettingsTest.php
Added
@@ -0,0 +1,80 @@ +<?php + +class SettingsTest extends Tests\SyncTestCase +{ + /** + * Test Settings command + */ + public function testSettingsUserInformation() + { + // Test retrieving the settings + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Settings xmlns="uri:Settings"> + <UserInformation> + <Get/> + </UserInformation> + </Settings> + EOF; + + $response = $this->request($request, 'Settings'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = self::fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $this->assertSame('1', $xpath->query("//ns:Settings/ns:Status")->item(0)->nodeValue); + $this->assertSame('1', $xpath->query("//ns:Settings/ns:UserInformation/ns:Status")->item(0)->nodeValue); + $this->assertSame( + self::$username, + $xpath->query("//ns:Settings/ns:UserInformation/ns:Get/ns:Accounts/ns:Account/ns:EmailAddresses/ns:PrimarySmtpAddress")->item(0)->nodeValue + ); + } + + /** + * Test Settings command + */ + public function testSettingsDeviceInfomation() + { + // Test device info update + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Settings xmlns="uri:Settings"> + <DeviceInformation> + <Set> + <Model>moto plus</Model> + <IMEI>111111111</IMEI> + <FriendlyName>fn</FriendlyName> + <OS>Android 10</OS> + <OSLanguage>English</OSLanguage> + <MobileOperator/> + </Set> + </DeviceInformation> + </Settings> + EOF; + + $response = $this->request($request, 'Settings'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $this->assertSame('1', $xpath->query("//ns:Settings/ns:Status")->item(0)->nodeValue); + $this->assertSame('1', $xpath->query("//ns:Settings/ns:DeviceInformation/ns:Set/ns:Status")->item(0)->nodeValue); + + // TODO: Assert the properties have been set + } + + /** + * Test Settings command regarding OOF + */ + public function testSettingsOOF() + { + // TODO: Test OOF settings + $this->markTestIncomplete(); + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/Sync/Sync
Added
+(directory)
View file
kolab-syncroton-2.4.2.tar.gz/tests/Sync/Sync/CalendarTest.php
Added
@@ -0,0 +1,75 @@ +<?php + +namespace Tests\Sync\Sync; + +class CalendarTest extends \Tests\SyncTestCase +{ + /** + * Test Sync command + */ + public function testSync() + { + $this->emptyTestFolder($davFolder = 'Calendar', 'event'); + $this->registerDevice(); + + // Test empty folder + $folderId = 'Calendar::Syncroton'; + $syncKey = 0; + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"> + <Collections> + <Collection> + <Class>Calendar</Class> + <SyncKey>{$syncKey}</SyncKey> + <CollectionId>{$folderId}</CollectionId> + <DeletesAsMoves/> + <GetChanges/> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $root = "//ns:Sync/ns:Collections/ns:Collection"; + $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue); + $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue); + $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue); + $this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Add")->count()); + + // Append two event objects and sync them + $this->appendObject($davFolder, 'event.ics1', 'event'); + $this->appendObject($davFolder, 'event.ics2', 'event'); + + $request = str_replace("<SyncKey>0</SyncKey>", "<SyncKey>{$syncKey}</SyncKey>", $request); + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $root = "//ns:Sync/ns:Collections/ns:Collection"; + $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue); + $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue); + $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue); + $this->assertSame(2, $xpath->query("{$root}/ns:Commands/ns:Add")->count()); + + $root .= "/ns:Commands/ns:Add"; + $this->assertStringMatchesFormat("CRC%s", $xpath->query("{$root}/ns:ServerId")->item(0)->nodeValue); + $this->assertSame('20240715T170000Z', $xpath->query("{$root}/ns:ApplicationData/Calendar:StartTime")->item(0)->nodeValue); + $this->assertSame('Meeting', $xpath->query("{$root}/ns:ApplicationData/Calendar:Subject")->item(0)->nodeValue); + $this->assertSame('20240714T170000Z', $xpath->query("{$root}/ns:ApplicationData/Calendar:StartTime")->item(1)->nodeValue); + $this->assertSame('Party', $xpath->query("{$root}/ns:ApplicationData/Calendar:Subject")->item(1)->nodeValue); + + return $syncKey; + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/Sync/Sync/ContactsTest.php
Added
@@ -0,0 +1,250 @@ +<?php + +namespace Tests\Sync\Sync; + +class ContactsTest extends \Tests\SyncTestCase +{ + /** + * Test Sync command + */ + public function testSync() + { + $davFolder = $this->isStorageDriver('kolab') ? 'Contacts' : 'Addressbook'; + $this->emptyTestFolder($davFolder, 'contact'); + $this->deleteTestFolder('Test Contacts Folder', 'contact'); // from other test files + $this->registerDevice(); + + // Test empty contacts folder + $folderId = 'Contacts::Syncroton'; + $syncKey = 0; + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"> + <Collections> + <Collection> + <Class>Contacts</Class> + <SyncKey>{$syncKey}</SyncKey> + <CollectionId>{$folderId}</CollectionId> + <DeletesAsMoves/> + <GetChanges/> + <Options> + <AirSyncBase:BodyPreference> + <AirSyncBase:Type>1</AirSyncBase:Type> + <AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize> + </AirSyncBase:BodyPreference> + <Conflict>1</Conflict> + </Options> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $root = "//ns:Sync/ns:Collections/ns:Collection"; + $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue); + $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue); + $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue); + $this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Add")->count()); + + // Append two contact objects and sync them + // TODO: Test a folder with contact groups inside + $this->appendObject($davFolder, 'contact.vcard1', 'contact'); + $this->appendObject($davFolder, 'contact.vcard2', 'contact'); + + $request = str_replace("<SyncKey>0</SyncKey>", "<SyncKey>{$syncKey}</SyncKey>", $request); + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $root = "//ns:Sync/ns:Collections/ns:Collection"; + $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue); + $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue); + $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue); + $this->assertSame(2, $xpath->query("{$root}/ns:Commands/ns:Add")->count()); + + $root .= "/ns:Commands/ns:Add"; + $this->assertStringMatchesFormat("CRC%s", $xpath->query("{$root}/ns:ServerId")->item(0)->nodeValue); + $this->assertSame('Jack', $xpath->query("{$root}/ns:ApplicationData/Contacts:FirstName")->item(0)->nodeValue); + $this->assertSame('Strong', $xpath->query("{$root}/ns:ApplicationData/Contacts:LastName")->item(0)->nodeValue); + $this->assertSame('Jane', $xpath->query("{$root}/ns:ApplicationData/Contacts:FirstName")->item(1)->nodeValue); + $this->assertSame('Doe', $xpath->query("{$root}/ns:ApplicationData/Contacts:LastName")->item(1)->nodeValue); + + return $syncKey; + } + + /** + * Test adding objects from client + * + * @depends testSync + */ + public function testAddFromClient($syncKey) + { + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase" xmlns:Contacts="uri:Contacts"> + <Collections> + <Collection> + <Class>Contacts</Class> + <SyncKey>{$syncKey}</SyncKey> + <CollectionId>Contacts::Syncroton</CollectionId> + <DeletesAsMoves/> + <GetChanges/> + <Options> + <AirSyncBase:BodyPreference> + <AirSyncBase:Type>1</AirSyncBase:Type> + <AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize> + </AirSyncBase:BodyPreference> + <Conflict>1</Conflict> + </Options> + <Commands> + <Add> + <ClientId>42</ClientId> + <ApplicationData> + <Contacts:FirstName>Lars</Contacts:FirstName> + </ApplicationData> + </Add> + </Commands> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $root = $xpath->query("//ns:Sync/ns:Collections/ns:Collection")->item(0); + $this->assertSame('1', $xpath->query("ns:Status", $root)->item(0)->nodeValue); + $this->assertSame(strval(++$syncKey), $xpath->query("ns:SyncKey", $root)->item(0)->nodeValue); + $root = $xpath->query("ns:Responses/ns:Add", $root)->item(0); + $this->assertSame('1', $xpath->query("ns:Status", $root)->item(0)->nodeValue); + $this->assertSame('42', $xpath->query("ns:ClientId", $root)->item(0)->nodeValue); + $serverId = $xpath->query("ns:ServerId", $root)->item(0)->nodeValue; + $this->assertStringMatchesFormat("CRC%s", $serverId); + + // TODO: Test the content on the server + + return $syncKey, $serverId; + } + + /** + * Test updating objects from client + * + * @depends testAddFromClient + */ + public function testChangeFromClient($params) + { + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase" xmlns:Contacts="uri:Contacts"> + <Collections> + <Collection> + <Class>Contacts</Class> + <SyncKey>{$params0}</SyncKey> + <CollectionId>Contacts::Syncroton</CollectionId> + <DeletesAsMoves/> + <GetChanges/> + <Options> + <AirSyncBase:BodyPreference> + <AirSyncBase:Type>1</AirSyncBase:Type> + <AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize> + </AirSyncBase:BodyPreference> + <Conflict>1</Conflict> + </Options> + <Commands> + <Change> + <ServerId>{$params1}</ServerId> + <ApplicationData> + <Contacts:FirstName>First</Contacts:FirstName> + <Contacts:LastName>Last</Contacts:LastName> + </ApplicationData> + </Change> + </Commands> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $root = $xpath->query("//ns:Sync/ns:Collections/ns:Collection")->item(0); + $this->assertSame('1', $xpath->query("ns:Status", $root)->item(0)->nodeValue); + $this->assertSame(strval(++$params0), $xpath->query("ns:SyncKey", $root)->item(0)->nodeValue); + $this->assertSame(0, $xpath->query("ns:Responses", $root)->length); + + // TODO: Assert updated content on the server + + return $params; + }
View file
kolab-syncroton-2.4.2.tar.gz/tests/Sync/Sync/EmailTest.php
Added
@@ -0,0 +1,179 @@ +<?php + +namespace Tests\Sync\Sync; + +class EmailTest extends \Tests\SyncTestCase +{ + /** + * Test Sync command + */ + public function testSync() + { + $this->emptyTestFolder('INBOX', 'mail'); + $this->registerDevice(); + + // Test invalid collection identifier + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync"> + <Collections> + <Collection> + <SyncKey>0</SyncKey> + <CollectionId>1111111111</CollectionId> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $this->assertSame('12', $xpath->query("//ns:Sync/ns:Status")->item(0)->nodeValue); + + // Test INBOX + $folderId = '38b950ebd62cd9a66929c89615d0fc04'; + $syncKey = 0; + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync"> + <Collections> + <Collection> + <SyncKey>{$syncKey}</SyncKey> + <CollectionId>{$folderId}</CollectionId> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $this->assertSame('1', $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:Status")->item(0)->nodeValue); + $this->assertSame(strval(++$syncKey), $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:SyncKey")->item(0)->nodeValue); + $this->assertSame('Email', $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:Class")->item(0)->nodeValue); + $this->assertSame($folderId, $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:CollectionId")->item(0)->nodeValue); + + // Test listing mail in INBOX, use WindowSize=1 + // Append two mail messages + $this->appendMail('INBOX', 'mail.sync1'); + $this->appendMail('INBOX', 'mail.sync2'); + + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"> + <Collections> + <Collection> + <SyncKey>{$syncKey}</SyncKey> + <CollectionId>{$folderId}</CollectionId> + <DeletesAsMoves>1</DeletesAsMoves> + <GetChanges>1</GetChanges> + <WindowSize>1</WindowSize> + <Options> + <FilterType>0</FilterType> + <Conflict>1</Conflict> + <BodyPreference xmlns="uri:AirSyncBase"> + <Type>2</Type> + <TruncationSize>51200</TruncationSize> + <AllOrNone>0</AllOrNone> + </BodyPreference> + </Options> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $root = "//ns:Sync/ns:Collections/ns:Collection"; + $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue); + $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue); + $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue); + $this->assertSame(1, $xpath->query("{$root}/ns:Commands/ns:Add")->count()); + + // Note: We assume messages are in IMAP default order, it may change in future + $root .= "/ns:Commands/ns:Add"; + $this->assertStringMatchesFormat("{$folderId}::%d", $xpath->query("{$root}/ns:ServerId")->item(0)->nodeValue); + $this->assertSame('test sync', $xpath->query("{$root}/ns:ApplicationData/Email:Subject")->item(0)->nodeValue); + + // List the rest of the mail + $request = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"> + <Collections> + <Collection> + <SyncKey>{$syncKey}</SyncKey> + <CollectionId>{$folderId}</CollectionId> + <DeletesAsMoves>1</DeletesAsMoves> + <GetChanges>1</GetChanges> + <Options> + <FilterType>0</FilterType> + <Conflict>1</Conflict> + <BodyPreference xmlns="uri:AirSyncBase"> + <Type>2</Type> + <TruncationSize>51200</TruncationSize> + <AllOrNone>0</AllOrNone> + </BodyPreference> + </Options> + </Collection> + </Collections> + </Sync> + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + $root = "//ns:Sync/ns:Collections/ns:Collection"; + $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue); + $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue); + $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue); + $this->assertSame(1, $xpath->query("{$root}/ns:Commands/ns:Add")->count()); + + // Note: We assume messages are in IMAP default order, it may change in future + $root .= "/ns:Commands/ns:Add"; + $this->assertStringMatchesFormat("{$folderId}::%d", $xpath->query("{$root}/ns:ServerId")->item(0)->nodeValue); + $this->assertSame('sync test with attachment', $xpath->query("{$root}/ns:ApplicationData/Email:Subject")->item(0)->nodeValue); + + return $syncKey; + } + + /** + * Test updating message properties from client + * + * @depends testSync + */ + public function testChangeFromClient($syncKey) + { + $this->markTestIncomplete(); + } + + /** + * Test deleting messages from client + * + * @depends testChangeFromClient + */ + public function testDeleteFromClient($syncKey) + { + $this->markTestIncomplete(); + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/SyncTestCase.php
Added
@@ -0,0 +1,362 @@ +<?php + +namespace Tests; + +class SyncTestCase extends \PHPUnit\Framework\TestCase +{ + protected static ?\GuzzleHttp\Client $client; + protected static ?string $deviceId; + protected static ?string $deviceType; + protected static ?string $username; + protected static ?string $password; + protected static bool $authenticated = false; + + protected array $folders = ; + + /** + * {@inheritDoc} + */ + public function setUp(): void + { + if (empty(self::$username)) { + $this->markTestSkipped('Not setup'); + } + + self::$deviceType = null; + } + + /** + * {@inheritDoc} + */ + public static function setUpBeforeClass(): void + { + $sync = \kolab_sync::get_instance(); + $config = $sync->config; + $db = $sync->get_dbh(); + + self::$username = $config->get('activesync_test_username'); + self::$password = $config->get('activesync_test_password'); + + if (empty(self::$username)) { + return; + } + + self::$deviceId = 'test' . time(); + + $db->query('DELETE FROM syncroton_device'); + $db->query('DELETE FROM syncroton_synckey'); + $db->query('DELETE FROM syncroton_folder'); + $db->query('DELETE FROM syncroton_data'); + $db->query('DELETE FROM syncroton_data_folder'); + $db->query('DELETE FROM syncroton_modseq'); + $db->query('DELETE FROM syncroton_content'); + + self::$client = new \GuzzleHttp\Client( + 'http_errors' => false, + 'base_uri' => 'http://localhost:8000', + 'verify' => false, + 'auth' => self::$username, self::$password, + 'connect_timeout' => 10, + 'timeout' => 10, + 'headers' => + 'Content-Type' => 'application/xml; charset=utf-8', + 'Depth' => '1', + , + ); + + // TODO: execute: php -S localhost:8000 + } + + /** + * {@inheritDoc} + */ + public static function tearDownAfterClass(): void + { + if (self::$deviceId) { + $sync = \kolab_sync::get_instance(); + + if (self::$authenticated || $sync->authenticate(self::$username, self::$password)) { + $sync->password = self::$password; + + $storage = $sync->storage(); + $storage->device_delete(self::$deviceId); + } + + $db = $sync->get_dbh(); + $db->query('DELETE FROM syncroton_device'); + $db->query('DELETE FROM syncroton_synckey'); + $db->query('DELETE FROM syncroton_folder'); + } + } + + /** + * Append an email message to the IMAP folder + */ + protected function appendMail($folder, $filename, $replace = ) + { + $imap = $this->getImapStorage(); + + $source = __DIR__ . '/src/' . $filename; + + if (!file_exists($source)) { + exit("File does not exist: {$source}"); + } + + $is_file = true; + + if (!empty($replace)) { + $is_file = false; + $source = file_get_contents($source); + foreach ($replace as $token => $value) { + $source = str_replace($token, $value, $source); + } + } + + $uid = $imap->save_message($folder, $source, '', $is_file); + + if ($uid === false) { + exit("Failed to append mail into {$folder}"); + } + + return $uid; + } + + /** + * Append an DAV object to a DAV/IMAP folder + */ + protected function appendObject($foldername, $filename, $type) + { + $path = __DIR__ . '/src/' . $filename; + + if (!file_exists($path)) { + exit("File does not exist: {$path}"); + } + + $content = file_get_contents($path); + $uid = preg_match('/UID:(?:urn:uuid:)?(a-z0-9-+)/', $content, $m) ? $m1 : null; + + if (empty($uid)) { + exit("Filed to find UID in {$path}"); + } + + if ($this->isStorageDriver('kolab')) { + $imap = $this->getImapStorage(); + if ($imap->folder_exists($foldername)) { + // TODO + exit("Not implemented for Kolab v3 storage driver"); + } + + return; + } + + $dav = $this->getDavStorage(); + + foreach ($dav->get_folders($type) as $folder) { + if ($folder->get_name() === $foldername) { + $dav_type = $folder->get_dav_type(); + $location = $folder->object_location($uid); + + if ($folder->dav->create($location, $content, $dav_type) !== false) { + return; + } + } + } + + exit("Failed to append object into {$foldername}"); + } + + /** + * Delete a folder + */ + protected function deleteTestFolder($name, $type) + { + // Deleting IMAP folders + if ($type == 'mail' || $this->isStorageDriver('kolab')) { + $imap = $this->getImapStorage(); + if ($imap->folder_exists($name)) { + $imap->delete_folder($name); + } + + return; + } + + // Deleting DAV folders + $dav = $this->getDavStorage(); + + foreach ($dav->get_folders($type) as $folder) { + if ($folder->get_name() === $name) { + $dav->folder_delete($folder->id, $type); + } + } + } + + /** + * Remove all objects from a folder + */ + protected function emptyTestFolder($name, $type) + { + // Deleting in IMAP folders + if ($type == 'mail' || $this->isStorageDriver('kolab')) {
View file
kolab-syncroton-2.4.2.tar.gz/tests/Unit
Added
+(directory)
View file
kolab-syncroton-2.4.2.tar.gz/tests/Unit/BodyConverterTest.php
Added
@@ -0,0 +1,41 @@ +<?php + +class BodyConverterTest extends PHPUnit\Framework\TestCase +{ + public function data_html_to_text() + { + return + '', '', + '<div></div>', '', + '<div>a</div>', 'a', + '<html><head><title>title</title></head></html>', '', + ; + } + + /** + * @dataProvider data_html_to_text + */ + public function test_html_to_text($html, $text) + { + $converter = new kolab_sync_body_converter($html, Syncroton_Model_EmailBody::TYPE_HTML); + $output = $converter->convert(Syncroton_Model_EmailBody::TYPE_PLAINTEXT); + + $this->assertEquals(trim($text), trim($output)); + } + + /** + * Test RTF convertion to HTML and Plain text + */ + public function test_rtf_to_text() + { + $rtf = file_get_contents(__DIR__ . '/../src/sample.rtf'); + + $converter = new kolab_sync_body_converter($rtf, Syncroton_Model_EmailBody::TYPE_RTF); + + $output = $converter->convert(Syncroton_Model_EmailBody::TYPE_PLAINTEXT); + $this->assertStringContainsString('This is text', trim($output)); + + $output = $converter->convert(Syncroton_Model_EmailBody::TYPE_HTML); + $this->assertStringContainsString('<span style="font-family:Helvetica,sans-serif;color:#0000ff;">anchor</span>', trim($output)); + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/Unit/DataCalendarTest.php
Added
@@ -0,0 +1,126 @@ +<?php + +class DataCalendarTest extends PHPUnit\Framework\TestCase +{ + /** + * Test for kolab_sync_data_calendar::from_kolab_alarm() + */ + public function test_from_kolab_alarm() + { + $obj = new kolab_sync_data_calendar_test(); + + $result = $obj->from_kolab_alarm(); + $this->assertSame(null, $result); + + $event = 'valarms' => + 'action' => 'DISPLAY', + 'trigger' => 'PT5M', + ; + $result = $obj->from_kolab_alarm($event); + $this->assertSame(null, $result); + + $event = 'valarms' => + 'action' => 'DISPLAY', + 'trigger' => '-PT5M', + ; + $result = $obj->from_kolab_alarm($event); + $this->assertSame(5, $result); + + $event = 'valarms' => + 'action' => 'DISPLAY', + 'trigger' => 'PT0M', + ; + $result = $obj->from_kolab_alarm($event); + $this->assertSame(0, $result); + + $event = 'valarms' => + 'action' => 'DISPLAY', + 'trigger' => '-PT0M', + ; + $result = $obj->from_kolab_alarm($event); + $this->assertSame(0, $result); + + $event = 'valarms' => + 'action' => 'DISPLAY', + 'trigger' => 'PT0S', + ; + $result = $obj->from_kolab_alarm($event); + $this->assertSame(0, $result); + + // alarms on specified DateTime (T2420) + + $event = + // no start datetime defined + 'valarms' => + + 'action' => 'DISPLAY', + 'trigger' => new DateTime('now + 1 hour'), + , + , + ; + $result = $obj->from_kolab_alarm($event); + $this->assertSame(null, $result); + + $event = + 'start' => new DateTime('now + 10 minutes'), + 'valarms' => + + 'action' => 'DISPLAY', + 'trigger' => new DateTime('now + 1 hour'), + , + , + ; + $result = $obj->from_kolab_alarm($event); + $this->assertSame(null, $result); + + $event = + 'start' => new DateTime('now + 60 minutes'), + 'valarms' => + + 'action' => 'DISPLAY', + 'trigger' => new DateTime('now + 50 minutes'), + , + , + ; + $result = $obj->from_kolab_alarm($event); + $this->assertSame(10, $result); + } + + /** + * Test for kolab_sync_data_calendar::to_kolab_alarm() + */ + public function test_to_kolab_alarm() + { + $obj = new kolab_sync_data_calendar_test(); + + $result = $obj->to_kolab_alarm(null, ); + $this->assertSame(, $result); + + $result = $obj->to_kolab_alarm(0, ); + $this->assertSame('-PT0M', $result0'trigger'); + + $result = $obj->to_kolab_alarm(15, ); + $this->assertSame('-PT15M', $result0'trigger'); + $this->assertSame('DISPLAY', $result0'action'); + } +} + +/** + * kolab_sync_data_calendar wrapper, so we can test protected methods too + */ +class kolab_sync_data_calendar_test extends kolab_sync_data_calendar +{ + public function __construct() + { + } + + public function from_kolab_alarm($value) + { + return parent::from_kolab_alarm($value); + } + + public function to_kolab_alarm($value, $event) + { + return parent::to_kolab_alarm($value, $event); + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/Unit/DataEmailTest.php
Added
@@ -0,0 +1,37 @@ +<?php + +class DataEmailTest extends PHPUnit\Framework\TestCase +{ + /** + * Test GlobalObjId encoding/decoding + */ + public function test_globalobjid() + { + // https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-asemail/e7424ddc-dd10-431e-a0b7-5c794863370e + $input = 'BAAAAIIA4AB0xbcQGoLgCAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAAHZDYWwtVWlkAQAAAHs4MTQxMkQzQy0yQTI0LTRFOUQtQjIwRS0xMUY3QkJFOTI3OTl9AA=='; + $output = kolab_sync_data_email::decodeGlobalObjId($input); + + $this->assertSame(51, $output'bytecount'); + $this->assertSame('{81412D3C-2A24-4E9D-B20E-11F7BBE92799}', $output'uid'); + + $encoded = kolab_sync_data_email::encodeGlobalObjId($output); + $this->assertSame($encoded, $input); + + $input = 'BAAAAIIA4AB0xbcQGoLgCAfUCRDgQMnBJoXEAQAAAAAAAAAAEAAAAAvw7UtuTulOnjnjhns3jvM='; + $output = kolab_sync_data_email::decodeGlobalObjId($input); + + $this->assertSame(16, $output'bytecount'); + $this->assertSame(2004, $output'year'); + $this->assertSame(9, $output'month'); + $this->assertSame(16, $output'day'); + $this->assertSame(127373090979660000, $output'now'); + + // This is how the "now" value is interpreted + // $winSecs = (int)($output'now' / 10000000); // convert microseconds to seconds + // $unixTimestamp = ($winSecs - 11644473600); // subtract 1.1.1600 - 1.1.1970 difference in seconds + // print(date(DateTime::RFC822, $unixTimestamp)); + + $encoded = kolab_sync_data_email::encodeGlobalObjId($output); + $this->assertSame($encoded, $input); + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/Unit/DataTasksTest.php
Added
@@ -0,0 +1,78 @@ +<?php + +class DataTasksTest extends PHPUnit\Framework\TestCase +{ + public function data_prio() + { + return + 0, null, + 1, 2, + 2, 2, + 3, 2, + 4, 2, + 5, 1, + 6, 0, + 7, 0, + 8, 0, + 9, 0, + // invalid input + 10, null, + ; + } + + public function data_importance() + { + return + 0, 9, + 1, 5, + 2, 1, + // invalid input + null, null, + 5, null, + ; + } + + /** + * Test for kolab_sync_data_tasks::prio_to_importance() + * @dataProvider data_prio() + */ + public function test_prio_to_importance($input, $output) + { + $data = new kolab_sync_data_tasks_test(); + $result = $data->prio_to_importance($input); + + $this->assertEquals($output, $result); + } + + /** + * Test for kolab_sync_data_tasks::importance_to_prio() + * @dataProvider data_importance() + */ + public function test_importance_to_prio($input, $output) + { + $data = new kolab_sync_data_tasks_test(); + $result = $data->importance_to_prio($input); + + $this->assertEquals($output, $result); + } +} + +/** + * kolab_sync_data_tasks wrapper, so we can test preotected methods too + */ +class kolab_sync_data_tasks_test extends kolab_sync_data_tasks +{ + public function __construct() + { + } + + public function prio_to_importance($value) + { + return parent::prio_to_importance($value); + } + + public function importance_to_prio($value) + { + return parent::importance_to_prio($value); + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/Unit/DataTest.php
Added
@@ -0,0 +1,152 @@ +<?php + +class DataTest extends PHPUnit\Framework\TestCase +{ + /** + * Test for kolab_sync_data::recurrence_to_kolab() + */ + public function test_recurrence_to_kolab() + { + $xml = '<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase" xmlns:Calendar="uri:Calendar"> + <ApplicationData> + <Calendar:Recurrence> + <Calendar:Type>0</Calendar:Type> + <Calendar:Interval>1</Calendar:Interval> + <Calendar:Until>20101128T225959Z</Calendar:Until> + </Calendar:Recurrence> + </ApplicationData> + </Sync>'; + + $xml = new SimpleXMLElement($xml); + $event = new Syncroton_Model_Event($xml->ApplicationData); + $data = new kolab_sync_data_test(); + + $result = $data->recurrence_to_kolab($event); + + $this->assertEquals('DAILY', $result'FREQ'); + $this->assertEquals(1, $result'INTERVAL'); + $this->assertEquals('20101128T225959Z', $result'UNTIL'->format("Ymd\THis\Z")); + + $xml = '<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase" xmlns:Calendar="uri:Calendar"> + <ApplicationData> + <Calendar:Recurrence> + <Calendar:Type>1</Calendar:Type> + <Calendar:Interval>1</Calendar:Interval> + <Calendar:DayOfWeek>8</Calendar:DayOfWeek> + </Calendar:Recurrence> + </ApplicationData> + </Sync>'; + + $xml = new SimpleXMLElement($xml); + $event = new Syncroton_Model_Event($xml->ApplicationData); + + $result = $data->recurrence_to_kolab($event, null); + + $this->assertEquals('WEEKLY', $result'FREQ'); + $this->assertEquals(1, $result'INTERVAL'); + $this->assertEquals('WE', $result'BYDAY'); + } + + /** + * Test for kolab_sync_data::recurrence_from_kolab() + */ + public function test_recurrence_from_kolab() + { + $event = + 'uid' => '52A09F6151F020312D99779F86838CF5-93BC4FC398A3FD52', + '_type' => 'event', + 'priority' => 0, + 'attendees' => + + 'rsvp' => false, + 'email' => 'bartek.machniak@nestle.kolab.ch', + 'role' => 'ORGANIZER', + 'status' => 'ACCEPTED', + , + + 'name' => 'Machniak, Aleksander', + 'status' => 'ACCEPTED', + 'cutype' => 'INDIVIDUAL', + 'rsvp' => false, + 'email' => 'aleksander.machniak@nestle.kolab.ch', + , + , + 'created' => new DateTime('2023-10-20 09:49:26.000000'), + 'changed' => new DateTime('2023-10-20 09:49:34.000000'), + 'description' => 'description', + 'end' => new DateTime('2023-10-20 14:30:00.000000'), + 'start' => new DateTime('2023-10-20 14:00:00.000000'), + 'location' => '', + 'organizer' => + 'rsvp' => false, + 'email' => 'bartek.machniak@nestle.kolab.ch', + 'role' => 'ORGANIZER', + 'status' => 'ACCEPTED', + , + 'sequence' => 0, + 'status' => 'CONFIRMED', + 'free_busy' => 'busy', + 'allday' => false, + 'recurrence' => + 'FREQ' => 'WEEKLY', + 'INTERVAL' => '1', + , + ; + + $data = new kolab_sync_data_test(); + + $data->recurrence_from_kolab(null, $event, $result); + + $this->assertEquals($data::RECUR_TYPE_WEEKLY, $result'recurrence'->type); + $this->assertEquals($data::RECUR_DOW_FRIDAY, $result'recurrence'->dayOfWeek); + $this->assertEquals(1, $result'recurrence'->interval); + + $event'recurrence' = + 'FREQ' => 'MONTHLY', + 'BYMONTHDAY' => '2,15', + 'INTERVAL' => '5', + 'COUNT' => 3, + ; + + $data->recurrence_from_kolab(null, $event, $result); + + $this->assertEquals($data::RECUR_TYPE_MONTHLY, $result'recurrence'->type); + $this->assertEquals(2, $result'recurrence'->dayOfMonth); + $this->assertEquals(5, $result'recurrence'->interval); + $this->assertEquals(3, $result'recurrence'->occurrences); + + // TODO: More cases + } +} + +/** + * kolab_sync_data wrapper, so we can test preotected methods too + */ +class kolab_sync_data_test extends kolab_sync_data +{ + public function __construct() + { + } + + public function recurrence_to_kolab($data, $dummy1 = null, $dummy2 = null) + { + return parent::recurrence_to_kolab($data, null); + } + + public function recurrence_from_kolab($collection, $data, &$result, $type = 'Event') + { + return parent::recurrence_from_kolab($collection, $data, $result, $type); + } + + public function toKolab($data, $folderId, $entry = null, $timezone = null) + { + return ; + } + + public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId, $as_array = false) + { + throw new Syncroton_Exception_NotFound("Not implemented"); + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/Unit/MessageTest.php
Added
@@ -0,0 +1,146 @@ +<?php + +class MessageTest extends PHPUnit\Framework\TestCase +{ + /** + * Test message parsing and headers setting + */ + public function test_headers() + { + $source = file_get_contents(TESTS_DIR . '/src/mail.plain'); + $message = new kolab_sync_message($source); + $headers = $message->headers(); + + $this->assertArrayHasKey('MIME-Version', $headers); + $this->assertCount(8, $headers); + $this->assertEquals('kolab@domain.tld', $headers'To'); + + // test set_header() + $message->set_header('to', 'test@domain.tld'); + $headers = $message->headers(); + + $this->assertCount(8, $headers); + $this->assertEquals('test@domain.tld', $headers'To'); + } + + /** + * Test message parsing + */ + public function test_source() + { + $source = file_get_contents(TESTS_DIR . '/src/mail.plain'); + $message = new kolab_sync_message($source); + $result = $message->source(); + + $this->assertEquals($source, str_replace("\r\n", "\n", $result)); + } + + /** + * Test adding attachments to the message + */ + public function test_attachment() + { + $source = file_get_contents(TESTS_DIR . '/src/mail.plain'); + $mixed = file_get_contents(TESTS_DIR . '/src/mail.plain.mixed'); + $mixed2 = file_get_contents(TESTS_DIR . '/src/mail.mixed'); + + // test adding attachment to text/plain message + $message = new kolab_sync_message($source); + $message->add_attachment('aaa', + 'content_type' => 'text/plain', + 'encoding' => '8bit', + ); + + $result = $message->source(); + $result = str_replace("\r\n", "\n", $result); + if (preg_match('/boundary="(^"+)"/', $result, $m)) { + $mixed = str_replace('BOUNDARY', $m1, $mixed); + } + + $this->assertEquals($mixed, $result); + + // test adding attachment to multipart/mixed message + $message = new kolab_sync_message($mixed); + $message->add_attachment('aaa', + 'content_type' => 'text/plain', + 'encoding' => 'base64', + ); + + $result = $message->source(); + $result = str_replace("\r\n", "\n", $result); + if (preg_match('/boundary="(^"+)"/', $result, $m)) { + $mixed2 = str_replace('BOUNDARY', $m1, $mixed2); + } + + $this->assertEquals($mixed2, $result); + } + + /** + * Test appending a text to the message + */ + public function test_append() + { + // test appending text to text/plain message + $source = file_get_contents(TESTS_DIR . '/src/mail.plain'); + $append = file_get_contents(TESTS_DIR . '/src/mail.plain.append'); + + $message = new kolab_sync_message($source); + $message->append('a'); + + $result = $message->source(); + $result = str_replace("\r\n", "\n", $result); + $this->assertEquals($append, $result); + } + + /** + * Test recoding the message + */ + public function test_recode_message_1() + { + $source = file_get_contents(TESTS_DIR . '/src/mail.recode1'); + $result = file_get_contents(TESTS_DIR . '/src/mail.recode1.out'); + + $message = kolab_sync_message::recode_message($source); + + $this->assertEquals($result, $message); + } + + /** + * Test recoding the message + */ + public function test_recode_message_2() + { + $source = file_get_contents(TESTS_DIR . '/src/mail.recode2'); + $result = file_get_contents(TESTS_DIR . '/src/mail.recode2.out'); + + $message = kolab_sync_message::recode_message($source); + + $this->assertEquals($result, $message); + } + + /** + * Test recoding the message + */ + public function test_recode_message_3() + { + $source = file_get_contents(TESTS_DIR . '/src/mail.recode3'); + $result = file_get_contents(TESTS_DIR . '/src/mail.recode3.out'); + + $message = kolab_sync_message::recode_message($source); + + $this->assertEquals($result, $message); + } + + /** + * Test recoding the message + */ + public function test_recode_message_4() + { + $source = file_get_contents(TESTS_DIR . '/src/mail.recode4'); + $result = file_get_contents(TESTS_DIR . '/src/mail.recode4.out'); + + $message = kolab_sync_message::recode_message($source); + + $this->assertEquals($result, $message); + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/Unit/TimezoneConverterTest.php
Added
@@ -0,0 +1,174 @@ +<?php + +class TimezoneConverterTest extends PHPUnit\Framework\TestCase +{ + public function test_list_timezones() + { + // date_default_timezone_set('America/Los_Angeles'); + + $converter = kolab_sync_timezone_converter::getInstance(); + $output = $converter->getListOfTimezones('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAEAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAFAAEAAAAAAAAAxP///w=='); + + $this->assertTrue(is_array($output)); + + $converter = kolab_sync_timezone_converter::getInstance(); + $output = $converter->getListOfTimezones('xP///0MAZQBuAHQAcgBhAGwAIABFAHUAcgBvAHAAZQAgAFMAdABhAG4AZABhAHIAZAAgAFQAaQBtAGUAAAAAAAAAAAAAAAoAAAAFAAMAAAAAAAAAAAAAAEMAZQBuAHQAcgBhAGwAIABFAHUAcgBvAHAAZQAgAEQAYQB5AGwAaQBnAGgAdAAgAFQAaQBtAGUAAAAAAAAAAAAAAAMAAAAFAAIAAAAAAAAAxP///w=='); + + $this->assertTrue(is_array($output)); + $this->assertTrue(isset($output'Europe/Warsaw')); + + $converter = kolab_sync_timezone_converter::getInstance(); + $output = $converter->getListOfTimezones('4AEAAFAAYQBjAGkAZgBpAGMAIABTAHQAYQBuAGQAYQByAGQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAIAAAAAAAAAAAAAAFAAYQBjAGkAZgBpAGMAIABEAGEAeQBsAGkAZwBoAHQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAIAAAAAAAAAxP///w=='); + + $this->assertTrue(is_array($output)); + $this->assertTrue(isset($output'America/Los_Angeles')); + + $converter = kolab_sync_timezone_converter::getInstance(); + $output = $converter->getListOfTimezones('Lv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=='); + + $this->assertTrue(is_array($output)); + $this->assertTrue(isset($output'Asia/Tehran')); + + // As seen in outlook + $converter = kolab_sync_timezone_converter::getInstance(); + $output = $converter->getListOfTimezones('Lv///0kAcgBhAG4AIABTAHQAYQBuAGQAYQByAGQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkABAADABcAOwA7AOcDAAAAAEkAcgBhAG4AIABEAGEAeQBsAGkAZwBoAHQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAwAEAAAAAAAAAAAAxP///w=='); + + $this->assertTrue(is_array($output)); + $this->assertTrue(isset($output'Asia/Tehran')); + } + + public function data_get_timezone() + { + return + 'UTC', + 'Europe/Warsaw', + 'Europe/Zurich', + 'America/Los_Angeles', + 'Asia/Tehran', + ; + } + + /** + * @dataProvider data_get_timezone + */ + public function test_get_timezone($tzName) + { + date_default_timezone_set('America/Los_Angeles'); + + $converter = kolab_sync_timezone_converter::getInstance(); + $datetime = '2017-01-01T12:00:00Z'; + + $offsets = $converter->getOffsetsForTimezone($tzName, $datetime); + $output = $converter->getTimezone($offsets, $tzName); + $this->assertSame($tzName, $output); + } + + public function test_get_offsets_for_timezone() + { + date_default_timezone_set('America/Los_Angeles'); + + $converter = kolab_sync_timezone_converter::getInstance(); + $datetime = '2017-01-01T12:00:00Z'; + + $output = $converter->getOffsetsForTimezone('UTC', $datetime); + + $this->assertSame($output'bias', 0); + $this->assertSame($output'standardBias', 0); + $this->assertSame($output'daylightBias', 0); + $this->assertSame($output'standardMonth', 0); + $this->assertSame($output'daylightMonth', 0); + + $output = $converter->getOffsetsForTimezone('Europe/Warsaw', $datetime); + + $this->assertSame($output'standardBias', 0); + $this->assertSame($output'standardMonth', 10); + $this->assertSame($output'standardWeek', 5); + $this->assertSame($output'standardHour', 3); + $this->assertSame($output'daylightBias', -60); + $this->assertSame($output'daylightMonth', 3); + $this->assertSame($output'daylightWeek', 5); + $this->assertSame($output'daylightHour', 2); + + $output = $converter->getOffsetsForTimezone('America/Los_Angeles', $datetime); + + $this->assertSame($output'bias', 480); + $this->assertSame($output'standardBias', 0); + $this->assertSame($output'standardMonth', 11); + $this->assertSame($output'standardWeek', 1); + $this->assertSame($output'standardHour', 2); + $this->assertSame($output'daylightBias', -60); + $this->assertSame($output'daylightMonth', 3); + $this->assertSame($output'daylightWeek', 2); + $this->assertSame($output'daylightHour', 2); + + $output = $converter->getOffsetsForTimezone('Atlantic/Azores', $datetime); + + $this->assertSame($output'bias', 60); + $this->assertSame($output'standardBias', 0); + $this->assertSame($output'standardMonth', 10); + $this->assertSame($output'standardWeek', 5); + $this->assertSame($output'standardHour', 1); + $this->assertSame($output'daylightBias', -60); + $this->assertSame($output'daylightMonth', 3); + $this->assertSame($output'daylightWeek', 5); + $this->assertSame($output'daylightHour', 0); + + //Check before dst change + $output = $converter->getOffsetsForTimezone('Asia/Tehran', $datetime); + + $this->assertSame($output'bias', -210); + $this->assertSame($output'standardBias', 0); + $this->assertSame($output'standardMonth', 9); + $this->assertSame($output'standardWeek', 3); + $this->assertSame($output'standardDayOfWeek', 4); + $this->assertSame($output'standardHour', 24); + $this->assertSame($output'daylightBias', -60); + $this->assertSame($output'daylightMonth', 3); + $this->assertSame($output'daylightWeek', 4); + $this->assertSame($output'daylightDayOfWeek', 3); + $this->assertSame($output'daylightHour', 0); + + //Check after dst change + $output = $converter->getOffsetsForTimezone('Asia/Tehran', '2023-01-01T12:00:00Z'); + + $this->assertSame($output'bias', -210); + $this->assertSame($output'standardBias', 0); + $this->assertSame($output'standardMonth', 0); + $this->assertSame($output'standardWeek', 0); + $this->assertSame($output'standardDayOfWeek', 0); + $this->assertSame($output'standardHour', 0); + $this->assertSame($output'daylightBias', 0); + $this->assertSame($output'daylightMonth', 0); + $this->assertSame($output'daylightWeek', 0); + $this->assertSame($output'daylightDayOfWeek', 0); + $this->assertSame($output'daylightHour', 0); + } + + public function data_timezone_conversion() + { + return + //Pre dst change + 'Asia/Tehran', 'Lv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAgADABcAOwA7AOcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAQAEAAAAAAAAAAAAxP///w==', '2021-07-01T12:00:00Z', + //Post dst change + 'Asia/Tehran', 'Lv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==', '2023-04-01T12:00:00Z', + 'Pacific/Pago_Pago', 'lAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==', '2021-07-01T12:00:00Z', + 'Europe/Warsaw', 'xP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAFAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAFAAIAAAAAAAAAxP///w==', '2021-07-01T12:00:00Z', + ; + } + + /** + * @dataProvider data_timezone_conversion + */ + public function test_timezone_conversion($tz, $expected, $datetime) + { + $converter = kolab_sync_timezone_converter::getInstance(); + $output = $converter->encodeTimezone($tz, $datetime); + + $this->assertSame($expected, $output); + + $output = $converter->getListOfTimezones($output); + + $this->assertTrue(is_array($output)); + $this->assertTrue(isset($output$tz)); + } +}
View file
kolab-syncroton-2.4.2.tar.gz/tests/Unit/WbxmlTest.php
Added
@@ -0,0 +1,909 @@ +<?php + +class WbxmlTest extends PHPUnit\Framework\TestCase +{ + //function testDecode() + //{ + // //TODO input some wbxml document + // // + // $dom = new DOMDocument(); + // $dom->loadXML($lastSyncCollection'lastXML'); + // // + // try { + // $decoder = new Syncroton_Wbxml_Decoder($dom); + // $requestBody = $decoder->decode(); + // if ($this->_logger instanceof Zend_Log) { + // $requestBody->formatOutput = true; + // $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " xml request:\n" . $requestBody->saveXML()); + // } + // } catch(Syncroton_Wbxml_Exception_UnexpectedEndOfFile $e) { + // $requestBody = NULL; + // } + // //TODO validate output + //} + + + + public function testEncode() + { + $outputStream = fopen("php://temp", 'r+'); + + $encoder = new Syncroton_Wbxml_Encoder($outputStream, 'UTF-8', 3); + + $xml = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase" xmlns:Tasks="uri:Tasks"> + <Collections> + <Collection> + <SyncKey>2</SyncKey> + <CollectionId>tasksId</CollectionId> + <Commands> + <Add> + <ClientId>clientId2</ClientId> + <ApplicationData> + <Subject xmlns="uri:Tasks">task2</Subject> + <Complete xmlns="uri:Tasks">0</Complete> + <DueDate xmlns="uri:Tasks">2020-11-04T00:00:00.000Z</DueDate> + <UtcDueDate xmlns="uri:Tasks">2020-11-03T23:00:00.000Z</UtcDueDate> + </ApplicationData> + </Add> + <Add> + <ClientId>clientId3</ClientId> + <ApplicationData> + <Subject xmlns="uri:Tasks">task3</Subject> + <Complete xmlns="uri:Tasks">0</Complete> + <DueDate xmlns="uri:Tasks">2020-11-04T00:00:00.000Z</DueDate> + <UtcDueDate xmlns="uri:Tasks">2020-11-03T23:00:00.000Z</UtcDueDate> + </ApplicationData> + </Add> + </Commands> + </Collection> + </Collections> + <WindowSize>16</WindowSize> + </Sync> + EOF; + + + $dom = new DOMDocument(); + $dom->loadXML($xml); + + $encoder->encode($dom); + + rewind($outputStream); + $output = stream_get_contents($outputStream); + // print("----"); + // print(var_export($output, true)); + // print("----"); + $this->assertEquals( + base64_decode('AwFqAEVcT0sDMgABUgN0YXNrc0lkAAFWR0wDY2xpZW50SWQyAAFdAAlgA3Rhc2syAAFKAzAAAUwDMjAyMC0xMS0wNFQwMDowMDowMC4wMDBaAAFNAzIwMjAtMTEtMDNUMjM6MDA6MDAuMDAwWgABAQEAAEdMA2NsaWVudElkMwABXQAJYAN0YXNrMwABSgMwAAFMAzIwMjAtMTEtMDRUMDA6MDA6MDAuMDAwWgABTQMyMDIwLTExLTAzVDIzOjAwOjAwLjAwMFoAAQEBAQEBAABVAzE2AAEB'), + $output + ); + } + + public function testEncodeFolderSync() + { + $outputStream = fopen("php://temp", 'r+'); + + $encoder = new Syncroton_Wbxml_Encoder($outputStream, 'UTF-8', 3); + + $xml = <<<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> + <FolderSync xmlns="uri:FolderHierarchy" xmlns:Syncroton="uri:Syncroton" xmlns:Internal="uri:Internal"> + <Status>1</Status> + <SyncKey>1</SyncKey> + <Changes> + <Count>18</Count> + <Add> + <ServerId>2685b302b79f58d2753199545e3cb8be</ServerId> + <ParentId>0</ParentId> + <DisplayName>Test2</DisplayName> + <Type>13</Type> + </Add> + <Add> + <ServerId>9770b083c68e8584f396d15a116d6608</ServerId> + <ParentId>0</ParentId> + <DisplayName>DavidCalendar</DisplayName> + <Type>13</Type> + </Add> + <Add> + <ServerId>0f66388806743c514b8063bf0dc87486</ServerId> + <ParentId>0</ParentId> + <DisplayName>SergeyCalendar</DisplayName> + <Type>13</Type> + </Add> + <Add> + <ServerId>cca1b81c734abbcd669bea90d23e08ae</ServerId> + <ParentId>0</ParentId> + <DisplayName>Calendar</DisplayName> + <Type>8</Type> + </Add> + <Add> + <ServerId>ab1ddb4ef8e8f8fcc2c9f5a7f9062452</ServerId> + <ParentId>0</ParentId> + <DisplayName>PubCal</DisplayName> + <Type>13</Type> + </Add> + <Add> + <ServerId>d98bd8721371544ed095841ead941893</ServerId> + <ParentId>0</ParentId> + <DisplayName>(david) Test2</DisplayName> + <Type>13</Type> + </Add> + <Add> + <ServerId>9e7b9656ef61d4af2fb2fdcabe600079</ServerId> + <ParentId>0</ParentId> + <DisplayName>(david) DavidCalendar</DisplayName> + <Type>13</Type> + </Add> + <Add> + <ServerId>384cf2d877c39a622fdc2a16898052e2</ServerId> + <ParentId>0</ParentId> + <DisplayName>(david) Calendar</DisplayName> + <Type>13</Type> + </Add> + <Add> + <ServerId>Contacts::Syncroton</ServerId> + <ParentId>0</ParentId> + <DisplayName>Contacts</DisplayName> + <Type>9</Type> + </Add> + <Add> + <ServerId>1bb8c55fe84d52c6968db2571f7dc124</ServerId> + <ParentId>0</ParentId> + <DisplayName>Archive</DisplayName> + <Type>12</Type> + </Add> + <Add> + <ServerId>b51abe73e9e98fe200a4afe409050502</ServerId> + <ParentId>38b950ebd62cd9a66929c89615d0fc04</ParentId> + <DisplayName>Spam</DisplayName> + <Type>12</Type> + </Add> + <Add> + <ServerId>cf529c792fc87d1f207435b3921bb02e</ServerId> + <ParentId>0</ParentId> + <DisplayName>Sent</DisplayName> + <Type>5</Type> + </Add> + <Add> + <ServerId>715ed9ea29b8a5377a69c1f758037c65</ServerId> + <ParentId>0</ParentId> + <DisplayName>Spam</DisplayName> + <Type>12</Type> + </Add> + <Add> + <ServerId>db0d959a3aeb21757f8849a830947a7a</ServerId> + <ParentId>0</ParentId> + <DisplayName>Trash</DisplayName> + <Type>4</Type> + </Add> + <Add> + <ServerId>5ac9ec2e1a9d99e2e10cabe4abf26729</ServerId> + <ParentId>0</ParentId> + <DisplayName>Drafts</DisplayName> + <Type>3</Type> + </Add> + <Add> + <ServerId>38b950ebd62cd9a66929c89615d0fc04</ServerId> + <ParentId>0</ParentId> + <DisplayName>INBOX</DisplayName> + <Type>2</Type> + </Add> + <Add> + <ServerId>fc56f4c7ffe0aefa622db9f8d9186c4a</ServerId> + <ParentId>0</ParentId> + <DisplayName>Notes</DisplayName> + <Type>10</Type> + </Add>
View file
kolab-syncroton-2.4.2.tar.gz/tests/body_converter.php
Deleted
@@ -1,45 +0,0 @@ -<?php - -class body_converter extends PHPUnit\Framework\TestCase -{ - function data_html_to_text() - { - return array( - array('', ''), - array('<div></div>', ''), - array('<div>a</div>', 'a'), - array('<html><head><title>title</title></head></html>', ''), - ); - } - - /** - * @dataProvider data_html_to_text - */ - function test_html_to_text($html, $text) - { - $converter = new kolab_sync_body_converter($html, Syncroton_Model_EmailBody::TYPE_HTML); - $output = $converter->convert(Syncroton_Model_EmailBody::TYPE_PLAINTEXT); - - $this->assertEquals(trim($text), trim($output)); - } - - /** - * - */ - function test_rtf_to_text() - { - $rtf = '0QAAAB0CAABMWkZ1Pzsq5D8ACQMwAQMB9wKnAgBjaBEKwHNldALRcHJx4DAgVGFoA3ECgwBQ6wNUDzcyD9MyBgAGwwKDpxIBA+MReDA0EhUgAoArApEI5jsJbzAVwzEyvjgJtBdCCjIXQRb0ORIAHxeEGOEYExjgFcMyNTX/CbQaYgoyGmEaHBaKCaUa9v8c6woUG3YdTRt/Hwwabxbt/xyPF7gePxg4JY0YVyRMKR+dJfh9CoEBMAOyMTYDMUksgSc1FGAnNhqAJ1Q3My3BNAqFfS7A'; - $rtf = base64_decode($rtf); - $text = 'Test'; - $html = '<pre>Test</pre>'; - - $converter = new kolab_sync_body_converter($rtf, Syncroton_Model_EmailBody::TYPE_RTF); - - $output = $converter->convert(Syncroton_Model_EmailBody::TYPE_PLAINTEXT); - $this->assertEquals(trim($text), trim($output)); - - $output = $converter->convert(Syncroton_Model_EmailBody::TYPE_HTML); - $this->assertEquals(trim($html), trim($output)); - } - -}
View file
kolab-syncroton-2.4.2.tar.gz/tests/bootstrap.php
Changed
@@ -1,5 +1,8 @@ <?php +error_reporting(E_ALL); +ini_set('display_errors', 1); + if (php_sapi_name() != 'cli') { die("Not in shell mode (php-cli)"); } @@ -7,5 +10,6 @@ define('TESTS_DIR', dirname(__FILE__) . '/'); require_once(TESTS_DIR . '/../lib/init.php'); +require_once(TESTS_DIR . '/SyncTestCase.php'); rcube::get_instance()->config->set('devel_mode', false);
View file
kolab-syncroton-2.4.2.tar.gz/tests/data.php
Deleted
@@ -1,74 +0,0 @@ -<?php - -class data extends PHPUnit\Framework\TestCase -{ - /** - * Test for kolab_sync_data::recurrence_to_kolab() - */ - function test_recurrence_to_kolab() - { - $xml = '<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> - <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase" xmlns:Calendar="uri:Calendar"> - <ApplicationData> - <Calendar:Recurrence> - <Calendar:Type>0</Calendar:Type> - <Calendar:Interval>1</Calendar:Interval> - <Calendar:Until>20101128T225959Z</Calendar:Until> - </Calendar:Recurrence> - </ApplicationData> - </Sync>'; - - $xml = new SimpleXMLElement($xml); - $event = new Syncroton_Model_Event($xml->ApplicationData); - $data = new kolab_sync_data_test; - - $result = $data->recurrence_to_kolab($event); - - $this->assertEquals('DAILY', $result'FREQ'); - $this->assertEquals(1, $result'INTERVAL'); - $this->assertEquals('20101128T225959Z', $result'UNTIL'->format("Ymd\THis\Z")); - - $xml = '<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> - <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase" xmlns:Calendar="uri:Calendar"> - <ApplicationData> - <Calendar:Recurrence> - <Calendar:Type>1</Calendar:Type> - <Calendar:Interval>1</Calendar:Interval> - <Calendar:DayOfWeek>8</Calendar:DayOfWeek> - </Calendar:Recurrence> - </ApplicationData> - </Sync>'; - - $xml = new SimpleXMLElement($xml); - $event = new Syncroton_Model_Event($xml->ApplicationData); - - $result = $data->recurrence_to_kolab($event, null); - - $this->assertEquals('WEEKLY', $result'FREQ'); - $this->assertEquals(1, $result'INTERVAL'); - $this->assertEquals('WE', $result'BYDAY'); - } -} - -/** - * kolab_sync_data wrapper, so we can test preotected methods too - */ -class kolab_sync_data_test extends kolab_sync_data -{ - function __construct() - { - } - - public function recurrence_to_kolab($data, $dummy1 = null, $dummy2 = null) - { - return parent::recurrence_to_kolab($data, null); - } - - function toKolab(Syncroton_Model_IEntry $data, $folderId, $entry = null, $timezone = null) - { - } - - function getEntry(Syncroton_Model_SyncCollection $collection, $serverId, $as_array = false) - { - } -}
View file
kolab-syncroton-2.4.2.tar.gz/tests/data_calendar.php
Deleted
@@ -1,126 +0,0 @@ -<?php - -class data_calendar extends PHPUnit\Framework\TestCase -{ - /** - * Test for kolab_sync_data_calendar::from_kolab_alarm() - */ - function test_from_kolab_alarm() - { - $obj = new kolab_sync_data_calendar_test; - - $result = $obj->from_kolab_alarm(array()); - $this->assertSame(null, $result); - - $event = array('valarms' => array(array( - 'action' => 'DISPLAY', - 'trigger' => 'PT5M', - ))); - $result = $obj->from_kolab_alarm($event); - $this->assertSame(null, $result); - - $event = array('valarms' => array(array( - 'action' => 'DISPLAY', - 'trigger' => '-PT5M', - ))); - $result = $obj->from_kolab_alarm($event); - $this->assertSame(5, $result); - - $event = array('valarms' => array(array( - 'action' => 'DISPLAY', - 'trigger' => 'PT0M', - ))); - $result = $obj->from_kolab_alarm($event); - $this->assertSame(0, $result); - - $event = array('valarms' => array(array( - 'action' => 'DISPLAY', - 'trigger' => '-PT0M', - ))); - $result = $obj->from_kolab_alarm($event); - $this->assertSame(0, $result); - - $event = array('valarms' => array(array( - 'action' => 'DISPLAY', - 'trigger' => 'PT0S', - ))); - $result = $obj->from_kolab_alarm($event); - $this->assertSame(0, $result); - - // alarms on specified DateTime (T2420) - - $event = array( - // no start datetime defined - 'valarms' => array( - array( - 'action' => 'DISPLAY', - 'trigger' => new DateTime('now + 1 hour'), - ), - ), - ); - $result = $obj->from_kolab_alarm($event); - $this->assertSame(null, $result); - - $event = array( - 'start' => new DateTime('now + 10 minutes'), - 'valarms' => array( - array( - 'action' => 'DISPLAY', - 'trigger' => new DateTime('now + 1 hour'), - ), - ), - ); - $result = $obj->from_kolab_alarm($event); - $this->assertSame(null, $result); - - $event = array( - 'start' => new DateTime('now + 60 minutes'), - 'valarms' => array( - array( - 'action' => 'DISPLAY', - 'trigger' => new DateTime('now + 50 minutes'), - ), - ), - ); - $result = $obj->from_kolab_alarm($event); - $this->assertSame(10, $result); - } - - /** - * Test for kolab_sync_data_calendar::to_kolab_alarm() - */ - function test_to_kolab_alarm() - { - $obj = new kolab_sync_data_calendar_test; - - $result = $obj->to_kolab_alarm(null, array()); - $this->assertSame(array(), $result); - - $result = $obj->to_kolab_alarm(0, array()); - $this->assertSame('-PT0M', $result0'trigger'); - - $result = $obj->to_kolab_alarm(15, array()); - $this->assertSame('-PT15M', $result0'trigger'); - $this->assertSame('DISPLAY', $result0'action'); - } -} - -/** - * kolab_sync_data_calendar wrapper, so we can test protected methods too - */ -class kolab_sync_data_calendar_test extends kolab_sync_data_calendar -{ - function __construct() - { - } - - public function from_kolab_alarm($value) - { - return parent::from_kolab_alarm($value); - } - - public function to_kolab_alarm($value, $event) - { - return parent::to_kolab_alarm($value, $event); - } -}
View file
kolab-syncroton-2.4.2.tar.gz/tests/data_tasks.php
Deleted
@@ -1,78 +0,0 @@ -<?php - -class data_tasks extends PHPUnit\Framework\TestCase -{ - function data_prio() - { - return array( - array(0, null), - array(1, 2), - array(2, 2), - array(3, 2), - array(4, 2), - array(5, 1), - array(6, 0), - array(7, 0), - array(8, 0), - array(9, 0), - // invalid input - array(10, null), - ); - } - - function data_importance() - { - return array( - array(0, 9), - array(1, 5), - array(2, 1), - // invalid input - array(null, null), - array(5, null), - ); - } - - /** - * Test for kolab_sync_data_tasks::prio_to_importance() - * @dataProvider data_prio() - */ - function test_prio_to_importance($input, $output) - { - $data = new kolab_sync_data_tasks_test; - $result = $data->prio_to_importance($input); - - $this->assertEquals($output, $result); - } - - /** - * Test for kolab_sync_data_tasks::importance_to_prio() - * @dataProvider data_importance() - */ - function test_importance_to_prio($input, $output) - { - $data = new kolab_sync_data_tasks_test; - $result = $data->importance_to_prio($input); - - $this->assertEquals($output, $result); - } -} - -/** - * kolab_sync_data_tasks wrapper, so we can test preotected methods too - */ -class kolab_sync_data_tasks_test extends kolab_sync_data_tasks -{ - function __construct() - { - } - - public function prio_to_importance($value) - { - return parent::prio_to_importance($value); - } - - public function importance_to_prio($value) - { - return parent::importance_to_prio($value); - } -}
View file
kolab-syncroton-2.4.2.tar.gz/tests/globalid_converter.php
Deleted
@@ -1,37 +0,0 @@ -<?php - -class globalid_converter extends PHPUnit\Framework\TestCase -{ - /** - * Test GlobalObjId encoding/decoding - */ - function test_globalobjid() - { - // https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-asemail/e7424ddc-dd10-431e-a0b7-5c794863370e - $input = 'BAAAAIIA4AB0xbcQGoLgCAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAAHZDYWwtVWlkAQAAAHs4MTQxMkQzQy0yQTI0LTRFOUQtQjIwRS0xMUY3QkJFOTI3OTl9AA=='; - $output = kolab_sync_data_email::decodeGlobalObjId($input); - - $this->assertSame(51, $output'bytecount'); - $this->assertSame('{81412D3C-2A24-4E9D-B20E-11F7BBE92799}', $output'uid'); - - $encoded = kolab_sync_data_email::encodeGlobalObjId($output); - $this->assertSame($encoded, $input); - - $input = 'BAAAAIIA4AB0xbcQGoLgCAfUCRDgQMnBJoXEAQAAAAAAAAAAEAAAAAvw7UtuTulOnjnjhns3jvM='; - $output = kolab_sync_data_email::decodeGlobalObjId($input); - - $this->assertSame(16, $output'bytecount'); - $this->assertSame(2004, $output'year'); - $this->assertSame(9, $output'month'); - $this->assertSame(16, $output'day'); - $this->assertSame(127373090979660000, $output'now'); - - // This is how the "now" value is interpreted - // $winSecs = (int)($output'now' / 10000000); // convert microseconds to seconds - // $unixTimestamp = ($winSecs - 11644473600); // subtract 1.1.1600 - 1.1.1970 difference in seconds - // print(date(DateTime::RFC822, $unixTimestamp)); - - $encoded = kolab_sync_data_email::encodeGlobalObjId($output); - $this->assertSame($encoded, $input); - } -}
View file
kolab-syncroton-2.4.2.tar.gz/tests/message.php
Deleted
@@ -1,146 +0,0 @@ -<?php - -class message extends PHPUnit\Framework\TestCase -{ - /** - * Test message parsing and headers setting - */ - function test_headers() - { - $source = file_get_contents(TESTS_DIR . '/src/mail.plain'); - $message = new kolab_sync_message($source); - $headers = $message->headers(); - - $this->assertArrayHasKey('MIME-Version', $headers); - $this->assertCount(8, $headers); - $this->assertEquals('kolab@domain.tld', $headers'To'); - - // test set_header() - $message->set_header('to', 'test@domain.tld'); - $headers = $message->headers(); - - $this->assertCount(8, $headers); - $this->assertEquals('test@domain.tld', $headers'To'); - } - - /** - * Test message parsing - */ - function test_source() - { - $source = file_get_contents(TESTS_DIR . '/src/mail.plain'); - $message = new kolab_sync_message($source); - $result = $message->source(); - - $this->assertEquals($source, str_replace("\r\n", "\n", $result)); - } - - /** - * Test adding attachments to the message - */ - function test_attachment() - { - $source = file_get_contents(TESTS_DIR . '/src/mail.plain'); - $mixed = file_get_contents(TESTS_DIR . '/src/mail.plain.mixed'); - $mixed2 = file_get_contents(TESTS_DIR . '/src/mail.mixed'); - - // test adding attachment to text/plain message - $message = new kolab_sync_message($source); - $message->add_attachment('aaa', array( - 'content_type' => 'text/plain', - 'encoding' => '8bit', - )); - - $result = $message->source(); - $result = str_replace("\r\n", "\n", $result); - if (preg_match('/boundary="(^"+)"/', $result, $m)) { - $mixed = str_replace('BOUNDARY', $m1, $mixed); - } - - $this->assertEquals($mixed, $result); - - // test adding attachment to multipart/mixed message - $message = new kolab_sync_message($mixed); - $message->add_attachment('aaa', array( - 'content_type' => 'text/plain', - 'encoding' => 'base64', - )); - - $result = $message->source(); - $result = str_replace("\r\n", "\n", $result); - if (preg_match('/boundary="(^"+)"/', $result, $m)) { - $mixed2 = str_replace('BOUNDARY', $m1, $mixed2); - } - - $this->assertEquals($mixed2, $result); - } - - /** - * Test appending a text to the message - */ - function test_append() - { - // test appending text to text/plain message - $source = file_get_contents(TESTS_DIR . '/src/mail.plain'); - $append = file_get_contents(TESTS_DIR . '/src/mail.plain.append'); - - $message = new kolab_sync_message($source); - $message->append('a'); - - $result = $message->source(); - $result = str_replace("\r\n", "\n", $result); - $this->assertEquals($append, $result); - } - - /** - * Test recoding the message - */ - function test_recode_message_1() - { - $source = file_get_contents(TESTS_DIR . '/src/mail.recode1'); - $result = file_get_contents(TESTS_DIR . '/src/mail.recode1.out'); - - $message = kolab_sync_message::recode_message($source); - - $this->assertEquals($result, $message); - } - - /** - * Test recoding the message - */ - function test_recode_message_2() - { - $source = file_get_contents(TESTS_DIR . '/src/mail.recode2'); - $result = file_get_contents(TESTS_DIR . '/src/mail.recode2.out'); - - $message = kolab_sync_message::recode_message($source); - - $this->assertEquals($result, $message); - } - - /** - * Test recoding the message - */ - function test_recode_message_3() - { - $source = file_get_contents(TESTS_DIR . '/src/mail.recode3'); - $result = file_get_contents(TESTS_DIR . '/src/mail.recode3.out'); - - $message = kolab_sync_message::recode_message($source); - - $this->assertEquals($result, $message); - } - - /** - * Test recoding the message - */ - function test_recode_message_4() - { - $source = file_get_contents(TESTS_DIR . '/src/mail.recode4'); - $result = file_get_contents(TESTS_DIR . '/src/mail.recode4.out'); - - $message = kolab_sync_message::recode_message($source); - - $this->assertEquals($result, $message); - } -}
View file
kolab-syncroton-2.4.2.tar.gz/tests/phpunit.xml
Changed
@@ -2,15 +2,11 @@ bootstrap="bootstrap.php" colors="true"> <testsuites> - <testsuite name="All Tests"> - <file>body_converter.php</file> - <file>data.php</file> - <file>data_calendar.php</file> - <file>data_tasks.php</file> - <file>globalid_converter.php</file> - <file>message.php</file> - <file>timezone_converter.php</file> - <file>wbxml.php</file> + <testsuite name="Unit"> + <directory suffix="Test.php">Unit</directory> + </testsuite> + <testsuite name="Sync"> + <directory suffix="Test.php">Sync</directory> </testsuite> </testsuites> </phpunit>
View file
kolab-syncroton-2.4.2.tar.gz/tests/src/contact.vcard1
Added
@@ -0,0 +1,6 @@ +BEGIN:VCARD +VERSION:3.0 +UID:urn:uuid:abcdef-0123-4567-89ab-abcdefabcdef +FN:Jane Doe +N:Doe;Jane;J.;; +END:VCARD
View file
kolab-syncroton-2.4.2.tar.gz/tests/src/contact.vcard2
Added
@@ -0,0 +1,6 @@ +BEGIN:VCARD +VERSION:3.0 +UID:urn:uuid:abcdef-0123-4567-89ab-abcdefabc123 +FN:Jack Strong +N:Strong;Jack;;; +END:VCARD
View file
kolab-syncroton-2.4.2.tar.gz/tests/src/event.ics1
Added
@@ -0,0 +1,12 @@ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//test/test//NONSGML v1.0//EN +BEGIN:VEVENT +UID:abcdef +DTSTAMP:19970714T170000Z +ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com +DTSTART:20240714T170000Z +DTEND:20240714T180000Z +SUMMARY:Party +END:VEVENT +END:VCALENDAR
View file
kolab-syncroton-2.4.2.tar.gz/tests/src/event.ics2
Added
@@ -0,0 +1,12 @@ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//test/test//NONSGML v1.0//EN +BEGIN:VEVENT +UID:123456 +DTSTAMP:19970714T170000Z +ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com +DTSTART:20240715T170000Z +DTEND:20240715T180000Z +SUMMARY:Meeting +END:VEVENT +END:VCALENDAR
View file
kolab-syncroton-2.4.2.tar.gz/tests/src/mail.itip1
Added
@@ -0,0 +1,62 @@ +MIME-Version: 1.0 +Date: Thu, 07 Dec 2023 13:29:14 +0100 +Message-ID: <14ab307198d32cee00b38ffb54c9e577@nestle.kolab.ch> +From: "Organizer" <$from> +To: <$to> +Subject: You've been invited to "Test" +Content-Type: multipart/alternative; + boundary="=_f39ac9438326f676a8d562e163aa31e0" + +--=_f39ac9438326f676a8d562e163aa31e0 +Content-Transfer-Encoding: quoted-printable +Content-Type: text/plain; charset=UTF-8; + format=flowed + +*Test* +--=_f39ac9438326f676a8d562e163aa31e0 +Content-Transfer-Encoding: 8bit +Content-Type: text/calendar; charset=UTF-8; method=REQUEST; name=event.ics + +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Roundcube 1.5-git//Sabre VObject 4.5.3//EN +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VTIMEZONE +TZID:Europe/Warsaw +BEGIN:DAYLIGHT +DTSTART:20230326T010000 +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +TZNAME:CEST +END:DAYLIGHT +BEGIN:DAYLIGHT +DTSTART:20240331T010000 +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +TZNAME:CEST +END:DAYLIGHT +BEGIN:STANDARD +DTSTART:20231029T010000 +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +TZNAME:CET +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +UID:1154B829349633D80E143AAB5641170A-93BC4FC398A3FD52 +DTSTAMP:20231207T122914Z +CREATED:20231207T122914Z +LAST-MODIFIED:20231207T122914Z +DTSTART;TZID=Europe/Warsaw:20231207T140000 +DTEND;TZID=Europe/Warsaw:20231207T143000 +SUMMARY:Test +SEQUENCE:0 +TRANSP:OPAQUE +ATTENDEE;CN="Attendee Name";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPA + NT;CUTYPE=INDIVIDUAL;RSVP=TRUE:mailto:$to +ORGANIZER;CN="Organizer Name":mailto:$from +END:VEVENT +END:VCALENDAR + +--=_f39ac9438326f676a8d562e163aa31e0--
View file
kolab-syncroton-2.4.2.tar.gz/tests/src/mail.sync1
Added
@@ -0,0 +1,10 @@ +Date: Thu, 09 Aug 2012 13:18:31 +0000 +Subject: test sync +Message-ID: <sync1@domain.tld> +From: "Sync 1" <user@domain.tld> +To: "To 1" <kolab1@domain.tld>, "To 2" <kolab2@domain.tld> +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: base64 + +ZWVlYQ==
View file
kolab-syncroton-2.4.2.tar.gz/tests/src/mail.sync2
Added
@@ -0,0 +1,20 @@ +Date: Thu, 10 Aug 2012 13:18:31 +0000 +Subject: sync test with attachment +Message-ID: <sync2@domain.tld> +From: user@domain.tld +To: kolab@domain.tld +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="BOUNDARY" + +--BOUNDARY +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: base64 + +ZWVl +--BOUNDARY +Content-Transfer-Encoding: base64 +Content-Type: image/jpeg; name=logo.gif +Content-Disposition: inline; filename=logo.gif; size=2574 + +/9j/4AAQSkZJRgABAgEASABIAAD/4QqARXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUA +--BOUNDARY--
View file
kolab-syncroton-2.4.2.tar.gz/tests/src/sample.rtf
Added
@@ -0,0 +1,18 @@ +{\rtf1\mac\deff2 {\fonttbl{\f0\fswiss Chicago;}{\f2\froman New York;}{\f3\fswiss Geneva;}{\f4\fmodern Monaco;}{\f11\fnil Cairo;}{\f13\fnil Zapf Dingbats;}{\f14\fnil Bookman;}{\f15\fnil N Helvetica Narrow;}{\f16\fnil Palatino;}{\f18\fnil Zapf Chancery;} +{\f20\froman Times;}{\f21\fswiss Helvetica;}{\f22\fmodern Courier;}{\f23\ftech Symbol;}{\f33\fnil Avant Garde;}{\f34\fnil New Century Schlbk;}{\f1297\fnil GoudyHundred;}{\f1602\fnil BlackChancery;}{\f2515\fnil MT Extra;}{\f4950\fnil TTYFont;} +{\f11132\fnil InsigniaLQmono;}{\f11133\fnil InsigniaLQprop;}{\f32500\fnil VT320;}{\f32525\fnil VT100;}}{\colortbl\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0; +\red255\green255\blue0;\red255\green255\blue255;}{\stylesheet{\s250\li720 \f21\fs20\ul \sbasedon0\snext0 heading 6;}{\s251\li720 \b\f21\fs20 \sbasedon0\snext0 heading 5;}{\s252\li360 \f21\ul \sbasedon0\snext0 heading 4;}{\s253\li360 \b\f21 +\sbasedon0\snext0 heading 3;}{\s254\sb120 \b\f21 \sbasedon0\snext0 heading 2;}{\s255\sb240 \b\f21\ul \sbasedon0\snext0 heading 1;}{\f21 \sbasedon222\snext0 Normal;}{\s2 \b\f21\cf1 \sbasedon0\snext2 Anchor;}}{\info{\author Chuck Shotton}} +\margl720\margr720\ftnbj\fracwidth \sectd \sbknone\linemod0\linex0\cols1\endnhere \pard\plain \s255\sb240 \b\f21\ul Heading 1\par +\pard\plain \f21 This is the first normal paragraph!\par +\pard\plain \s254\sb120 \b\f21 Heading 2\par +\pard\plain \s253\li360 \b\f21 Heading 3\par +\pard\plain \s252\li360 \f21\ul Heading 4\par +\pard\plain \s251\li720 \b\f21\fs20 Heading 5\par +\pard\plain \s250\li720 \f21\fs20\ul Heading 6\par +\pard\plain \f21 This is a chunk of normal text.\par +This is a chunk of normal text with specials, &, <, and >.\par +This is a second paragraph.\par +This is text with embedded {\b bold}, {\i italic}, and {\ul underline} styles.\par +Here is the {\cf1 anchor} style. And here is the {\cf5 Image} style.\par +} \ No newline at end of file
View file
kolab-syncroton-2.4.2.tar.gz/tests/timezone_converter.php
Deleted
@@ -1,175 +0,0 @@ -<?php - -class timezone_converter extends PHPUnit\Framework\TestCase -{ - function test_list_timezones() - { -// date_default_timezone_set('America/Los_Angeles'); - - $converter = kolab_sync_timezone_converter::getInstance(); - $output = $converter->getListOfTimezones('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAEAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAFAAEAAAAAAAAAxP///w=='); - - $this->assertTrue(is_array($output)); - $this->assertSame(array(), $output); - - $converter = kolab_sync_timezone_converter::getInstance(); - $output = $converter->getListOfTimezones('xP///0MAZQBuAHQAcgBhAGwAIABFAHUAcgBvAHAAZQAgAFMAdABhAG4AZABhAHIAZAAgAFQAaQBtAGUAAAAAAAAAAAAAAAoAAAAFAAMAAAAAAAAAAAAAAEMAZQBuAHQAcgBhAGwAIABFAHUAcgBvAHAAZQAgAEQAYQB5AGwAaQBnAGgAdAAgAFQAaQBtAGUAAAAAAAAAAAAAAAMAAAAFAAIAAAAAAAAAxP///w=='); - - $this->assertTrue(is_array($output)); - $this->assertTrue(isset($output'Europe/Warsaw')); - - $converter = kolab_sync_timezone_converter::getInstance(); - $output = $converter->getListOfTimezones('4AEAAFAAYQBjAGkAZgBpAGMAIABTAHQAYQBuAGQAYQByAGQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAIAAAAAAAAAAAAAAFAAYQBjAGkAZgBpAGMAIABEAGEAeQBsAGkAZwBoAHQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAIAAAAAAAAAxP///w=='); - - $this->assertTrue(is_array($output)); - $this->assertTrue(isset($output'America/Los_Angeles')); - - $converter = kolab_sync_timezone_converter::getInstance(); - $output = $converter->getListOfTimezones('Lv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=='); - - $this->assertTrue(is_array($output)); - $this->assertTrue(isset($output'Asia/Tehran')); - - // As seen in outlook - $converter = kolab_sync_timezone_converter::getInstance(); - $output = $converter->getListOfTimezones('Lv///0kAcgBhAG4AIABTAHQAYQBuAGQAYQByAGQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkABAADABcAOwA7AOcDAAAAAEkAcgBhAG4AIABEAGEAeQBsAGkAZwBoAHQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAwAEAAAAAAAAAAAAxP///w=='); - - $this->assertTrue(is_array($output)); - $this->assertTrue(isset($output'Asia/Tehran')); - } - - function data_get_timezone() - { - return - 'UTC', - 'Europe/Warsaw', - 'Europe/Zurich', - 'America/Los_Angeles', - 'Asia/Tehran', - ; - } - - /** - * @dataProvider data_get_timezone - */ - function test_get_timezone($tzName) - { - date_default_timezone_set('America/Los_Angeles'); - - $converter = kolab_sync_timezone_converter::getInstance(); - $datetime = '2017-01-01T12:00:00Z'; - - $offsets = $converter->getOffsetsForTimezone($tzName, $datetime); - $output = $converter->getTimezone($offsets, $tzName); - $this->assertSame($tzName, $output); - } - - function test_get_offsets_for_timezone() - { - date_default_timezone_set('America/Los_Angeles'); - - $converter = kolab_sync_timezone_converter::getInstance(); - $datetime = '2017-01-01T12:00:00Z'; - - $output = $converter->getOffsetsForTimezone('UTC', $datetime); - - $this->assertSame($output'bias', 0); - $this->assertSame($output'standardBias', 0); - $this->assertSame($output'daylightBias', 0); - $this->assertSame($output'standardMonth', 0); - $this->assertSame($output'daylightMonth', 0); - - $output = $converter->getOffsetsForTimezone('Europe/Warsaw', $datetime); - - $this->assertSame($output'standardBias', 0); - $this->assertSame($output'standardMonth', 10); - $this->assertSame($output'standardWeek', 5); - $this->assertSame($output'standardHour', 3); - $this->assertSame($output'daylightBias', -60); - $this->assertSame($output'daylightMonth', 3); - $this->assertSame($output'daylightWeek', 5); - $this->assertSame($output'daylightHour', 2); - - $output = $converter->getOffsetsForTimezone('America/Los_Angeles', $datetime); - - $this->assertSame($output'bias', 480); - $this->assertSame($output'standardBias', 0); - $this->assertSame($output'standardMonth', 11); - $this->assertSame($output'standardWeek', 1); - $this->assertSame($output'standardHour', 2); - $this->assertSame($output'daylightBias', -60); - $this->assertSame($output'daylightMonth', 3); - $this->assertSame($output'daylightWeek', 2); - $this->assertSame($output'daylightHour', 2); - - $output = $converter->getOffsetsForTimezone('Atlantic/Azores', $datetime); - - $this->assertSame($output'bias', 60); - $this->assertSame($output'standardBias', 0); - $this->assertSame($output'standardMonth', 10); - $this->assertSame($output'standardWeek', 5); - $this->assertSame($output'standardHour', 1); - $this->assertSame($output'daylightBias', -60); - $this->assertSame($output'daylightMonth', 3); - $this->assertSame($output'daylightWeek', 5); - $this->assertSame($output'daylightHour', 0); - - //Check before dst change - $output = $converter->getOffsetsForTimezone('Asia/Tehran', $datetime); - - $this->assertSame($output'bias', -210); - $this->assertSame($output'standardBias', 0); - $this->assertSame($output'standardMonth', 9); - $this->assertSame($output'standardWeek', 3); - $this->assertSame($output'standardDayOfWeek', 4); - $this->assertSame($output'standardHour', 24); - $this->assertSame($output'daylightBias', -60); - $this->assertSame($output'daylightMonth', 3); - $this->assertSame($output'daylightWeek', 4); - $this->assertSame($output'daylightDayOfWeek', 3); - $this->assertSame($output'daylightHour', 0); - - //Check after dst change - $output = $converter->getOffsetsForTimezone('Asia/Tehran', '2023-01-01T12:00:00Z'); - - $this->assertSame($output'bias', -210); - $this->assertSame($output'standardBias', 0); - $this->assertSame($output'standardMonth', 0); - $this->assertSame($output'standardWeek', 0); - $this->assertSame($output'standardDayOfWeek', 0); - $this->assertSame($output'standardHour', 0); - $this->assertSame($output'daylightBias', 0); - $this->assertSame($output'daylightMonth', 0); - $this->assertSame($output'daylightWeek', 0); - $this->assertSame($output'daylightDayOfWeek', 0); - $this->assertSame($output'daylightHour', 0); - } - - function data_timezone_conversion() - { - return array( - //Pre dst change - array('Asia/Tehran', 'Lv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAgADABcAOwA7AOcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAQAEAAAAAAAAAAAAxP///w==', '2021-07-01T12:00:00Z'), - //Post dst change - array('Asia/Tehran', 'Lv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==', '2023-04-01T12:00:00Z'), - array('Pacific/Pago_Pago', 'lAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==', '2021-07-01T12:00:00Z'), - array('Europe/Warsaw', 'xP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAFAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAFAAIAAAAAAAAAxP///w==', '2021-07-01T12:00:00Z'), - ); - } - - /** - * @dataProvider data_timezone_conversion - */ - function test_timezone_conversion($tz, $expected, $datetime) - { - $converter = kolab_sync_timezone_converter::getInstance(); - $output = $converter->encodeTimezone($tz, $datetime); - - $this->assertSame($expected, $output); - - $output = $converter->getListOfTimezones($output); - - $this->assertTrue(is_array($output)); - $this->assertTrue(isset($output$tz)); - } -}
View file
kolab-syncroton-2.4.2.tar.gz/tests/wbxml.php
Deleted
@@ -1,892 +0,0 @@ -<?php - -class wbxml extends PHPUnit\Framework\TestCase -{ - //function testDecode() - //{ - // //TODO input some wbxml document - // // - // $dom = new DOMDocument(); - // $dom->loadXML($lastSyncCollection'lastXML'); - // // - // try { - // $decoder = new Syncroton_Wbxml_Decoder($dom); - // $requestBody = $decoder->decode(); - // if ($this->_logger instanceof Zend_Log) { - // $requestBody->formatOutput = true; - // $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " xml request:\n" . $requestBody->saveXML()); - // } - // } catch(Syncroton_Wbxml_Exception_UnexpectedEndOfFile $e) { - // $requestBody = NULL; - // } - // //TODO validate output - //} - - - - public function testEncode() - { - $outputStream = fopen("php://temp", 'r+'); - - $encoder = new Syncroton_Wbxml_Encoder($outputStream, 'UTF-8', 3); - - $xml = <<<EOF - <?xml version="1.0" encoding="utf-8"?> - <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> - <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase" xmlns:Tasks="uri:Tasks"> - <Collections> - <Collection> - <SyncKey>2</SyncKey> - <CollectionId>tasksId</CollectionId> - <Commands> - <Add> - <ClientId>clientId2</ClientId> - <ApplicationData> - <Subject xmlns="uri:Tasks">task2</Subject> - <Complete xmlns="uri:Tasks">0</Complete> - <DueDate xmlns="uri:Tasks">2020-11-04T00:00:00.000Z</DueDate> - <UtcDueDate xmlns="uri:Tasks">2020-11-03T23:00:00.000Z</UtcDueDate> - </ApplicationData> - </Add> - <Add> - <ClientId>clientId3</ClientId> - <ApplicationData> - <Subject xmlns="uri:Tasks">task3</Subject> - <Complete xmlns="uri:Tasks">0</Complete> - <DueDate xmlns="uri:Tasks">2020-11-04T00:00:00.000Z</DueDate> - <UtcDueDate xmlns="uri:Tasks">2020-11-03T23:00:00.000Z</UtcDueDate> - </ApplicationData> - </Add> - </Commands> - </Collection> - </Collections> - <WindowSize>16</WindowSize> - </Sync> - EOF; - - - $dom = new DOMDocument(); - $dom->loadXML($xml); - - $encoder->encode($dom); - - rewind($outputStream); - $output = stream_get_contents($outputStream); - // print("----"); - // print(var_export($output, true)); - // print("----"); - $this->assertEquals( - base64_decode('AwFqAEVcT0sDMgABUgN0YXNrc0lkAAFWR0wDY2xpZW50SWQyAAFdAAlgA3Rhc2syAAFKAzAAAUwDMjAyMC0xMS0wNFQwMDowMDowMC4wMDBaAAFNAzIwMjAtMTEtMDNUMjM6MDA6MDAuMDAwWgABAQEAAEdMA2NsaWVudElkMwABXQAJYAN0YXNrMwABSgMwAAFMAzIwMjAtMTEtMDRUMDA6MDA6MDAuMDAwWgABTQMyMDIwLTExLTAzVDIzOjAwOjAwLjAwMFoAAQEBAQEBAABVAzE2AAEB'), - $output - ); - } - - public function testEncodeFolderSync() - { - $outputStream = fopen("php://temp", 'r+'); - - $encoder = new Syncroton_Wbxml_Encoder($outputStream, 'UTF-8', 3); - - $xml = <<<EOF - <?xml version="1.0" encoding="utf-8"?> - <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> - <FolderSync xmlns="uri:FolderHierarchy" xmlns:Syncroton="uri:Syncroton" xmlns:Internal="uri:Internal"> - <Status>1</Status> - <SyncKey>1</SyncKey> - <Changes> - <Count>18</Count> - <Add> - <ServerId>2685b302b79f58d2753199545e3cb8be</ServerId> - <ParentId>0</ParentId> - <DisplayName>Test2</DisplayName> - <Type>13</Type> - </Add> - <Add> - <ServerId>9770b083c68e8584f396d15a116d6608</ServerId> - <ParentId>0</ParentId> - <DisplayName>DavidCalendar</DisplayName> - <Type>13</Type> - </Add> - <Add> - <ServerId>0f66388806743c514b8063bf0dc87486</ServerId> - <ParentId>0</ParentId> - <DisplayName>SergeyCalendar</DisplayName> - <Type>13</Type> - </Add> - <Add> - <ServerId>cca1b81c734abbcd669bea90d23e08ae</ServerId> - <ParentId>0</ParentId> - <DisplayName>Calendar</DisplayName> - <Type>8</Type> - </Add> - <Add> - <ServerId>ab1ddb4ef8e8f8fcc2c9f5a7f9062452</ServerId> - <ParentId>0</ParentId> - <DisplayName>PubCal</DisplayName> - <Type>13</Type> - </Add> - <Add> - <ServerId>d98bd8721371544ed095841ead941893</ServerId> - <ParentId>0</ParentId> - <DisplayName>(david) Test2</DisplayName> - <Type>13</Type> - </Add> - <Add> - <ServerId>9e7b9656ef61d4af2fb2fdcabe600079</ServerId> - <ParentId>0</ParentId> - <DisplayName>(david) DavidCalendar</DisplayName> - <Type>13</Type> - </Add> - <Add> - <ServerId>384cf2d877c39a622fdc2a16898052e2</ServerId> - <ParentId>0</ParentId> - <DisplayName>(david) Calendar</DisplayName> - <Type>13</Type> - </Add> - <Add> - <ServerId>Contacts::Syncroton</ServerId> - <ParentId>0</ParentId> - <DisplayName>Contacts</DisplayName> - <Type>9</Type> - </Add> - <Add> - <ServerId>1bb8c55fe84d52c6968db2571f7dc124</ServerId> - <ParentId>0</ParentId> - <DisplayName>Archive</DisplayName> - <Type>12</Type> - </Add> - <Add> - <ServerId>b51abe73e9e98fe200a4afe409050502</ServerId> - <ParentId>38b950ebd62cd9a66929c89615d0fc04</ParentId> - <DisplayName>Spam</DisplayName> - <Type>12</Type> - </Add> - <Add> - <ServerId>cf529c792fc87d1f207435b3921bb02e</ServerId> - <ParentId>0</ParentId> - <DisplayName>Sent</DisplayName> - <Type>5</Type> - </Add> - <Add> - <ServerId>715ed9ea29b8a5377a69c1f758037c65</ServerId> - <ParentId>0</ParentId> - <DisplayName>Spam</DisplayName> - <Type>12</Type> - </Add> - <Add> - <ServerId>db0d959a3aeb21757f8849a830947a7a</ServerId> - <ParentId>0</ParentId> - <DisplayName>Trash</DisplayName> - <Type>4</Type> - </Add> - <Add> - <ServerId>5ac9ec2e1a9d99e2e10cabe4abf26729</ServerId> - <ParentId>0</ParentId> - <DisplayName>Drafts</DisplayName> - <Type>3</Type> - </Add> - <Add> - <ServerId>38b950ebd62cd9a66929c89615d0fc04</ServerId> - <ParentId>0</ParentId> - <DisplayName>INBOX</DisplayName> - <Type>2</Type> - </Add> - <Add> - <ServerId>fc56f4c7ffe0aefa622db9f8d9186c4a</ServerId> - <ParentId>0</ParentId> - <DisplayName>Notes</DisplayName> - <Type>10</Type> - </Add>
View file
kolab-syncroton.dsc
Changed
@@ -2,7 +2,7 @@ Source: kolab-syncroton Binary: kolab-syncroton Architecture: all -Version: 1:2.4.2.10-1~kolab1 +Version: 1:2.4.2.11-1~kolab1 Maintainer: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> Uploaders: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> Homepage: http://www.kolab.org/
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
.