Issues (4868)

admin/admin-cli.php (8 issues)

1
#!/usr/bin/env php
2
<?php
3
/**
4
 * Admin - Command line interface
5
 *
6
 * @link http://www.egroupware.org
7
 * @package admin
8
 * @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
9
 * @copyright (c) 2006-19 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
10
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
11
 */
12
13
use EGroupware\Api;
14
use EGroupware\Api\Framework;
15
use EGroupware\Api\Vfs;
16
17
chdir(dirname(__FILE__));	// to enable our relative pathes to work
18
19
if (php_sapi_name() !== 'cli')	// security precaution: forbit calling admin-cli as web-page
20
{
21
	die('<h1>admin-cli.php must NOT be called as web-page --> exiting !!!</h1>');
22
}
23
elseif ($_SERVER['argc'] <= 1 || $_SERVER['argc'] == 2 && in_array($_SERVER['argv'][1], array('-h', '--help')))
24
{
25
	usage();
26
}
27
elseif ($_SERVER['argv'][1] == '--exit-codes')
28
{
29
	list_exit_codes();
30
	exit(0);
31
}
32
else
33
{
34
	$arguments = $_SERVER['argv'];
35
	array_shift($arguments);
36
	$action = array_shift($arguments);
37
}
38
39
// allow to specify instance by using a username with appended @domain-name
40
$arg0s = explode(',',@array_shift($arguments));
41
@list($user,$domain) = explode('@',$arg0s[0].'@');
42
load_egw($user, @$arg0s[1], $domain);
43
44
switch($action)
45
{
46
	case '--edit-user':
47
		return do_edit_user($arg0s);
48
49
	case '--add-user':	// like --edit-account, but always runs addaccount hook
50
		return do_edit_user($arg0s,true);
51
52
	case '--edit-alias':
53
	case '--edit-forward':
54
	case '--edit-quota':
55
		return do_edit_mail(substr($action, 7), $arg0s);
56
57
	case '--change-pw':
58
		return do_change_pw($arg0s);
59
60
	case '--delete-user':
61
		return do_delete_account($arg0s[2],$arg0s[3]);
62
63
	case '--edit-group':
64
		return do_edit_group($arg0s);
65
66
	case '--delete-group':
67
		return do_delete_account($arg0s[2],0,false);
68
69
	case '--allow-app':
70
	case '--deny-app':
71
		return do_account_app($arg0s,$action == '--allow-app');
72
73
	case '--change-account-id':
74
		return do_change_account_id($arg0s);
75
76
	/* ToDo: get this working again
77
	case '--subscribe-other':
78
		return do_subscribe_other($arg0s[2],$arg0s[3]);
79
	*/
80
	case '--check-acl';
81
		return do_check_acl();
82
83
	case '--show-header';
84
		return run_command(new setup_cmd_showheader($arg0s[2]));
85
86
	default:
87
		// we allow to call admin_cmd classes directly, if they define the constant SETUP_CLI_CALLABLE
88
		if (substr($action,0,2) == '--' && (class_exists($class = str_replace('-','_',substr($action, 2))) ||
89
			class_exists($class = preg_replace('/^--([a-z0-9_]+)-([a-z0-9_]+)$/i', 'EGroupware\\$1\\$2', $action)) ||
90
			class_exists($class = preg_replace('/^--([a-z0-9_]+)-([a-z0-9_]+)$/i', 'EGroupware\\$1\\AdminCmds\\$2', $action))) &&
91
			is_subclass_of($class,'admin_cmd') && @constant($class.'::SETUP_CLI_CALLABLE'))
92
		{
93
			$args = array();
94
			$args['domain'] = array_shift($arg0s);	// domain must be first argument, to ensure right domain get's selected in header-include
95
			foreach($arg0s as $arg)
96
			{
97
				list($name,$value) = explode('=',$arg,2);
98
				if(property_exists('admin_cmd',$name))		// dont allow to overwrite admin_cmd properties
99
				{
100
					throw new Api\Exception\WrongUserinput(lang("Invalid argument '%1' !!!",$arg),90);
101
				}
102
				if (substr($name,-1) == ']')	// allow 1-dim. arrays
103
				{
104
					list($name,$sub) = explode('[',substr($name,0,-1),2);
105
					if (empty($sub))
106
					{
107
						$args[$name][] = $value;
108
					}
109
					else
110
					{
111
						$args[$name][$sub] = $value;
112
					}
113
				}
114
				else
115
				{
116
					$args[$name] = $value;
117
				}
118
			}
119
			return run_command(new $class($args));
120
		}
121
		usage($action, 1);
122
		break;
123
}
124
exit(0);
125
126
/**
127
 * run a command object, after checking for additional arguments: sheduled, requested or comment
128
 *
129
 * Does not return! Echos success or error messsage and exits with either 0 (success) or the numerical error-code
130
 *
131
 * @param admin_cmd $cmd
132
 */
