lib/ext
Aleksander Machniak
machniak at kolabsys.com
Mon Mar 10 13:02:16 CET 2014
lib/ext/Syncroton/Command/AutoDiscover.php | 126 ++++++++++++++++++++++++
lib/ext/Syncroton/Command/Options.php | 6 -
lib/ext/Syncroton/Command/Sync.php | 5
lib/ext/Syncroton/Command/Wbxml.php | 4
lib/ext/Syncroton/Data/AData.php | 68 +++++++-----
lib/ext/Syncroton/Model/Account.php | 76 ++++++++++++++
lib/ext/Syncroton/Model/EmailMeetingRequest.php | 98 ++++++++++++++++++
lib/ext/Syncroton/Model/EmailRecurrence.php | 74 ++++++++++++++
8 files changed, 421 insertions(+), 36 deletions(-)
New commits:
commit cb7725c6fc35ee5fcd48292db11584bb977a0c09
Author: Aleksander Machniak <machniak at kolabsys.com>
Date: Mon Mar 10 13:01:32 2014 +0100
Update Syncroton lib with fix for Bug #2664
diff --git a/lib/ext/Syncroton/Command/AutoDiscover.php b/lib/ext/Syncroton/Command/AutoDiscover.php
new file mode 100644
index 0000000..c2415a1
--- /dev/null
+++ b/lib/ext/Syncroton/Command/AutoDiscover.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Syncroton
+ *
+ * @package Syncroton
+ * @subpackage Command
+ * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3
+ * @copyright Copyright (c) 2013-2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author Lars Kneschke <l.kneschke at metaways.de>
+ */
+
+/**
+ * class to handle AutoDiscover command
+ *
+ * @package Syncroton
+ * @subpackage Command
+ */
+class Syncroton_Command_AutoDiscover implements Syncroton_Command_ICommand
+{
+ /**
+ * the domDocucment containing the xml request from the client
+ *
+ * @var DOMDocument
+ */
+ protected $requestBody;
+
+ protected $emailAddress;
+
+ public $mobileSyncUrl;
+
+ public $certEnrollUrl;
+
+ /**
+ * constructor of this class
+ *
+ * @param DOMDocument $_requestBody
+ * @param Syncroton_Model_IDevice $_device
+ * @param string $_policyKey
+ */
+ public function __construct($requestBody, Syncroton_Model_IDevice $device = null, $policyKey = null)
+ {
+ $this->requestBody = $requestBody;
+ }
+
+ /**
+ * process the incoming data
+ */
+ public function handle()
+ {
+ $xpath = new DomXPath($this->requestBody);
+ $xpath->registerNamespace('2006', 'http://schemas.microsoft.com/exchange/autodiscover/mobilesync/requestschema/2006');
+
+ $nodes = $xpath->query('//2006:Autodiscover/2006:Request/2006:EMailAddress');
+ if ($nodes->length === 0) {
+ throw new Syncroton_Exception();
+ }
+
+ $this->emailAddress = $nodes->item(0)->nodeValue;
+ }
+
+ /**
+ * create the response
+ *
+ * @return DOMDocument
+ */
+ public function getResponse()
+ {
+ // Creates an instance of the DOMImplementation class
+ $imp = new DOMImplementation();
+
+ // Creates a DOMDocument instance
+ $document = $imp->createDocument("http://schemas.microsoft.com/exchange/autodiscover/mobilesync/requestschema/2006", 'Autodiscover');
+ $document->xmlVersion = '1.0';
+ $document->encoding = 'UTF-8';
+ $document->formatOutput = false;
+
+ $response = $document->documentElement->appendChild($document->createElement('Response'));
+
+ $user = $response->appendChild($document->createElement('User'));
+ $user->appendChild($document->createElement('EMailAddress', $this->emailAddress));
+
+ $settings = $document->createElement('Settings');
+
+ if (!empty($this->mobileSyncUrl)) {
+ $server = $document->createElement('Server');
+
+ $server->appendChild($document->createElement('Type', 'MobileSync'));
+
+ $server->appendChild($document->createElement('Url', $this->mobileSyncUrl));
+ $server->appendChild($document->createElement('Name', $this->mobileSyncUrl));
+
+ $settings->appendChild($server);
+ }
+
+ if (!empty($this->certEnrollUrl)) {
+ $server = $document->createElement('Server');
+
+ $server->appendChild($document->createElement('Type', 'CertEnroll'));
+
+ $server->appendChild($document->createElement('Url', $this->certEnrollUrl));
+ $server->appendChild($document->createElement('Name'));
+ $server->appendChild($document->createElement('ServerData', 'CertEnrollTemplate'));
+
+ $settings->appendChild($server);
+ }
+
+ if ($settings->hasChildNodes()) {
+ $action = $response->appendChild($document->createElement('Action'));
+ $action->appendChild($settings);
+ }
+
+ return $document;
+ }
+
+ /**
+ * return headers of command
+ *
+ * @return array list of headers
+ */
+ public function getHeaders()
+ {
+ return array(
+ 'Content-Type' => 'text/xml;charset=utf-8'
+ );
+ }
+}
diff --git a/lib/ext/Syncroton/Command/Options.php b/lib/ext/Syncroton/Command/Options.php
index f126cc5..52f33ad 100644
--- a/lib/ext/Syncroton/Command/Options.php
+++ b/lib/ext/Syncroton/Command/Options.php
@@ -19,7 +19,7 @@ class Syncroton_Command_Options
{
/**
* this function generates the response for the client
- *
+ *
* @return void
*/
public function getHeaders()
@@ -28,7 +28,7 @@ class Syncroton_Command_Options
return array(
'MS-Server-ActiveSync' => '14.00.0536.000',
'MS-ASProtocolVersions' => '2.5,12.0,12.1,14.0,14.1',
- 'MS-ASProtocolCommands' => 'CreateCollection,DeleteCollection,FolderCreate,FolderDelete,FolderSync,FolderUpdate,GetAttachment,GetHierarchy,GetItemEstimate,ItemOperations,MeetingResponse,MoveCollection,MoveItems,Provision,ResolveRecipients,Ping,SendMail,Search,Settings,SmartForward,SmartReply,Sync,ValidateCert'
+ 'MS-ASProtocolCommands' => 'FolderCreate,FolderDelete,FolderSync,FolderUpdate,GetAttachment,GetItemEstimate,ItemOperations,MeetingResponse,MoveItems,Provision,ResolveRecipients,Ping,SendMail,Search,Settings,SmartForward,SmartReply,Sync,ValidateCert'
);
- }
+ }
}
diff --git a/lib/ext/Syncroton/Command/Sync.php b/lib/ext/Syncroton/Command/Sync.php
index 45ac895..8feb0ef 100644
--- a/lib/ext/Syncroton/Command/Sync.php
+++ b/lib/ext/Syncroton/Command/Sync.php
@@ -415,6 +415,9 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
$collections = $this->_outputDom->createElementNS('uri:AirSync', 'Collections');
$totalChanges = 0;
+
+ // Detect devices that do not support empty Sync reponse
+ $emptySyncSupported = !preg_match('/(meego|nokian800)/i', $this->_device->useragent);
// continue only if there are changes or no time is left
if ($this->_heartbeatInterval > 0) {
@@ -890,7 +893,7 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
if ($this->_logger instanceof Zend_Log)
$this->_logger->info(__METHOD__ . '::' . __LINE__ . " current synckey is ". $collectionData->syncState->counter);
- if ($collection->childNodes->length > 4 || $collectionData->syncState->counter != $collectionData->syncKey) {
+ if (!$emptySyncSupported || $collection->childNodes->length > 4 || $collectionData->syncState->counter != $collectionData->syncKey) {
$collections->appendChild($collection);
}
}
diff --git a/lib/ext/Syncroton/Command/Wbxml.php b/lib/ext/Syncroton/Command/Wbxml.php
index a252d25..feb20a8 100644
--- a/lib/ext/Syncroton/Command/Wbxml.php
+++ b/lib/ext/Syncroton/Command/Wbxml.php
@@ -61,14 +61,14 @@ abstract class Syncroton_Command_Wbxml implements Syncroton_Command_ICommand
* @var DOMDocument
*/
protected $_outputDom;
-
+
/**
* the domDocucment containing the xml request from the client
*
* @var DOMDocument
*/
protected $_requestBody;
-
+
/**
* the default namespace
*
diff --git a/lib/ext/Syncroton/Data/AData.php b/lib/ext/Syncroton/Data/AData.php
index 447d138..7867237 100644
--- a/lib/ext/Syncroton/Data/AData.php
+++ b/lib/ext/Syncroton/Data/AData.php
@@ -17,17 +17,12 @@
*/
abstract class Syncroton_Data_AData implements Syncroton_Data_IData
{
- const LONGID_DELIMITER = "\xe2\x87\x94"; # UTF8 â
+ const LONGID_DELIMITER = "\xe2\x87\x94"; # UTF-8 character â
/**
- * used by unit tests only to simulated added folders
+ * @var DateTime
*/
- public static $changedEntries = array();
-
- /**
- * used by unit tests only to simulated exhausted memory
- */
- public static $exhaustedEntries = array();
+ protected $_timeStamp;
/**
* the constructor
@@ -38,7 +33,7 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
public function __construct(Syncroton_Model_IDevice $_device, DateTime $_timeStamp)
{
$this->_device = $_device;
- $this->_timestamp = $_timeStamp;
+ $this->_timeStamp = $_timeStamp;
$this->_db = Syncroton_Registry::getDatabase();
$this->_tablePrefix = 'Syncroton_';
$this->_ownerId = '1234';
@@ -87,12 +82,12 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
$id = !empty($folder->serverId) ? $folder->serverId : sha1(mt_rand(). microtime());
$this->_db->insert($this->_tablePrefix . 'data_folder', array(
- 'id' => $id,
- 'type' => $folder->type,
+ 'id' => $id,
+ 'type' => $folder->type,
'name' => $folder->displayName,
'owner_id' => $this->_ownerId,
'parent_id' => $folder->parentId,
- 'creation_time' => $this->_timestamp->format('Y-m-d H:i:s')
+ 'creation_time' => $this->_timeStamp->format("Y-m-d H:i:s")
));
return $this->getFolder($id);
@@ -107,10 +102,11 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
$id = sha1(mt_rand(). microtime());
$this->_db->insert($this->_tablePrefix . 'data', array(
- 'id' => $id,
- 'class' => get_class($_entry),
- 'folder_id' => $_folderId,
- 'data' => serialize($_entry)
+ 'id' => $id,
+ 'class' => get_class($_entry),
+ 'folder_id' => $_folderId,
+ 'creation_time' => $this->_timeStamp->format("Y-m-d H:i:s"),
+ 'data' => serialize($_entry)
));
return $id;
@@ -187,11 +183,25 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
*/
public function getChangedEntries($_folderId, DateTime $_startTimeStamp, DateTime $_endTimeStamp = NULL, $filterType = NULL)
{
- if (!isset(Syncroton_Data_AData::$changedEntries[get_class($this)])) {
- return array();
- } else {
- return Syncroton_Data_AData::$changedEntries[get_class($this)];
+ $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
+
+ $select = $this->_db->select()
+ ->from($this->_tablePrefix . 'data', array('id'))
+ ->where('folder_id = ?', $_folderId)
+ ->where('last_modified_time > ?', $_startTimeStamp->format("Y-m-d H:i:s"));
+
+ if ($_endTimeStamp instanceof DateTime) {
+ $select->where('last_modified_time < ?', $_endTimeStamp->format("Y-m-d H:i:s"));
+ }
+
+ $ids = array();
+
+ $stmt = $this->_db->query($select);
+ while ($id = $stmt->fetchColumn()) {
+ $ids[] = $id;
}
+
+ return $ids;
}
/**
@@ -230,7 +240,7 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
/**
* @param Syncroton_Model_IFolder|string $_folderId
- * @param string $_filter
+ * @param string $_filter
* @return array
*/
public function getServerEntries($_folderId, $_filter)
@@ -281,15 +291,12 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
* @see Syncroton_Data_IData::getEntry()
*/
public function getEntry(Syncroton_Model_SyncCollection $collection, $serverId)
- {
- if (isset(self::$exhaustedEntries[get_class($this)]) && is_array(self::$exhaustedEntries[get_class($this)]) && in_array($serverId, self::$exhaustedEntries[get_class($this)])) {
- throw new Syncroton_Exception_MemoryExhausted('memory exchausted for ' . $serverId);
- }
+ {
$select = $this->_db->select()
->from($this->_tablePrefix . 'data', array('data'))
->where('id = ?', $serverId);
- $stmt = $this->_db->query($select);
+ $stmt = $this->_db->query($select);
$entry = $stmt->fetchColumn();
if ($entry === false) {
@@ -328,10 +335,11 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
* @see Syncroton_Data_IData::updateEntry()
*/
public function updateEntry($_folderId, $_serverId, Syncroton_Model_IEntry $_entry)
- {
+ {
$this->_db->update($this->_tablePrefix . 'data', array(
- 'folder_id' => $_folderId,
- 'data' => serialize($_entry)
+ 'folder_id' => $_folderId,
+ 'last_modified_time' => $this->_timeStamp->format("Y-m-d H:i:s"),
+ 'data' => serialize($_entry)
), array(
'id = ?' => $_serverId
));
@@ -346,7 +354,7 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
$this->_db->update($this->_tablePrefix . 'data_folder', array(
'name' => $folder->displayName,
'parent_id' => $folder->parentId,
- 'last_modified_time' => $this->_timestamp->format('Y-m-d H:i:s')
+ 'last_modified_time' => $this->_timeStamp->format("Y-m-d H:i:s"),
), array(
'id = ?' => $folder->serverId,
'owner_id = ?' => $this->_ownerId
diff --git a/lib/ext/Syncroton/Model/Account.php b/lib/ext/Syncroton/Model/Account.php
new file mode 100644
index 0000000..0ed9d65
--- /dev/null
+++ b/lib/ext/Syncroton/Model/Account.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Syncroton
+ *
+ * @package Syncroton
+ * @subpackage Model
+ * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3
+ * @copyright Copyright (c) 2012-2014 Kolab Systems AG
+ * @author Aleksander Machniak <machniak at kolabsys.com>
+ */
+
+/**
+ * class to handle (Settings/UserInformation/Get/Accounts/) Account element
+ *
+ * @package Syncroton
+ * @subpackage Model
+ * @property string accountId
+ * @property string accountName
+ * @property string userDisplayName
+ * @property bool sendDisabled
+ * @property string primaryAddress
+ * @property array addresses
+ */
+class Syncroton_Model_Account extends Syncroton_Model_AXMLEntry
+{
+ protected $_xmlBaseElement = 'Account';
+
+ protected $_properties = array(
+ 'Settings' => array(
+ 'accountId' => array('type' => 'string'),
+ 'accountName' => array('type' => 'string'),
+ 'userDisplayName' => array('type' => 'string'),
+ 'sendDisabled' => array('type' => 'number'),
+// 'emailAddresses' => array('type' => 'container'),
+ ),
+ 'Internal' => array(
+ 'primaryAddress' => array('type' => 'string'),
+ 'addresses' => array('type' => 'array'),
+ ),
+ );
+
+ /**
+ * (non-PHPdoc)
+ * @see Syncroton_Model_AXMLEntry::appendXML()
+ */
+ public function appendXML(DOMElement $_domParent, Syncroton_Model_IDevice $device)
+ {
+ parent::appendXML($_domParent, $device);
+
+ $nameSpace = 'uri:Settings';
+ $document = $_domParent->ownerDocument;
+
+ // handle EmailAddresses element
+ $list = $document->createElementNS($nameSpace, 'EmailAddresses');
+
+ if (!empty($this->_elements['primaryAddress'])) {
+ $element = $document->createElementNS($nameSpace, 'PrimarySmtpAddress', $this->_elements['primaryAddress']);
+ $list->appendChild($element);
+ }
+
+ foreach ((array)$this->_elements['addresses'] as $address) {
+ // skip empty values
+ if (empty($address)) {
+ continue;
+ }
+
+ $element = $document->createElementNS($nameSpace, 'SMTPAddress', $address);
+ $list->appendChild($element);
+ }
+
+ if ($list->hasChildNodes()) {
+ $_domParent->appendChild($list);
+ }
+ }
+
+}
diff --git a/lib/ext/Syncroton/Model/EmailMeetingRequest.php b/lib/ext/Syncroton/Model/EmailMeetingRequest.php
new file mode 100644
index 0000000..2786be4
--- /dev/null
+++ b/lib/ext/Syncroton/Model/EmailMeetingRequest.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Syncroton
+ *
+ * @package Syncroton
+ * @subpackage Model
+ * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3
+ * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author Lars Kneschke <l.kneschke at metaways.de>
+ */
+
+/**
+ * class to handle Email:MeetingRequest
+ *
+ * @package Syncroton
+ * @subpackage Model
+ * @property bool AllDayEvent
+ * @property int BusyStatus
+ * @property int DisallowNewTimeProposal
+ * @property DateTime DtStamp
+ * @property DateTime EndTime
+ * @property string GlobalObjId
+ * @property int InstanceType
+ * @property int MeetingMessageType
+ * @property string Organizer
+ * @property string RecurrenceId
+ * @property array Recurrences
+ * @property int Reminder
+ * @property int ResponseRequested
+ * @property int Sensitivity
+ * @property DateTime StartTime
+ * @property string Timezone
+ */
+class Syncroton_Model_EmailMeetingRequest extends Syncroton_Model_AXMLEntry
+{
+ /**
+ * busy status constants
+ */
+ const BUSY_STATUS_FREE = 0;
+ const BUSY_STATUS_TENATTIVE = 1;
+ const BUSY_STATUS_BUSY = 2;
+ const BUSY_STATUS_OUT = 3;
+
+ /**
+ * sensitivity constants
+ */
+ const SENSITIVITY_NORMAL = 0;
+ const SENSITIVITY_PERSONAL = 1;
+ const SENSITIVITY_PRIVATE = 2;
+ const SENSITIVITY_CONFIDENTIAL = 3;
+
+ /**
+ * instanceType constants
+ */
+ const TYPE_NORMAL = 0;
+ const TYPE_RECURRING_MASTER = 1;
+ const TYPE_RECURRING_SINGLE = 2;
+ const TYPE_RECURRING_EXCEPTION = 3;
+
+ /**
+ * messageType constants
+ */
+ const MESSAGE_TYPE_NORMAL = 0;
+ const MESSAGE_TYPE_REQUEST = 1;
+ const MESSAGE_TYPE_FULL_UPDATE = 2;
+ const MESSAGE_TYPE_INFO_UPDATE = 3;
+ const MESSAGE_TYPE_OUTDATED = 4;
+ const MESSAGE_TYPE_COPY = 5;
+ const MESSAGE_TYPE_DELEGATED = 6;
+
+ protected $_dateTimeFormat = "Ymd\THis\Z";
+
+ protected $_xmlBaseElement = 'MeetingRequest';
+
+ protected $_properties = array(
+ 'Email' => array(
+ 'allDayEvent' => array('type' => 'number'),
+ 'busyStatus' => array('type' => 'number'),
+ 'disallowNewTimeProposal' => array('type' => 'number'),
+ 'dtStamp' => array('type' => 'datetime'),
+ 'endTime' => array('type' => 'datetime'),
+ 'globalObjId' => array('type' => 'string'),
+ 'instanceType' => array('type' => 'datetime'),
+ 'location' => array('type' => 'string'),
+ 'organizer' => array('type' => 'string'), //e-mail address
+ 'recurrenceId' => array('type' => 'datetime'),
+ 'recurrences' => array('type' => 'container'),
+ 'reminder' => array('type' => 'number'),
+ 'responseRequested' => array('type' => 'number'),
+ 'sensitivity' => array('type' => 'number'),
+ 'startTime' => array('type' => 'datetime'),
+ 'timeZone' => array('type' => 'timezone'),
+ ),
+ 'Email2' => array(
+ 'meetingMessageType' => array('type' => 'number'),
+ ),
+ );
+}
diff --git a/lib/ext/Syncroton/Model/EmailRecurrence.php b/lib/ext/Syncroton/Model/EmailRecurrence.php
new file mode 100644
index 0000000..b90cf19
--- /dev/null
+++ b/lib/ext/Syncroton/Model/EmailRecurrence.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Syncroton
+ *
+ * @package Syncroton
+ * @subpackage Model
+ * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3
+ * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author Lars Kneschke <l.kneschke at metaways.de>
+ */
+
+/**
+ * class to handle Email::Recurrence
+ *
+ * @package Syncroton
+ * @subpackage Model
+ * @property int CalendarType
+ * @property int DayOfMonth
+ * @property int DayOfWeek
+ * @property int FirstDayOfWeek
+ * @property int Interval
+ * @property int IsLeapMonth
+ * @property int MonthOfYear
+ * @property int Occurrences
+ * @property int Type
+ * @property DateTime Until
+ * @property int WeekOfMonth
+ */
+
+class Syncroton_Model_EmailRecurrence extends Syncroton_Model_AXMLEntry
+{
+ protected $_xmlBaseElement = 'Recurrence';
+
+ /**
+ * recur types
+ */
+ const TYPE_DAILY = 0; // Recurs daily
+ const TYPE_WEEKLY = 1; // Recurs weekly
+ const TYPE_MONTHLY = 3; // Recurs monthly
+ const TYPE_MONTHLY_DAYN = 2; // Recurs monthly on the nth day
+ const TYPE_YEARLY = 5; // Recurs yearly on the nth day of the nth month each year
+ const TYPE_YEARLY_DAYN = 6; // Recurs yearly on the nth day of the week of the nth month
+
+ /**
+ * day of week constants
+ */
+ const RECUR_DOW_SUNDAY = 1;
+ const RECUR_DOW_MONDAY = 2;
+ const RECUR_DOW_TUESDAY = 4;
+ const RECUR_DOW_WEDNESDAY = 8;
+ const RECUR_DOW_THURSDAY = 16;
+ const RECUR_DOW_FRIDAY = 32;
+ const RECUR_DOW_SATURDAY = 64;
+
+ protected $_dateTimeFormat = "Ymd\THis\Z";
+
+ protected $_properties = array(
+ 'Email' => array(
+ 'dayOfMonth' => array('type' => 'number'),
+ 'dayOfWeek' => array('type' => 'number'),
+ 'interval' => array('type' => 'number'), // 1 or 2
+ 'monthOfYear' => array('type' => 'number'),
+ 'occurrences' => array('type' => 'number'),
+ 'type' => array('type' => 'number'),
+ 'until' => array('type' => 'datetime'),
+ 'weekOfMonth' => array('type' => 'number'),
+ ),
+ 'Email2' => array(
+ 'calendarType' => array('type' => 'number'),
+ 'firstDayOfWeek' => array('type' => 'number'),
+ 'isLeapMonth' => array('type' => 'number'),
+ )
+ );
+}
More information about the commits
mailing list