7 commits - lib/ext lib/kolab_sync_backend_device.php lib/kolab_sync_backend.php lib/kolab_sync_data_calendar.php lib/kolab_sync_data_contacts.php lib/kolab_sync_data_email.php lib/kolab_sync_data.php lib/kolab_sync_data_tasks.php lib/kolab_sync.php
Aleksander Machniak
machniak at kolabsys.com
Mon Sep 3 12:44:10 CEST 2012
lib/ext/Syncroton/Command/GetAttachment.php | 2
lib/ext/Syncroton/Command/Wbxml.php | 23 +++--
lib/ext/Syncroton/Model/AEntry.php | 28 +++++-
lib/ext/Syncroton/Model/Email.php | 16 +--
lib/ext/Syncroton/Model/Event.php | 45 ++++++++++
lib/ext/Syncroton/Model/EventException.php | 2
lib/ext/Syncroton/Model/StoreRequest.php | 18 +++-
lib/ext/Syncroton/Server.php | 10 --
lib/ext/Syncroton/Wbxml/Abstract.php | 29 ++++++
lib/ext/Syncroton/Wbxml/Encoder.php | 21 +++-
lib/kolab_sync.php | 15 +++
lib/kolab_sync_backend.php | 44 ++++++++--
lib/kolab_sync_backend_device.php | 5 -
lib/kolab_sync_data.php | 9 --
lib/kolab_sync_data_calendar.php | 2
lib/kolab_sync_data_contacts.php | 2
lib/kolab_sync_data_email.php | 121 +++++++++++++++++++++-------
lib/kolab_sync_data_tasks.php | 2
18 files changed, 305 insertions(+), 89 deletions(-)
New commits:
commit 43cd411c0028193c704ca08c75c4bd873f055797
Author: Aleksander Machniak <alec at alec.pl>
Date: Mon Sep 3 12:43:37 2012 +0200
Fixed email folders handling, fixed some minor issues
diff --git a/lib/kolab_sync_data_calendar.php b/lib/kolab_sync_data_calendar.php
index 1c756d9..d441fde 100644
--- a/lib/kolab_sync_data_calendar.php
+++ b/lib/kolab_sync_data_calendar.php
@@ -227,7 +227,7 @@ class kolab_sync_data_calendar extends kolab_sync_data
break;
case 'description':
- $value = $this->setBody($value, Syncroton_Model_EmailBody::TYPE_PLAINTEXT);
+ $value = $this->setBody($value);
break;
}
diff --git a/lib/kolab_sync_data_contacts.php b/lib/kolab_sync_data_contacts.php
index 5a71da4..7a60c0e 100644
--- a/lib/kolab_sync_data_contacts.php
+++ b/lib/kolab_sync_data_contacts.php
@@ -156,7 +156,7 @@ class kolab_sync_data_contacts extends kolab_sync_data
break;
case 'notes':
- $value = $this->setBody($value, Syncroton_Model_EmailBody::TYPE_PLAINTEXT);
+ $value = $this->setBody($value);
break;
}
diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
index 3e97dae..22207a0 100644
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -51,6 +51,19 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
);
/**
+ * Special folder type/name map
+ *
+ * @var array
+ */
+ protected $folder_types = array(
+ 2 => 'Inbox',
+ 3 => 'Drafts',
+ 4 => 'Deleted Items',
+ 5 => 'Sent Items',
+ 6 => 'Outbox',
+ );
+
+ /**
* Kolab object type
*
* @var string
@@ -388,21 +401,72 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
}
/**
- * Returns default folder for current class type.
- */
- protected function getDefaultFolder()
+ * Return list of supported folders for this backend
+ *
+ * @return array
+ */
+ public function getAllFolders()
{
- // There's always INBOX
- $real_id = $this->backend->folder_id('INBOX', 'mail.inbox');
- $folder_id = $this->defaultRootFolder;
+ $list = $this->backend->folders_list($this->device->deviceid, $this->modelName);
+
+ // device doesn't support multiple folders
+ if (!in_array(strtolower($this->device->devicetype), array('iphone', 'ipad', 'thundertine', 'windowsphone'))) {
+ // We'll return max. one folder of supported type
+ $result = array();
+ $types = $this->folder_types;
+
+ foreach ($list as $idx => $folder) {
+ if (isset($types[$folder['type']])) {
+ $folder_id = $types[$folder['type']];
+ $result[$folder_id] = array(
+ 'displayName' => $folder_id,
+ 'serverId' => $folder_id,
+ 'parentId' => 0,
+ 'type' => $folder['type'],
+ );
+ unset($types[$folder['type']]);
+ }
+ }
- return array(
- 'displayName' => 'Inbox',
- 'realid' => $real_id,
- 'serverId' => $folder_id,
- 'parentId' => 0,
- 'type' => $this->defaultFolderType,
- );
+ $list = $result;
+ }
+
+ foreach ($list as $idx => $folder) {
+ $list[$idx] = new Syncroton_Model_Folder($folder);
+ }
+
+ return $list;
+ }
+
+ /**
+ * Return list of folders for specified folder ID
+ *
+ * @return array Folder identifiers list
+ */
+ protected function extractFolders($folder_id)
+ {
+ $list = $this->backend->folders_list($this->device->deviceid, $this->modelName);
+ $result = array();
+
+ // device supports multiple folders?
+ if (in_array(strtolower($this->device->devicetype), array('iphone', 'ipad', 'thundertine', 'windowsphone'))) {
+ if ($list[$folder_id]) {
+ $result[] = $folder_id;
+ }
+ }
+ else if ($type = array_search($folder_id, $this->folder_types)) {
+ foreach ($list as $id => $folder) {
+ if ($folder['type'] == $type || ($folder_id == 'Inbox' && $folder['type'] == 12)) {
+ $result[] = $id;
+ }
+ }
+ }
+
+ if (empty($result)) {
+ throw new Syncroton_Exception_NotFound('Folder not found');
+ }
+
+ return $result;
}
/**
@@ -418,7 +482,8 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
public function moveItem($srcFolderId, $serverId, $dstFolderId)
{
$msg = $this->parseMessageId($serverId);
- $dstname = $this->backend->folder_id2name($dstFolderId, $this->device->deviceid);
+ $dest = $this->extractFolders($dstFolderId);
+ $dstname = $this->backend->folder_id2name(array_shift($dest), $this->device->deviceid);
if (empty($msg)) {
throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_SOURCE);
@@ -652,14 +717,7 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
*/
protected function searchEntries($folderid, $filter = array(), $result_type = self::RESULT_UID)
{
- if ($folderid == $this->defaultRootFolder) {
- $folders = $this->backend->folders_list($this->device->deviceid, $this->modelName);
- $folders = array_keys($folders);
- }
- else {
- $folders = array($folderid);
- }
-
+ $folders = $this->extractFolders($folderid);
$filter_str = 'ALL UNDELETED';
// convert filter into one IMAP search string
@@ -799,7 +857,9 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
}
if (!empty($query['and']['collections'])) {
- $folders[] = $query['and']['collections'];
+ foreach ($query['and']['collections'] as $collection) {
+ $folders = array_merge($folders, $this->extractFolders($collection));
+ }
}
if (!empty($query['and']['greaterThan'])
diff --git a/lib/kolab_sync_data_tasks.php b/lib/kolab_sync_data_tasks.php
index 318dc5b..d94caf0 100644
--- a/lib/kolab_sync_data_tasks.php
+++ b/lib/kolab_sync_data_tasks.php
@@ -188,7 +188,7 @@ class kolab_sync_data_tasks extends kolab_sync_data
break;
case 'description':
- $value = $this->getBody($value);
+ $value = $this->getBody($value, Syncroton_Model_EmailBody::TYPE_PLAINTEXT);
// If description isn't specified keep old description
if ($value === null) {
continue 2;
commit 748290b81482bbd540de25a1f6c2584179ff1ab3
Author: Aleksander Machniak <alec at alec.pl>
Date: Mon Sep 3 09:25:42 2012 +0200
Fix searching email by Received date
diff --git a/lib/ext/Syncroton/Model/StoreRequest.php b/lib/ext/Syncroton/Model/StoreRequest.php
index e78f41c..170c3cb 100644
--- a/lib/ext/Syncroton/Model/StoreRequest.php
+++ b/lib/ext/Syncroton/Model/StoreRequest.php
@@ -88,24 +88,34 @@ class Syncroton_Model_StoreRequest
if (isset($xmlStore->Query->And->ConversationId)) {
$this->_store['query']['and']['conversationId'] = (string) $xmlStore->Query->And->ConversationId;
}
+
+ // Protocol specification defines Value as string and DateReceived as datetime, but
+ // PocketPC device I tested sends XML as follows:
+ // <GreaterThan>
+ // <DateReceived>
+ // <Value>2012-08-02T16:54:11.000Z</Value>
+ // </GreaterThan>
+
if (isset($xmlStore->Query->And->GreaterThan)) {
if (isset($xmlStore->Query->And->GreaterThan->Value)) {
- $this->_store['query']['and']['greaterThan']['value'] = (string) $xmlStore->Query->And->GreaterThan->Value;
+ $value = (string) $xmlStore->Query->And->GreaterThan->Value;
+ $this->_store['query']['and']['greaterThan']['value'] = new DateTime($value, new DateTimeZone('UTC'));
}
$email = $xmlStore->Query->And->GreaterThan->children('uri:Email');
if (isset($email->DateReceived)) {
- $this->_store['query']['and']['greaterThan']['dateReceived'] = new DateTime((string) $email->DateReceived, new DateTimeZone('UTC'));
+ $this->_store['query']['and']['greaterThan']['dateReceived'] = true;
}
}
if (isset($xmlStore->Query->And->LessThan)) {
if (isset($xmlStore->Query->And->LessThan->Value)) {
- $this->_store['query']['and']['lessThan']['value'] = (string) $xmlStore->Query->And->LessThan->Value;
+ $value = (string) $xmlStore->Query->And->LessThan->Value;
+ $this->_store['query']['and']['lessThan']['value'] = new DateTime($value, new DateTimeZone('UTC'));
}
$email = $xmlStore->Query->And->LessThan->children('uri:Email');
if (isset($email->DateReceived)) {
- $this->_store['query']['and']['leasThan']['dateReceived'] = new DateTime((string) $email->DateReceived, new DateTimeZone('UTC'));
+ $this->_store['query']['and']['leasThan']['dateReceived'] = true;
}
}
diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
index f36c42d..3e97dae 100644
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -806,21 +806,20 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
&& !empty($query['and']['greaterThan']['dateReceived'])
&& !empty($query['and']['greaterThan']['value'])
) {
- // @TODO: date format ?
- $search_str .= ' SINCE ' . trim($query['and']['greaterThan']['value']);
+ $search_str .= ' SINCE ' . $query['and']['greaterThan']['value']->format('d-M-Y');
}
if (!empty($query['and']['lessThan'])
&& !empty($query['and']['lessThan']['dateReceived'])
&& !empty($query['and']['lessThan']['value'])
) {
- // @TODO: date format ?
- $search_str .= ' BEFORE ' . trim($query['and']['lessThan']['value']);
+ $search_str .= ' BEFORE ' . $query['and']['lessThan']['value']->format('d-M-Y');
}
}
if ($search !== null) {
// @FIXME: should we use TEXT/BODY search?
+ // ActiveSync protocol specification says "indexed fields"
$search_keys = array('SUBJECT', 'TO', 'FROM', 'CC');
$search_str .= str_repeat(' OR', count($search_keys)-1);
foreach ($search_keys as $key) {
commit a461edbb8f456f3252cf1f9b416f23fb1f8ea7cd
Author: Aleksander Machniak <alec at alec.pl>
Date: Sun Sep 2 19:53:01 2012 +0200
Syncroton update (with byteArray support)
diff --git a/lib/ext/Syncroton/Command/GetAttachment.php b/lib/ext/Syncroton/Command/GetAttachment.php
index 5bf745d..28c0deb 100644
--- a/lib/ext/Syncroton/Command/GetAttachment.php
+++ b/lib/ext/Syncroton/Command/GetAttachment.php
@@ -23,6 +23,8 @@ class Syncroton_Command_GetAttachment extends Syncroton_Command_Wbxml
*/
protected $_attachmentName;
+ protected $_skipValidatePolicyKey = true;
+
/**
* process the XML file and add, change, delete or fetches data
*
diff --git a/lib/ext/Syncroton/Command/Wbxml.php b/lib/ext/Syncroton/Command/Wbxml.php
index 537900a..f87a71e 100644
--- a/lib/ext/Syncroton/Command/Wbxml.php
+++ b/lib/ext/Syncroton/Command/Wbxml.php
@@ -145,16 +145,19 @@ abstract class Syncroton_Command_Wbxml implements Syncroton_Command_ICommand
if ($this->_logger instanceof Zend_Log)
$this->_logger->debug(__METHOD__ . '::' . __LINE__ . " sync timestamp: " . $this->_syncTimeStamp->format('Y-m-d H:i:s'));
- // Creates an instance of the DOMImplementation class
- $imp = new DOMImplementation();
-
- // Creates a DOMDocumentType instance
- $dtd = $imp->createDocumentType('AirSync', "-//AIRSYNC//DTD AirSync//EN", "http://www.microsoft.com/");
-
- // Creates a DOMDocument instance
- $this->_outputDom = $imp->createDocument($this->_defaultNameSpace, $this->_documentElement, $dtd);
- $this->_outputDom->formatOutput = false;
- $this->_outputDom->encoding = 'utf-8';
+ if (isset($this->_defaultNameSpace) && isset($this->_documentElement)) {
+ // Creates an instance of the DOMImplementation class
+ $imp = new DOMImplementation();
+
+ // Creates a DOMDocumentType instance
+ $dtd = $imp->createDocumentType('AirSync', "-//AIRSYNC//DTD AirSync//EN", "http://www.microsoft.com/");
+
+ // Creates a DOMDocument instance
+ $this->_outputDom = $imp->createDocument($this->_defaultNameSpace, $this->_documentElement, $dtd);
+ $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Syncroton', 'uri:Syncroton');
+ $this->_outputDom->formatOutput = false;
+ $this->_outputDom->encoding = 'utf-8';
+ }
if ($this->_skipValidatePolicyKey != true) {
if (!empty($this->_device->policyId)) {
diff --git a/lib/ext/Syncroton/Model/AEntry.php b/lib/ext/Syncroton/Model/AEntry.php
index 79cfb9a..21e2e3c 100644
--- a/lib/ext/Syncroton/Model/AEntry.php
+++ b/lib/ext/Syncroton/Model/AEntry.php
@@ -57,11 +57,6 @@ abstract class Syncroton_Model_AEntry implements Syncroton_Model_IEntry, Iterato
$nameSpace = 'uri:' . $nameSpace;
- // strip off any non printable control characters
- if (!ctype_print($value)) {
- #$value = $this->removeControlChars($value);
- }
-
if (isset($elementProperties['childElement'])) {
$element = $_domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementName));
foreach($value as $subValue) {
@@ -172,7 +167,7 @@ abstract class Syncroton_Model_AEntry implements Syncroton_Model_IEntry, Iterato
}
}
- protected function _appendXMLElement($element, $elementProperties, $value)
+ protected function _appendXMLElement(DOMElement $element, $elementProperties, $value)
{
if ($value instanceof Syncroton_Model_IEntry) {
$value->appendXML($element);
@@ -189,9 +184,30 @@ abstract class Syncroton_Model_AEntry implements Syncroton_Model_IEntry, Iterato
}
}
+ // strip off any non printable control characters
+ if (!ctype_print($value)) {
+ $value = $this->_removeControlChars($value);
+ }
+
+ if ($elementProperties['type'] == 'byteArray') {
+ $element->setAttributeNS('uri:Syncroton', 'Syncroton:encoding', 'oqaque');
+ }
+
$element->appendChild($element->ownerDocument->createTextNode($value));
}
}
+
+ /**
+ * removed control chars from string which are not allowd in XML values
+ *
+ * @param string|array $_dirty
+ * @return string
+ */
+ protected function _removeControlChars($dirty)
+ {
+ return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', null, $dirty);
+ }
+
/**
*
diff --git a/lib/ext/Syncroton/Model/Email.php b/lib/ext/Syncroton/Model/Email.php
index 2ef7da2..1e74a70 100644
--- a/lib/ext/Syncroton/Model/Email.php
+++ b/lib/ext/Syncroton/Model/Email.php
@@ -9,16 +9,16 @@
*/
/**
- * class to handle ActiveSync event
+ * class to handle ActiveSync email
*
* @package Model
- * @property array Attachments
- * @property string ContentType
- * @property Syncroton_Model_EmailFlag Flag
- * @property Syncroton_Model_EmailBody Body
- * @property array Cc
- * @property array To
- * @property int Read
+ * @property array attachments
+ * @property string contentType
+ * @property array flag
+ * @property Syncroton_Model_EmailBody body
+ * @property array cc
+ * @property array to
+ * @property int read
*/
class Syncroton_Model_Email extends Syncroton_Model_AEntry
{
diff --git a/lib/ext/Syncroton/Model/Event.php b/lib/ext/Syncroton/Model/Event.php
index 02307e0..cf0de60 100644
--- a/lib/ext/Syncroton/Model/Event.php
+++ b/lib/ext/Syncroton/Model/Event.php
@@ -64,4 +64,49 @@ class Syncroton_Model_Event extends Syncroton_Model_AEntry
'uID' => array('type' => 'string'),
)
);
+
+ public function setFromArray(array $properties)
+ {
+ parent::setFromArray($properties);
+
+ $this->_copyFieldsFromParent();
+ }
+
+ /**
+ * set properties from SimpleXMLElement object
+ *
+ * @param SimpleXMLElement $xmlCollection
+ * @throws InvalidArgumentException
+ */
+ public function setFromSimpleXMLElement(SimpleXMLElement $properties)
+ {
+ parent::setFromSimpleXMLElement($properties);
+
+ $this->_copyFieldsFromParent();
+ }
+
+ /**
+ * copy some fileds of the main event to the exception if they are missing
+ * these fields can be left out, if they have the same value in the main event
+ * and the exception
+ */
+ protected function _copyFieldsFromParent()
+ {
+ if (isset($this->_elements['exceptions']) && is_array($this->_elements['exceptions'])) {
+ foreach ($this->_elements['exceptions'] as $exception) {
+ // no need to update deleted exceptions
+ if ($exception->deleted == 1) {
+ continue;
+ }
+
+ $parentFields = array('allDayEvent', 'attendees', 'busyStatus', 'meetingStatus', 'sensitivity', 'subject');
+
+ foreach ($parentFields as $field) {
+ if (!isset($exception->$field) && isset($this->_elements[$field])) {
+ $exception->$field = $this->_elements[$field];
+ }
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/lib/ext/Syncroton/Model/EventException.php b/lib/ext/Syncroton/Model/EventException.php
index 400c397..7d7224b 100644
--- a/lib/ext/Syncroton/Model/EventException.php
+++ b/lib/ext/Syncroton/Model/EventException.php
@@ -20,7 +20,7 @@
* @property int windowSize
*/
-class Syncroton_Model_EventException extends Syncroton_Model_Event
+class Syncroton_Model_EventException extends Syncroton_Model_AEntry
{
protected $_xmlBaseElement = 'Exception';
diff --git a/lib/ext/Syncroton/Server.php b/lib/ext/Syncroton/Server.php
index a1f4f55..2a9555a 100644
--- a/lib/ext/Syncroton/Server.php
+++ b/lib/ext/Syncroton/Server.php
@@ -109,9 +109,7 @@ class Syncroton_Server
$requestBody = $decoder->decode();
if ($this->_logger instanceof Zend_Log) {
$requestBody->formatOutput = true;
- // remove not important XML information
- $request_str = preg_replace('|(</*)([a-z0-9]+:)?([a-z0-9]+)[^>]*>|i', '\\1\\3>', $requestBody->saveXML());
- $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " xml request:\n" . trim($request_str));
+ $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " xml request:\n" . $requestBody->saveXML());
}
} catch(Syncroton_Wbxml_Exception_UnexpectedEndOfFile $e) {
$requestBody = NULL;
@@ -158,7 +156,7 @@ class Syncroton_Server
if ($this->_logger instanceof Zend_Log)
$this->_logger->crit(__METHOD__ . '::' . __LINE__ . " exception message: " . $e->getMessage());
if ($this->_logger instanceof Zend_Log)
- $this->_logger->info(__METHOD__ . '::' . __LINE__ . " " . $e->getTraceAsString());
+ $this->_logger->crit(__METHOD__ . '::' . __LINE__ . " " . $e->getTraceAsString());
header("HTTP/1.1 500 Internal server error");
@@ -168,9 +166,7 @@ class Syncroton_Server
if ($response instanceof DOMDocument) {
if ($this->_logger instanceof Zend_Log) {
$response->formatOutput = true;
- // remove not important XML information
- $response_str = preg_replace('|(</*)([a-z0-9]+:)?([a-z0-9]+)[^>]*>|i', '\\1\\3>', $response->saveXML());
- $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " xml response:\n" . trim($response_str));
+ $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " xml response:\n" . $response->saveXML());
}
$outputStream = fopen("php://temp", 'r+');
diff --git a/lib/ext/Syncroton/Wbxml/Abstract.php b/lib/ext/Syncroton/Wbxml/Abstract.php
index e1d0c36..6c86806 100644
--- a/lib/ext/Syncroton/Wbxml/Abstract.php
+++ b/lib/ext/Syncroton/Wbxml/Abstract.php
@@ -202,8 +202,37 @@ abstract class Syncroton_Wbxml_Abstract
fwrite($this->_stream, $_string);
}
+ /**
+ * write opaque string to stream
+ *
+ * @param string|resource $_string
+ * @throws Syncroton_Wbxml_Exception
+ */
+ protected function _writeOpaqueString($_string)
+ {
+ if (is_resource($_string)) {
+ $stream = $_string;
+ } else {
+ $stream = fopen("php://temp", 'r+');
+ fwrite($stream, $_string);
+ }
+ $length = ftell($stream);
+ rewind($stream);
+
+ $this->_writeByte(Syncroton_Wbxml_Abstract::OPAQUE);
+ $this->_writeMultibyteUInt($length);
+ $writenBytes = stream_copy_to_stream($stream, $this->_stream);
+
+ if($writenBytes !== $length) {
+ throw new Syncroton_Wbxml_Exception('blow');
+ }
+
+ fclose($stream);
+ }
+
protected function _writeTerminatedString($_string)
{
+ $this->_writeByte(Syncroton_Wbxml_Abstract::STR_I);
fwrite($this->_stream, $_string);
fwrite($this->_stream, chr(0));
}
diff --git a/lib/ext/Syncroton/Wbxml/Encoder.php b/lib/ext/Syncroton/Wbxml/Encoder.php
index 93ee8f7..667cfec 100644
--- a/lib/ext/Syncroton/Wbxml/Encoder.php
+++ b/lib/ext/Syncroton/Wbxml/Encoder.php
@@ -159,8 +159,7 @@ class Syncroton_Wbxml_Encoder extends Syncroton_Wbxml_Abstract
xml_set_character_data_handler($parser, '_handleCharacters');
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
- $xmlString = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', null, $_dom->saveXML());
- if (!xml_parse($parser, $xmlString)) {
+ if (!xml_parse($parser, $_dom->saveXML())) {
#file_put_contents(tempnam(sys_get_temp_dir(), "xmlerrors"), $_dom->saveXML());
throw new Syncroton_Wbxml_Exception(sprintf('XML error: %s at line %d',
xml_error_string(xml_get_error_code($parser)),
@@ -181,10 +180,11 @@ class Syncroton_Wbxml_Encoder extends Syncroton_Wbxml_Abstract
protected function _handleStartTag($_parser, $_tag, $_attributes)
{
$this->_level++;
+ $this->_currentTagData = null;
// write data for previous tag happens whith <tag1><tag2>
if($this->_currentTag !== NULL) {
- $this->_writeTag($this->_currentTag, $this->_attributes, true, $this->_currentTagData);
+ $this->_writeTag($this->_currentTag, $this->_attributes, true);
}
list($nameSpace, $this->_currentTag) = explode(';', $_tag);
@@ -194,6 +194,7 @@ class Syncroton_Wbxml_Encoder extends Syncroton_Wbxml_Abstract
}
$this->_attributes = $_attributes;
+
}
/**
@@ -291,6 +292,13 @@ class Syncroton_Wbxml_Encoder extends Syncroton_Wbxml_Abstract
// handle the tag
$identity = $this->_codePage->getIdentity($_tag);
+ if (is_array($_attributes) && isset($_attributes['Syncroton:encoding'])) {
+ $encoding = 'opaque';
+ unset($_attributes['Syncroton:encoding']);
+ } else {
+ $encoding = 'termstring';
+ }
+
if(!empty($_attributes)) {
$identity |= 0x80;
}
@@ -303,8 +311,11 @@ class Syncroton_Wbxml_Encoder extends Syncroton_Wbxml_Abstract
// handle the data
if($_data !== NULL) {
- $this->_writeByte(Syncroton_Wbxml_Abstract::STR_I);
- $this->_writeTerminatedString($_data);
+ if ($encoding == 'opaque') {
+ $this->_writeOpaqueString($_data);
+ } else {
+ $this->_writeTerminatedString($_data);
+ }
}
$this->_currentTagData = NULL;
commit 4f4538299bee9b20402626b1f56fadd48abc771a
Author: Aleksander Machniak <alec at alec.pl>
Date: Sun Sep 2 14:27:06 2012 +0200
More fixes
diff --git a/lib/kolab_sync_data.php b/lib/kolab_sync_data.php
index 06a95d9..1ef5efb 100644
--- a/lib/kolab_sync_data.php
+++ b/lib/kolab_sync_data.php
@@ -190,8 +190,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
// get the folders the user has access to
$list = $this->backend->folders_list($this->device->deviceid, $this->modelName);
}
-
- if ($default = $this->getDefaultFolder()) {
+ else if ($default = $this->getDefaultFolder()) {
$list = array($default['serverId'] => $default);
}
@@ -337,17 +336,17 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
$item = $this->getObject($srcFolderId, $serverId, $folder);
if (!$item || !$folder) {
- throw Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_SOURCE);
+ throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_SOURCE);
}
$dstname = $this->backend->folder_id2name($dstFolderId, $this->device->deviceid);
if ($dstname === null) {
- throw Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_DESTINATION);
+ throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_DESTINATION);
}
if (!$folder->move($serverId, $dstname)) {
- throw Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_SOURCE);
+ throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_SOURCE);
}
return $item['uid'];
commit 696761b811a8fb94771fd87492d486f2a13a3e56
Author: Aleksander Machniak <alec at alec.pl>
Date: Sun Sep 2 14:06:32 2012 +0200
Fix date format in IMAP SEARCH
diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
index 9c29510..f36c42d 100644
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -381,7 +381,7 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
$dt = new DateTime('now', new DateTimeZone('UTC'));
$dt->modify($mod);
// RFC3501: IMAP SEARCH
- $filter[] = 'SINCE ' . $dt->format('d-m-Y');
+ $filter[] = 'SINCE ' . $dt->format('d-M-Y');
}
return $filter;
@@ -806,6 +806,7 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
&& !empty($query['and']['greaterThan']['dateReceived'])
&& !empty($query['and']['greaterThan']['value'])
) {
+ // @TODO: date format ?
$search_str .= ' SINCE ' . trim($query['and']['greaterThan']['value']);
}
@@ -813,6 +814,7 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
&& !empty($query['and']['lessThan']['dateReceived'])
&& !empty($query['and']['lessThan']['value'])
) {
+ // @TODO: date format ?
$search_str .= ' BEFORE ' . trim($query['and']['lessThan']['value']);
}
}
commit cfbfbde475e8415f12a3d095c36213a726bcaec3
Author: Aleksander Machniak <alec at alec.pl>
Date: Sun Sep 2 13:11:22 2012 +0200
Improved message sending: Use default idenity if From: is not set,
Generate Message-ID if not set, other fixes and improvements
diff --git a/lib/kolab_sync.php b/lib/kolab_sync.php
index 0969e8e..5a6d994 100644
--- a/lib/kolab_sync.php
+++ b/lib/kolab_sync.php
@@ -28,11 +28,24 @@
*/
class kolab_sync extends rcube
{
+ /**
+ * Application name
+ *
+ * @var string
+ */
public $app_name = 'ActiveSync for Kolab'; // no double quotes inside
+ /**
+ * Current user
+ *
+ * @var rcube_user
+ */
+ public $user;
+
private $data = array();
const CHARSET = 'UTF-8';
+ const VERSION = 1.0;
/**
diff --git a/lib/kolab_sync_backend.php b/lib/kolab_sync_backend.php
index 3cbd548..29235a1 100644
--- a/lib/kolab_sync_backend.php
+++ b/lib/kolab_sync_backend.php
@@ -734,11 +734,21 @@ class kolab_sync_backend
$mailto = $headers['To'];
- $headers['User-Agent'] .= $rcube->app_name;
+ $headers['User-Agent'] .= sprintf('%s v.%.1f', $rcube->app_name, kolab_sync::VERSION);
if ($agent = $rcube->config->get('useragent')) {
$headers['User-Agent'] .= '/' . $agent;
}
+ if (empty($headers['From'])) {
+ $headers['From'] = $this->get_identity();
+ }
+ if (empty($headers['Message-ID'])) {
+ $headers['Message-ID'] = $this->gen_message_id();
+ }
+
+ // remove empty headers
+ $headers = array_filter($headers);
+
// send thru SMTP server using custom SMTP library
if ($rcube->config->get('smtp_server')) {
$smtp_headers = $headers;
@@ -840,7 +850,14 @@ class kolab_sync_backend
return $sent;
}
-
+ /**
+ * 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
+ */
public function parse_mime($message, $decode_body = false)
{
if (is_resource($message)) {
@@ -858,7 +875,7 @@ class kolab_sync_backend
foreach ($headers as $line) {
if (ord($line[0]) <= 32) {
- $lines[$ln] .= (empty($lines[$ln]) ? '' : "\n") . trim($line);
+ $lines[$ln] .= (empty($lines[$ln]) ? '' : "\n") . $line;
}
else {
$lines[++$ln] = trim($line);
@@ -872,6 +889,7 @@ class kolab_sync_backend
'to' => 'To',
'cc' => 'Cc',
'bcc' => 'Bcc',
+ 'message-id' => 'Message-ID',
'content-type' => 'Content-Type',
'content-transfer-encoding' => 'Content-Transfer-Encoding',
);
@@ -937,15 +955,27 @@ class kolab_sync_backend
}
/**
+ * Returns email address string from default identity of the current user
+ */
+ protected function get_identity()
+ {
+ $user = kolab_sync::get_instance()->user;
+
+ if ($identity = $user->get_identity()) {
+ return format_email_recipient(format_email($identity['email']), $identity['name']);
+ }
+ }
+
+ /**
* Unique Message-ID generator.
*
* @return string Message-ID
*/
-/*
- public function gen_message_id()
+ protected function gen_message_id()
{
+ $user = kolab_sync::get_instance()->user;
$local_part = md5(uniqid('rcmail'.mt_rand(),true));
-// $domain_part = $this->user->get_username('domain');
+ $domain_part = $user->get_username('domain');
// Try to find FQDN, some spamfilters doesn't like 'localhost' (#1486924)
if (!preg_match('/\.[a-z]+$/i', $domain_part)) {
@@ -959,5 +989,5 @@ class kolab_sync_backend
return sprintf('<%s@%s>', $local_part, $domain_part);
}
-*/
+
}
commit f6fe8e0894240b9b0ad1fe95354312d960a7a04d
Author: Aleksander Machniak <alec at alec.pl>
Date: Sun Sep 2 12:37:49 2012 +0200
Fixed some errors
diff --git a/lib/kolab_sync.php b/lib/kolab_sync.php
index 2fb9b61..0969e8e 100644
--- a/lib/kolab_sync.php
+++ b/lib/kolab_sync.php
@@ -310,7 +310,7 @@ class kolab_sync extends rcube
if (function_exists('memory_get_peak_usage'))
$mem .= '/' . sprintf('%.1f', memory_get_peak_usage() / 1048576);
- $log = $_SERVER['REQUEST_URI'] . ($mem ? " [$mem]" : '');
+ $log = $_SERVER['QUERY_STRING'] . ($mem ? " [$mem]" : '');
if (defined('RCMAIL_START'))
self::print_timer(RCMAIL_START, $log);
else
diff --git a/lib/kolab_sync_backend_device.php b/lib/kolab_sync_backend_device.php
index fec5193..91adb54 100644
--- a/lib/kolab_sync_backend_device.php
+++ b/lib/kolab_sync_backend_device.php
@@ -61,8 +61,9 @@ class kolab_sync_backend_device extends kolab_sync_backend_common implements Syn
// Create device entry in kolab backend
$created = $this->backend->device_create(array(
- 'ID' => $device->id,
- 'TYPE' => $device->devicetype,
+ 'ID' => $device->id,
+ 'TYPE' => $device->devicedype,
+ 'ALIAS' => $device->friendlyname,
), $device->deviceid);
if (!$created) {
diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
index 2f0aaaa..9c29510 100644
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -421,15 +421,15 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
$dstname = $this->backend->folder_id2name($dstFolderId, $this->device->deviceid);
if (empty($msg)) {
- throw Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_SOURCE);
+ throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_SOURCE);
}
if ($dstname === null) {
- throw Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_DESTINATION);
+ throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_DESTINATION);
}
if (!$this->storage->move_message($msg['uid'], $dstname, $msg['foldername'])) {
- throw Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_SOURCE);
+ throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_SOURCE);
}
// Use COPYUID feature (RFC2359) to get the new UID of the copied message
@@ -525,7 +525,7 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
$sent = $this->backend->send_message($body, $smtp_error);
if (!$sent) {
- throw Syncroton_Exception_Status(Syncroton_Exception_Status::MAIL_SUBMISSION_FAILED);
+ throw new Syncroton_Exception_Status(Syncroton_Exception_Status::MAIL_SUBMISSION_FAILED);
}
// Save sent message in Sent folder
More information about the commits
mailing list