133
function run_command(admin_cmd $cmd)
134
{
135
	global $arguments,$user,$arg0s,$domain;
136
137
	$skip_checks = false;
138
	while ($arguments && ($extra = array_shift($arguments)))
139
	{
140
		switch($extra)
141
		{
142
			case '--schedule':	// schedule the command instead of running it directly
143
				$time = admin_cmd::parse_date(array_shift($arguments));
144
				break;
145
146
			case '--requested':	// note who requested to run the command
147
				$cmd->requested = 0;
148
				$cmd->requested_email = array_shift($arguments);
149
				break;
150
151
			case '--comment':	// note a comment
152
				$cmd->comment = array_shift($arguments);
153
				break;
154
155
			case '--remote':	// run the command on a remote install
156
				$cmd->remote_id = admin_cmd::parse_remote(array_shift($arguments));
157
				break;
158
159
			case '--skip-checks':	// do not yet run the checks for scheduled local commands
160
				$skip_checks = true;
161
				break;
162
163
			case '--try-run':	// only run checks
164
			case '--dry-run':	// only run checks
165
				$dry_run = true;
166
				break;
167
168
			case '--header-access':
169
				if ($cmd instanceof setup_cmd)
170
				{
171
					list($user,$pw) = explode(',',array_shift($arguments),2);
172
					$cmd->set_header_secret($user,$pw);
173
				}
174
				break;
175
176
			default:
177
				//fail(99,lang('Unknown option %1',$extra);
178
				echo lang('Unknown option %1',$extra)."\n\n";
179
				usage('',99);
180
				break;
181
		}
182
	}
183
	if ($dry_run && $skip_checks)
184
	{
185
		echo lang('You can NOT use --dry-run together with --skip-checks!')."\n\n";
186
		usage('', 99);
187
	}
188
	//_debug_array($cmd);
189
	try {
190
		$msg = $cmd->run($time, true, $skip_checks, $dry_run);
191
		if (!is_bool($msg) && $msg) print_r($msg);
192
193
		// cli can NOT clear instance cache of APC(u), as cli uses different shared memory then webserver
194
		// --> we use a webservice call to clear cache (might fail if no domain in specified in webserver_url or on command line)
195
		if (!$dry_run)
196
		{
197
			$url = $GLOBALS['egw_info']['server']['webserver_url'].'/json.php?menuaction=admin.admin_hooks.ajax_clear_cache';
198
			if ($url[0] == '/') $url = 'http://'.(!empty($domain) && $domain != 'default' ? $domain : 'localhost').$url;
199
			$data = file_get_contents($url, false, Framework::proxy_context($user,$arg0s[1]));
200
			//error_log("file_get_contents('$url') returned ".array2string($data));
201
			if ($data && strpos($data, '"success"') !== false)
202
			{
203
				//error_log('Instance cache cleared.');
204
			}
205
			else
206
			{
207
				error_log('You might need to clear the cache for changes to be visiable: Admin >> Clear cache!');
208
			}
209
		}
210
	}
211
	catch (Api\Exception $e) {
212
		echo "\n".$e->getMessage()."\n\n";
213
		exit($e->getCode());
0 ignored issues
show
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...
214
	}
215
	echo "\n";
216
217
	exit(0);
0 ignored issues
show
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...
218
}
219
220
/**
221
 * callback to authenticate with the user/pw specified on the commandline
222
 *
223
 * @param array &$account account_info with keys 'login', 'passwd' and optional 'passwd_type'
224
 * @return boolean/string true if we allow the access and account is set, a sessionid or false otherwise
225
 */
