Passed
Branch master (f497d2)
by Mike
03:18
created

MAPIUtils::IsInCalendarSyncInterval()   B

Complexity

Conditions 11
Paths 2

Size

Total Lines 35
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 18
nc 2
nop 3
dl 0
loc 35
rs 7.3166
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * SPDX-License-Identifier: AGPL-3.0-only
4
 * SPDX-FileCopyrightText: Copyright 2007-2013,2016 Zarafa Deutschland GmbH
5
 * SPDX-FileCopyrightText: Copyright 2020-2022 grommunio GmbH
6
 */
7
8
/**
9
 * MAPI to AS mapping class.
10
 */
11
class MAPIUtils {
12
	/**
13
	 * Create a MAPI restriction to use within an email folder which will
14
	 * return all messages since since $timestamp.
15
	 *
16
	 * @param long $timestamp Timestamp since when to include messages
0 ignored issues
show
Bug introduced by
The type long 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...
17
	 *
18
	 * @return array
19
	 */
20
	public static function GetEmailRestriction($timestamp) {
21
		// ATTENTION: ON CHANGING THIS RESTRICTION, MAPIUtils::IsInEmailSyncInterval() also needs to be changed
22
		return [
23
			RES_PROPERTY,
24
			[
25
				RELOP => RELOP_GE,
26
				ULPROPTAG => PR_MESSAGE_DELIVERY_TIME,
27
				VALUE => $timestamp,
28
			],
29
		];
30
	}
31
32
	/**
33
	 * Create a MAPI restriction to use in the calendar which will
34
	 * return all future calendar items, plus those since $timestamp.
35
	 *
36
	 * @param MAPIStore $store     the MAPI store
0 ignored issues
show
Bug introduced by
The type MAPIStore 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...
37
	 * @param long      $timestamp Timestamp since when to include messages
38
	 *
39
	 * @return array
40
	 */
41
	// TODO getting named properties
42
	public static function GetCalendarRestriction($store, $timestamp) {
43
		// This is our viewing window
44
		$start = $timestamp;
45
		$end = 0x7FFFFFFF; // infinite end
46
47
		$props = MAPIMapping::GetAppointmentProperties();
48
		$props = getPropIdsFromStrings($store, $props);
49
50
		// ATTENTION: ON CHANGING THIS RESTRICTION, MAPIUtils::IsInCalendarSyncInterval() also needs to be changed
51
		return [
52
			RES_OR,
53
			[
54
				// OR
55
				// item.end > window.start && item.start < window.end
56
				[
57
					RES_AND,
58
					[
59
						[
60
							RES_PROPERTY,
61
							[
62
								RELOP => RELOP_LE,
63
								ULPROPTAG => $props["starttime"],
64
								VALUE => $end,
65
							],
66
						],
67
						[
68
							RES_PROPERTY,
69
							[
70
								RELOP => RELOP_GE,
71
								ULPROPTAG => $props["endtime"],
72
								VALUE => $start,
73
							],
74
						],
75
					],
76
				],
77
				// OR
78
				[
79
					RES_OR,
80
					[
81
						// OR
82
						// (EXIST(recurrence_enddate_property) && item[isRecurring] == true && recurrence_enddate_property >= start)
83
						[
84
							RES_AND,
85
							[
86
								[
87
									RES_EXIST,
88
									[ULPROPTAG => $props["recurrenceend"],
89
									],
90
								],
91
								[
92
									RES_PROPERTY,
93
									[
94
										RELOP => RELOP_EQ,
95
										ULPROPTAG => $props["isrecurring"],
96
										VALUE => true,
97
									],
98
								],
99
								[
100
									RES_PROPERTY,
101
									[
102
										RELOP => RELOP_GE,
103
										ULPROPTAG => $props["recurrenceend"],
104
										VALUE => $start,
105
									],
106
								],
107
							],
108
						],
109
						// OR
110
						// (!EXIST(recurrence_enddate_property) && item[isRecurring] == true && item[start] <= end)
111
						[
112
							RES_AND,
113
							[
114
								[
115
									RES_NOT,
116
									[
117
										[
118
											RES_EXIST,
119
											[ULPROPTAG => $props["recurrenceend"],
120
											],
121
										],
122
									],
123
								],
124
								[
125
									RES_PROPERTY,
126
									[
127
										RELOP => RELOP_LE,
128
										ULPROPTAG => $props["starttime"],
129
										VALUE => $end,
130
									],
131
								],
132
								[
133
									RES_PROPERTY,
134
									[
135
										RELOP => RELOP_EQ,
136
										ULPROPTAG => $props["isrecurring"],
137
										VALUE => true,
138
									],
139
								],
140
							],
141
						],
142
					],
143
				], // EXISTS OR
144
			],
145
		];        // global OR
146
	}
147
148
	/**
149
	 * Create a MAPI restriction in order to check if a contact has a picture.
150
	 *
151
	 * @return array
152
	 */
153
	public static function GetContactPicRestriction() {
154
		return [
155
			RES_PROPERTY,
156
			[
157
				RELOP => RELOP_EQ,
158
				ULPROPTAG => mapi_prop_tag(PT_BOOLEAN, 0x7FFF),
1 ignored issue
show
Bug introduced by
The function mapi_prop_tag was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

158
				ULPROPTAG => /** @scrutinizer ignore-call */ mapi_prop_tag(PT_BOOLEAN, 0x7FFF),
Loading history...
159
				VALUE => true,
160
			],
161
		];
162
	}
163
164
	/**
165
	 * Create a MAPI restriction for search.
166
	 *
167
	 * @param string $query
168
	 *
169
	 * @return array
170
	 */
171
	public static function GetSearchRestriction($query) {
172
		return [
173
			RES_AND,
174
			[
175
				[
176
					RES_OR,
177
					[
178
						[
179
							RES_CONTENT,
180
							[
181
								FUZZYLEVEL => FL_SUBSTRING | FL_IGNORECASE,
182
								ULPROPTAG => PR_DISPLAY_NAME,
183
								VALUE => $query,
184
							],
185
						],
186
						[
187
							RES_CONTENT,
188
							[
189
								FUZZYLEVEL => FL_SUBSTRING | FL_IGNORECASE,
190
								ULPROPTAG => PR_ACCOUNT,
191
								VALUE => $query,
192
							],
193
						],
194
						[
195
							RES_CONTENT,
196
							[
197
								FUZZYLEVEL => FL_SUBSTRING | FL_IGNORECASE,
198
								ULPROPTAG => PR_SMTP_ADDRESS,
199
								VALUE => $query,
200
							],
201
						],
202
					], // RES_OR
203
				],
204
				[
205
					RES_OR,
206
					[
207
						[
208
							RES_PROPERTY,
209
							[
210
								RELOP => RELOP_EQ,
211
								ULPROPTAG => PR_OBJECT_TYPE,
212
								VALUE => MAPI_MAILUSER,
213
							],
214
						],
215
						[
216
							RES_PROPERTY,
217
							[
218
								RELOP => RELOP_EQ,
219
								ULPROPTAG => PR_OBJECT_TYPE,
220
								VALUE => MAPI_DISTLIST,
221
							],
222
						],
223
					],
224
				], // RES_OR
225
			], // RES_AND
226
		];
227
	}
228
229
	/**
230
	 * Create a MAPI restriction for a certain email address.
231
	 *
232
	 * @param MAPIStore $store the MAPI store
233
	 * @param string    $query email address
234
	 * @param mixed     $email
235
	 *
236
	 * @return array
237
	 */
238
	public static function GetEmailAddressRestriction($store, $email) {
239
		$props = MAPIMapping::GetContactProperties();
240
		$props = getPropIdsFromStrings($store, $props);
241
242
		return [
243
			RES_OR,
244
			[
245
				[
246
					RES_PROPERTY,
247
					[
248
						RELOP => RELOP_EQ,
249
						ULPROPTAG => $props['emailaddress1'],
250
						VALUE => [$props['emailaddress1'] => $email],
251
					],
252
				],
253
				[
254
					RES_PROPERTY,
255
					[
256
						RELOP => RELOP_EQ,
257
						ULPROPTAG => $props['emailaddress2'],
258
						VALUE => [$props['emailaddress2'] => $email],
259
					],
260
				],
261
				[
262
					RES_PROPERTY,
263
					[
264
						RELOP => RELOP_EQ,
265
						ULPROPTAG => $props['emailaddress3'],
266
						VALUE => [$props['emailaddress3'] => $email],
267
					],
268
				],
269
			],
270
		];
271
	}
272
273
	/**
274
	 * Create a MAPI restriction for a certain folder type.
275
	 *
276
	 * @param string $foldertype folder type for restriction
277
	 *
278
	 * @return array
279
	 */
280
	public static function GetFolderTypeRestriction($foldertype) {
281
		return [
282
			RES_PROPERTY,
283
			[
284
				RELOP => RELOP_EQ,
285
				ULPROPTAG => PR_CONTAINER_CLASS,
286
				VALUE => [PR_CONTAINER_CLASS => $foldertype],
287
			],
288
		];
289
	}
290
291
	/**
292
	 * Returns subfolders of given type for a folder or false if there are none.
293
	 *
294
	 * @param MAPIFolder $folder
0 ignored issues
show
Bug introduced by
The type MAPIFolder 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...
295
	 * @param string     $type
296
	 *
297
	 * @return bool|MAPITable
0 ignored issues
show
Bug introduced by
The type MAPITable 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...
298
	 */
299
	public static function GetSubfoldersForType($folder, $type) {
300
		$subfolders = mapi_folder_gethierarchytable($folder, CONVENIENT_DEPTH);
1 ignored issue
show
Bug introduced by
The function mapi_folder_gethierarchytable was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

300
		$subfolders = /** @scrutinizer ignore-call */ mapi_folder_gethierarchytable($folder, CONVENIENT_DEPTH);
Loading history...
301
		mapi_table_restrict($subfolders, MAPIUtils::GetFolderTypeRestriction($type));
1 ignored issue
show
Bug introduced by
The function mapi_table_restrict was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

301
		/** @scrutinizer ignore-call */ 
302
  mapi_table_restrict($subfolders, MAPIUtils::GetFolderTypeRestriction($type));
Loading history...
302
		if (mapi_table_getrowcount($subfolders) > 0) {
1 ignored issue
show
Bug introduced by
The function mapi_table_getrowcount was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

302
		if (/** @scrutinizer ignore-call */ mapi_table_getrowcount($subfolders) > 0) {
Loading history...
303
			return mapi_table_queryallrows($subfolders, [PR_ENTRYID]);
1 ignored issue
show
Bug introduced by
The function mapi_table_queryallrows was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

303
			return /** @scrutinizer ignore-call */ mapi_table_queryallrows($subfolders, [PR_ENTRYID]);
Loading history...
304
		}
305
306
		return false;
307
	}
308
309
	/**
310
	 * Checks if mapimessage is inside the synchronization interval
311
	 * also defined by MAPIUtils::GetEmailRestriction().
312
	 *
313
	 * @param MAPIStore   $store       mapi store
314
	 * @param MAPIMessage $mapimessage the mapi message to be checked
0 ignored issues
show
Bug introduced by
The type MAPIMessage 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 long        $timestamp   the lower time limit
316
	 *
317
	 * @return bool
318
	 */
319
	public static function IsInEmailSyncInterval($store, $mapimessage, $timestamp) {
320
		$p = mapi_getprops($mapimessage, [PR_MESSAGE_DELIVERY_TIME]);
1 ignored issue
show
Bug introduced by
The function mapi_getprops was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

320
		$p = /** @scrutinizer ignore-call */ mapi_getprops($mapimessage, [PR_MESSAGE_DELIVERY_TIME]);
Loading history...
321
322
		if (isset($p[PR_MESSAGE_DELIVERY_TIME]) && $p[PR_MESSAGE_DELIVERY_TIME] >= $timestamp) {
323
			SLog::Write(LOGLEVEL_DEBUG, "MAPIUtils->IsInEmailSyncInterval: Message is in the synchronization interval");
324
325
			return true;
326
		}
327
328
		SLog::Write(LOGLEVEL_WARN, "MAPIUtils->IsInEmailSyncInterval: Message is OUTSIDE the synchronization interval");
329
330
		return false;
331
	}
332
333
	/**
334
	 * Checks if mapimessage is inside the synchronization interval
335
	 * also defined by MAPIUtils::GetCalendarRestriction().
336
	 *
337
	 * @param MAPIStore   $store       mapi store
338
	 * @param MAPIMessage $mapimessage the mapi message to be checked
339
	 * @param long        $timestamp   the lower time limit
340
	 *
341
	 * @return bool
342
	 */
343
	public static function IsInCalendarSyncInterval($store, $mapimessage, $timestamp) {
344
		// This is our viewing window
345
		$start = $timestamp;
346
		$end = 0x7FFFFFFF; // infinite end
347
348
		$props = MAPIMapping::GetAppointmentProperties();
349
		$props = getPropIdsFromStrings($store, $props);
350
351
		$p = mapi_getprops($mapimessage, [$props["starttime"], $props["endtime"], $props["recurrenceend"], $props["isrecurring"], $props["recurrenceend"]]);
1 ignored issue
show
Bug introduced by
The function mapi_getprops was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

351
		$p = /** @scrutinizer ignore-call */ mapi_getprops($mapimessage, [$props["starttime"], $props["endtime"], $props["recurrenceend"], $props["isrecurring"], $props["recurrenceend"]]);
Loading history...
352
353
		if (
354
				(
355
					isset($p[$props["endtime"]], $p[$props["starttime"]]) &&
356
					// item.end > window.start && item.start < window.end
357
					$p[$props["endtime"]] > $start && $p[$props["starttime"]] < $end
358
				) ||
359
			(
360
				isset($p[$props["isrecurring"]], $p[$props["recurrenceend"]]) &&
361
					// (EXIST(recurrence_enddate_property) && item[isRecurring] == true && recurrence_enddate_property >= start)
362
					 $p[$props["isrecurring"]] == true && $p[$props["recurrenceend"]] >= $start
363
			) ||
364
			(
365
				isset($p[$props["isrecurring"]], $p[$props["starttime"]]) &&
366
					// (!EXIST(recurrence_enddate_property) && item[isRecurring] == true && item[start] <= end)
367
					!isset($p[$props["recurrenceend"]]) && $p[$props["isrecurring"]] == true && $p[$props["starttime"]] <= $end
368
			)
369
		   ) {
370
			SLog::Write(LOGLEVEL_DEBUG, "MAPIUtils->IsInCalendarSyncInterval: Message is in the synchronization interval");
371
372
			return true;
373
		}
374
375
		SLog::Write(LOGLEVEL_WARN, "MAPIUtils->IsInCalendarSyncInterval: Message is OUTSIDE the synchronization interval");
376
377
		return false;
378
	}
379
380
	/**
381
	 * Checks if mapimessage is in a shared folder and private.
382
	 *
383
	 * @param string      $folderid    binary folderid of the message
384
	 * @param MAPIMessage $mapimessage the mapi message to be checked
385
	 *
386
	 * @return bool
387
	 */
388
	public static function IsMessageSharedAndPrivate($folderid, $mapimessage) {
389
		$sensitivity = mapi_getprops($mapimessage, [PR_SENSITIVITY]);
1 ignored issue
show
Bug introduced by
The function mapi_getprops was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

389
		$sensitivity = /** @scrutinizer ignore-call */ mapi_getprops($mapimessage, [PR_SENSITIVITY]);
Loading history...
390
		if (isset($sensitivity[PR_SENSITIVITY]) && $sensitivity[PR_SENSITIVITY] >= SENSITIVITY_PRIVATE) {
391
			$hexFolderid = bin2hex($folderid);
392
			$shortId = GSync::GetDeviceManager()->GetFolderIdForBackendId($hexFolderid);
393
			if (Utils::GetFolderOriginFromId($shortId) == DeviceManager::FLD_ORIGIN_IMPERSONATED) {
394
				SLog::Write(LOGLEVEL_DEBUG, sprintf("MAPIUtils->IsMessageSharedAndPrivate(): Message is in impersonated store '%s' and marked as private", GSync::GetBackend()->GetImpersonatedUser()));
395
396
				return true;
397
			}
398
			$sharedUser = GSync::GetAdditionalSyncFolderStore($hexFolderid);
399
			if (Utils::GetFolderOriginFromId($shortId) != DeviceManager::FLD_ORIGIN_USER && $sharedUser != false && $sharedUser != 'SYSTEM') {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $sharedUser of type string to the boolean false. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
400
				SLog::Write(LOGLEVEL_DEBUG, sprintf("MAPIUtils->IsMessageSharedAndPrivate(): Message is in shared store '%s' and marked as private", $sharedUser));
401
402
				return true;
403
			}
404
		}
405
406
		return false;
407
	}
408
409
	/**
410
	 * Reads data of large properties from a stream.
411
	 *
412
	 * @param MAPIMessage $message
413
	 * @param long        $prop
414
	 *
415
	 * @return string
416
	 */
417
	public static function readPropStream($message, $prop) {
418
		$stream = mapi_openproperty($message, $prop, IID_IStream, 0, 0);
1 ignored issue
show
Bug introduced by
The function mapi_openproperty was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

418
		$stream = /** @scrutinizer ignore-call */ mapi_openproperty($message, $prop, IID_IStream, 0, 0);
Loading history...
419
		$ret = mapi_last_hresult();
1 ignored issue
show
Bug introduced by
The function mapi_last_hresult was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

419
		$ret = /** @scrutinizer ignore-call */ mapi_last_hresult();
Loading history...
420
		if ($ret == MAPI_E_NOT_FOUND) {
421
			SLog::Write(LOGLEVEL_DEBUG, sprintf("MAPIUtils->readPropStream: property 0x%08X not found. It is either empty or not set. It will be ignored.", $prop));
422
423
			return "";
424
		}
425
		if ($ret) {
426
			SLog::Write(LOGLEVEL_ERROR, "MAPIUtils->readPropStream error opening stream: 0x%08X", $ret);
427
428
			return "";
429
		}
430
		$data = "";
0 ignored issues
show
Unused Code introduced by
The assignment to $data is dead and can be removed.
Loading history...
431
		$string = "";
432
		while (1) {
433
			$data = mapi_stream_read($stream, 1024);
1 ignored issue
show
Bug introduced by
The function mapi_stream_read was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

433
			$data = /** @scrutinizer ignore-call */ mapi_stream_read($stream, 1024);
Loading history...
434
			if (strlen($data) == 0) {
435
				break;
436
			}
437
			$string .= $data;
438
		}
439
440
		return $string;
441
	}
442
443
	/**
444
	 * Checks if a store supports properties containing unicode characters.
445
	 *
446
	 * @param MAPIStore $store
447
	 *
448
	 * @return
449
	 */
450
	public static function IsUnicodeStore($store) {
451
		$supportmask = mapi_getprops($store, [PR_STORE_SUPPORT_MASK]);
1 ignored issue
show
Bug introduced by
The function mapi_getprops was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

451
		$supportmask = /** @scrutinizer ignore-call */ mapi_getprops($store, [PR_STORE_SUPPORT_MASK]);
Loading history...
452
		if (isset($supportmask[PR_STORE_SUPPORT_MASK]) && ($supportmask[PR_STORE_SUPPORT_MASK] & STORE_UNICODE_OK)) {
453
			SLog::Write(LOGLEVEL_DEBUG, "Store supports properties containing Unicode characters.");
454
			define('STORE_SUPPORTS_UNICODE', true);
455
			define('STORE_INTERNET_CPID', INTERNET_CPID_UTF8);
456
		}
457
	}
458
459
	/**
460
	 * Returns the MAPI PR_CONTAINER_CLASS string for an ActiveSync Foldertype.
461
	 *
462
	 * @param int $foldertype
463
	 *
464
	 * @return string
465
	 */
466
	public static function GetContainerClassFromFolderType($foldertype) {
467
		switch ($foldertype) {
468
			case SYNC_FOLDER_TYPE_TASK:
469
			case SYNC_FOLDER_TYPE_USER_TASK:
470
				return "IPF.Task";
471
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
472
473
			case SYNC_FOLDER_TYPE_APPOINTMENT:
474
			case SYNC_FOLDER_TYPE_USER_APPOINTMENT:
475
				return "IPF.Appointment";
476
				break;
477
478
			case SYNC_FOLDER_TYPE_CONTACT:
479
			case SYNC_FOLDER_TYPE_USER_CONTACT:
480
				return "IPF.Contact";
481
				break;
482
483
			case SYNC_FOLDER_TYPE_NOTE:
484
			case SYNC_FOLDER_TYPE_USER_NOTE:
485
				return "IPF.StickyNote";
486
				break;
487
488
			case SYNC_FOLDER_TYPE_JOURNAL:
489
			case SYNC_FOLDER_TYPE_USER_JOURNAL:
490
				return "IPF.Journal";
491
				break;
492
493
			case SYNC_FOLDER_TYPE_INBOX:
494
			case SYNC_FOLDER_TYPE_DRAFTS:
495
			case SYNC_FOLDER_TYPE_WASTEBASKET:
496
			case SYNC_FOLDER_TYPE_SENTMAIL:
497
			case SYNC_FOLDER_TYPE_OUTBOX:
498
			case SYNC_FOLDER_TYPE_USER_MAIL:
499
			case SYNC_FOLDER_TYPE_OTHER:
500
			case SYNC_FOLDER_TYPE_UNKNOWN:
501
			default:
502
				return "IPF.Note";
503
				break;
504
		}
505
	}
506
507
	public static function GetSignedAttachmentRestriction() {
508
		return [
509
			RES_PROPERTY,
510
			[
511
				RELOP => RELOP_EQ,
512
				ULPROPTAG => PR_ATTACH_MIME_TAG,
513
				VALUE => [PR_ATTACH_MIME_TAG => 'multipart/signed'],
514
			],
515
		];
516
	}
517
518
	/**
519
	 * Calculates the native body type of a message using available properties. Refer to oxbbody.
520
	 *
521
	 * @param array $messageprops
522
	 *
523
	 * @return int
524
	 */
525
	public static function GetNativeBodyType($messageprops) {
526
		// check if the properties are set and get the error code if needed
527
		if (!isset($messageprops[PR_BODY])) {
528
			$messageprops[PR_BODY] = self::GetError(PR_BODY, $messageprops);
529
		}
530
		if (!isset($messageprops[PR_RTF_COMPRESSED])) {
531
			$messageprops[PR_RTF_COMPRESSED] = self::GetError(PR_RTF_COMPRESSED, $messageprops);
532
		}
533
		if (!isset($messageprops[PR_HTML])) {
534
			$messageprops[PR_HTML] = self::GetError(PR_HTML, $messageprops);
535
		}
536
		if (!isset($messageprops[PR_RTF_IN_SYNC])) {
537
			$messageprops[PR_RTF_IN_SYNC] = self::GetError(PR_RTF_IN_SYNC, $messageprops);
538
		}
539
540
		if ( // 1
541
				($messageprops[PR_BODY] == MAPI_E_NOT_FOUND) &&
542
				($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_FOUND) &&
543
				($messageprops[PR_HTML] == MAPI_E_NOT_FOUND)) {
544
			return SYNC_BODYPREFERENCE_PLAIN;
545
		}
546
		if ( // 2
547
				($messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
548
				($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_FOUND) &&
549
				($messageprops[PR_HTML] == MAPI_E_NOT_FOUND)) {
550
			return SYNC_BODYPREFERENCE_PLAIN;
551
		}
552
		if ( // 3
553
				($messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
554
				($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
555
				($messageprops[PR_HTML] == MAPI_E_NOT_FOUND)) {
556
			return SYNC_BODYPREFERENCE_RTF;
557
		}
558
		if ( // 4
559
				($messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
560
				($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
561
				($messageprops[PR_HTML] == MAPI_E_NOT_ENOUGH_MEMORY) &&
562
				($messageprops[PR_RTF_IN_SYNC])) {
563
			return SYNC_BODYPREFERENCE_RTF;
564
		}
565
		if ( // 5
566
				($messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
567
				($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
568
				($messageprops[PR_HTML] == MAPI_E_NOT_ENOUGH_MEMORY) &&
569
				(!$messageprops[PR_RTF_IN_SYNC])) {
570
			return SYNC_BODYPREFERENCE_HTML;
571
		}
572
		if ( // 6
573
				($messageprops[PR_RTF_COMPRESSED] != MAPI_E_NOT_FOUND || $messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
574
				($messageprops[PR_HTML] != MAPI_E_NOT_FOUND || $messageprops[PR_HTML] == MAPI_E_NOT_ENOUGH_MEMORY) &&
575
				($messageprops[PR_RTF_IN_SYNC])) {
576
			return SYNC_BODYPREFERENCE_RTF;
577
		}
578
		if ( // 7
579
				($messageprops[PR_RTF_COMPRESSED] != MAPI_E_NOT_FOUND || $messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
580
				($messageprops[PR_HTML] != MAPI_E_NOT_FOUND || $messageprops[PR_HTML] == MAPI_E_NOT_ENOUGH_MEMORY) &&
581
				(!$messageprops[PR_RTF_IN_SYNC])) {
582
			return SYNC_BODYPREFERENCE_HTML;
583
		}
584
		if ( // 8
585
				($messageprops[PR_BODY] != MAPI_E_NOT_FOUND || $messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
586
				($messageprops[PR_RTF_COMPRESSED] != MAPI_E_NOT_FOUND || $messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
587
				($messageprops[PR_RTF_IN_SYNC])) {
588
			return SYNC_BODYPREFERENCE_RTF;
589
		}
590
		if ( // 9.1
591
				($messageprops[PR_BODY] != MAPI_E_NOT_FOUND || $messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
592
				($messageprops[PR_RTF_COMPRESSED] != MAPI_E_NOT_FOUND || $messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
593
				(!$messageprops[PR_RTF_IN_SYNC])) {
594
			return SYNC_BODYPREFERENCE_PLAIN;
595
		}
596
		if ( // 9.2
597
				($messageprops[PR_RTF_COMPRESSED] != MAPI_E_NOT_FOUND || $messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
598
				($messageprops[PR_BODY] == MAPI_E_NOT_FOUND) &&
599
				($messageprops[PR_HTML] == MAPI_E_NOT_FOUND)) {
600
			return SYNC_BODYPREFERENCE_RTF;
601
		}
602
		if ( // 9.3
603
				($messageprops[PR_BODY] != MAPI_E_NOT_FOUND || $messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
604
				($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_FOUND) &&
605
				($messageprops[PR_HTML] == MAPI_E_NOT_FOUND)) {
606
			return SYNC_BODYPREFERENCE_PLAIN;
607
		}
608
		if ( // 9.4
609
				($messageprops[PR_HTML] != MAPI_E_NOT_FOUND || $messageprops[PR_HTML] == MAPI_E_NOT_ENOUGH_MEMORY) &&
610
				($messageprops[PR_BODY] == MAPI_E_NOT_FOUND) &&
611
				($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_FOUND)) {
612
			return SYNC_BODYPREFERENCE_HTML;
613
		}
614
		// 10
615
		return SYNC_BODYPREFERENCE_PLAIN;
616
	}
617
618
	/**
619
	 * Returns the error code for a given property.
620
	 * Helper for MAPIUtils::GetNativeBodyType() function but also used in other places.
621
	 *
622
	 * @param int   $tag
623
	 * @param array $messageprops
624
	 *
625
	 * @return int (MAPI_ERROR_CODE)
626
	 */
627
	public static function GetError($tag, $messageprops) {
628
		$prBodyError = mapi_prop_tag(PT_ERROR, mapi_prop_id($tag));
2 ignored issues
show
Bug introduced by
The function mapi_prop_tag was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

628
		$prBodyError = /** @scrutinizer ignore-call */ mapi_prop_tag(PT_ERROR, mapi_prop_id($tag));
Loading history...
Bug introduced by
The function mapi_prop_id was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

628
		$prBodyError = mapi_prop_tag(PT_ERROR, /** @scrutinizer ignore-call */ mapi_prop_id($tag));
Loading history...
629
		if (isset($messageprops[$prBodyError]) && mapi_is_error($messageprops[$prBodyError])) {
1 ignored issue
show
Bug introduced by
The function mapi_is_error was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

629
		if (isset($messageprops[$prBodyError]) && /** @scrutinizer ignore-call */ mapi_is_error($messageprops[$prBodyError])) {
Loading history...
630
			if ($messageprops[$prBodyError] == MAPI_E_NOT_ENOUGH_MEMORY_32BIT ||
631
					$messageprops[$prBodyError] == MAPI_E_NOT_ENOUGH_MEMORY_64BIT) {
632
				return MAPI_E_NOT_ENOUGH_MEMORY;
633
			}
634
		}
635
636
		return MAPI_E_NOT_FOUND;
637
	}
638
639
	/**
640
	 * Function will be used to decode smime messages and convert it to normal messages.
641
	 *
642
	 * @param MAPISession    $session
0 ignored issues
show
Bug introduced by
The type MAPISession 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...
643
	 * @param MAPIStore      $store
644
	 * @param MAPIAdressBook $addressBook
0 ignored issues
show
Bug introduced by
The type MAPIAdressBook 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...
645
	 * @param MAPIMessage    $message     smime message
646
	 * @param mixed          $mapimessage
647
	 */
648
	public static function ParseSmime($session, $store, $addressBook, &$mapimessage) {
649
		$props = mapi_getprops($mapimessage, [PR_MESSAGE_CLASS, PR_SUBJECT, PR_MESSAGE_DELIVERY_TIME, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_SEARCH_KEY, PR_MESSAGE_FLAGS]);
1 ignored issue
show
Bug introduced by
The function mapi_getprops was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

649
		$props = /** @scrutinizer ignore-call */ mapi_getprops($mapimessage, [PR_MESSAGE_CLASS, PR_SUBJECT, PR_MESSAGE_DELIVERY_TIME, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_SEARCH_KEY, PR_MESSAGE_FLAGS]);
Loading history...
650
		$read = $props[PR_MESSAGE_FLAGS] & MSGFLAG_READ;
651
652
		if (isset($props[PR_MESSAGE_CLASS]) && stripos($props[PR_MESSAGE_CLASS], 'IPM.Note.SMIME.MultipartSigned') !== false) {
653
			// this is a signed message. decode it.
654
			$attachTable = mapi_message_getattachmenttable($mapimessage);
1 ignored issue
show
Bug introduced by
The function mapi_message_getattachmenttable was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

654
			$attachTable = /** @scrutinizer ignore-call */ mapi_message_getattachmenttable($mapimessage);
Loading history...
655
			$rows = mapi_table_queryallrows($attachTable, [PR_ATTACH_MIME_TAG, PR_ATTACH_NUM]);
1 ignored issue
show
Bug introduced by
The function mapi_table_queryallrows was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

655
			$rows = /** @scrutinizer ignore-call */ mapi_table_queryallrows($attachTable, [PR_ATTACH_MIME_TAG, PR_ATTACH_NUM]);
Loading history...
656
			$attnum = false;
657
658
			foreach ($rows as $row) {
659
				if (isset($row[PR_ATTACH_MIME_TAG]) && $row[PR_ATTACH_MIME_TAG] == 'multipart/signed') {
660
					$attnum = $row[PR_ATTACH_NUM];
661
				}
662
			}
663
664
			if ($attnum !== false) {
665
				$att = mapi_message_openattach($mapimessage, $attnum);
1 ignored issue
show
Bug introduced by
The function mapi_message_openattach was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

665
				$att = /** @scrutinizer ignore-call */ mapi_message_openattach($mapimessage, $attnum);
Loading history...
666
				$data = mapi_openproperty($att, PR_ATTACH_DATA_BIN);
1 ignored issue
show
Bug introduced by
The function mapi_openproperty was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

666
				$data = /** @scrutinizer ignore-call */ mapi_openproperty($att, PR_ATTACH_DATA_BIN);
Loading history...
667
				mapi_message_deleteattach($mapimessage, $attnum);
1 ignored issue
show
Bug introduced by
The function mapi_message_deleteattach was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

667
				/** @scrutinizer ignore-call */ 
668
    mapi_message_deleteattach($mapimessage, $attnum);
Loading history...
668
				mapi_inetmapi_imtomapi($session, $store, $addressBook, $mapimessage, $data, ["parse_smime_signed" => 1]);
1 ignored issue
show
Bug introduced by
The function mapi_inetmapi_imtomapi was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

668
				/** @scrutinizer ignore-call */ 
669
    mapi_inetmapi_imtomapi($session, $store, $addressBook, $mapimessage, $data, ["parse_smime_signed" => 1]);
Loading history...
669
				SLog::Write(LOGLEVEL_DEBUG, "Convert a smime signed message to a normal message.");
670
			}
671
			$mprops = mapi_getprops($mapimessage, [PR_MESSAGE_FLAGS]);
672
			// Workaround for issue 13
673
			mapi_setprops($mapimessage, [
1 ignored issue
show
Bug introduced by
The function mapi_setprops was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

673
			/** @scrutinizer ignore-call */ 
674
   mapi_setprops($mapimessage, [
Loading history...
674
				PR_MESSAGE_CLASS => 'IPM.Note.SMIME.MultipartSigned',
675
				PR_SUBJECT => $props[PR_SUBJECT],
676
				PR_MESSAGE_DELIVERY_TIME => $props[PR_MESSAGE_DELIVERY_TIME],
677
				PR_SENT_REPRESENTING_NAME => $props[PR_SENT_REPRESENTING_NAME],
678
				PR_SENT_REPRESENTING_ENTRYID => $props[PR_SENT_REPRESENTING_ENTRYID],
679
				PR_SENT_REPRESENTING_SEARCH_KEY => $props[PR_SENT_REPRESENTING_SEARCH_KEY],
680
				// mark the message as read if the main message has read flag
681
				PR_MESSAGE_FLAGS => $read ? $mprops[PR_MESSAGE_FLAGS] | MSGFLAG_READ : $mprops[PR_MESSAGE_FLAGS],
682
			]);
683
		}
684
		// TODO check if we need to do this for encrypted (and signed?) message as well
685
	}
686
687
	/**
688
	 * Compares two entryIds. It is possible to have two different entryIds that should match as they
689
	 * represent the same object (in multiserver environments).
690
	 *
691
	 * @param string $entryId1
692
	 * @param string $entryId2
693
	 *
694
	 * @return bool
695
	 */
696
	public static function CompareEntryIds($entryId1, $entryId2) {
697
		if (!is_string($entryId1) || !is_string($entryId2)) {
0 ignored issues
show
introduced by
The condition is_string($entryId1) is always true.
Loading history...
introduced by
The condition is_string($entryId2) is always true.
Loading history...
698
			return false;
699
		}
700
701
		if ($entryId1 === $entryId2) {
702
			// if normal comparison succeeds then we can directly say that entryids are same
703
			return true;
704
		}
705
706
		$eid1 = self::createEntryIdObj($entryId1);
707
		$eid2 = self::createEntryIdObj($entryId2);
708
709
		if ($eid1['length'] != $eid2['length'] ||
710
				$eid1['abFlags'] != $eid2['abFlags'] ||
711
				$eid1['version'] != $eid2['version'] ||
712
				$eid1['type'] != $eid2['type']) {
713
			return false;
714
		}
715
716
		if ($eid1['name'] == 'EID_V0') {
717
			if ($eid1['length'] < $eid1['min_length'] || $eid1['id'] != $eid2['id']) {
718
				return false;
719
			}
720
		}
721
		elseif ($eid1['length'] < $eid1['min_length'] || $eid1['uniqueId'] != $eid2['uniqueId']) {
722
			return false;
723
		}
724
725
		return true;
726
	}
727
728
	/**
729
	 * Creates an object that has split up all the components of an entryID.
730
	 *
731
	 * @param string $entryid Entryid
732
	 *
733
	 * @return object EntryID object
734
	 */
735
	private static function createEntryIdObj($entryid) {
736
		// check if we are dealing with old or new object entryids
737
		return (substr($entryid, 40, 8) == '00000000') ? self::getEID_V0Version($entryid) : self::getEIDVersion($entryid);
0 ignored issues
show
Bug Best Practice introduced by
The expression return substr($entryid, ...getEIDVersion($entryid) also could return the type array<string,string> which is incompatible with the documented return type object.
Loading history...
738
	}
739
740
	/**
741
	 * The entryid from the begin of zarafa till 5.20.
742
	 *
743
	 * @param string $entryid
744
	 *
745
	 * @return object EntryID object
746
	 */
747
	private static function getEID_V0Version($entryid) {
748
		// always make entryids in uppercase so comparison will be case insensitive
749
		$entryId = strtoupper($entryid);
750
751
		$res = [
752
			'abFlags' => '',  // BYTE[4],  4 bytes,  8 hex characters
753
			'guid' => '',  // GUID,    16 bytes, 32 hex characters
754
			'version' => '',  // ULONG,    4 bytes,  8 hex characters
755
			'type' => '',  // ULONG,    4 bytes,  8 hex characters
756
			'id' => '',  // ULONG,    4 bytes,  8 hex characters
757
			'server' => '',  // CHAR,    variable length
758
			'padding' => '',  // TCHAR[3], 4 bytes,  8 hex characters (upto 4 bytes)
759
		];
760
761
		$res['length'] = strlen($entryId);
762
		$offset = 0;
763
764
		// First determine padding, and remove if from the entryId
765
		$res['padding'] = self::getPadding($entryId);
766
		$entryId = substr($entryId, 0, strlen($entryId) - strlen($res['padding']));
767
768
		$res['abFlags'] = substr($entryId, $offset, 8);
769
		$offset = +8;
770
771
		$res['guid'] = substr($entryId, $offset, 32);
772
		$offset += 32;
773
774
		$res['version'] = substr($entryId, $offset, 8);
775
		$offset += 8;
776
777
		$res['type'] = substr($entryId, $offset, 8);
778
		$offset += 8;
779
780
		$res['id'] = substr($entryId, $offset, 8);
781
		$offset += 8;
782
783
		$res['server'] = substr($entryId, $offset);
784
785
		$res['min_length'] = 64;
786
		$res['name'] = 'EID_V0';
787
788
		return $res;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $res returns the type array<string,string> which is incompatible with the documented return type object.
Loading history...
789
	}
790
791
	/**
792
	 * Entryid from version 6.
793
	 *
794
	 * @param string $entryid
795
	 *
796
	 * @return null[]|number[]|string[]
797
	 */
798
	private static function getEIDVersion($entryid) {
799
		// always make entryids in uppercase so comparison will be case insensitive
800
		$entryId = strtoupper($entryid);
801
802
		$res = [
803
			'abFlags' => '',  // BYTE[4],  4 bytes,  8 hex characters
804
			'guid' => '',  // GUID,    16 bytes, 32 hex characters
805
			'version' => '',  // ULONG,    4 bytes,  8 hex characters
806
			'type' => '',  // ULONG,    4 bytes,  8 hex characters
807
			'uniqueId' => '',  // ULONG,   16 bytes,  32 hex characters
808
			'server' => '',  // CHAR,    variable length
809
			'padding' => '',  // TCHAR[3], 4 bytes,  8 hex characters (upto 4 bytes)
810
		];
811
812
		$res['length'] = strlen($entryId);
813
		$offset = 0;
814
815
		// First determine padding, and remove if from the entryId
816
		$res['padding'] = self::getPadding($entryId);
817
		$entryId = substr($entryId, 0, strlen($entryId) - strlen($res['padding']));
818
819
		$res['abFlags'] = substr($entryId, $offset, 8);
820
		$offset = +8;
821
822
		$res['guid'] = substr($entryId, $offset, 32);
823
		$offset += 32;
824
825
		$res['version'] = substr($entryId, $offset, 8);
826
		$offset += 8;
827
828
		$res['type'] = substr($entryId, $offset, 8);
829
		$offset += 8;
830
831
		$res['uniqueId'] = substr($entryId, $offset, 32);
832
		$offset += 32;
833
834
		$res['server'] = substr($entryId, $offset);
835
836
		$res['min_length'] = 88;
837
		$res['name'] = 'EID';
838
839
		return $res;
840
	}
841
842
	/**
843
	 * Detect padding (max 3 bytes) from the entryId.
844
	 *
845
	 * @param string $entryId
846
	 *
847
	 * @return string
848
	 */
849
	private static function getPadding($entryId) {
850
		$len = strlen($entryId);
851
		$padding = '';
852
		$offset = 0;
853
854
		for ($iterations = 4; $iterations > 0; --$iterations) {
855
			if (substr($entryId, $len - ($offset + 2), $len - $offset) == '00') {
856
				$padding .= '00';
857
				$offset += 2;
858
			}
859
			else {
860
				// if non-null character found then break the loop
861
				break;
862
			}
863
		}
864
865
		return $padding;
866
	}
867
}
868