Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117877007
D5187.1775337676.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
14 KB
Referenced Files
None
Subscribers
None
D5187.1775337676.diff
View Options
diff --git a/lib/ext/Syncroton/Command/Ping.php b/lib/ext/Syncroton/Command/Ping.php
--- a/lib/ext/Syncroton/Command/Ping.php
+++ b/lib/ext/Syncroton/Command/Ping.php
@@ -65,6 +65,7 @@
$intervalStart = time();
$status = self::STATUS_NO_CHANGES_FOUND;
+ $pingTimeout = Syncroton_Registry::getPingTimeout();
// the client does not send a wbxml document, if the Ping parameters did not change compared with the last request
if ($this->_requestBody instanceof DOMDocument) {
$xml = simplexml_import_dom($this->_requestBody);
@@ -72,6 +73,11 @@
if (isset($xml->HeartbeatInterval)) {
$this->_device->pinglifetime = (int)$xml->HeartbeatInterval;
+ // Magic value for testing
+ if ($this->_device->pinglifetime == 9999) {
+ $pingTimeout = 1;
+ $this->_device->pinglifetime = 900;
+ }
}
if (isset($xml->Folders->Folder)) {
@@ -264,10 +270,10 @@
// break if there are less than PingTimeout + 10 seconds left for the next loop
// otherwise the response will be returned after the client has finished his Ping
// request already maybe
- if ($secondsLeft < (Syncroton_Registry::getPingTimeout() + 10)) {
+ if ($secondsLeft < ($pingTimeout + 10)) {
break;
} else {
- $this->goToSleep(Syncroton_Registry::getPingTimeout());
+ $this->goToSleep($pingTimeout);
}
} while (Syncroton_Server::validateSession());
diff --git a/lib/kolab_sync_backend_folder.php b/lib/kolab_sync_backend_folder.php
--- a/lib/kolab_sync_backend_folder.php
+++ b/lib/kolab_sync_backend_folder.php
@@ -144,8 +144,12 @@
Syncroton_Data_Factory::CLASS_TASKS,
];
- // Reset imap cache so we work with up-to-date folders list
+ // Reset imap cache, metadata cache and the folder list cache so we work with up-to-date folders lists
rcube::get_instance()->get_storage()->clear_cache('mailboxes', true);
+ kolab_sync::storage()->reset();
+ foreach ($folder_classes as $class) {
+ Syncroton_Data_Factory::factory($class, $device, $timestamp)->clearCache();
+ }
// Retrieve all folders already sent to the client
$select = $this->db->query("SELECT * FROM `{$this->table_name}` WHERE `device_id` = ?", $device->id);
diff --git a/lib/kolab_sync_data.php b/lib/kolab_sync_data.php
--- a/lib/kolab_sync_data.php
+++ b/lib/kolab_sync_data.php
@@ -747,6 +747,14 @@
return $folders;
}
+ /**
+ * Clear the internal folder list cache
+ */
+ public function clearCache()
+ {
+ $this->folders = [];
+ }
+
/**
* List of all IMAP folders (or subtree)
*
diff --git a/lib/kolab_sync_storage.php b/lib/kolab_sync_storage.php
--- a/lib/kolab_sync_storage.php
+++ b/lib/kolab_sync_storage.php
@@ -124,6 +124,7 @@
public function reset()
{
$this->folders = [];
+ $this->folder_meta = null;
}
/**
diff --git a/tests/Sync/PingTest.php b/tests/Sync/PingTest.php
--- a/tests/Sync/PingTest.php
+++ b/tests/Sync/PingTest.php
@@ -28,11 +28,11 @@
$dom = $this->fromWbxml($response->getBody());
$xpath = $this->xpath($dom);
- //Initially we know no folders
+ // Initially we know no folders
$this->assertSame('7', $xpath->query("//ns:Ping/ns:Status")->item(0)->nodeValue);
- //We discover folders with a foldersync
+ // We discover folders with a foldersync
$request = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
@@ -44,7 +44,7 @@
$response = $this->request($request, 'FolderSync');
$this->assertEquals(200, $response->getStatusCode());
- //Now we get to the actual ping
+ // Now we get to the actual ping
$request = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
@@ -63,12 +63,61 @@
$this->assertEquals(200, $response->getStatusCode());
$dom = $this->fromWbxml($response->getBody());
$xpath = $this->xpath($dom);
- // Initially we know no folders
+ // We don't find the folder state because it was never synced
$this->assertSame('2', $xpath->query("//ns:Ping/ns:Status")->item(0)->nodeValue);
+
+ // Sync inbox
+ $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>0</SyncKey>
+ <CollectionId>38b950ebd62cd9a66929c89615d0fc04</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());
+
+ // Now we should get no change
+ $request = <<<EOF
+ <?xml version="1.0" encoding="utf-8"?>
+ <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
+ <Ping xmlns="uri:Ping">
+ <HeartbeatInterval>0</HeartbeatInterval>
+ <Folders>
+ <Folder>
+ <Id>38b950ebd62cd9a66929c89615d0fc04</Id>
+ <Class>Email</Class>
+ </Folder>
+ </Folders>
+ </Ping>
+ EOF;
+
+ $response = $this->request($request, 'Ping');
+ $this->assertEquals(200, $response->getStatusCode());
+ $dom = $this->fromWbxml($response->getBody());
+ $xpath = $this->xpath($dom);
+ $this->assertSame('1', $xpath->query("//ns:Ping/ns:Status")->item(0)->nodeValue);
}
/**
- * Test Ping command
+ * Test Unknown Folder
*/
public function testUnknownFolder()
{
@@ -95,4 +144,148 @@
$this->assertSame('7', $xpath->query("//ns:Ping/ns:Status")->item(0)->nodeValue);
}
+
+ /**
+ * Test New Folder
+ */
+ public function testNewFolder()
+ {
+ // Initialize the folder state
+ $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());
+
+ $this->createTestFolder("NewFolder", "mail");
+ $request = <<<EOF
+ <?xml version="1.0" encoding="utf-8"?>
+ <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
+ <Ping xmlns="uri:Ping">
+ <HeartbeatInterval>900</HeartbeatInterval>
+ <Folders>
+ <Folder>
+ <Id>38b950ebd62cd9a66929c89615d0fc04</Id>
+ <Class>Email</Class>
+ </Folder>
+ </Folders>
+ </Ping>
+ EOF;
+
+ $response = $this->request($request, 'Ping');
+
+ $this->assertEquals(200, $response->getStatusCode());
+
+ $dom = $this->fromWbxml($response->getBody());
+ $xpath = $this->xpath($dom);
+
+ $this->assertSame('7', $xpath->query("//ns:Ping/ns:Status")->item(0)->nodeValue);
+ }
+
+ /**
+ * Test Changed Subscription Folder
+ */
+ public function testNewFolderSubscriptionState()
+ {
+ // Initialize the folder state
+ $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());
+
+ $this->setSubscriptionState("NewFolder", null);
+ $request = <<<EOF
+ <?xml version="1.0" encoding="utf-8"?>
+ <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
+ <Ping xmlns="uri:Ping">
+ <HeartbeatInterval>900</HeartbeatInterval>
+ <Folders>
+ <Folder>
+ <Id>38b950ebd62cd9a66929c89615d0fc04</Id>
+ <Class>Email</Class>
+ </Folder>
+ </Folders>
+ </Ping>
+ EOF;
+
+ $response = $this->request($request, 'Ping');
+
+ $this->assertEquals(200, $response->getStatusCode());
+
+ $dom = $this->fromWbxml($response->getBody());
+ $xpath = $this->xpath($dom);
+
+ $this->assertSame('7', $xpath->query("//ns:Ping/ns:Status")->item(0)->nodeValue);
+ }
+
+ /**
+ * Test changed subscription while ping is running
+ */
+ public function testNewFolderSubscriptionStateDuringPing()
+ {
+ // Initialize the folder state
+ $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());
+
+ $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());
+
+ // Set the metadata via a background script, while Ping is running.
+ // This is essential to trigger a bug where the initial Ping seeds the roundcube metadata cache,
+ // and then subsequent checks don't update the cache. We have to use a separate process to set
+ // the metadata, because otherwise we update the cache (we could also not use the roundcube
+ // infrastructure instead).
+ $deviceId = self::$deviceId;
+ $username = self::$username;
+ $password = self::$password;
+ exec("php setmetadata.php $deviceId NewFolder $username $password > /dev/null 2>&1 &");
+
+ $request = <<<EOF
+ <?xml version="1.0" encoding="utf-8"?>
+ <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
+ <Ping xmlns="uri:Ping">
+ <HeartbeatInterval>9999</HeartbeatInterval>
+ <Folders>
+ <Folder>
+ <Id>38b950ebd62cd9a66929c89615d0fc04</Id>
+ <Class>Email</Class>
+ </Folder>
+ </Folders>
+ </Ping>
+ EOF;
+
+ $response = $this->request($request, 'Ping');
+ $this->assertEquals(200, $response->getStatusCode());
+ $dom = $this->fromWbxml($response->getBody());
+ $xpath = $this->xpath($dom);
+
+ $this->assertSame('7', $xpath->query("//ns:Ping/ns:Status")->item(0)->nodeValue);
+ }
}
diff --git a/tests/SyncTestCase.php b/tests/SyncTestCase.php
--- a/tests/SyncTestCase.php
+++ b/tests/SyncTestCase.php
@@ -224,22 +224,31 @@
/**
* Create a folder
*/
- protected function createTestFolder($name, $type)
+ protected function createTestFolder($name, $type, $subscriptionState = '1')
{
// Create IMAP folders
if ($type == 'mail' || $this->isStorageDriver('kolab')) {
$imap = $this->getImapStorage();
//TODO set type if not mail
$imap->create_folder($name, true);
+ $this->setSubscriptionState($name, $subscriptionState);
+ }
+ }
+ /**
+ * Subscribe test folder
+ */
+ protected function setSubscriptionState($name, $subscriptionState)
+ {
+ $metadata = null;
+ if ($subscriptionState) {
$metadata = [];
$metadata['FOLDER'] = [];
$metadata['FOLDER'][self::$deviceId] = [];
- $metadata['FOLDER'][self::$deviceId]['S'] = '1';
- $imap->set_metadata($name, ['/private/vendor/kolab/activesync' => json_encode($metadata)]);
-
- return;
+ $metadata['FOLDER'][self::$deviceId]['S'] = $subscriptionState;
+ $metadata = json_encode($metadata);
}
+ $this->getImapStorage()->set_metadata($name, ['/private/vendor/kolab/activesync' => $metadata]);
}
/**
diff --git a/tests/setmetadata.php b/tests/setmetadata.php
new file mode 100644
--- /dev/null
+++ b/tests/setmetadata.php
@@ -0,0 +1,21 @@
+<?php
+
+define('TESTS_DIR', dirname(__FILE__) . '/');
+require_once(TESTS_DIR . '/../lib/init.php');
+
+sleep(5);
+
+$deviceid=$argv[1] ;
+$folderName=$argv[2] ;
+
+$metadata = [];
+$metadata['FOLDER'] = [];
+$metadata['FOLDER'][$deviceid] = [];
+$metadata['FOLDER'][$deviceid]['S'] = '1';
+$metadata = json_encode($metadata);
+\kolab_sync::get_instance()->authenticate($argv[3], $argv[4]);
+if (\kolab_sync::get_instance()->get_storage()->set_metadata($folderName, ['/private/vendor/kolab/activesync' => $metadata])) {
+ print("Set metdata on $deviceid on $folderName");
+} else {
+ print("Failed to set metdata on $deviceid on $folderName");
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 4, 9:21 PM (4 h, 58 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18831217
Default Alt Text
D5187.1775337676.diff (14 KB)
Attached To
Mode
D5187: Clear caches so we can detect new folders
Attached
Detach File
Event Timeline