226
function user_pass_from_argv(&$account)
227
{
228
	$account = array(
229
		'login'  => $GLOBALS['arg0s'][0],
230
		'passwd' => $GLOBALS['arg0s'][1],
231
		'passwd_type' => 'text',
232
	);
233
	//print_r($account);
234
	if (!($sessionid = $GLOBALS['egw']->session->create($account)))
235
	{
236
		//fail(1,lang("Wrong admin-account or -password !!!"));
237
		echo lang("Wrong admin-account or -password !!!")."\n\n";
238
		usage('',1);
239
	}
240
	if (!$GLOBALS['egw_info']['user']['apps']['admin'])	// will be tested by the header too, but whould give html error-message
241
	{
242
		//fail(2,lang("Permission denied !!!"));
243
		echo lang("Permission denied !!!")."\n\n";
244
		usage('',2);
245
	}
246
	return $sessionid;
247
}
248
249
/**
250
 * Start the eGW session, exits on wrong credintials
251
 *
252
 * @param string $user
253
 * @param string $passwd
254
 * @param string $domain
255
 */
256
function load_egw($user,$passwd,$domain='default')
257
{
258
	//echo "load_egw($user,$passwd,$domain)\n";
259
	$_REQUEST['domain'] = $domain;
260
	$GLOBALS['egw_login_data'] = array(
261
		'login'  => $user,
262
		'passwd' => $passwd,
263
		'passwd_type' => 'text',
264
	);
265
266
	if (ini_get('session.save_handler') == 'files' && !is_writable(ini_get('session.save_path')) && is_dir('/tmp') && is_writable('/tmp'))
267
	{
268
		ini_set('session.save_path','/tmp');	// regular users may have no rights to apache's session dir
269
	}
270
271
	$GLOBALS['egw_info'] = array(
272
		'flags' => array(
273
			'currentapp' => 'admin',
274
			'noheader' => true,
275
			'autocreate_session_callback' => 'user_pass_from_argv',
276
			'no_exception_handler' => 'cli',
277
		)
278
	);
279
280
	if (substr($user,0,5) != 'root_')
281
	{
282
		include('../header.inc.php');
283
	}
284
	else
285
	{
286
		$GLOBALS['egw_info']['flags']['currentapp'] = 'login';
287
		include('../header.inc.php');
288
289
		if ($user == 'root_'.$GLOBALS['egw_info']['server']['header_admin_user'] &&
290
			_check_pw($GLOBALS['egw_info']['server']['header_admin_password'],$passwd) ||
291
			$user == 'root_'.$GLOBALS['egw_domain'][$_GET['domain']]['config_user'] &&
292
			_check_pw($GLOBALS['egw_domain'][$_GET['domain']]['config_passwd'],$passwd))
293
		{
294
			echo "\nRoot access granted!\n";
295
			Vfs::$is_root = true;
296
		}
297
		else
298
		{
299
			die("Unknown user or password!\n");
0 ignored issues
show
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...
300
		}
301
	}
302
}
303
304
/**
305
 * Check password against a md5 hash or cleartext password
306
 *
307
 * @param string $hash_or_cleartext
308
 * @param string $pw
309
 * @return boolean
310
 */
