Overview

Request 3305 (superseded)

New release 2.4.2.23


kolab-syncroton.spec Changed
x
 
1
@@ -17,12 +17,6 @@
2
 
3
 %{!?php_inidir: %global php_inidir %{_sysconfdir}/php.d}
4
 
5
-%if 0%{?suse_version} < 1 && 0%{?fedora} < 1 && 0%{?rhel} < 7
6
-%global with_systemd 0
7
-%else
8
-%global with_systemd 1
9
-%endif
10
-
11
 %if 0%{?suse_version}
12
 %global httpd_group www
13
 %global httpd_name apache2
14
@@ -43,7 +37,7 @@
15
 %global upstream_version 2.4.2
16
 
17
 Name:           kolab-syncroton
18
-Version: 2.4.2.39
19
+Version: 2.4.2.23
20
 Release:        1%{?dist}
21
 Summary:        ActiveSync for Kolab Groupware
22
 
23
@@ -112,7 +106,6 @@
24
 
25
 cp -a lib %{buildroot}/%{_datadir}/%{name}/.
26
 cp -a index.php %{buildroot}/%{_datadir}/%{name}/.
27
-cp -a bin %{buildroot}/%{_datadir}/%{name}/.
28
 
29
 %if 0%{?plesk}
30
 cp -a %SOURCE2 %{buildroot}/%{_sysconfdir}/roundcubemail/kolab_syncroton.inc.php
31
@@ -171,7 +164,7 @@
32
 %post
33
 if  -f "%{php_inidir}/apc.ini" -o -f "%{php_inidir}/apcu.ini" ; then
34
     if  ! -z "`grep ^apc.enabled=1 %{php_inidir}/apc{,u}.ini 2>/dev/null`" ; then
35
-%if 0%{?with_systemd}
36
+%if 0%{?fedora} > 15
37
         /bin/systemctl condrestart %{httpd_name}.service
38
 %else
39
         /sbin/service %{httpd_name} condrestart
40
@@ -183,44 +176,17 @@
41
     /bin/systemctl reload php-fpm.service || :
42
 fi
43
 
44
-if  -f "/usr/lib/systemd/system/plesk-php74-fpm.service" ; then
45
-    /bin/systemctl reload plesk-php74-fpm.service || :
46
-fi
47
-
48
-if  -f "/usr/lib/systemd/system/plesk-php80-fpm.service" ; then
49
-    /bin/systemctl reload plesk-php80-fpm.service || :
50
-fi
51
-
52
-if  -f "/usr/lib/systemd/system/plesk-php81-fpm.service" ; then
53
-    /bin/systemctl reload plesk-php81-fpm.service || :
54
-fi
55
-
56
-if  -f "/usr/lib/systemd/system/plesk-php82-fpm.service" ; then
57
-    /bin/systemctl reload plesk-php82-fpm.service || :
58
-fi
59
-
60
-if  -f "/usr/lib/systemd/system/plesk-php83-fpm.service" ; then
61
-    /bin/systemctl reload plesk-php83-fpm.service || :
62
-fi
63
-
64
-
65
 
66
-%if 0%{?plesk} > 0 && 0%{?rhel} <= 8
67
-for version in 8.2 8.1 8.0 7.4; do
68
-    php="/opt/plesk/php/$version/bin/php"
69
+%if 0%{?plesk} > 0 && 0%{?rhel} == 7
70
+php="/opt/plesk/php/7.4/bin/php"
71
 %else
72
-for version in 1; do
73
-    php="/usr/bin/php"
74
+php="/usr/bin/php"
75
 %endif
76
 
77
-    if  -f "$php" ; then
78
-        ${php} /usr/share/roundcubemail/bin/updatedb.sh \
79
-            --dir /usr/share/doc/kolab-syncroton/SQL/ \
80
-            --package syncroton \
81
-            >/dev/null 2>&1 || :
82
-        break
83
-    fi
84
-done
85
+${php} /usr/share/roundcubemail/bin/updatedb.sh \
86
+    --dir /usr/share/doc/kolab-syncroton/SQL/ \
87
+    --package syncroton \
88
+    >/dev/null 2>&1 || :
89
 
90
 exit 0
91
 
92
debian.changelog Changed
7
 
1
@@ -1,4 +1,4 @@
2
-kolab-syncroton (2.4.2.39-0~kolab1) unstable; urgency=low
3
+kolab-syncroton (2.4.2.23-0~kolab1) unstable; urgency=low
4
 
5
   * Release version 2.4.2
6
 
7
debian.tar.gz/dirs Changed
8
 
1
@@ -1,6 +1,5 @@
2
 usr/share/kolab-syncroton/config
3
 usr/share/kolab-syncroton/lib
4
-usr/share/kolab-syncroton/bin
5
 usr/share/kolab-syncroton/lib/ext
6
 usr/share/kolab-syncroton/lib/plugins
7
 var/lib/kolab-syncroton
8
debian.tar.gz/install Changed
9
 
1
@@ -2,7 +2,6 @@
2
 index.php usr/share/kolab-syncroton/
3
 lib/.htaccess usr/share/kolab-syncroton/lib/
