1
|
|
|
<?php |
2
|
|
|
/* |
3
|
|
|
* SPDX-License-Identifier: AGPL-3.0-only |
4
|
|
|
* SPDX-FileCopyrightText: Copyright 2007-2016 Zarafa Deutschland GmbH |
5
|
|
|
* SPDX-FileCopyrightText: Copyright 2020-2022 grommunio GmbH |
6
|
|
|
* |
7
|
|
|
* Defines general behavior of sub-WBXML entities (Sync* objects) that can be |
8
|
|
|
* parsed directly (as a stream) from WBXML. They are automatically decoded |
9
|
|
|
* according to $mapping by the Streamer and the Sync WBXML mappings. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
abstract class SyncObject extends Streamer { |
13
|
|
|
public const STREAMER_CHECKS = 6; |
14
|
|
|
public const STREAMER_CHECK_REQUIRED = 7; |
15
|
|
|
public const STREAMER_CHECK_ZEROORONE = 8; |
16
|
|
|
public const STREAMER_CHECK_NOTALLOWED = 9; |
17
|
|
|
public const STREAMER_CHECK_ONEVALUEOF = 10; |
18
|
|
|
public const STREAMER_CHECK_SETZERO = "setToValue0"; |
19
|
|
|
public const STREAMER_CHECK_SETONE = "setToValue1"; |
20
|
|
|
public const STREAMER_CHECK_SETTWO = "setToValue2"; |
21
|
|
|
public const STREAMER_CHECK_SETEMPTY = "setToValueEmpty"; |
22
|
|
|
public const STREAMER_CHECK_CMPLOWER = 13; |
23
|
|
|
public const STREAMER_CHECK_CMPHIGHER = 14; |
24
|
|
|
public const STREAMER_CHECK_LENGTHMAX = 15; |
25
|
|
|
public const STREAMER_CHECK_EMAIL = 16; |
26
|
|
|
|
27
|
|
|
protected $unsetVars; |
28
|
|
|
protected $supportsPrivateStripping; |
29
|
|
|
protected $checkedParameters; |
30
|
|
|
|
31
|
|
|
public function __construct($mapping) { |
32
|
|
|
$this->unsetVars = []; |
33
|
|
|
$this->supportsPrivateStripping = false; |
34
|
|
|
$this->checkedParameters = false; |
35
|
|
|
parent::__construct($mapping); |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Sets all supported but not transmitted variables |
40
|
|
|
* of this SyncObject to an "empty" value, so they are deleted when being saved. |
41
|
|
|
* |
42
|
|
|
* @param array $supportedFields array with all supported fields, if available |
43
|
|
|
* |
44
|
|
|
* @return bool |
45
|
|
|
*/ |
46
|
|
|
public function emptySupported($supportedFields) { |
47
|
|
|
// Some devices do not send supported tag. In such a case remove all not set properties. |
48
|
|
|
if ($supportedFields === false || !is_array($supportedFields) || (empty($supportedFields))) { |
|
|
|
|
49
|
|
|
if (defined('UNSET_UNDEFINED_PROPERTIES') && |
50
|
|
|
UNSET_UNDEFINED_PROPERTIES && |
51
|
|
|
( |
52
|
|
|
$this instanceof SyncContact || |
53
|
|
|
$this instanceof SyncAppointment || |
54
|
|
|
$this instanceof SyncTask |
55
|
|
|
)) { |
56
|
|
|
SLog::Write(LOGLEVEL_INFO, sprintf("%s->emptySupported(): no supported list available, emptying all not set parameters", get_class($this))); |
57
|
|
|
$supportedFields = array_keys($this->mapping); |
58
|
|
|
} |
59
|
|
|
else { |
60
|
|
|
return false; |
61
|
|
|
} |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
foreach ($supportedFields as $field) { |
65
|
|
|
if (!isset($this->mapping[$field])) { |
66
|
|
|
SLog::Write(LOGLEVEL_WARN, sprintf("Field '%s' is supposed to be emptied but is not defined for '%s'", $field, get_class($this))); |
67
|
|
|
|
68
|
|
|
continue; |
69
|
|
|
} |
70
|
|
|
$var = $this->mapping[$field][self::STREAMER_VAR]; |
71
|
|
|
// add var to $this->unsetVars if $var is not set |
72
|
|
|
if (!isset($this->{$var})) { |
73
|
|
|
$this->unsetVars[] = $var; |
74
|
|
|
} |
75
|
|
|
} |
76
|
|
|
SLog::Write(LOGLEVEL_DEBUG, sprintf("Supported variables to be unset: %s", implode(',', $this->unsetVars))); |
77
|
|
|
|
78
|
|
|
return true; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Compares this a SyncObject to another. |
83
|
|
|
* In case that all available mapped fields are exactly EQUAL, it returns true. |
84
|
|
|
* |
85
|
|
|
* @see SyncObject |
86
|
|
|
* |
87
|
|
|
* @param SyncObject $odo other SyncObject |
88
|
|
|
* @param bool $log flag to turn on logging |
89
|
|
|
* @param bool $strictTypeCompare to enforce type matching |
90
|
|
|
* |
91
|
|
|
* @return bool |
92
|
|
|
*/ |
93
|
|
|
public function equals($odo, $log = false, $strictTypeCompare = false) { |
|
|
|
|
94
|
|
|
if ($odo === false) { |
|
|
|
|
95
|
|
|
return false; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
// check objecttype |
99
|
|
|
if (!$odo instanceof SyncObject) { |
|
|
|
|
100
|
|
|
SLog::Write(LOGLEVEL_DEBUG, "SyncObject->equals() the target object is not a SyncObject"); |
101
|
|
|
|
102
|
|
|
return false; |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
// check for mapped fields |
106
|
|
|
foreach ($this->mapping as $v) { |
107
|
|
|
$val = $v[self::STREAMER_VAR]; |
108
|
|
|
// array of values? |
109
|
|
|
if (isset($v[self::STREAMER_ARRAY])) { |
110
|
|
|
// if neither array is created then don't fail the comparison |
111
|
|
|
if (!isset($this->{$val}) && !isset($odo->{$val})) { |
112
|
|
|
SLog::Write(LOGLEVEL_DEBUG, sprintf("SyncObject->equals() array '%s' is NOT SET in either object", $val)); |
113
|
|
|
|
114
|
|
|
continue; |
115
|
|
|
} |
116
|
|
|
if (is_array($this->{$val}) && is_array($odo->{$val})) { |
117
|
|
|
// if both arrays exist then seek for differences in the arrays |
118
|
|
|
if (count(array_diff($this->{$val}, $odo->{$val})) + count(array_diff($odo->{$val}, $this->{$val})) > 0) { |
119
|
|
|
SLog::Write(LOGLEVEL_DEBUG, sprintf("SyncObject->equals() items in array '%s' differ", $val)); |
120
|
|
|
|
121
|
|
|
return false; |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
else { |
125
|
|
|
SLog::Write(LOGLEVEL_DEBUG, sprintf("SyncObject->equals() array '%s' is set in one but not the other object", $val)); |
126
|
|
|
|
127
|
|
|
return false; |
128
|
|
|
} |
129
|
|
|
} |
130
|
|
|
else { |
131
|
|
|
if (isset($this->{$val}, $odo->{$val})) { |
132
|
|
|
if ($strictTypeCompare) { |
133
|
|
|
if ($this->{$val} !== $odo->{$val}) { |
134
|
|
|
SLog::Write(LOGLEVEL_DEBUG, sprintf("SyncObject->equals() false on field '%s': '%s' != '%s' using strictTypeCompare", $val, Utils::PrintAsString($this->{$val}), Utils::PrintAsString($odo->{$val}))); |
135
|
|
|
|
136
|
|
|
return false; |
137
|
|
|
} |
138
|
|
|
} |
139
|
|
|
else { |
140
|
|
|
if ($this->{$val} != $odo->{$val}) { |
141
|
|
|
SLog::Write(LOGLEVEL_DEBUG, sprintf("SyncObject->equals() false on field '%s': '%s' != '%s'", $val, Utils::PrintAsString($this->{$val}), Utils::PrintAsString($odo->{$val}))); |
142
|
|
|
|
143
|
|
|
return false; |
144
|
|
|
} |
145
|
|
|
} |
146
|
|
|
} |
147
|
|
|
elseif (!isset($this->{$val}) && !isset($odo->{$val})) { |
148
|
|
|
continue; |
149
|
|
|
} |
150
|
|
|
else { |
151
|
|
|
SLog::Write(LOGLEVEL_DEBUG, sprintf("SyncObject->equals() false because field '%s' is only defined at one obj: '%s' != '%s'", $val, Utils::PrintAsString(isset($this->{$val})), Utils::PrintAsString(isset($odo->{$val})))); |
152
|
|
|
|
153
|
|
|
return false; |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
return true; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* String representation of the object. |
163
|
|
|
* |
164
|
|
|
* @return string |
165
|
|
|
*/ |
166
|
|
|
public function __toString() { |
167
|
|
|
$str = get_class($this) . " (\n"; |
168
|
|
|
|
169
|
|
|
$streamerVars = []; |
170
|
|
|
foreach ($this->mapping as $k => $v) { |
171
|
|
|
$streamerVars[$v[self::STREAMER_VAR]] = (isset($v[self::STREAMER_TYPE])) ? $v[self::STREAMER_TYPE] : false; |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
foreach (get_object_vars($this) as $k => $v) { |
175
|
|
|
if ($k == "mapping") { |
176
|
|
|
continue; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
if (array_key_exists($k, $streamerVars)) { |
180
|
|
|
$strV = "(S) "; |
181
|
|
|
} |
182
|
|
|
else { |
183
|
|
|
$strV = ""; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
// self::STREAMER_ARRAY ? |
187
|
|
|
if (is_array($v)) { |
188
|
|
|
$str .= "\t" . $strV . $k . "(Array) size: " . count($v) . "\n"; |
189
|
|
|
foreach ($v as $value) { |
190
|
|
|
$str .= "\t\t" . Utils::PrintAsString($value) . "\n"; |
191
|
|
|
} |
192
|
|
|
} |
193
|
|
|
elseif ($v instanceof SyncObject) { |
194
|
|
|
$str .= "\t" . $strV . $k . " => " . str_replace("\n", "\n\t\t\t", $v->__toString()) . "\n"; |
195
|
|
|
} |
196
|
|
|
else { |
197
|
|
|
$str .= "\t" . $strV . $k . " => " . (isset($this->{$k}) ? Utils::PrintAsString($this->{$k}) : "null") . "\n"; |
198
|
|
|
} |
199
|
|
|
} |
200
|
|
|
$str .= ")"; |
201
|
|
|
|
202
|
|
|
return $str; |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* Returns the properties which have to be unset on the server. |
207
|
|
|
* |
208
|
|
|
* @return array |
209
|
|
|
*/ |
210
|
|
|
public function getUnsetVars() { |
211
|
|
|
return $this->unsetVars; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* Removes not necessary data from the object. |
216
|
|
|
* |
217
|
|
|
* @param mixed $flags |
218
|
|
|
* |
219
|
|
|
* @return bool |
220
|
|
|
*/ |
221
|
|
|
public function StripData($flags = 0) { |
222
|
|
|
if ($flags === 0 && isset($this->unsetVars)) { |
223
|
|
|
unset($this->unsetVars); |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
return parent::StripData($flags); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* Indicates if a SyncObject supports the private flag and stripping of private data. |
231
|
|
|
* If an object does not support it, it will not be sent to the client but permanently be excluded from the sync. |
232
|
|
|
* |
233
|
|
|
* @return bool - default false defined in constructor - overwritten by implementation |
234
|
|
|
*/ |
235
|
|
|
public function SupportsPrivateStripping() { |
236
|
|
|
return $this->supportsPrivateStripping; |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* Indicates the amount of parameters that were set before Checks were executed and potentially set other parameters. |
241
|
|
|
* |
242
|
|
|
* @return bool/int - returns false if Check() was not executed |
|
|
|
|
243
|
|
|
*/ |
244
|
|
|
public function getCheckedParameters() { |
245
|
|
|
return $this->checkedParameters; |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
/** |
249
|
|
|
* Method checks if the object has the minimum of required parameters |
250
|
|
|
* and fulfills semantic dependencies. |
251
|
|
|
* |
252
|
|
|
* General checks: |
253
|
|
|
* STREAMER_CHECK_REQUIRED may have as value false (do not fix, ignore object!) or set-to-values: STREAMER_CHECK_SETZERO/ONE/TWO, STREAMER_CHECK_SETEMPTY |
254
|
|
|
* STREAMER_CHECK_ZEROORONE may be 0 or 1, if none of these, set-to-values: STREAMER_CHECK_SETZERO or STREAMER_CHECK_SETONE |
255
|
|
|
* STREAMER_CHECK_NOTALLOWED fails if is set |
256
|
|
|
* STREAMER_CHECK_ONEVALUEOF expects an array with accepted values, fails if value is not in array |
257
|
|
|
* |
258
|
|
|
* Comparison: |
259
|
|
|
* STREAMER_CHECK_CMPLOWER compares if the current parameter is lower as a literal or another parameter of the same object |
260
|
|
|
* STREAMER_CHECK_CMPHIGHER compares if the current parameter is higher as a literal or another parameter of the same object |
261
|
|
|
* |
262
|
|
|
* @param bool $logAsDebug (opt) default is false, so messages are logged in WARN log level |
263
|
|
|
* |
264
|
|
|
* @return bool |
265
|
|
|
*/ |
266
|
|
|
public function Check($logAsDebug = false) { |
267
|
|
|
// semantic checks general "turn off switch" |
268
|
|
|
if (defined("DO_SEMANTIC_CHECKS") && DO_SEMANTIC_CHECKS === false) { |
|
|
|
|
269
|
|
|
SLog::Write(LOGLEVEL_DEBUG, "SyncObject->Check(): semantic checks disabled. Check your config for 'DO_SEMANTIC_CHECKS'."); |
270
|
|
|
|
271
|
|
|
return true; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
$defaultLogLevel = LOGLEVEL_WARN; |
275
|
|
|
$this->checkedParameters = 0; |
276
|
|
|
|
277
|
|
|
// in some cases non-false checks should not provoke a WARN log but only a DEBUG log |
278
|
|
|
if ($logAsDebug) { |
279
|
|
|
$defaultLogLevel = LOGLEVEL_DEBUG; |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
$objClass = get_class($this); |
283
|
|
|
foreach ($this->mapping as $k => $v) { |
284
|
|
|
// check sub-objects recursively |
285
|
|
|
if (isset($v[self::STREAMER_TYPE], $this->{$v[self::STREAMER_VAR]})) { |
286
|
|
|
if ($this->{$v[self::STREAMER_VAR]} instanceof SyncObject) { |
287
|
|
|
if (!$this->{$v[self::STREAMER_VAR]}->Check($logAsDebug)) { |
288
|
|
|
return false; |
289
|
|
|
} |
290
|
|
|
} |
291
|
|
|
elseif (is_array($this->{$v[self::STREAMER_VAR]})) { |
292
|
|
|
foreach ($this->{$v[self::STREAMER_VAR]} as $subobj) { |
293
|
|
|
if ($subobj instanceof SyncObject && !$subobj->Check($logAsDebug)) { |
294
|
|
|
return false; |
295
|
|
|
} |
296
|
|
|
} |
297
|
|
|
} |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
if (isset($v[self::STREAMER_CHECKS])) { |
301
|
|
|
foreach ($v[self::STREAMER_CHECKS] as $rule => $condition) { |
302
|
|
|
// count parameter if it's set |
303
|
|
|
if (isset($this->{$v[self::STREAMER_VAR]})) { |
304
|
|
|
++$this->checkedParameters; |
305
|
|
|
} |
306
|
|
|
|
307
|
|
|
// check REQUIRED settings |
308
|
|
|
if ($rule === self::STREAMER_CHECK_REQUIRED && (!isset($this->{$v[self::STREAMER_VAR]}) || $this->{$v[self::STREAMER_VAR]} === '')) { |
309
|
|
|
// parameter is not set but .. |
310
|
|
|
// requested to set to 0 |
311
|
|
|
if ($condition === self::STREAMER_CHECK_SETZERO) { |
312
|
|
|
$this->{$v[self::STREAMER_VAR]} = 0; |
313
|
|
|
SLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Fixed object from type %s: parameter '%s' is set to 0", $objClass, $v[self::STREAMER_VAR])); |
314
|
|
|
} |
315
|
|
|
// requested to be set to 1 |
316
|
|
|
elseif ($condition === self::STREAMER_CHECK_SETONE) { |
317
|
|
|
$this->{$v[self::STREAMER_VAR]} = 1; |
318
|
|
|
SLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Fixed object from type %s: parameter '%s' is set to 1", $objClass, $v[self::STREAMER_VAR])); |
319
|
|
|
} |
320
|
|
|
// requested to be set to 2 |
321
|
|
|
elseif ($condition === self::STREAMER_CHECK_SETTWO) { |
322
|
|
|
$this->{$v[self::STREAMER_VAR]} = 2; |
323
|
|
|
SLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Fixed object from type %s: parameter '%s' is set to 2", $objClass, $v[self::STREAMER_VAR])); |
324
|
|
|
} |
325
|
|
|
// requested to be set to '' |
326
|
|
|
elseif ($condition === self::STREAMER_CHECK_SETEMPTY) { |
327
|
|
|
if (!isset($this->{$v[self::STREAMER_VAR]})) { |
328
|
|
|
$this->{$v[self::STREAMER_VAR]} = ''; |
329
|
|
|
SLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Fixed object from type %s: parameter '%s' is set to ''", $objClass, $v[self::STREAMER_VAR])); |
330
|
|
|
} |
331
|
|
|
} |
332
|
|
|
// there is another value !== false |
333
|
|
|
elseif ($condition !== false) { |
334
|
|
|
$this->{$v[self::STREAMER_VAR]} = $condition; |
335
|
|
|
SLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Fixed object from type %s: parameter '%s' is set to '%s'", $objClass, $v[self::STREAMER_VAR], $condition)); |
336
|
|
|
} |
337
|
|
|
// no fix available! |
338
|
|
|
else { |
339
|
|
|
SLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Unmet condition in object from type %s: parameter '%s' is required but not set. Check failed!", $objClass, $v[self::STREAMER_VAR])); |
340
|
|
|
|
341
|
|
|
return false; |
342
|
|
|
} |
343
|
|
|
} // end STREAMER_CHECK_REQUIRED |
344
|
|
|
|
345
|
|
|
// check STREAMER_CHECK_ZEROORONE |
346
|
|
|
if ($rule === self::STREAMER_CHECK_ZEROORONE && isset($this->{$v[self::STREAMER_VAR]})) { |
347
|
|
|
if ($this->{$v[self::STREAMER_VAR]} != 0 && $this->{$v[self::STREAMER_VAR]} != 1) { |
348
|
|
|
$newval = $condition === self::STREAMER_CHECK_SETZERO ? 0 : 1; |
349
|
|
|
$this->{$v[self::STREAMER_VAR]} = $newval; |
350
|
|
|
SLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Fixed object from type %s: parameter '%s' is set to '%s' as it was not 0 or 1", $objClass, $v[self::STREAMER_VAR], $newval)); |
351
|
|
|
} |
352
|
|
|
}// end STREAMER_CHECK_ZEROORONE |
353
|
|
|
|
354
|
|
|
// check STREAMER_CHECK_ONEVALUEOF |
355
|
|
|
if ($rule === self::STREAMER_CHECK_ONEVALUEOF && isset($this->{$v[self::STREAMER_VAR]})) { |
356
|
|
|
if (!in_array($this->{$v[self::STREAMER_VAR]}, $condition)) { |
357
|
|
|
SLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): object from type %s: parameter '%s'->'%s' is not in the range of allowed values.", $objClass, $v[self::STREAMER_VAR], $this->{$v[self::STREAMER_VAR]})); |
358
|
|
|
|
359
|
|
|
return false; |
360
|
|
|
} |
361
|
|
|
}// end STREAMER_CHECK_ONEVALUEOF |
362
|
|
|
|
363
|
|
|
// Check value compared to other value or literal |
364
|
|
|
if ($rule === self::STREAMER_CHECK_CMPHIGHER || $rule === self::STREAMER_CHECK_CMPLOWER) { |
365
|
|
|
if (isset($this->{$v[self::STREAMER_VAR]})) { |
366
|
|
|
$cmp = false; |
367
|
|
|
// directly compare against literals |
368
|
|
|
if (is_int($condition)) { |
369
|
|
|
$cmp = $condition; |
370
|
|
|
} |
371
|
|
|
// check for invalid compare-to |
372
|
|
|
elseif (!isset($this->mapping[$condition])) { |
373
|
|
|
SLog::Write(LOGLEVEL_ERROR, sprintf("SyncObject->Check(): Can not compare parameter '%s' against the other value '%s' as it is not defined object from type %s. Please report this! Check skipped!", $objClass, $v[self::STREAMER_VAR], $condition)); |
374
|
|
|
|
375
|
|
|
continue; |
376
|
|
|
} |
377
|
|
|
else { |
378
|
|
|
$cmpPar = $this->mapping[$condition][self::STREAMER_VAR]; |
379
|
|
|
if (isset($this->{$cmpPar})) { |
380
|
|
|
$cmp = $this->{$cmpPar}; |
381
|
|
|
} |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
if ($cmp === false) { |
385
|
|
|
SLog::Write(LOGLEVEL_WARN, sprintf("SyncObject->Check(): Unmet condition in object from type %s: parameter '%s' can not be compared, as the comparable is not set. Check failed!", $objClass, $v[self::STREAMER_VAR])); |
386
|
|
|
|
387
|
|
|
return false; |
388
|
|
|
} |
389
|
|
|
if ( |
390
|
|
|
($rule == self::STREAMER_CHECK_CMPHIGHER && intval($this->{$v[self::STREAMER_VAR]}) < $cmp) || |
391
|
|
|
($rule == self::STREAMER_CHECK_CMPLOWER && intval($this->{$v[self::STREAMER_VAR]}) > $cmp) |
392
|
|
|
) { |
393
|
|
|
SLog::Write(LOGLEVEL_WARN, sprintf( |
394
|
|
|
"SyncObject->Check(): Unmet condition in object from type %s: parameter '%s' is %s than '%s'. Check failed!", |
395
|
|
|
$objClass, |
396
|
|
|
$v[self::STREAMER_VAR], |
397
|
|
|
($rule === self::STREAMER_CHECK_CMPHIGHER) ? 'LOWER' : 'HIGHER', |
398
|
|
|
isset($cmpPar) ? $cmpPar : $condition |
399
|
|
|
)); |
400
|
|
|
|
401
|
|
|
return false; |
402
|
|
|
} |
403
|
|
|
} |
404
|
|
|
} // STREAMER_CHECK_CMP* |
405
|
|
|
|
406
|
|
|
// check STREAMER_CHECK_LENGTHMAX |
407
|
|
|
if ($rule === self::STREAMER_CHECK_LENGTHMAX && isset($this->{$v[self::STREAMER_VAR]})) { |
408
|
|
|
if (is_array($this->{$v[self::STREAMER_VAR]})) { |
409
|
|
|
// implosion takes 2bytes, so we just assume ", " here |
410
|
|
|
$chkstr = implode(", ", $this->{$v[self::STREAMER_VAR]}); |
411
|
|
|
} |
412
|
|
|
else { |
413
|
|
|
$chkstr = $this->{$v[self::STREAMER_VAR]}; |
414
|
|
|
} |
415
|
|
|
|
416
|
|
|
if (strlen($chkstr) > $condition) { |
417
|
|
|
SLog::Write(LOGLEVEL_WARN, sprintf("SyncObject->Check(): object from type %s: parameter '%s' is longer than %d. Check failed", $objClass, $v[self::STREAMER_VAR], $condition)); |
418
|
|
|
|
419
|
|
|
return false; |
420
|
|
|
} |
421
|
|
|
}// end STREAMER_CHECK_LENGTHMAX |
422
|
|
|
|
423
|
|
|
// check STREAMER_CHECK_EMAIL |
424
|
|
|
// if $condition is false then the check really fails. Otherwise invalid emails are removed. |
425
|
|
|
// if nothing is left (all emails were false), the parameter is set to condition |
426
|
|
|
if ($rule === self::STREAMER_CHECK_EMAIL && isset($this->{$v[self::STREAMER_VAR]})) { |
427
|
|
|
if ($condition === false && ((is_array($this->{$v[self::STREAMER_VAR]}) && empty($this->{$v[self::STREAMER_VAR]})) || strlen($this->{$v[self::STREAMER_VAR]}) == 0)) { |
428
|
|
|
continue; |
429
|
|
|
} |
430
|
|
|
|
431
|
|
|
$as_array = false; |
432
|
|
|
|
433
|
|
|
if (is_array($this->{$v[self::STREAMER_VAR]})) { |
434
|
|
|
$mails = $this->{$v[self::STREAMER_VAR]}; |
435
|
|
|
$as_array = true; |
436
|
|
|
} |
437
|
|
|
else { |
438
|
|
|
$mails = [$this->{$v[self::STREAMER_VAR]}]; |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
$output = []; |
442
|
|
|
foreach ($mails as $mail) { |
443
|
|
|
if (!Utils::CheckEmail($mail)) { |
444
|
|
|
SLog::Write(LOGLEVEL_WARN, sprintf("SyncObject->Check(): object from type %s: parameter '%s' contains an invalid email address '%s'. Address is removed.", $objClass, $v[self::STREAMER_VAR], $mail)); |
445
|
|
|
} |
446
|
|
|
else { |
447
|
|
|
$output[] = $mail; |
448
|
|
|
} |
449
|
|
|
} |
450
|
|
|
if (count($mails) != count($output)) { |
451
|
|
|
if ($condition === false) { |
452
|
|
|
return false; |
453
|
|
|
} |
454
|
|
|
|
455
|
|
|
// nothing left, use $condition as new value |
456
|
|
|
if (count($output) == 0) { |
457
|
|
|
$output[] = $condition; |
458
|
|
|
} |
459
|
|
|
|
460
|
|
|
// if we are allowed to rewrite the attribute, we do that |
461
|
|
|
if ($as_array) { |
462
|
|
|
$this->{$v[self::STREAMER_VAR]} = $output; |
463
|
|
|
} |
464
|
|
|
else { |
465
|
|
|
$this->{$v[self::STREAMER_VAR]} = $output[0]; |
466
|
|
|
} |
467
|
|
|
} |
468
|
|
|
}// end STREAMER_CHECK_EMAIL |
469
|
|
|
} // foreach CHECKS |
470
|
|
|
} // isset CHECKS |
471
|
|
|
} // foreach mapping |
472
|
|
|
|
473
|
|
|
return true; |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
/** |
477
|
|
|
* Returns human friendly property name from its value if a mapping is available. |
478
|
|
|
* |
479
|
|
|
* @param array $v |
480
|
|
|
* @param mixed $val |
481
|
|
|
* |
482
|
|
|
* @return mixed |
483
|
|
|
*/ |
484
|
|
|
public function GetNameFromPropertyValue($v, $val) { |
485
|
|
|
if (isset($v[self::STREAMER_VALUEMAP][$val])) { |
486
|
|
|
return $v[self::STREAMER_VALUEMAP][$val]; |
487
|
|
|
} |
488
|
|
|
|
489
|
|
|
return $val; |
490
|
|
|
} |
491
|
|
|
|
492
|
|
|
/** |
493
|
|
|
* Called after the SyncObject was unserialized. |
494
|
|
|
* |
495
|
|
|
* @return bool |
496
|
|
|
*/ |
497
|
|
|
public function postUnserialize() { |
498
|
|
|
return true; |
499
|
|
|
} |
500
|
|
|
} |
501
|
|
|
|