311
function _check_pw($hash_or_cleartext,$pw)
312
{
313
	return Api\Auth::compare_password($pw, $hash_or_cleartext,
314
		// old header.inc.php allows md5 or plain passwords with out {type} prefix, which takes precedence
315
		preg_match('/^[0-9a-f]{32}$/', $hash_or_cleartext) ? 'md5' : 'plain');
316
}
317
318
/**
319
 * Give a usage message and exit
320
 *
321
 * @param string $action =null
322
 * @param int $ret =0 exit-code
323
 */
324
function usage($action=null,$ret=0)
325
{
326
	unset($action);
327
	$cmd = basename($_SERVER['argv'][0]);
328
	echo "Usage: $cmd --command admin-account[@domain],admin-password,options,... [--schedule {YYYY-mm-dd|+1 week|+5 days}] [--requested 'Name <email>'] [--comment 'comment ...'] [--remote {id|name}] [--skip-checks] [--try-run]\n\n";
329
330
	echo "\n\t--skip-checks\tdo NOT run checks\n";
331
	echo "\t--try-run\tonly run checks\n";
332
333
	echo "\tAlternativly you can also use a setup user and password by prefixing it with 'root_', eg. 'root_admin' for setup user 'admin'.\n\n";
334
335
	echo "--edit-user admin-account[@domain],admin-password,account[=new-account-name],first-name,last-name,password,email,expires{never(default)|YYYY-MM-DD|already},can-change-pw{yes(default)|no},anon-user{yes|no(default)},primary-group{Default(default)|...}[,groups,...][,homedirectory,loginshell]\n";
336
	echo "	Edit or add a user to EGroupware. If you specify groups, they *replace* the exiting memberships! homedirectory+loginshell are supported only for LDAP and must start with a slash!\n";
337
	echo "--change-pw admin-account[@domain],admin-password,account,password\n";
338
	echo "  Change/set the password for a given user\n";
339
	echo "--delete-user admin-account[@domain],admin-password,account-to-delete[,account-to-move-data]\n";
340
	echo "	Deletes a user from EGroupware. It's data can be moved to an other user or it get deleted too.\n";
341
	echo "	You can use '--not-existing' for accounts-to-delete, to delete all no (longer) existing users and groups.\n";
342
	echo "--edit-group admin-account[@domain],admin-password,group[=new-group-name],email[,members,...]\n";
343
	echo "	Edit or add a group to EGroupware. If you specify members, they *replace* the exiting members!\n";
344
	echo "--delete-group admin-account[@domain],admin-password,group-to-delete\n";
345
	echo "	Deletes a group from EGroupware.\n";
346
	echo "--allow-app admin-account[@domain],admin-password,account,application,...\n";
347
	echo "--deny-app admin-account[@domain],admin-password,account,application,...\n";
348
	echo "	Give or deny an account (user or group specified by account name or id) run rights for the given applications.\n";
349
	echo "--change-account-id admin-account[@domain],admin-password,from1,to1[...,fromN,toN]\n";
350
	echo "	Changes one or more account_id's in the database (make a backup before!).\n";
351
	echo "--check-acl admin-account[@domain],admin-password\n";
352
	echo "	Deletes ACL entries of not longer existing accounts (make a database backup before! --> setup-cli.php).\n";
353
	echo "--admin-cmd-check-cats admin-account[@domain],admin-password\n";
354
	echo "	Deletes categories of not longer existing accounts.\n";
355
	echo "--edit-alias admin-account[@domain],admin-password,account[=acc_id],create-identity(yes,no/default),[+/-]alias1,...\n";
356
	echo "--edit-forward admin-account[@domain],admin-password,account[=acc_id],mode(forwardOnly),[+/-]forward1,...\n";
357
	echo "--edit-quota admin-account[@domain],admin-password,account[=acc_id],quota(mb)\n";
358
	echo "  Edit mail account of EGroupware managed mail-server for a given user and optional acc_id (can't be scheduled or try-run)\n";
359
	echo "--exit-codes admin-account[@domain],admin-password\n";
360
	echo "	List all exit codes of the command line interface\n";
361
362
	exit($ret);
0 ignored issues
show
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...
363
}
364
365
/**
366
 * Edit mail account of EGroupware managed mail-server
367
 *
368
 * @param string $type "alias", "forward", "quota"
369
 * @param array $arg0s admin-account[@domain],admin-password,account[=acc_id],...
370
 *	- alias:   create-identity(yes,no/default),[+/-]alias1,...aliasN
371
 *	- forward: mode(forwardOnly),[+/-]forward1,...forwardN
372
 *	- quota:   quota(mb)
373
 * @return int 0 on success
374
 */
