Passed
Push — master ( 34e8da...f497d2 )
by
unknown
06:10 queued 02:50
created
lib/utils/stringstreamwrapper.php 3 patches
Indentation   +152 added lines, -152 removed lines patch added patch discarded remove patch
@@ -9,158 +9,158 @@
 block discarded – undo
9 9
  */
10 10
 
11 11
 class StringStreamWrapper {
12
-	public const PROTOCOL = "stringstream";
13
-
14
-	private $stringstream;
15
-	private $position;
16
-	private $stringlength;
17
-	private $truncateHtmlSafe;
18
-	private $context;
19
-
20
-	/**
21
-	 * Opens the stream
22
-	 * The string to be streamed is passed over the context.
23
-	 *
24
-	 * @param string $path        Specifies the URL that was passed to the original function
25
-	 * @param string $mode        The mode used to open the file, as detailed for fopen()
26
-	 * @param int    $options     Holds additional flags set by the streams API
27
-	 * @param string $opened_path if the path is opened successfully, and STREAM_USE_PATH is set in options,
28
-	 *                            opened_path should be set to the full path of the file/resource that was actually opened
29
-	 *
30
-	 * @return bool
31
-	 */
32
-	public function stream_open($path, $mode, $options, &$opened_path) {
33
-		$contextOptions = stream_context_get_options($this->context);
34
-		if (!isset($contextOptions[self::PROTOCOL]['string'])) {
35
-			return false;
36
-		}
37
-
38
-		$this->position = 0;
39
-
40
-		// this is our stream!
41
-		$this->stringstream = $contextOptions[self::PROTOCOL]['string'];
42
-		$this->truncateHtmlSafe = (isset($contextOptions[self::PROTOCOL]['truncatehtmlsafe'])) ? $contextOptions[self::PROTOCOL]['truncatehtmlsafe'] : false;
43
-
44
-		$this->stringlength = strlen($this->stringstream);
45
-		SLog::Write(LOGLEVEL_DEBUG, sprintf("StringStreamWrapper::stream_open(): initialized stream length: %d - HTML-safe-truncate: %s", $this->stringlength, Utils::PrintAsString($this->truncateHtmlSafe)));
46
-
47
-		return true;
48
-	}
49
-
50
-	/**
51
-	 * Reads from stream.
52
-	 *
53
-	 * @param int $len amount of bytes to be read
54
-	 *
55
-	 * @return string
56
-	 */
57
-	public function stream_read($len) {
58
-		$data = substr($this->stringstream, $this->position, $len);
59
-		$this->position += strlen($data);
60
-
61
-		return $data;
62
-	}
63
-
64
-	/**
65
-	 * Writes data to the stream.
66
-	 *
67
-	 * @param string $data
68
-	 *
69
-	 * @return int
70
-	 */
71
-	public function stream_write($data) {
72
-		$l = strlen($data);
73
-		$this->stringstream = substr($this->stringstream, 0, $this->position) . $data . substr($this->stringstream, $this->position += $l);
74
-		$this->stringlength = strlen($this->stringstream);
75
-
76
-		return $l;
77
-	}
78
-
79
-	/**
80
-	 * Stream "seek" functionality.
81
-	 *
82
-	 * @param int $offset
83
-	 * @param int $whence
84
-	 *
85
-	 * @return bool
86
-	 */
87
-	public function stream_seek($offset, $whence = SEEK_SET) {
88
-		if ($whence == SEEK_CUR) {
89
-			$this->position += $offset;
90
-		}
91
-		elseif ($whence == SEEK_END) {
92
-			$this->position = $this->stringlength + $offset;
93
-		}
94
-		else {
95
-			$this->position = $offset;
96
-		}
97
-
98
-		return true;
99
-	}
100
-
101
-	/**
102
-	 * Returns the current position on stream.
103
-	 *
104
-	 * @return int
105
-	 */
106
-	public function stream_tell() {
107
-		return $this->position;
108
-	}
109
-
110
-	/**
111
-	 * Indicates if 'end of file' is reached.
112
-	 *
113
-	 * @return bool
114
-	 */
115
-	public function stream_eof() {
116
-		return $this->position >= $this->stringlength;
117
-	}
118
-
119
-	/**
120
-	 * Truncates the stream to the new size.
121
-	 *
122
-	 * @param int $new_size
123
-	 *
124
-	 * @return bool
125
-	 */
126
-	public function stream_truncate($new_size) {
127
-		// cut the string!
128
-		$this->stringstream = Utils::Utf8_truncate($this->stringstream, $new_size, $this->truncateHtmlSafe);
129
-		$this->stringlength = strlen($this->stringstream);
130
-
131
-		if ($this->position > $this->stringlength) {
132
-			SLog::Write(LOGLEVEL_WARN, sprintf("StringStreamWrapper->stream_truncate(): stream position (%d) ahead of new size of %d. Repositioning pointer to end of stream.", $this->position, $this->stringlength));
133
-			$this->position = $this->stringlength;
134
-		}
135
-
136
-		return true;
137
-	}
138
-
139
-	/**
140
-	 * Retrieves information about a stream.
141
-	 *
142
-	 * @return array
143
-	 */
144
-	public function stream_stat() {
145
-		return [
146
-			7 => $this->stringlength,
147
-			'size' => $this->stringlength,
148
-		];
149
-	}
150
-
151
-	/**
152
-	 * Instantiates a StringStreamWrapper.
153
-	 *
154
-	 * @param string $string           The string to be wrapped
155
-	 * @param bool   $truncatehtmlsafe Indicates if a truncation should be done html-safe - default: false
156
-	 *
157
-	 * @return StringStreamWrapper
158
-	 */
159
-	public static function Open($string, $truncatehtmlsafe = false) {
160
-		$context = stream_context_create([self::PROTOCOL => ['string' => &$string, 'truncatehtmlsafe' => $truncatehtmlsafe]]);
161
-
162
-		return fopen(self::PROTOCOL . "://", 'r', false, $context);
163
-	}
12
+    public const PROTOCOL = "stringstream";
13
+
14
+    private $stringstream;
15
+    private $position;
16
+    private $stringlength;
17
+    private $truncateHtmlSafe;
18
+    private $context;
19
+
20
+    /**
21
+     * Opens the stream
22
+     * The string to be streamed is passed over the context.
23
+     *
24
+     * @param string $path        Specifies the URL that was passed to the original function
25
+     * @param string $mode        The mode used to open the file, as detailed for fopen()
26
+     * @param int    $options     Holds additional flags set by the streams API
27
+     * @param string $opened_path if the path is opened successfully, and STREAM_USE_PATH is set in options,
28
+     *                            opened_path should be set to the full path of the file/resource that was actually opened
29
+     *
30
+     * @return bool
31
+     */
32
+    public function stream_open($path, $mode, $options, &$opened_path) {
33
+        $contextOptions = stream_context_get_options($this->context);
34
+        if (!isset($contextOptions[self::PROTOCOL]['string'])) {
35
+            return false;
36
+        }
37
+
38
+        $this->position = 0;
39
+
40
+        // this is our stream!
41
+        $this->stringstream = $contextOptions[self::PROTOCOL]['string'];
42
+        $this->truncateHtmlSafe = (isset($contextOptions[self::PROTOCOL]['truncatehtmlsafe'])) ? $contextOptions[self::PROTOCOL]['truncatehtmlsafe'] : false;
43
+
44
+        $this->stringlength = strlen($this->stringstream);
45
+        SLog::Write(LOGLEVEL_DEBUG, sprintf("StringStreamWrapper::stream_open(): initialized stream length: %d - HTML-safe-truncate: %s", $this->stringlength, Utils::PrintAsString($this->truncateHtmlSafe)));
46
+
47
+        return true;
48
+    }
49
+
50
+    /**
51
+     * Reads from stream.
52
+     *
53
+     * @param int $len amount of bytes to be read
54
+     *
55
+     * @return string
56
+     */
57
+    public function stream_read($len) {
58
+        $data = substr($this->stringstream, $this->position, $len);
59
+        $this->position += strlen($data);
60
+
61
+        return $data;
62
+    }
63
+
64
+    /**
65
+     * Writes data to the stream.
66
+     *
67
+     * @param string $data
68
+     *
69
+     * @return int
70
+     */
71
+    public function stream_write($data) {
72
+        $l = strlen($data);
73
+        $this->stringstream = substr($this->stringstream, 0, $this->position) . $data . substr($this->stringstream, $this->position += $l);
74
+        $this->stringlength = strlen($this->stringstream);
75
+
76
+        return $l;
77
+    }
78
+
79
+    /**
80
+     * Stream "seek" functionality.
81
+     *
82
+     * @param int $offset
83
+     * @param int $whence
84
+     *
85
+     * @return bool
86
+     */
87
+    public function stream_seek($offset, $whence = SEEK_SET) {
88
+        if ($whence == SEEK_CUR) {
89
+            $this->position += $offset;
90
+        }
91
+        elseif ($whence == SEEK_END) {
92
+            $this->position = $this->stringlength + $offset;
93
+        }
94
+        else {
95
+            $this->position = $offset;
96
+        }
97
+
98
+        return true;
99
+    }
100
+
101
+    /**
102
+     * Returns the current position on stream.
103
+     *
104
+     * @return int
105
+     */
106
+    public function stream_tell() {
107
+        return $this->position;
108
+    }
109
+
110
+    /**
111
+     * Indicates if 'end of file' is reached.
112
+     *
113
+     * @return bool
114
+     */
115
+    public function stream_eof() {
116
+        return $this->position >= $this->stringlength;
117
+    }
118
+
119
+    /**
120
+     * Truncates the stream to the new size.
121
+     *
122
+     * @param int $new_size
123
+     *
124
+     * @return bool
125
+     */
126
+    public function stream_truncate($new_size) {
127
+        // cut the string!
128
+        $this->stringstream = Utils::Utf8_truncate($this->stringstream, $new_size, $this->truncateHtmlSafe);
129
+        $this->stringlength = strlen($this->stringstream);
130
+
131
+        if ($this->position > $this->stringlength) {
132
+            SLog::Write(LOGLEVEL_WARN, sprintf("StringStreamWrapper->stream_truncate(): stream position (%d) ahead of new size of %d. Repositioning pointer to end of stream.", $this->position, $this->stringlength));
133
+            $this->position = $this->stringlength;
134
+        }
135
+
136
+        return true;
137
+    }
138
+
139
+    /**
140
+     * Retrieves information about a stream.
141
+     *
142
+     * @return array
143
+     */
144
+    public function stream_stat() {
145
+        return [
146
+            7 => $this->stringlength,
147
+            'size' => $this->stringlength,
148
+        ];
149
+    }
150
+
151
+    /**
152
+     * Instantiates a StringStreamWrapper.
153
+     *
154
+     * @param string $string           The string to be wrapped
155
+     * @param bool   $truncatehtmlsafe Indicates if a truncation should be done html-safe - default: false
156
+     *
157
+     * @return StringStreamWrapper
158
+     */
159
+    public static function Open($string, $truncatehtmlsafe = false) {
160
+        $context = stream_context_create([self::PROTOCOL => ['string' => &$string, 'truncatehtmlsafe' => $truncatehtmlsafe]]);
161
+
162
+        return fopen(self::PROTOCOL . "://", 'r', false, $context);
163
+    }
164 164
 }
165 165
 
166 166
 stream_wrapper_register(StringStreamWrapper::PROTOCOL, "StringStreamWrapper");
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -70,7 +70,7 @@  discard block
 block discarded – undo
70 70
 	 */
71 71
 	public function stream_write($data) {
72 72
 		$l = strlen($data);
73
-		$this->stringstream = substr($this->stringstream, 0, $this->position) . $data . substr($this->stringstream, $this->position += $l);
73
+		$this->stringstream = substr($this->stringstream, 0, $this->position).$data.substr($this->stringstream, $this->position += $l);
74 74
 		$this->stringlength = strlen($this->stringstream);
75 75
 
76 76
 		return $l;
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
 	public static function Open($string, $truncatehtmlsafe = false) {
160 160
 		$context = stream_context_create([self::PROTOCOL => ['string' => &$string, 'truncatehtmlsafe' => $truncatehtmlsafe]]);
161 161
 
162
-		return fopen(self::PROTOCOL . "://", 'r', false, $context);
162
+		return fopen(self::PROTOCOL."://", 'r', false, $context);
163 163
 	}
164 164
 }
165 165
 
Please login to merge, or discard this patch.
Braces   +2 added lines, -4 removed lines patch added patch discarded remove patch
@@ -87,11 +87,9 @@
 block discarded – undo
