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

listfolders_handle()   A

Complexity

Conditions 5
Paths 12

Size

Total Lines 39
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 5
eloc 28
nc 12
nop 0
dl 0
loc 39
rs 9.1608
c 1
b 1
f 0
1
#!/usr/bin/env php
2
<?php
3
/*
4
 * SPDX-License-Identifier: AGPL-3.0-only
5
 * SPDX-FileCopyrightText: Copyright 2007-2013,2015-2016 Zarafa Deutschland GmbH
6
 * SPDX-FileCopyrightText: Copyright 2020-2022 grommunio GmbH
7
 *
8
 * This is a small command line tool to list folders of a user store or public
9
 * folder available for synchronization.
10
 */
11
12
define('MAPI_SERVER', 'default:');
13
define('SSLCERT_FILE', null);
14
define('SSLCERT_PASS', null);
15
16
$supported_classes = [
17
	"IPF.Note" => "SYNC_FOLDER_TYPE_USER_MAIL",
18
	"IPF.Task" => "SYNC_FOLDER_TYPE_USER_TASK",
19
	"IPF.Appointment" => "SYNC_FOLDER_TYPE_USER_APPOINTMENT",
20
	"IPF.Contact" => "SYNC_FOLDER_TYPE_USER_CONTACT",
21
	"IPF.StickyNote" => "SYNC_FOLDER_TYPE_USER_NOTE",
22
];
23
24
main();
25
26
function main() {
27
	listfolders_configure();
28
	listfolders_handle();
29
}
30
31
function listfolders_configure() {
32
	if (php_sapi_name() != "cli") {
33
		fwrite(STDERR, "This script can only be called from the CLI.\n");
34
35
		exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
36
	}
37
38
	if (!function_exists("getopt")) {
39
		echo "PHP Function 'getopt()' not found. Please check your PHP version and settings.\n";
40
41
		exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
42
	}
43
44
	require 'mapi/mapi.util.php';
45
	require 'mapi/mapidefs.php';
46
	require 'mapi/mapicode.php';
47
	require 'mapi/mapitags.php';
48
	require 'mapi/mapiguid.php';
49
}
50
51
function listfolders_handle() {
52
	$shortoptions = "l:h:u:p:c:";
53
	$options = getopt($shortoptions);
54
55
	$mapi = MAPI_SERVER;
56
	$sslcert_file = SSLCERT_FILE;
57
	$sslcert_pass = SSLCERT_PASS;
58
	$user = "SYSTEM";
59
	$pass = "";
60
61
	if (isset($options['h'])) {
62
		$mapi = $options['h'];
63
	}
64
65
	// accept a remote user
66
	if (isset($options['u'], $options['p'])) {
67
		$user = $options['u'];
68
		$pass = $options['p'];
69
	}
70
	// accept a certificate and passwort for login
71
	elseif (isset($options['c'], $options['p'])) {
72
		$sslcert_file = $options['c'];
73
		$sslcert_pass = $options['p'];
74
	}
75
76
	$zarafaAdmin = listfolders_zarafa_admin_setup($mapi, $user, $pass, $sslcert_file, $sslcert_pass);
77
	if (isset($zarafaAdmin['adminStore'], $options['l'])) {
78
		listfolders_getlist($zarafaAdmin['adminStore'], $zarafaAdmin['session'], trim($options['l']));
79
	}
80
	else {
81
		echo "Usage:\n" .
82
				"listfolders.php [actions] [options]\n\n" .
83
				"Actions: [-l username]\n" .
84
					"\t-l username\tlist folders of user, for public folder use 'SYSTEM'\n\n" .
85
				"Global options: [-h path] [[-u remoteuser] [-p password]] [[-c certificate_path] [-p password]]\n" .
86
					"\t-h path\t\tconnect through <path>, e.g. file:///var/run/socket or https://10.0.0.1:237/grommunio\n" .
87
					"\t-u remoteuser\tlogin as authenticated administration user\n" .
88
					"\t-c certificate\tlogin with a ssl certificate located in this location, e.g. /etc/zarafa/ssl/client.pem\n" .
89
					"\t-p password\tpassword of the remoteuser or certificate\n\n";
90
	}
91
}
92
93
function listfolders_zarafa_admin_setup($mapi, $user, $pass, $sslcert_file, $sslcert_pass) {
94
	$session = @mapi_logon_zarafa($user, $pass, $mapi, $sslcert_file, $sslcert_pass, 0, 'script', 'script');
1 ignored issue
show
Bug introduced by
The function mapi_logon_zarafa 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

94
	$session = @/** @scrutinizer ignore-call */ mapi_logon_zarafa($user, $pass, $mapi, $sslcert_file, $sslcert_pass, 0, 'script', 'script');
Loading history...
95
96
	if (!$session) {
97
		printf("User '%s' could not login. The script will exit. Errorcode: 0x%08x\n", $user, 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

97
		printf("User '%s' could not login. The script will exit. Errorcode: 0x%08x\n", $user, /** @scrutinizer ignore-call */ mapi_last_hresult());
Loading history...
98
99
		exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
100
	}
101
102
	$adminStore = null;
103
	$stores = @mapi_getmsgstorestable($session);
1 ignored issue
show
Bug introduced by
The function mapi_getmsgstorestable 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

103
	$stores = @/** @scrutinizer ignore-call */ mapi_getmsgstorestable($session);
Loading history...
104
	$storeslist = @mapi_table_queryallrows($stores, [PR_ENTRYID, PR_DEFAULT_STORE, PR_MDB_PROVIDER]);
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

104
	$storeslist = @/** @scrutinizer ignore-call */ mapi_table_queryallrows($stores, [PR_ENTRYID, PR_DEFAULT_STORE, PR_MDB_PROVIDER]);
Loading history...
105
	foreach ($storeslist as $store) {
106
		if (isset($store[PR_DEFAULT_STORE]) && $store[PR_DEFAULT_STORE] == true) {
107
			$adminStore = @mapi_openmsgstore($session, $store[PR_ENTRYID]);
1 ignored issue
show
Bug introduced by
The function mapi_openmsgstore 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

107
			$adminStore = @/** @scrutinizer ignore-call */ mapi_openmsgstore($session, $store[PR_ENTRYID]);
Loading history...
108
109
			break;
110
		}
111
	}
112
	$zarafauserinfo['admin'] = 1;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$zarafauserinfo was never initialized. Although not strictly required by PHP, it is generally a good practice to add $zarafauserinfo = array(); before regardless.
Loading history...
113
	$admin = (isset($zarafauserinfo['admin']) && $zarafauserinfo['admin']) ? true : false;
114
115
	if (!$stores || !$storeslist || !$adminStore || !$admin) {
116
		echo "There was error trying to log in as admin or retrieving admin info. The script will exit.\n";
117
118
		exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
119
	}
120
121
	return ["session" => $session, "adminStore" => $adminStore];
122
}
123
124
function listfolders_getlist($adminStore, $session, $user) {
125
	global $supported_classes;
126
127
	if (strtoupper($user) == 'SYSTEM') {
128
		// Find the public store store
129
		$storestables = @mapi_getmsgstorestable($session);
1 ignored issue
show
Bug introduced by
The function mapi_getmsgstorestable 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

129
		$storestables = @/** @scrutinizer ignore-call */ mapi_getmsgstorestable($session);
Loading history...
130
		$result = @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

130
		$result = @/** @scrutinizer ignore-call */ mapi_last_hresult();
Loading history...
131
132
		if ($result == NOERROR) {
133
			$rows = @mapi_table_queryallrows($storestables, [PR_ENTRYID, PR_MDB_PROVIDER]);
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

133
			$rows = @/** @scrutinizer ignore-call */ mapi_table_queryallrows($storestables, [PR_ENTRYID, PR_MDB_PROVIDER]);
Loading history...
134
135
			foreach ($rows as $row) {
136
				if (isset($row[PR_MDB_PROVIDER]) && $row[PR_MDB_PROVIDER] == ZARAFA_STORE_PUBLIC_GUID) {
137
					if (!isset($row[PR_ENTRYID])) {
138
						echo "Public folder are not available.\nIf this is a multi-tenancy system, use -u and -p and login with an admin user of the company.\nThe script will exit.\n";
139
140
						exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
141
					}
142
					$entryid = $row[PR_ENTRYID];
143
144
					break;
145
				}
146
			}
147
		}
148
	}
149
	else {
150
		$entryid = @mapi_msgstore_createentryid($adminStore, $user);
1 ignored issue
show
Bug introduced by
The function mapi_msgstore_createentryid 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

150
		$entryid = @/** @scrutinizer ignore-call */ mapi_msgstore_createentryid($adminStore, $user);
Loading history...
151
	}
152
153
	$userStore = @mapi_openmsgstore($session, $entryid);
1 ignored issue
show
Bug introduced by
The function mapi_openmsgstore 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

153
	$userStore = @/** @scrutinizer ignore-call */ mapi_openmsgstore($session, $entryid);
Loading history...
Comprehensibility Best Practice introduced by
The variable $entryid does not seem to be defined for all execution paths leading up to this point.
Loading history...
154
	$hresult = mapi_last_hresult();
155
156
	// Cache the store for later use
157
	if ($hresult != NOERROR) {
158
		echo "Could not open store for '{$user}'. The script will exit.\n";
159
160
		exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
161
	}
162
163
	if (strtoupper($user) != 'SYSTEM') {
164
		$inbox = mapi_msgstore_getreceivefolder($userStore);
1 ignored issue
show
Bug introduced by
The function mapi_msgstore_getreceivefolder 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

164
		$inbox = /** @scrutinizer ignore-call */ mapi_msgstore_getreceivefolder($userStore);
Loading history...
165
		if (mapi_last_hresult() != NOERROR) {
166
			printf("Could not open inbox for %s (0x%08X). The script will exit.\n", $user, mapi_last_hresult());
167
168
			exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
169
		}
170
		$inboxProps = mapi_getprops($inbox, [PR_SOURCE_KEY]);
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

170
		$inboxProps = /** @scrutinizer ignore-call */ mapi_getprops($inbox, [PR_SOURCE_KEY]);
Loading history...
171
	}
172
173
	$storeProps = mapi_getprops($userStore, [PR_IPM_OUTBOX_ENTRYID, PR_IPM_SENTMAIL_ENTRYID, PR_IPM_WASTEBASKET_ENTRYID]);
174
	$root = @mapi_msgstore_openentry($userStore, null);
1 ignored issue
show
Bug introduced by
The function mapi_msgstore_openentry 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

174
	$root = @/** @scrutinizer ignore-call */ mapi_msgstore_openentry($userStore, null);
Loading history...
175
	$h_table = @mapi_folder_gethierarchytable($root, 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

175
	$h_table = @/** @scrutinizer ignore-call */ mapi_folder_gethierarchytable($root, CONVENIENT_DEPTH);
Loading history...
176
	$subfolders = @mapi_table_queryallrows($h_table, [PR_ENTRYID, PR_DISPLAY_NAME, PR_CONTAINER_CLASS, PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY, PR_FOLDER_TYPE, PR_ATTR_HIDDEN]);
177
178
	echo "Available folders in store '{$user}':\n" . str_repeat("-", 50) . "\n";
179
	foreach ($subfolders as $folder) {
180
		// do not display hidden and search folders
181
		if ((isset($folder[PR_ATTR_HIDDEN]) && $folder[PR_ATTR_HIDDEN]) ||
182
			(isset($folder[PR_FOLDER_TYPE]) && $folder[PR_FOLDER_TYPE] == FOLDER_SEARCH)) {
183
			continue;
184
		}
185
186
		// handle some special folders
187
		if ((strtoupper($user) != 'SYSTEM') &&
188
			((isset($inboxProps[PR_SOURCE_KEY]) && $folder[PR_SOURCE_KEY] == $inboxProps[PR_SOURCE_KEY]) ||
189
			$folder[PR_ENTRYID] == $storeProps[PR_IPM_SENTMAIL_ENTRYID] ||
190
			$folder[PR_ENTRYID] == $storeProps[PR_IPM_WASTEBASKET_ENTRYID])) {
191
			$folder[PR_CONTAINER_CLASS] = "IPF.Note";
192
		}
193
194
		if (isset($folder[PR_CONTAINER_CLASS]) && array_key_exists($folder[PR_CONTAINER_CLASS], $supported_classes)) {
195
			echo "Folder name:\t" . $folder[PR_DISPLAY_NAME] . "\n";
196
			echo "Folder ID:\t" . bin2hex($folder[PR_SOURCE_KEY]) . "\n";
197
			echo "Type:\t\t" . $supported_classes[$folder[PR_CONTAINER_CLASS]] . "\n";
198
			echo "\n";
199
		}
200
	}
201
}
202
203
function CheckMapiExtVersion($version = "") {
204
	// compare build number if requested
205
	if (preg_match('/^\d+$/', $version) && strlen($version) > 3) {
206
		$vs = preg_split('/-/', phpversion("mapi"));
207
208
		return $version <= $vs[1];
209
	}
210
211
	if (extension_loaded("mapi")) {
212
		if (version_compare(phpversion("mapi"), $version) == -1) {
213
			return false;
214
		}
215
	}
216
	else {
217
		return false;
218
	}
219
220
	return true;
221
}
222