375
function do_edit_mail($type, array $arg0s)
376
{
377
	array_shift($arg0s); // admin-account
378
	array_shift($arg0s);	// admin-pw
379
	list($account, $acc_id) = explode('=', array_shift($arg0s));
380
	$account_id = is_numeric($account) ? (int)$account : $GLOBALS['egw']->accounts->name2id($account);
381
	if (!$GLOBALS['egw']->accounts->exists($account_id) && !($account_id = $GLOBALS['egw']->accounts->name2id($account)))
382
	{
383
		echo "Unknown user-account '$account'!\n";
384
		exit(1);
0 ignored issues
show
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...
385
	}
386
	$found = 0;
387
	foreach($acc_id ? array(Api\Mail\Account::read($acc_id, $account_id)) :
388
		Api\Mail\Account::search($account_id, false) as $account)
389
	{
390
		if (!isset($acc_id) && !Api\Mail\Account::is_multiple($account)) continue;	// no need to waste time on personal accounts
391
392
		$args = $arg0s;
393
		try {
394
			if (!($data = $account->getUserData($account_id)))
395
			{
396
				continue;	// not a managed mail-server
397
			}
398
			switch($type)
399
			{
400
				case 'alias':
401
					$create_identity = strtolower(array_shift($args)) === 'yes';
402
					$delete_identity = $args[0][0] == '-';
403
					array_modify($data['mailAlternateAddress'], $args);
404
					break;
405
				case 'forward':
406
					$data['deliveryMode'] = strtolower(array_shift($args)) === 'forwardonly' ? Api\Mail\Smtp::FORWARD_ONLY : '';
407
					array_modify($data['mailForwardingAddress'], $args);
408
					break;
409
				case 'quota':
410
					$data['quotaLimit'] = int($args[0]);
411
					break;
412
			}
413
			$account->saveUserData($account_id, $data);
414
			echo "Data in mail-account (acc_id=$account->acc_id) updated.\n";
415
			++$found;
416
417
			// create identities for all aliases
418
			if ($type == 'alias' && $create_identity && $args)
419
			{
420
				// check if user allready has an identity created for given aliases
421
				foreach(Api\Mail\Account::identities($account, false, 'ident_email', $account_id) as $ident_id => $email)
422
				{
423
					if (($key = array_search($email, $args)) !== false)
424
					{
425
						// delete identities, if "-" is used and email of identity matches given ones and is not standard identity
426
						if ($delete_identity && $ident_id != $account->ident_id)
427
						{
428
							Api\Mail\Account::delete_identity($ident_id);
429
						}
430
						unset($args[$key]);
431
					}
432
				}
433
				// create not existing identities by copying standard identity plus alias as email
434
				foreach($args as $email)
435
				{
436
					$identity = $account->params;
437
					unset($identity['ident_id']);
438
					unset($identity['ident_name']);
439
					$identity['ident_email'] = $email;
440
					$identity['account_id'] = $account_id;	// make this a personal identity for $account_id
441
					Api\Mail\Account::save_identity($identity);
442
				}
443
				if ($args) echo "Identity(s) for ".implode(', ', $args)." created.\n";
444
			}
445
		}
446
		catch(\Exception $e) {
447
			_egw_log_exception($e);
448
			echo $e->getMessage()."\n";
449
		}
450
	}
451
	if (!$found)
452
	{
453
		echo "No mailserver managed by this EGroupware instance!\n";
454
		exit(2);
0 ignored issues
show
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...
455
	}
456
	exit(0);
0 ignored issues
show
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...
457
}
458
459
/**
460
 * Set, add or remove from array depending on $mod[0][0] being '+', '-' or something else (set)
461
 *
462
 * @param array& $arr
463
 * @param array& $mod eg. ["[email protected]","[email protected]"] will add all given alias to $arr
464
 *  on return optional +/- prefix has been removed
465
 * @return array
466
 */