4
 lib/*.php usr/share/kolab-syncroton/lib/
5
-bin/*.php usr/share/kolab-syncroton/bin/
6
 lib/ext/ usr/share/kolab-syncroton/lib/
7
 logs/.htaccess var/log/kolab-syncroton/
8
 temp/.htaccess var/lib/kolab-syncroton/
9
kolab-syncroton-2.4.2.tar.gz/bin Deleted
2
 
1
-(directory)
2
kolab-syncroton-2.4.2.tar.gz/bin/analyzelogs.php Deleted
152
 
1
@@ -1,150 +0,0 @@
2
-#!/usr/bin/env php
3
-<?php
4
-
5
-/*
6
- +--------------------------------------------------------------------------+
7
- | Kolab Sync (ActiveSync for Kolab)                                        |
8
- |                                                                          |
9
- | Copyright (C) 2024, Apheleia IT AG <contact@apheleia-it.ch>         |
10
- |                                                                          |
11
- | This program is free software: you can redistribute it and/or modify     |
12
- | it under the terms of the GNU Affero General Public License as published |
13
- | by the Free Software Foundation, either version 3 of the License, or     |
14
- | (at your option) any later version.                                      |
15
- |                                                                          |
16
- | This program is distributed in the hope that it will be useful,          |
17
- | but WITHOUT ANY WARRANTY; without even the implied warranty of           |
18
- | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the             |
19
- | GNU Affero General Public License for more details.                      |
20
- |                                                                          |
21
- | You should have received a copy of the GNU Affero General Public License |
22
- | along with this program. If not, see <http://www.gnu.org/licenses/>      |
23
- +--------------------------------------------------------------------------+
24
- | Author: Christian Mollekopf <mollekopf@apheleia-it.ch>                      |
25
- +--------------------------------------------------------------------------+
26
-*/
27
-
28
-
29
-define('RCUBE_INSTALL_PATH', realpath(dirname(__FILE__) . '/../') . '/');
30
-
31
-// Define include path
32
-$include_path  = RCUBE_INSTALL_PATH . 'lib' . PATH_SEPARATOR;
33
-$include_path .= RCUBE_INSTALL_PATH . 'lib/ext' . PATH_SEPARATOR;
34
-$include_path .= ini_get('include_path');
35
-set_include_path($include_path);
36
-
37
-require_once "Syncroton/Command/ICommand.php";
38
-require_once "Syncroton/Command/Wbxml.php";
39
-require_once "Syncroton/Command/Sync.php";
40
-require_once "Syncroton/Command/Ping.php";
41
-require_once "Syncroton/Command/MoveItems.php";
42
-require_once "Syncroton/Command/FolderSync.php";
43
-
44
-$filename = $argv1;
45
-
46
-$content = file_get_contents($filename);
47
-
48
-// Split up the log files into chunks that hopefully match the commands
49
-$parts = preg_split("/\.*\: " . preg_quote("DEBUG Syncroton_Server::handle::65 REQUEST METHOD: POST", '/') . "/", $content, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
50
-
51
-function getStatusConstants($classname)
52
-{
53
-    $reflect = new ReflectionClass($classname);
54
-    $result = $reflect->getConstants();
55
-    $result = array_filter($result, function ($val) {
56
-        return str_starts_with($val, "STATUS_");
57
-    }, ARRAY_FILTER_USE_KEY);
58
-    $result = array_flip($result);
59
-    return $result;
60
-}
61
-
62
-function explainStatus($command, $status)
63
-{
64
-    if (!$status) {
65
-        return "none";
66
-    }
67
-    switch ($command) {
68
-        case "Ping":
69
-            $result = getStatusConstants("Syncroton_Command_Ping");
70
-            return $result$status ?? "Unknown";
71
-        case "Sync":
72
-            $result = getStatusConstants("Syncroton_Command_Sync");
73
-            return $result$status ?? "Unknown";
74
-        case "MoveItems":
75
-            $result = getStatusConstants("Syncroton_Command_MoveItems");
76
-            return $result$status ?? "Unknown";
77
-        case "FolderSync":
78
-            $result = getStatusConstants("Syncroton_Command_FolderSync");
79
-            return $result$status ?? "Unknown";
80
-    }
81
-    return "Unknown command";
82
-}
83
-
84
-foreach ($parts as $part) {
85
-    preg_match('/\(.*)\: /', $part, $matches);
86
-    $timestamp = $matches1;
87
-
88
-    preg_match('/\command\ => (.*)/', $part, $matches);
89
-    $command = $matches1;
90
-
91
-    preg_match('/\<Status\>(.*)\<\/Status\>/', $part, $matches);
92
-    $status = $matches1 ?? null;
93
-
94
-    $statusExplained = explainStatus($command, $status);
95
-
96
-    print(" Command: " . str_pad($command, 10) . str_pad("\tStatus: $status ($statusExplained)", 45) . "\tTimestamp: $timestamp\n");
97
-    if ($command == "Sync") {
98
-        // Find collections within this sync
99
-        // 25-Sep-2024 09:16:35.347730: INFO Syncroton_Command_Sync::handle::221 SyncKey is 7301 Class: Email CollectionId: 38b950ebd62cd9a66929c89615d0fc04
100
-        if (preg_match_all('/SyncKey is (.*) Class: (.*) CollectionId: (.*)/', $part, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
101
-            foreach ($matches as $set) {
102
-                $offset = $set01;
103
-                $collectionId = $set30;
104
-                $class = $set20;
105
-                $synckey = $set10;
106
-                print(str_pad("  Collection: $collectionId ($class)", 58) . "\tSyncKey: $synckey\n");
107
-
108
-                //Find the offset for this collections messages
109
-                if (preg_match("/Processing $collectionId\.\.\./", $part, $match, PREG_OFFSET_CAPTURE, $offset)) {
110
-                    // print_r($match);
111
-                    $offset = $match01 ?? null;
112
-                    //Find the actual changes
113
-                    if ($offset && preg_match('/found \(added\/changed\/deleted\) (.*)\/(.*)\/(.*) entries for sync from server to client/', $part, $changesMatch, PREG_OFFSET_CAPTURE, $offset)) {
114
-                        // If the offset is too large we are looking at the next collection.
115
-                        if ($changesMatch01 - $offset < 200) {
116
-                            print("    " . $changesMatch00 . "\n");
117
-                        }
118
-                    }
119
-                }
120
-                //TODO We could figure out what the diff per collection was in terms of synckey to the last sync
121
-                //TODO We could figure out what we actually return in the response compared to the detected changeset
122
-                //TODO Warn if a collection is repeatedly synced with the same synckey, but changes are detected. It may be stuck in a sync loop.
123
-            }
124
-        }
125
-
126
-        // Detect entries that are being added from the client
127
-        if (preg_match_all('/found (.*) entries to be added on server/', $part, $matches)) {
128
-            foreach ($matches0 ??  as $match) {
129
-                print("  " . $match . "\n");
130
-            }
131
-        }
132
-
133
-        if (preg_match_all('/found (.*) entries to be updated on server/', $part, $matches)) {
134
-            foreach ($matches0 ??  as $match) {
135
-                print("  " . $match . "\n");
136
-            }
137
-        }
138
-
139
-        if (preg_match_all('/found (.*) entries to be deleted on server/', $part, $matches)) {
140
-            foreach ($matches0 ??  as $match) {
141
-                print("  " . $match . "\n");
142
-            }
143
-        }
144
-    }
145
-    //TODO on Sync:
146
-    //* number of Add/Change/Remove from client and from server
147
-    //* Synckey
148
-    //* list involved folders
149
-    //TODO on Sync:
150
-    //* Reason for interruption
151
-}
152
kolab-syncroton-2.4.2.tar.gz/bin/delete-device.php Deleted
100
 
1
@@ -1,98 +0,0 @@
2
-#!/usr/bin/env php
3
-<?php
4
-
5
-/*
6
- +--------------------------------------------------------------------------+
7
- | Kolab Sync (ActiveSync for Kolab)                                        |
8
- |                                                                          |
9
- | Copyright (C) 2024, Apheleia IT AG <contact@apheleia-it.ch>         |
10
- |                                                                          |
11
- | This program is free software: you can redistribute it and/or modify     |
12
- | it under the terms of the GNU Affero General Public License as published |
13
- | by the Free Software Foundation, either version 3 of the License, or     |
14
- | (at your option) any later version.                                      |
15
- |                                                                          |
16
- | This program is distributed in the hope that it will be useful,          |
17
- | but WITHOUT ANY WARRANTY; without even the implied warranty of           |
18
- | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the             |
19
- | GNU Affero General Public License for more details.                      |
20
- |                                                                          |
21
- | You should have received a copy of the GNU Affero General Public License |
22
- | along with this program. If not, see <http://www.gnu.org/licenses/>      |
23
- +--------------------------------------------------------------------------+
24
- | Author: Christian Mollekopf <mollekopf@apheleia-it.ch>                      |
25
- +--------------------------------------------------------------------------+
26
-*/
27
-
28
-
29
-define('RCUBE_INSTALL_PATH', realpath(dirname(__FILE__) . '/../') . '/');
30
-define('RCUBE_PLUGINS_DIR', RCUBE_INSTALL_PATH . 'lib/plugins/');
31
-
32
-// Define include path
33
-$include_path  = RCUBE_INSTALL_PATH . 'lib' . PATH_SEPARATOR;
34
-$include_path .= RCUBE_INSTALL_PATH . 'lib/ext' . PATH_SEPARATOR;
35
-$include_path .= ini_get('include_path');
36
-set_include_path($include_path);
37
-
38
-// include composer autoloader (if available)
39
-if (@file_exists(RCUBE_INSTALL_PATH . 'vendor/autoload.php')) {
40
-    require RCUBE_INSTALL_PATH . 'vendor/autoload.php';
41
-}
42
-
43
-// include global functions from Roundcube Framework
44
-require_once 'Roundcube/bootstrap.php';
45
-
46
-$opts = rcube_utils::get_opt(
47
-    's' => 'since', // Deletes *all* devices that haven't been used since the given timestamp. Doesn't take owner and device id into account. Timestamp format e.g.: "2024-11-01"
48
-    'o' => 'owner',
49
-    'd' => 'deviceid',
50
-);
51
-
52
-$rcube = \rcube::get_instance();
53
-$db    = $rcube->get_dbh();
54
-
55
-if (!empty($opts'since')) {
56
-    $since = $opts'since';
57
-    $since = new DateTime($since);
58
-    print("Removing all devices that haven't been used since: " . $since->format('Y-m-d H:i:s') . "\n");
59
-
60
-    $db->query(
61
-        "DELETE FROM `syncroton_device`"
62
-        . " WHERE `lastping` < ? OR `lastping` = NULL",
63
-        $since->format('Y-m-d H:i:s')
64
-    );
65
-    return;
66
-}
67
-
68
-if (empty($opts'deviceid')) {
69
-    rcube::raise_error("Device id not specified (--deviceid).", false, true);
70
-}
71
-$device = $opts'deviceid';
72
-
73
-if (empty($opts'owner')) {
74
-    rcube::raise_error("owner not specified (--owner).", false, true);
75
-}
76
-$owner = $opts'owner';
77
-
78
-$select = $db->query(
79
-    "SELECT `user_id` FROM `users`"
80
-    . " WHERE `username` = ?"
81
-    . " ORDER BY `user_id` DESC",
82
-    \strtolower($owner)
83
-);
84
-
85
-if ($data = $db->fetch_assoc($select)) {
86
-    $userid = $data'user_id';
87
-} else {
88
-    rcube::raise_error("User not found in roundcube database, aborting: $email.", false, true);
89
-}
90
-
91
-print("Found the user with id: $userid\n");
92
-
93
-$db->query(
94
-    "DELETE FROM syncroton_device WHERE owner_id = ? AND deviceid = ?",
95
-    $userid,
96
-    $device
97
-);
98
-
99
-print("Deleted the device with the deviceid: $deviceid\n");
100
kolab-syncroton-2.4.2.tar.gz/bin/inspect.php Deleted
350
 
1
@@ -1,348 +0,0 @@
2
-#!/usr/bin/env php
3
-<?php
4
-
5
-/*
6
- +--------------------------------------------------------------------------+
7
- | Kolab Sync (ActiveSync for Kolab)                                        |
8
- |                                                                          |
9
- | Copyright (C) 2024, Apheleia IT AG <contact@apheleia-it.ch>         |
10
- |                                                                          |
11
- | This program is free software: you can redistribute it and/or modify     |
12
- | it under the terms of the GNU Affero General Public License as published |
13
- | by the Free Software Foundation, either version 3 of the License, or     |
14
- | (at your option) any later version.                                      |
15
- |                                                                          |
16
- | This program is distributed in the hope that it will be useful,          |
17
- | but WITHOUT ANY WARRANTY; without even the implied warranty of           |
18
- | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the             |
19
- | GNU Affero General Public License for more details.                      |
20
- |                                                                          |
21
- | You should have received a copy of the GNU Affero General Public License |
22
- | along with this program. If not, see <http://www.gnu.org/licenses/>      |
23
- +--------------------------------------------------------------------------+
24
- | Author: Christian Mollekopf <mollekopf@apheleia-it.ch>                      |
25
- +--------------------------------------------------------------------------+
26
-*/
27
-
28
-
29
-define('RCUBE_INSTALL_PATH', realpath(dirname(__FILE__) . '/../') . '/');
30
-define('RCUBE_PLUGINS_DIR', RCUBE_INSTALL_PATH . 'lib/plugins/');
31
-
32
-// Define include path
33
-$include_path  = RCUBE_INSTALL_PATH . 'lib' . PATH_SEPARATOR;
34
-$include_path .= RCUBE_INSTALL_PATH . 'lib/ext' . PATH_SEPARATOR;
35
-$include_path .= ini_get('include_path');
36
-set_include_path($include_path);
37
-
38
-// include composer autoloader (if available)
39
-if (@file_exists(RCUBE_INSTALL_PATH . 'vendor/autoload.php')) {
40
-    require RCUBE_INSTALL_PATH . 'vendor/autoload.php';
41
-}
42
-
43
-// include global functions from Roundcube Framework
44
-require_once 'Roundcube/bootstrap.php';
45
-
46
-
47
-function filterTypeToIMAPSearch($filter_type = 0)
48
-{
49
-    switch ($filter_type) {
50
-        case 1:
51
-            $mod = '-1 day';
52
-            break;
53
-        case 2:
54
-            $mod = '-3 days';
55
-            break;
56
-        case 3:
57
-            $mod = '-1 week';
58
-            break;
59
-        case 4:
60
-            $mod = '-2 weeks';
61
-            break;
62
-        case 5:
63
-            $mod = '-1 month';
64
-            break;
65
-    }
66
-
67
-    if (!empty($mod)) {
68
-        $dt = new DateTime('now', new DateTimeZone('UTC'));
69
-        $dt->modify($mod);
70
-        // RFC3501: IMAP SEARCH
71
-        return 'SINCE ' . $dt->format('d-M-Y');
72
-    }
73
-
74
-    return "";
75
-}
76
-
77
-
78
-$opts = rcube_utils::get_opt(
79
-    'e' => 'email',
80
-    'p' => 'adminpassword',
81
-    'd' => 'debug',
82
-);
83
-
84
-if (empty($opts'email')) {
85
-    rcube::raise_error("Email address not specified (--email).", false, true);
86
-}
87
-$email = $opts'email';
88
-
89
-$proxyAuth = false;
90
-if ($password = $opts'adminpassword') {
91
-    $proxyAuth = true;
92
-    $user = "cyrus-admin";
93
-} else {
94
-    $password = $opts'password';
95
-}
96
-
97
-if (empty($password)) {
98
-    rcube::raise_error("Password not specified (--adminpassword/--password).", false, true);
99
-}
100
-
101
-$rcube = rcube::get_instance();
102
-$default_port = $rcube->config->get('default_port', 143);
103
-$default_host = $rcube->config->get('default_host');
104
-$imap = new \rcube_imap_generic();
105
-if ($proxyAuth) {
106
-    $options'auth_cid' = $user;
107
-    $options'auth_pw' = $password;
108
-}
109
-$options'auth_type' = 'PLAIN';
110
-$options'port' = $default_port;
111
-$options'socket_options' = 
112
-    'ssl' => 
113
-        'verify_peer_name' => false,
114
-        'verify_peer' => false,
115
-        'allow_self_signed' => true,
116
-    ,
117
-;
118
-
119
-ini_set('display_errors', 1);
120
-error_reporting(E_ALL);
121
-
122
-$debug = !empty($opts'debug');
123
-
124
-$imap->setDebug($debug);
125
-if (!$imap->connect($default_host, $email, $password, $options)) {
126
-    rcube::raise_error("Failed to connect to imap.", false, true);
127
-}
128
-
129
-$rcube = \rcube::get_instance();
130
-$db    = $rcube->get_dbh();
131
-
132
-$select = $db->query(
133
-    "SELECT `user_id` FROM `users`"
134
-    . " WHERE `username` = ?"
135
-    . " ORDER BY `user_id` DESC",
136
-    \strtolower($email)
137
-);
138
-
139
-if ($data = $db->fetch_assoc($select)) {
140
-    $userid = $data'user_id';
141
-} else {
142
-    rcube::raise_error("User not found in roundcube database (only available after first login): $email.", false, true);
143
-}
144
-
145
-print("Found the user with id: $userid\n");
146
-
147
-$devicesSelect = $db->query(
148
-    "SELECT `id`, `deviceid`, `devicetype` FROM `syncroton_device`"
149
-    . " WHERE `owner_id` = ?",
150
-    $userid
151
-);
152
-
153
-$result = ;
154
-while ($data = $db->fetch_assoc($devicesSelect)) {
155
-    $deviceid = $data"deviceid";
156
-    $device_id = $data"id";
157
-
158
-    $result$device_id'deviceid' = $deviceid;
159
-    $result$device_id'device_id' = $device_id;
160
-    $result$device_id'devicetype' = $data"devicetype";
161
-
162
-    $select = $db->limitquery(
163
-        "SELECT `counter`, `lastsync` FROM `syncroton_synckey`"
164
-        . " WHERE `device_id` = ? AND `type` = 'FolderSync'"
165
-        . " ORDER BY `counter` DESC",
166
-        0,
167
-        1,
168
-        $device_id
169
-    );
170
-
171
-    if ($data = $db->fetch_assoc($select)) {
172
-        $result$device_id'FolderSync' = 
173
-            "counter" => $data'counter',
174
-            "lastsync" => $data'lastsync',
175
-        ;
176
-    } else {
177
-        echo("Synckey not found.\n");
178
-    }
179
-
180
-    $folderSelect = $db->query(
181
-        "SELECT * FROM `syncroton_folder`"
182
-        . " WHERE `device_id` = ?",
183
-        $device_id
184
-    );
185
-
186
-    while ($folder = $db->fetch_assoc($folderSelect)) {
187
-        $select = $db->limitquery(
188
-            "SELECT `counter`, `lastsync`, `extra_data` FROM `syncroton_synckey`"
189
-            . " WHERE `device_id` = ? AND `type` = ?"
190
-            . " ORDER BY `counter` DESC",
191
-            0,
192
-            1,
193
-            $device_id,
194
-            $folder'id'
195
-        );
196
-
197
-        if ($data = $db->fetch_assoc($select)) {
198
-            $result$device_id'folders'$folder'id' = 
199
-                "counter" => $data'counter',
200
-                "lastsync" => $data'lastsync',
201
-                "modseq" => $data'extra_data' ? json_decode($data'extra_data')->modseq : null,
202
-            ;
203
-        }
204
-
205
-        $result$device_id'folders'$folder'id''name' = $folder'displayname';
206
-        $result$device_id'folders'$folder'id''folderid' = $folder'folderid';
207
-        $result$device_id'folders'$folder'id''class' = $folder'class';
208
-        $result$device_id'folders'$folder'id''lastfiltertype' = $folder'lastfiltertype' ?? null;
209
-
210
-        $imap->select($folder'displayname');
211
-        $result$device_id'folders'$folder'id''imapModseq' = $imap->data'HIGHESTMODSEQ' ?? null;
212
-
213
-        $index = $imap->search(
214
-            $folder'displayname',
215
-            'ALL UNDELETED ' . filterTypeToIMAPSearch($folder'lastfiltertype'),
216
-            false,
217
-            'COUNT'
218
-        );
219
-        if (!$index->is_error()) {
220
-            $result$device_id'folders'$folder'id''imapMessagecount' = $index->count();
221
-        }
222
-
223
-        $select = $db->query(
224
-            "SELECT count(*) FROM `syncroton_content`"
225
-            . " WHERE `device_id` = ? AND `folder_id` = ?",
226
-            $device_id,
227
-            $folder'id'
228
-        );
229
-
230
-        if ($data = $db->fetch_assoc($select)) {
231
-            $result$device_id'folders'$folder'id''contentCount' = array_values($data)0;
232
-        }
233
-    }
234
-}
235
-
236
-if ($debug) {
237
-    var_export($result);
238
-}
239
-
240
-function println($output)
241
-{
242
-    print("{$output}\n");
243
-}
244
-
245
-function filterType($value)
246
-{
247
-    if (!$value) {
248
-        return "No filter";
249
-    }
250
-    switch ($value) {
251
-        case 0: return "No filter";
252
-        case 1: return "1 day";
253
-        case 2: return "3 days";
254
-        case 3: return "1 week";
255
-        case 4: return "2 weeks";
256
-        case 5: return "1 month";
257
-        case 6: return "3 months (WARNING: not implemented)";
258
-        case 7: return "6 months (WARNING: not implemented)";
259
-        case 8: return "Filter by incomplete tasks";
260
-    }
261
-    return "Unknown value: $value";
262
-}
263
-
264
-function getContentUids($db, $device_id, $folder_id)
265
-{
266
-    $contentSelect = $db->query(
267
-        "SELECT contentid FROM `syncroton_content`"
268
-        . " WHERE `device_id` = ? AND `folder_id` = ? AND `is_deleted` = 0",
269
-        $device_id,
270
-        $folder_id
271
-    );
272
-
273
-    $contentUids = ;
274
-    while ($content = $db->fetch_assoc($contentSelect)) {
275
-        $contentUids = explode('::', $content'contentid')1;
276
-    }
277
-    return $contentUids;
278
-}
279
-
280
-function getImapUids($imap, $folder, $lastfiltertype)
281
-{
282
-    $imap->select($folder);
283
-    $index = $imap->search($folder, 'ALL UNDELETED ' . filterTypeToIMAPSearch($lastfiltertype), true);
284
-    if (!$index->is_error()) {
285
-        return $index->get();
286
-    }
287
-    return ;
288
-}
289
-
290
-println("");
291
-foreach ($result as $deviceId => $values) {
292
-    $device_id = $values'deviceid';
293
-    println("Device: $device_id ($deviceId)");
294
-    println("  Last folder sync: " . $values'FolderSync''lastsync');
295
-    println("  Folder sync count: " . $values'FolderSync''counter');
296
-    println("  Folders:");
297
-    foreach ($values'folders' ??  as $folderId => $folder) {
298
-        $folder_id = $folder'folderid';
299
-        println("    " . $folder'name' . " $folder_id ($folderId)");
300
-        $messageCount = $folder'contentCount';
301
-        $totalCount = $folder'imapMessagecount' ?? "unknown";
302
-        $modseq = $folder'modseq' ?? "none";
303
-        $imapModseq = $folder'imapModseq';
304
-        // We're not using modseq for groupware folders
305
-        if ($messageCount == $totalCount && ($modseq == "none" || $modseq == $imapModseq)) {
306
-            println("    Status: Fully Synced ($messageCount messages)");
307
-        } else {
308
-            println("    Status: Incomplete ($messageCount/$totalCount messages)");
309
-            println("    Modseq: " . $modseq . "/" . $imapModseq);
310
-        }
311
-        println("    Last sync: " . ($folder'lastsync' ?? "None"));
312
-        println("    Number of syncs: " . ($folder'counter' ?? "None"));
313
-        println("    Filter type: " . filterType($folder'lastfiltertype' ?? null));
314
-
315
-        if (($folder'class' == "Email") && ($folder'counter' ?? false) && $messageCount != $totalCount && ($modseq == "none" || $modseq == $imapModseq)) {
316
-            if (($folder'lastfiltertype' ?? false) && $messageCount > $totalCount) {
317
-                // This doesn't have to indicate an issue, since the timewindow of the filter wanders, so some messages that have been synchronized may no longer match the window.
318
-            } else {
319
-                println("    Issue Detected: The sync state seems to be inconsistent. The device should be fully synced, but the sync counts differ.");
320
-                println("    There are $messageCount ContentParts (should match number of messages on the device), but $totalCount messages in IMAP matching the filter.");
321
-
322
-                $contentUids = getContentUids($db, $deviceId, $folderId);
323
-                $imapUids = getImapUids($imap, $folder'name', $folder'lastfiltertype' ?? null);
324
-
325
-                $entries = array_diff($imapUids, $contentUids);
326
-                if (!empty($entries)) {
327
-                    println("       The following messages are on the server, but not the device:");
328
-                    foreach ($entries as $uid) {
329
-                        println("           $uid");
330
-                        //TODO get details from imap?
331
-                    }
332
-                }
333
-
334
-                $entries = array_diff($contentUids, $imapUids);
335
-                if (!empty($entries)) {
336
-                    println("       The following messages are on the device, but not the server:");
337
-                    foreach ($entries as $uid) {
338
-                        println("           $uid");
339
-                        //TODO get details from the content part?
340
-                        //TODO display creation_synckey?
341
-                    }
342
-                }
343
-                println("");
344
-            }
345
-        }
346
-
347
-        println("");
348
-    }
349
-}
350
kolab-syncroton-2.4.2.tar.gz/bin/resync.php Deleted
120
 
1
@@ -1,118 +0,0 @@
2
-#!/usr/bin/php
3
-<?php
4
-
5
-/*
6
- +--------------------------------------------------------------------------+
7
- | Kolab Sync (ActiveSync for Kolab)                                        |
8
- |                                                                          |
9
- | Copyright (C) 2024, Apheleia IT AG <contact@apheleia-it.ch>              |
10
- |                                                                          |
11
- | This program is free software: you can redistribute it and/or modify     |
12
- | it under the terms of the GNU Affero General Public License as published |
13
- | by the Free Software Foundation, either version 3 of the License, or     |
14
- | (at your option) any later version.                                      |
15
- |                                                                          |
16
- | This program is distributed in the hope that it will be useful,          |
17
- | but WITHOUT ANY WARRANTY; without even the implied warranty of           |
18
- | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the             |
19
- | GNU Affero General Public License for more details.                      |
20
- |                                                                          |
21
- | You should have received a copy of the GNU Affero General Public License |
22
- | along with this program. If not, see <http://www.gnu.org/licenses/>      |
23
- +--------------------------------------------------------------------------+
24
- | Author: Aleksander Machniak <machniak@apheleia-it.ch>                    |
25
- +--------------------------------------------------------------------------+
26
-*/
27
-
28
-define('RCUBE_INSTALL_PATH', realpath(dirname(__FILE__) . '/../') . '/');
29
-define('RCUBE_PLUGINS_DIR', RCUBE_INSTALL_PATH . 'lib/plugins/');
30
-
31
-// Define include path
32
-$include_path  = RCUBE_INSTALL_PATH . 'lib' . PATH_SEPARATOR;
33
-$include_path .= RCUBE_INSTALL_PATH . 'lib/ext' . PATH_SEPARATOR;
34
-$include_path .= ini_get('include_path');
35
-set_include_path($include_path);
36
-
37
-// include composer autoloader (if available)
38
-if (@file_exists(RCUBE_INSTALL_PATH . 'vendor/autoload.php')) {
39
-    require RCUBE_INSTALL_PATH . 'vendor/autoload.php';
40
-}
41
-
42
-// include global functions from Roundcube Framework
43
-require_once 'Roundcube/bootstrap.php';
44
-
45
-$opts = rcube_utils::get_opt(
46
-    'o' => 'owner',
47
-    'f' => 'folder',
48
-    'd' => 'deviceid',
49
-    't' => 'devicetype', // e.g. WindowsOutlook15 or iPhone
50
-);
51
-
52
-$rcube = \rcube::get_instance();
53
-$db    = $rcube->get_dbh();
54
-
55
-if (empty($opts'owner')) {
56
-    rcube::raise_error("Owner not specified (--owner).", false, true);
57
-}
58
-if (empty($opts'folder')) {
59
-    rcube::raise_error("Folder name not specified (--folder).", false, true);
60
-}
61
-
62
-$select = $db->query(
63
-    "SELECT `user_id` FROM `users` WHERE `username` = ? ORDER BY `user_id` DESC",
64
-    \strtolower($opts'owner')
65
-);
66
-
67
-if ($data = $db->fetch_assoc($select)) {
68
-    $userid = $data'user_id';
69
-} else {
70
-    rcube::raise_error("User not found in Roundcube database.", false, true);
71
-}
72
-
73
-$devices = ;
74
-if (!empty($opts'deviceid')) {
75
-    $select = $db->query(
76
-        "SELECT `id` FROM `syncroton_device` WHERE `owner_id` = ? AND `deviceid` = ?",
77
-        $userid,
78
-        $opts'deviceid'
79
-    );
80
-    while ($record = $db->fetch_assoc($select)) {
81
-        $devices = $record'id';
82
-    }
83
-} elseif (!empty($opts'devicetype')) {
84
-    $select = $db->query(
85
-        "SELECT `id` FROM `syncroton_device` WHERE `owner_id` = ? AND `devicetype` = ?",
86
-        $userid,
87
-        $opts'devicetype'
88
-    );
89
-    while ($record = $db->fetch_assoc($select)) {
90
-        $devices = $record'id';
91
-    }
92
-} else {
93
-    $select = $db->query("SELECT `id` FROM `syncroton_device` WHERE `owner_id` = ?", $userid);
94
-    while ($record = $db->fetch_assoc($select)) {
95
-        $devices = $record'id';
96
-    }
97
-}
98
-
99
-if (empty($devices)) {
100
-    rcube::raise_error("Device not found.", false, true);
101
-}
102
-
103
-// TODO: Support not only top-level folders
104
-
105
-$select = $db->query(
106
-    "SELECT syncroton_folder.id, `displayname`, `folderid`, `deviceid` FROM `syncroton_folder`"
107
-    . " JOIN `syncroton_device` ON syncroton_device.id = syncroton_folder.device_id"
108
-    . " WHERE `device_id` IN (" . $db->array2list($devices) . ")"
109
-    . " AND `parentid` = '0' AND `displayname` = " . $db->quote($opts'folder')
110
-);
111
-
112
-while ($record = $db->fetch_assoc($select)) {
113
-    if (!empty($opts'dry-run')) {
114
-        print("DRY-RUN {$record'displayname'} {$record'deviceid'} ({$record'id'}:{$record'folderid'})\n");
115
-    } else {
116
-        $db->query("UPDATE `syncroton_folder` SET `resync` = 1 WHERE id = ?", $record'id');
117
-        print("{$record'displayname'} {$record'deviceid'} ({$record'id'}:{$record'folderid'})\n");
118
-    }
119
-}
120
kolab-syncroton-2.4.2.tar.gz/docs/SQL/mysql.initial.sql Changed
18
 
1
@@ -44,10 +44,8 @@
2
     `displayname` varchar(254) NOT NULL,
3
     `type` int(11) NOT NULL,
4
     `creation_time` datetime NOT NULL,
5
-    `creation_synckey` int(11) NOT NULL DEFAULT '0',
6
     `lastfiltertype` int(11) DEFAULT NULL,
7
     `supportedfields` longblob DEFAULT NULL,
8
-    `resync` tinyint(1) DEFAULT NULL,
9
     PRIMARY KEY (`id`),
10
     UNIQUE KEY `device_id--class--folderid` (`device_id`(40),`class`(40),`folderid`(40)),
11
     KEY `folderstates::device_id--devices::id` (`device_id`),
12
@@ -117,4 +115,4 @@
13
  PRIMARY KEY(`name`)
14
 ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
15
 
16
-INSERT INTO `system` (`name`, `value`) VALUES ('syncroton-version', '2024102300');
17
+INSERT INTO `system` (`name`, `value`) VALUES ('syncroton-version', '2024031100');
18
kolab-syncroton-2.4.2.tar.gz/docs/SQL/mysql/2024101700.sql Deleted
3
 
1
@@ -1,1 +0,0 @@
2
-ALTER TABLE `syncroton_folder` ADD `resync` tinyint(1) DEFAULT NULL;
3
kolab-syncroton-2.4.2.tar.gz/docs/SQL/mysql/2024102300.sql Deleted
3
 
1
@@ -1,1 +0,0 @@
2
-ALTER TABLE `syncroton_folder` ADD `creation_synckey` int(11) NOT NULL DEFAULT '0';
3
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/ABackend.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/Content.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/Device.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/Folder.php Changed
28
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -52,7 +51,7 @@
8
      * (non-PHPdoc)
9
      * @see Syncroton_Backend_IFolder::getFolderState()
10
      */
11
-    public function getFolderState($deviceId, $class, $syncKey)
12
+    public function getFolderState($deviceId, $class)
13
     {
14
         $deviceId = $deviceId instanceof Syncroton_Model_IDevice ? $deviceId->id : $deviceId;
15
 
16
@@ -86,11 +85,6 @@
17
         $this->_db->delete($this->_tablePrefix . $this->_tableName, $where);
18
     }
19
 
20
-    public function exists($deviceid, $folderid)
21
-    {
22
-        return false; // not implemented
23
-    }
24
-
25
     /**
26
      * (non-PHPdoc)
27
      * @see Syncroton_Backend_IFolder::hasHierarchyChanges()
28
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/IBackend.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/IContent.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/IDevice.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/IFolder.php Changed
34
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -33,10 +32,9 @@
8
      *
9
      * @param  Syncroton_Model_Device|string  $deviceId
10
      * @param  string                         $class
11
-     * @param  int                            $syncKey
12
      * @return array
13
      */
14
-    public function getFolderState($deviceId, $class, $syncKey);
15
+    public function getFolderState($deviceId, $class);
16
 
17
     /**
18
      * delete all stored folderId's for given device
19
@@ -53,14 +51,4 @@
20
      * @return bool True if folders hierarchy changed, False otherwise
21
      */
22
     public function hasHierarchyChanges($device);
23
-
24
-    /**
25
-     * Check if the folder already exists
26
-     *
27
-     * @param Syncroton_Model_Device|string  $deviceid Device object or identifier
28
-     * @param string                         $folderid Folder identifier
29
-     *
30
-     * @return bool true if it exists
31
-     */
32
-    public function exists($deviceid, $folderid);
33
 }
34
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/ISyncState.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/Policy.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/SyncState.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/AutoDiscover.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/FolderCreate.php Changed
24
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -64,7 +63,7 @@
8
             return;
9
         }
10
 
11
-        switch ($folder->type) {
12
+        switch($folder->type) {
13
             case Syncroton_Command_FolderSync::FOLDERTYPE_CALENDAR_USER_CREATED:
14
                 $folder->class = Syncroton_Data_Factory::CLASS_CALENDAR;
15
                 break;
16
@@ -101,7 +100,6 @@
17
                 $this->_folder->class        = $folder->class;
18
                 $this->_folder->deviceId     = $this->_device->id;
19
                 $this->_folder->creationTime = $this->_syncTimeStamp;
20
-                $this->_folder->creationSynckey = $this->_syncState->counter;
21
 
22
                 // Check if the folder already exists to avoid a duplicate insert attempt in db
23
                 try {
24
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/FolderDelete.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/FolderSync.php Changed
154
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -69,11 +68,6 @@
8
     protected $_syncKey;
9
 
10
     /**
11
-     * @var bool
12
-     */
13
-    protected $_syncKeyReused = false;
14
-
15
-    /**
16
      * Parse FolderSync request
17
      */
18
     public function handle()
19
@@ -97,20 +91,9 @@
20
             $this->_syncStateBackend->resetState($this->_device, 'FolderSync');
21
 
22
             return;
23
-        } else {
24
-            // The synckey that is sent to us should already be existing, because we create it at the end,
25
-            // however, the next one shouldn't
26
-            if ($this->_syncStateBackend->haveNext($this->_device, 'FolderSync', $syncKey)) {
27
-                $this->_syncKeyReused = true;
28
-                if ($this->_logger instanceof Zend_Log) {
29
-                    $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " already known synckey $syncKey provided");
30
-                }
31
-            }
32
         }
33
+
34
         if (!($this->_syncState = $this->_syncStateBackend->validate($this->_device, 'FolderSync', $syncKey)) instanceof Syncroton_Model_SyncState) {
35
-            if ($this->_logger instanceof Zend_Log) {
36
-                $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " invalid synckey $syncKey provided, invalidating sync state");
37
-            }
38
             $this->_syncStateBackend->resetState($this->_device, 'FolderSync');
39
         }
40
     }
41
@@ -144,7 +127,7 @@
42
         $updates = ;
43
         $deletes = ;
44
 
