This request is superseded by
request 3306
(Show diff)
Overview
Request 3305 (superseded)
New release 2.4.2.23
- Created by mollekopf 8 months ago
- In state superseded
- Supersedes 3304
- Superseded by 3306
-
Open review for
Admin
-
Open review for
vanmeeuwen
-
Open review for
mollekopf
-
Open review for
kolab-developers
kolab-syncroton.spec
Changed
x
1
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/Content.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/Device.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/Folder.php
Changed
28
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/IContent.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/IDevice.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/IFolder.php
Changed
34
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/Policy.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Backend/SyncState.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/AutoDiscover.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/FolderCreate.php
Changed
24
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/FolderSync.php
Changed
154
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
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
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
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
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
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
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/GetAttachment.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/GetItemEstimate.php
Changed
34
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
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
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/ItemOperations.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/MeetingResponse.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/MoveItems.php
Changed
51
1
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/Ping.php
Changed
60
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
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
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
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
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/Search.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/SendMail.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/Settings.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/SmartForward.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/SmartReply.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/Sync.php
Changed
427
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/AData.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/Calendar.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/Contacts.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/Email.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/Factory.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/IData.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/IDataCalendar.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/IDataEmail.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/IDataSearch.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/Notes.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/Tasks.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/AccessDenied.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/DeadlockDetected.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/MemoryExhausted.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/NotFound.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/PolicyKeyMissing.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/ProvisioningNeeded.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/Status.php
Changed
7
1
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
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
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
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
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
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
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
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
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
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Exception/UnexpectedValue.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/AEntry.php
Changed
16
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
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
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
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Contact.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Content.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Device.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/DeviceInformation.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Email.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EmailAttachment.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EmailBody.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EmailFlag.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EmailMeetingRequest.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EmailRecurrence.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Event.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EventAttendee.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EventException.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/EventRecurrence.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/FileReference.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Folder.php
Changed
11
1
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/GALPicture.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/IContent.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/IEntry.php
Changed
7
1
2
<?php
3
-
4
/*
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/IFolder.php
Changed
15
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/ISyncState.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/IXMLEntry.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/MeetingResponse.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Note.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Policy.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/SendMail.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/SmartForward.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/SmartReply.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/StoreRequest.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/StoreResponseResult.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/SyncCollection.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/SyncState.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/Task.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Model/TaskRecurrence.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Registry.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Zend Framework
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Server.php
Changed
47
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
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
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/TransactionManagerInterface.php
Changed
7
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Abstract.php
Changed
43
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
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
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
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
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
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
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
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
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
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
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
77
{
78
$uInt = $this->_getMultibyteUInt();
79
80
- switch ($uInt) {
81
+ switch($uInt) {
82
case 106:
83
$this->_charSet = 'UTF-8';
84
break;
85
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Wbxml/Encoder.php
Changed
83
1
2
<?php
3
-
4
/**
5
* Syncroton
6
*
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
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
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
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
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
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
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
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
2
<?php
3
-
4
/**
5
* Syncroton
6
*
7
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync.php
Changed
86
1
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
56
return $syncKey;
57
}
58
59
+
60
/**
61
* Test a sync key that doesn't exist yet.
62
* @depends testDeleteFromClient
63
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
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
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
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
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
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
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
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
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
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
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
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
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
kolab-syncroton
x86_64
x86_64
x86_64
x86_64
x86_64
ppc64le
x86_64
x86_64
x86_64
x86_64
x86_64
x86_64
x86_64
x86_64
x86_64
ppc64le
x86_64
x86_64
x86_64
x86_64
x86_64
x86_64
x86_64
x86_64
Refresh
Login required, please
login
in order to comment
Request History
mollekopf created request 8 months ago
New release 2.4.2.23
mollekopf superseded request 8 months ago
superseded by 3306