87 87
 	public function stream_seek($offset, $whence = SEEK_SET) {
88 88
 		if ($whence == SEEK_CUR) {
89 89
 			$this->position += $offset;
90
-		}
91
-		elseif ($whence == SEEK_END) {
90
+		} elseif ($whence == SEEK_END) {
92 91
 			$this->position = $this->stringlength + $offset;
93
-		}
94
-		else {
92
+		} else {
95 93
 			$this->position = $offset;
96 94
 		}
97 95
 
Please login to merge, or discard this patch.
lib/utils/g_RFC822.php 4 patches
Indentation   +952 added lines, -952 removed lines patch added patch discarded remove patch
@@ -75,956 +75,956 @@
 block discarded – undo
75 75
  * @license BSD
76 76
  */
77 77
 class Mail_RFC822 {
78
-	/**
79
-	 * The address being parsed by the RFC822 object.
80
-	 *
81
-	 * @var string
82
-	 */
83
-	public $address = '';
84
-
85
-	/**
86
-	 * The default domain to use for unqualified addresses.
87
-	 *
88
-	 * @var string
89
-	 */
90
-	public $default_domain = 'localhost';
91
-
92
-	/**
93
-	 * Should we return a nested array showing groups, or flatten everything?
94
-	 *
95
-	 * @var bool
96
-	 */
97
-	public $nestGroups = true;
98
-
99
-	/**
100
-	 * Whether or not to validate atoms for non-ascii characters.
101
-	 *
102
-	 * @var bool
103
-	 */
104
-	public $validate = true;
105
-
106
-	/**
107
-	 * The array of raw addresses built up as we parse.
108
-	 *
109
-	 * @var array
110
-	 */
111
-	public $addresses = [];
112
-
113
-	/**
114
-	 * The final array of parsed address information that we build up.
115
-	 *
116
-	 * @var array
117
-	 */
118
-	public $structure = [];
119
-
120
-	/**
121
-	 * The current error message, if any.
122
-	 *
123
-	 * @var string
124
-	 */
125
-	public $error;
126
-
127
-	/**
128
-	 * An internal counter/pointer.
129
-	 *
130
-	 * @var int
131
-	 */
132
-	public $index;
133
-
134
-	/**
135
-	 * The number of groups that have been found in the address list.
136
-	 *
137
-	 * @var int
138
-	 */
139
-	public $num_groups = 0;
140
-
141
-	/**
142
-	 * A variable so that we can tell whether or not we're inside a
143
-	 * Mail_RFC822 object.
144
-	 *
145
-	 * @var bool
146
-	 */
147
-	public $mailRFC822 = true;
148
-
149
-	/**
150
-	 * A limit after which processing stops.
151
-	 *
152
-	 * @var int
153
-	 */
154
-	public $limit;
155
-
156
-	/**
157
-	 * Sets up the object. The address must either be set here or when
158
-	 * calling parseAddressList(). One or the other.
159
-	 *
160
-	 * @param string     $address        the address(es) to validate
161
-	 * @param string     $default_domain Default domain/host etc. If not supplied, will be set to localhost.
162
-	 * @param bool       $nest_groups    whether to return the structure with groups nested for easier viewing
163
-	 * @param bool       $validate       Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
164
-	 * @param null|mixed $limit
165
-	 *
166
-	 * @return object mail_RFC822 A new Mail_RFC822 object
167
-	 */
168
-	public function __construct($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) {
169
-		if (isset($address)) {
170
-			$this->address = $address;
171
-		}
172
-		if (isset($default_domain)) {
173
-			$this->default_domain = $default_domain;
174
-		}
175
-		if (isset($nest_groups)) {
176
-			$this->nestGroups = $nest_groups;
177
-		}
178
-		if (isset($validate)) {
179
-			$this->validate = $validate;
180
-		}
181
-		if (isset($limit)) {
182
-			$this->limit = $limit;
183
-		}
184
-	}
185
-
186
-	/**
187
-	 * Starts the whole process. The address must either be set here
188
-	 * or when creating the object. One or the other.
189
-	 *
190
-	 * @param string     $address        the address(es) to validate
191
-	 * @param string     $default_domain default domain/host etc
192
-	 * @param bool       $nest_groups    whether to return the structure with groups nested for easier viewing
193
-	 * @param bool       $validate       Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
194
-	 * @param null|mixed $limit
195
-	 *
196
-	 * @return array a structured array of addresses
197
-	 */
198
-	public function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) {
199
-		if (!isset($this) || !isset($this->mailRFC822)) {
200
-			$obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit);
201
-
202
-			return $obj->parseAddressList();
203
-		}
204
-
205
-		if (isset($address)) {
206
-			$this->address = $address;
207
-		}
208
-		// grommunio-sync addition
209
-		if (strlen(trim($this->address)) == 0) {
210
-			return [];
211
-		}
212
-		if (isset($default_domain)) {
213
-			$this->default_domain = $default_domain;
214
-		}
215
-		if (isset($nest_groups)) {
216
-			$this->nestGroups = $nest_groups;
217
-		}
218
-		if (isset($validate)) {
219
-			$this->validate = $validate;
220
-		}
221
-		if (isset($limit)) {
222
-			$this->limit = $limit;
223
-		}
224
-
225
-		$this->structure = [];
226
-		$this->addresses = [];
227
-		$this->error = null;
228
-		$this->index = null;
229
-
230
-		// Unfold any long lines in $this->address.
231
-		$this->address = preg_replace('/\r?\n/', "\r\n", $this->address);
232
-		$this->address = preg_replace('/\r\n(\t| )+/', ' ', $this->address);
233
-
234
-		while ($this->address = $this->_splitAddresses($this->address));
235
-
236
-		if ($this->address === false || isset($this->error)) {
237
-			// require_once 'PEAR.php';
238
-			return $this->raiseError($this->error);
239
-		}
240
-
241
-		// Validate each address individually.  If we encounter an invalid
242
-		// address, stop iterating and return an error immediately.
243
-		foreach ($this->addresses as $address) {
244
-			$valid = $this->_validateAddress($address);
245
-
246
-			if ($valid === false || isset($this->error)) {
247
-				// require_once 'PEAR.php';
248
-				return $this->raiseError($this->error);
249
-			}
250
-
251
-			if (!$this->nestGroups) {
252
-				$this->structure = array_merge($this->structure, $valid);
253
-			}
254
-			else {
255
-				$this->structure[] = $valid;
256
-			}
257
-		}
258
-
259
-		return $this->structure;
260
-	}
261
-
262
-	/**
263
-	 * Splits an address into separate addresses.
264
-	 *
265
-	 * @param string $address the addresses to split
266
-	 *
267
-	 * @return bool success or failure
268
-	 */
269
-	protected function _splitAddresses($address) {
270
-		if (!empty($this->limit) && count($this->addresses) == $this->limit) {
271
-			return '';
272
-		}
273
-
274
-		if ($this->_isGroup($address) && !isset($this->error)) {
275
-			$split_char = ';';
276
-			$is_group = true;
277
-		}
278
-		elseif (!isset($this->error)) {
279
-			$split_char = ',';
280
-			$is_group = false;
281
-		}
282
-		elseif (isset($this->error)) {
283
-			return false;
284
-		}
285
-
286
-		// Split the string based on the above ten or so lines.
287
-		$parts = explode($split_char, $address);
288
-		$string = $this->_splitCheck($parts, $split_char);
289
-
290
-		// If a group...
291
-		if ($is_group) {
292
-			// If $string does not contain a colon outside of
293
-			// brackets/quotes etc then something's fubar.
294
-
295
-			// First check there's a colon at all:
296
-			if (strpos($string, ':') === false) {
297
-				$this->error = 'Invalid address: ' . $string;
298
-
299
-				return false;
300
-			}
301
-
302
-			// Now check it's outside of brackets/quotes:
303
-			if (!$this->_splitCheck(explode(':', $string), ':')) {
304
-				return false;
305
-			}
306
-
307
-			// We must have a group at this point, so increase the counter:
308
-			++$this->num_groups;
309
-		}
310
-
311
-		// $string now contains the first full address/group.
312
-		// Add to the addresses array.
313
-		$this->addresses[] = [
314
-			'address' => trim($string),
315
-			'group' => $is_group,
316
-		];
317
-
318
-		// Remove the now stored address from the initial line, the +1
319
-		// is to account for the explode character.
320
-		$address = trim(substr($address, strlen($string) + 1));
321
-
322
-		// If the next char is a comma and this was a group, then
323
-		// there are more addresses, otherwise, if there are any more
324
-		// chars, then there is another address.
325
-		if ($is_group && substr($address, 0, 1) == ',') {
326
-			return trim(substr($address, 1));
327
-		}
328
-		if (strlen($address) > 0) {
329
-			return $address;
330
-		}
331
-
332
-		return '';
333
-		// If you got here then something's off
334
-		return false;
335
-	}
336
-
337
-	/**
338
-	 * Checks for a group at the start of the string.
339
-	 *
340
-	 * @param string $address the address to check
341
-	 *
342
-	 * @return bool whether or not there is a group at the start of the string
343
-	 */
344
-	protected function _isGroup($address) {
345
-		// First comma not in quotes, angles or escaped:
346
-		$parts = explode(',', $address);
347
-		$string = $this->_splitCheck($parts, ',');
348
-
349
-		// Now we have the first address, we can reliably check for a
350
-		// group by searching for a colon that's not escaped or in
351
-		// quotes or angle brackets.
352
-		if (count($parts = explode(':', $string)) > 1) {
353
-			$string2 = $this->_splitCheck($parts, ':');
354
-
355
-			return $string2 !== $string;
356
-		}
357
-
358
-		return false;
359
-	}
360
-
361
-	/**
362
-	 * A common function that will check an exploded string.
363
-	 *
364
-	 * @param array  $parts the exloded string
365
-	 * @param string $char  the char that was exploded on
366
-	 *
367
-	 * @return mixed false if the string contains unclosed quotes/brackets, or the string on success
368
-	 */
369
-	protected function _splitCheck($parts, $char) {
370
-		$string = $parts[0];
371
-
372
-		for ($i = 0; $i < count($parts); ++$i) {
373
-			if ($this->_hasUnclosedQuotes($string) ||
374
-				$this->_hasUnclosedBrackets($string, '<>') ||
375
-				$this->_hasUnclosedBrackets($string, '[]') ||
376
-				$this->_hasUnclosedBrackets($string, '()') ||
377
-				substr($string, -1) == '\\') {
378
-				if (isset($parts[$i + 1])) {
379
-					$string = $string . $char . $parts[$i + 1];
380
-				}
381
-				else {
382
-					$this->error = 'Invalid address spec. Unclosed bracket or quotes';
383
-
384
-					return false;
385
-				}
386
-			}
387
-			else {
388
-				$this->index = $i;
389
-
390
-				break;
391
-			}
392
-		}
393
-
394
-		return $string;
395
-	}
396
-
397
-	/**
398
-	 * Checks if a string has unclosed quotes or not.
399
-	 *
400
-	 * @param string $string the string to check
401
-	 *
402
-	 * @return bool true if there are unclosed quotes inside the string,
403
-	 *              false otherwise
404
-	 */
405
-	protected function _hasUnclosedQuotes($string) {
406
-		$string = trim($string);
407
-		$iMax = strlen($string);
408
-		$in_quote = false;
409
-		$i = $slashes = 0;
410
-
411
-		for (; $i < $iMax; ++$i) {
412
-			switch ($string[$i]) {
413
-			case '\\':
414
-				++$slashes;
415
-
416
-				break;
417
-
418
-			case '"':
419
-				if ($slashes % 2 == 0) {
420
-					$in_quote = !$in_quote;
421
-				}
422
-				// Fall through to default action below.
423
-
424
-				// no break
425
-			default:
426
-				$slashes = 0;
427
-
428
-				break;
429
-			}
430
-		}
431
-
432
-		return $in_quote;
433
-	}
434
-
435
-	/**
436
-	 * Checks if a string has an unclosed brackets or not. IMPORTANT:
437
-	 * This function handles both angle brackets and square brackets;.
438
-	 *
439
-	 * @param string $string the string to check
440
-	 * @param string $chars  the characters to check for
441
-	 *
442
-	 * @return bool true if there are unclosed brackets inside the string, false otherwise
443
-	 */
444
-	protected function _hasUnclosedBrackets($string, $chars) {
445
-		$num_angle_start = substr_count($string, $chars[0]);
446
-		$num_angle_end = substr_count($string, $chars[1]);
447
-
448
-		$this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]);
449
-		$this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]);
450
-
451
-		if ($num_angle_start < $num_angle_end) {
452
-			$this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')';
453
-
454
-			return false;
455
-		}
456
-
457
-		return $num_angle_start > $num_angle_end;
458
-	}
459
-
460
-	/**
461
-	 * Sub function that is used only by hasUnclosedBrackets().
462
-	 *
463
-	 * @param string $string the string to check
464
-	 * @param int    &$num   The number of occurrences
465
-	 * @param string $char   the character to count
466
-	 *
467
-	 * @return int the number of occurrences of $char in $string, adjusted for backslashes
468
-	 */
469
-	protected function _hasUnclosedBracketsSub($string, &$num, $char) {
470
-		$parts = explode($char, $string);
471
-		for ($i = 0; $i < count($parts); ++$i) {
472
-			if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i])) {
473
-				--$num;
474
-			}
475
-			if (isset($parts[$i + 1])) {
476
-				$parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1];
477
-			}
478
-		}
479
-
480
-		return $num;
481
-	}
482
-
483
-	/**
484
-	 * Function to begin checking the address.
485
-	 *
486
-	 * @param string $address the address to validate
487
-	 *
488
-	 * @return mixed false on failure, or a structured array of address information on success
489
-	 */
490
-	protected function _validateAddress($address) {
491
-		$is_group = false;
492
-		$addresses = [];
493
-
494
-		if ($address['group']) {
495
-			$is_group = true;
496
-
497
-			// Get the group part of the name
498
-			$parts = explode(':', $address['address']);
499
-			$groupname = $this->_splitCheck($parts, ':');
500
-			$structure = [];
501
-
502
-			// And validate the group part of the name.
503
-			if (!$this->_validatePhrase($groupname)) {
504
-				$this->error = 'Group name did not validate.';
505
-
506
-				return false;
507
-			}
508
-			// Don't include groups if we are not nesting
509
-			// them. This avoids returning invalid addresses.
510
-			if ($this->nestGroups) {
511
-				$structure = new stdClass();
512
-				$structure->groupname = $groupname;
513
-			}
514
-
515
-			$address['address'] = ltrim(substr($address['address'], strlen($groupname . ':')));
516
-		}
517
-
518
-		// If a group then split on comma and put into an array.
519
-		// Otherwise, Just put the whole address in an array.
520
-		if ($is_group) {
521
-			while (strlen($address['address']) > 0) {
522
-				$parts = explode(',', $address['address']);
523
-				$addresses[] = $this->_splitCheck($parts, ',');
524
-				$address['address'] = trim(substr($address['address'], strlen(end($addresses) . ',')));
525
-			}
526
-		}
527
-		else {
528
-			$addresses[] = $address['address'];
529
-		}
530
-
531
-		// Trim the whitespace from all of the address strings.
532
-		array_map('trim', $addresses);
533
-
534
-		// Validate each mailbox.
535
-		// Format could be one of: name <[email protected]>
536
-		//                         [email protected]
537
-		//                         geezer
538
-		// ... or any other format valid by RFC 822.
539
-		for ($i = 0; $i < count($addresses); ++$i) {
540
-			if (!$this->validateMailbox($addresses[$i])) {
541
-				if (empty($this->error)) {
542
-					$this->error = 'Validation failed for: ' . $addresses[$i];
543
-				}
544
-
545
-				return false;
546
-			}
547
-		}
548
-
549
-		// Nested format
550
-		if ($this->nestGroups) {
551
-			if ($is_group) {
552
-				$structure->addresses = $addresses;
553
-			}
554
-			else {
555
-				$structure = $addresses[0];
556
-			}
557
-
558
-			// Flat format
559
-		}
560
-		else {
561
-			if ($is_group) {
562
-				$structure = array_merge($structure, $addresses);
563
-			}
564
-			else {
565
-				$structure = $addresses;
566
-			}
567
-		}
568
-
569
-		return $structure;
570
-	}
571
-
572
-	/**
573
-	 * Function to validate a phrase.
574
-	 *
575
-	 * @param string $phrase the phrase to check
576
-	 *
577
-	 * @return bool success or failure
578
-	 */
579
-	protected function _validatePhrase($phrase) {
580
-		// Splits on one or more Tab or space.
581
-		$parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY);
582
-
583
-		$phrase_parts = [];
584
-		while (count($parts) > 0) {
585
-			$phrase_parts[] = $this->_splitCheck($parts, ' ');
586
-			for ($i = 0; $i < $this->index + 1; ++$i) {
587
-				array_shift($parts);
588
-			}
589
-		}
590
-
591
-		foreach ($phrase_parts as $part) {
592
-			// If quoted string:
593
-			if (substr($part, 0, 1) == '"') {
594
-				if (!$this->_validateQuotedString($part)) {
595
-					return false;
596
-				}
597
-
598
-				continue;
599
-			}
600
-
601
-			// Otherwise it's an atom:
602
-			if (!$this->_validateAtom($part)) {
603
-				return false;
604
-			}
605
-		}
606
-
607
-		return true;
608
-	}
609
-
610
-	/**
611
-	 * Function to validate an atom which from rfc822 is:
612
-	 * atom = 1*<any CHAR except specials, SPACE and CTLs>.
613
-	 *
614
-	 * If validation ($this->validate) has been turned off, then
615
-	 * validateAtom() doesn't actually check anything. This is so that you
616
-	 * can split a list of addresses up before encoding personal names
617
-	 * (umlauts, etc.), for example.
618
-	 *
619
-	 * @param string $atom the string to check
620
-	 *
621
-	 * @return bool success or failure
622
-	 */
623
-	protected function _validateAtom($atom) {
624
-		if (!$this->validate) {
625
-			// Validation has been turned off; assume the atom is okay.
626
-			return true;
627
-		}
628
-
629
-		// Check for any char from ASCII 0 - ASCII 127
630
-		if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) {
631
-			return false;
632
-		}
633
-
634
-		// Check for specials:
635
-		if (preg_match('/[][()<>@,;\\:". ]/', $atom)) {
636
-			return false;
637
-		}
638
-
639
-		// Check for control characters (ASCII 0-31):
640
-		if (preg_match('/[\\x00-\\x1F]+/', $atom)) {
641
-			return false;
642
-		}
643
-
644
-		return true;
645
-	}
646
-
647
-	/**
648
-	 * Function to validate quoted string, which is:
649
-	 * quoted-string = <"> *(qtext/quoted-pair) <">.
650
-	 *
651
-	 * @param string $qstring The string to check
652
-	 *
653
-	 * @return bool success or failure
654
-	 */
655
-	protected function _validateQuotedString($qstring) {
656
-		// Leading and trailing "
657
-		$qstring = substr($qstring, 1, -1);
658
-
659
-		// Perform check, removing quoted characters first.
660
-		return !preg_match('/[\x0D\\\\"]/', preg_replace('/\\\\./', '', $qstring));
661
-	}
662
-
663
-	/**
664
-	 * Function to validate a mailbox, which is:
665
-	 * mailbox =   addr-spec         ; simple address
666
-	 *           / phrase route-addr ; name and route-addr.
667
-	 *
668
-	 * @param string &$mailbox The string to check
669
-	 *
670
-	 * @return bool success or failure
671
-	 */
672
-	public function validateMailbox(&$mailbox) {
673
-		// A couple of defaults.
674
-		$phrase = '';
675
-		$comment = '';
676
-		$comments = [];
677
-
678
-		// Catch any RFC822 comments and store them separately.
679
-		$_mailbox = $mailbox;
680
-		while (strlen(trim($_mailbox)) > 0) {
681
-			$parts = explode('(', $_mailbox);
682
-			$before_comment = $this->_splitCheck($parts, '(');
683
-			if ($before_comment != $_mailbox) {
684
-				// First char should be a (.
685
-				$comment = substr(str_replace($before_comment, '', $_mailbox), 1);
686
-				$parts = explode(')', $comment);
687
-				$comment = $this->_splitCheck($parts, ')');
688
-				$comments[] = $comment;
689
-
690
-				// +2 is for the brackets
691
-				$_mailbox = substr($_mailbox, strpos($_mailbox, '(' . $comment) + strlen($comment) + 2);
692
-			}
693
-			else {
694
-				break;
695
-			}
696
-		}
697
-
698
-		foreach ($comments as $comment) {
699
-			$mailbox = str_replace("({$comment})", '', $mailbox);
700
-		}
701
-
702
-		$mailbox = trim($mailbox);
703
-
704
-		// Check for name + route-addr
705
-		if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') {
706
-			$parts = explode('<', $mailbox);
707
-			$name = $this->_splitCheck($parts, '<');
708
-
709
-			$phrase = trim($name);
710
-			$route_addr = trim(substr($mailbox, strlen($name . '<'), -1));
711
-
712
-			// grommunio-sync fix for umlauts and other special chars
713
-			if (substr($phrase, 0, 1) != '"' && substr($phrase, -1) != '"') {
714
-				$phrase = '"' . $phrase . '"';
715
-			}
716
-
717
-			if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) {
718
-				return false;
719
-			}
720
-
721
-			// Only got addr-spec
722
-		}
723
-		else {
724
-			// First snip angle brackets if present.
725
-			if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') {
726
-				$addr_spec = substr($mailbox, 1, -1);
727
-			}
728
-			else {
729
-				$addr_spec = $mailbox;
730
-			}
731
-
732
-			if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
733
-				return false;
734
-			}
735
-		}
736
-
737
-		// Construct the object that will be returned.
738
-		$mbox = new stdClass();
739
-
740
-		// Add the phrase (even if empty) and comments
741
-		$mbox->personal = $phrase;
742
-		$mbox->comment = isset($comments) ? $comments : [];
743
-
744
-		if (isset($route_addr)) {
745
-			$mbox->mailbox = $route_addr['local_part'];
746
-			$mbox->host = $route_addr['domain'];
747
-			$route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : '';
748
-		}
749
-		else {
750
-			$mbox->mailbox = $addr_spec['local_part'];
751
-			$mbox->host = $addr_spec['domain'];
752
-		}
753
-
754
-		$mailbox = $mbox;
755
-
756
-		return true;
757
-	}
758
-
759
-	/**
760
-	 * This function validates a route-addr which is:
761
-	 * route-addr = "<" [route] addr-spec ">".
762
-	 *
763
-	 * Angle brackets have already been removed at the point of
764
-	 * getting to this function.
765
-	 *
766
-	 * @param string $route_addr the string to check
767
-	 *
768
-	 * @return mixed false on failure, or an array containing validated address/route information on success
769
-	 */
770
-	protected function _validateRouteAddr($route_addr) {
771
-		// Check for colon.
772
-		if (strpos($route_addr, ':') !== false) {
773
-			$parts = explode(':', $route_addr);
774
-			$route = $this->_splitCheck($parts, ':');
775
-		}
776
-		else {
777
-			$route = $route_addr;
778
-		}
779
-
780
-		// If $route is same as $route_addr then the colon was in
781
-		// quotes or brackets or, of course, non existent.
782
-		if ($route === $route_addr) {
783
-			unset($route);
784
-			$addr_spec = $route_addr;
785
-			if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
786
-				return false;
787
-			}
788
-		}
789
-		else {
790
-			// Validate route part.
791
-			if (($route = $this->_validateRoute($route)) === false) {
792
-				return false;
793
-			}
794
-
795
-			$addr_spec = substr($route_addr, strlen($route . ':'));
796
-
797
-			// Validate addr-spec part.
798
-			if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
799
-				return false;
800
-			}
801
-		}
802
-
803
-		if (isset($route)) {
804
-			$return['adl'] = $route;
805
-		}
806
-		else {
807
-			$return['adl'] = '';
808
-		}
809
-
810
-		return array_merge($return, $addr_spec);
811
-	}
812
-
813
-	/**
814
-	 * Function to validate a route, which is:
815
-	 * route = 1#("@" domain) ":".
816
-	 *
817
-	 * @param string $route the string to check
818
-	 *
819
-	 * @return mixed false on failure, or the validated $route on success
820
-	 */
821
-	protected function _validateRoute($route) {
822
-		// Split on comma.
823
-		$domains = explode(',', trim($route));
824
-
825
-		foreach ($domains as $domain) {
826
-			$domain = str_replace('@', '', trim($domain));
827
-			if (!$this->_validateDomain($domain)) {
828
-				return false;
829
-			}
830
-		}
831
-
832
-		return $route;
833
-	}
834
-
835
-	/**
836
-	 * Function to validate a domain, though this is not quite what
837
-	 * you expect of a strict internet domain.
838
-	 *
839
-	 * domain = sub-domain *("." sub-domain)
840
-	 *
841
-	 * @param string $domain the string to check
842
-	 *
843
-	 * @return mixed false on failure, or the validated domain on success
844
-	 */
845
-	protected function _validateDomain($domain) {
846
-		// Note the different use of $subdomains and $sub_domains
847
-		$subdomains = explode('.', $domain);
848
-
849
-		while (count($subdomains) > 0) {
850
-			$sub_domains[] = $this->_splitCheck($subdomains, '.');
851
-			for ($i = 0; $i < $this->index + 1; ++$i) {
852
-				array_shift($subdomains);
853
-			}
854
-		}
855
-
856
-		foreach ($sub_domains as $sub_domain) {
857
-			if (!$this->_validateSubdomain(trim($sub_domain))) {
858
-				return false;
859
-			}
860
-		}
861
-
862
-		// Managed to get here, so return input.
863
-		return $domain;
864
-	}
865
-
866
-	/**
867
-	 * Function to validate a subdomain:
868
-	 *   subdomain = domain-ref / domain-literal.
869
-	 *
870
-	 * @param string $subdomain the string to check
871
-	 *
872
-	 * @return bool success or failure
873
-	 */
874
-	protected function _validateSubdomain($subdomain) {
875
-		if (preg_match('|^\[(.*)]$|', $subdomain, $arr)) {
876
-			if (!$this->_validateDliteral($arr[1])) {
877
-				return false;
878
-			}
879
-		}
880
-		else {
881
-			if (!$this->_validateAtom($subdomain)) {
882
-				return false;
883
-			}
884
-		}
885
-
886
-		// Got here, so return successful.
887
-		return true;
888
-	}
889
-
890
-	/**
891
-	 * Function to validate a domain literal:
892
-	 *   domain-literal =  "[" *(dtext / quoted-pair) "]".
893
-	 *
894
-	 * @param string $dliteral the string to check
895
-	 *
896
-	 * @return bool success or failure
897
-	 */
898
-	protected function _validateDliteral($dliteral) {
899
-		return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && ((!isset($matches[1])) || $matches[1] != '\\');
900
-	}
901
-
902
-	/**
903
-	 * Function to validate an addr-spec.
904
-	 *
905
-	 * addr-spec = local-part "@" domain
906
-	 *
907
-	 * @param string $addr_spec the string to check
908
-	 *
909
-	 * @return mixed false on failure, or the validated addr-spec on success
910
-	 */
911
-	protected function _validateAddrSpec($addr_spec) {
912
-		$addr_spec = trim($addr_spec);
913
-
914
-		// Split on @ sign if there is one.
915
-		if (strpos($addr_spec, '@') !== false) {
916
-			$parts = explode('@', $addr_spec);
917
-			$local_part = $this->_splitCheck($parts, '@');
918
-			$domain = substr($addr_spec, strlen($local_part . '@'));
919
-
920
-		// No @ sign so assume the default domain.
921
-		}
922
-		else {
923
-			$local_part = $addr_spec;
924
-			$domain = $this->default_domain;
925
-		}
926
-
927
-		if (($local_part = $this->_validateLocalPart($local_part)) === false) {
928
-			return false;
929
-		}
930
-		if (($domain = $this->_validateDomain($domain)) === false) {
931
-			return false;
932
-		}
933
-
934
-		// Got here so return successful.
935
-		return ['local_part' => $local_part, 'domain' => $domain];
936
-	}
937
-
938
-	/**
939
-	 * Function to validate the local part of an address:
940
-	 *   local-part = word *("." word).
941
-	 *
942
-	 * @param string $local_part
943
-	 *
944
-	 * @return mixed false on failure, or the validated local part on success
945
-	 */
946
-	protected function _validateLocalPart($local_part) {
947
-		$parts = explode('.', $local_part);
948
-		$words = [];
949
-
950
-		// Split the local_part into words.
951
-		while (count($parts) > 0) {
952
-			$words[] = $this->_splitCheck($parts, '.');
953
-			for ($i = 0; $i < $this->index + 1; ++$i) {
954
-				array_shift($parts);
955
-			}
956
-		}
957
-
958
-		// Validate each word.
959
-		foreach ($words as $word) {
960
-			// word cannot be empty (#17317)
961
-			if ($word === '') {
962
-				return false;
963
-			}
964
-			// If this word contains an unquoted space, it is invalid. (6.2.4)
965
-			if (strpos($word, ' ') && $word[0] !== '"') {
966
-				return false;
967
-			}
968
-
969
-			if ($this->_validatePhrase(trim($word)) === false) {
970
-				return false;
971
-			}
972
-		}
973
-
974
-		// Managed to get here, so return the input.
975
-		return $local_part;
976
-	}
977
-
978
-	/**
979
-	 * Returns an approximate count of how many addresses are in the
980
-	 * given string. This is APPROXIMATE as it only splits based on a
981
-	 * comma which has no preceding backslash. Could be useful as
982
-	 * large amounts of addresses will end up producing *large*
983
-	 * structures when used with parseAddressList().
984
-	 *
985
-	 * @param string $data Addresses to count
986
-	 *
987
-	 * @return int Approximate count
988
-	 */
989
-	public function approximateCount($data) {
990
-		return count(preg_split('/(?<!\\\\),/', $data));
991
-	}
992
-
993
-	/**
994
-	 * This is a email validating function separate to the rest of the
995
-	 * class. It simply validates whether an email is of the common
996
-	 * internet form: <user>@<domain>. This can be sufficient for most
997
-	 * people. Optional stricter mode can be utilised which restricts
998
-	 * mailbox characters allowed to alphanumeric, full stop, hyphen
999
-	 * and underscore.
1000
-	 *
1001
-	 * @param string $data   Address to check
1002
-	 * @param bool   $strict Optional stricter mode
1003
-	 *
1004
-	 * @return mixed False if it fails, an indexed array
1005
-	 *               username/domain if it matches
1006
-	 */
1007
-	public function isValidInetAddress($data, $strict = false) {
1008
-		$regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i';
1009
-		if (preg_match($regex, trim($data), $matches)) {
1010
-			return [$matches[1], $matches[2]];
1011
-		}
1012
-
1013
-		return false;
1014
-	}
1015
-
1016
-	/**
1017
-	 * grommunio-sync helper for error logging
1018
-	 * removing PEAR dependency.
1019
-	 *
1020
-	 * @param  string  debug message
1021
-	 * @param mixed $message
1022
-	 *
1023
-	 * @return bool always false as there was an error
1024
-	 */
1025
-	public function raiseError($message) {
1026
-		SLog::Write(LOGLEVEL_ERROR, "z_RFC822 error: " . $message);
1027
-
1028
-		return false;
1029
-	}
78
+    /**
79
+     * The address being parsed by the RFC822 object.
80
+     *
81
+     * @var string
82
+     */
83
+    public $address = '';
84
+
85
+    /**
86
+     * The default domain to use for unqualified addresses.
87
+     *
88
+     * @var string
89
+     */
90
+    public $default_domain = 'localhost';
91
+
92
+    /**
93
+     * Should we return a nested array showing groups, or flatten everything?
94
+     *
95
+     * @var bool
96
+     */
97
+    public $nestGroups = true;
98
+
99
+    /**
100
+     * Whether or not to validate atoms for non-ascii characters.
101
+     *
102
+     * @var bool
103
+     */
104
+    public $validate = true;
105
+
106
+    /**
107
+     * The array of raw addresses built up as we parse.
108
+     *
109
+     * @var array
110
+     */
111
+    public $addresses = [];
112
+
113
+    /**
114
+     * The final array of parsed address information that we build up.
115
+     *
116
+     * @var array
117
+     */
118
+    public $structure = [];
119
+
120
+    /**
121
+     * The current error message, if any.
122
+     *
123
+     * @var string
124
+     */
125
+    public $error;
126
+
127
+    /**
128
+     * An internal counter/pointer.
129
+     *
130
+     * @var int
131
+     */
132
+    public $index;
133
+
134
+    /**
135
+     * The number of groups that have been found in the address list.
136
+     *
137
+     * @var int
138
+     */
139
+    public $num_groups = 0;
140
+
141
+    /**
142
+     * A variable so that we can tell whether or not we're inside a
143
+     * Mail_RFC822 object.
144
+     *
145
+     * @var bool
146
+     */
147
+    public $mailRFC822 = true;
148
+
149
+    /**
150
+     * A limit after which processing stops.
151
+     *
152
+     * @var int
153
+     */
154
+    public $limit;
155
+
156
+    /**
157
+     * Sets up the object. The address must either be set here or when
158
+     * calling parseAddressList(). One or the other.
159
+     *
160
+     * @param string     $address        the address(es) to validate
161
+     * @param string     $default_domain Default domain/host etc. If not supplied, will be set to localhost.
162
+     * @param bool       $nest_groups    whether to return the structure with groups nested for easier viewing
163
+     * @param bool       $validate       Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
164
+     * @param null|mixed $limit
165
+     *
166
+     * @return object mail_RFC822 A new Mail_RFC822 object
167
+     */
168
+    public function __construct($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) {
169
+        if (isset($address)) {
170
+            $this->address = $address;
171
+        }
172
+        if (isset($default_domain)) {
173
+            $this->default_domain = $default_domain;
174
+        }
175
+        if (isset($nest_groups)) {
176
+            $this->nestGroups = $nest_groups;
177
+        }
178
+        if (isset($validate)) {
179
+            $this->validate = $validate;
180
+        }
181
+        if (isset($limit)) {
182
+            $this->limit = $limit;
183
+        }
184
+    }
185
+
186
+    /**
187
+     * Starts the whole process. The address must either be set here
188
+     * or when creating the object. One or the other.
189
+     *
190
+     * @param string     $address        the address(es) to validate
191
+     * @param string     $default_domain default domain/host etc
192
+     * @param bool       $nest_groups    whether to return the structure with groups nested for easier viewing
193
+     * @param bool       $validate       Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
194
+     * @param null|mixed $limit
195
+     *
196
+     * @return array a structured array of addresses
197
+     */
198
+    public function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) {
199
+        if (!isset($this) || !isset($this->mailRFC822)) {
200
+            $obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit);
201
+
202
+            return $obj->parseAddressList();
203
+        }
204
+
205
+        if (isset($address)) {
206
+            $this->address = $address;
207
+        }
208
+        // grommunio-sync addition
209
+        if (strlen(trim($this->address)) == 0) {
210
+            return [];
211
+        }
212
+        if (isset($default_domain)) {
213
+            $this->default_domain = $default_domain;
214
+        }
215
+        if (isset($nest_groups)) {
216
+            $this->nestGroups = $nest_groups;
217
+        }
218
+        if (isset($validate)) {
219
+            $this->validate = $validate;
220
+        }
221
+        if (isset($limit)) {
222
+            $this->limit = $limit;
223
+        }
224
+
225
+        $this->structure = [];
226
+        $this->addresses = [];
227
+        $this->error = null;
228
+        $this->index = null;
229
+
230
+        // Unfold any long lines in $this->address.
231
+        $this->address = preg_replace('/\r?\n/', "\r\n", $this->address);
232
+        $this->address = preg_replace('/\r\n(\t| )+/', ' ', $this->address);
233
+
234
+        while ($this->address = $this->_splitAddresses($this->address));
235
+
236
+        if ($this->address === false || isset($this->error)) {
237
+            // require_once 'PEAR.php';
238
+            return $this->raiseError($this->error);
239
+        }
240
+
241
+        // Validate each address individually.  If we encounter an invalid
242
+        // address, stop iterating and return an error immediately.
243
+        foreach ($this->addresses as $address) {
244
+            $valid = $this->_validateAddress($address);
245
+
246
+            if ($valid === false || isset($this->error)) {
247
+                // require_once 'PEAR.php';
248
+                return $this->raiseError($this->error);
249
+            }
250
+
251
+            if (!$this->nestGroups) {
252
+                $this->structure = array_merge($this->structure, $valid);
253
+            }
254
+            else {
255
+                $this->structure[] = $valid;
256
+            }
257
+        }
258
+
259
+        return $this->structure;
260
+    }
261
+
262
+    /**
263
+     * Splits an address into separate addresses.
264
+     *
265
+     * @param string $address the addresses to split
266
+     *
267
+     * @return bool success or failure
268
+     */
269
+    protected function _splitAddresses($address) {
270
+        if (!empty($this->limit) && count($this->addresses) == $this->limit) {
271
+            return '';
272
+        }
273
+
274
+        if ($this->_isGroup($address) && !isset($this->error)) {
275
+            $split_char = ';';
276
+            $is_group = true;
277
+        }
278
+        elseif (!isset($this->error)) {
279
+            $split_char = ',';
280
+            $is_group = false;
281
+        }
282
+        elseif (isset($this->error)) {
283
+            return false;
284
+        }
285
+
286
+        // Split the string based on the above ten or so lines.
287
+        $parts = explode($split_char, $address);
288
+        $string = $this->_splitCheck($parts, $split_char);
289
+
290
+        // If a group...
291
+        if ($is_group) {
292
+            // If $string does not contain a colon outside of
293
+            // brackets/quotes etc then something's fubar.
294
+
295
+            // First check there's a colon at all:
296
+            if (strpos($string, ':') === false) {
297
+                $this->error = 'Invalid address: ' . $string;
298
+
299
+                return false;
300
+            }
301
+
302
+            // Now check it's outside of brackets/quotes:
303
+            if (!$this->_splitCheck(explode(':', $string), ':')) {
304
+                return false;
305
+            }
306
+
307
+            // We must have a group at this point, so increase the counter:
308
+            ++$this->num_groups;
309
+        }
310
+
311
+        // $string now contains the first full address/group.
312
+        // Add to the addresses array.
313
+        $this->addresses[] = [
314
+            'address' => trim($string),
315
+            'group' => $is_group,
316
+        ];
317
+
318
+        // Remove the now stored address from the initial line, the +1
319
+        // is to account for the explode character.
320
+        $address = trim(substr($address, strlen($string) + 1));
321
+
322
+        // If the next char is a comma and this was a group, then
323
+        // there are more addresses, otherwise, if there are any more
324
+        // chars, then there is another address.
325
+        if ($is_group && substr($address, 0, 1) == ',') {
326
+            return trim(substr($address, 1));
327
+        }
328
+        if (strlen($address) > 0) {
329
+            return $address;
330
+        }
331
+
332
+        return '';
333
+        // If you got here then something's off
334
+        return false;
335
+    }
336
+
337
+    /**
338
+     * Checks for a group at the start of the string.
339
+     *
340
+     * @param string $address the address to check
341
+     *
342
+     * @return bool whether or not there is a group at the start of the string
343
+     */
344
+    protected function _isGroup($address) {
345
+        // First comma not in quotes, angles or escaped:
346
+        $parts = explode(',', $address);
347
+        $string = $this->_splitCheck($parts, ',');
348
+
349
+        // Now we have the first address, we can reliably check for a
350
+        // group by searching for a colon that's not escaped or in
351
+        // quotes or angle brackets.
352
+        if (count($parts = explode(':', $string)) > 1) {
353
+            $string2 = $this->_splitCheck($parts, ':');
354
+
355
+            return $string2 !== $string;
356
+        }
357
+
358
+        return false;
359
+    }
360
+
361
+    /**
362
+     * A common function that will check an exploded string.
363
+     *
364
+     * @param array  $parts the exloded string
365
+     * @param string $char  the char that was exploded on
366
+     *
367
+     * @return mixed false if the string contains unclosed quotes/brackets, or the string on success
368
+     */
369
+    protected function _splitCheck($parts, $char) {
370
+        $string = $parts[0];
371
+
372
+        for ($i = 0; $i < count($parts); ++$i) {
373
+            if ($this->_hasUnclosedQuotes($string) ||
374
+                $this->_hasUnclosedBrackets($string, '<>') ||
375
+                $this->_hasUnclosedBrackets($string, '[]') ||
376
+                $this->_hasUnclosedBrackets($string, '()') ||
377
+                substr($string, -1) == '\\') {
378
+                if (isset($parts[$i + 1])) {
379
+                    $string = $string . $char . $parts[$i + 1];
380
+                }
381
+                else {
382
+                    $this->error = 'Invalid address spec. Unclosed bracket or quotes';
383
+
384
+                    return false;
385
+                }
386
+            }
387
+            else {
388
+                $this->index = $i;
389
+
390
+                break;
391
+            }
392
+        }
393
+
394
+        return $string;
395
+    }
396
+
397
+    /**
398
+     * Checks if a string has unclosed quotes or not.
399
+     *
400
+     * @param string $string the string to check
401
+     *
402
+     * @return bool true if there are unclosed quotes inside the string,
403
+     *              false otherwise
404
+     */
405
+    protected function _hasUnclosedQuotes($string) {
406
+        $string = trim($string);
407
+        $iMax = strlen($string);
408
+        $in_quote = false;
409
+        $i = $slashes = 0;
410
+
411
+        for (; $i < $iMax; ++$i) {
412
+            switch ($string[$i]) {
413
+            case '\\':
414
+                ++$slashes;
415
+
416
+                break;
417
+
418
+            case '"':
419
+                if ($slashes % 2 == 0) {
420
+                    $in_quote = !$in_quote;
421
+                }
422
+                // Fall through to default action below.
423
+
424
+                // no break
425
+            default:
426
+                $slashes = 0;
427
+
428
+                break;
429
+            }
430
+        }
431
+
432
+        return $in_quote;
433
+    }
434
+
435
+    /**
436
+     * Checks if a string has an unclosed brackets or not. IMPORTANT:
437
+     * This function handles both angle brackets and square brackets;.
438
+     *
439
+     * @param string $string the string to check
440
+     * @param string $chars  the characters to check for
441
+     *
442
+     * @return bool true if there are unclosed brackets inside the string, false otherwise
443
+     */
444
+    protected function _hasUnclosedBrackets($string, $chars) {
445
+        $num_angle_start = substr_count($string, $chars[0]);
446
+        $num_angle_end = substr_count($string, $chars[1]);
447
+
448
+        $this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]);
449
+        $this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]);
450
+
451
+        if ($num_angle_start < $num_angle_end) {
452
+            $this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')';
453
+
454
+            return false;
455
+        }
456
+
457
+        return $num_angle_start > $num_angle_end;
458
+    }
459
+
460
+    /**
461
+     * Sub function that is used only by hasUnclosedBrackets().
462
+     *
463
+     * @param string $string the string to check
464
+     * @param int    &$num   The number of occurrences
465
+     * @param string $char   the character to count
466
+     *
467
+     * @return int the number of occurrences of $char in $string, adjusted for backslashes
468
+     */
469
+    protected function _hasUnclosedBracketsSub($string, &$num, $char) {
470
+        $parts = explode($char, $string);
471
+        for ($i = 0; $i < count($parts); ++$i) {
472
+            if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i])) {
473
+                --$num;
474
+            }
475
+            if (isset($parts[$i + 1])) {
476
+                $parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1];
477
+            }
478
+        }
479
+
480
+        return $num;
481
+    }
482
+
483
+    /**
484
+     * Function to begin checking the address.
485
+     *
486
+     * @param string $address the address to validate
487
+     *
488
+     * @return mixed false on failure, or a structured array of address information on success
489
+     */
490
+    protected function _validateAddress($address) {
491
+        $is_group = false;
492
+        $addresses = [];
493
+
494
+        if ($address['group']) {
495
+            $is_group = true;
496
+
497
+            // Get the group part of the name
498
+            $parts = explode(':', $address['address']);
499
+            $groupname = $this->_splitCheck($parts, ':');
500
+            $structure = [];
501
+
502
+            // And validate the group part of the name.
503
+            if (!$this->_validatePhrase($groupname)) {
504
+                $this->error = 'Group name did not validate.';
505
+
506
+                return false;
507
+            }
508
+            // Don't include groups if we are not nesting
509
+            // them. This avoids returning invalid addresses.
510
+            if ($this->nestGroups) {
511
+                $structure = new stdClass();
512
+                $structure->groupname = $groupname;
513
+            }
514
+
515
+            $address['address'] = ltrim(substr($address['address'], strlen($groupname . ':')));
516
+        }
517
+
518
+        // If a group then split on comma and put into an array.
519
+        // Otherwise, Just put the whole address in an array.
520
+        if ($is_group) {
521
+            while (strlen($address['address']) > 0) {
522
+                $parts = explode(',', $address['address']);
523
+                $addresses[] = $this->_splitCheck($parts, ',');
524
+                $address['address'] = trim(substr($address['address'], strlen(end($addresses) . ',')));
525
+            }
526
+        }
527
+        else {
528
+            $addresses[] = $address['address'];
529
+        }
530
+
531
+        // Trim the whitespace from all of the address strings.
532
+        array_map('trim', $addresses);
533
+
534
+        // Validate each mailbox.
535
+        // Format could be one of: name <[email protected]>
536
+        //                         [email protected]
537
+        //                         geezer
538
+        // ... or any other format valid by RFC 822.
539
+        for ($i = 0; $i < count($addresses); ++$i) {
540
+            if (!$this->validateMailbox($addresses[$i])) {
541
+                if (empty($this->error)) {
542
+                    $this->error = 'Validation failed for: ' . $addresses[$i];
543
+                }
544
+
545
+                return false;
546
+            }
547
+        }
548
+
549
+        // Nested format
550
+        if ($this->nestGroups) {
551
+            if ($is_group) {
552
+                $structure->addresses = $addresses;
553
+            }
554
+            else {
555
+                $structure = $addresses[0];
556
+            }
557
+
558
+            // Flat format
559
+        }
560
+        else {
561
+            if ($is_group) {
562
+                $structure = array_merge($structure, $addresses);
563
+            }
564
+            else {
565
+                $structure = $addresses;
566
+            }
567
+        }
568
+
569
+        return $structure;
570
+    }
571
+
572
+    /**
573
+     * Function to validate a phrase.
574
+     *
575
+     * @param string $phrase the phrase to check
576
+     *
577
+     * @return bool success or failure
578
+     */
579
+    protected function _validatePhrase($phrase) {
580
+        // Splits on one or more Tab or space.
581
+        $parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY);
582
+
583
+        $phrase_parts = [];
584
+        while (count($parts) > 0) {
585
+            $phrase_parts[] = $this->_splitCheck($parts, ' ');
586
+            for ($i = 0; $i < $this->index + 1; ++$i) {
587
+                array_shift($parts);
588
+            }
589
+        }
590
+
591
+        foreach ($phrase_parts as $part) {
592
+            // If quoted string:
593
+            if (substr($part, 0, 1) == '"') {
594
+                if (!$this->_validateQuotedString($part)) {
595
+                    return false;
596
+                }
597
+
598
+                continue;
599
+            }
600
+
601
+            // Otherwise it's an atom:
602
+            if (!$this->_validateAtom($part)) {
603
+                return false;
604
+            }
605
+        }
606
+
607
+        return true;
608
+    }
609
+
610
+    /**
611
+     * Function to validate an atom which from rfc822 is:
612
+     * atom = 1*<any CHAR except specials, SPACE and CTLs>.
613
+     *
614
+     * If validation ($this->validate) has been turned off, then
615
+     * validateAtom() doesn't actually check anything. This is so that you
616
+     * can split a list of addresses up before encoding personal names
617
+     * (umlauts, etc.), for example.
618
+     *
619
+     * @param string $atom the string to check
620
+     *
621
+     * @return bool success or failure
622
+     */
623
+    protected function _validateAtom($atom) {
624
+        if (!$this->validate) {
625
+            // Validation has been turned off; assume the atom is okay.
626
+            return true;
627
+        }
628
+
629
+        // Check for any char from ASCII 0 - ASCII 127
630
+        if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) {
631
+            return false;
632
+        }
633
+
634
+        // Check for specials:
635
+        if (preg_match('/[][()<>@,;\\:". ]/', $atom)) {
636
+            return false;
637
+        }
638
+
639
+        // Check for control characters (ASCII 0-31):
640
+        if (preg_match('/[\\x00-\\x1F]+/', $atom)) {
641
+            return false;
642
+        }
643
+
644
+        return true;
645
+    }
646
+
647
+    /**
648
+     * Function to validate quoted string, which is:
649
+     * quoted-string = <"> *(qtext/quoted-pair) <">.
650
+     *
651
+     * @param string $qstring The string to check
652
+     *
653
+     * @return bool success or failure
654
+     */
655
+    protected function _validateQuotedString($qstring) {
656
+        // Leading and trailing "
657
+        $qstring = substr($qstring, 1, -1);
658
+
659
+        // Perform check, removing quoted characters first.
660
+        return !preg_match('/[\x0D\\\\"]/', preg_replace('/\\\\./', '', $qstring));
661
+    }
662
+
663
+    /**
664
+     * Function to validate a mailbox, which is:
665
+     * mailbox =   addr-spec         ; simple address
666
+     *           / phrase route-addr ; name and route-addr.
667
+     *
668
+     * @param string &$mailbox The string to check
669
+     *
670
+     * @return bool success or failure
671
+     */
672
+    public function validateMailbox(&$mailbox) {
673
+        // A couple of defaults.
674
+        $phrase = '';
675
+        $comment = '';
676
+        $comments = [];
677
+
678
+        // Catch any RFC822 comments and store them separately.
679
+        $_mailbox = $mailbox;
680
+        while (strlen(trim($_mailbox)) > 0) {
681
+            $parts = explode('(', $_mailbox);
682
+            $before_comment = $this->_splitCheck($parts, '(');
683
+            if ($before_comment != $_mailbox) {
684
+                // First char should be a (.
685
+                $comment = substr(str_replace($before_comment, '', $_mailbox), 1);
686
+                $parts = explode(')', $comment);
687
+                $comment = $this->_splitCheck($parts, ')');
688
+                $comments[] = $comment;
689
+
690
+                // +2 is for the brackets
691
+                $_mailbox = substr($_mailbox, strpos($_mailbox, '(' . $comment) + strlen($comment) + 2);
692
+            }
693
+            else {
694
+                break;
695
+            }
696
+        }
697
+
698
+        foreach ($comments as $comment) {
699
+            $mailbox = str_replace("({$comment})", '', $mailbox);
700
+        }
701
+
702
+        $mailbox = trim($mailbox);
703
+
704
+        // Check for name + route-addr
705
+        if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') {
706
+            $parts = explode('<', $mailbox);
707
+            $name = $this->_splitCheck($parts, '<');
708
+
709
+            $phrase = trim($name);
710
+            $route_addr = trim(substr($mailbox, strlen($name . '<'), -1));
711
+
712
+            // grommunio-sync fix for umlauts and other special chars
713
+            if (substr($phrase, 0, 1) != '"' && substr($phrase, -1) != '"') {
714
+                $phrase = '"' . $phrase . '"';
715
+            }
716
+
717
+            if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) {
718
+                return false;
719
+            }
720
+
721
+            // Only got addr-spec
722
+        }
723
+        else {
724
+            // First snip angle brackets if present.
725
+            if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') {
726
+                $addr_spec = substr($mailbox, 1, -1);
727
+            }
728
+            else {
729
+                $addr_spec = $mailbox;
730
+            }
731
+
732
+            if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
733
+                return false;
734
+            }
735
+        }
736
+
737
+        // Construct the object that will be returned.
738
+        $mbox = new stdClass();
739
+
740
+        // Add the phrase (even if empty) and comments
741
+        $mbox->personal = $phrase;
742
+        $mbox->comment = isset($comments) ? $comments : [];
743
+
744
+        if (isset($route_addr)) {
745
+            $mbox->mailbox = $route_addr['local_part'];
746
+            $mbox->host = $route_addr['domain'];
747
+            $route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : '';
748
+        }
749
+        else {
750
+            $mbox->mailbox = $addr_spec['local_part'];
751
+            $mbox->host = $addr_spec['domain'];
752
+        }
753
+
754
+        $mailbox = $mbox;
755
+
756
+        return true;
757
+    }
758
+
759
+    /**
760
+     * This function validates a route-addr which is:
761
+     * route-addr = "<" [route] addr-spec ">".
762
+     *
763
+     * Angle brackets have already been removed at the point of
764
+     * getting to this function.
765
+     *
766
+     * @param string $route_addr the string to check
767
+     *
768
+     * @return mixed false on failure, or an array containing validated address/route information on success
769
+     */
770
+    protected function _validateRouteAddr($route_addr) {
771
+        // Check for colon.
772
+        if (strpos($route_addr, ':') !== false) {
773
+            $parts = explode(':', $route_addr);
774
+            $route = $this->_splitCheck($parts, ':');
775
+        }
776
+        else {
777
+            $route = $route_addr;
778
+        }
779
+
780
+        // If $route is same as $route_addr then the colon was in
781
+        // quotes or brackets or, of course, non existent.
782
+        if ($route === $route_addr) {
783
+            unset($route);
784
+            $addr_spec = $route_addr;
785
+            if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
786
+                return false;
787
+            }
788
+        }
789
+        else {
790
+            // Validate route part.
791
+            if (($route = $this->_validateRoute($route)) === false) {
792
+                return false;
793
+            }
794
+
795
+            $addr_spec = substr($route_addr, strlen($route . ':'));
796
+
797
+            // Validate addr-spec part.
798
+            if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
799
+                return false;
800
+            }
801
+        }
802
+
803
+        if (isset($route)) {
804
+            $return['adl'] = $route;
805
+        }
806
+        else {
807
+            $return['adl'] = '';
808
+        }
809
+
810
+        return array_merge($return, $addr_spec);
811
+    }
812
+
813
+    /**
814
+     * Function to validate a route, which is:
815
+     * route = 1#("@" domain) ":".
816
+     *
817
+     * @param string $route the string to check
818
+     *
819
+     * @return mixed false on failure, or the validated $route on success
820
+     */
821
+    protected function _validateRoute($route) {
822
+        // Split on comma.
823
+        $domains = explode(',', trim($route));
824
+
825
+        foreach ($domains as $domain) {
826
+            $domain = str_replace('@', '', trim($domain));
827
+            if (!$this->_validateDomain($domain)) {
828
+                return false;
829
+            }
830
+        }
831
+
832
+        return $route;
833
+    }
834
+
835
+    /**
836
+     * Function to validate a domain, though this is not quite what
837
+     * you expect of a strict internet domain.
838
+     *
839
+     * domain = sub-domain *("." sub-domain)
840
+     *
841
+     * @param string $domain the string to check
842
+     *
843
+     * @return mixed false on failure, or the validated domain on success
844
+     */
845
+    protected function _validateDomain($domain) {
846
+        // Note the different use of $subdomains and $sub_domains
847
+        $subdomains = explode('.', $domain);
848
+
849
+        while (count($subdomains) > 0) {
850
+            $sub_domains[] = $this->_splitCheck($subdomains, '.');
851
+            for ($i = 0; $i < $this->index + 1; ++$i) {
852
+                array_shift($subdomains);
853
+            }
854
+        }
855
+
856
+        foreach ($sub_domains as $sub_domain) {
857
+            if (!$this->_validateSubdomain(trim($sub_domain))) {
858
+                return false;
859
+            }
860
+        }
861
+
862
+        // Managed to get here, so return input.
863
+        return $domain;
864
+    }
865
+
866
+    /**
867
+     * Function to validate a subdomain:
868
+     *   subdomain = domain-ref / domain-literal.
869
+     *
870
+     * @param string $subdomain the string to check
871
+     *
872
+     * @return bool success or failure
873
+     */
874
+    protected function _validateSubdomain($subdomain) {
875
+        if (preg_match('|^\[(.*)]$|', $subdomain, $arr)) {
876
+            if (!$this->_validateDliteral($arr[1])) {
877
+                return false;
878
+            }
879
+        }
880
+        else {
881
+            if (!$this->_validateAtom($subdomain)) {
882
+                return false;
883
+            }
884
+        }
885
+
886
+        // Got here, so return successful.
887
+        return true;
888
+    }
889
+
890
+    /**
891
+     * Function to validate a domain literal:
892
+     *   domain-literal =  "[" *(dtext / quoted-pair) "]".
893
+     *
894
+     * @param string $dliteral the string to check
895
+     *
896
+     * @return bool success or failure
897
+     */
898
+    protected function _validateDliteral($dliteral) {
899
+        return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && ((!isset($matches[1])) || $matches[1] != '\\');
900
+    }
901
+
902
+    /**
903
+     * Function to validate an addr-spec.
904
+     *
905
+     * addr-spec = local-part "@" domain
906
+     *
907
+     * @param string $addr_spec the string to check
908
+     *
909
+     * @return mixed false on failure, or the validated addr-spec on success
910
+     */
911
+    protected function _validateAddrSpec($addr_spec) {
912
+        $addr_spec = trim($addr_spec);
913
+
914
+        // Split on @ sign if there is one.
915
+        if (strpos($addr_spec, '@') !== false) {
916
+            $parts = explode('@', $addr_spec);
917
+            $local_part = $this->_splitCheck($parts, '@');
918
+            $domain = substr($addr_spec, strlen($local_part . '@'));
919
+
920
+        // No @ sign so assume the default domain.
921
+        }
922
+        else {
923
+            $local_part = $addr_spec;
924
+            $domain = $this->default_domain;
925
+        }
926
+
927
+        if (($local_part = $this->_validateLocalPart($local_part)) === false) {
928
+            return false;
929
+        }
930
+        if (($domain = $this->_validateDomain($domain)) === false) {
931
+            return false;
932
+        }
933
+
934
+        // Got here so return successful.
935
+        return ['local_part' => $local_part, 'domain' => $domain];
936
+    }
937
+
938
+    /**
939
+     * Function to validate the local part of an address:
940
+     *   local-part = word *("." word).
941
+     *
942
+     * @param string $local_part
943
+     *
944
+     * @return mixed false on failure, or the validated local part on success
945
+     */
946
+    protected function _validateLocalPart($local_part) {
947
+        $parts = explode('.', $local_part);
948
+        $words = [];
949
+
950
+        // Split the local_part into words.
951
+        while (count($parts) > 0) {
952
+            $words[] = $this->_splitCheck($parts, '.');
953
+            for ($i = 0; $i < $this->index + 1; ++$i) {
954
+                array_shift($parts);
955
+            }
956
+        }
957
+
958
+        // Validate each word.
959
+        foreach ($words as $word) {
960
+            // word cannot be empty (#17317)
961
+            if ($word === '') {
962
+                return false;
963
+            }
964
+            // If this word contains an unquoted space, it is invalid. (6.2.4)
965
+            if (strpos($word, ' ') && $word[0] !== '"') {
966
+                return false;
967
+            }
968
+
969
+            if ($this->_validatePhrase(trim($word)) === false) {
970
+                return false;
971
+            }
972
+        }
973
+
974
+        // Managed to get here, so return the input.
975
+        return $local_part;
976
+    }
977
+
978
+    /**
979
+     * Returns an approximate count of how many addresses are in the
980
+     * given string. This is APPROXIMATE as it only splits based on a
981
+     * comma which has no preceding backslash. Could be useful as
982
+     * large amounts of addresses will end up producing *large*
983
+     * structures when used with parseAddressList().
984
+     *
985
+     * @param string $data Addresses to count
986
+     *
987
+     * @return int Approximate count
988
+     */
989
+    public function approximateCount($data) {
990
+        return count(preg_split('/(?<!\\\\),/', $data));
991
+    }
992
+
993
+    /**
994
+     * This is a email validating function separate to the rest of the
995
+     * class. It simply validates whether an email is of the common
996
+     * internet form: <user>@<domain>. This can be sufficient for most
997
+     * people. Optional stricter mode can be utilised which restricts
998
+     * mailbox characters allowed to alphanumeric, full stop, hyphen
999
+     * and underscore.
1000
+     *
1001
+     * @param string $data   Address to check
1002
+     * @param bool   $strict Optional stricter mode
1003
+     *
1004
+     * @return mixed False if it fails, an indexed array
1005
+     *               username/domain if it matches
1006
+     */
1007
+    public function isValidInetAddress($data, $strict = false) {
1008
+        $regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i';
1009
+        if (preg_match($regex, trim($data), $matches)) {
1010
+            return [$matches[1], $matches[2]];
1011
+        }
1012
+
1013
+        return false;
1014
+    }
1015
+
1016
+    /**
1017
+     * grommunio-sync helper for error logging
1018
+     * removing PEAR dependency.
1019
+     *
1020
+     * @param  string  debug message
1021
+     * @param mixed $message
1022
+     *
1023
+     * @return bool always false as there was an error
1024
+     */
1025
+    public function raiseError($message) {
1026
+        SLog::Write(LOGLEVEL_ERROR, "z_RFC822 error: " . $message);
1027
+
1028
+        return false;
1029
+    }
1030 1030
 }
