Page MenuHomePhorge

D5838.1775183185.diff
No OneTemporary

Authored By
Unknown
Size
25 KB
Referenced Files
None
Subscribers
None

D5838.1775183185.diff

diff --git a/composer.json-dist b/composer.json-dist
--- a/composer.json-dist
+++ b/composer.json-dist
@@ -15,6 +15,7 @@
"pear/net_sieve": "~1.4.0",
"roundcube/rtf-html-php": "~2.1",
"sabre/vobject": "~4.5.1",
+ "symfony/polyfill-php85": "^1.33.0",
"zf1s/zend-controller": "~1.12.20",
"zf1s/zend-json": "~1.12.20",
"zf1s/zend-log": "~1.12.20"
diff --git a/lib/kolab_sync_data_notes.php b/lib/kolab_sync_data_notes.php
--- a/lib/kolab_sync_data_notes.php
+++ b/lib/kolab_sync_data_notes.php
@@ -96,7 +96,7 @@
break;
}
- if (empty($value) || is_array($value)) {
+ if (empty($value) || (is_array($value) && $key != 'categories')) {
continue;
}
@@ -137,6 +137,14 @@
if ($value === null) {
continue 2;
}
+
+ // Make sure to use HTML format for Kolab v4
+ if (kolab_sync::get_instance()->config->get('activesync_storage') == 'kolab4') {
+ if (!preg_match('/<(html|body)(\s+[a-z]|>)/i', $value, $m)) {
+ $value = "<!DOCTYPE html><html><body><pre>{$value}</pre></body></html>";
+ }
+ }
+
break;
}
diff --git a/lib/kolab_sync_plugin_api.php b/lib/kolab_sync_plugin_api.php
--- a/lib/kolab_sync_plugin_api.php
+++ b/lib/kolab_sync_plugin_api.php
@@ -86,7 +86,7 @@
*
* @param string $fn Path to script
*/
- public function include_script($fn)
+ public function include_script($fn, $unused = [])
{
//empty
}
diff --git a/lib/kolab_sync_storage_kolab4.php b/lib/kolab_sync_storage_kolab4.php
--- a/lib/kolab_sync_storage_kolab4.php
+++ b/lib/kolab_sync_storage_kolab4.php
@@ -124,7 +124,7 @@
if ($flat_mode) {
$list = $this->folders_list_flat_mail($list);
}
- } elseif (in_array($type, [self::MODEL_CONTACTS, self::MODEL_CALENDAR, self::MODEL_TASKS])) {
+ } elseif (in_array($type, [self::MODEL_CONTACTS, self::MODEL_CALENDAR, self::MODEL_TASKS, self::MODEL_NOTES])) {
if (!empty($this->folders)) {
foreach ($this->folders as $unique_key => $folder) {
if (strpos($unique_key, "DAV:$type:") === 0) {
@@ -142,7 +142,7 @@
$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
+ // any access to the folder (or list) will invoke excessive DAV requests
$unique_key = $folder_data['serverId'] . ":$deviceid:$type";
$this->folders[$unique_key] = $folder;
}
@@ -247,7 +247,7 @@
}
return false;
- } elseif ($type == 8 || $type == 13 || $type == 7 || $type == 15 || $type == 9 || $type == 14) {
+ } elseif (in_array($type, [8, 13, 7, 15, 9, 14, 10, 17])) {
// DAV folder
$type = preg_replace('|\..*|', '', self::type_activesync2kolab($type));
@@ -585,6 +585,7 @@
'contact' => [],
'event' => [],
'task' => [],
+ 'note' => [],
];
foreach ($all_folders as $folder) {
diff --git a/tests/Sync/FoldersTest.php b/tests/Sync/FoldersTest.php
--- a/tests/Sync/FoldersTest.php
+++ b/tests/Sync/FoldersTest.php
@@ -16,11 +16,11 @@
$this->deleteTestFolder('Test Contacts Folder', 'contact');
$this->deleteTestFolder('Test Contacts New', 'contact');
// Make sure the default folders exist
+ $this->createTestFolder('Notes', 'note.default');
if (!$this->isStorageDriver('kolab4')) {
$this->createTestFolder('Calendar', 'event.default');
$this->createTestFolder('Contacts', 'contact.default');
$this->createTestFolder('Tasks', 'task.default');
- $this->createTestFolder('Notes', 'note.default');
}
//TODO: handle kolab4 case?
}
@@ -305,10 +305,10 @@
['Drafts', Syncroton_Command_FolderSync::FOLDERTYPE_DRAFTS],
['Sent', Syncroton_Command_FolderSync::FOLDERTYPE_SENTMAIL],
['Trash', Syncroton_Command_FolderSync::FOLDERTYPE_DELETEDITEMS],
- ['Spam', Syncroton_Command_FolderSync::FOLDERTYPE_MAIL_USER_CREATED],
+ // ['Spam', Syncroton_Command_FolderSync::FOLDERTYPE_MAIL_USER_CREATED],
+ ['Notes', Syncroton_Command_FolderSync::FOLDERTYPE_NOTE],
['Tasks', Syncroton_Command_FolderSync::FOLDERTYPE_TASK],
];
-
} else {
$folders = [
['Calendar', Syncroton_Command_FolderSync::FOLDERTYPE_CALENDAR],
@@ -351,6 +351,7 @@
['Drafts', Syncroton_Command_FolderSync::FOLDERTYPE_DRAFTS],
['Sent', Syncroton_Command_FolderSync::FOLDERTYPE_SENTMAIL],
['Trash', Syncroton_Command_FolderSync::FOLDERTYPE_DELETEDITEMS],
+ ['Notes', Syncroton_Command_FolderSync::FOLDERTYPE_NOTE],
// Note: For now Kolab 4 uses the same Calendar folder for calendar and tasks
['/^(Tasks|Calendar)$/', Syncroton_Command_FolderSync::FOLDERTYPE_TASK],
];
@@ -390,7 +391,7 @@
$xpath = $this->xpath($dom);
// This depends on multifolder blacklists to be configured (otherwise we get no "collective" folders)
- $deleted = $this->isStorageDriver('kolab4') ? 4 : 5; // No Notes folder in Kolab4
+ $deleted = 4;
$syncKey = 2;
$this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue);
@@ -787,6 +788,7 @@
['Sent', Syncroton_Command_FolderSync::FOLDERTYPE_SENTMAIL],
['Spam', Syncroton_Command_FolderSync::FOLDERTYPE_MAIL_USER_CREATED],
['Trash', Syncroton_Command_FolderSync::FOLDERTYPE_DELETEDITEMS],
+ ['Notes', Syncroton_Command_FolderSync::FOLDERTYPE_NOTE],
['Tasks', Syncroton_Command_FolderSync::FOLDERTYPE_TASK],
];
diff --git a/tests/Sync/Sync/NotesTest.php b/tests/Sync/Sync/NotesTest.php
new file mode 100644
--- /dev/null
+++ b/tests/Sync/Sync/NotesTest.php
@@ -0,0 +1,347 @@
+<?php
+
+namespace Tests\Sync\Sync;
+
+class NotesTest extends \Tests\SyncTestCase
+{
+ /**
+ * Test Sync command
+ */
+ public function testSync()
+ {
+ // Test with multi-folder support enabled
+ self::$deviceType = 'iphone';
+
+ $davFolder = 'Notes';
+ $this->createTestFolder($davFolder, 'note', false);
+ $this->emptyTestFolder($davFolder, 'note');
+ $this->deleteTestFolder('Test Notes Folder', 'note'); // from other test files
+ $this->registerDevice();
+
+ // Test empty contacts folder
+ $folderId = array_search('Notes', $this->folders);
+ $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>Notes</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());
+
+ if ($this->isStorageDriver('kolab')) {
+ $this->markTestSkipped("Appending test objects does not work with 'kolab' storage yet.");
+ }
+
+ // Append two notes objects and sync them
+ $this->appendObject($davFolder, 'note1.html', 'note');
+ $this->appendObject($davFolder, 'note2.html', 'note');
+
+ $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);
+ $r = "{$root}[1]/ns:ApplicationData";
+ $this->assertSame('test note', $xpath->query("{$r}/Notes:Subject")->item(0)->nodeValue);
+ $this->assertSame('IPM.StickyNote', $xpath->query("{$r}/Notes:MessageClass")->item(0)->nodeValue);
+ $this->assertSame('1', $xpath->query("{$r}/AirSyncBase:Body/AirSyncBase:Type")->item(0)->nodeValue);
+ $this->assertStringContainsString('test note 1', $xpath->query("{$r}/AirSyncBase:Body/AirSyncBase:Data")->item(0)->nodeValue);
+ $this->assertCount(2, $xpath->query("{$r}/Notes:Categories/Notes:Category"));
+ $this->assertSame('test1', $xpath->query("{$r}/Notes:Categories/Notes:Category")->item(0)->nodeValue);
+ $this->assertSame('test2', $xpath->query("{$r}/Notes:Categories/Notes:Category")->item(1)->nodeValue);
+ $r = "{$root}[2]/ns:ApplicationData";
+ $this->assertSame('test note 2', $xpath->query("{$r}/Notes:Subject")->item(0)->nodeValue);
+ $this->assertSame('IPM.StickyNote', $xpath->query("{$r}/Notes:MessageClass")->item(0)->nodeValue);
+ $this->assertSame('1', $xpath->query("{$r}/AirSyncBase:Body/AirSyncBase:Type")->item(0)->nodeValue);
+ $this->assertStringContainsString('test note 2', $xpath->query("{$r}/AirSyncBase:Body/AirSyncBase:Data")->item(0)->nodeValue);
+ $this->assertCount(0, $xpath->query("{$r}/Notes:Categories/Notes:Category"));
+
+ return [$syncKey, $folderId];
+ }
+
+ /**
+ * Test adding objects from client
+ *
+ * @depends testSync
+ */
+ public function testAddFromClient($params)
+ {
+ // Test with multi-folder support enabled
+ self::$deviceType = 'iphone';
+
+ [$syncKey, $folderId] = $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:Notes="uri:Notes">
+ <Collections>
+ <Collection>
+ <Class>Notes</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>
+ <Commands>
+ <Add>
+ <ClientId>42</ClientId>
+ <ApplicationData>
+ <Notes:Subject>test note 3</Notes:Subject>
+ <Notes:MessageClass>IPM.StickyNote</Notes:MessageClass>
+ <AirSyncBase:Body>
+ <AirSyncBase:Type>1</AirSyncBase:Type>
+ <AirSyncBase:Data>test note 3</AirSyncBase:Data>
+ </AirSyncBase:Body>
+ <Notes:Categories>
+ <Notes:Category>test1</Notes:Category>
+ <Notes:Category>test2</Notes:Category>
+ </Notes:Categories>
+ </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);
+
+ // Assert the content on the server
+ $notes = $this->getDavObjects('Notes', 'note');
+ usort($notes, function ($c1, $c2) { return $c1['title'] <=> $c2['title']; });
+ $this->assertCount(3, $notes);
+ $this->assertSame('test note 3', $notes[2]['title']);
+ $this->assertStringContainsString('<pre>test note 3</pre>', $notes[2]['description']);
+ $this->assertSame(['test1', 'test2'], $notes[2]['categories']);
+
+ return [$syncKey, $folderId, $serverId];
+ }
+
+ /**
+ * Test updating objects from client
+ *
+ * @depends testAddFromClient
+ */
+ public function testChangeFromClient($params)
+ {
+ // Test with multi-folder support enabled
+ self::$deviceType = 'iphone';
+
+ [$syncKey, $folderId, $serverId] = $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:Notes="uri:Notes">
+ <Collections>
+ <Collection>
+ <Class>Notes</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>
+ <Commands>
+ <Change>
+ <ServerId>{$serverId}</ServerId>
+ <ApplicationData>
+ <Notes:Subject>test note 3 mod</Notes:Subject>
+ <Notes:Categories>
+ <Notes:Category>test1</Notes:Category>
+ <Notes:Category>test3</Notes:Category>
+ </Notes:Categories>
+ </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(++$syncKey), $xpath->query("ns:SyncKey", $root)->item(0)->nodeValue);
+ $this->assertSame(0, $xpath->query("ns:Responses", $root)->length);
+
+ // Assert updated content on the server
+ $notes = $this->getDavObjects('Notes', 'note');
+ usort($notes, function ($c1, $c2) { return $c1['title'] <=> $c2['title']; });
+ $this->assertCount(3, $notes);
+ $this->assertSame('test note 3 mod', $notes[2]['title']);
+ $this->assertStringContainsString('<pre>test note 3</pre>', $notes[2]['description']);
+ $this->assertSame(['test1', 'test3'], $notes[2]['categories']);
+
+ return [$syncKey, $folderId, $serverId];
+ }
+
+ /**
+ * Test deleting objects from client
+ *
+ * @depends testChangeFromClient
+ */
+ public function testDeleteFromClient($params)
+ {
+ // Test with multi-folder support enabled
+ self::$deviceType = 'iphone';
+
+ [$syncKey, $folderId, $serverId] = $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:Notes="uri:Notes">
+ <Collections>
+ <Collection>
+ <Class>Notes</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>
+ <Commands>
+ <Delete>
+ <ServerId>{$serverId}</ServerId>
+ </Delete>
+ </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);
+ $this->assertSame(0, $xpath->query("ns:Responses", $root)->length);
+
+ // Assert deleted note on the server
+ $notes = $this->getDavObjects('Notes', 'note');
+ usort($notes, function ($c1, $c2) { return $c1['title'] <=> $c2['title']; });
+ $this->assertSame(['test note', 'test note 2'], array_column($notes, 'title'));
+ }
+
+ /**
+ * Test creating a notes folder
+ *
+ * @depends testSync
+ */
+ public function testCreateFolder()
+ {
+ // Create a notes folder
+ $folderName = 'Test Notes Folder';
+ $folderType = \Syncroton_Command_FolderSync::FOLDERTYPE_NOTE_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);
+
+ $this->assertSame('1', $xpath->query("//ns:FolderCreate/ns:Status")->item(0)->nodeValue);
+ $this->assertSame('2', $xpath->query("//ns:FolderCreate/ns:SyncKey")->item(0)->nodeValue);
+ $this->assertSame(1, $xpath->query("//ns:FolderCreate/ns:ServerId")->count());
+ $folderId = $xpath->query("//ns:FolderCreate/ns:ServerId")->item(0)->nodeValue;
+
+ $folders = $this->getDavFolders('note');
+ $folders = array_map(fn ($f) => $f->get_name(), $folders);
+ $this->assertSame(['Notes', $folderName], $folders);
+ }
+}
diff --git a/tests/SyncTestCase.php b/tests/SyncTestCase.php
--- a/tests/SyncTestCase.php
+++ b/tests/SyncTestCase.php
@@ -185,6 +185,18 @@
$location = $folder->object_location($uid);
if ($folder->dav->create($location, $content, $dav_type) !== false) {
+ if ($type == 'note') {
+ $props = [];
+ if (preg_match('/<\!-- Title:(.*) -->/i', $content, $m)) {
+ $props['title'] = $m[1];
+ }
+ if (preg_match('/<\!-- Categories:(.*) -->/i', $content, $m)) {
+ $props['categories'] = explode(' ', $m[1]);
+ }
+
+ $folder->dav->propPatch($location, $props);
+ }
+
return;
}
}
@@ -231,6 +243,29 @@
$imap->set_metadata($name, ['/private/vendor/kolab/folder-type' => $type]);
}
$this->setSubscriptionState($name, $type, $subscriptionState);
+ return;
+ }
+
+ // Create DAV folder
+ $dav = $this->getDavStorage();
+ $type = preg_replace('/\..*$/', '', $type);
+
+ foreach ($dav->get_folders($type) as $folder) {
+ if ($folder->get_name() === $name) {
+ if ($subscriptionState) {
+ $this->setSubscriptionState($name, $type, $subscriptionState);
+ }
+ return;
+ }
+ }
+
+ $folder = ['name' => $name, 'type' => $type];
+ if ($dav->folder_update($folder) === false) {
+ throw new \Exception("Failed to create DAV folder: {$name}");
+ }
+
+ if ($subscriptionState) {
+ $this->setSubscriptionState($name, $type, $subscriptionState);
}
}
@@ -377,6 +412,16 @@
throw new \Exception("Folder not found");
}
+ /**
+ * Get list of folders from a DAV folder
+ */
+ protected function getDavFolders($type)
+ {
+ $dav = $this->getDavStorage();
+
+ return $dav->get_folders($type);
+ }
+
/**
* Initialize DAV storage
*/
@@ -519,6 +564,7 @@
$xpath->registerNamespace("ComposeMail", "uri:ComposeMail");
$xpath->registerNamespace("Email", "uri:Email");
$xpath->registerNamespace("Email2", "uri:Email2");
+ $xpath->registerNamespace("Notes", "uri:Notes");
$xpath->registerNamespace("Settings", "uri:Settings");
$xpath->registerNamespace("Tasks", "uri:Tasks");
diff --git a/tests/src/note1.html b/tests/src/note1.html
new file mode 100644
--- /dev/null
+++ b/tests/src/note1.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+<!-- UID:12345678-12345678 -->
+<!-- Title:test note -->
+<!-- Categories:test1 test2 -->
+<p>test note 1</p>
+</body>
+</html>
diff --git a/tests/src/note2.html b/tests/src/note2.html
new file mode 100644
--- /dev/null
+++ b/tests/src/note2.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<!-- UID:aaaa-aaaa -->
+<!-- Title:test note 2 -->
+<p>test note 2</p>
+</body>
+</html>

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 3, 2:26 AM (21 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18822139
Default Alt Text
D5838.1775183185.diff (25 KB)

Event Timeline