Test Failed
Push — master ( cd42b5...841446 )
by
unknown
16:44 queued 06:09
created

EntryId::getWrappedSEID()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 37
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 21
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 37
rs 9.584
1
<?php
2
3
	class EntryId {
4
		/* Bit definitions for abFlags[3] of ENTRYID */
5
		public const ZARAFA_FAVORITE = '01';
6
7
		/* GUID of root public folder */
8
		public const STATIC_GUID_PUBLICFOLDER = '00000000000000000000000000000003';
9
		/* GUID of root favorite folder */
10
		public const STATIC_GUID_FAVORITE = '00000000000000000000000000000002';
11
		/* GUID of ipm_subtree of public store */
12
		public const STATIC_GUID_FAVSUBTREE = '00000000000000000000000000000001';
13
		/* GUID of Global Addressbook */
14
		public const MUIDECSAB = 'AC21A95040D3EE48B319FBA753304425';
15
		/* GUID of Contact Provider */
16
		public const MUIDZCSAB = '727F0430E3924FDAB86AE52A7FE46571';
17
		/* GUID for OneOff entryid */
18
		public const MAPI_ONE_OFF_UID = '812B1FA4BEA310199D6E00DD010F5402';
19
		/* GUID for Address book recipient */
20
		public const MUIDEMSAB = 'DCA740C8C042101AB4B908002B2FE182';
21
22
		/* Hardcoded ID used for generating entryid of addressbook container */
23
		public const ZARAFA_UID_ADDRESS_BOOK = '00000000';
24
		/* Hardcoded ID used for generating entryid of global addressbook container */
25
		public const ZARAFA_UID_GLOBAL_ADDRESS_BOOK = '01000000';
26
		/* Hardcoded ID used for generating entryid of global addresslists container */
27
		public const ZARAFA_UID_GLOBAL_ADDRESS_LISTS = '02000000';
28
29
		public function __construct() {
30
		}
31
32
		// Detect padding (max 3 bytes) from the entryId
33
		private function getPadding($entryId) {
34
			$len = strlen($entryId);
35
			$padding = '';
36
			$offset = 0;
37
38
			for ($iterations = 4; $iterations > 0; --$iterations) {
39
				if (substr($entryId, $len - ($offset + 2), $len - $offset) == '00') {
40
					$padding .= '00';
41
					$offset += 2;
42
				}
43
				else {
44
					// if non-null character found then break the loop
45
					break;
46
				}
47
			}
48
49
			return $padding;
50
		}
51
52
		// Entryid from version 6
53
		private function getEIDVersion($entryid) {
54
			// always make entryids in uppercase so comparison will be case insensitive
55
			$entryId = strtoupper($entryid);
56
57
			$res = [
58
				'abFlags' => '',		// BYTE[4],   4 bytes,  8 hex characters
59
				'guid' => '',		// GUID,     16 bytes, 32 hex characters
60
				'version' => '',		// ULONG,     4 bytes,  8 hex characters
61
				'type' => '',		// ULONG,     4 bytes,  8 hex characters
62
				'uniqueId' => '',		// ULONG,    16 bytes,  32 hex characters
63
				'server' => '',		// CHAR,     variable length
64
				'padding' => '',		// TCHAR[3],  4 bytes,  8 hex characters (upto 4 bytes)
65
			];
66
67
			$res['length'] = strlen($entryId);
68
			$offset = 0;
69
70
			// First determine padding, and remove if from the entryId
71
			$res['padding'] = $this->getPadding($entryId);
72
			$entryId = substr($entryId, 0, strlen($entryId) - strlen($res['padding']));
73
74
			$res['abFlags'] = substr($entryId, $offset, 8);
75
			$offset = +8;
76
77
			$res['guid'] = substr($entryId, $offset, 32);
78
			$offset += 32;
79
80
			$res['version'] = substr($entryId, $offset, 8);
81
			$offset += 8;
82
83
			$res['type'] = substr($entryId, $offset, 8);
84
			$offset += 8;
85
86
			$res['uniqueId'] = substr($entryId, $offset, 32);
87
			$offset += 32;
88
89
			$res['server'] = substr($entryId, $offset);
90
91
			$res['min_length'] = 88;
92
			$res['name'] = 'EID';
93
94
			return $res;
95
		}
96
97
		// The entryid from the begin of zarafa till 5.20
98
		private function getEID_V0Version($entryid) {
99
			// always make entryids in uppercase so comparison will be case insensitive
100
			$entryId = strtoupper($entryid);
101
102
			$res = [
103
				'abFlags' => '',		// BYTE[4],   4 bytes,  8 hex characters
104
				'guid' => '',		// GUID,     16 bytes, 32 hex characters
105
				'version' => '',		// ULONG,     4 bytes,  8 hex characters
106
				'type' => '',		// ULONG,     4 bytes,  8 hex characters
107
				'id' => '',		// ULONG,     4 bytes,  8 hex characters
108
				'server' => '',		// CHAR,     variable length
109
				'padding' => '',		// TCHAR[3],  4 bytes,  8 hex characters (upto 4 bytes)
110
			];
111
112
			$res['length'] = strlen($entryId);
113
			$offset = 0;
114
115
			// First determine padding, and remove if from the entryId
116
			$res['padding'] = $this->getPadding($entryId);
117
			$entryId = substr($entryId, 0, strlen($entryId) - strlen($res['padding']));
118
119
			$res['abFlags'] = substr($entryId, $offset, 8);
120
			$offset = +8;
121
122
			$res['guid'] = substr($entryId, $offset, 32);
123
			$offset += 32;
124
125
			$res['version'] = substr($entryId, $offset, 8);
126
			$offset += 8;
127
128
			$res['type'] = substr($entryId, $offset, 8);
129
			$offset += 8;
130
131
			$res['id'] = substr($entryId, $offset, 8);
132
			$offset += 8;
133
134
			$res['server'] = substr($entryId, $offset);
135
136
			$res['min_length'] = 64;
137
			$res['name'] = 'EID_V0';
138
139
			return $res;
140
		}
141
142
		// wrapped store entryid
143
		private function getWrappedSEID($storeEntryId) {
144
			$res = [];
145
146
			$res['name'] = 'WrappedSEID';
147
			$res['length'] = strlen($storeEntryId);
148
149
			// always make entryids in uppercase so comparison will be case insensitive
150
			$storeEntryId = strtoupper($storeEntryId);
151
152
			$offset = 0;
153
154
			$res['flags'] = substr($storeEntryId, $offset, 8);
155
			$offset += 8;
156
157
			$res['providerUID'] = substr($storeEntryId, $offset, 32);
158
			$offset += 32;
159
160
			$res['version'] = substr($storeEntryId, $offset, 2);
161
			$offset += 2;
162
163
			$res['type'] = substr($storeEntryId, $offset, 2);
164
			$offset += 2;
165
166
			// find length of dll name, find null character which indicates end of dll name after the current offset
167
			$termCharIndex = strpos(substr($storeEntryId, $offset), '00');
168
			$res['DLLFileName'] = substr($storeEntryId, $offset, $termCharIndex);
169
			$offset += $termCharIndex;
170
171
			$res['terminationChar'] = substr($storeEntryId, $offset, 2);
172
			$offset += 2;
173
174
			$res['unWrappedEntryId'] = substr($storeEntryId, $offset);
175
176
			// unwrapped entryid is actually an object entryid so decompose it
177
			$res['unWrappedEntryId'] = $this->createEntryIdObj($res['unWrappedEntryId']);
178
179
			return $res;
180
		}
181
182
		// Addressbook Entryid
183
		private function getABEIDVersion($entryId) {
184
			// always make entryids in uppercase so comparison will be case insensitive
185
			$entryId = strtoupper($entryId);
186
187
			$res = [
188
				'abFlags' => '',		// BYTE[4],   4 bytes,  8 hex characters
189
				'guid' => '',		// GUID,     16 bytes, 32 hex characters
190
				'version' => '',		// ULONG,     4 bytes,  8 hex characters
191
				'type' => '',		// ULONG,     4 bytes,  8 hex characters
192
				'id' => '',		// ULONG,    16 bytes,  32 hex characters
193
				'extid' => '',		// CHAR,     variable length
194
				'padding' => '',		// TCHAR[3],  4 bytes,  8 hex characters (upto 4 bytes)
195
			];
196
197
			$res['length'] = strlen($entryId);
198
			$offset = 0;
199
200
			// First determine padding, and remove if from the entryId
201
			$res['padding'] = $this->getPadding($entryId);
202
			$entryId = substr($entryId, 0, strlen($entryId) - strlen($res['padding']));
203
204
			$res['abFlags'] = substr($entryId, $offset, 8);
205
			$offset = +8;
206
207
			$res['guid'] = substr($entryId, $offset, 32);
208
			$offset += 32;
209
210
			$res['version'] = substr($entryId, $offset, 8);
211
			$offset += 8;
212
213
			$res['type'] = substr($entryId, $offset, 8);
214
			$offset += 8;
215
216
			$res['id'] = substr($entryId, $offset, 8);
217
			$offset += 8;
218
219
			$res['extid'] = substr($entryId, $offset);
220
221
			$res['min_length'] = 88;
222
			$res['name'] = 'ABEID';
223
224
			return $res;
225
		}
226
227
		/**
228
		 * Creates an object that has split up all the components of an entryID.
229
		 *
230
		 * @param {String} entryid Entryid
231
		 * @param mixed $entryid
232
		 *
233
		 * @return {Object} EntryID object
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Object} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Object}.
Loading history...
234
		 */
235
		private function createEntryIdObj($entryid) {
236
			// check if we are dealing with old or new object entryids
237
			$versionString = substr($entryid, 40, 8);
238
239
			if ($versionString == '00000000') {
240
				// use EID_V0 struct
241
				$eidObj = $this->getEID_V0Version($entryid);
242
			}
243
			else {
244
				// use EID struct
245
				$eidObj = $this->getEIDVersion($entryid);
246
			}
247
248
			return $eidObj;
249
		}
250
251
		/**
252
		 * Compares two entryIds. It is possible to have two different entryIds that should match as they
253
		 * represent the same object (in multiserver environments).
254
		 *
255
		 * @param {String} entryId1 EntryID
256
		 * @param {String} entryId2 EntryID
0 ignored issues
show
Bug introduced by
The type entryId2 was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
257
		 * @param mixed $entryId1
258
		 * @param mixed $entryId2
259
		 *
260
		 * @return {Boolean} Result of the comparison
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Boolean} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Boolean}.
Loading history...
261
		 */
262
		public function compareEntryIds($entryId1, $entryId2) {
263
			if (!is_string($entryId1) || !is_string($entryId2)) {
264
				return false;
265
			}
266
267
			if ($entryId1 === $entryId2) {
268
				// if normal comparison succeeds then we can directly say that entryids are same
269
				return true;
270
			}
271
272
			return false;
273
		}
274
275
		/**
276
		 * Creates an object that has split up all the components of a store entryid.
277
		 *
278
		 * @param {String} storeEntryId unwrapped store entryid
0 ignored issues
show
Bug introduced by
The type storeEntryId was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
279
		 * @param mixed $storeEntryId
280
		 *
281
		 * @return {Object} store entryid object
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Object} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Object}.
Loading history...
282
		 */
283
		private function createStoreEntryIdObj($storeEntryId) {
0 ignored issues
show
Unused Code introduced by
The method createStoreEntryIdObj() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
284
			return $this->getWrappedSEID($storeEntryId);
285
		}
286
287
		/**
288
		 * Compares two entryIds. It is possible to have two different entryIds that should match as they
289
		 * represent the same object (in multiserver environments).
290
		 *
291
		 * @param {String} storeEntryId1 store entryid
292
		 * @param {String} storeEntryId2 store entryid
0 ignored issues
show
Bug introduced by
The type storeEntryId2 was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
293
		 * @param mixed $storeEntryId1
294
		 * @param mixed $storeEntryId2
295
		 *
296
		 * @return {Boolean} Result of the comparison
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Boolean} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Boolean}.
Loading history...
297
		 */
298
		public function compareStoreEntryIds($storeEntryId1, $storeEntryId2) {
299
			if (!is_string($storeEntryId1) || !is_string($storeEntryId2)) {
300
				return false;
301
			}
302
303
			if ($storeEntryId1 === $storeEntryId2) {
304
				// if normal comparison succeeds then we can directly say that entryids are same
305
				return true;
306
			}
307
308
			return false;
309
		}
310
311
		/**
312
		 * Creates an object that has split up all the components of an addressbook entryid.
313
		 *
314
		 * @param {String} abEntryId unwrapped addressbook entryid
0 ignored issues
show
Bug introduced by
The type abEntryId was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
315
		 * @param mixed $abEntryId
316
		 *
317
		 * @return {Object} addresbook entryid object
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Object} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Object}.
Loading history...
318
		 */
319
		public function createABEntryIdObj($abEntryId) {
320
			return $this->getABEIDVersion($abEntryId);
321
		}
322
323
		/**
324
		 * Creates an object that has wrapped a normal entryid using the AddressBook Provider GUID.
325
		 *
326
		 * @param {String} entryId unwrapped entryid
327
		 * @param {Number} objType The ObjectType which represents the object
0 ignored issues
show
Bug introduced by
The type objType was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
328
		 * @param mixed $entryId
329
		 * @param mixed $objType
330
		 *
331
		 * @return {String} wrapped addresbook entryid object
0 ignored issues
show
Documentation Bug introduced by
The doc comment {String} at position 0 could not be parsed: Unknown type name '{' at position 0 in {String}.
Loading history...
332
		 */
333
		public function wrapABEntryIdObj($entryId, $objType) {
334
			$objType = dechex($objType);
335
336
			// add padding for the type, which is of 4 bytes (8 characters)
337
			$objType = str_pad($objType, 2, '0', STR_PAD_LEFT);
338
			$objType = str_pad($objType, 8, '0', STR_PAD_RIGHT);
339
340
			return '00000000' . self::MUIDZCSAB . $objType . '00000000' . $entryId;
341
		}
342
343
		/**
344
		 * Unwrap a Address Book Provider Entryid to a normal entryid.
345
		 *
346
		 * @param {String} abEntryId wrapped entryid
347
		 * @param mixed $abEntryId
348
		 *
349
		 * @return {Object} unwrapped entryid
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Object} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Object}.
Loading history...
350
		 */
351
		public function unwrapABEntryIdObj($abEntryId) {
352
			// Remove ulVersion (8 char), muid (32 char), ulObjType (8 char) and ulOffset (8 char)
353
			return substr($abEntryId, 56);
354
		}
355
356
		/**
357
		 * Compares two entryIds. It is possible to have two different entryIds that should match as they
358
		 * represent the same object (in multiserver environments).
359
		 *
360
		 * @param {String} entryId1 EntryID
361
		 * @param {String} entryId2 EntryID
362
		 * @param mixed $entryId1
363
		 * @param mixed $entryId2
364
		 *
365
		 * @return {Boolean} Result of the comparison
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Boolean} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Boolean}.
Loading history...
366
		 */
367
		public function compareABEntryIds($entryId1, $entryId2) {
368
			if (!is_string($entryId1) || !is_string($entryId2)) {
369
				return false;
370
			}
371
372
			if ($entryId1 === $entryId2) {
373
				// if normal comparison succeeds then we can directly say that entryids are same
374
				return true;
375
			}
376
377
			return false;
378
		}
379
380
		/**
381
		 * Checks if the passed folder entryid is a folder in the favorites folder, favorites folder
382
		 * contains 0x01 in the abFlags[3] flag.
383
		 *
384
		 * @param {String} entryId folder entryid
385
		 * @param mixed $entryId
386
		 *
387
		 * @return {Boolean} true of folder is a favorite folder else false
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Boolean} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Boolean}.
Loading history...
388
		 */
389
		public function isFavoriteFolder($entryId) {
390
			$entryIdObj = $this->createEntryIdObj($entryId);
391
392
			return substr($entryIdObj['abFlags'], 6, 8) == self::ZARAFA_FAVORITE;
393
		}
394
395
		/**
396
		 * Checks if the given entryid is a oneoff entryid.
397
		 *
398
		 * @param {String} entryId The entryid
399
		 * @param mixed $entryId
400
		 *
401
		 * @return {Boolean} true if the entryid is a oneoff
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Boolean} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Boolean}.
Loading history...
402
		 */
403
		public function isOneOffEntryId($entryId) {
404
			$entryIdObj = $this->createEntryIdObj($entryId);
405
406
			return $entryIdObj['guid'] == self::MAPI_ONE_OFF_UID;
407
		}
408
409
		/**
410
		 * Checks if the passed folder entryid is root favorites folder.
411
		 *
412
		 * @param {String} entryId folder entryid
413
		 * @param mixed $entryId
414
		 *
415
		 * @return {Boolean} true of folder is a root favorite folder else false
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Boolean} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Boolean}.
Loading history...
416
		 */
417
		public function isFavoriteRootFolder($entryId) {
418
			$entryIdObj = $this->createEntryIdObj($entryId);
419
420
			return $entryIdObj['uniqueId'] == self::STATIC_GUID_FAVORITE;
421
		}
422
423
		/**
424
		 * Checks if the passed folder entryid is root public folder.
425
		 *
426
		 * @param {String} entryId folder entryid
427
		 * @param mixed $entryId
428
		 *
429
		 * @return {Boolean} true of folder is a root public folder else false
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Boolean} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Boolean}.
Loading history...
430
		 */
431
		public function isPublicRootFolder($entryId) {
432
			$entryIdObj = $this->createEntryIdObj($entryId);
433
434
			return $entryIdObj['uniqueId'] == self::STATIC_GUID_PUBLICFOLDER;
435
		}
436
437
		/**
438
		 * Checks if the passed folder entryid is public subtree folder.
439
		 *
440
		 * @param {String} entryId folder entryid
441
		 * @param mixed $entryId
442
		 *
443
		 * @return {Boolean} true of folder is a root public folder else false
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Boolean} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Boolean}.
Loading history...
444
		 */
445
		public function isPublicSubtreeFolder($entryId) {
446
			$entryIdObj = $this->createEntryIdObj($entryId);
447
448
			return $entryIdObj['uniqueId'] == self::STATIC_GUID_FAVSUBTREE;
449
		}
450
451
		/**
452
		 * Checks if the given entryid.
453
		 *
454
		 * @param {String} entryId Addressbook entryid
455
		 * @param mixed $entryId
456
		 */
457
		public function hasContactProviderGUID($entryId) {
458
			$entryIdObj = $this->createABEntryIdObj($entryId);
459
460
			return $entryIdObj['guid'] == self::MUIDZCSAB;
461
		}
462
463
		/**
464
		 * Checks if the GUID part of the entryid is of the Global Addressbook.
465
		 *
466
		 * @param {String} $entryId Address Book entryid
0 ignored issues
show
Documentation Bug introduced by
The doc comment {String} at position 0 could not be parsed: Unknown type name '{' at position 0 in {String}.
Loading history...
467
		 *
468
		 * @return {Boolean} true if guid matches the Global Addressbook else false
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Boolean} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Boolean}.
Loading history...
469
		 */
470
		public function hasAddressBookGUID($entryId) {
471
			$entryIdObj = $this->createABEntryIdObj($entryId);
472
473
			return $entryIdObj['guid'] == self::MUIDECSAB;
474
		}
475
476
		/**
477
		 * Checks if the GUID part of the entryid is of the Address book recipient.
478
		 *
479
		 * @param {String} $entryId Address Book entryid
0 ignored issues
show
Documentation Bug introduced by
The doc comment {String} at position 0 could not be parsed: Unknown type name '{' at position 0 in {String}.
Loading history...
480
		 *
481
		 * @return {Boolean} true if guid matches the Ab recipient else false
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Boolean} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Boolean}.
Loading history...
482
		 */
483
		public function hasAddressBookRecipientGUID($entryId) {
484
			$entryIdObj = $this->createABEntryIdObj($entryId);
485
486
			return $entryIdObj['guid'] == self::MUIDEMSAB;
487
		}
488
489
		/**
490
		 * Checks if the GUID part of the entryid is of the Global Addressbook Container.
491
		 *
492
		 * @param {String} $entryId Address Book entryid
0 ignored issues
show
Documentation Bug introduced by
The doc comment {String} at position 0 could not be parsed: Unknown type name '{' at position 0 in {String}.
Loading history...
493
		 *
494
		 * @return {Boolean} true if guid matches the Global Addressbook Container else false
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Boolean} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Boolean}.
Loading history...
495
		 */
496
		public function isGlobalAddressbookContainer($entryId) {
497
			// check for global addressbook entryid
498
			if ($this->hasAddressBookGUID($entryId) === false) {
499
				return false;
500
			}
501
502
			$entryIdObj = $this->createABEntryIdObj($entryId);
503
504
			// check for object_type == MAPI_ABCONT and id == 1
505
			return $entryIdObj['type'] == '04000000' && $entryIdObj['id'] == self::ZARAFA_UID_GLOBAL_ADDRESS_BOOK;
506
		}
507
508
		/**
509
		 * Creates an object that has split up all the components of an message store entryid.
510
		 *
511
		 * @param {String} $entryId message store entryid
0 ignored issues
show
Documentation Bug introduced by
The doc comment {String} at position 0 could not be parsed: Unknown type name '{' at position 0 in {String}.
Loading history...
512
		 *
513
		 * @return {Object} message store entryid object
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Object} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Object}.
Loading history...
514
		 */
515
		public function createMsgStoreEntryIdObj($entryId) {
516
			$res = [
517
				'Flags' => '',
518
				'ProviderUID' => '',
519
				'Version' => '',
520
				'Flag' => '',
521
				'DLLFileName' => '',
522
				'WrappedFlags' => '',
523
				'WrappedProviderUID' => '',
524
				'WrappedType' => '',
525
				'ServerShortname' => '',
526
				'MailboxDN' => '',
527
				'V2' => [
528
					'Magic' => '',
529
					'Size' => '',
530
					'Version' => '',
531
					'OffsetDN' => '',
532
					'OffsetFQDN' => '',
533
					'ServerDN' => '',
534
					'ServerFQDN' => '',
535
					'ReservedBlock' => '',
536
				],
537
				'V3' => [
538
					'Magic' => '',
539
					'Size' => '',
540
					'Version' => '',
541
					'OffsetSmtpAddress' => '',
542
					'SmtpAddress' => '',
543
				],
544
			];
545
546
			if (!$entryId) {
547
				return $res;
548
			}
549
550
			$offset = 0;
551
			if (!$this->getAndCheckComponents($entryId, $offset, 4, 0x0, $res, 'Flags')) {
552
				return $res;
553
			}
554
			$offset += 4;
555
556
			if (!$this->getAndCheckComponents($entryId, $offset, 16, MUID_STORE_WRAP_GUID, $res, 'ProviderUID')) {
557
				return $res;
558
			}
559
			$offset += 16;
560
561
			if (!$this->getAndCheckComponents($entryId, $offset, 1, 0x0, $res, 'Version')) {
562
				return $res;
563
			}
564
			++$offset;
565
566
			if (!$this->getAndCheckComponents($entryId, $offset, 1, 0x0, $res, 'Flag')) {
567
				return $res;
568
			}
569
			++$offset;
570
571
			if (!$this->getAndCheckComponents($entryId, $offset, 10, 'emsmdb.dll', $res, 'DLLFileName')) {
572
				return $res;
573
			}
574
			$offset += 14;
575
576
			if (!$this->getAndCheckComponents($entryId, $offset, 4, 0x0, $res, 'WrappedFlags')) {
577
				return $res;
578
			}
579
			$offset += 4;
580
581
			if (!$this->getAndCheckComponents($entryId, $offset, 16, [MUID_STORE_PRIVATE_GUID, MUID_STORE_PUBLIC_GUID], $res, 'WrappedProviderUID')) {
582
				return $res;
583
			}
584
			$offset += 16;
585
586
			if (!$this->getAndCheckComponents($entryId, $offset, 4, array_map('hex2bin', ['0C000000', '06000000']), $res, 'WrappedType')) {
587
				return $res;
588
			}
589
			$offset += 4;
590
591
			$zeroBytePos = strpos($entryId, "\0", $offset);
592
			if ($zeroBytePos !== false) {
593
				$res['ServerShortname'] = trim(substr($entryId, $offset, $zeroBytePos - $offset));
594
				$offset = $zeroBytePos + 1;
595
			}
596
597
			$zeroBytePos = strpos($entryId, "\0", $offset);
598
			if ($zeroBytePos !== false) {
599
				$res['MailboxDN'] = trim(substr($entryId, $offset, $zeroBytePos - $offset));
600
				$offset = $zeroBytePos + 1;
0 ignored issues
show
Unused Code introduced by
The assignment to $offset is dead and can be removed.
Loading history...
601
			}
602
603
			// TODO V2 and V3 structs
604
605
			return $res;
606
		}
607
608
		/**
609
		 * Reads $len bytes beginning from $start of the $entryid,
610
		 * checks if the value of resulting string is expected and adds it
611
		 * to $res object in such case.
612
		 *
613
		 * @param {String} $entryId message store entryid
0 ignored issues
show
Documentation Bug introduced by
The doc comment {String} at position 0 could not be parsed: Unknown type name '{' at position 0 in {String}.
Loading history...
614
		 * @param {int} $start start position of the value to get
615
		 * @param {int} $len length in bytes of the value to get
616
		 * @param {Object} $checkValue value to check against
617
		 * @param {Object} $res message store entryid object
618
		 * @param {String} $key component name
619
		 *
620
		 * @return {Boolean} true if the component has the expected value, false otherwise
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Boolean} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Boolean}.
Loading history...
621
		 */
622
		private function getAndCheckComponents($entryId, $start, $len, $checkValue, &$res, $key) {
623
			$val = substr($entryId, $start, $len);
624
			if (is_array($checkValue)) {
625
				if (!in_array($val, $checkValue)) {
626
					error_log(sprintf(
627
						"Unexpected value in store entryid for user %s. Entryid: %s key: '%s' value: '%s' expected: %s",
628
						$GLOBALS["mapisession"]->getUserName(),
629
						bin2hex($entryId),
630
						$key,
631
						$val,
632
						print_r(array_map('bin2hex', $checkValue), 1)
0 ignored issues
show
Bug introduced by
It seems like print_r(array_map('bin2hex', $checkValue), 1) can also be of type true; however, parameter $values of sprintf() does only seem to accept double|integer|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

632
						/** @scrutinizer ignore-type */ print_r(array_map('bin2hex', $checkValue), 1)
Loading history...
633
					));
634
635
					return false;
636
				}
637
			}
638
			elseif ($checkValue !== null && $val != $checkValue) {
639
				$user = $GLOBALS["mapisession"] !== null ? $GLOBALS["mapisession"]->getUserName() :
640
						"<mapisession not yet initialized>";
641
				error_log(sprintf(
642
					"Unexpected value in store entryid for user %s. Entryid: %s key: '%s' value: '%s' expected: %s",
643
					$user,
644
					bin2hex($entryId),
645
					$key,
646
					$val,
647
					$checkValue
648
				));
649
650
				return false;
651
			}
652
653
			$res[$key] = $val;
654
655
			return true;
656
		}
657
658
		/**
659
		 * Creates an object that has split up all the components of a message entryid.
660
		 *
661
		 * @param {String} $entryId message entryid
0 ignored issues
show
Documentation Bug introduced by
The doc comment {String} at position 0 could not be parsed: Unknown type name '{' at position 0 in {String}.
Loading history...
662
		 *
663
		 * @return {Object} message entryid object
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Object} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Object}.
Loading history...
664
		 */
665
		public function createMessageEntryIdObj($entryId) {
666
			// always make entryids in uppercase so comparison will be case insensitive
667
			$entryId = strtoupper($entryId);
668
669
			$res = [
670
				'providerguid' => '',			// GUID,     16 bytes, 32 hex characters
671
				'messagetype' => '',			// UINT,      2 bytes,  4 hex characters
672
				'folderdbguid' => '',			// GUID,     16 bytes, 32 hex characters
673
				'foldercounter' => '',		// ULONG,     6 bytes, 12 hex characters
674
				'padding' => '',					// TCHAR[3],  2 bytes,  4 hex characters
675
				'messagedbguid' => '',		// GUID,     16 bytes, 32 hex characters
676
				'messagecounter' => '',	// ULONG,     6 bytes, 12 hex characters
677
			];
678
679
			if (!$entryId) {
680
				return $res;
681
			}
682
683
			$res['length'] = strlen($entryId);
684
			$offset = 0;
685
686
			$res['providerguid'] = substr($entryId, $offset, 32);
687
			$offset += 32;
688
689
			$res['messagetype'] = substr($entryId, $offset, 4);
690
			$offset += 4;
691
692
			$res['folderdbguid'] = substr($entryId, $offset, 32);
693
			$offset += 32;
694
695
			$res['foldercounter'] = substr($entryId, $offset, 12);
696
			$offset += 12;
697
698
			$res['padding'] = substr($entryId, $offset, 4);
699
			$offset += 4;
700
701
			$res['messagedbguid'] = substr($entryId, $offset, 32);
702
			$offset += 32;
703
704
			$res['messagecounter'] = substr($entryId, $offset, 12);
705
			$offset += 12;
706
707
			return $res;
708
		}
709
710
		/**
711
		 * Creates a folder entryid with provided parameters.
712
		 *
713
		 * @param $providerguid {String} provider guid
0 ignored issues
show
Documentation Bug introduced by
The doc comment {String} at position 0 could not be parsed: Unknown type name '{' at position 0 in {String}.
Loading history...
714
		 * @param $foldertype {int} folder type flag
715
		 * @param $folderdbguid {String} folder db guid
716
		 * @param $foldercounter {String} folder counter
717
		 *
718
		 * @return {String} folder entryid
0 ignored issues
show
Documentation Bug introduced by
The doc comment {String} at position 0 could not be parsed: Unknown type name '{' at position 0 in {String}.
Loading history...
719
		 */
720
		public function createFolderEntryId($providerguid, $foldertype, $folderdbguid, $foldercounter) {
721
			return strtoupper('00000000' . $providerguid . $foldertype . $folderdbguid . $foldercounter . '0000');
722
		}
723
724
		/**
725
		 * Creates an object that has split up all the components of a folder entryid.
726
		 *
727
		 * @param {String} $entryId folder entryid
0 ignored issues
show
Documentation Bug introduced by
The doc comment {String} at position 0 could not be parsed: Unknown type name '{' at position 0 in {String}.
Loading history...
728
		 *
729
		 * @return {Object} folder entryid object
0 ignored issues
show
Documentation Bug introduced by
The doc comment {Object} at position 0 could not be parsed: Unknown type name '{' at position 0 in {Object}.
Loading history...
730
		 */
731
		public function createFolderEntryIdObj($entryId) {
732
			// always make entryids in uppercase so comparison will be case insensitive
733
			$entryId = strtoupper($entryId);
734
735
			$res = [
736
				'abflags' => '',					// BYTE[4],   4 bytes,  8 hex characters
737
				'providerguid' => '',			// GUID,     16 bytes, 32 hex characters
738
				'foldertype' => '',				// UINT,      2 bytes,  4 hex characters
739
				'folderdbguid' => '',			// GUID,     16 bytes, 32 hex characters
740
				'foldercounter' => '',		// ULONG,     6 bytes, 12 hex characters
741
				'padding' => '',					// TCHAR[3],  2 bytes,  4 hex characters
742
			];
743
744
			if (!$entryId) {
745
				return $res;
746
			}
747
748
			$res['length'] = strlen($entryId);
749
			$offset = 0;
750
751
			$res['abflags'] = substr($entryId, $offset, 8);
752
			$offset += 8;
753
754
			$res['providerguid'] = substr($entryId, $offset, 32);
755
			$offset += 32;
756
757
			$res['foldertype'] = substr($entryId, $offset, 4);
758
			$offset += 4;
759
760
			$res['folderdbguid'] = substr($entryId, $offset, 32);
761
			$offset += 32;
762
763
			$res['foldercounter'] = substr($entryId, $offset, 12);
764
			$offset += 12;
765
766
			$res['padding'] = substr($entryId, $offset, 4);
767
			$offset += 4;
768
769
			return $res;
770
		}
771
	}
772
773
	// Create global entryId object
774
	$GLOBALS["entryid"] = new EntryId();
775