Please login to merge, or discard this patch.
Switch Indentation   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -410,22 +410,22 @@
 block discarded – undo
410 410
 
411 411
 		for (; $i < $iMax; ++$i) {
412 412
 			switch ($string[$i]) {
413
-			case '\\':
414
-				++$slashes;
413
+			    case '\\':
414
+				    ++$slashes;
415 415
 
416
-				break;
416
+				    break;
417 417
 
418
-			case '"':
419
-				if ($slashes % 2 == 0) {
420
-					$in_quote = !$in_quote;
421
-				}
422
-				// Fall through to default action below.
418
+			    case '"':
419
+				    if ($slashes % 2 == 0) {
420
+					    $in_quote = !$in_quote;
421
+				    }
422
+				    // Fall through to default action below.
423 423
 
424
-				// no break
425
-			default:
426
-				$slashes = 0;
424
+				    // no break
425
+			    default:
426
+				    $slashes = 0;
427 427
 
428
-				break;
428
+				    break;
429 429
 			}
430 430
 		}
431 431
 
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
 
295 295
 			// First check there's a colon at all:
296 296
 			if (strpos($string, ':') === false) {
297
-				$this->error = 'Invalid address: ' . $string;
297
+				$this->error = 'Invalid address: '.$string;
298 298
 
299 299
 				return false;
300 300
 			}