467
function array_modify(&$arr, array &$mod)
468
{
469
	if (!is_array($arr)) $arr = array();
470
471
	switch($mod[0][0])
472
	{
473
		case '-':
474
			$mod[0] = substr($mod[0], 1);
475
			$arr = array_values(array_unique(array_diff($arr, $mod)));
476
			break;
477
478
		case '+';
479
			$mod[0] = substr($mod[0], 1);
480
			$arr = array_values(array_unique(array_merge($arr, $mod)));
481
			break;
482
483
		default:
484
			$arr = array_values(array_unique($mod));
485
	}
486
	return $arr;
487
}
488
489
/**
490
 * Give or deny an account (user or group specified by account name or id) run rights for the given applications.
491
 *
492
 * @param array $args admin-account[@domain],admin-password,account,application,...
493
 * @param boolean $allow true=allow, false=deny
494
 * @return int 0 on success
495
 */
496
function do_account_app($args,$allow)
497
{
498
	array_shift($args);	// admin-account
499
	array_shift($args);	// admin-pw
500
	$account = array_shift($args);
501
502
	include_once(EGW_INCLUDE_ROOT.'/admin/inc/class.admin_cmd_account_app.inc.php');
503
	run_command(new admin_cmd_account_app($allow,$account,$args));
504
}
505
506
/**
507
 * Edit or add a group to EGroupware. If you specify members, they *replace* the exiting member!
508
 *                    1:                     2:             3:                     4:     5:
509
 * @param array $args admin-account[@domain],admin-password,group[=new-group-name],email[,members,...]
510
 */
511
function do_edit_group($args)
512
{
513
	array_shift($args);	// admin-account
514
	array_shift($args);	// admin-pw
515
	list($account,$new_account_name) = explode('=',array_shift($args));	// account[=new-account-name]
516
517
	$data = array(
518
		'account_lid' => $new_account_name,
519
		'account_email' => array_shift($args),
520
		'account_members' => $args,
521
	);
522
	try {
523
		admin_cmd::parse_account($account,false);
524
525
		foreach($data as &$value)	// existing account --> empty values mean dont change, not set them empty!
526
		{
527
			if ((string)$value === '') $value = null;
528
		}
529
	}
530
	catch (Exception $e) {	// new group
531
		unset($e);	// not used
532
		$data['account_lid'] = $account;
533
		$account = false;
534
	}
535
	run_command(new admin_cmd_edit_group($account,$data));
536
}
537
538
/**
539
 * Change/Set Password for a given user
540
 *                    1:                     2:             3:      4:
541
 * @param array $args admin-account[@domain],admin-password,account,password
542
 */
543
function do_change_pw($args)
544
{
545
	array_shift($args);     // admin-account
546
	array_shift($args);     // admin-pw
547
	$account = array_shift($args);	// account
548
	$password = array_shift($args);	// pw
549
550
	run_command(new admin_cmd_change_pw($account,$password));
551
}
552
553
/**
554
 * Edit or add a user to EGroupware. If you specify groups, they *replace* the exiting memberships!
555
 *                    1:                     2:             3:                         4:         5:        6:       7:    8:                                         9:                                 10:                            11:                                  12
556
 * @param array $args admin-account[@domain],admin-password,account[=new-account-name],first-name,last-name,password,email,expires{never(default)|YYYY-MM-DD|already},can-change-pw{true(default)|false},anon-user{true|false(default)},primary-group{Default(default)|...}[,groups,...][,homedirectory,loginshell]
557
 * @param boolean $run_addaccount_hook =null default run hook depending on account existence, true=allways run addaccount hook
558
 */