45
-        foreach ($this->_classes as $class) {
46
+        foreach($this->_classes as $class) {
47
             try {
48
                 $dataController = Syncroton_Data_Factory::factory($class, $this->_device, $this->_syncTimeStamp);
49
             } catch (Exception $e) {
50
@@ -160,7 +143,7 @@
51
                 $serverFolders = $dataController->getAllFolders();
52
 
53
                 // retrieve all folders sent to client
54
-                $clientFolders = $this->_folderBackend->getFolderState($this->_device, $class, $this->_syncState->counter);
55
+                $clientFolders = $this->_folderBackend->getFolderState($this->_device, $class);
56
 
57
                 if ($this->_syncState->counter > 0) {
58
                     // retrieve all folders changed since last sync
59
@@ -211,7 +194,6 @@
60
                 } else {
61
                     $add = $serverFolders$serverFolderId;
62
                     $add->creationTime = $this->_syncTimeStamp;
63
-                    $add->creationSynckey = $this->_syncState->counter + 1;
64
                     $add->deviceId     = $this->_device->id;
65
                     unset($add->id);
66
                 }
67
@@ -252,17 +234,6 @@
68
                 }
69
             }
70
 
71
-            // Handle folders set for forced re-sync, we'll send a delete action to the client,
72
-            // but because the folder is still existing and subscribed on the backend it should
73
-            // "immediately" be added again (and re-synced).
74
-            $forceDeleteIds = array_keys(array_filter($clientFolders, function ($f) { return !empty($f->resync); }));
75
-            if (!empty($forceDeleteIds)) {
76
-                if ($this->_logger instanceof Zend_Log) {
77
-                    $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " forcing resync of: " . var_export($forceDeleteIds, true));
78
-                }
79
-            }
80
-            $serverFoldersIds = array_diff($serverFoldersIds, $forceDeleteIds);
81
-
82
             // calculate deleted entries
83
             $serverDiff = array_diff($clientFoldersIds, $serverFoldersIds);
84
             foreach ($serverDiff as $serverFolderId) {
85
@@ -272,53 +243,48 @@
86
 
87
         $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', self::STATUS_SUCCESS));
88
 
89
-        $newSyncKey = $this->_syncState->counter;
90
         $count = count($adds) + count($updates) + count($deletes);
91
-        if ($count > 0) {
92
-            $newSyncKey++;
93
+        if($count > 0) {
94
+            $this->_syncState->counter++;
95
+            $this->_syncState->lastsync = $this->_syncTimeStamp;
96
         }
97
 
98
         // create xml output
99
-        $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'SyncKey', $newSyncKey));
100
+        $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'SyncKey', $this->_syncState->counter));
101
 
102
         $changes = $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Changes'));
103
         $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Count', $count));
104
 
105
-        foreach ($adds as $folder) {
106
+        foreach($adds as $folder) {
107
             $add = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Add'));
108
 
109
             $folder->appendXML($add, $this->_device);
110
 
111
-            if (!$this->_syncKeyReused && empty($folder->id)) {
112
-                // The folder could exist in the backend if we e.g. delete the same name and then recreate,
113
-                // or disable/reenable for syncing.
114
-                if (!$this->_folderBackend->exists($this->_device->id, $folder->serverId)) {
115
-                    $this->_folderBackend->create($folder);
116
-                }
117
+            // store folder in backend
118
+            if (empty($folder->id)) {
119
+                $this->_folderBackend->create($folder);
120
             }
121
         }
122
 
123
-        foreach ($updates as $folder) {
124
+        foreach($updates as $folder) {
125
             $update = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Update'));
126
 
127
             $folder->appendXML($update, $this->_device);
128
+
129
             $this->_folderBackend->update($folder);
130
         }
131
 
132
-        foreach ($deletes as $folder) {
133
+        foreach($deletes as $folder) {
134
             $delete = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Delete'));
135
             $delete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'ServerId', $folder->serverId));
136
 
137
             $this->_folderBackend->delete($folder);
138
         }
139
 
140
-        if ($this->_syncState->counter != $newSyncKey) {
141
-            $this->_syncState->counter = $newSyncKey;
142
-            $this->_syncState->lastsync = $this->_syncTimeStamp;
143
-            // Keep previous sync states in case a sync key is re-sent.
144
-            // We always insert because deleteOtherStates is executed from _syncStateBackend->validate,
145
-            // which means we remove and re-insert the latest state on key resend.
146
-            $this->_syncStateBackend->create($this->_syncState, true); // @phpstan-ignore-line
147
+        if (empty($this->_syncState->id)) {
148
+            $this->_syncStateBackend->create($this->_syncState);
149
+        } else {
150
+            $this->_syncStateBackend->update($this->_syncState);
151
         }
152
 
153
         return $this->_outputDom;
154
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/FolderUpdate.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/GetAttachment.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/GetItemEstimate.php Changed
34
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -60,7 +59,7 @@
8
                 $collectionData'folder' = $this->_folderBackend->getFolder($this->_device, $collectionData'collectionId');
9
                 $collectionData'folder'->lastfiltertype = $collectionData'filterType';
10
 
11
-                if ($collectionData'syncKey' === 0) {
12
+                if($collectionData'syncKey' === 0) {
13
                     $collectionData'syncState' = new Syncroton_Model_SyncState(
14
                         'device_id' => $this->_device,
15
                         'counter'   => 0,
16
@@ -93,7 +92,7 @@
17
     {
18
         $itemEstimate = $this->_outputDom->documentElement;
19
 
20
-        foreach ($this->_collections as $collectionData) {
21
+        foreach($this->_collections as $collectionData) {
22
             $response = $itemEstimate->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Response'));
23
 
24
             // invalid collectionid provided
25
@@ -132,7 +131,7 @@
26
                 $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Status', self::STATUS_SUCCESS));
27
                 $collection = $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Collection'));
28
                 $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'CollectionId', $collectionData'collectionId'));
29
-                if ($collectionData'syncState'->counter === 0) {
30
+                if($collectionData'syncState'->counter === 0) {
31
                     // this is the first sync. in most cases there are data on the server.
32
                     $count = count($dataController->getServerEntries($collectionData'collectionId', $collectionData'filterType'));
33
                 } else {
34
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/ICommand.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/ItemOperations.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/MeetingResponse.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/MoveItems.php Changed
51
 
1
@@ -59,11 +59,11 @@
2
             $response = $moves->appendChild($this->_outputDom->createElementNS('uri:Move', 'Response'));
3
             $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'SrcMsgId', $move'srcMsgId'));
4
 
5
-            if ($this->_logger instanceof Zend_Log) {
6
-                $this->_logger->info(__METHOD__ . '::' . __LINE__ . " Moving from " . $move'srcFldId' . " to " . $move'dstFldId');
7
-            }
8
-
9
             try {
10
+                if ($move'srcFldId' === $move'dstFldId') {
11
+                    throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::SAME_FOLDER);
12
+                }
13
+
14
                 try {
15
                     $sourceFolder = $this->_folderBackend->getFolder($this->_device, $move'srcFldId');
16
                 } catch (Syncroton_Exception_NotFound $e) {
17
@@ -76,30 +76,19 @@
18
                     throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_DESTINATION);
19
                 }
20
 
21
-                if ($move'srcFldId' === $move'dstFldId') {
22
-                    throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::SAME_FOLDER);
23
-                }
24
-
25
                 $dataController = Syncroton_Data_Factory::factory($sourceFolder->class, $this->_device, $this->_syncTimeStamp);
26
                 $newId          = $dataController->moveItem($move'srcFldId', $move'srcMsgId', $move'dstFldId');
27
+
28
                 if (!$newId) {
29
-                    // We don't actually know what the reason was that this failed, but from the resolution description this error seems to make the most sense,
30
-                    // and we rule out most other reasons before.
31
                     throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_SOURCE);
32
                 }
33
 
34
                 $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'Status', Syncroton_Command_MoveItems::STATUS_SUCCESS));
35
                 $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'DstMsgId', $newId));
36
-            } catch (Syncroton_Exception_Status_MoveItems $e) {
37
-                if ($this->_logger instanceof Zend_Log) {
38
-                    $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " Move failed: " . $e->getMessage());
39
-                }
40
+            } catch (Syncroton_Exception_Status $e) {
41
                 $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'Status', $e->getCode()));
42
             } catch (Exception $e) {
43
-                if ($this->_logger instanceof Zend_Log) {
44
-                    $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " Move failed: " . $e->getMessage());
45
-                }
46
-                $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'Status', Syncroton_Exception_Status_MoveItems::FOLDER_LOCKED));
47
+                $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'Status', Syncroton_Exception_Status::SERVER_ERROR));
48
             }
49
         }
50
 
51
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/Options.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/Ping.php Changed
60
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -53,7 +52,7 @@
8
             $xml = simplexml_import_dom($this->_requestBody);
9
             $xml->registerXPathNamespace('Ping', 'Ping');
10
 