@@ -376,7 +376,7 @@  discard block
 block discarded – undo
376 376
 				$this->_hasUnclosedBrackets($string, '()') ||
377 377
 				substr($string, -1) == '\\') {
378 378
 				if (isset($parts[$i + 1])) {
379
-					$string = $string . $char . $parts[$i + 1];
379
+					$string = $string.$char.$parts[$i + 1];
380 380
 				}
381 381
 				else {
382 382
 					$this->error = 'Invalid address spec. Unclosed bracket or quotes';
@@ -449,7 +449,7 @@  discard block
 block discarded – undo
449 449
 		$this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]);
450 450
 
451 451
 		if ($num_angle_start < $num_angle_end) {
452
-			$this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')';
452
+			$this->error = 'Invalid address spec. Unmatched quote or bracket ('.$chars.')';
453 453
 
454 454
 			return false;
455 455
 		}
@@ -473,7 +473,7 @@  discard block
 block discarded – undo
473 473
 				--$num;
474 474
 			}
475 475
 			if (isset($parts[$i + 1])) {
476
-				$parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1];
476
+				$parts[$i + 1] = $parts[$i].$char.$parts[$i + 1];
477 477
 			}
478 478
 		}
479 479
 
@@ -512,7 +512,7 @@  discard block
 block discarded – undo
512 512
 				$structure->groupname = $groupname;
513 513
 			}
514 514
 
515
-			$address['address'] = ltrim(substr($address['address'], strlen($groupname . ':')));
515
+			$address['address'] = ltrim(substr($address['address'], strlen($groupname.':')));
516 516
 		}
517 517
 
518 518
 		// If a group then split on comma and put into an array.
@@ -521,7 +521,7 @@  discard block
 block discarded – undo
521 521
 			while (strlen($address['address']) > 0) {
522 522
 				$parts = explode(',', $address['address']);
523 523
 				$addresses[] = $this->_splitCheck($parts, ',');
524
-				$address['address'] = trim(substr($address['address'], strlen(end($addresses) . ',')));
524
+				$address['address'] = trim(substr($address['address'], strlen(end($addresses).',')));
525 525
 			}
526 526
 		}
527 527
 		else {
@@ -539,7 +539,7 @@  discard block
 block discarded – undo
539 539
 		for ($i = 0; $i < count($addresses); ++$i) {
540 540
 			if (!$this->validateMailbox($addresses[$i])) {
541 541
 				if (empty($this->error)) {
542
-					$this->error = 'Validation failed for: ' . $addresses[$i];
542
+					$this->error = 'Validation failed for: '.$addresses[$i];
543 543
 				}
544 544
 
545 545
 				return false;
@@ -688,7 +688,7 @@  discard block
 block discarded – undo
688 688
 				$comments[] = $comment;
689 689
 
690 690
 				// +2 is for the brackets
691
-				$_mailbox = substr($_mailbox, strpos($_mailbox, '(' . $comment) + strlen($comment) + 2);
691
+				$_mailbox = substr($_mailbox, strpos($_mailbox, '('.$comment) + strlen($comment) + 2);
692 692
 			}
693 693
 			else {
694 694
 				break;
@@ -707,11 +707,11 @@  discard block
 block discarded – undo
707 707
 			$name = $this->_splitCheck($parts, '<');
708 708
 
709 709
 			$phrase = trim($name);
710
-			$route_addr = trim(substr($mailbox, strlen($name . '<'), -1));
710
+			$route_addr = trim(substr($mailbox, strlen($name.'<'), -1));
711 711
 
712 712
 			// grommunio-sync fix for umlauts and other special chars
713 713
 			if (substr($phrase, 0, 1) != '"' && substr($phrase, -1) != '"') {
714
-				$phrase = '"' . $phrase . '"';
714
+				$phrase = '"'.$phrase.'"';
715 715
 			}
716 716
 
717 717
 			if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) {
@@ -792,7 +792,7 @@  discard block
 block discarded – undo
792 792
 				return false;
793 793
 			}
794 794
 
795
-			$addr_spec = substr($route_addr, strlen($route . ':'));
795
+			$addr_spec = substr($route_addr, strlen($route.':'));
796 796
 
797 797
 			// Validate addr-spec part.
798 798
 			if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
@@ -915,7 +915,7 @@  discard block
 block discarded – undo
915 915
 		if (strpos($addr_spec, '@') !== false) {
916 916
 			$parts = explode('@', $addr_spec);
917 917
 			$local_part = $this->_splitCheck($parts, '@');
918
-			$domain = substr($addr_spec, strlen($local_part . '@'));
918
+			$domain = substr($addr_spec, strlen($local_part.'@'));
919 919
 
920 920
 		// No @ sign so assume the default domain.
921 921
 		}
@@ -1023,7 +1023,7 @@  discard block
 block discarded – undo
1023 1023
 	 * @return bool always false as there was an error
1024 1024
 	 */
1025 1025
 	public function raiseError($message) {
1026
-		SLog::Write(LOGLEVEL_ERROR, "z_RFC822 error: " . $message);
1026
+		SLog::Write(LOGLEVEL_ERROR, "z_RFC822 error: ".$message);
1027 1027
 
1028 1028
 		return false;
1029 1029
 	}
Please login to merge, or discard this patch.
Braces   +18 added lines, -36 removed lines patch added patch discarded remove patch
@@ -250,8 +250,7 @@  discard block
 block discarded – undo
250 250
 
251 251
 			if (!$this->nestGroups) {
252 252
 				$this->structure = array_merge($this->structure, $valid);
253
-			}
254
-			else {
253
+			} else {
255 254
 				$this->structure[] = $valid;
256 255
 			}
257 256
 		}
@@ -274,12 +273,10 @@  discard block
 block discarded – undo
274 273
 		if ($this->_isGroup($address) && !isset($this->error)) {
275 274
 			$split_char = ';';
276 275
 			$is_group = true;
277
-		}
278
-		elseif (!isset($this->error)) {
276
+		} elseif (!isset($this->error)) {
279 277
 			$split_char = ',';
280 278
 			$is_group = false;
281
-		}
282
-		elseif (isset($this->error)) {
279
+		} elseif (isset($this->error)) {
283 280
 			return false;
284 281
 		}
285 282
 
@@ -377,14 +374,12 @@  discard block
 block discarded – undo
377 374
 				substr($string, -1) == '\\') {
378 375
 				if (isset($parts[$i + 1])) {
379 376
 					$string = $string . $char . $parts[$i + 1];
380
-				}
381
-				else {
377
+				} else {
382 378
 					$this->error = 'Invalid address spec. Unclosed bracket or quotes';
383 379
 
384 380
 					return false;
385 381
 				}
386
-			}
387
-			else {
382
+			} else {
388 383
 				$this->index = $i;
389 384
 
390 385
 				break;
@@ -523,8 +518,7 @@  discard block
 block discarded – undo
523 518
 				$addresses[] = $this->_splitCheck($parts, ',');
524 519
 				$address['address'] = trim(substr($address['address'], strlen(end($addresses) . ',')));
525 520
 			}
526
-		}
527
-		else {
521
+		} else {
528 522
 			$addresses[] = $address['address'];
529 523
 		}
530 524
 
@@ -550,18 +544,15 @@  discard block
 block discarded – undo
550 544
 		if ($this->nestGroups) {
551 545
 			if ($is_group) {
552 546
 				$structure->addresses = $addresses;
553
-			}
554
-			else {
547
+			} else {
555 548
 				$structure = $addresses[0];
556 549
 			}
557 550
 
558 551
 			// Flat format
559
-		}
560
-		else {
552
+		} else {
561 553
 			if ($is_group) {
562 554
 				$structure = array_merge($structure, $addresses);
563
-			}
564
-			else {
555
+			} else {
565 556
 				$structure = $addresses;
566 557
 			}
567 558
 		}
@@ -689,8 +680,7 @@  discard block
 block discarded – undo
689 680
 
690 681
 				// +2 is for the brackets
691 682
 				$_mailbox = substr($_mailbox, strpos($_mailbox, '(' . $comment) + strlen($comment) + 2);
692
-			}
693
-			else {
683
+			} else {
694 684
 				break;
695 685
 			}
696 686
 		}
@@ -719,13 +709,11 @@  discard block
 block discarded – undo
719 709
 			}
720 710
 
721 711
 			// Only got addr-spec
722
-		}
723
-		else {
712
+		} else {
724 713
 			// First snip angle brackets if present.
725 714
 			if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') {
726 715
 				$addr_spec = substr($mailbox, 1, -1);
727
-			}
728
-			else {
716
+			} else {
729 717
 				$addr_spec = $mailbox;
730 718
 			}
731 719
 
@@ -745,8 +733,7 @@  discard block
 block discarded – undo
745 733
 			$mbox->mailbox = $route_addr['local_part'];
746 734
 			$mbox->host = $route_addr['domain'];
747 735
 			$route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : '';
748
-		}
749
-		else {
736
+		} else {
750 737
 			$mbox->mailbox = $addr_spec['local_part'];
751 738
 			$mbox->host = $addr_spec['domain'];
752 739
 		}
@@ -772,8 +759,7 @@  discard block
 block discarded – undo
772 759
 		if (strpos($route_addr, ':') !== false) {
773 760
 			$parts = explode(':', $route_addr);
774 761
 			$route = $this->_splitCheck($parts, ':');
775
-		}
776
-		else {
762
+		} else {
777 763
 			$route = $route_addr;
778 764
 		}
779 765
 
@@ -785,8 +771,7 @@  discard block
 block discarded – undo
785 771
 			if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
786 772
 				return false;
787 773
 			}