559
function do_edit_user($args,$run_addaccount_hook=null)
560
{
561
	array_shift($args);	// admin-account
562
	array_shift($args);	// admin-pw
563
	list($account,$new_account_name) = explode('=',array_shift($args));	// account[=new-account-name]
564
565
	$data = array();
566
	// do we need to support ldap only attributes: homedirectory and loginshell
567
	if (($GLOBALS['egw_info']['server']['account_repository'] == 'ldap' ||
568
		 empty($GLOBALS['egw_info']['server']['account_repository']) && $GLOBALS['egw_info']['server']['auth_type'] == 'ldap') &&
569
		$GLOBALS['egw_info']['server']['ldap_extra_attributes'] && count($args) > 9 &&	// 9 = primary group
570
		($last_arg = array_pop($dummy=$args)) && $last_arg[0] == '/')	// last argument start with a slash
571
	{
572
		$data['loginshell'] = array_pop($args);
573
		$data['homedirectory'] = array_pop($args);
574
	}
575
	$data += array(
576
		'account_lid' => $new_account_name,
577
		'account_firstname' => array_shift($args),
578
		'account_lastname' => array_shift($args),
579
		'account_passwd' => array_shift($args),
580
		'account_email' => array_shift($args),
581
		'account_expires' => array_shift($args),
582
		'changepassword' => array_shift($args),
583
		'anonymous' => array_shift($args),
584
		'account_primary_group' => array_shift($args),
585
		'account_groups' => $args,
586
	);
587
	try {
588
		admin_cmd::parse_account($account,true);
589
590
		foreach($data as &$value)	// existing account --> empty values mean dont change, not set them empty!
591
		{
592
			if ((string)$value === '') $value = null;
593
		}
594
	}
595
	catch (Exception $e) {	// new account
596
		unset($e);	// not used
597
		$data['account_lid'] = $account;
598
		$account = false;
599
	}
600
	run_command(new admin_cmd_edit_user($account,$data,null,$run_addaccount_hook));
601
}
602
603
/**
604
 * Delete a given acount from eGW
605
 *
606
 * @param int/string $account account-name of -id
607
 * @param int/string $new_user =0 for users only: account to move the entries too
608
 * @param boolean $is_user =true are we called for a user or group
609
 * @return int 0 on success, 2-4 otherwise (see source)
610
 */
611
function do_delete_account($account,$new_user=0,$is_user=true)
612
{
613
	run_command(new admin_cmd_delete_account($account,$new_user,$is_user));
614
}
615
616
/**
617
 * Deletes ACL entries of not longer existing accounts
618
 *
619
 * @return int 0 allways
620
 */
621
function do_check_acl()
622
{
623
	run_command(new admin_cmd_check_acl());
624
}
625
626
/**
627
 * Changes one or more account_id's in the database (make a backup before!).
628
 *
629
 * @param array $args admin-account[@domain],admin-password,from1,to1[...,fromN,toN]
630
 * @return int 0 on success
631
 */
632
function do_change_account_id($args)
633
{
634
	if (count($args) < 4) usage();	// 4 means at least user,pw,from1,to1
635
636
	$ids2change = array();
637
	for($n = 2; $n < count($args); $n += 2)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
638
	{
639
		$from = (int)$args[$n];
640
		$to   = (int)$args[$n+1];
641
		$ids2change[$from] = $to;
642
	}
643
	run_command(new admin_cmd_change_account_id($ids2change));
644
}
645
646
/**
647
 * List all exit codes used by the command line interface
648
 *
649
 * The list is generated by "greping" this file for thrown exceptions.
650
 * Exceptions have to be in one line, to be recogniced!
651
 */