11
-            if (isset($xml->HeartbeatInterval)) {
12
+            if(isset($xml->HeartbeatInterval)) {
13
                 $this->_device->pinglifetime = (int)$xml->HeartbeatInterval;
14
             }
15
 
16
@@ -69,10 +68,6 @@
17
                 $folders = ;
18
                 foreach ($xml->Folders->Folder as $folderXml) {
19
                     try {
20
-                        if (empty((string)$folderXml->Id)) {
21
-                            // Ignore empty folder ids
22
-                            continue;
23
-                        }
24
                         // does the folder exist?
25
                         $folder = $this->_folderBackend->getFolder($this->_device, (string)$folderXml->Id);
26
 
27
@@ -129,7 +124,7 @@
28
             do {
29
                 // take a break to save battery lifetime
30
                 call_user_func($sleepCallback);
31
-                sleep(min(Syncroton_Registry::getPingTimeout(), $lifeTime));
32
+                sleep(Syncroton_Registry::getPingTimeout());
33
 
34
                 // make sure the connection is still alive, abort otherwise
35
                 if (connection_aborted()) {
36
@@ -196,10 +191,6 @@
37
                 $now = new DateTime('now', new DateTimeZone('UTC'));
38
 
39
                 foreach ($folders as $folderId) {
40
-                    if (empty($folderId)) {
41
-                        // Ignore empty folder ids
42
-                        continue;
43
-                    }
44
                     try {
45
                         /** @var Syncroton_Model_Folder $folder */
46
                         $folder         = $this->_folderBackend->get($folderId);
47
@@ -280,10 +271,10 @@
48
 
49
         $ping = $this->_outputDom->documentElement;
50
         $ping->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Status', $status));
51
-        if ($status === self::STATUS_CHANGES_FOUND) {
52
+        if($status === self::STATUS_CHANGES_FOUND) {
53
             $folders = $ping->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Folders'));
54
 
55
-            foreach ($this->_foldersWithChanges as $changedFolder) {
56
+            foreach($this->_foldersWithChanges as $changedFolder) {
57
                 $folder = $folders->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Folder', $changedFolder->serverId));
58
                 if ($this->_logger instanceof Zend_Log) {
59
                     $this->_logger->info(__METHOD__ . '::' . __LINE__ . " DeviceId: " . $this->_device->deviceid . " changes in folder: " . $changedFolder->serverId);
60
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/Provision.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/Search.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/SendMail.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/Settings.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/SmartForward.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/SmartReply.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/Sync.php Changed
427
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -223,7 +222,7 @@
8
             }
9
 
10
             // initial synckey
11
-            if ($collectionData->syncKey === 0) {
12
+            if($collectionData->syncKey === 0) {
13
                 if ($this->_logger instanceof Zend_Log) {
14
                     $this->_logger->info(__METHOD__ . '::' . __LINE__ . " initial client synckey 0 provided");
15
                 }
16
@@ -251,7 +250,7 @@
17
                 }
18
             }
19
             // check for invalid synckey
20
-            if (($collectionData->syncState = $this->_syncStateBackend->validate($this->_device, $collectionData->folder, $collectionData->syncKey)) === false) {
21
+            if(($collectionData->syncState = $this->_syncStateBackend->validate($this->_device, $collectionData->folder, $collectionData->syncKey)) === false) {
22
                 if ($this->_logger instanceof Zend_Log) {
23
                     $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " invalid synckey {$collectionData->syncKey} provided");
24
                 }
25
@@ -267,7 +266,7 @@
26
 
27
             $dataController = Syncroton_Data_Factory::factory($collectionData->folder->class, $this->_device, $this->_syncTimeStamp);
28
 
29
-            switch ($collectionData->folder->class) {
30
+            switch($collectionData->folder->class) {
31
                 case Syncroton_Data_Factory::CLASS_CALENDAR:
32
                     $dataClass = 'Syncroton_Model_Event';
33
                     break;
34
@@ -302,7 +301,7 @@
35
             ;
36
 
37
             // handle incoming data
38
-            if ($collectionData->hasClientAdds()) {
39
+            if($collectionData->hasClientAdds()) {
40
                 $adds = $collectionData->getClientAdds();
41
 
42
                 if ($this->_logger instanceof Zend_Log) {
43
@@ -367,7 +366,7 @@
44
             }
45
 
46
             // handle changes, but only if not first sync
47
-            if (!$syncKeyReused && $collectionData->syncKey > 1 && $collectionData->hasClientChanges()) {
48
+            if(!$syncKeyReused && $collectionData->syncKey > 1 && $collectionData->hasClientChanges()) {
49
                 $changes = $collectionData->getClientChanges();
50
 
51
                 if ($this->_logger instanceof Zend_Log) {
52
@@ -400,7 +399,7 @@
53
             }
54
 
55
             // handle deletes, but only if not first sync
56
-            if (!$syncKeyReused && $collectionData->hasClientDeletes()) {
57
+            if(!$syncKeyReused && $collectionData->hasClientDeletes()) {
58
                 $deletes = $collectionData->getClientDeletes();
59
                 if ($this->_logger instanceof Zend_Log) {
60
                     $this->_logger->info(__METHOD__ . '::' . __LINE__ . " found " . count($deletes) . " entries to be deleted on server");
61
@@ -416,7 +415,7 @@
62
                         try {
63
                             $dataController->deleteEntry($collectionData->collectionId, $serverId, $collectionData);
64
 
65
-                        } catch (Syncroton_Exception_NotFound $e) {
66
+                        } catch(Syncroton_Exception_NotFound $e) {
67
                             if ($this->_logger instanceof Zend_Log) {
68
                                 $this->_logger->crit(__METHOD__ . '::' . __LINE__ . ' tried to delete entry ' . $serverId . ' but entry was not found');
69
                             }
70
@@ -442,7 +441,7 @@
71
             }
72
 
73
             // handle fetches, but only if not first sync
74
-            if ($collectionData->syncKey > 1 && $collectionData->hasClientFetches()) {
75
+            if($collectionData->syncKey > 1 && $collectionData->hasClientFetches()) {
76
                 // the default value for GetChanges is 1. If the phone don't want the changes it must set GetChanges to 0
77
                 // some prevoius versions of iOS did not set GetChanges to 0 for fetches. Let's enforce getChanges to false here.
78
                 $collectionData->getChanges = false;
79
@@ -468,93 +467,6 @@
80
         }
81
     }
82
 
83
-    private function getServerModifications($dataController, $collectionData, $clientModifications)
84
-    {
85
-        $serverModifications = 
86
-            'added'   => ,
87
-            'changed' => ,
88
-            'deleted' => ,
89
-        ;
90
-
91
-        // We first use hasChanges because it has a fast path for when there are no changes by fetching the count of messages only.
92
-        // However, in all other cases we will end up fetching the same entries as below, which is less than ideal.
93
-        // TODO: We should create a new method, which checks if there are no changes, and otherwise just let the code below figure out
94
-        // if there are any changes to process.
95
-        if (!$dataController->hasChanges($this->_contentStateBackend, $collectionData->folder, $collectionData->syncState)) {
96
-            return $serverModifications;
97
-        }
98
-
99
-        // update _syncTimeStamp as $dataController->hasChanges might have spent some time
100
-        $this->_syncTimeStamp = new DateTime('now', new DateTimeZone('UTC'));
101
-
102
-        // fetch entries added since last sync
103
-        $allClientEntries = $this->_contentStateBackend->getFolderState(
104
-            $this->_device,
105
-            $collectionData->folder,
106
-            $collectionData->syncState->counter
107
-        );
108
-
109
-        // fetch entries changed since last sync
110
-        $allChangedEntries = $dataController->getChangedEntries(
111
-            $collectionData->collectionId,
112
-            $collectionData->syncState,
113
-            $collectionData->options'filterType'
114
-        );
115
-
116
-        // fetch all entries
117
-        $allServerEntries = $dataController->getServerEntries(
118
-            $collectionData->collectionId,
119
-            $collectionData->options'filterType'
120
-        );
121
-
122
-        // add entries
123
-        $serverDiff = array_diff($allServerEntries, $allClientEntries);
124
-        // add entries which produced problems during delete from client
125
-        $serverModifications'added' = $clientModifications'forceAdd';
126
-        // add entries not yet sent to client
127
-        $serverModifications'added' = array_unique(array_merge($serverModifications'added', $serverDiff));
128
-
129
-        // @todo still needed?
130
-        foreach ($serverModifications'added' as $id => $serverId) {
131
-            // skip entries added by client during this sync session
132
-            if (isset($clientModifications'added'$serverId) && !isset($clientModifications'forceAdd'$serverId)) {
133
-                if ($this->_logger instanceof Zend_Log) {
134
-                    $this->_logger->info(__METHOD__ . '::' . __LINE__ . " skipped added entry: " . $serverId);
135
-                }
136
-                unset($serverModifications'added'$id);
137
-            }
138
-        }
139
-
140
-        // entries to be deleted
141
-        $serverModifications'deleted' = array_diff($allClientEntries, $allServerEntries);
142
-
143
-        // entries changed since last sync
144
-        $serverModifications'changed' = array_merge($allChangedEntries, $clientModifications'forceChange');
145
-
146
-        foreach ($serverModifications'changed' as $id => $serverId) {
147
-            // skip entry, if it got changed by client during current sync
148
-            if (isset($clientModifications'changed'$serverId) && !isset($clientModifications'forceChange'$serverId)) {
149
-                if ($this->_logger instanceof Zend_Log) {
150
-                    $this->_logger->info(__METHOD__ . '::' . __LINE__ . " skipped changed entry: " . $serverId);
151
-                }
152
-                unset($serverModifications'changed'$id);
153
-            }
154
-            // skip entry, make sure we don't sent entries already added by client in this request
155
-            elseif (isset($clientModifications'added'$serverId) && !isset($clientModifications'forceAdd'$serverId)) {
156
-                if ($this->_logger instanceof Zend_Log) {
157
-                    $this->_logger->info(__METHOD__ . '::' . __LINE__ . " skipped change for added entry: " . $serverId);
158
-                }
159
-                unset($serverModifications'changed'$id);
160
-            }
161
-        }
162
-
163
-        // entries comeing in scope are already in $serverModifications'added' and do not need to
164
-        // be send with $serverCanges
165
-        $serverModifications'changed' = array_diff($serverModifications'changed', $serverModifications'added');
166
-
167
-        return $serverModifications;
168
-    }
169
-
170
     /**
171
      * (non-PHPdoc)
172
      * @see Syncroton_Command_Wbxml::getResponse()
173
@@ -593,7 +505,7 @@
174
 
175
                 $now = new DateTime('now', new DateTimeZone('UTC'));
176
 
177
-                foreach ($this->_collections as $collectionData) {
178
+                foreach($this->_collections as $collectionData) {
179
                     // continue immediately if folder does not exist
180
                     if (! ($collectionData->folder instanceof Syncroton_Model_IFolder)) {
181
                         break 2;
182
@@ -660,7 +572,7 @@
183
                         $dataController = Syncroton_Data_Factory::factory($collectionData->folder->class, $this->_device, $this->_syncTimeStamp);
184
 
185
                         // countinue immediately if there are any changes available
186
-                        if ($dataController->hasChanges($this->_contentStateBackend, $collectionData->folder, $collectionData->syncState)) {
187
+                        if($dataController->hasChanges($this->_contentStateBackend, $collectionData->folder, $collectionData->syncState)) {
188
                             break 2;
189
                         }
190
                     }
191
@@ -751,17 +663,18 @@
192
                 ;
193
 
194
                 $status = self::STATUS_SUCCESS;
195
+                $hasChanges = 0;
196
 
197
                 if ($collectionData->getChanges === true) {
198
                     // continue sync session?
199
-                    if (is_array($collectionData->syncState->pendingdata)) {
200
+                    if(is_array($collectionData->syncState->pendingdata)) {
201
                         $serverModifications = $collectionData->syncState->pendingdata;
202
                         if ($this->_logger instanceof Zend_Log) {
203
-                            $this->_logger->info(__METHOD__ . '::' . __LINE__ . " restored from sync state.");
204
+                            $this->_logger->info(__METHOD__ . '::' . __LINE__ . " restored from sync state: (added/changed/deleted) " . count($serverModifications'added') . '/' . count($serverModifications'changed') . '/' . count($serverModifications'deleted') . ' entries for sync from server to client');
205
                         }
206
                     } else {
207
                         try {
208
-                            $serverModifications = $this->getServerModifications($dataController, $collectionData, $clientModifications);
209
+                            $hasChanges = $dataController->hasChanges($this->_contentStateBackend, $collectionData->folder, $collectionData->syncState);
210
                         } catch (Syncroton_Exception_NotFound $e) {
211
                             if ($this->_logger instanceof Zend_Log) {
212
                                 $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " Folder changes checking failed (not found): " . $e->getTraceAsString());
213
@@ -773,6 +686,85 @@
214
                                 $this->_logger->crit(__METHOD__ . '::' . __LINE__ . " Folder changes checking failed: " . $e->getMessage());
215
                             }
216
 
217
+                            // Prevent from removing client entries when getServerEntries() fails
218
+                            // @todo: should we break the loop here?
219
+                            $status = self::STATUS_SERVER_ERROR;
220
+                        }
221
+                    }
222
+
223
+                    if ($hasChanges) {
224
+                        // update _syncTimeStamp as $dataController->hasChanges might have spent some time
225
+                        $this->_syncTimeStamp = new DateTime('now', new DateTimeZone('UTC'));
226
+
227
+                        try {
228
+                            // fetch entries added since last sync
229
+                            $allClientEntries = $this->_contentStateBackend->getFolderState(
230
+                                $this->_device,
231
+                                $collectionData->folder,
232
+                                $collectionData->syncState->counter
233
+                            );
234
+
235
+                            // fetch entries changed since last sync
236
+                            $allChangedEntries = $dataController->getChangedEntries(
237
+                                $collectionData->collectionId,
238
+                                $collectionData->syncState,
239
+                                $collectionData->options'filterType'
240
+                            );
241
+
242
+                            // fetch all entries
243
+                            $allServerEntries = $dataController->getServerEntries(
244
+                                $collectionData->collectionId,
245
+                                $collectionData->options'filterType'
246
+                            );
247
+
248
+                            // add entries
249
+                            $serverDiff = array_diff($allServerEntries, $allClientEntries);
250
+                            // add entries which produced problems during delete from client
251
+                            $serverModifications'added' = $clientModifications'forceAdd';
252
+                            // add entries not yet sent to client
253
+                            $serverModifications'added' = array_unique(array_merge($serverModifications'added', $serverDiff));
254
+
255
+                            // @todo still needed?
256
+                            foreach($serverModifications'added' as $id => $serverId) {
257
+                                // skip entries added by client during this sync session
258
+                                if(isset($clientModifications'added'$serverId) && !isset($clientModifications'forceAdd'$serverId)) {
259
+                                    if ($this->_logger instanceof Zend_Log) {
260
+                                        $this->_logger->info(__METHOD__ . '::' . __LINE__ . " skipped added entry: " . $serverId);
261
+                                    }
262
+                                    unset($serverModifications'added'$id);
263
+                                }
264
+                            }
265
+
266
+                            // entries to be deleted
267
+                            $serverModifications'deleted' = array_diff($allClientEntries, $allServerEntries);
268
+
269
+                            // entries changed since last sync
270
+                            $serverModifications'changed' = array_merge($allChangedEntries, $clientModifications'forceChange');
271
+
272
+                            foreach($serverModifications'changed' as $id => $serverId) {
273
+                                // skip entry, if it got changed by client during current sync
274
+                                if(isset($clientModifications'changed'$serverId) && !isset($clientModifications'forceChange'$serverId)) {
275
+                                    if ($this->_logger instanceof Zend_Log) {
276
+                                        $this->_logger->info(__METHOD__ . '::' . __LINE__ . " skipped changed entry: " . $serverId);
277
+                                    }
278
+                                    unset($serverModifications'changed'$id);
279
+                                }
280
+                                // skip entry, make sure we don't sent entries already added by client in this request
281
+                                elseif (isset($clientModifications'added'$serverId) && !isset($clientModifications'forceAdd'$serverId)) {
282
+                                    if ($this->_logger instanceof Zend_Log) {
283
+                                        $this->_logger->info(__METHOD__ . '::' . __LINE__ . " skipped change for added entry: " . $serverId);
284
+                                    }
285
+                                    unset($serverModifications'changed'$id);
286
+                                }
287
+                            }
288
+
289
+                            // entries comeing in scope are already in $serverModifications'added' and do not need to
290
+                            // be send with $serverCanges
291
+                            $serverModifications'changed' = array_diff($serverModifications'changed', $serverModifications'added');
292
+                        } catch (Exception $e) {
293
+                            if ($this->_logger instanceof Zend_Log) {
294
+                                $this->_logger->crit(__METHOD__ . '::' . __LINE__ . " Folder state checking failed: " . $e->getMessage());
295
+                            }
296
                             if ($this->_logger instanceof Zend_Log) {
297
                                 $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " Folder state checking failed: " . $e->getTraceAsString());
298
                             }
299
@@ -781,10 +773,10 @@
300
                             // @todo: should we break the loop here?
301
                             $status = self::STATUS_SERVER_ERROR;
302
                         }
303
-                    }
304
 
305
-                    if ($this->_logger instanceof Zend_Log) {
306
-                        $this->_logger->info(__METHOD__ . '::' . __LINE__ . " found (added/changed/deleted) " . count($serverModifications'added') . '/' . count($serverModifications'changed') . '/' . count($serverModifications'deleted') . ' entries for sync from server to client');
307
+                        if ($this->_logger instanceof Zend_Log) {
308
+                            $this->_logger->info(__METHOD__ . '::' . __LINE__ . " found (added/changed/deleted) " . count($serverModifications'added') . '/' . count($serverModifications'changed') . '/' . count($serverModifications'deleted') . ' entries for sync from server to client');
309
+                        }
310
                     }
311
                 }
312
 
313
@@ -806,12 +798,12 @@
314
                 }
315
 
316
                 // send reponse for newly added entries
317
-                if (!empty($clientModifications'added')) {
318
-                    foreach ($clientModifications'added' as $entryData) {
319
+                if(!empty($clientModifications'added')) {
320
+                    foreach($clientModifications'added' as $entryData) {
321
                         $add = $responses->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Add'));
322
                         $add->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ClientId', $entryData'clientId'));
323
                         // we have no serverId if the add failed
324
-                        if (isset($entryData'serverId')) {
325
+                        if(isset($entryData'serverId')) {
326
                             $add->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ServerId', $entryData'serverId'));
327
                         }
328
                         $add->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Status', $entryData'status'));
329
@@ -819,8 +811,8 @@
330
                 }
331
 
332
                 // send reponse for changed entries
333
-                if (!empty($clientModifications'changed')) {
334
-                    foreach ($clientModifications'changed' as $serverId => $status) {
335
+                if(!empty($clientModifications'changed')) {
336
+                    foreach($clientModifications'changed' as $serverId => $status) {
337
                         if ($status !== Syncroton_Command_Sync::STATUS_SUCCESS) {
338
                             $change = $responses->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Change'));
339
                             $change->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ServerId', $serverId));
340
@@ -830,19 +822,19 @@
341
                 }
342
 
343
                 // send response for to be fetched entries
344
-                if (!empty($collectionData->toBeFetched)) {
345
+                if(!empty($collectionData->toBeFetched)) {
346
                     // unset all truncation settings as entries are not allowed to be truncated during fetch
347
                     $fetchCollectionData = clone $collectionData;
348
 
349
                     // unset truncationSize
350
                     if (isset($fetchCollectionData->options'bodyPreferences') && is_array($fetchCollectionData->options'bodyPreferences')) {
351
-                        foreach ($fetchCollectionData->options'bodyPreferences' as $key => $bodyPreference) {
352
+                        foreach($fetchCollectionData->options'bodyPreferences' as $key => $bodyPreference) {
353
                             unset($fetchCollectionData->options'bodyPreferences'$key'truncationSize');
354
                         }
355
                     }
356
                     $fetchCollectionData->options'mimeTruncation' = Syncroton_Command_Sync::TRUNCATE_NOTHING;
357
 
358
-                    foreach ($collectionData->toBeFetched as $serverId) {
359
+                    foreach($collectionData->toBeFetched as $serverId) {
360
                         $fetch = $responses->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Fetch'));
361
                         $fetch->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ServerId', $serverId));
362
 
363
@@ -874,8 +866,8 @@
364
 
365
                 $commands = $this->_outputDom->createElementNS('uri:AirSync', 'Commands');
366
 
367
-                foreach ($serverModifications'added' as $id => $serverId) {
368
-                    if ($collectionChanges == $collectionData->windowSize || $totalChanges + $collectionChanges >= $this->_globalWindowSize) {
369
+                foreach($serverModifications'added' as $id => $serverId) {
370
+                    if($collectionChanges == $collectionData->windowSize || $totalChanges + $collectionChanges >= $this->_globalWindowSize) {
371
                         break;
372
                     }
373
 
374
@@ -927,8 +919,8 @@
375
                 /**
376
                  * process entries changed on server side
377
                  */
378
-                foreach ($serverModifications'changed' as $id => $serverId) {
379
-                    if ($collectionChanges == $collectionData->windowSize || $totalChanges + $collectionChanges >= $this->_globalWindowSize) {
380
+                foreach($serverModifications'changed' as $id => $serverId) {
381
+                    if($collectionChanges == $collectionData->windowSize || $totalChanges + $collectionChanges >= $this->_globalWindowSize) {
382
                         break;
383
                     }
384
 
385
@@ -968,8 +960,8 @@
386
                     unset($serverModifications'changed'$id);
387
                 }
388
 
389
-                foreach ($serverModifications'deleted' as $id => $serverId) {
390
-                    if ($collectionChanges == $collectionData->windowSize || $totalChanges + $collectionChanges >= $this->_globalWindowSize) {
391
+                foreach($serverModifications'deleted' as $id => $serverId) {
392
+                    if($collectionChanges == $collectionData->windowSize || $totalChanges + $collectionChanges >= $this->_globalWindowSize) {
393
                         break;
394
                     }
395
 
396
@@ -1077,7 +1069,7 @@
397
                 if (!empty($clientModifications'added')) {
398
                     // Store a client id mapping in case we encounter a reused sync_key in a future request.
399
                     $newClientIdMap = ;
400
-                    foreach ($clientModifications'added' as $entryData) {
401
+                    foreach($clientModifications'added' as $entryData) {
402
                         // No serverId if we failed to add
403
                         if ($entryData'status' == self::STATUS_SUCCESS) {
404
                             $newClientIdMap$entryData'clientId' = $entryData'serverId';
405
@@ -1095,18 +1087,18 @@
406
                         $this->_syncStateBackend->create($collectionData->syncState, true); // @phpstan-ignore-line
407
 
408
                         // store contentstates for new entries added to client
409
-                        foreach ($newContentStates as $state) {
410
+                        foreach($newContentStates as $state) {
411
                             try {
412
                                 //This can happen if we rerun a previous sync-key
413
                                 $state = $this->_contentStateBackend->getContentState($state->device_id, $state->folder_id, $state->contentid);
414
                                 $this->_contentStateBackend->update($state);
415
-                            } catch (Exception $zdse) {
416
+                            } catch(Exception $zdse) {
417
                                 $this->_contentStateBackend->create($state);
418
                             }
419
                         }
420
 
421
                         // remove contentstates for entries to be deleted on client
422
-                        foreach ($deletedContentStates as $state) {
423
+                        foreach($deletedContentStates as $state) {
424
                             $this->_contentStateBackend->delete($state);
425
                         }
426
 
427
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/Wbxml.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/AData.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/Calendar.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/Contacts.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/Email.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/Factory.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/IData.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/IDataCalendar.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/IDataEmail.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/IDataSearch.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/Notes.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/Tasks.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/AccessDenied.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/DeadlockDetected.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/MemoryExhausted.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/NotFound.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/PolicyKeyMissing.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/ProvisioningNeeded.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/Status.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/Status/Autodiscover.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/Status/FolderCreate.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/Status/FolderDelete.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/Status/FolderSync.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/Status/FolderUpdate.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/Status/GetItemEstimate.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/Status/ItemOperations.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/Status/MeetingResponse.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/Status/MoveItems.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/Status/Settings.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/Status/Sync.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/UnexpectedValue.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/AEntry.php Changed
16
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -71,7 +70,7 @@
8
      */
9
     public function setFromArray(array $properties)
10
     {
11
-        foreach ($properties as $key => $value) {
12
+        foreach($properties as $key => $value) {
13
             try {
14
                 $this->$key = $value; //echo __LINE__ . PHP_EOL;
15
             } catch (InvalidArgumentException $iae) {
16
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/AXMLEntry.php Changed
46
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -48,9 +47,9 @@
8
     {
9
         $this->_addXMLNamespaces($domParrent);
10
 
11
-        foreach ($this->_elements as $elementName => $value) {
12
+        foreach($this->_elements as $elementName => $value) {
13
             // skip empty values
14
-            if ($value === null || $value === '' || (is_array($value) && empty($value))) {
15
+            if($value === null || $value === '' || (is_array($value) && empty($value))) {
16
                 continue;
17
             }
18
 
19
@@ -70,7 +69,7 @@
20
 
21
             if (isset($elementProperties'childElement')) {
22
                 $element = $domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementName));
23
-                foreach ($value as $subValue) {
24
+                foreach($value as $subValue) {
25
                     $subElement = $domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementProperties'childElement'));
26
                     $this->_appendXMLElement($device, $subElement, $elementProperties, $subValue);
27
                     $element->appendChild($subElement);
28
@@ -103,7 +102,7 @@
29
     {
30
         $properties = ;
31
 
32
-        foreach ($this->_properties as $namespace => $namespaceProperties) {
33
+        foreach($this->_properties as $namespace => $namespaceProperties) {
34
             if ($selectedNamespace !== null && $namespace != $selectedNamespace) {
35
                 continue;
36
             }
37
@@ -256,7 +255,7 @@
38
      */
39
     protected function _getElementProperties($element)
40
     {
41
-        foreach ($this->_properties as $namespace => $namespaceProperties) {
42
+        foreach($this->_properties as $namespace => $namespaceProperties) {
43
             if (array_key_exists($element, $namespaceProperties)) {
44
                 return $namespace, $namespaceProperties$element;
45
             }
46
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Account.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Contact.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Content.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Device.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/DeviceInformation.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Email.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EmailAttachment.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EmailBody.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EmailFlag.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EmailMeetingRequest.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EmailRecurrence.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Event.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EventAttendee.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EventException.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EventRecurrence.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/FileReference.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Folder.php Changed
11
 
1
@@ -33,9 +33,7 @@
2
             'ownerId'        => 'type' => 'string',
3
             'class'          => 'type' => 'string',
4
             'creationTime'   => 'type' => 'datetime',
5
-            'creationSynckey' => 'type' => 'number',
6
             'lastfiltertype' => 'type' => 'number',
7
-            'resync'         => 'type' => 'number',
8
         ,
9
     ;
10
 }
11
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/GAL.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/GALPicture.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/IContent.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/IEntry.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /*
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/IFolder.php Changed
15
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -22,7 +21,6 @@
8
  * @property    string   $parentId
9
  * @property    string   $displayName
10
  * @property    DateTime $creationTime
11
- * @property    int      $creationSynckey
12
  * @property    int      $lastfiltertype
13
  * @property    int      $type
14
  */
15
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/IPolicy.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/ISyncState.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/IXMLEntry.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/MeetingResponse.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Note.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Policy.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/SendMail.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/SmartForward.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/SmartReply.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/StoreRequest.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/StoreResponseResult.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/SyncCollection.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/SyncState.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Task.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/TaskRecurrence.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Registry.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Zend Framework
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Server.php Changed
47
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -53,10 +52,7 @@
8
         $this->_request = $request instanceof Zend_Controller_Request_Http ? $request : new Zend_Controller_Request_Http();
9
         $this->_body    = $body !== null ? $body : fopen('php://input', 'r');
10
 
11
-        // Not available on unauthenticated OPTIONS request
12
-        if (!empty($this->_userId)) {
13
-            $this->_deviceBackend = Syncroton_Registry::getDeviceBackend();
14
-        }
15
+        $this->_deviceBackend = Syncroton_Registry::getDeviceBackend();
16
 
17
     }
18
 
19
@@ -66,17 +62,7 @@
20
             $this->_logger->debug(__METHOD__ . '::' . __LINE__ . ' REQUEST METHOD: ' . $this->_request->getMethod());
21
         }
22
 
23
-        if ($this->_request->getMethod() != "OPTIONS" && empty($this->_userId)) {
24
-            // Outlook on ios/android sends unauthenticated requests for Ping/FolderSync/Settings
25
-            // (which doesn't seem to make much sense), so we handle this case silently,
26
-            // even though it should normally be a warning.
27
-            $this->_logger->debug(__METHOD__ . '::' . __LINE__ . ' Not authenticated');
28
-            header('WWW-Authenticate: Basic realm="ActiveSync for Kolab"');
29
-            header('HTTP/1.1 401 Unauthorized');
30
-            exit;
31
-        }
32
-
33
-        switch ($this->_request->getMethod()) {
34
+        switch($this->_request->getMethod()) {
35
             case 'OPTIONS':
36
                 $this->_handleOptions();
37
                 break;
38
@@ -142,7 +128,7 @@
39
                 if ($this->_logger instanceof Zend_Log) {
40
                     $this->_logDomDocument($requestBody, 'request', __METHOD__, __LINE__);
41
                 }
42
-            } catch (Syncroton_Wbxml_Exception_UnexpectedEndOfFile $e) {
43
+            } catch(Syncroton_Wbxml_Exception_UnexpectedEndOfFile $e) {
44
                 if ($this->_logger instanceof Zend_Log) {
45
                     $this->_logger->warn(__METHOD__ . '::' . __LINE__ . " unexpected end of file.");
46
                 }
47
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/TransactionManager.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/TransactionManagerInterface.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Abstract.php Changed
43
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -112,7 +111,7 @@
8
      */
9
     public function getDPI($_uInt = 0)
10
     {
11
-        if (!defined('Syncroton_Wbxml_Abstract::DPI_' . $_uInt)) {
12
+        if(!defined('Syncroton_Wbxml_Abstract::DPI_' . $_uInt)) {
13
             throw new Syncroton_Wbxml_Exception('unknown wellknown identifier: ' . $_uInt);
14
         }
15
 
16
@@ -143,7 +142,7 @@
17
     {
18
         $byte = fread($this->_stream, 1);
19
 
20
-        if ($byte === false) {
21
+        if($byte === false) {
22
             throw new Syncroton_Wbxml_Exception("failed reading one byte");
23
         }
24
 
25
@@ -205,7 +204,7 @@
26
         do {
27
             $byte = ($remainder & 127);
28
             $remainder >>= 7;
29
-            if ($multibyte === null) {
30
+            if($multibyte === null) {
31
                 $multibyte = chr($byte);
32
             } else {
33
                 $multibyte = chr($byte | 128) . $multibyte;
34
@@ -241,7 +240,7 @@
35
         $this->_writeMultibyteUInt($length);
36
         $writenBytes = stream_copy_to_stream($stream, $this->_stream);
37
 
38
-        if ($writenBytes !== $length) {
39
+        if($writenBytes !== $length) {
40
             throw new Syncroton_Wbxml_Exception('blow');
41
         }
42
 
43
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Decoder.php Changed
112
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -55,10 +54,10 @@
8
      */
9
     public function __construct($_stream, $_dpi = null)
10
     {
11
-        if (!is_resource($_stream) || get_resource_type($_stream) != 'stream') {
12
+        if(!is_resource($_stream) || get_resource_type($_stream) != 'stream') {
13
             throw new Syncroton_Wbxml_Exception('$_stream must be a stream');
14
         }
15
-        if ($_dpi !== null) {
16
+        if($_dpi !== null) {
17
             $this->_dpi = $_dpi;
18
         }
19
 
20
@@ -66,7 +65,7 @@
21
 
22
         $this->_version = $this->_getByte();
23
 
24
-        if (feof($this->_stream)) {
25
+        if(feof($this->_stream)) {
26
             throw new Syncroton_Wbxml_Exception_UnexpectedEndOfFile();
27
         }
28
 
29
@@ -78,7 +77,7 @@
30
 
31
         // resolve DPI as we have read the stringtable now
32
         // this->_dpi contains the string table index
33
-        if ($this->_dpiType === Syncroton_Wbxml_Abstract::DPI_STRINGTABLE) {
34
+        if($this->_dpiType === Syncroton_Wbxml_Abstract::DPI_STRINGTABLE) {
35
             $this->_dpi = $this->_stringTable$this->_dpi;
36
         }
37
 
38
@@ -121,7 +120,7 @@
39
         while (!feof($this->_stream)) {
40
             $byte = $this->_getByte();
41
 
42
-            switch ($byte) {
43
+            switch($byte) {
44
                 case Syncroton_Wbxml_Abstract::END:
45
                     $node = $node->parentNode;
46
                     $openTags--;
47
@@ -129,7 +128,7 @@
48
 
49
                 case Syncroton_Wbxml_Abstract::OPAQUE:
50
                     $length = $this->_getMultibyteUInt();
51
-                    if ($length > 0) {
52
+                    if($length > 0) {
53
                         $opaque = $this->_getOpaque($length);
54
                         try {
55
                             // let see if we can decode it. maybe the opaque data is wbxml encoded content
56
@@ -142,8 +141,8 @@
57
 
58
                             fclose($opaqueDataStream);
59
 
60
-                            foreach ($dom->childNodes as $newNode) {
61
-                                if ($newNode instanceof DOMElement) {
62
+                            foreach($dom->childNodes as $newNode) {
63
+                                if($newNode instanceof DOMElement) {
64
                                     $newNode = $this->_dom->importNode($newNode, true);
65
                                     $node->appendChild($newNode);
66
                                 }
67
@@ -241,7 +240,7 @@
68
     {
69
         $uInt = $this->_getMultibyteUInt();
70
 
71
-        if ($uInt == 0) {
72
+        if($uInt == 0) {
73
             // get identifier from stringtable
74
             $this->_dpiType = Syncroton_Wbxml_Abstract::DPI_STRINGTABLE;
75
             // string table identifier, can be resolved only after reading string table
76
@@ -261,7 +260,7 @@
77
     {
78
         $uInt = $this->_getMultibyteUInt();
79
 
80
-        switch ($uInt) {
81
+        switch($uInt) {
82
             case 106:
83
                 $this->_charSet = 'UTF-8';
84
                 break;
85
@@ -280,21 +279,21 @@
86
     {
87
         $length = $this->_getMultibyteUInt();
88
 
89
-        if ($length > 0) {
90
+        if($length > 0) {
91
             $rawStringTable = $this->_getOpaque($length);
92
             $index = null;
93
             $string = null;
94
 
95
-            for ($i = 0; $i < strlen($rawStringTable); $i++) {
96
-                if ($index === null) {
97
+            for($i = 0; $i < strlen($rawStringTable); $i++) {
98
+                if($index === null) {
99
                     $index = $i;
100
                 }
101
-                if (ord($rawStringTable$i) != 0) {
102
+                if(ord($rawStringTable$i) != 0) {
103
                     $string .= $rawStringTable$i;
104
                 }
105
 
106
                 // either the string has ended or we reached a \0
107
-                if ($i + 1 == strlen($rawStringTable) || ord($rawStringTable$i) == 0) {
108
+                if($i + 1 == strlen($rawStringTable) || ord($rawStringTable$i) == 0) {
109
                     $this->_stringTable$index = $string;
110
                     $index = null;
111
                     $string = null;
112
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/Abstract.php Changed
25
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -88,7 +87,7 @@
8
      */
9
     public function getIdentity($_tag)
10
     {
11
-        if (!isset($this->_tags$_tag)) {
12
+        if(!isset($this->_tags$_tag)) {
13
             //var_dump($this->_tags);
14
             throw new Syncroton_Wbxml_Exception("tag $_tag not found");
15
         }
16
@@ -106,7 +105,7 @@
17
     {
18
         $tag = array_search($_identity, $this->_tags);
19
 
20
-        if ($tag === false) {
21
+        if($tag === false) {
22
             throw new Syncroton_Wbxml_Exception("identity $_identity not found");
23
         }
24
 
25
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage0.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage1.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage10.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage11.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage12.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage13.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage14.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage15.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage16.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage17.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage18.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage19.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage2.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage20.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage21.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage22.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage23.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage24.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage254.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage3.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage4.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage5.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage6.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage7.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage8.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/ActiveSync/CodePage9.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/Exception/CodePageNotFound.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Dtd/Factory.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Encoder.php Changed
83
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
@@ -55,7 +54,7 @@
8
         // the WBXML version
9
         $this->_writeByte($this->_version);
10
 
11
-        if ($this->_codePage->getDPI() === null) {
12
+        if($this->_codePage->getDPI() === null) {
13
             // the document public identifier
14
             $this->_writeMultibyteUInt(1);
15
         } else {
16
@@ -69,7 +68,7 @@
17
         // write the charSet
18
         $this->_writeCharSet($this->_charSet);
19
 
20
-        if ($this->_codePage->getDPI() === null) {
21
+        if($this->_codePage->getDPI() === null) {
22
             // the length of the string table
23
             $this->_writeMultibyteUInt(0);
24
         } else {
25
@@ -88,7 +87,7 @@
26
      */
27
     protected function _writeCharSet($_charSet)
28
     {
29
-        switch (strtoupper($_charSet)) {
30
+        switch(strtoupper($_charSet)) {
31
             case 'UTF-8':
32
                 $this->_writeMultibyteUInt(106);
33
                 break;
34
@@ -124,7 +123,7 @@
35
 
36
     private function writeNode($node, $withContent = false, $data = null)
37
     {
38
-        if ($this->_codePage->getNameSpace() != $node->namespaceURI) {
39
+        if($this->_codePage->getNameSpace() != $node->namespaceURI) {
40
             $this->_switchCodePage($node->namespaceURI);
41
         }
42
         $this->_writeTag($node->localName, $this->getAttributes($node), $withContent, $data);
43
@@ -190,7 +189,7 @@
44
      */
45
     protected function _writeTag($_tag, $_attributes = null, $_hasContent = false, $_data = null)
46
     {
47
-        if ($_hasContent == false && $_data !== null) {
48
+        if($_hasContent == false && $_data !== null) {
49
             throw new Syncroton_Wbxml_Exception('$_hasContent can not be false, when $_data !== NULL');
50
         }
51
 
52
@@ -204,18 +203,18 @@
53
             $encoding = 'termstring';
54
         }
55
 
56
-        if (!empty($_attributes)) {
57
+        if(!empty($_attributes)) {
58
             $identity |= 0x80;
59
         }
60
 
61
-        if ($_hasContent == true) {
62
+        if($_hasContent == true) {
63
             $identity |= 0x40;
64
         }
65
 
66
         $this->_writeByte($identity);
67
 
68
         // handle the data
69
-        if ($_data !== null) {
70
+        if($_data !== null) {
71
             if ($encoding == 'opaque') {
72
                 $this->_writeOpaqueString(base64_decode($_data));
73
             } else {
74
@@ -232,7 +231,7 @@
75
     protected function _switchCodePage($_nameSpace)
76
     {
77
         $codePageName = $this->_stripNameSpace($_nameSpace);
78
-        if (!defined('Syncroton_Wbxml_Dtd_ActiveSync::CODEPAGE_' . strtoupper($codePageName))) {
79
+        if(!defined('Syncroton_Wbxml_Dtd_ActiveSync::CODEPAGE_' . strtoupper($codePageName))) {
80
             throw new Syncroton_Wbxml_Exception('codepage ' . $codePageName . ' not found');
81
         }
82
         // switch to another codepage
83
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Exception.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Exception/UnexpectedEndOfFile.php Changed
7
 
1
@@ -1,5 +1,4 @@
2
 <?php
3
-
4
 /**
5
  * Syncroton
6
  *
7
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync.php Changed
86
 
1
@@ -135,30 +135,30 @@
2
             $userid = $this->authenticate($_SERVER'PHP_AUTH_USER', $_SERVER'PHP_AUTH_PW');
3
         }
4
 
5
-        if (!empty($userid)) {
6
-            $this->plugins->exec_hook('ready', 'task' => 'syncroton');
7
+        if (empty($userid)) {
8
+            header('WWW-Authenticate: Basic realm="' . $this->app_name . '"');
9
+            header('HTTP/1.1 401 Unauthorized');
10
+            exit;
11
+        }
12
 
13
-            // Set log directory per-user (again, in case the username changed above)
14
-            $this->set_log_dir();
15
+        $this->plugins->exec_hook('ready', 'task' => 'syncroton');
16
 
17
-            // Save user password for Roundcube Framework
18
-            $this->password = $_SERVER'PHP_AUTH_PW';
19
-        }
20
+        // Set log directory per-user (again, in case the username changed above)
21
+        $this->set_log_dir();
22
+
23
+        // Save user password for Roundcube Framework
24
+        $this->password = $_SERVER'PHP_AUTH_PW';
25
 
26
         // Register Syncroton backends/callbacks
27
         Syncroton_Registry::set(Syncroton_Registry::LOGGERBACKEND, $this->logger);
28
         Syncroton_Registry::set(Syncroton_Registry::DATABASE, $this->get_dbh());
29
         Syncroton_Registry::set(Syncroton_Registry::TRANSACTIONMANAGER, kolab_sync_transaction_manager::getInstance());
30
-        // The unauthenticated OPTIONS request doesn't require these backends and we can't
31
-        // instantiate them without credentials for the underlying storage backend
32
-        if (!empty($userid)) {
33
-            Syncroton_Registry::set(Syncroton_Registry::DEVICEBACKEND, new kolab_sync_backend_device());
34
-            Syncroton_Registry::set(Syncroton_Registry::FOLDERBACKEND, new kolab_sync_backend_folder());
35
-            Syncroton_Registry::set(Syncroton_Registry::SYNCSTATEBACKEND, new kolab_sync_backend_state());
36
-            Syncroton_Registry::set(Syncroton_Registry::CONTENTSTATEBACKEND, new kolab_sync_backend_content());
37
-            Syncroton_Registry::set(Syncroton_Registry::POLICYBACKEND, new kolab_sync_backend_policy());
38
-            Syncroton_Registry::set(Syncroton_Registry::SLEEP_CALLBACK, $this, 'sleep');
39
-        }
40
+        Syncroton_Registry::set(Syncroton_Registry::DEVICEBACKEND, new kolab_sync_backend_device());
41
+        Syncroton_Registry::set(Syncroton_Registry::FOLDERBACKEND, new kolab_sync_backend_folder());
42
+        Syncroton_Registry::set(Syncroton_Registry::SYNCSTATEBACKEND, new kolab_sync_backend_state());
43
+        Syncroton_Registry::set(Syncroton_Registry::CONTENTSTATEBACKEND, new kolab_sync_backend_content());
44
+        Syncroton_Registry::set(Syncroton_Registry::POLICYBACKEND, new kolab_sync_backend_policy());
45
+        Syncroton_Registry::set(Syncroton_Registry::SLEEP_CALLBACK, $this, 'sleep');
46
 
47
         Syncroton_Registry::setContactsDataClass('kolab_sync_data_contacts');
48
         Syncroton_Registry::setCalendarDataClass('kolab_sync_data_calendar');
49
@@ -174,7 +174,7 @@
50
         Syncroton_Registry::set(Syncroton_Registry::MAX_COLLECTIONS, (int) $this->config->get('activesync_max_folders', 100));
51
 
52
         // Run Syncroton
53
-        $syncroton = new Syncroton_Server($userid ?? null);
54
+        $syncroton = new Syncroton_Server($userid);
55
         $syncroton->handle();
56
     }
57
 
58
@@ -386,10 +386,8 @@
59
 
60
     /**
61
      * Initializes and returns the storage backend object
62
-     *
63
-     * @param bool $init Reset the driver internal state
64
      */
65
-    public static function storage($init = false)
66
+    public static function storage()
67
     {
68
         $class = 'kolab_sync_storage';
69
         $self  = self::get_instance();
70
@@ -398,15 +396,6 @@
71
             $class .= '_' . strtolower($name);
72
         }
73
 
74
-        if ($init) {
75
-            // Reset storage driver internal state
76
-            $reflection = new ReflectionClass($class);
77
-            $property = $reflection->getProperty('instance');
78
-            $property->setAccessible(true);
79
-            $property->setValue($class::get_instance(), null);
80
-            $property->setAccessible(false);
81
-        }
82
-
83
         return $class::get_instance();
84
     }
85
 
86
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_backend_folder.php Changed
94
 
1
@@ -50,19 +50,15 @@
2
      *
3
      * @param Syncroton_Model_Device|string $deviceid Device object or identifier
4
      * @param string                        $class    Class name
5
-     * @param int                           $syncKey  Sync key
6
      *
7
      * @return array List of object identifiers
8
      */
9
-    public function getFolderState($deviceid, $class, $syncKey = null)
10
+    public function getFolderState($deviceid, $class)
11
     {
12
         $device_id = $deviceid instanceof Syncroton_Model_IDevice ? $deviceid->id : $deviceid;
13
 
14
         $where = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id);
15
         $where = $this->db->quote_identifier('class') . ' = ' . $this->db->quote($class);
16
-        if ($syncKey) {
17
-            $where = $this->db->quote_identifier('creation_synckey') . ' < ' . $this->db->quote($syncKey + 1);
18
-        }
19
 
20
         $select = $this->db->query('SELECT * FROM `' . $this->table_name . '` WHERE ' . implode(' AND ', $where));
21
         $result = ;
22
@@ -92,37 +88,14 @@
23
         $select = $this->db->query('SELECT * FROM `' . $this->table_name . '` WHERE ' . implode(' AND ', $where));
24
         $folder = $this->db->fetch_assoc($select);
25
 
26
-        if (!empty($folder'resync')) {
27
-            throw new Syncroton_Exception_NotFound("Folder $folderid not found because of resync");
28
-        }
29
         if (empty($folder)) {
30
-            throw new Syncroton_Exception_NotFound("Folder $folderid not found");
31
+            throw new Syncroton_Exception_NotFound('Folder not found');
32
         }
33
 
34
         return $this->get_object($folder);
35
     }
36
 
37
     /**
38
-     * Check if the folder already exists
39
-     *
40
-     * @param Syncroton_Model_Device|string  $deviceid Device object or identifier
41
-     * @param string                         $folderid Folder identifier
42
-     *
43
-     * @return bool true if it exists
44
-     */
45
-    public function exists($deviceid, $folderid)
46
-    {
47
-        $device_id = $deviceid instanceof Syncroton_Model_IDevice ? $deviceid->id : $deviceid;
48
-
49
-        $where = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id);
50
-        $where = $this->db->quote_identifier('folderid') . ' = ' . $this->db->quote($folderid);
51
-
52
-        $select = $this->db->query('SELECT 1 FROM `' . $this->table_name . '` WHERE ' . implode(' AND ', $where));
53
-        $folder = $this->db->fetch_assoc($select);
54
-        return !empty($folder);
55
-    }
56
-
57
-    /**
58
      * Find out if the folder hierarchy changed since the last FolderSync
59
      *
60
      * @param Syncroton_Model_Device $device Device object
61
@@ -147,18 +120,6 @@
62
         // Reset imap cache so we work with up-to-date folders list
63
         rcube::get_instance()->get_storage()->clear_cache('mailboxes', true);
64
 
65
-        // Retrieve all folders already sent to the client
66
-        $select = $this->db->query("SELECT * FROM `{$this->table_name}` WHERE `device_id` = ?", $device->id);
67
-
68
-        while ($folder = $this->db->fetch_assoc($select)) {
69
-            if (!empty($folder'resync')) {
70
-                // Folder re-sync requested
71
-                return true;
72
-            }
73
-
74
-            $client_folders$folder'folderid' = $this->get_object($folder);
75
-        }
76
-
77
         foreach ($folder_classes as $class) {
78
             try {
79
                 // retrieve all folders available in data backend
80
@@ -171,6 +132,13 @@
81
             }
82
         }
83
 
84
+        // retrieve all folders sent to the client
85
+        $select = $this->db->query("SELECT * FROM `{$this->table_name}` WHERE `device_id` = ?", $device->id);
86
+
87
+        while ($folder = $this->db->fetch_assoc($select)) {
88
+            $client_folders$folder'folderid' = $this->get_object($folder);
89
+        }
90
+
91
         ksort($client_folders);
92
         ksort($server_folders);
93
 
94
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_backend_state.php Changed
33
 
1
@@ -115,10 +115,6 @@
2
         $select = $this->db->limitquery("SELECT * FROM `{$this->table_name}` WHERE " . implode(' AND ', $where)
3
             . " ORDER BY `counter` DESC", 0, 1);
4
 
5
-        if ($err = $this->db->is_error($select)) {
6
-            throw new Exception("Query failed while fetching sync state: {$err}");
7
-        }
8
-
9
         $state = $this->db->fetch_assoc($select);
10
 
11
         if (empty($state)) {
12
@@ -168,10 +164,6 @@
13
 
14
         $select = $this->db->query("SELECT * FROM `{$this->table_name}` WHERE " . implode(' AND ', $where));
15
 
16
-        if ($err = $this->db->is_error($select)) {
17
-            throw new Exception("Query failed while validating sync state: {$err}");
18
-        }
19
-
20
         while ($row = $this->db->fetch_assoc($select)) {
21
             $states$row'counter' = $this->get_object($row);
22
         }
23
@@ -231,9 +223,6 @@
24
         $where'counter'      = $this->db->quote_identifier('counter') . ' > ' . $this->db->quote($sync_key);
25
 
26
         $select = $this->db->query("SELECT id FROM `{$this->table_name}` WHERE " . implode(' AND ', $where));
27
-        if ($err = $this->db->is_error($select)) {
28
-            throw new Exception("Query failed while checking for sync state: {$err}");
29
-        }
30
         return $this->db->num_rows($select) > 0;
31
     }
32
 }
33
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data.php Changed
10
 
1
@@ -1175,7 +1175,7 @@
2
         $r          = $data'recurrence';
3
 
4
         // required fields
5
-        switch ($r'FREQ') {
6
+        switch($r'FREQ') {
7
             case 'DAILY':
8
                 $recurrence'type' = self::RECUR_TYPE_DAILY;
9
                 break;
10
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data_calendar.php Changed
14
 
1
@@ -691,11 +691,7 @@
2
         }
3
 
4
         // extract event from the invitation
5
-        try {
6
-            $event, $existing = $this->get_event_from_invitation($request);
7
-        } catch (Exception $e) {
8
-            throw new Syncroton_Exception_Status_MeetingResponse(Syncroton_Exception_Status_MeetingResponse::MEETING_ERROR);
9
-        }
10
+        $event, $existing = $this->get_event_from_invitation($request);
11
         /*
12
                     switch ($status) {
13
                         case 'ACCEPTED':  $event'free_busy' = 'busy';      break;
14
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data_contacts.php Changed
11
 
1
@@ -272,8 +272,7 @@
2
         $emails = ;
3
         for ($x = 0; $x < 3; $x++) {
4
             $key = 'email' . ($x + 1) . 'Address';
5
-            $value = $data->$key ?? null;
6
-            if ($value) {
7
+            if ($value = $data->$key) {
8
                 // Android sends email address as: Lars Kneschke <l.kneschke@metaways.de>
9
                 if (preg_match('/(.*)<(.+@^@+)>/', $value, $matches)) {
10
                     $value = trim($matches2);
11
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data_email.php Changed
37
 
1
@@ -674,7 +674,7 @@
2
         $result = ;
3
 
4
         if (!is_array($list)) {
5
-            throw new Syncroton_Exception_NotFound("Folder $folder_id not found: no folders available");
6
+            throw new Syncroton_Exception_NotFound('Folder not found');
7
         }
8
 
9
         // device supports multiple folders?
10
@@ -691,7 +691,7 @@
11
         }
12
 
13
         if (empty($result)) {
14
-            throw new Syncroton_Exception_NotFound("Folder $folder_id not found.");
15
+            throw new Syncroton_Exception_NotFound('Folder not found');
16
         }
17
 
18
         return $result;
19
@@ -1132,14 +1132,14 @@
20
      */
21
     public function getFileReference($fileReference)
22
     {
23
+        $folderid, $uid, $part_id = explode('::', $fileReference);
24
+
25
         $message = $this->getObject($fileReference);
26
 
27
         if (!$message) {
28
-            throw new Syncroton_Exception_NotFound("Message $fileReference not found");
29
+            throw new Syncroton_Exception_NotFound('Message not found');
30
         }
31
 
32
-        $folderid, $uid, $part_id = explode('::', $fileReference);
33
-
34
         $part = $message->mime_parts$part_id;
35
         $body = $message->get_part_body($part_id);
36
 
37
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_logger.php Changed
12
 
1
@@ -161,8 +161,8 @@
2
             }
3
 
4
             foreach ($params as $key => $val) {
5
-                if (isset($_GET$val)) {
6
-                    $device$key = $_GET$val;
7
+                if ($val = $_GET$val) {
8
+                    $device$key = $val;
9
                 }
10
             }
11
 
12
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_storage.php Changed
327
 
1
@@ -56,7 +56,7 @@
2
     protected $folders = ;
3
     protected $root_meta;
4
     protected $relations = ;
5
-    protected $relationSupport = self::MODEL_TASKS, self::MODEL_NOTES, self::MODEL_EMAIL;
6
+    protected $relationSupport = true;
7
     protected $tag_rts = ;
8
     private $modseq = ;
9
 
10
@@ -109,7 +109,7 @@
11
         $this->storage->set_options(
12
             // @TODO: there can be Roundcube plugins defining additional headers,
13
             // we maybe would need to add them here
14
-            'fetch_headers' => 'X-KOLAB-TYPE X-KOLAB-MIME-VERSION MESSAGE-ID',
15
+            'fetch_headers' => 'X-KOLAB-TYPE X-KOLAB-MIME-VERSION',
16
             'skip_deleted'  => true,
17
             'threading'     => false,
18
         );
19
@@ -694,7 +694,7 @@
20
             return $uid;
21
         }
22
 
23
-        $useTags = in_array($type, $this->relationSupport);
24
+        $useTags = $this->relationSupport && ($type == self::MODEL_TASKS || $type == self::MODEL_NOTES);
25
 
26
         // convert categories into tags, save them after creating an object
27
         if ($useTags && !empty($data'categories')) {
28
@@ -752,7 +752,7 @@
29
             return $this->storage->delete_message($uid, $foldername);
30
         }
31
 
32
-        $useTags = in_array($type, $this->relationSupport);
33
+        $useTags = $this->relationSupport && ($type == self::MODEL_TASKS || $type == self::MODEL_NOTES);
34
 
35
         $folder = $this->getFolder($folderid, $deviceid, $type);
36
 
37
@@ -795,14 +795,14 @@
38
             }
39
 
40
             // Categories (Tags) change
41
-            if (isset($params'categories') && in_array($type, $this->relationSupport)) {
42
-                $headers = $this->storage->fetch_headers($foldername, $uid, false);
43
+            if (isset($params'categories') && $this->relationSupport) {
44
+                $message = new rcube_message($uid, $foldername);
45
 
46
-                if (empty($headers) || empty($headers$uid)) {
47
+                if (empty($message->headers)) {
48
                     throw new Syncroton_Exception_Status_Sync(Syncroton_Exception_Status_Sync::SYNC_SERVER_ERROR);
49
                 }
50
 
51
-                $this->setCategories($headers$uid, $params'categories');
52
+                $this->setCategories($message, $params'categories');
53
             }
54
 
55
             return $uid;
56
@@ -810,7 +810,7 @@
57
 
58
         $folder = $this->getFolder($folderid, $deviceid, $type);
59
 
60
-        $useTags = in_array($type, $this->relationSupport);
61
+        $useTags = $this->relationSupport && ($type == self::MODEL_TASKS || $type == self::MODEL_NOTES);
62
 
63
         // convert categories into tags, save them after updating an object
64
         if ($useTags && array_key_exists('categories', $data)) {
65
@@ -836,16 +836,16 @@
66
     /**
67
      * Returns list of categories assigned to an object
68
      *
69
-     * @param rcube_message_header|string $object     UID or mail message headers
70
-     * @param array                       $categories Addition tag names to merge with
71
+     * @param object|string $object     UID or rcube_message object
72
+     * @param array         $categories Addition tag names to merge with
73
      *
74
      * @return array List of categories
75
      */
76
-    protected function getCategories($object, $categories = )
77
+    public function getCategories($object, $categories = )
78
     {
79
         if (is_object($object)) {
80
             // support only messages with message-id
81
-            if (!($msg_id = $object->get('message-id', false))) {
82
+            if (!($msg_id = $object->headers->get('message-id', false))) {
83
                 return ;
84
             }
85
 
86
@@ -952,10 +952,8 @@
87
             $message = new rcube_message($uid, $foldername);
88
 
89
             if (!empty($message->headers)) {
90
-                if (in_array($type, $this->relationSupport)) {
91
-                    $message->headers->folder = $foldername;
92
-                    $message->headers->uid = $uid;
93
-                    $message->headers->others'categories' = $this->getCategories($message->headers);
94
+                if ($this->relationSupport) {
95
+                    $message->headers->others'categories' = $this->getCategories($message);
96
                 }
97
 
98
                 return $message;
99
@@ -976,7 +974,7 @@
100
             throw new Syncroton_Exception_Status(Syncroton_Exception_Status::SERVER_ERROR);
101
         }
102
 
103
-        $useTags = in_array($type, $this->relationSupport);
104
+        $useTags = $this->relationSupport && ($type == self::MODEL_TASKS || $type == self::MODEL_NOTES);
105
 
106
         if ($useTags) {
107
             $result'categories' = $this->getCategories($uid, $result'categories' ?? );
108
@@ -1044,12 +1042,6 @@
109
 
110
             // Use COPYUID feature (RFC2359) to get the new UID of the copied message
111
             if (empty($this->storage->conn->data'COPYUID')) {
112
-                // Check if the source item actually exists. Cyrus IMAP reports
113
-                // OK on a MOVE with an invalid UID, But COPYUID will be empty.
114
-                // This way we only incur the cost of the extra check once the move fails.
115
-                if (!$this->storage->get_message_headers($uid, $src_name)) {
116
-                    throw new Syncroton_Exception_Status_MoveItems(Syncroton_Exception_Status_MoveItems::INVALID_SOURCE);
117
-                }
118
                 throw new Syncroton_Exception_Status(Syncroton_Exception_Status::SERVER_ERROR);
119
             }
120
 
121
@@ -1073,10 +1065,10 @@
122
     /**
123
      * Set categories to an object
124
      *
125
-     * @param rcube_message_header|string $object     UID or mail message headers
126
-     * @param array                       $categories List of Category names
127
+     * @param object|string $object     UID or rcube_message object
128
+     * @param array         $categories List of Category names
129
      */
130
-    protected function setCategories($object, $categories)
131
+    public function setCategories($object, $categories)
132
     {
133
         if (!is_object($object)) {
134
             $config = kolab_storage_config::get_instance();
135
@@ -1086,7 +1078,7 @@
136
 
137
         $config = kolab_storage_config::get_instance();
138
         $delta  = Syncroton_Registry::getPingTimeout();
139
-        $uri    = kolab_storage_config::get_message_uri($object, $object->folder);
140
+        $uri    = kolab_storage_config::get_message_uri($object->headers, $object->folder);
141
 
142
         // for all tag objects...
143
         foreach ($config->get_tags() as $relation) {
144
@@ -1252,7 +1244,7 @@
145
         }
146
 
147
         // get members of modified relations
148
-        if (in_array($type, $this->relationSupport)) {
149
+        if ($this->relationSupport) {
150
             $changed_msgs = $this->getChangesByRelations($folderid, $device_key, $type, $filter);
151
             // handle relation changes
152
             if (!empty($changed_msgs)) {
153
@@ -1260,7 +1252,7 @@
154
 
155
                 switch ($result_type) {
156
                     case kolab_sync_data::RESULT_COUNT:
157
-                        $result += count($members); // @phpstan-ignore-line
158
+                        $result += count($members);
159
                         break;
160
 
161
                     case kolab_sync_data::RESULT_UID:
162
@@ -1321,7 +1313,7 @@
163
         // there's a PHP Warning from kolab_storage if $filter isn't an array
164
         if (empty($filter)) {
165
             $filter = ;
166
-        } elseif (in_array($type, $this->relationSupport)) {
167
+        } elseif ($this->relationSupport && ($type == self::MODEL_TASKS || $type == self::MODEL_NOTES)) {
168
             $changed_objects = $this->getChangesByRelations($folderid, $device_key, $type, $filter);
169
         }
170
 
171
@@ -1378,7 +1370,7 @@
172
                     // need a precise result here
173
                     $count = $folder->count($tag_filter);
174
                     if ($count !== null) {
175
-                        $result += (int) $count; // @phpstan-ignore-line
176
+                        $result += (int) $count;
177
                     }
178
 
179
                     break;
180
@@ -1572,19 +1564,9 @@
181
                 ;
182
             }
183
 
184
-            // If the new and the old timestamp are the same our cache breaks.
185
-            // We must preserve the previous changes, because if this function is rerun we must detect the same changes again.
186
-            $sinceFormatted = $since->format('Y-m-d H:i:s');
187
-            if ($this->syncTimeStamp->format('Y-m-d H:i:s') == $sinceFormatted) {
188
-                // Preserve the previous timestamp (relations_state_get just checks the overflow bucket first)
189
-                // FIXME: The one caveat is that we will still update the database and thus overwrite the old entry.
190
-                // That means if we rerun the same request, the changes will not be detected
191
-                // => We should not be dealing with timestamps really.
192
-                $this->relations$folderid$sinceFormatted . "-1" = $this->relations$folderid$sinceFormatted ?? null;
193
-                $this->relations$folderid$sinceFormatted = null;
194
-            }
195
+            $now = new DateTime('now', new DateTimeZone('UTC'));
196
 
197
-            $this->relations_state_set($device_key, $folderid, $this->syncTimeStamp, $data);
198
+            $this->relations_state_set($device_key, $folderid, $now, $data);
199
         }
200
 
201
         // in mail mode return only message URIs
202
@@ -1938,23 +1920,22 @@
203
     public function relations_state_set($device_key, $folderid, $synctime, $relations)
204
     {
205
         $synctime = $synctime->format('Y-m-d H:i:s');
206
+        $rcube    = rcube::get_instance();
207
+        $db       = $rcube->get_dbh();
208
+        $old_data = $this->relations$folderid$synctime ?? null;
209
 
210
-        // Protect against inserting the same values twice (this code can be executed twice in the same request)
211
-        if (!isset($this->relations$folderid$synctime)) {
212
-            $rcube = rcube::get_instance();
213
-            $db = $rcube->get_dbh();
214
+        if (empty($old_data)) {
215
             $this->relations$folderid$synctime = $relations;
216
-            $data = gzdeflate(json_encode($relations));
217
+            $data = rcube_charset::clean(json_encode($relations));
218
 
219
-            if ($data === false) {
220
-                throw new Exception("Failed to compress relation data");
221
-            }
222
-
223
-            $result = $db->insert_or_update(
224
-                'syncroton_relations_state',
225
-                'device_id' => $device_key, 'folder_id' => $folderid, 'synctime' => $synctime,
226
-                'data',
227
-                $data
228
+            $result = $db->query(
229
+                "INSERT INTO `syncroton_relations_state`"
230
+                . " (`device_id`, `folder_id`, `synctime`, `data`)"
231
+                . " VALUES (?, ?, ?, ?)",
232
+                $device_key,
233
+                $folderid,
234
+                $synctime,
235
+                $data
236
             );
237
 
238
             if ($err = $db->is_error($result)) {
239
@@ -1970,18 +1951,15 @@
240
     {
241
         $synctime = $synctime->format('Y-m-d H:i:s');
242
 
243
-        // If we had a collision before
244
-        if (isset($this->relations$folderid$synctime . "-1")) {
245
-            return $this->relations$folderid$synctime . "-1";
246
-        }
247
+        if (empty($this->relations$folderid$synctime)) {
248
+            $this->relations$folderid = ;
249
 
250
-        if (!isset($this->relations$folderid$synctime)) {
251
             $rcube = rcube::get_instance();
252
-            $db = $rcube->get_dbh();
253
+            $db    = $rcube->get_dbh();
254
 
255
             $db->limitquery(
256
                 "SELECT `data`, `synctime` FROM `syncroton_relations_state`"
257
-                . " WHERE `device_id` = ? AND `folder_id` = ? AND `synctime` < ?"
258
+                . " WHERE `device_id` = ? AND `folder_id` = ? AND `synctime` <= ?"
259
                 . " ORDER BY `synctime` DESC",
260
                 0,
261
                 1,
262
@@ -1990,50 +1968,21 @@
263
                 $synctime
264
             );
265
 
266
-            $row = $db->fetch_assoc();
267
-            if (!$row) {
268
-                // Only if we don't have a timestamp that is older than synctime do we return the next best.
269
-                // We MUST return an entry if there are any, because otherwise we will keep INSERTing new entries in,
270
-                // relations_state_set
271
-                $db->limitquery(
272
-                    "SELECT `data`, `synctime` FROM `syncroton_relations_state`"
273
-                    . " WHERE `device_id` = ? AND `folder_id` = ?"
274
-                    . " ORDER BY `synctime` ASC",
275
-                    0,
276
-                    1,
277
-                    $device_key,
278
-                    $folderid,
279
-                    $synctime
280
-                );
281
-                $row = $db->fetch_assoc();
282
-            }
283
-
284
-            if ($row) {
285
-                // Don't use $row'synctime' for the internal cache, and use $synctime instead.
286
-                // The synctime of the found row is usually earlier than the requested synctime.
287
-                // Note: We use the internal cache because there's a call to both hasChanges() and
288
-                // getChangedEntries() in Sync. It's needed until we add some caching on a higher level.
289
-                $data = $row'data';
290
-                // Support data in both compressed and uncompressed format
291
-                if (strlen($data) && $data0 != '{' && $data0 != '') {
292
-                    $data = gzinflate($data);
293
-                }
294
-                $this->relations$folderid$synctime = json_decode($data, true);
295
-
296
-                // Cleanup: remove all records older than the current one.
297
-                // We must use the row's synctime, otherwise we would delete the record we just loaded
298
-                // We must delete all entries that are before the synctime to clean up old entries,
299
-                // but we must also delete all entries that are more recent in case the sync gets rerun
300
-                // with the same timestamp (e.g. when rerunning the same sync request).
301
-                // Otherwise the number of entries will start to grow with every sync.
302
-                $db->query(
303
-                    "DELETE FROM `syncroton_relations_state`"
304
-                    . " WHERE `device_id` = ? AND `folder_id` = ? AND `synctime` <> ?",
305
-                    $device_key,
306
-                    $folderid,
307
-                    $row'synctime'
308
-                );
309
+            if ($row = $db->fetch_assoc()) {
310
+                // MariaDB's datetime output includes microseconds, we need to remove them,
311
+                // it must be "Y-m-d H:i:s" format
312
+                $synctime = preg_replace('/\.0-9+/', '', $row'synctime');
313
+                $this->relations$folderid$synctime = json_decode($row'data', true);
314
             }
315
+
316
+            // Cleanup: remove all records except the current one
317
+            $db->query(
318
+                "DELETE FROM `syncroton_relations_state`"
319
+                . " WHERE `device_id` = ? AND `folder_id` = ? AND `synctime` <> ?",
320
+                $device_key,
321
+                $folderid,
322
+                $synctime
323
+            );
324
         }
325
 
326
         return $this->relations$folderid$synctime ?? null;
327
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_storage_kolab4.php Changed
71
 
1
@@ -29,8 +29,7 @@
2
 class kolab_sync_storage_kolab4 extends kolab_sync_storage
3
 {
4
     protected $davStorage = null;
5
-    protected $tagStorage = null;
6
-    protected $relationSupport = self::MODEL_EMAIL;
7
+    protected $relationSupport = false;
8
 
9
     /**
10
      * This implements the 'singleton' design pattern
11
@@ -67,7 +66,6 @@
12
         // Inject user+password to the URL, there's no other way to pass it to the DAV client
13
         $url = str_replace('://', '://' . rawurlencode($sync->username) . ':' . rawurlencode($sync->password) . '@', $url);
14
 
15
-        $this->tagStorage = new kolab_storage_tags();
16
         $this->davStorage = new kolab_storage_dav($url); // DAV
17
         $this->storage = $sync->get_storage(); // IMAP
18
 
19
@@ -467,35 +465,6 @@
20
     }
21
 
22
     /**
23
-     * Returns list of categories assigned to an object
24
-     *
25
-     * @param rcube_message_header|string $object     UID or mail message headers
26
-     * @param array                       $categories Addition tag names to merge with
27
-     *
28
-     * @return array List of categories
29
-     */
30
-    protected function getCategories($object, $categories = )
31
-    {
32
-        $tags = $this->tagStorage->get_tags_for($object);
33
-
34
-        // merge result with old categories
35
-        if (!empty($categories)) {
36
-            $tags = array_unique(array_merge($tags, (array) $categories));
37
-        }
38
-
39
-        return $tags;
40
-    }
41
-
42
-    /**
43
-     * Detect changes of tag objects data and assigned messages
44
-     */
45
-    protected function getChangesByRelations($folderid, $device_key, $type, $filter)
46
-    {
47
-        // This is not needed with Kolab4 that uses METADATA/ANNOTATE and immutable tags
48
-        return ;
49
-    }
50
-
51
-    /**
52
      * Gets kolab_storage_folder object from Activesync folder ID.
53
      *
54
      * @param string $folderid Folder identifier
55
@@ -599,15 +568,4 @@
56
         }
57
         return parent::getExtraData($folderid, $deviceid);
58
     }
59
-
60
-    /**
61
-     * Set categories to an object
62
-     *
63
-     * @param rcube_message_header|string $object     UID or mail message headers
64
-     * @param array                       $categories List of Category names
65
-     */
66
-    protected function setCategories($object, $categories)
67
-    {
68
-        $this->tagStorage->set_tags_for($object, $categories);
69
-    }
70
 }
71
kolab-syncroton-2.4.2.tar.gz/tests/Sync/FoldersTest.php Changed
274
 
1
@@ -3,270 +3,16 @@
2
 class FoldersTest extends Tests\SyncTestCase
3
 {
4
     /**
5
-     * Cleanup folders
6
+     * Test FolderSync command
7
      */
8
-    protected function foldersCleanup(): void
9
+    public function testFolderSync()
10
     {
11
         // Note: We essentially assume the test account is in an initial state, extra folders may break tests
12
         // Anyway, we first remove folders that might have been created during tests in this file
13
-        $this->deleteTestFolder('NewFolder', 'mail');
14
-        $this->deleteTestFolder('NewFolder2', 'mail');
15
         $this->deleteTestFolder('Test Folder', 'mail');
16
         $this->deleteTestFolder('Test Folder New', 'mail');
17
         $this->deleteTestFolder('Test Contacts Folder', 'contact');
18
         $this->deleteTestFolder('Test Contacts New', 'contact');
19
-    }
20
-
21
-    /**
22
-     * Test FolderSync command
23
-     */
24
-    public function testFolderSyncBasic()
25
-    {
26
-        $this->foldersCleanup();
27
-
28
-        $request = <<<EOF
29
-            <?xml version="1.0" encoding="utf-8"?>
30
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
31
-            <FolderSync xmlns="uri:FolderHierarchy">
32
-                <SyncKey>0</SyncKey>
33
-            </FolderSync>
34
-            EOF;
35
-
36
-        $response = $this->request($request, 'FolderSync');
37
-
38
-        $this->assertEquals(200, $response->getStatusCode());
39
-
40
-        $dom = $this->fromWbxml($response->getBody());
41
-        $xpath = $this->xpath($dom);
42
-
43
-        $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue);
44
-        $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:SyncKey")->item(0)->nodeValue);
45
-        // We expect some folders to exist (dont' know how many)
46
-        $this->assertTrue(intval($xpath->query("//ns:FolderSync/ns:Changes/ns:Count")->item(0)->nodeValue) > 2);
47
-
48
-        $request = <<<EOF
49
-            <?xml version="1.0" encoding="utf-8"?>
50
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
51
-            <FolderSync xmlns="uri:FolderHierarchy">
52
-                <SyncKey>1</SyncKey>
53
-            </FolderSync>
54
-            EOF;
55
-
56
-        $response = $this->request($request, 'FolderSync');
57
-
58
-        $this->assertEquals(200, $response->getStatusCode());
59
-
60
-        $dom = $this->fromWbxml($response->getBody());
61
-        $xpath = $this->xpath($dom);
62
-
63
-        $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue);
64
-        $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:SyncKey")->item(0)->nodeValue);
65
-        // No changes on second sync
66
-        $this->assertSame(strval(0), $xpath->query("//ns:FolderSync/ns:Changes/ns:Count")->item(0)->nodeValue);
67
-
68
-        //Clear the creation_synckey (that's the migration scenario)
69
-        //Shouldn't trigger a change
70
-        $rcube = \rcube::get_instance();
71
-        $db    = $rcube->get_dbh();
72
-        $result = $db->query(
73
-            "UPDATE `syncroton_folder` SET `creation_synckey` = 0",
74
-        );
75
-
76
-        $request = <<<EOF
77
-            <?xml version="1.0" encoding="utf-8"?>
78
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
79
-            <FolderSync xmlns="uri:FolderHierarchy">
80
-                <SyncKey>1</SyncKey>
81
-            </FolderSync>
82
-            EOF;
83
-
84
-        $response = $this->request($request, 'FolderSync');
85
-        $this->assertEquals(200, $response->getStatusCode());
86
-        $dom = $this->fromWbxml($response->getBody());
87
-        $xpath = $this->xpath($dom);
88
-        $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue);
89
-        $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:SyncKey")->item(0)->nodeValue);
90
-        // No changes on second sync
91
-        $this->assertSame(strval(0), $xpath->query("//ns:FolderSync/ns:Changes/ns:Count")->item(0)->nodeValue);
92
-    }
93
-
94
-    /**
95
-     * Test invalid sync key
96
-     */
97
-    public function testFolderInvalidSyncKey()
98
-    {
99
-        $request = <<<EOF
100
-            <?xml version="1.0" encoding="utf-8"?>
101
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
102
-            <FolderSync xmlns="uri:FolderHierarchy">
103
-                <SyncKey>999</SyncKey>
104
-            </FolderSync>
105
-            EOF;
106
-
107
-        $response = $this->request($request, 'FolderSync');
108
-
109
-        $this->assertEquals(200, $response->getStatusCode());
110
-
111
-        $dom = $this->fromWbxml($response->getBody());
112
-        $xpath = $this->xpath($dom);
113
-
114
-        $this->assertSame('9', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue);
115
-    }
116
-
117
-    /**
118
-     * Test synckey reuse
119
-     */
120
-    public function testSyncKeyResend()
121
-    {
122
-        $request = <<<EOF
123
-            <?xml version="1.0" encoding="utf-8"?>
124
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
125
-            <FolderSync xmlns="uri:FolderHierarchy">
126
-                <SyncKey>0</SyncKey>
127
-            </FolderSync>
128
-            EOF;
129
-        $response = $this->request($request, 'FolderSync');
130
-        $this->assertEquals(200, $response->getStatusCode());
131
-        $dom = $this->fromWbxml($response->getBody());
132
-        $xpath = $this->xpath($dom);
133
-        $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue);
134
-
135
-        //Now change something
136
-        $this->createTestFolder("NewFolder", "mail");
137
-        $request = <<<EOF
138
-            <?xml version="1.0" encoding="utf-8"?>
139
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
140
-            <FolderSync xmlns="uri:FolderHierarchy">
141
-                <SyncKey>1</SyncKey>
142
-            </FolderSync>
143
-            EOF;
144
-
145
-        $response = $this->request($request, 'FolderSync');
146
-        $this->assertEquals(200, $response->getStatusCode());
147
-        $dom = $this->fromWbxml($response->getBody());
148
-        $xpath = $this->xpath($dom);
149
-        $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue);
150
-        $this->assertSame('2', $xpath->query("//ns:FolderSync/ns:SyncKey")->item(0)->nodeValue);
151
-        $this->assertSame(strval(1), $xpath->query("//ns:FolderSync/ns:Changes/ns:Count")->item(0)->nodeValue);
152
-
153
-        //Resend the same synckey
154
-        $request = <<<EOF
155
-            <?xml version="1.0" encoding="utf-8"?>
156
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
157
-            <FolderSync xmlns="uri:FolderHierarchy">
158
-                <SyncKey>1</SyncKey>
159
-            </FolderSync>
160
-            EOF;
161
-
162
-        $response = $this->request($request, 'FolderSync');
163
-        $this->assertEquals(200, $response->getStatusCode());
164
-        $dom = $this->fromWbxml($response->getBody());
165
-        $xpath = $this->xpath($dom);
166
-        $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue);
167
-        $this->assertSame('2', $xpath->query("//ns:FolderSync/ns:SyncKey")->item(0)->nodeValue);
168
-        $this->assertSame(strval(1), $xpath->query("//ns:FolderSync/ns:Changes/ns:Count")->item(0)->nodeValue);
169
-
170
-        //And now make sure we can still move on
171
-        $request = <<<EOF
172
-            <?xml version="1.0" encoding="utf-8"?>
173
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
174
-            <FolderSync xmlns="uri:FolderHierarchy">
175
-                <SyncKey>2</SyncKey>
176
-            </FolderSync>
177
-            EOF;
178
-        $response = $this->request($request, 'FolderSync');
179
-        $this->assertEquals(200, $response->getStatusCode());
180
-        $dom = $this->fromWbxml($response->getBody());
181
-        $xpath = $this->xpath($dom);
182
-        $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue);
183
-        $this->assertSame('2', $xpath->query("//ns:FolderSync/ns:SyncKey")->item(0)->nodeValue);
184
-
185
-        //Now add another folder
186
-        $this->createTestFolder("NewFolder2", "mail");
187
-        $request = <<<EOF
188
-            <?xml version="1.0" encoding="utf-8"?>
189
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
190
-            <FolderSync xmlns="uri:FolderHierarchy">
191
-                <SyncKey>2</SyncKey>
192
-            </FolderSync>
193
-            EOF;
194
-        $response = $this->request($request, 'FolderSync');
195
-        $this->assertEquals(200, $response->getStatusCode());
196
-        $dom = $this->fromWbxml($response->getBody());
197
-        $xpath = $this->xpath($dom);
198
-        $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue);
199
-        $this->assertSame('3', $xpath->query("//ns:FolderSync/ns:SyncKey")->item(0)->nodeValue);
200
-        $this->assertSame(strval(1), $xpath->query("//ns:FolderSync/ns:Changes/ns:Count")->item(0)->nodeValue);
201
-
202
-        //And finally make sure we can't go back two synckeys (because that has been cleaned up meanwhile)
203
-        $this->createTestFolder("NewFolder2", "mail");
204
-        $request = <<<EOF
205
-            <?xml version="1.0" encoding="utf-8"?>
206
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
207
-            <FolderSync xmlns="uri:FolderHierarchy">
208
-                <SyncKey>1</SyncKey>
209
-            </FolderSync>
210
-            EOF;
211
-        $response = $this->request($request, 'FolderSync');
212
-        $this->assertEquals(200, $response->getStatusCode());
213
-        $dom = $this->fromWbxml($response->getBody());
214
-        $xpath = $this->xpath($dom);
215
-        $this->assertSame('9', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue);
216
-    }
217
-
218
-    /**
219
-     * This test recreates a previously deleted folder.
220
-     * Currently similar to disabling/reenabling a folder for sync, but should perhaps be tested separately
221
-     *
222
-     * @depends testSyncKeyResend
223
-     */
224
-    public function testRecreatePreviousFolder()
225
-    {
226
-        $this->deleteTestFolder('NewFolder', 'mail');
227
-        $this->deleteTestFolder('NewFolder2', 'mail');
228
-        $request = <<<EOF
229
-            <?xml version="1.0" encoding="utf-8"?>
230
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
231
-            <FolderSync xmlns="uri:FolderHierarchy">
232
-                <SyncKey>0</SyncKey>
233
-            </FolderSync>
234
-            EOF;
235
-        $response = $this->request($request, 'FolderSync');
236
-        $this->assertEquals(200, $response->getStatusCode());
237
-        $dom = $this->fromWbxml($response->getBody());
238
-        $xpath = $this->xpath($dom);
239
-        $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue);
240
-
241
-        //Now change something
242
-        $this->createTestFolder("NewFolder", "mail");
243
-        $request = <<<EOF
244
-            <?xml version="1.0" encoding="utf-8"?>
245
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
246
-            <FolderSync xmlns="uri:FolderHierarchy">
247
-                <SyncKey>1</SyncKey>
248
-            </FolderSync>
249
-            EOF;
250
-
251
-        $response = $this->request($request, 'FolderSync');
252
-        $this->assertEquals(200, $response->getStatusCode());
253
-        $dom = $this->fromWbxml($response->getBody());
254
-        $xpath = $this->xpath($dom);
255
-        $this->assertSame('1', $xpath->query("//ns:FolderSync/ns:Status")->item(0)->nodeValue);
256
-        $this->assertSame('2', $xpath->query("//ns:FolderSync/ns:SyncKey")->item(0)->nodeValue);
257
-        $this->assertSame(strval(1), $xpath->query("//ns:FolderSync/ns:Changes/ns:Count")->item(0)->nodeValue);
258
-
259
-        // Cleanup for the other tests
260
-        $this->deleteTestFolder('NewFolder', 'mail');
261
-        $this->deleteTestFolder('NewFolder2', 'mail');
262
-    }
263
-
264
-    /**
265
-     * Test FolderSync command
266
-     */
267
-    public function testFolderSync()
268
-    {
269
-        $this->foldersCleanup();
270
-        $this->resetDevice();
271
 
272
         $request = <<<EOF
273
             <?xml version="1.0" encoding="utf-8"?>
274
kolab-syncroton-2.4.2.tar.gz/tests/Sync/MoveItemsTest.php Changed
106
 
1
@@ -134,78 +134,15 @@
2
         $this->assertSame('test sync', $xpath->query("ns:Commands/ns:Add/ns:ApplicationData/Email:Subject", $root)->item(0)->nodeValue);
3
     }
4
 
5
-    public function testInvalidMove()
6
-    {
7
-        $this->emptyTestFolder('INBOX', 'mail');
8
-        $this->emptyTestFolder('Trash', 'mail');
9
-        $uid = $this->appendMail('INBOX', 'mail.sync1');
10
-        $this->registerDevice();
11
-        $inbox = array_search('INBOX', $this->folders);
12
-        $trash = array_search('Trash', $this->folders);
13
-
14
-        // Move item that doesn't exist
15
-        $request = <<<EOF
16
-            <?xml version="1.0" encoding="utf-8"?>
17
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
18
-            <MoveItems xmlns="uri:Move">
19
-                <Move>
20
-                    <SrcMsgId>foobar::99999</SrcMsgId>
21
-                    <SrcFldId>foobar</SrcFldId>
22
-                    <DstFldId>foobar</DstFldId>
23
-                </Move>
24
-            </MoveItems>
25
-            EOF;
26
-
27
-        $response = $this->request($request, 'MoveItems');
28
-
29
-        $this->assertEquals(200, $response->getStatusCode());
30
-
31
-        $dom = $this->fromWbxml($response->getBody());
32
-        $xpath = $this->xpath($dom);
33
-        $xpath->registerNamespace('Move', 'uri:Move');
34
-
35
-        $root = $xpath->query("//Move:MoveItems/Move:Response")->item(0);
36
-        $this->assertSame('1', $xpath->query("Move:Status", $root)->item(0)->nodeValue);
37
-
38
-        // Move item that doesn't exist
39
-        $request = <<<EOF
40
-            <?xml version="1.0" encoding="utf-8"?>
41
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
42
-            <MoveItems xmlns="uri:Move">
43
-                <Move>
44
-                    <SrcMsgId>{$inbox}::99999</SrcMsgId>
45
-                    <SrcFldId>{$inbox}</SrcFldId>
46
-                    <DstFldId>{$trash}</DstFldId>
47
-                </Move>
48
-            </MoveItems>
49
-            EOF;
50
-
51
-        $response = $this->request($request, 'MoveItems');
52
-
53
-        $this->assertEquals(200, $response->getStatusCode());
54
-
55
-        $dom = $this->fromWbxml($response->getBody());
56
-        $xpath = $this->xpath($dom);
57
-        $xpath->registerNamespace('Move', 'uri:Move');
58
-
59
-        $root = $xpath->query("//Move:MoveItems/Move:Response")->item(0);
60
-        $this->assertSame('1', $xpath->query("Move:Status", $root)->item(0)->nodeValue);
61
-    }
62
-
63
     /**
64
      * Test moving a contact
65
      */
66
     public function testMoveContact()
67
     {
68
-        if ($this->isStorageDriver('kolab')) {
69
-            // The Contacts folder is not available, and consequently appendObject fails
70
-            $this->markTestSkipped('This test only works with the DAV backend.');
71
-        }
72
-
73
         // Test with multi-folder support enabled
74
         self::$deviceType = 'iphone';
75
 
76
-        $davFolder = 'Contacts';
77
+        $davFolder = $this->isStorageDriver('kolab') ? 'Contacts' : 'Addressbook';
78
         $this->emptyTestFolder($davFolder, 'contact');
79
         $this->deleteTestFolder($folderName = 'Test Contacts Folder', 'contact');
80
         $this->appendObject($davFolder, 'contact.vcard1', 'contact');
81
@@ -213,7 +150,6 @@
82
         $this->registerDevice();
83
 
84
         $srcFolderId = array_search($davFolder, $this->folders);
85
-        $this->assertTrue(!empty($srcFolderId));
86
 
87
         // Create a contacts folder
88
         $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT_USER_CREATED;
89
@@ -260,8 +196,6 @@
90
         $response = $this->request($request, 'Sync');
91
 
92
         $this->assertEquals(200, $response->getStatusCode());
93
-        $root = $xpath->query("//ns:Sync/ns:Collections/ns:Collection")->item(0);
94
-        $this->assertSame('1', $xpath->query("ns:Status", $root)->item(0)->nodeValue);
95
 
96
         $request = <<<EOF
97
             <?xml version="1.0" encoding="utf-8"?>
98
@@ -308,7 +242,6 @@
99
         $xpath = $this->xpath($dom);
100
 
101
         $root = $xpath->query("//ns:Sync/ns:Collections/ns:Collection")->item(0);
102
-        $this->assertSame('1', $xpath->query("ns:Status", $root)->item(0)->nodeValue);
103
         $this->assertSame($srcFolderId, $xpath->query("ns:CollectionId", $root)->item(0)->nodeValue);
104
         $this->assertSame(1, $xpath->query("ns:Commands/ns:Add", $root)->count());
105
         $this->assertSame('Jane', $xpath->query("ns:Commands/ns:Add/ns:ApplicationData/Contacts:FirstName", $root)->item(0)->nodeValue);
106
kolab-syncroton-2.4.2.tar.gz/tests/Sync/OptionsTest.php Changed
10
 
1
@@ -7,7 +7,7 @@
2
      */
3
     public function testOptions()
4
     {
5
-        $response = self::$client->request('OPTIONS', '', 'auth' => null);
6
+        $response = self::$client->request('OPTIONS', '');
7
         $this->assertEquals(200, $response->getStatusCode());
8
         $this->assertStringContainsString('14', $response->getHeader('MS-Server-ActiveSync')0);
9
         $this->assertStringContainsString('14.1', $response->getHeader('MS-ASProtocolVersions')0);
10
kolab-syncroton-2.4.2.tar.gz/tests/Sync/PingTest.php Deleted
100
 
1
@@ -1,98 +0,0 @@
2
-<?php
3
-
4
-class PingTest extends Tests\SyncTestCase
5
-{
6
-    /**
7
-     * Test Ping command
8
-     */
9
-    public function testFolderSyncBasic()
10
-    {
11
-        $request = <<<EOF
12
-            <?xml version="1.0" encoding="utf-8"?>
13
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
14
-            <Ping xmlns="uri:Ping">
15
-                <HeartbeatInterval>900</HeartbeatInterval>
16
-                <Folders>
17
-                    <Folder>
18
-                        <Id>38b950ebd62cd9a66929c89615d0fc04</Id>
19
-                        <Class>Email</Class>
20
-                    </Folder>
21
-                </Folders>
22
-            </Ping>
23
-            EOF;
24
-
25
-        $response = $this->request($request, 'Ping');
26
-
27
-        $this->assertEquals(200, $response->getStatusCode());
28
-
29
-        $dom = $this->fromWbxml($response->getBody());
30
-        $xpath = $this->xpath($dom);
31
-
32
-        //Initially we know no folders
33
-        $this->assertSame('7', $xpath->query("//ns:Ping/ns:Status")->item(0)->nodeValue);
34
-
35
-
36
-        //We discover folders with a foldersync
37
-        $request = <<<EOF
38
-            <?xml version="1.0" encoding="utf-8"?>
39
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
40
-            <FolderSync xmlns="uri:FolderHierarchy">
41
-                <SyncKey>0</SyncKey>
42
-            </FolderSync>
43
-            EOF;
44
-
45
-        $response = $this->request($request, 'FolderSync');
46
-        $this->assertEquals(200, $response->getStatusCode());
47
-
48
-        //Now we get to the actual ping
49
-        $request = <<<EOF
50
-            <?xml version="1.0" encoding="utf-8"?>
51
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
52
-            <Ping xmlns="uri:Ping">
53
-                <HeartbeatInterval>0</HeartbeatInterval>
54
-                <Folders>
55
-                    <Folder>
56
-                        <Id>38b950ebd62cd9a66929c89615d0fc04</Id>
57
-                        <Class>Email</Class>
58
-                    </Folder>
59
-                </Folders>
60
-            </Ping>
61
-            EOF;
62
-
63
-        $response = $this->request($request, 'Ping');
64
-        $this->assertEquals(200, $response->getStatusCode());
65
-        $dom = $this->fromWbxml($response->getBody());
66
-        $xpath = $this->xpath($dom);
67
-        // Initially we know no folders
68
-        $this->assertSame('2', $xpath->query("//ns:Ping/ns:Status")->item(0)->nodeValue);
69
-    }
70
-
71
-    /**
72
-     * Test Ping command
73
-     */
74
-    public function testUnknownFolder()
75
-    {
76
-        $request = <<<EOF
77
-            <?xml version="1.0" encoding="utf-8"?>
78
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
79
-            <Ping xmlns="uri:Ping">
80
-                <HeartbeatInterval>900</HeartbeatInterval>
81
-                <Folders>
82
-                    <Folder>
83
-                        <Id>foobar</Id>
84
-                        <Class>Email</Class>
85
-                    </Folder>
86
-                </Folders>
87
-            </Ping>
88
-            EOF;
89
-
90
-        $response = $this->request($request, 'Ping');
91
-
92
-        $this->assertEquals(200, $response->getStatusCode());
93
-
94
-        $dom = $this->fromWbxml($response->getBody());
95
-        $xpath = $this->xpath($dom);
96
-
97
-        $this->assertSame('7', $xpath->query("//ns:Ping/ns:Status")->item(0)->nodeValue);
98
-    }
99
-}
100
kolab-syncroton-2.4.2.tar.gz/tests/Sync/Sync/ContactsTest.php Changed
10
 
1
@@ -9,7 +9,7 @@
2
      */
3
     public function testSync()
4
     {
5
-        $davFolder = 'Contacts';
6
+        $davFolder = $this->isStorageDriver('kolab') ? 'Contacts' : 'Addressbook';
7
         $this->emptyTestFolder($davFolder, 'contact');
8
         $this->deleteTestFolder('Test Contacts Folder', 'contact'); // from other test files
9
         $this->registerDevice();
10
kolab-syncroton-2.4.2.tar.gz/tests/Sync/Sync/EmailITipTest.php Changed
10
 
1
@@ -69,6 +69,8 @@
2
         $dom = $this->fromWbxml($response->getBody());
3
         $xpath = $this->xpath($dom);
4
 
5
+        // print($dom->saveXML());
6
+
7
         $root = "//ns:Sync/ns:Collections/ns:Collection";
8
         $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
9
         $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
10
kolab-syncroton-2.4.2.tar.gz/tests/Sync/Sync/EmailTest.php Changed
77
 
1
@@ -148,7 +148,6 @@
2
         $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
3
         $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue);
4
         $this->assertSame(1, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
5
-        $this->assertSame('0', $xpath->query("{$root}/ns:Commands/ns:Add/ns:ApplicationData/Email:Read")->item(0)->nodeValue);
6
 
7
         // Note: We assume messages are in IMAP default order, it may change in future
8
         $root .= "/ns:Commands/ns:Add";
9
@@ -239,6 +238,7 @@
10
         $this->assertEquals(200, $response->getStatusCode());
11
         $dom = $this->fromWbxml($response->getBody());
12
         $xpath = $this->xpath($dom);
13
+        // print($dom->saveXML());
14
 
15
         $root = "//ns:Sync/ns:Collections/ns:Collection";
16
         $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
17
@@ -247,10 +247,10 @@
18
         $this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
19
         $this->assertSame(2, $xpath->query("{$root}/ns:Commands/ns:Change")->count());
20
         $this->assertSame(2, $xpath->query("{$root}/ns:Commands/ns:Change/ns:ApplicationData/Email:Read")->count());
21
-        $this->assertSame('1', $xpath->query("{$root}/ns:Commands/ns:Change/ns:ApplicationData/Email:Read")->item(0)->nodeValue);
22
-        $this->assertSame('1', $xpath->query("{$root}/ns:Commands/ns:Change/ns:ApplicationData/Email:Read")->item(1)->nodeValue);
23
-        $this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Change/ns:ApplicationData/AirSyncBase:Body")->count());
24
+        $this->assertSame('0', $xpath->query("{$root}/ns:Commands/ns:Change/ns:ApplicationData/Email:Read")->item(0)->nodeValue);
25
+        $this->assertSame('0', $xpath->query("{$root}/ns:Commands/ns:Change/ns:ApplicationData/Email:Read")->item(1)->nodeValue);
26
 
27
+        $this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Change/ns:ApplicationData/AirSyncBase:Body")->count());
28
         return $syncKey;
29
     }
30
 
31
@@ -293,6 +293,7 @@
32
         $this->assertEquals(200, $response->getStatusCode());
33
         $dom = $this->fromWbxml($response->getBody());
34
         $xpath = $this->xpath($dom);
35
+        // print($dom->saveXML());
36
 
37
         $root = "//ns:Sync/ns:Collections/ns:Collection";
38
         $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
39
@@ -348,6 +349,7 @@
40
         $this->assertEquals(200, $response->getStatusCode());
41
         $dom = $this->fromWbxml($response->getBody());
42
         $xpath = $this->xpath($dom);
43
+        // print($dom->saveXML());
44
 
45
         $root = "//ns:Sync/ns:Collections/ns:Collection";
46
         $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
47
@@ -402,6 +404,7 @@
48
         $this->assertEquals(200, $response->getStatusCode());
49
         $dom = $this->fromWbxml($response->getBody());
50
         $xpath = $this->xpath($dom);
51
+        // print($dom->saveXML());
52
 
53
         $root = "//ns:Sync/ns:Collections/ns:Collection";
54
         $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
55
@@ -419,6 +422,7 @@
56
         return $syncKey;
57
     }
58
 
59
+
60
     /**
61
     * Test a sync key that doesn't exist yet.
62
     * @depends testDeleteFromClient
63
@@ -456,6 +460,7 @@
64
         $this->assertEquals(200, $response->getStatusCode());
65
         $dom = $this->fromWbxml($response->getBody());
66
         $xpath = $this->xpath($dom);
67
+        // print($dom->saveXML());
68
 
69
         $root = "//ns:Sync/ns:Collections/ns:Collection";
70
         $this->assertSame('3', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
71
@@ -464,4 +469,5 @@
72
         //We have to start over after this. The sync state was removed.
73
         return 0;
74
     }
75
+
76
 }
77
kolab-syncroton-2.4.2.tar.gz/tests/Sync/Sync/InconsistencyTest.php Deleted
143
 
1
@@ -1,141 +0,0 @@
2
-<?php
3
-
4
-namespace Tests\Sync\Sync;
5
-
6
-class InconsistencyTest extends \Tests\SyncTestCase
7
-{
8
-    /**
9
-     * Test Sync command
10
-     */
11
-    public function testSync()
12
-    {
13
-        $this->emptyTestFolder('INBOX', 'mail');
14
-        $this->registerDevice();
15
-
16
-        // Append two mail messages
17
-        $uid1 = $this->appendMail('INBOX', 'mail.sync1');
18
-        $this->appendMail('INBOX', 'mail.sync2');
19
-
20
-        // Initial sync
21
-        $folderId = '38b950ebd62cd9a66929c89615d0fc04';
22
-        $syncKey = 0;
23
-        $request = <<<EOF
24
-            <?xml version="1.0" encoding="utf-8"?>
25
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
26
-            <Sync xmlns="uri:AirSync">
27
-                <Collections>
28
-                    <Collection>
29
-                        <SyncKey>{$syncKey}</SyncKey>
30
-                        <CollectionId>{$folderId}</CollectionId>
31
-                    </Collection>
32
-                </Collections>
33
-            </Sync>
34
-            EOF;
35
-
36
-        $response = $this->request($request, 'Sync');
37
-        $this->assertEquals(200, $response->getStatusCode());
38
-        $syncKey++;
39
-
40
-        $request = <<<EOF
41
-            <?xml version="1.0" encoding="utf-8"?>
42
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
43
-            <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase">
44
-                <Collections>
45
-                    <Collection>
46
-                        <SyncKey>{$syncKey}</SyncKey>
47
-                        <CollectionId>{$folderId}</CollectionId>
48
-                        <DeletesAsMoves>1</DeletesAsMoves>
49
-                        <GetChanges>1</GetChanges>
50
-                        <WindowSize>2</WindowSize>
51
-                        <Options>
52
-                            <FilterType>0</FilterType>
53
-                            <Conflict>1</Conflict>
54
-                            <BodyPreference xmlns="uri:AirSyncBase">
55
-                                <Type>2</Type>
56
-                                <TruncationSize>51200</TruncationSize>
57
-                                <AllOrNone>0</AllOrNone>
58
-                            </BodyPreference>
59
-                        </Options>
60
-                    </Collection>
61
-                </Collections>
62
-            </Sync>
63
-            EOF;
64
-
65
-        $response = $this->request($request, 'Sync');
66
-
67
-        $this->assertEquals(200, $response->getStatusCode());
68
-
69
-        $dom = $this->fromWbxml($response->getBody());
70
-        $xpath = $this->xpath($dom);
71
-
72
-        $root = "//ns:Sync/ns:Collections/ns:Collection";
73
-        $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
74
-        $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
75
-        $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue);
76
-        $this->assertSame(2, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
77
-
78
-        // Initial sync is complete
79
-        // We now artifically create a sync inconsistency be deleting the content part of the first mail.
80
-        // This replicates a situation that we've seen, but don't know yet how it was created in the first place.
81
-        $rcube = \rcube::get_instance();
82
-        $db    = $rcube->get_dbh();
83
-        $result = $db->query(
84
-            "DELETE FROM `syncroton_content`"
85
-            . " WHERE `contentid` = ?",
86
-            "$folderId::$uid1"
87
-        );
88
-        $this->assertNull($db->is_error($result));
89
-
90
-        // Now sync again
91
-        $request = <<<EOF
92
-            <?xml version="1.0" encoding="utf-8"?>
93
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
94
-            <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase">
95
-                <Collections>
96
-                    <Collection>
97
-                        <SyncKey>{$syncKey}</SyncKey>
98
-                        <CollectionId>{$folderId}</CollectionId>
99
-                        <DeletesAsMoves>1</DeletesAsMoves>
100
-                        <GetChanges>1</GetChanges>
101
-                        <Options>
102
-                            <FilterType>0</FilterType>
103
-                            <Conflict>1</Conflict>
104
-                            <BodyPreference xmlns="uri:AirSyncBase">
105
-                                <Type>2</Type>
106
-                                <TruncationSize>51200</TruncationSize>
107
-                                <AllOrNone>0</AllOrNone>
108
-                            </BodyPreference>
109
-                        </Options>
110
-                    </Collection>
111
-                </Collections>
112
-            </Sync>
113
-            EOF;
114
-
115
-        $response = $this->request($request, 'Sync');
116
-
117
-        $this->assertEquals(200, $response->getStatusCode());
118
-
119
-        $dom = $this->fromWbxml($response->getBody());
120
-        $xpath = $this->xpath($dom);
121
-
122
-        $root = "//ns:Sync/ns:Collections/ns:Collection";
123
-        $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
124
-        $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
125
-        $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue);
126
-        $this->assertSame(1, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
127
-
128
-        // Assert that we have all content parts back
129
-        $result = $db->query(
130
-            "SELECT `contentid` FROM `syncroton_content`"
131
-            . " WHERE `device_id` IN (SELECT `id` FROM `syncroton_device` WHERE `deviceid` = ?)",
132
-            self::$deviceId
133
-        );
134
-        $data = ;
135
-        while ($state = $db->fetch_assoc($result)) {
136
-            $data = $state;
137
-        }
138
-        $this->assertSame(2, count($data));
139
-
140
-        return $syncKey;
141
-    }
142
-}
143
kolab-syncroton-2.4.2.tar.gz/tests/Sync/Sync/RelationsTest.php Deleted
286
 
1
@@ -1,284 +0,0 @@
2
-<?php
3
-
4
-namespace Tests\Sync\Sync;
5
-
6
-class RelationsTest extends \Tests\SyncTestCase
7
-{
8
-    protected function initialSyncRequest($folderId)
9
-    {
10
-        $request = <<<EOF
11
-            <?xml version="1.0" encoding="utf-8"?>
12
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
13
-            <Sync xmlns="uri:AirSync">
14
-                <Collections>
15
-                    <Collection>
16
-                        <SyncKey>0</SyncKey>
17
-                        <CollectionId>{$folderId}</CollectionId>
18
-                    </Collection>
19
-                </Collections>
20
-            </Sync>
21
-            EOF;
22
-        return $this->request($request, 'Sync');
23
-    }
24
-
25
-    protected function syncRequest($syncKey, $folderId, $windowSize = null)
26
-    {
27
-        $request = <<<EOF
28
-            <?xml version="1.0" encoding="utf-8"?>
29
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
30
-            <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase">
31
-                <Collections>
32
-                    <Collection>
33
-                        <SyncKey>{$syncKey}</SyncKey>
34
-                        <CollectionId>{$folderId}</CollectionId>
35
-                        <DeletesAsMoves>1</DeletesAsMoves>
36
-                        <GetChanges>1</GetChanges>
37
-                        <WindowSize>{$windowSize}</WindowSize>
38
-                        <Options>
39
-                            <FilterType>0</FilterType>
40
-                            <Conflict>1</Conflict>
41
-                            <BodyPreference xmlns="uri:AirSyncBase">
42
-                                <Type>2</Type>
43
-                                <TruncationSize>51200</TruncationSize>
44
-                                <AllOrNone>0</AllOrNone>
45
-                            </BodyPreference>
46
-                        </Options>
47
-                    </Collection>
48
-                </Collections>
49
-            </Sync>
50
-            EOF;
51
-        return $this->request($request, 'Sync');
52
-    }
53
-
54
-    private function getRelationsState($device_id, $folderId)
55
-    {
56
-        $db    = \rcube::get_instance()->get_dbh();
57
-        $result = $db->query(
58
-            "SELECT `data`, `synctime` FROM `syncroton_relations_state`"
59
-            . " WHERE `device_id` IN (SELECT `id` FROM `syncroton_device` WHERE `deviceid` = ?) AND `folder_id` = ?"
60
-            . " ORDER BY `synctime` DESC",
61
-            $device_id,
62
-            $folderId
63
-        );
64
-        $data = ;
65
-        while ($state = $db->fetch_assoc($result)) {
66
-            $data = $state;
67
-        }
68
-        return $data;
69
-    }
70
-
71
-    /**
72
-     * Test Sync command
73
-     */
74
-    public function testRelationsSync()
75
-    {
76
-        $sync = \kolab_sync::get_instance();
77
-
78
-        $this->emptyTestFolder('INBOX', 'mail');
79
-        if ($this->isStorageDriver('kolab4')) {
80
-            $sync->get_storage()->set_metadata(\kolab_storage_tags::METADATA_ROOT, \kolab_storage_tags::METADATA_TAGS_KEY => null);
81
-        } else {
82
-            $this->emptyTestFolder('Configuration', 'configuration');
83
-        }
84
-        $this->registerDevice();
85
-
86
-        // Test INBOX
87
-        $folderId = '38b950ebd62cd9a66929c89615d0fc04';
88
-        $syncKey = 0;
89
-        $response = $this->initialSyncRequest($folderId);
90
-        $this->assertEquals(200, $response->getStatusCode());
91
-
92
-        $dom = $this->fromWbxml($response->getBody());
93
-        $xpath = $this->xpath($dom);
94
-
95
-        $this->assertSame('1', $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:Status")->item(0)->nodeValue);
96
-        $this->assertSame(strval(++$syncKey), $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:SyncKey")->item(0)->nodeValue);
97
-        $this->assertSame('Email', $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:Class")->item(0)->nodeValue);
98
-        $this->assertSame($folderId, $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:CollectionId")->item(0)->nodeValue);
99
-
100
-        // First we append
101
-        $uid1 = $this->appendMail('INBOX', 'mail.sync1');
102
-        $uid2 = $this->appendMail('INBOX', 'mail.sync2');
103
-        $this->appendMail('INBOX', 'mail.sync1', 'sync1' => 'sync3');
104
-        $this->appendMail('INBOX', 'mail.sync1', 'sync1' => 'sync4');
105
-
106
-        $sync = \kolab_sync::get_instance();
107
-
108
-        // Add a tag
109
-        $sync->storage(true)->updateItem($folderId, self::$deviceId, \kolab_sync_storage::MODEL_EMAIL, $uid1, null, 'categories' => 'test1');
110
-        sleep(1);
111
-
112
-        $response = $this->syncRequest($syncKey, $folderId, 10);
113
-        $this->assertEquals(200, $response->getStatusCode());
114
-        $dom = $this->fromWbxml($response->getBody());
115
-        $xpath = $this->xpath($dom);
116
-        $root = "//ns:Sync/ns:Collections/ns:Collection";
117
-        $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
118
-        $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
119
-        $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue);
120
-        $this->assertSame(4, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
121
-
122
-        $root .= "/ns:Commands/ns:Add";
123
-        $this->assertSame(1, $xpath->query("{$root}/ns:ApplicationData/Email:Categories")->count());
124
-        $this->assertSame("test1", $xpath->query("{$root}/ns:ApplicationData/Email:Categories")->item(0)->nodeValue);
125
-
126
-        // Add a second tag
127
-        $sync->storage(true)->updateItem($folderId, self::$deviceId, \kolab_sync_storage::MODEL_EMAIL, $uid1, null, 'categories' => 'test1', 'test2');
128
-        sleep(1); // Necessary to make sure we pick up on the tag.
129
-
130
-        $response = $this->syncRequest($syncKey, $folderId, 10);
131
-        $this->assertEquals(200, $response->getStatusCode());
132
-        $dom = $this->fromWbxml($response->getBody());
133
-        $xpath = $this->xpath($dom);
134
-
135
-        $root = "//ns:Sync/ns:Collections/ns:Collection";
136
-        $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
137
-        $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
138
-        $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue);
139
-        $this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
140
-        $this->assertSame(1, $xpath->query("{$root}/ns:Commands/ns:Change")->count());
141
-        $root .= "/ns:Commands/ns:Change";
142
-        $this->assertSame(1, $xpath->query("{$root}/ns:ApplicationData/Email:Categories")->count());
143
-        //FIXME not sure what I'm doing wrong, but the xml looks ok
144
-        $this->assertSame("test1test2", $xpath->query("{$root}/ns:ApplicationData/Email:Categories")->item(0)->nodeValue);
145
-
146
-        $retries = 2;
147
-        $syncKey--;
148
-        // Rerun the same command and make sure we get the same result
149
-        for ($i = 0; $i < $retries; $i++) {
150
-            $response = $this->syncRequest($syncKey, $folderId, 10);
151
-            $this->assertEquals(200, $response->getStatusCode());
152
-            $dom = $this->fromWbxml($response->getBody());
153
-            $xpath = $this->xpath($dom);
154
-
155
-            $root = "//ns:Sync/ns:Collections/ns:Collection";
156
-            $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
157
-            $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue);
158
-            $this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
159
-            $this->assertSame(1, $xpath->query("{$root}/ns:Commands/ns:Change")->count());
160
-            $root .= "/ns:Commands/ns:Change";
161
-            $this->assertSame(1, $xpath->query("{$root}/ns:ApplicationData/Email:Categories")->count());
162
-            //FIXME not sure what I'm doing wrong, but the xml looks ok
163
-            $this->assertSame("test1test2", $xpath->query("{$root}/ns:ApplicationData/Email:Categories")->item(0)->nodeValue);
164
-
165
-            // Assert the db state
166
-            if ($this->isStorageDriver('kolab')) {
167
-                $this->assertSame(2, count($this->getRelationsState(self::$deviceId, $folderId)));
168
-            }
169
-            // Make sure we have a new timestamp after the first iteration.
170
-            // This way we can potentially catch errors when we end up using the same or a different timestamp.
171
-            sleep(1);
172
-        }
173
-        $syncKey += ($retries + 1);
174
-
175
-        // Reset to no tags
176
-        $sync->storage(true)->updateItem($folderId, self::$deviceId, \kolab_sync_storage::MODEL_EMAIL, $uid1, null, 'categories' => );
177
-        sleep(1); // Necessary to make sure we pick up on the tag.
178
-
179
-        $response = $this->syncRequest($syncKey, $folderId, 10);
180
-        $this->assertEquals(200, $response->getStatusCode());
181
-        $dom = $this->fromWbxml($response->getBody());
182
-        $xpath = $this->xpath($dom);
183
-
184
-        $root = "//ns:Sync/ns:Collections/ns:Collection";
185
-        $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
186
-        $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
187
-        $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue);
188
-        $this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
189
-        $this->assertSame(1, $xpath->query("{$root}/ns:Commands/ns:Change")->count());
190
-        $root .= "/ns:Commands/ns:Change";
191
-        $this->assertSame(0, $xpath->query("{$root}/ns:ApplicationData/Email:Categories")->count());
192
-        //FIXME this currently fails because we omit the empty categories element
193
-        // $this->assertSame("", $xpath->query("{$root}/ns:ApplicationData/Email:Categories")->item(0)->nodeValue);
194
-
195
-        // Assert the db state
196
-        if ($this->isStorageDriver('kolab')) {
197
-            $this->assertSame(2, count($this->getRelationsState(self::$deviceId, $folderId)));
198
-        }
199
-
200
-        $response = $this->syncRequest($syncKey, $folderId, 10);
201
-        $this->assertEquals(200, $response->getStatusCode());
202
-        // We expect an empty response without a change
203
-        $this->assertEquals(0, $response->getBody()->getSize());
204
-        // print($dom->saveXML());
205
-
206
-        return $syncKey;
207
-    }
208
-
209
-    public function testPing()
210
-    {
211
-        // Setup with a tag and an initial sync completed
212
-        $folderId = '38b950ebd62cd9a66929c89615d0fc04';
213
-        $sync = \kolab_sync::get_instance();
214
-
215
-        $uid1 = $this->appendMail('INBOX', 'mail.sync1');
216
-        $sync->storage(true)->updateItem($folderId, self::$deviceId, \kolab_sync_storage::MODEL_EMAIL, $uid1, null, 'categories' => 'test1');
217
-        sleep(1);
218
-
219
-        $response = $this->syncRequest(0, $folderId, 10);
220
-        $this->assertEquals(200, $response->getStatusCode());
221
-        $response = $this->syncRequest(1, $folderId, 10);
222
-        $this->assertEquals(200, $response->getStatusCode());
223
-
224
-        if ($this->isStorageDriver('kolab')) {
225
-            $this->assertSame(2, count($this->getRelationsState(self::$deviceId, $folderId)));
226
-        }
227
-
228
-        // Make sure the timestamp changes
229
-        sleep(1);
230
-
231
-        // Pings should not change the number of relation states
232
-        for ($i = 0; $i < 2; $i++) {
233
-            $request = <<<EOF
234
-                <?xml version="1.0" encoding="utf-8"?>
235
-                <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
236
-                <Ping xmlns="uri:Ping">
237
-                    <HeartbeatInterval>0</HeartbeatInterval>
238
-                    <Folders>
239
-                        <Folder>
240
-                            <Id>$folderId</Id>
241
-                            <Class>Email</Class>
242
-                        </Folder>
243
-                    </Folders>
244
-                </Ping>
245
-                EOF;
246
-
247
-            $response = $this->request($request, 'Ping');
248
-
249
-            $this->assertEquals(200, $response->getStatusCode());
250
-            if ($this->isStorageDriver('kolab')) {
251
-                $this->assertSame(1, count($this->getRelationsState(self::$deviceId, $folderId)));
252
-            }
253
-        }
254
-
255
-        // This simulates a specific case where we had:
256
-        // * An old lastsync timestamp (because the folders were not actively synchronized)
257
-        // * The folder was still included in the ping command
258
-        // => This resulted in the relations code never finding a relation, and thus not cleaning up, but it still inserted new entries
259
-        $db    = \rcube::get_instance()->get_dbh();
260
-        $result = $db->query(
261
-            "UPDATE `syncroton_synckey` SET `lastsync` = '2023-06-23 13:15:03'"
262
-        );
263
-
264
-        $request = <<<EOF
265
-            <?xml version="1.0" encoding="utf-8"?>
266
-            <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
267
-            <Ping xmlns="uri:Ping">
268
-                <HeartbeatInterval>0</HeartbeatInterval>
269
-                <Folders>
270
-                    <Folder>
271
-                        <Id>$folderId</Id>
272
-                        <Class>Email</Class>
273
-                    </Folder>
274
-                </Folders>
275
-            </Ping>
276
-            EOF;
277
-
278
-        $response = $this->request($request, 'Ping');
279
-
280
-        $this->assertEquals(200, $response->getStatusCode());
281
-        if ($this->isStorageDriver('kolab')) {
282
-            $this->assertSame(1, count($this->getRelationsState(self::$deviceId, $folderId)));
283
-        }
284
-    }
285
-}
286
kolab-syncroton-2.4.2.tar.gz/tests/SyncTestCase.php Changed
110
 
1
@@ -43,7 +43,7 @@
2
             return;
3
         }
4
 
5
-        self::$deviceId = 'test' . str_replace('.', '', microtime(true));
6
+        self::$deviceId = 'test' . time();
7
 
8
         $db->query('DELETE FROM syncroton_device');
9
         $db->query('DELETE FROM syncroton_synckey');
10
@@ -51,7 +51,6 @@
11
         $db->query('DELETE FROM syncroton_data');
12
         $db->query('DELETE FROM syncroton_data_folder');
13
         $db->query('DELETE FROM syncroton_content');
14
-        $db->query('DELETE FROM syncroton_relations_state');
15
 
16
         self::$client = new \GuzzleHttp\Client(
17
                 'http_errors' => false,
18
@@ -88,7 +87,6 @@
19
             $db->query('DELETE FROM syncroton_device');
20
             $db->query('DELETE FROM syncroton_synckey');
21
             $db->query('DELETE FROM syncroton_folder');
22
-            $db->query('DELETE FROM syncroton_relations_state');
23
         }
24
     }
25
 
26
@@ -118,7 +116,7 @@
27
         $uid = $imap->save_message($folder, $source, '', $is_file);
28
 
29
         if ($uid === false) {
30
-            exit("Failed to append mail {$filename} into {$folder}");
31
+            exit("Failed to append mail into {$folder}");
32
         }
33
 
34
         return $uid;
35
@@ -175,9 +173,9 @@
36
             if ($imap->folder_exists($foldername)) {
37
                 // TODO
38
                 exit("Not implemented for Kolab v3 storage driver");
39
-            } else {
40
-                exit("Folder is missing");
41
             }
42
+
43
+            return;
44
         }
45
 
46
         $dav = $this->getDavStorage();
47
@@ -222,27 +220,6 @@
48
     }
49
 
50
     /**
51
-     * Create a folder
52
-     */
53
-    protected function createTestFolder($name, $type)
54
-    {
55
-        // Create IMAP folders
56
-        if ($type == 'mail' || $this->isStorageDriver('kolab')) {
57
-            $imap = $this->getImapStorage();
58
-            //TODO set type if not mail
59
-            $imap->create_folder($name, true);
60
-
61
-            $metadata = ;
62
-            $metadata'FOLDER' = ;
63
-            $metadata'FOLDER'self::$deviceId = ;
64
-            $metadata'FOLDER'self::$deviceId'S' = '1';
65
-            $imap->set_metadata($name, '/private/vendor/kolab/activesync' => json_encode($metadata));
66
-
67
-            return;
68
-        }
69
-    }
70
-
71
-    /**
72
      * Remove all objects from a folder
73
      */
74
     protected function emptyTestFolder($name, $type)
75
@@ -379,19 +356,6 @@
76
         }
77
     }
78
 
79
-    protected function resetDevice()
80
-    {
81
-        $sync = \kolab_sync::get_instance();
82
-
83
-        if (self::$deviceId) {
84
-            $storage = $sync->storage();
85
-            $storage->device_delete(self::$deviceId);
86
-        }
87
-
88
-        $db = $sync->get_dbh();
89
-        $db->query('DELETE FROM syncroton_device');
90
-    }
91
-
92
     /**
93
      * Convert XML into WBXML binary content
94
      */
95
@@ -426,14 +390,6 @@
96
         return $xpath;
97
     }
98
 
99
-    /**
100
-      * Pretty print the DOM
101
-      */
102
-    protected function printDom($dom)
103
-    {
104
-        $dom->formatOutput = true;
105
-        print($dom->saveXML());
106
-    }
107
 
108
     /**
109
      * adapter for phpunit < 9
110
kolab-syncroton.dsc Changed
10
 
1
@@ -2,7 +2,7 @@
2
 Source: kolab-syncroton
3
 Binary: kolab-syncroton
4
 Architecture: all
5
-Version: 1:2.4.2.39-1~kolab1
6
+Version: 1:2.4.2.23-1~kolab1
7
 Maintainer: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
8
 Uploaders: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
9
 Homepage: http://www.kolab.org/
10
Refresh


Request History
mollekopf's avatar

mollekopf created request 8 months ago

New release 2.4.2.23