788
-		}
789
-		else {
774
+		} else {
790 775
 			// Validate route part.
791 776
 			if (($route = $this->_validateRoute($route)) === false) {
792 777
 				return false;
@@ -802,8 +787,7 @@  discard block
 block discarded – undo
802 787
 
803 788
 		if (isset($route)) {
804 789
 			$return['adl'] = $route;
805
-		}
806
-		else {
790
+		} else {
807 791
 			$return['adl'] = '';
808 792
 		}
809 793
 
@@ -876,8 +860,7 @@  discard block
 block discarded – undo
876 860
 			if (!$this->_validateDliteral($arr[1])) {
877 861
 				return false;
878 862
 			}
879
-		}
880
-		else {
863
+		} else {
881 864
 			if (!$this->_validateAtom($subdomain)) {
882 865
 				return false;
883 866
 			}
@@ -918,8 +901,7 @@  discard block
 block discarded – undo
918 901
 			$domain = substr($addr_spec, strlen($local_part . '@'));
919 902
 
920 903
 		// No @ sign so assume the default domain.
921
-		}
922
-		else {
904
+		} else {
923 905
 			$local_part = $addr_spec;
924 906
 			$domain = $this->default_domain;
925 907
 		}
Please login to merge, or discard this patch.
lib/utils/utils.php 3 patches
Indentation   +928 added lines, -928 removed lines patch added patch discarded remove patch
@@ -8,960 +8,960 @@  discard block
 block discarded – undo
8 8
  */
9 9
 
10 10
 class Utils {
11
-	/**
12
-	 * Prints a variable as string
13
-	 * If a boolean is sent, 'true' or 'false' is displayed.
14
-	 *
15
-	 * @param string $var
16
-	 *
17
-	 * @return string
18
-	 */
19
-	public static function PrintAsString($var) {
20
-		return ($var) ? (($var === true) ? 'true' : $var) : (($var === false) ? 'false' : (($var === '') ? 'empty' : (($var === null) ? 'null' : $var)));
21
-	}
22
-
23
-	/**
24
-	 * Splits a "domain\user" string into two values
25
-	 * If the string contains only the user, domain is returned empty.
26
-	 *
27
-	 * @param string $domainuser
28
-	 *
29
-	 * @return array index 0: user  1: domain
30
-	 */
31
-	public static function SplitDomainUser($domainuser) {
32
-		$pos = strrpos($domainuser, '\\');
33
-		if ($pos === false) {
34
-			$user = $domainuser;
35
-			$domain = '';
36
-		}
37
-		else {
38
-			$domain = substr($domainuser, 0, $pos);
39
-			$user = substr($domainuser, $pos + 1);
40
-		}
41
-
42
-		return [$user, $domain];
43
-	}
44
-
45
-	/**
46
-	 * Build an address string from the components.
47
-	 *
48
-	 * @param string $street  the street
49
-	 * @param string $zip     the zip code
50
-	 * @param string $city    the city
51
-	 * @param string $state   the state
52
-	 * @param string $country the country
53
-	 *
54
-	 * @return string the address string or null
55
-	 */
56
-	public static function BuildAddressString($street, $zip, $city, $state, $country) {
57
-		$out = "";
58
-
59
-		if (isset($country) && $street != "") {
60
-			$out = $country;
61
-		}
62
-
63
-		$zcs = "";
64
-		if (isset($zip) && $zip != "") {
65
-			$zcs = $zip;
66
-		}
67
-		if (isset($city) && $city != "") {
68
-			$zcs .= (($zcs) ? " " : "") . $city;
69
-		}
70
-		if (isset($state) && $state != "") {
71
-			$zcs .= (($zcs) ? " " : "") . $state;
72
-		}
73
-		if ($zcs) {
74
-			$out = $zcs . "\r\n" . $out;
75
-		}
76
-
77
-		if (isset($street) && $street != "") {
78
-			$out = $street . (($out) ? "\r\n\r\n" . $out : "");
79
-		}
80
-
81
-		return ($out) ? $out : null;
82
-	}
83
-
84
-	/**
85
-	 * Build the fileas string from the components according to the configuration.
86
-	 *
87
-	 * @param string $lastname
88
-	 * @param string $firstname
89
-	 * @param string $middlename
90
-	 * @param string $company
91
-	 *
92
-	 * @return string fileas
93
-	 */
94
-	public static function BuildFileAs($lastname = "", $firstname = "", $middlename = "", $company = "") {
95
-		if (defined('FILEAS_ORDER')) {
96
-			$fileas = $lastfirst = $firstlast = "";
97
-			$names = trim($firstname . " " . $middlename);
98
-			$lastname = trim($lastname);
99
-			$company = trim($company);
100
-
101
-			// lastfirst is "lastname, firstname middlename"
102
-			// firstlast is "firstname middlename lastname"
103
-			if (strlen($lastname) > 0) {
104
-				$lastfirst = $lastname;
105
-				if (strlen($names) > 0) {
106
-					$lastfirst .= ", {$names}";
107
-					$firstlast = "{$names} {$lastname}";
108
-				}
109
-				else {
110
-					$firstlast = $lastname;
111
-				}
112
-			}
113
-			elseif (strlen($names) > 0) {
114
-				$lastfirst = $firstlast = $names;
115
-			}
116
-
117
-			// if fileas with a company is selected
118
-			// but company is empty then it will
119
-			// fallback to firstlast or lastfirst
120
-			// (depending on which is selected for company)
121
-			switch (FILEAS_ORDER) {
122
-				case SYNC_FILEAS_COMPANYONLY:
123
-					if (strlen($company) > 0) {
124
-						$fileas = $company;
125
-					}
126
-					elseif (strlen($firstlast) > 0) {
127
-						$fileas = $lastfirst;
128
-					}
129
-					break;
130
-
131
-				case SYNC_FILEAS_COMPANYLAST:
132
-					if (strlen($company) > 0) {
133
-						$fileas = $company;
134
-						if (strlen($lastfirst) > 0) {
135
-							$fileas .= "({$lastfirst})";
136
-						}
137
-					}
138
-					elseif (strlen($lastfirst) > 0) {
139
-						$fileas = $lastfirst;
140
-					}
141
-					break;
142
-
143
-				case SYNC_FILEAS_COMPANYFIRST:
144
-					if (strlen($company) > 0) {
145
-						$fileas = $company;
146
-						if (strlen($firstlast) > 0) {
147
-							$fileas .= " ({$firstlast})";
148
-						}
149
-					}
150
-					elseif (strlen($firstlast) > 0) {
151
-						$fileas = $firstlast;
152
-					}
153
-					break;
154
-
155
-				case SYNC_FILEAS_FIRSTCOMPANY:
156
-					if (strlen($firstlast) > 0) {
157
-						$fileas = $firstlast;
158
-						if (strlen($company) > 0) {
159
-							$fileas .= " ({$company})";
160
-						}
161
-					}
162
-					elseif (strlen($company) > 0) {
163
-						$fileas = $company;
164
-					}
165
-					break;
166
-
167
-				case SYNC_FILEAS_LASTCOMPANY:
168
-					if (strlen($lastfirst) > 0) {
169
-						$fileas = $lastfirst;
170
-						if (strlen($company) > 0) {
171
-							$fileas .= " ({$company})";
172
-						}
173
-					}
174
-					elseif (strlen($company) > 0) {
175
-						$fileas = $company;
176
-					}
177
-					break;
178
-
179
-				case SYNC_FILEAS_LASTFIRST:
180
-					if (strlen($lastfirst) > 0) {
181
-						$fileas = $lastfirst;
182
-					}
183
-					break;
184
-
185
-				default:
186
-					$fileas = $firstlast;
187
-					break;
188
-			}
189
-			if (strlen($fileas) == 0) {
190
-				SLog::Write(LOGLEVEL_DEBUG, "Fileas is empty.");
191
-			}
192
-
193
-			return $fileas;
194
-		}
195
-		SLog::Write(LOGLEVEL_DEBUG, "FILEAS_ORDER not defined. Add it to your config.php.");
196
-
197
-		return null;
198
-	}
199
-
200
-	/**
201
-	 * Checks if the PHP-MAPI extension is available and in a requested version.
202
-	 *
203
-	 * @param string $version the version to be checked ("6.30.10-18495", parts or build number)
204
-	 *
205
-	 * @return bool installed version is superior to the checked string
206
-	 */
207
-	public static function CheckMapiExtVersion($version = "") {
208
-		if (!extension_loaded("mapi")) {
209
-			return false;
210
-		}
211
-		// compare build number if requested
212
-		if (preg_match('/^\d+$/', $version) && strlen($version) > 3) {
213
-			$vs = preg_split('/-/', phpversion("mapi"));
214
-
215
-			return $version <= $vs[1];
216
-		}
217
-		if (version_compare(phpversion("mapi"), $version) == -1) {
218
-			return false;
219
-		}
220
-
221
-		return true;
222
-	}
223
-
224
-	/**
225
-	 * Parses and returns an ecoded vCal-Uid from an OL compatible GlobalObjectID.
226
-	 *
227
-	 * @param string $olUid an OL compatible GlobalObjectID
228
-	 *
229
-	 * @return string the vCal-Uid if available in the olUid, else the original olUid as HEX
230
-	 */
231
-	public static function GetICalUidFromOLUid($olUid) {
232
-		// check if "vCal-Uid" is somewhere in outlookid case-insensitive
233
-		$icalUid = stristr($olUid, "vCal-Uid");
234
-		if ($icalUid !== false) {
235
-			// get the length of the ical id - go back 4 position from where "vCal-Uid" was found
236
-			$begin = unpack("V", substr($olUid, strlen($icalUid) * (-1) - 4, 4));
237
-			// remove "vCal-Uid" and packed "1" and use the ical id length
238
-			return substr($icalUid, 12, ($begin[1] - 13));
239
-		}
240
-
241
-		return strtoupper(bin2hex($olUid));
242
-	}
243
-
244
-	/**
245
-	 * Checks the given UID if it is an OL compatible GlobalObjectID
246
-	 * If not, the given UID is encoded inside the GlobalObjectID.
247
-	 *
248
-	 * @param string $icalUid an appointment uid as HEX
249
-	 *
250
-	 * @return string an OL compatible GlobalObjectID
251
-	 */
252
-	public static function GetOLUidFromICalUid($icalUid) {
253
-		if (strlen($icalUid) <= 64) {
254
-			$len = 13 + strlen($icalUid);
255
-			$OLUid = pack("V", $len);
256
-			$OLUid .= "vCal-Uid";
257
-			$OLUid .= pack("V", 1);
258
-			$OLUid .= $icalUid;
259
-
260
-			return hex2bin("040000008200E00074C5B7101A82E0080000000000000000000000000000000000000000" . bin2hex($OLUid) . "00");
261
-		}
262
-
263
-		return hex2bin($icalUid);
264
-	}
265
-
266
-	/**
267
-	 * Extracts the basedate of the GlobalObjectID and the RecurStartTime.
268
-	 *
269
-	 * @param string $goid           OL compatible GlobalObjectID
270
-	 * @param long   $recurStartTime
271
-	 *
272
-	 * @return long basedate
273
-	 */
274
-	public static function ExtractBaseDate($goid, $recurStartTime) {
275
-		$hexbase = substr(bin2hex($goid), 32, 8);
276
-		$day = hexdec(substr($hexbase, 6, 2));
277
-		$month = hexdec(substr($hexbase, 4, 2));
278
-		$year = hexdec(substr($hexbase, 0, 4));
279
-
280
-		if ($day && $month && $year) {
281
-			$h = $recurStartTime >> 12;
282
-			$m = ($recurStartTime - $h * 4096) >> 6;
283
-			$s = $recurStartTime - $h * 4096 - $m * 64;
284
-
285
-			return gmmktime($h, $m, $s, $month, $day, $year);
286
-		}
287
-
288
-		return false;
289
-	}
290
-
291
-	/**
292
-	 * Converts SYNC_FILTERTYPE into a timestamp.
293
-	 *
294
-	 * @param int $filtertype Filtertype
295
-	 *
296
-	 * @return long
297
-	 */
298
-	public static function GetCutOffDate($filtertype) {
299
-		$back = Utils::GetFiltertypeInterval($filtertype);
300
-
301
-		if ($back === false) {
302
-			return 0; // unlimited
303
-		}
304
-
305
-		return time() - $back;
306
-	}
307
-
308
-	/**
309
-	 * Returns the interval indicated by the filtertype.
310
-	 *
311
-	 * @param int $filtertype
312
-	 *
313
-	 * @return bool|long returns false on invalid filtertype
314
-	 */
315
-	public static function GetFiltertypeInterval($filtertype) {
316
-		$back = false;
317
-
318
-		switch ($filtertype) {
319
-			case SYNC_FILTERTYPE_1DAY:
320
-				$back = 60 * 60 * 24;
321
-				break;
322
-
323
-			case SYNC_FILTERTYPE_3DAYS:
324
-				$back = 60 * 60 * 24 * 3;
325
-				break;
326
-
327
-			case SYNC_FILTERTYPE_1WEEK:
328
-				$back = 60 * 60 * 24 * 7;
329
-				break;
330
-
331
-			case SYNC_FILTERTYPE_2WEEKS:
332
-				$back = 60 * 60 * 24 * 14;
333
-				break;
334
-
335
-			case SYNC_FILTERTYPE_1MONTH:
336
-				$back = 60 * 60 * 24 * 31;
337
-				break;
338
-
339
-			case SYNC_FILTERTYPE_3MONTHS:
340
-				$back = 60 * 60 * 24 * 31 * 3;
341
-				break;
342
-
343
-			case SYNC_FILTERTYPE_6MONTHS:
344
-				$back = 60 * 60 * 24 * 31 * 6;
345
-				break;
346
-
347
-			default:
348
-				$back = false;
349
-		}
350
-
351
-		return $back;
352
-	}
353
-
354
-	/**
355
-	 * Converts SYNC_TRUNCATION into bytes.
356
-	 *
357
-	 * @param int       SYNC_TRUNCATION
358
-	 * @param mixed $truncation
359
-	 *
360
-	 * @return long
361
-	 */
362
-	public static function GetTruncSize($truncation) {
363
-		switch ($truncation) {
364
-			case SYNC_TRUNCATION_HEADERS:
365
-				return 0;
366
-
367
-			case SYNC_TRUNCATION_512B:
368
-				return 512;
369
-
370
-			case SYNC_TRUNCATION_1K:
371
-				return 1024;
372
-
373
-			case SYNC_TRUNCATION_2K:
374
-				return 2 * 1024;
375
-
376
-			case SYNC_TRUNCATION_5K:
377
-				return 5 * 1024;
378
-
379
-			case SYNC_TRUNCATION_10K:
380
-				return 10 * 1024;
381
-
382
-			case SYNC_TRUNCATION_20K:
383
-				return 20 * 1024;
384
-
385
-			case SYNC_TRUNCATION_50K:
386
-				return 50 * 1024;
387
-
388
-			case SYNC_TRUNCATION_100K:
389
-				return 100 * 1024;
390
-
391
-			case SYNC_TRUNCATION_ALL:
392
-				return 1024 * 1024; // We'll limit to 1MB anyway
393
-
394
-			default:
395
-				return 1024; // Default to 1Kb
396
-		}
397
-	}
398
-
399
-	/**
400
-	 * Truncate an UTF-8 encoded string correctly.
401
-	 *
402
-	 * If it's not possible to truncate properly, an empty string is returned
403
-	 *
404
-	 * @param string $string   the string
405
-	 * @param string $length   position where string should be cut
406
-	 * @param bool   $htmlsafe doesn't cut html tags in half, doesn't ensure correct html - default: false
407
-	 *
408
-	 * @return string truncated string
409
-	 */
410
-	public static function Utf8_truncate($string, $length, $htmlsafe = false) {
411
-		// make sure length is always an integer
412
-		$length = (int) $length;
413
-
414
-		// if the input string is shorter then the trunction, make sure it's valid UTF-8!
415
-		if (strlen($string) <= $length) {
416
-			$length = strlen($string) - 1;
417
-		}
418
-
419
-		// The intent is not to cut HTML tags in half which causes displaying issues (see ZP-1240).
420
-		// The used method just tries to cut outside of tags, without checking tag validity and closing tags.
421
-		if ($htmlsafe) {
422
-			$offset = 0 - strlen($string) + $length;
423
-			$validPos = strrpos($string, "<", $offset);
424
-			if ($validPos > strrpos($string, ">", $offset)) {
425
-				$length = $validPos;
426
-			}
427
-		}
428
-
429
-		while ($length >= 0) {
430
-			if ((ord($string[$length]) < 0x80) || (ord($string[$length]) >= 0xC0)) {
431
-				return substr($string, 0, $length);
432
-			}
433
-			--$length;
434
-		}
435
-
436
-		return "";
437
-	}
438
-
439
-	/**
440
-	 * Indicates if the specified folder type is a system folder.
441
-	 *
442
-	 * @param int $foldertype
443
-	 *
444
-	 * @return bool
445
-	 */
446
-	public static function IsSystemFolder($foldertype) {
447
-		return (
448
-			$foldertype == SYNC_FOLDER_TYPE_INBOX ||
449
-			$foldertype == SYNC_FOLDER_TYPE_DRAFTS ||
450
-			$foldertype == SYNC_FOLDER_TYPE_WASTEBASKET ||
451
-			$foldertype == SYNC_FOLDER_TYPE_SENTMAIL ||
452
-			$foldertype == SYNC_FOLDER_TYPE_OUTBOX ||
453
-			$foldertype == SYNC_FOLDER_TYPE_TASK ||
454
-			$foldertype == SYNC_FOLDER_TYPE_APPOINTMENT ||
455
-			$foldertype == SYNC_FOLDER_TYPE_CONTACT ||
456
-			$foldertype == SYNC_FOLDER_TYPE_NOTE ||
457
-			$foldertype == SYNC_FOLDER_TYPE_JOURNAL
458
-			) ? true : false;
459
-	}
460
-
461
-	/**
462
-	 * Checks for valid email addresses
463
-	 * The used regex actually only checks if a valid email address is part of the submitted string
464
-	 * it also returns true for the mailbox format, but this is not checked explicitly.
465
-	 *
466
-	 * @param string $email address to be checked
467
-	 *
468
-	 * @return bool
469
-	 */
470
-	public static function CheckEmail($email) {
471
-		return strpos($email, '@') !== false ? true : false;
472
-	}
473
-
474
-	/**
475
-	 * Checks if a string is base64 encoded.
476
-	 *
477
-	 * @param string $string the string to be checked
478
-	 *
479
-	 * @return bool
480
-	 */
481
-	public static function IsBase64String($string) {
482
-		return (bool) preg_match("#^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+/]{4})?$#", $string);
483
-	}
11
+    /**
12
+     * Prints a variable as string
13
+     * If a boolean is sent, 'true' or 'false' is displayed.
14
+     *
15
+     * @param string $var
16
+     *
17
+     * @return string
18
+     */
19
+    public static function PrintAsString($var) {
20
+        return ($var) ? (($var === true) ? 'true' : $var) : (($var === false) ? 'false' : (($var === '') ? 'empty' : (($var === null) ? 'null' : $var)));
21
+    }
22
+
23
+    /**
24
+     * Splits a "domain\user" string into two values
25
+     * If the string contains only the user, domain is returned empty.
26
+     *
27
+     * @param string $domainuser
28
+     *
29
+     * @return array index 0: user  1: domain
30
+     */
31
+    public static function SplitDomainUser($domainuser) {
32
+        $pos = strrpos($domainuser, '\\');
33
+        if ($pos === false) {
34
+            $user = $domainuser;
35
+            $domain = '';
36
+        }
37
+        else {
38
+            $domain = substr($domainuser, 0, $pos);
39
+            $user = substr($domainuser, $pos + 1);
40
+        }
41
+
42
+        return [$user, $domain];
43
+    }
44
+
45
+    /**
46
+     * Build an address string from the components.
47
+     *
48
+     * @param string $street  the street
49
+     * @param string $zip     the zip code
50
+     * @param string $city    the city
51
+     * @param string $state   the state
52
+     * @param string $country the country
53
+     *
54
+     * @return string the address string or null
55
+     */
56
+    public static function BuildAddressString($street, $zip, $city, $state, $country) {
57
+        $out = "";
58
+
59
+        if (isset($country) && $street != "") {
60
+            $out = $country;
61
+        }
62
+
63
+        $zcs = "";
64
+        if (isset($zip) && $zip != "") {
65
+            $zcs = $zip;
66
+        }
67
+        if (isset($city) && $city != "") {
68
+            $zcs .= (($zcs) ? " " : "") . $city;
69
+        }
70
+        if (isset($state) && $state != "") {
71
+            $zcs .= (($zcs) ? " " : "") . $state;
72
+        }
73
+        if ($zcs) {
74
+            $out = $zcs . "\r\n" . $out;
75
+        }
76
+
77
+        if (isset($street) && $street != "") {
78
+            $out = $street . (($out) ? "\r\n\r\n" . $out : "");
79
+        }
80
+
81
+        return ($out) ? $out : null;
82
+    }
83
+
84
+    /**
85
+     * Build the fileas string from the components according to the configuration.
86
+     *
87
+     * @param string $lastname
88
+     * @param string $firstname
89
+     * @param string $middlename
90
+     * @param string $company
91
+     *
92
+     * @return string fileas
93
+     */
94
+    public static function BuildFileAs($lastname = "", $firstname = "", $middlename = "", $company = "") {
95
+        if (defined('FILEAS_ORDER')) {
96
+            $fileas = $lastfirst = $firstlast = "";
97
+            $names = trim($firstname . " " . $middlename);
98
+            $lastname = trim($lastname);
99
+            $company = trim($company);
100
+
101
+            // lastfirst is "lastname, firstname middlename"
102
+            // firstlast is "firstname middlename lastname"
103
+            if (strlen($lastname) > 0) {
104
+                $lastfirst = $lastname;
105
+                if (strlen($names) > 0) {
106
+                    $lastfirst .= ", {$names}";
107
+                    $firstlast = "{$names} {$lastname}";
108
+                }
109
+                else {
110
+                    $firstlast = $lastname;
111
+                }
112
+            }
113
+            elseif (strlen($names) > 0) {
114
+                $lastfirst = $firstlast = $names;
115
+            }
116
+
117
+            // if fileas with a company is selected
118
+            // but company is empty then it will
119
+            // fallback to firstlast or lastfirst
120
+            // (depending on which is selected for company)
121
+            switch (FILEAS_ORDER) {
122
+                case SYNC_FILEAS_COMPANYONLY:
123
+                    if (strlen($company) > 0) {
124
+                        $fileas = $company;
125
+                    }
126
+                    elseif (strlen($firstlast) > 0) {
127
+                        $fileas = $lastfirst;
128
+                    }
129
+                    break;
130
+
131
+                case SYNC_FILEAS_COMPANYLAST:
132
+                    if (strlen($company) > 0) {
133
+                        $fileas = $company;
134
+                        if (strlen($lastfirst) > 0) {
135
+                            $fileas .= "({$lastfirst})";
136
+                        }
137
+                    }
138
+                    elseif (strlen($lastfirst) > 0) {
139
+                        $fileas = $lastfirst;
140
+                    }
141
+                    break;
142
+
143
+                case SYNC_FILEAS_COMPANYFIRST:
144
+                    if (strlen($company) > 0) {
145
+                        $fileas = $company;
146
+                        if (strlen($firstlast) > 0) {
147
+                            $fileas .= " ({$firstlast})";
148
+                        }
149
+                    }
150
+                    elseif (strlen($firstlast) > 0) {
151
+                        $fileas = $firstlast;
152
+                    }
153
+                    break;
154
+
155
+                case SYNC_FILEAS_FIRSTCOMPANY:
156
+                    if (strlen($firstlast) > 0) {
157
+                        $fileas = $firstlast;
158
+                        if (strlen($company) > 0) {
159
+                            $fileas .= " ({$company})";
160
+                        }
161
+                    }
162
+                    elseif (strlen($company) > 0) {
163
+                        $fileas = $company;
164
+                    }
165
+                    break;
166
+
167
+                case SYNC_FILEAS_LASTCOMPANY:
168
+                    if (strlen($lastfirst) > 0) {
169
+                        $fileas = $lastfirst;
170
+                        if (strlen($company) > 0) {
171
+                            $fileas .= " ({$company})";
172
+                        }
173
+                    }
174
+                    elseif (strlen($company) > 0) {
175
+                        $fileas = $company;
176
+                    }
177
+                    break;
178
+
179
+                case SYNC_FILEAS_LASTFIRST:
180
+                    if (strlen($lastfirst) > 0) {
181
+                        $fileas = $lastfirst;
182
+                    }
183
+                    break;
184
+
185
+                default:
186
+                    $fileas = $firstlast;
187
+                    break;
188
+            }
189
+            if (strlen($fileas) == 0) {
190
+                SLog::Write(LOGLEVEL_DEBUG, "Fileas is empty.");
191
+            }
192
+
193
+            return $fileas;
194
+        }
195
+        SLog::Write(LOGLEVEL_DEBUG, "FILEAS_ORDER not defined. Add it to your config.php.");
196
+
197
+        return null;
198
+    }
199
+
200
+    /**
201
+     * Checks if the PHP-MAPI extension is available and in a requested version.
202
+     *
203
+     * @param string $version the version to be checked ("6.30.10-18495", parts or build number)
204
+     *
205
+     * @return bool installed version is superior to the checked string
206
+     */
207
+    public static function CheckMapiExtVersion($version = "") {
208
+        if (!extension_loaded("mapi")) {
209
+            return false;
210
+        }
211
+        // compare build number if requested
212
+        if (preg_match('/^\d+$/', $version) && strlen($version) > 3) {
213
+            $vs = preg_split('/-/', phpversion("mapi"));
214
+
215
+            return $version <= $vs[1];
216
+        }
217
+        if (version_compare(phpversion("mapi"), $version) == -1) {
218
+            return false;
219
+        }
220
+
221
+        return true;
222
+    }
223
+
224
+    /**
225
+     * Parses and returns an ecoded vCal-Uid from an OL compatible GlobalObjectID.
226
+     *
227
+     * @param string $olUid an OL compatible GlobalObjectID
228
+     *
229
+     * @return string the vCal-Uid if available in the olUid, else the original olUid as HEX
230
+     */
231
+    public static function GetICalUidFromOLUid($olUid) {
232
+        // check if "vCal-Uid" is somewhere in outlookid case-insensitive
233
+        $icalUid = stristr($olUid, "vCal-Uid");
234
+        if ($icalUid !== false) {
235
+            // get the length of the ical id - go back 4 position from where "vCal-Uid" was found
236
+            $begin = unpack("V", substr($olUid, strlen($icalUid) * (-1) - 4, 4));
237
+            // remove "vCal-Uid" and packed "1" and use the ical id length
238
+            return substr($icalUid, 12, ($begin[1] - 13));
239
+        }
240
+
241
+        return strtoupper(bin2hex($olUid));
242
+    }
243
+
244
+    /**
245
+     * Checks the given UID if it is an OL compatible GlobalObjectID
246
+     * If not, the given UID is encoded inside the GlobalObjectID.
247
+     *
248
+     * @param string $icalUid an appointment uid as HEX
249
+     *
250
+     * @return string an OL compatible GlobalObjectID
251
+     */
252
+    public static function GetOLUidFromICalUid($icalUid) {
253
+        if (strlen($icalUid) <= 64) {
254
+            $len = 13 + strlen($icalUid);
255
+            $OLUid = pack("V", $len);
256
+            $OLUid .= "vCal-Uid";
257
+            $OLUid .= pack("V", 1);
258
+            $OLUid .= $icalUid;
259
+
260
+            return hex2bin("040000008200E00074C5B7101A82E0080000000000000000000000000000000000000000" . bin2hex($OLUid) . "00");
261
+        }
262
+
263
+        return hex2bin($icalUid);
264
+    }
265
+
266
+    /**
267
+     * Extracts the basedate of the GlobalObjectID and the RecurStartTime.
268
+     *
269
+     * @param string $goid           OL compatible GlobalObjectID
270
+     * @param long   $recurStartTime
271
+     *
272
+     * @return long basedate
273
+     */
274
+    public static function ExtractBaseDate($goid, $recurStartTime) {
275
+        $hexbase = substr(bin2hex($goid), 32, 8);
276
+        $day = hexdec(substr($hexbase, 6, 2));
277
+        $month = hexdec(substr($hexbase, 4, 2));
278
+        $year = hexdec(substr($hexbase, 0, 4));
279
+
280
+        if ($day && $month && $year) {
281
+            $h = $recurStartTime >> 12;
282
+            $m = ($recurStartTime - $h * 4096) >> 6;
283
+            $s = $recurStartTime - $h * 4096 - $m * 64;
284
+
285
+            return gmmktime($h, $m, $s, $month, $day, $year);
286
+        }
287
+
288
+        return false;
289
+    }
290
+
291
+    /**
292
+     * Converts SYNC_FILTERTYPE into a timestamp.
293
+     *
294
+     * @param int $filtertype Filtertype
295
+     *
296
+     * @return long
297
+     */
298
+    public static function GetCutOffDate($filtertype) {
299
+        $back = Utils::GetFiltertypeInterval($filtertype);
300
+
301
+        if ($back === false) {
302
+            return 0; // unlimited
303
+        }
304
+
305
+        return time() - $back;
306
+    }
307
+
308
+    /**
309
+     * Returns the interval indicated by the filtertype.
310
+     *
311
+     * @param int $filtertype
312
+     *
313
+     * @return bool|long returns false on invalid filtertype
314
+     */
315
+    public static function GetFiltertypeInterval($filtertype) {
316
+        $back = false;
317
+
318
+        switch ($filtertype) {
319
+            case SYNC_FILTERTYPE_1DAY:
320
+                $back = 60 * 60 * 24;
321
+                break;
322
+
323
+            case SYNC_FILTERTYPE_3DAYS:
324
+                $back = 60 * 60 * 24 * 3;
325
+                break;
326
+
327
+            case SYNC_FILTERTYPE_1WEEK:
328
+                $back = 60 * 60 * 24 * 7;
329
+                break;
330
+
331
+            case SYNC_FILTERTYPE_2WEEKS:
332
+                $back = 60 * 60 * 24 * 14;
333
+                break;
334
+
335
+            case SYNC_FILTERTYPE_1MONTH:
336
+                $back = 60 * 60 * 24 * 31;
337
+                break;
338
+
339
+            case SYNC_FILTERTYPE_3MONTHS:
340
+                $back = 60 * 60 * 24 * 31 * 3;
341
+                break;
342
+
343
+            case SYNC_FILTERTYPE_6MONTHS:
344
+                $back = 60 * 60 * 24 * 31 * 6;
345
+                break;
346
+
347
+            default:
348
+                $back = false;
349
+        }
350
+
351
+        return $back;
352
+    }
353
+
354
+    /**
355
+     * Converts SYNC_TRUNCATION into bytes.
356
+     *
357
+     * @param int       SYNC_TRUNCATION
358
+     * @param mixed $truncation
359
+     *
360
+     * @return long
361
+     */
362
+    public static function GetTruncSize($truncation) {
363
+        switch ($truncation) {
364
+            case SYNC_TRUNCATION_HEADERS:
365
+                return 0;
366
+
367
+            case SYNC_TRUNCATION_512B:
368
+                return 512;
369
+
370
+            case SYNC_TRUNCATION_1K:
371
+                return 1024;
372
+
373
+            case SYNC_TRUNCATION_2K:
374
+                return 2 * 1024;
375
+
376
+            case SYNC_TRUNCATION_5K:
377
+                return 5 * 1024;
378
+
379
+            case SYNC_TRUNCATION_10K:
380
+                return 10 * 1024;
381
+
382
+            case SYNC_TRUNCATION_20K:
383
+                return 20 * 1024;
384
+
385
+            case SYNC_TRUNCATION_50K:
386
+                return 50 * 1024;
387
+
388
+            case SYNC_TRUNCATION_100K:
389
+                return 100 * 1024;
390
+
391
+            case SYNC_TRUNCATION_ALL:
392
+                return 1024 * 1024; // We'll limit to 1MB anyway
393
+
394
+            default:
395
+                return 1024; // Default to 1Kb
396
+        }
397
+    }
398
+
399
+    /**
400
+     * Truncate an UTF-8 encoded string correctly.
401
+     *
402
+     * If it's not possible to truncate properly, an empty string is returned
403
+     *
404
+     * @param string $string   the string
405
+     * @param string $length   position where string should be cut
406
+     * @param bool   $htmlsafe doesn't cut html tags in half, doesn't ensure correct html - default: false
407
+     *
408
+     * @return string truncated string
409
+     */
410
+    public static function Utf8_truncate($string, $length, $htmlsafe = false) {
411
+        // make sure length is always an integer
412
+        $length = (int) $length;
413
+
414
+        // if the input string is shorter then the trunction, make sure it's valid UTF-8!
415
+        if (strlen($string) <= $length) {
416
+            $length = strlen($string) - 1;
417
+        }
418
+
419
+        // The intent is not to cut HTML tags in half which causes displaying issues (see ZP-1240).
420
+        // The used method just tries to cut outside of tags, without checking tag validity and closing tags.
421
+        if ($htmlsafe) {
422
+            $offset = 0 - strlen($string) + $length;
423
+            $validPos = strrpos($string, "<", $offset);
424
+            if ($validPos > strrpos($string, ">", $offset)) {
425
+                $length = $validPos;
426
+            }
427
+        }
428
+
429
+        while ($length >= 0) {
430
+            if ((ord($string[$length]) < 0x80) || (ord($string[$length]) >= 0xC0)) {
431
+                return substr($string, 0, $length);
432
+            }
433
+            --$length;
434
+        }
435
+
436
+        return "";
437
+    }
438
+
439
+    /**
440
+     * Indicates if the specified folder type is a system folder.
441
+     *
442
+     * @param int $foldertype
443
+     *
444
+     * @return bool
445
+     */
446
+    public static function IsSystemFolder($foldertype) {
447
+        return (
448
+            $foldertype == SYNC_FOLDER_TYPE_INBOX ||
449
+            $foldertype == SYNC_FOLDER_TYPE_DRAFTS ||
450
+            $foldertype == SYNC_FOLDER_TYPE_WASTEBASKET ||
451
+            $foldertype == SYNC_FOLDER_TYPE_SENTMAIL ||
452
+            $foldertype == SYNC_FOLDER_TYPE_OUTBOX ||
453
+            $foldertype == SYNC_FOLDER_TYPE_TASK ||
454
+            $foldertype == SYNC_FOLDER_TYPE_APPOINTMENT ||
455
+            $foldertype == SYNC_FOLDER_TYPE_CONTACT ||
456
+            $foldertype == SYNC_FOLDER_TYPE_NOTE ||
457
+            $foldertype == SYNC_FOLDER_TYPE_JOURNAL
458
+            ) ? true : false;
459
+    }
460
+
461
+    /**
462
+     * Checks for valid email addresses
463
+     * The used regex actually only checks if a valid email address is part of the submitted string
464
+     * it also returns true for the mailbox format, but this is not checked explicitly.
465
+     *
466
+     * @param string $email address to be checked
467
+     *
468
+     * @return bool
469
+     */
470
+    public static function CheckEmail($email) {
471
+        return strpos($email, '@') !== false ? true : false;
472
+    }
473
+
474
+    /**
475
+     * Checks if a string is base64 encoded.
476
+     *
477
+     * @param string $string the string to be checked
478
+     *
479
+     * @return bool
480
+     */
481
+    public static function IsBase64String($string) {
482
+        return (bool) preg_match("#^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+/]{4})?$#", $string);
483
+    }
484 484
 
485
-	/**
486
-	 * Returns a command string for a given command code.
487
-	 *
488
-	 * @param int $code
489
-	 *
490
-	 * @return string or false if code is unknown
491
-	 */
492
-	public static function GetCommandFromCode($code) {
493
-		switch ($code) {
494
-			case GSync::COMMAND_SYNC:                 return 'Sync';
485
+    /**
486
+     * Returns a command string for a given command code.
487
+     *
488
+     * @param int $code
489
+     *
490
+     * @return string or false if code is unknown
491
+     */
492
+    public static function GetCommandFromCode($code) {
493
+        switch ($code) {
494
+            case GSync::COMMAND_SYNC:                 return 'Sync';
495 495
 
496
-			case GSync::COMMAND_SENDMAIL:             return 'SendMail';
496
+            case GSync::COMMAND_SENDMAIL:             return 'SendMail';
497 497
 
498
-			case GSync::COMMAND_SMARTFORWARD:         return 'SmartForward';
498
+            case GSync::COMMAND_SMARTFORWARD:         return 'SmartForward';
499 499
 
500
-			case GSync::COMMAND_SMARTREPLY:           return 'SmartReply';
500
+            case GSync::COMMAND_SMARTREPLY:           return 'SmartReply';
501 501
 
502
-			case GSync::COMMAND_GETATTACHMENT:        return 'GetAttachment';
502
+            case GSync::COMMAND_GETATTACHMENT:        return 'GetAttachment';
503 503
 
504
-			case GSync::COMMAND_FOLDERSYNC:           return 'FolderSync';
504
+            case GSync::COMMAND_FOLDERSYNC:           return 'FolderSync';
505 505
 
506
-			case GSync::COMMAND_FOLDERCREATE:         return 'FolderCreate';
506
+            case GSync::COMMAND_FOLDERCREATE:         return 'FolderCreate';
507 507
 
508
-			case GSync::COMMAND_FOLDERDELETE:         return 'FolderDelete';
508
+            case GSync::COMMAND_FOLDERDELETE:         return 'FolderDelete';
509 509
 
510
-			case GSync::COMMAND_FOLDERUPDATE:         return 'FolderUpdate';
510
+            case GSync::COMMAND_FOLDERUPDATE:         return 'FolderUpdate';
511 511
 
512
-			case GSync::COMMAND_MOVEITEMS:            return 'MoveItems';
512
+            case GSync::COMMAND_MOVEITEMS:            return 'MoveItems';
513 513
 
514
-			case GSync::COMMAND_GETITEMESTIMATE:      return 'GetItemEstimate';
514
+            case GSync::COMMAND_GETITEMESTIMATE:      return 'GetItemEstimate';
515 515
 
516
-			case GSync::COMMAND_MEETINGRESPONSE:      return 'MeetingResponse';
516
+            case GSync::COMMAND_MEETINGRESPONSE:      return 'MeetingResponse';
517 517
 
518
-			case GSync::COMMAND_SEARCH:               return 'Search';
518
+            case GSync::COMMAND_SEARCH:               return 'Search';
519 519
 
520
-			case GSync::COMMAND_SETTINGS:             return 'Settings';
520
+            case GSync::COMMAND_SETTINGS:             return 'Settings';
521 521
 
522
-			case GSync::COMMAND_PING:                 return 'Ping';
522
+            case GSync::COMMAND_PING:                 return 'Ping';
523 523
 
524
-			case GSync::COMMAND_ITEMOPERATIONS:       return 'ItemOperations';
524
+            case GSync::COMMAND_ITEMOPERATIONS:       return 'ItemOperations';
525 525
 
526
-			case GSync::COMMAND_PROVISION:            return 'Provision';
526
+            case GSync::COMMAND_PROVISION:            return 'Provision';
527 527
 
528
-			case GSync::COMMAND_RESOLVERECIPIENTS:    return 'ResolveRecipients';
528
+            case GSync::COMMAND_RESOLVERECIPIENTS:    return 'ResolveRecipients';
529 529
 
530
-			case GSync::COMMAND_VALIDATECERT:         return 'ValidateCert';
531
-			// Deprecated commands
532
-			case GSync::COMMAND_GETHIERARCHY:         return 'GetHierarchy';
530
+            case GSync::COMMAND_VALIDATECERT:         return 'ValidateCert';
531
+            // Deprecated commands
532
+            case GSync::COMMAND_GETHIERARCHY:         return 'GetHierarchy';
533 533
 
534
-			case GSync::COMMAND_CREATECOLLECTION:     return 'CreateCollection';
534
+            case GSync::COMMAND_CREATECOLLECTION:     return 'CreateCollection';
535 535
 
536
-			case GSync::COMMAND_DELETECOLLECTION:     return 'DeleteCollection';
536
+            case GSync::COMMAND_DELETECOLLECTION:     return 'DeleteCollection';
537 537
 
538
-			case GSync::COMMAND_MOVECOLLECTION:       return 'MoveCollection';
538
+            case GSync::COMMAND_MOVECOLLECTION:       return 'MoveCollection';
539 539
 
540
-			case GSync::COMMAND_NOTIFY:               return 'Notify';
541
-		}
540
+            case GSync::COMMAND_NOTIFY:               return 'Notify';
541
+        }
542 542
 
543
-		return false;
544
-	}
543
+        return false;
544
+    }
545 545
 
546
-	/**
547
-	 * Returns a command code for a given command.
548
-	 *
549
-	 * @param string $command
550
-	 *
551
-	 * @return int or false if command is unknown
552
-	 */
553
-	public static function GetCodeFromCommand($command) {
554
-		switch ($command) {
555
-			case 'Sync':                 return GSync::COMMAND_SYNC;
546
+    /**
547
+     * Returns a command code for a given command.
548
+     *
549
+     * @param string $command
550
+     *
551
+     * @return int or false if command is unknown
552
+     */
553
+    public static function GetCodeFromCommand($command) {
554
+        switch ($command) {
555
+            case 'Sync':                 return GSync::COMMAND_SYNC;
556 556
 
557
-			case 'SendMail':             return GSync::COMMAND_SENDMAIL;
557
+            case 'SendMail':             return GSync::COMMAND_SENDMAIL;
558 558
 
559
-			case 'SmartForward':         return GSync::COMMAND_SMARTFORWARD;
559
+            case 'SmartForward':         return GSync::COMMAND_SMARTFORWARD;
560 560
 
561
-			case 'SmartReply':           return GSync::COMMAND_SMARTREPLY;
561
+            case 'SmartReply':           return GSync::COMMAND_SMARTREPLY;
562 562
 
563
-			case 'GetAttachment':        return GSync::COMMAND_GETATTACHMENT;
563
+            case 'GetAttachment':        return GSync::COMMAND_GETATTACHMENT;
564 564
 
565
-			case 'FolderSync':           return GSync::COMMAND_FOLDERSYNC;
565
+            case 'FolderSync':           return GSync::COMMAND_FOLDERSYNC;
566 566
 
567
-			case 'FolderCreate':         return GSync::COMMAND_FOLDERCREATE;
567
+            case 'FolderCreate':         return GSync::COMMAND_FOLDERCREATE;
568 568
 
569
-			case 'FolderDelete':         return GSync::COMMAND_FOLDERDELETE;
569
+            case 'FolderDelete':         return GSync::COMMAND_FOLDERDELETE;
570 570
 
571
-			case 'FolderUpdate':         return GSync::COMMAND_FOLDERUPDATE;
571
+            case 'FolderUpdate':         return GSync::COMMAND_FOLDERUPDATE;
572 572
 
573
-			case 'MoveItems':            return GSync::COMMAND_MOVEITEMS;
573
+            case 'MoveItems':            return GSync::COMMAND_MOVEITEMS;
574 574
 
575
-			case 'GetItemEstimate':      return GSync::COMMAND_GETITEMESTIMATE;
575
+            case 'GetItemEstimate':      return GSync::COMMAND_GETITEMESTIMATE;
576 576
 
577
-			case 'MeetingResponse':      return GSync::COMMAND_MEETINGRESPONSE;
577
+            case 'MeetingResponse':      return GSync::COMMAND_MEETINGRESPONSE;
578 578
 
579
-			case 'Search':               return GSync::COMMAND_SEARCH;
579
+            case 'Search':               return GSync::COMMAND_SEARCH;
580 580
 
581
-			case 'Settings':             return GSync::COMMAND_SETTINGS;
581
+            case 'Settings':             return GSync::COMMAND_SETTINGS;
582 582
 
583
-			case 'Ping':                 return GSync::COMMAND_PING;
583
+            case 'Ping':                 return GSync::COMMAND_PING;
584 584
 
585
-			case 'ItemOperations':       return GSync::COMMAND_ITEMOPERATIONS;
585
+            case 'ItemOperations':       return GSync::COMMAND_ITEMOPERATIONS;
586 586
 
587
-			case 'Provision':            return GSync::COMMAND_PROVISION;
587
+            case 'Provision':            return GSync::COMMAND_PROVISION;
588 588
 
589
-			case 'ResolveRecipients':    return GSync::COMMAND_RESOLVERECIPIENTS;
589
+            case 'ResolveRecipients':    return GSync::COMMAND_RESOLVERECIPIENTS;
590 590
 
591
-			case 'ValidateCert':         return GSync::COMMAND_VALIDATECERT;
592
-			// Deprecated commands
593
-			case 'GetHierarchy':         return GSync::COMMAND_GETHIERARCHY;
591
+            case 'ValidateCert':         return GSync::COMMAND_VALIDATECERT;
592
+            // Deprecated commands
593
+            case 'GetHierarchy':         return GSync::COMMAND_GETHIERARCHY;
594 594
 
595
-			case 'CreateCollection':     return GSync::COMMAND_CREATECOLLECTION;
595
+            case 'CreateCollection':     return GSync::COMMAND_CREATECOLLECTION;
596 596
 
597
-			case 'DeleteCollection':     return GSync::COMMAND_DELETECOLLECTION;
597
+            case 'DeleteCollection':     return GSync::COMMAND_DELETECOLLECTION;
598 598
 
599
-			case 'MoveCollection':       return GSync::COMMAND_MOVECOLLECTION;
600
-
601
-			case 'Notify':               return GSync::COMMAND_NOTIFY;
602
-		}
603
-
604
-		return false;
605
-	}
606
-
607
-	/**
608
-	 * Normalize the given timestamp to the start of the day.
609
-	 *
610
-	 * @param long $timestamp
611
-	 *
612
-	 * @return long
613
-	 */
614
-	public static function getDayStartOfTimestamp($timestamp) {
615
-		return $timestamp - ($timestamp % (60 * 60 * 24));
616
-	}
617
-
618
-	/**
619
-	 * Returns a formatted string output from an optional timestamp.
620
-	 * If no timestamp is sent, NOW is used.
621
-	 *
622
-	 * @param long $timestamp
623
-	 *
624
-	 * @return string
625
-	 */
626
-	public static function GetFormattedTime($timestamp = false) {
627
-		if (!$timestamp) {
628
-			return @strftime("%d/%m/%Y %H:%M:%S");
629
-		}
630
-
631
-		return @strftime("%d/%m/%Y %H:%M:%S", $timestamp);
632
-	}
633
-
634
-	/**
635
-	 * Get charset name from a codepage.
636
-	 *
637
-	 * @see http://msdn.microsoft.com/en-us/library/dd317756(VS.85).aspx
638
-	 *
639
-	 * Table taken from common/codepage.cpp
640
-	 *
641
-	 * @param int codepage Codepage
642
-	 * @param mixed $codepage
643
-	 *
644
-	 * @return string iconv-compatible charset name
645
-	 */
646
-	public static function GetCodepageCharset($codepage) {
647
-		$codepages = [
648
-			20106 => "DIN_66003",
649
-			20108 => "NS_4551-1",
650
-			20107 => "SEN_850200_B",
651
-			950 => "big5",
652
-			50221 => "csISO2022JP",
653
-			51932 => "euc-jp",
654
-			51936 => "euc-cn",
655
-			51949 => "euc-kr",
656
-			949 => "euc-kr",
657
-			936 => "gb18030",
658
-			52936 => "csgb2312",
659
-			852 => "ibm852",
660
-			866 => "ibm866",
661
-			50220 => "iso-2022-jp",
662
-			50222 => "iso-2022-jp",
663
-			50225 => "iso-2022-kr",
664
-			1252 => "windows-1252",
665
-			28591 => "iso-8859-1",
666
-			28592 => "iso-8859-2",
667
-			28593 => "iso-8859-3",
668
-			28594 => "iso-8859-4",
669
-			28595 => "iso-8859-5",
670
-			28596 => "iso-8859-6",
671
-			28597 => "iso-8859-7",
672
-			28598 => "iso-8859-8",
673
-			28599 => "iso-8859-9",
674
-			28603 => "iso-8859-13",
675
-			28605 => "iso-8859-15",
676
-			20866 => "koi8-r",
677
-			21866 => "koi8-u",
678
-			932 => "shift-jis",
679
-			1200 => "unicode",
680
-			1201 => "unicodebig",
681
-			65000 => "utf-7",
682
-			65001 => "utf-8",
683
-			1250 => "windows-1250",
684
-			1251 => "windows-1251",
685
-			1253 => "windows-1253",
686
-			1254 => "windows-1254",
687
-			1255 => "windows-1255",
688
-			1256 => "windows-1256",
689
-			1257 => "windows-1257",
690
-			1258 => "windows-1258",
691
-			874 => "windows-874",
692
-			20127 => "us-ascii",
693
-		];
694
-
695
-		if (isset($codepages[$codepage])) {
696
-			return $codepages[$codepage];
697
-		}
698
-		// Defaulting to iso-8859-15 since it is more likely for someone to make a mistake in the codepage
699
-		// when using west-european charsets then when using other charsets since utf-8 is binary compatible
700
-		// with the bottom 7 bits of west-european
701
-		return "iso-8859-15";
702
-	}
703
-
704
-	/**
705
-	 * Converts a string encoded with codepage into an UTF-8 string.
706
-	 *
707
-	 * @param int    $codepage
708
-	 * @param string $string
709
-	 *
710
-	 * @return string
711
-	 */
712
-	public static function ConvertCodepageStringToUtf8($codepage, $string) {
713
-		if (function_exists("iconv")) {
714
-			$charset = self::GetCodepageCharset($codepage);
715
-
716
-			return iconv($charset, "utf-8", $string);
717
-		}
718
-
719
-		SLog::Write(LOGLEVEL_WARN, "Utils::ConvertCodepageStringToUtf8() 'iconv' is not available. Charset conversion skipped.");
720
-
721
-		return $string;
722
-	}
723
-
724
-	/**
725
-	 * Converts a string to another charset.
726
-	 *
727
-	 * @param int    $in
728
-	 * @param int    $out
729
-	 * @param string $string
730
-	 *
731
-	 * @return string
732
-	 */
733
-	public static function ConvertCodepage($in, $out, $string) {
734
-		// do nothing if both charsets are the same
735
-		if ($in == $out) {
736
-			return $string;
737
-		}
738
-
739
-		if (function_exists("iconv")) {
740
-			$inCharset = self::GetCodepageCharset($in);
741
-			$outCharset = self::GetCodepageCharset($out);
742
-
743
-			return iconv($inCharset, $outCharset, $string);
744
-		}
745
-
746
-		SLog::Write(LOGLEVEL_WARN, "Utils::ConvertCodepage() 'iconv' is not available. Charset conversion skipped.");
747
-
748
-		return $string;
749
-	}
750
-
751
-	/**
752
-	 * Returns the best match of preferred body preference types.
753
-	 *
754
-	 * @param array $bpTypes
755
-	 *
756
-	 * @return int
757
-	 */
758
-	public static function GetBodyPreferenceBestMatch($bpTypes) {
759
-		if ($bpTypes === false) {
760
-			return SYNC_BODYPREFERENCE_PLAIN;
761
-		}
762
-		// The best choice is RTF, then HTML and then MIME in order to save bandwidth
763
-		// because MIME is a complete message including the headers and attachments
764
-		if (in_array(SYNC_BODYPREFERENCE_RTF, $bpTypes)) {
765
-			return SYNC_BODYPREFERENCE_RTF;
766
-		}
767
-		if (in_array(SYNC_BODYPREFERENCE_HTML, $bpTypes)) {
768
-			return SYNC_BODYPREFERENCE_HTML;
769
-		}
770
-		if (in_array(SYNC_BODYPREFERENCE_MIME, $bpTypes)) {
771
-			return SYNC_BODYPREFERENCE_MIME;
772
-		}
773
-
774
-		return SYNC_BODYPREFERENCE_PLAIN;
775
-	}
776
-
777
-	/**
778
-	 * Checks if a file has the same owner and group as the parent directory.
779
-	 * If not, owner and group are fixed (being updated to the owner/group of the directory).
780
-	 * If the given file is a special file (i.g., /dev/null, fifo), nothing is changed.
781
-	 * Function code contributed by Robert Scheck aka rsc.
782
-	 *
783
-	 * @param string $file
784
-	 *
785
-	 * @return bool
786
-	 */
787
-	public static function FixFileOwner($file) {
788
-		if (!function_exists('posix_getuid')) {
789
-			SLog::Write(LOGLEVEL_DEBUG, "Utils::FixeFileOwner(): Posix subsystem not available, skipping.");
790
-
791
-			return false;
792
-		}
793
-		if (posix_getuid() == 0 && is_file($file)) {
794
-			$dir = dirname($file);
795
-			$perm_dir = stat($dir);
796
-			$perm_file = stat($file);
797
-
798
-			if ($perm_file['uid'] == 0 && $perm_dir['uid'] == 0 && $perm_dir['gid'] == 0) {
799
-				unlink($file);
800
-
801
-				throw new FatalException("FixFileOwner: {$dir} must be owned by the nginx/apache/php user instead of root for debian based systems and by root:grosync for RHEL-based systems");
802
-			}
803
-
804
-			if ($perm_dir['uid'] !== $perm_file['uid'] || $perm_dir['gid'] !== $perm_file['gid']) {
805
-				chown($file, $perm_dir['uid']);
806
-				chgrp($file, $perm_dir['gid']);
807
-				chmod($file, 0664);
808
-			}
809
-		}
810
-
811
-		return true;
812
-	}
813
-
814
-	/**
815
-	 * Returns AS-style LastVerbExecuted value from the server value.
816
-	 *
817
-	 * @param int $verb
818
-	 *
819
-	 * @return int
820
-	 */
821
-	public static function GetLastVerbExecuted($verb) {
822
-		switch ($verb) {
823
-			case NOTEIVERB_REPLYTOSENDER:   return AS_REPLYTOSENDER;
824
-
825
-			case NOTEIVERB_REPLYTOALL:      return AS_REPLYTOALL;
826
-
827
-			case NOTEIVERB_FORWARD:         return AS_FORWARD;
828
-		}
829
-
830
-		return 0;
831
-	}
832
-
833
-	/**
834
-	 * Returns the local part from email address.
835
-	 *
836
-	 * @param string $email
837
-	 *
838
-	 * @return string
839
-	 */
840
-	public static function GetLocalPartFromEmail($email) {
841
-		$pos = strpos($email, '@');
842
-		if ($pos === false) {
843
-			return $email;
844
-		}
845
-
846
-		return substr($email, 0, $pos);
847
-	}
848
-
849
-	/**
850
-	 * Format bytes to a more human readable value.
851
-	 *
852
-	 * @param int $bytes
853
-	 * @param int $precision
854
-	 *
855
-	 * @return string|void
856
-	 */
857
-	public static function FormatBytes($bytes, $precision = 2) {
858
-		if ($bytes <= 0) {
859
-			return '0 B';
860
-		}
861
-
862
-		$units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB'];
863
-		$base = log($bytes, 1024);
864
-		$fBase = floor($base);
865
-		$pow = pow(1024, $base - $fBase);
866
-
867
-		return sprintf("%.{$precision}f %s", $pow, $units[$fBase]);
868
-	}
869
-
870
-	/**
871
-	 * Returns folder origin identifier from its id.
872
-	 *
873
-	 * @param string $folderid
874
-	 *
875
-	 * @return bool|string matches values of DeviceManager::FLD_ORIGIN_*
876
-	 */
877
-	public static function GetFolderOriginFromId($folderid) {
878
-		$origin = substr($folderid, 0, 1);
879
-
880
-		switch ($origin) {
881
-			case DeviceManager::FLD_ORIGIN_CONFIG:
882
-			case DeviceManager::FLD_ORIGIN_GAB:
883
-			case DeviceManager::FLD_ORIGIN_SHARED:
884
-			case DeviceManager::FLD_ORIGIN_USER:
885
-			case DeviceManager::FLD_ORIGIN_IMPERSONATED:
886
-				return $origin;
887
-		}
888
-		SLog::Write(LOGLEVEL_WARN, sprintf("Utils->GetFolderOriginFromId(): Unknown folder origin for folder with id '%s'", $folderid));
889
-
890
-		return false;
891
-	}
892
-
893
-	/**
894
-	 * Returns folder origin as string from its id.
895
-	 *
896
-	 * @param string $folderid
897
-	 *
898
-	 * @return string
899
-	 */
900
-	public static function GetFolderOriginStringFromId($folderid) {
901
-		$origin = substr($folderid, 0, 1);
902
-
903
-		switch ($origin) {
904
-			case DeviceManager::FLD_ORIGIN_CONFIG:
905
-				return 'configured';
906
-
907
-			case DeviceManager::FLD_ORIGIN_GAB:
908
-				return 'GAB';
909
-
910
-			case DeviceManager::FLD_ORIGIN_SHARED:
911
-				return 'shared';
912
-
913
-			case DeviceManager::FLD_ORIGIN_USER:
914
-				return 'user';
915
-
916
-			case DeviceManager::FLD_ORIGIN_IMPERSONATED:
917
-				return 'impersonated';
918
-		}
919
-		SLog::Write(LOGLEVEL_WARN, sprintf("Utils->GetFolderOriginStringFromId(): Unknown folder origin for folder with id '%s'", $folderid));
920
-
921
-		return 'unknown';
922
-	}
923
-
924
-	/**
925
-	 * Splits the id into folder id and message id parts. A colon in the $id indicates
926
-	 * that the id has folderid:messageid format.
927
-	 *
928
-	 * @param string $id
929
-	 *
930
-	 * @return array
931
-	 */
932
-	public static function SplitMessageId($id) {
933
-		if (strpos($id, ':') !== false) {
934
-			return explode(':', $id);
935
-		}
936
-
937
-		return [null, $id];
938
-	}
939
-
940
-	/**
941
-	 * Converts a string freebusy type into a numeric status.
942
-	 *
943
-	 * @param string $fbType
944
-	 *
945
-	 * @return int
946
-	 */
947
-	public static function GetFbStatusFromType($fbType) {
948
-		switch ($fbType) {
949
-			case 'Free':
950
-				return fbFree;
951
-
952
-			case 'Tentative':
953
-				return fbTentative;
954
-
955
-			case 'Busy':
956
-				return fbBusy;
957
-
958
-			case 'OOF':
959
-				return fbOutOfOffice;
960
-		}
961
-		SLog::Write(LOGLEVEL_WARN, sprintf("Utils->GetFbStatusFromType(): Unknown free busy type '%s'", $fbType));
962
-
963
-		return fbNoData;
964
-	}
599
+            case 'MoveCollection':       return GSync::COMMAND_MOVECOLLECTION;
600
+
601
+            case 'Notify':               return GSync::COMMAND_NOTIFY;
602
+        }
603
+
604
+        return false;
605
+    }
606
+
607
+    /**
608
+     * Normalize the given timestamp to the start of the day.
609
+     *
610
+     * @param long $timestamp
611
+     *
612
+     * @return long
613
+     */
614
+    public static function getDayStartOfTimestamp($timestamp) {
615
+        return $timestamp - ($timestamp % (60 * 60 * 24));
616
+    }
617
+
618
+    /**
619
+     * Returns a formatted string output from an optional timestamp.
620
+     * If no timestamp is sent, NOW is used.
621
+     *
622
+     * @param long $timestamp
623
+     *
624
+     * @return string
625
+     */
626
+    public static function GetFormattedTime($timestamp = false) {
627
+        if (!$timestamp) {
628
+            return @strftime("%d/%m/%Y %H:%M:%S");
629
+        }
630
+
631
+        return @strftime("%d/%m/%Y %H:%M:%S", $timestamp);
632
+    }
633
+
634
+    /**
635
+     * Get charset name from a codepage.
636
+     *
637
+     * @see http://msdn.microsoft.com/en-us/library/dd317756(VS.85).aspx
638
+     *
639
+     * Table taken from common/codepage.cpp
640
+     *
641
+     * @param int codepage Codepage
642
+     * @param mixed $codepage
643
+     *
644
+     * @return string iconv-compatible charset name
645
+     */
646
+    public static function GetCodepageCharset($codepage) {
647
+        $codepages = [
648
+            20106 => "DIN_66003",
649
+            20108 => "NS_4551-1",
650
+            20107 => "SEN_850200_B",
651
+            950 => "big5",
652
+            50221 => "csISO2022JP",
653
+            51932 => "euc-jp",
654
+            51936 => "euc-cn",
655
+            51949 => "euc-kr",
656
+            949 => "euc-kr",
657
+            936 => "gb18030",
658
+            52936 => "csgb2312",
659
+            852 => "ibm852",
660
+            866 => "ibm866",
661
+            50220 => "iso-2022-jp",
662
+            50222 => "iso-2022-jp",
663
+            50225 => "iso-2022-kr",
664
+            1252 => "windows-1252",
665
+            28591 => "iso-8859-1",
666
+            28592 => "iso-8859-2",
667
+            28593 => "iso-8859-3",
668
+            28594 => "iso-8859-4",
669
+            28595 => "iso-8859-5",
670
+            28596 => "iso-8859-6",
671
+            28597 => "iso-8859-7",
672
+            28598 => "iso-8859-8",
673
+            28599 => "iso-8859-9",
674
+            28603 => "iso-8859-13",
675
+            28605 => "iso-8859-15",
676
+            20866 => "koi8-r",
677
+            21866 => "koi8-u",
678
+            932 => "shift-jis",
679
+            1200 => "unicode",
680
+            1201 => "unicodebig",
681
+            65000 => "utf-7",
682
+            65001 => "utf-8",
683
+            1250 => "windows-1250",
684
+            1251 => "windows-1251",
685
+            1253 => "windows-1253",
686
+            1254 => "windows-1254",
687
+            1255 => "windows-1255",
688
+            1256 => "windows-1256",
689
+            1257 => "windows-1257",
690
+            1258 => "windows-1258",
691
+            874 => "windows-874",
692
+            20127 => "us-ascii",
693
+        ];
694
+
695
+        if (isset($codepages[$codepage])) {
696
+            return $codepages[$codepage];
697
+        }
698
+        // Defaulting to iso-8859-15 since it is more likely for someone to make a mistake in the codepage
699
+        // when using west-european charsets then when using other charsets since utf-8 is binary compatible
700
+        // with the bottom 7 bits of west-european
701
+        return "iso-8859-15";
702
+    }
703
+
704
+    /**
705
+     * Converts a string encoded with codepage into an UTF-8 string.
706
+     *
707
+     * @param int    $codepage
708
+     * @param string $string
709
+     *
710
+     * @return string
711
+     */
712
+    public static function ConvertCodepageStringToUtf8($codepage, $string) {
713
+        if (function_exists("iconv")) {
714
+            $charset = self::GetCodepageCharset($codepage);
715
+
716
+            return iconv($charset, "utf-8", $string);
717
+        }
718
+
719
+        SLog::Write(LOGLEVEL_WARN, "Utils::ConvertCodepageStringToUtf8() 'iconv' is not available. Charset conversion skipped.");
720
+
721
+        return $string;
722
+    }
723
+
724
+    /**
725
+     * Converts a string to another charset.
726
+     *
727
+     * @param int    $in
728
+     * @param int    $out
729
+     * @param string $string
730
+     *
731
+     * @return string
732
+     */
733
+    public static function ConvertCodepage($in, $out, $string) {
734
+        // do nothing if both charsets are the same
735
+        if ($in == $out) {
736
+            return $string;
737
+        }
738
+
739
+        if (function_exists("iconv")) {
740
+            $inCharset = self::GetCodepageCharset($in);
741
+            $outCharset = self::GetCodepageCharset($out);
742
+
743
+            return iconv($inCharset, $outCharset, $string);
744
+        }
745
+
746
+        SLog::Write(LOGLEVEL_WARN, "Utils::ConvertCodepage() 'iconv' is not available. Charset conversion skipped.");
747
+
748
+        return $string;
749
+    }
750
+
751
+    /**
752
+     * Returns the best match of preferred body preference types.
753
+     *
754
+     * @param array $bpTypes
755
+     *
756
+     * @return int
757
+     */
758
+    public static function GetBodyPreferenceBestMatch($bpTypes) {
759
+        if ($bpTypes === false) {
760
+            return SYNC_BODYPREFERENCE_PLAIN;
761
+        }
762
+        // The best choice is RTF, then HTML and then MIME in order to save bandwidth
763
+        // because MIME is a complete message including the headers and attachments
764
+        if (in_array(SYNC_BODYPREFERENCE_RTF, $bpTypes)) {
765
+            return SYNC_BODYPREFERENCE_RTF;
766
+        }
767
+        if (in_array(SYNC_BODYPREFERENCE_HTML, $bpTypes)) {
768
+            return SYNC_BODYPREFERENCE_HTML;
769
+        }
770
+        if (in_array(SYNC_BODYPREFERENCE_MIME, $bpTypes)) {
771
+            return SYNC_BODYPREFERENCE_MIME;
772
+        }
773
+
774
+        return SYNC_BODYPREFERENCE_PLAIN;
775
+    }
776
+
777
+    /**
778
+     * Checks if a file has the same owner and group as the parent directory.
779
+     * If not, owner and group are fixed (being updated to the owner/group of the directory).
780
+     * If the given file is a special file (i.g., /dev/null, fifo), nothing is changed.
781
+     * Function code contributed by Robert Scheck aka rsc.
782
+     *
783
+     * @param string $file
784
+     *
785
+     * @return bool
786
+     */
787
+    public static function FixFileOwner($file) {
788
+        if (!function_exists('posix_getuid')) {
789
+            SLog::Write(LOGLEVEL_DEBUG, "Utils::FixeFileOwner(): Posix subsystem not available, skipping.");
790
+
791
+            return false;
792
+        }
793
+        if (posix_getuid() == 0 && is_file($file)) {
794
+            $dir = dirname($file);
795
+            $perm_dir = stat($dir);
796
+            $perm_file = stat($file);
797
+
798
+            if ($perm_file['uid'] == 0 && $perm_dir['uid'] == 0 && $perm_dir['gid'] == 0) {
799
+                unlink($file);
800
+
801
+                throw new FatalException("FixFileOwner: {$dir} must be owned by the nginx/apache/php user instead of root for debian based systems and by root:grosync for RHEL-based systems");
802
+            }
803
+
804
+            if ($perm_dir['uid'] !== $perm_file['uid'] || $perm_dir['gid'] !== $perm_file['gid']) {
805
+                chown($file, $perm_dir['uid']);
806
+                chgrp($file, $perm_dir['gid']);
807
+                chmod($file, 0664);
808
+            }
809
+        }
810
+
811
+        return true;
812
+    }
813
+
814
+    /**
815
+     * Returns AS-style LastVerbExecuted value from the server value.
816
+     *
817
+     * @param int $verb
818
+     *
819
+     * @return int
820
+     */
821
+    public static function GetLastVerbExecuted($verb) {
822
+        switch ($verb) {
823
+            case NOTEIVERB_REPLYTOSENDER:   return AS_REPLYTOSENDER;
824
+
825
+            case NOTEIVERB_REPLYTOALL:      return AS_REPLYTOALL;
826
+
827
+            case NOTEIVERB_FORWARD:         return AS_FORWARD;
828
+        }
829
+
830
+        return 0;
831
+    }
832
+
833
+    /**
834
+     * Returns the local part from email address.
835
+     *
836
+     * @param string $email
837
+     *
838
+     * @return string
839
+     */
840
+    public static function GetLocalPartFromEmail($email) {
841
+        $pos = strpos($email, '@');
842
+        if ($pos === false) {
843
+            return $email;
844
+        }
845
+
846
+        return substr($email, 0, $pos);
847
+    }
848
+
849
+    /**
850
+     * Format bytes to a more human readable value.
851
+     *
852
+     * @param int $bytes
853
+     * @param int $precision
854
+     *
855
+     * @return string|void
856
+     */
857
+    public static function FormatBytes($bytes, $precision = 2) {
858
+        if ($bytes <= 0) {
859
+            return '0 B';
860
+        }
861
+
862
+        $units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB'];
863
+        $base = log($bytes, 1024);
864
+        $fBase = floor($base);
865
+        $pow = pow(1024, $base - $fBase);
866
+
867
+        return sprintf("%.{$precision}f %s", $pow, $units[$fBase]);
868
+    }
869
+
870
+    /**
871
+     * Returns folder origin identifier from its id.
872
+     *
873
+     * @param string $folderid
874
+     *
875
+     * @return bool|string matches values of DeviceManager::FLD_ORIGIN_*
876
+     */
877
+    public static function GetFolderOriginFromId($folderid) {
878
+        $origin = substr($folderid, 0, 1);
879
+
880
+        switch ($origin) {
881
+            case DeviceManager::FLD_ORIGIN_CONFIG:
882
+            case DeviceManager::FLD_ORIGIN_GAB:
883
+            case DeviceManager::FLD_ORIGIN_SHARED:
884
+            case DeviceManager::FLD_ORIGIN_USER:
885
+            case DeviceManager::FLD_ORIGIN_IMPERSONATED:
886
+                return $origin;
887
+        }
888
+        SLog::Write(LOGLEVEL_WARN, sprintf("Utils->GetFolderOriginFromId(): Unknown folder origin for folder with id '%s'", $folderid));
889
+
890
+        return false;
891
+    }
892
+
893
+    /**
894
+     * Returns folder origin as string from its id.
895
+     *
896
+     * @param string $folderid
897
+     *
898
+     * @return string
899
+     */
900
+    public static function GetFolderOriginStringFromId($folderid) {
901
+        $origin = substr($folderid, 0, 1);
902
+
903
+        switch ($origin) {
904
+            case DeviceManager::FLD_ORIGIN_CONFIG:
905
+                return 'configured';
906
+
907
+            case DeviceManager::FLD_ORIGIN_GAB:
908
+                return 'GAB';
909
+
910
+            case DeviceManager::FLD_ORIGIN_SHARED:
911
+                return 'shared';
912
+
913
+            case DeviceManager::FLD_ORIGIN_USER:
914
+                return 'user';
915
+
916
+            case DeviceManager::FLD_ORIGIN_IMPERSONATED:
917
+                return 'impersonated';
918
+        }
919
+        SLog::Write(LOGLEVEL_WARN, sprintf("Utils->GetFolderOriginStringFromId(): Unknown folder origin for folder with id '%s'", $folderid));
920
+
921
+        return 'unknown';
922
+    }
923
+
924
+    /**
925
+     * Splits the id into folder id and message id parts. A colon in the $id indicates
926
+     * that the id has folderid:messageid format.
927
+     *
928
+     * @param string $id
929
+     *
930
+     * @return array
931
+     */
932
+    public static function SplitMessageId($id) {
933
+        if (strpos($id, ':') !== false) {
934
+            return explode(':', $id);
935
+        }
936
+
937
+        return [null, $id];
938
+    }
939
+
940
+    /**
941
+     * Converts a string freebusy type into a numeric status.
942
+     *
943
+     * @param string $fbType
944
+     *
945
+     * @return int
946
+     */
947
+    public static function GetFbStatusFromType($fbType) {
948
+        switch ($fbType) {
949
+            case 'Free':
950
+                return fbFree;
951
+
952
+            case 'Tentative':
953
+                return fbTentative;
954
+
955
+            case 'Busy':
956
+                return fbBusy;
957
+
958
+            case 'OOF':
959
+                return fbOutOfOffice;
960
+        }
961
+        SLog::Write(LOGLEVEL_WARN, sprintf("Utils->GetFbStatusFromType(): Unknown free busy type '%s'", $fbType));
962
+
963
+        return fbNoData;
964
+    }
965 965
 }
966 966
 
967 967
 // TODO Win1252/UTF8 functions are deprecated and will be removed sometime
@@ -969,41 +969,41 @@  discard block
 block discarded – undo
969 969
 // STORE_SUPPORTS_UNICODE is true and the conversion will not be done
970 970
 // for other backends.
971 971
 function utf8_to_windows1252($string, $option = "", $force_convert = false) {
972
-	// if the store supports unicode return the string without converting it
973
-	if (!$force_convert && defined('STORE_SUPPORTS_UNICODE') && STORE_SUPPORTS_UNICODE == true) {
974
-		return $string;
975
-	}
972
+    // if the store supports unicode return the string without converting it
973
+    if (!$force_convert && defined('STORE_SUPPORTS_UNICODE') && STORE_SUPPORTS_UNICODE == true) {
974
+        return $string;
975
+    }
976 976
 
977
-	if (function_exists("iconv")) {
978
-		return @iconv("UTF-8", "Windows-1252" . $option, $string);
979
-	}
977
+    if (function_exists("iconv")) {
978
+        return @iconv("UTF-8", "Windows-1252" . $option, $string);
979
+    }
980 980
 
981
-	return utf8_decode($string); // no euro support here
981
+    return utf8_decode($string); // no euro support here
982 982
 }
983 983
 
984 984
 function windows1252_to_utf8($string, $option = "", $force_convert = false) {
985
-	// if the store supports unicode return the string without converting it
986
-	if (!$force_convert && defined('STORE_SUPPORTS_UNICODE') && STORE_SUPPORTS_UNICODE == true) {
987
-		return $string;
988
-	}
985
+    // if the store supports unicode return the string without converting it
986
+    if (!$force_convert && defined('STORE_SUPPORTS_UNICODE') && STORE_SUPPORTS_UNICODE == true) {
987
+        return $string;
988
+    }
989 989
 
990
-	if (function_exists("iconv")) {
991
-		return @iconv("Windows-1252", "UTF-8" . $option, $string);
992
-	}
990
+    if (function_exists("iconv")) {
991
+        return @iconv("Windows-1252", "UTF-8" . $option, $string);
992
+    }
993 993
 
994
-	return utf8_encode($string); // no euro support here
994
+    return utf8_encode($string); // no euro support here
995 995
 }
996 996
 
997 997
 function w2u($string) {
998
-	return windows1252_to_utf8($string);
998
+    return windows1252_to_utf8($string);
999 999
 }
1000 1000
 function u2w($string) {
1001
-	return utf8_to_windows1252($string);
1001
+    return utf8_to_windows1252($string);
1002 1002
 }
1003 1003
 
1004 1004
 function w2ui($string) {
1005
-	return windows1252_to_utf8($string, "//TRANSLIT");
1005
+    return windows1252_to_utf8($string, "//TRANSLIT");
1006 1006
 }
1007 1007
 function u2wi($string) {
1008
-	return utf8_to_windows1252($string, "//TRANSLIT");
1008
+    return utf8_to_windows1252($string, "//TRANSLIT");
1009 1009
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -65,17 +65,17 @@  discard block
 block discarded – undo
65 65
 			$zcs = $zip;
66 66
 		}
67 67
 		if (isset($city) && $city != "") {
68
-			$zcs .= (($zcs) ? " " : "") . $city;
68
+			$zcs .= (($zcs) ? " " : "").$city;
69 69
 		}
70 70
 		if (isset($state) && $state != "") {
71
-			$zcs .= (($zcs) ? " " : "") . $state;
71
+			$zcs .= (($zcs) ? " " : "").$state;
72 72
 		}
73 73
 		if ($zcs) {
74
-			$out = $zcs . "\r\n" . $out;
74
+			$out = $zcs."\r\n".$out;
75 75
 		}
76 76
 
77 77
 		if (isset($street) && $street != "") {
78
-			$out = $street . (($out) ? "\r\n\r\n" . $out : "");
78
+			$out = $street.(($out) ? "\r\n\r\n".$out : "");
79 79
 		}
80 80
 
81 81
 		return ($out) ? $out : null;
@@ -94,7 +94,7 @@  discard block
 block discarded – undo
94 94
 	public static function BuildFileAs($lastname = "", $firstname = "", $middlename = "", $company = "") {
95 95
 		if (defined('FILEAS_ORDER')) {
96 96
 			$fileas = $lastfirst = $firstlast = "";
97
-			$names = trim($firstname . " " . $middlename);
97
+			$names = trim($firstname." ".$middlename);
98 98
 			$lastname = trim($lastname);
99 99
 			$company = trim($company);
100 100
 
@@ -257,7 +257,7 @@  discard block
 block discarded – undo
257 257
 			$OLUid .= pack("V", 1);
258 258
 			$OLUid .= $icalUid;
259 259
 
260
-			return hex2bin("040000008200E00074C5B7101A82E0080000000000000000000000000000000000000000" . bin2hex($OLUid) . "00");
260
+			return hex2bin("040000008200E00074C5B7101A82E0080000000000000000000000000000000000000000".bin2hex($OLUid)."00");
261 261
 		}
262 262
 
263 263
 		return hex2bin($icalUid);
@@ -409,7 +409,7 @@  discard block
 block discarded – undo
409 409
 	 */
410 410
 	public static function Utf8_truncate($string, $length, $htmlsafe = false) {
411 411
 		// make sure length is always an integer
412
-		$length = (int) $length;
412
+		$length = (int)$length;
413 413
 
414 414
 		// if the input string is shorter then the trunction, make sure it's valid UTF-8!
415 415
 		if (strlen($string) <= $length) {
@@ -479,7 +479,7 @@  discard block
 block discarded – undo
479 479
 	 * @return bool
480 480
 	 */
481 481
 	public static function IsBase64String($string) {
482
-		return (bool) preg_match("#^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+/]{4})?$#", $string);
482
+		return (bool)preg_match("#^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+/]{4})?$#", $string);
483 483
 	}
484 484
 
485 485
 	/**
@@ -975,7 +975,7 @@  discard block
 block discarded – undo
975 975
 	}
976 976
 
977 977
 	if (function_exists("iconv")) {
978
-		return @iconv("UTF-8", "Windows-1252" . $option, $string);
978
+		return @iconv("UTF-8", "Windows-1252".$option, $string);
979 979
 	}
980 980
 
981 981
 	return utf8_decode($string); // no euro support here
@@ -988,7 +988,7 @@  discard block
 block discarded – undo
988 988
 	}
989 989
 
990 990
 	if (function_exists("iconv")) {
991
-		return @iconv("Windows-1252", "UTF-8" . $option, $string);
991
+		return @iconv("Windows-1252", "UTF-8".$option, $string);
992 992
 	}
993 993
 
994 994
 	return utf8_encode($string); // no euro support here
Please login to merge, or discard this patch.
Braces   +8 added lines, -16 removed lines patch added patch discarded remove patch
@@ -33,8 +33,7 @@  discard block
 block discarded – undo
33 33
 		if ($pos === false) {
34 34
 			$user = $domainuser;
35 35
 			$domain = '';
36
-		}
37
-		else {
36
+		} else {
38 37
 			$domain = substr($domainuser, 0, $pos);
39 38
 			$user = substr($domainuser, $pos + 1);
40 39
 		}
@@ -105,12 +104,10 @@  discard block
 block discarded – undo
105 104
 				if (strlen($names) > 0) {
106 105
 					$lastfirst .= ", {$names}";
107 106
 					$firstlast = "{$names} {$lastname}";
108
-				}
109
-				else {
107
+				} else {
110 108
 					$firstlast = $lastname;
111 109
 				}
112
-			}
113
-			elseif (strlen($names) > 0) {
110
+			} elseif (strlen($names) > 0) {
114 111
 				$lastfirst = $firstlast = $names;
115 112
 			}
116 113
 
@@ -122,8 +119,7 @@  discard block
 block discarded – undo
122 119
 				case SYNC_FILEAS_COMPANYONLY:
123 120
 					if (strlen($company) > 0) {
124 121
 						$fileas = $company;
125
-					}
126
-					elseif (strlen($firstlast) > 0) {
122
+					} elseif (strlen($firstlast) > 0) {
127 123
 						$fileas = $lastfirst;
128 124
 					}
129 125
 					break;
@@ -134,8 +130,7 @@  discard block
 block discarded – undo
134 130
 						if (strlen($lastfirst) > 0) {
135 131
 							$fileas .= "({$lastfirst})";
136 132
 						}
137
-					}
138
-					elseif (strlen($lastfirst) > 0) {
133
+					} elseif (strlen($lastfirst) > 0) {
139 134
 						$fileas = $lastfirst;
140 135
 					}
141 136
 					break;
@@ -146,8 +141,7 @@  discard block
 block discarded – undo
146 141
 						if (strlen($firstlast) > 0) {
147 142
 							$fileas .= " ({$firstlast})";
148 143
 						}
149
-					}
150
-					elseif (strlen($firstlast) > 0) {
144
+					} elseif (strlen($firstlast) > 0) {
151 145
 						$fileas = $firstlast;
152 146
 					}
153 147
 					break;
@@ -158,8 +152,7 @@  discard block
 block discarded – undo
158 152
 						if (strlen($company) > 0) {
159 153
 							$fileas .= " ({$company})";
160 154
 						}
161
-					}
162
-					elseif (strlen($company) > 0) {
155
+					} elseif (strlen($company) > 0) {
163 156
 						$fileas = $company;
164 157
 					}
165 158
 					break;
@@ -170,8 +163,7 @@  discard block
 block discarded – undo
170 163
 						if (strlen($company) > 0) {
171 164
 							$fileas .= " ({$company})";
172 165
 						}
173
-					}
174
-					elseif (strlen($company) > 0) {
166
+					} elseif (strlen($company) > 0) {
175 167
 						$fileas = $company;
176 168
 					}
177 169
 					break;
Please login to merge, or discard this patch.
lib/exceptions/notimplementedexception.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -8,5 +8,5 @@
 block discarded – undo
8 8
  * available which is non-fatal.
9 9
  */
10 10
 class NotImplementedException extends GSyncException {
11
-	protected $defaultLogLevel = LOGLEVEL_ERROR;
11
+    protected $defaultLogLevel = LOGLEVEL_ERROR;
12 12
 }
Please login to merge, or discard this patch.
lib/exceptions/syncobjectbrokenexception.php 1 patch
Indentation   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -9,28 +9,28 @@
 block discarded – undo
9 9
  */
10 10
 
11 11
 class SyncObjectBrokenException extends GSyncException {
12
-	protected $defaultLogLevel = LOGLEVEL_WARN;
13
-	private $syncObject;
12
+    protected $defaultLogLevel = LOGLEVEL_WARN;
13
+    private $syncObject;
14 14
 
15
-	/**
16
-	 * Returns the SyncObject which caused this Exception (if set).
17
-	 *
18
-	 * @return SyncObject
19
-	 */
20
-	public function GetSyncObject() {
21
-		return isset($this->syncObject) ? $this->syncObject : false;
22
-	}
15
+    /**
16
+     * Returns the SyncObject which caused this Exception (if set).
17
+     *
18
+     * @return SyncObject
19
+     */
20
+    public function GetSyncObject() {
21
+        return isset($this->syncObject) ? $this->syncObject : false;
22
+    }
23 23
 
24
-	/**
25
-	 * Sets the SyncObject which caused the exception so it can be later retrieved.
26
-	 *
27
-	 * @param SyncObject $syncobject
28
-	 *
29
-	 * @return bool
30
-	 */
31
-	public function SetSyncObject($syncobject) {
32
-		$this->syncObject = $syncobject;
24
+    /**
25
+     * Sets the SyncObject which caused the exception so it can be later retrieved.
26
+     *
27
+     * @param SyncObject $syncobject
28
+     *
29
+     * @return bool
30
+     */
31
+    public function SetSyncObject($syncobject) {
32
+        $this->syncObject = $syncobject;
33 33
 
34
-		return true;
35
-	}
34
+        return true;
35
+    }
36 36
 }
Please login to merge, or discard this patch.
lib/exceptions/authenticationrequiredexception.php 1 patch
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -7,9 +7,9 @@
 block discarded – undo
7 7
  * Exception sending a "401 Unauthorized" to the mobile
8 8
  */
9 9
 class AuthenticationRequiredException extends HTTPReturnCodeException {
10
-	protected $defaultLogLevel = LOGLEVEL_INFO;
11
-	protected $httpReturnCode = HTTP_CODE_401;
12
-	protected $httpReturnMessage = "Unauthorized";
13
-	protected $httpHeaders = ['WWW-Authenticate: Basic realm="GSync"'];
14
-	protected $showLegal = true;
10
+    protected $defaultLogLevel = LOGLEVEL_INFO;
11
+    protected $httpReturnCode = HTTP_CODE_401;
12
+    protected $httpReturnMessage = "Unauthorized";
13
+    protected $httpHeaders = ['WWW-Authenticate: Basic realm="GSync"'];
14
+    protected $showLegal = true;
15 15
 }
Please login to merge, or discard this patch.
lib/exceptions/statusexception.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -7,5 +7,5 @@
 block discarded – undo
7 7
  * Main exception related to errors regarding synchronization
8 8
  */
9 9
 class StatusException extends GSyncException {
10
-	protected $defaultLogLevel = LOGLEVEL_INFO;
10
+    protected $defaultLogLevel = LOGLEVEL_INFO;
11 11
 }
Please login to merge, or discard this patch.
lib/exceptions/gsyncexception.php 2 patches
Indentation   +24 added lines, -24 removed lines patch added patch discarded remove patch
@@ -8,34 +8,34 @@
 block discarded – undo
8 8
  */
9 9
 
10 10
 class GSyncException extends Exception {
11
-	protected $defaultLogLevel = LOGLEVEL_FATAL;
12
-	protected $httpReturnCode = HTTP_CODE_500;
13
-	protected $httpReturnMessage = "Internal Server Error";
14
-	protected $httpHeaders = [];
15
-	protected $showLegal = true;
11
+    protected $defaultLogLevel = LOGLEVEL_FATAL;
12
+    protected $httpReturnCode = HTTP_CODE_500;
13
+    protected $httpReturnMessage = "Internal Server Error";
14
+    protected $httpHeaders = [];
15
+    protected $showLegal = true;
16 16
 
17
-	public function __construct($message = "", $code = 0, $previous = null, $logLevel = false) {
18
-		if (!$message) {
19
-			$message = $this->httpReturnMessage;
20
-		}
17
+    public function __construct($message = "", $code = 0, $previous = null, $logLevel = false) {
18
+        if (!$message) {
19
+            $message = $this->httpReturnMessage;
20
+        }
21 21
 
22
-		if (!$logLevel) {
23
-			$logLevel = $this->defaultLogLevel;
24
-		}
22
+        if (!$logLevel) {
23
+            $logLevel = $this->defaultLogLevel;
24
+        }
25 25
 
26
-		parent::__construct($message, (int) $code);
27
-		SLog::Write($logLevel, get_class($this) . ': ' . $message . ' - code: ' . $code . ' - file: ' . $this->getFile() . ':' . $this->getLine(), false);
28
-	}
26
+        parent::__construct($message, (int) $code);
27
+        SLog::Write($logLevel, get_class($this) . ': ' . $message . ' - code: ' . $code . ' - file: ' . $this->getFile() . ':' . $this->getLine(), false);
28
+    }
29 29
 
30
-	public function getHTTPCodeString() {
31
-		return $this->httpReturnCode . " " . $this->httpReturnMessage;
32
-	}
30
+    public function getHTTPCodeString() {
31
+        return $this->httpReturnCode . " " . $this->httpReturnMessage;
32
+    }
33 33
 
34
-	public function getHTTPHeaders() {
35
-		return $this->httpHeaders;
36
-	}
34
+    public function getHTTPHeaders() {
35
+        return $this->httpHeaders;
36
+    }
37 37
 
38
-	public function showLegalNotice() {
39
-		return $this->showLegal;
40
-	}
38
+    public function showLegalNotice() {
39
+        return $this->showLegal;
40
+    }
41 41
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -23,12 +23,12 @@
 block discarded – undo
23 23
 			$logLevel = $this->defaultLogLevel;
24 24
 		}
25 25
 
26
-		parent::__construct($message, (int) $code);
27
-		SLog::Write($logLevel, get_class($this) . ': ' . $message . ' - code: ' . $code . ' - file: ' . $this->getFile() . ':' . $this->getLine(), false);
26
+		parent::__construct($message, (int)$code);
27
+		SLog::Write($logLevel, get_class($this).': '.$message.' - code: '.$code.' - file: '.$this->getFile().':'.$this->getLine(), false);
28 28
 	}
29 29
 
30 30
 	public function getHTTPCodeString() {
31
-		return $this->httpReturnCode . " " . $this->httpReturnMessage;
31
+		return $this->httpReturnCode." ".$this->httpReturnMessage;
32 32
 	}
33 33
 
34 34
 	public function getHTTPHeaders() {
Please login to merge, or discard this patch.
lib/exceptions/provisioningrequiredexception.php 1 patch
Indentation   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -7,7 +7,7 @@
 block discarded – undo
7 7
  * Exception announcing to the mobile that a provisioning request is required
8 8
  */
9 9
 class ProvisioningRequiredException extends HTTPReturnCodeException {
10
-	protected $defaultLogLevel = LOGLEVEL_INFO;
11
-	protected $httpReturnCode = HTTP_CODE_449;
12
-	protected $httpReturnMessage = "Retry after sending a PROVISION command";
10
+    protected $defaultLogLevel = LOGLEVEL_INFO;
11
+    protected $httpReturnCode = HTTP_CODE_449;
12
+    protected $httpReturnMessage = "Retry after sending a PROVISION command";
13 13
 }
Please login to merge, or discard this patch.