652
function list_exit_codes()
653
{
654
	error_reporting(error_reporting() & ~E_NOTICE);
655
656
	if (!function_exists('lang'))
657
	{
658
		function lang($str)
659
		{
660
			return $str;
661
		}
662
	}
663
664
	$codes = array();
665
	$files = array('admin-cli.php');
666
	foreach(scandir(__DIR__.'/inc') as $file)
667
	{
668
		if (substr($file,0,strlen('class.admin_cmd')) == 'class.admin_cmd')
669
		{
670
			$files[] = 'inc/'.$file;
671
		}
672
	}
673
	foreach($files as $file)
674
	{
675
		$content = file_get_contents(__DIR__.'/'.$file);
676
677
		$matches = null;
678
		if (preg_match_all('/throw new (Api\\\\Exception[\\\\a-z_]*)\((.*),\\s*([0-9]+)\);/mi',$content,$matches))
679
		{
680
			//echo $file.":\n"; print_r($matches);
681
			foreach($matches[3] as $key => $code)
682
			{
683
				$src = preg_replace('/(self::)?\$[a-z_>-]+/i', "''", $matches[2][$key]);	// gives fatal error otherwise
684
				@eval('$src = '.$src.';');
685
686
				if (!empty($src) && (!isset($codes[$code]) || !in_array($src, $codes[$code])))
687
				{
688
					//if (isset($codes[$code])) echo "$file redefines #$code: ".implode(', ', $codes[$code])."\n";
689
					$codes[$code][] = $src;
690
				}
691
			}
692
		}
693
	}
694
	$codes[0] = 'Ok';
695
	ksort($codes, SORT_NUMERIC);
696
	foreach($codes as $num => $msgs)
697
	{
698
		echo $num."\t".str_replace("\n","\n\t", implode(', ', (array)$msgs))."\n";
699
	}
700
}
701
702
/**
703
 * Read the IMAP ACLs
704
 *
705
 * @param array $args admin-account[@domain],admin-password,accout_lid[,pw]
706
 * @return int 0 on success
707
 */
708
function do_subscribe_other($account_lid,$pw=null)
709
{
710
	unset($account_lid, $pw);
711
	/* ToDo: this cant work, not even in 14.x
712
	if (!($account_id = $GLOBALS['egw']->accounts->name2id($account_lid)))
713
	{
714
		throw new Api\Exception\WrongUserinput(lang("Unknown account: %1 !!!",$account_lid),15);
715
	}
716
	$GLOBALS['egw_info']['user'] = array(
717
		'account_id' => $account_id,
718
		'account_lid' => $account_lid,
719
		'passwd' => $pw,
720
	);
721
	$emailadmin = new emailadmin_bo();
722
	$user_profile = $emailadmin->getUserProfile('felamimail');
723
	unset($emailadmin);
724
725
	$icServer = new cyrusimap();
726
	//$icServer =& $user_profile->ic_server[0];
727
	//print_r($icServer);
728
729
	$icServer->openConnection(!$pw);
730
731
	$delimiter = $icServer->getHierarchyDelimiter();
732
733
	$mailboxes = $icServer->getMailboxes();
734
	//print_r($mailboxes);
735
736
	$own_mbox = 'user'.$delimiter.$account_lid;
737
738
	foreach($mailboxes as $n => $mailbox)
739
	{
740
//		if ($n < 1) continue;
741
742
		if (substr($mailbox,0,5) != 'user'.$delimiter || substr($mailbox,0,strlen($own_mbox)) == $own_mbox) continue;
743
744
		if (!$pw) $mailbox = str_replace('INBOX','user'.$delimiter.$account_lid,$mailbox);
745
746
		//$rights = $icServer->getACL($mailbox);
747
		//echo "getACL($mailbox)\n";
748
		//foreach($rights as $data)
749
		//{
750
		//	echo $data['USER'].' '.$data['RIGHTS']."\n";
751
		//}
752
		echo "subscribing $mailbox for $account_lid\n";
753
		//$icServer->subscribeMailbox($mailbox);
754
		//exit;
755
	}*/
756
}
757