1 | <?php |
||||
2 | /** |
||||
3 | * Setup |
||||
4 | * |
||||
5 | * @link http://www.egroupware.org |
||||
6 | * @package setup |
||||
7 | * @author Joseph Engo <[email protected]> |
||||
8 | * @author Dan Kuykendall <[email protected]> |
||||
9 | * @author Mark Peters <[email protected]> |
||||
10 | * @author Miles Lott <[email protected]> |
||||
11 | * @author Ralf Becker <RalfBecker-AT-outdoor-training.de> |
||||
12 | * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License |
||||
13 | */ |
||||
14 | |||||
15 | use EGroupware\Api; |
||||
16 | use EGroupware\Api\Link; |
||||
17 | use EGroupware\Api\Egw; |
||||
18 | use EGroupware\Api\Vfs; |
||||
19 | |||||
20 | class setup |
||||
21 | { |
||||
22 | var $db; |
||||
23 | var $config_table = 'egw_config'; |
||||
24 | var $applications_table = 'egw_applications'; |
||||
25 | var $acl_table = 'egw_acl'; |
||||
26 | var $accounts_table = 'egw_accounts'; |
||||
27 | var $prefs_table = 'egw_preferences'; |
||||
28 | var $lang_table = 'egw_lang'; |
||||
29 | var $languages_table = 'egw_languages'; |
||||
30 | var $hooks_table = 'egw_hooks'; |
||||
31 | var $cats_table = 'egw_categories'; |
||||
32 | var $oProc; |
||||
33 | var $cookie_domain; |
||||
34 | |||||
35 | /** |
||||
36 | * @var setup_detection |
||||
37 | */ |
||||
38 | var $detection; |
||||
39 | /** |
||||
40 | * @var setup_process |
||||
41 | */ |
||||
42 | var $process; |
||||
43 | /** |
||||
44 | * @var setup_translation |
||||
45 | */ |
||||
46 | var $translation; |
||||
47 | /** |
||||
48 | * @var setup_html |
||||
49 | */ |
||||
50 | var $html; |
||||
51 | |||||
52 | var $system_charset; |
||||
53 | var $lang; |
||||
54 | |||||
55 | var $ConfigDomain; |
||||
56 | |||||
57 | /* table name vars */ |
||||
58 | var $tbl_apps; |
||||
59 | var $tbl_config; |
||||
60 | var $tbl_hooks; |
||||
61 | |||||
62 | /** |
||||
63 | * php version required by eGroupware |
||||
64 | * |
||||
65 | * @var float |
||||
66 | */ |
||||
67 | var $required_php_version = 7.1; |
||||
68 | /** |
||||
69 | * PHP Version recommended for eGroupware |
||||
70 | * |
||||
71 | * @var string |
||||
72 | */ |
||||
73 | var $recommended_php_version = '7.3'; |
||||
74 | |||||
75 | function __construct($html=False, $translation=False) |
||||
76 | { |
||||
77 | // setup us as $GLOBALS['egw_setup'], as this gets used in our sub-objects |
||||
78 | $GLOBALS['egw_setup'] =& $this; |
||||
79 | |||||
80 | if (!is_object($GLOBALS['egw'])) |
||||
81 | { |
||||
82 | $GLOBALS['phpgw'] = $GLOBALS['egw'] = new Egw\Base(); |
||||
83 | } |
||||
84 | $this->detection = new setup_detection(); |
||||
85 | $this->process = new setup_process(); |
||||
86 | |||||
87 | if (preg_match('/^[a-z0-9-]+$/i', $_REQUEST['system_charset'])) $this->system_charset = $_REQUEST['system_charset']; |
||||
88 | |||||
89 | /* The setup application needs these */ |
||||
90 | if ($html) $this->html = new setup_html(); |
||||
91 | if ($translation) $this->translation = new setup_translation(); |
||||
92 | } |
||||
93 | |||||
94 | /** |
||||
95 | * include api db class for the ConfigDomain and connect to the db |
||||
96 | */ |
||||
97 | function loaddb($connect_and_setcharset=true) |
||||
98 | { |
||||
99 | if(!isset($this->ConfigDomain) || empty($this->ConfigDomain)) |
||||
100 | { |
||||
101 | $this->ConfigDomain = isset($_REQUEST['ConfigDomain']) ? $_REQUEST['ConfigDomain'] : $_POST['FormDomain']; |
||||
102 | } |
||||
103 | $GLOBALS['egw_info']['server']['db_type'] = $GLOBALS['egw_domain'][$this->ConfigDomain]['db_type']; |
||||
104 | |||||
105 | if ($GLOBALS['egw_info']['server']['db_type'] == 'pgsql') |
||||
106 | { |
||||
107 | $GLOBALS['egw_info']['server']['db_persistent'] = False; |
||||
108 | } |
||||
109 | |||||
110 | try { |
||||
111 | $GLOBALS['egw']->db = $this->db = new Api\Db\Deprecated($GLOBALS['egw_domain'][$this->ConfigDomain]); |
||||
112 | $this->db->connect(); |
||||
113 | } |
||||
114 | catch (Exception $e) { |
||||
115 | unset($e); |
||||
116 | return; |
||||
117 | } |
||||
118 | $this->db->set_app(Api\Db::API_APPNAME); |
||||
119 | |||||
120 | if ($connect_and_setcharset) |
||||
121 | { |
||||
122 | try { |
||||
123 | $this->set_table_names(); // sets/checks config- and applications-table-name |
||||
124 | |||||
125 | // Set the DB's client charset if a system-charset is set |
||||
126 | if (($this->system_charset = $this->db->select($this->config_table,'config_value',array( |
||||
127 | 'config_app' => 'phpgwapi', |
||||
128 | 'config_name' => 'system_charset', |
||||
129 | ),__LINE__,__FILE__)->fetchColumn())) |
||||
130 | { |
||||
131 | $this->db_charset_was = $this->db->Link_ID->GetCharSet(); // needed for the update |
||||
132 | |||||
133 | // we can NOT set the DB charset for mysql, if the api version < 1.0.1.019, as it would mess up the DB content!!! |
||||
134 | if (substr($this->db->Type,0,5) == 'mysql') // we need to check the api version |
||||
135 | { |
||||
136 | $api_version = $this->db->select($this->applications_table,'app_version',array( |
||||
137 | 'app_name' => 'phpgwapi', |
||||
138 | ),__LINE__,__FILE__)->fetchColumn(); |
||||
139 | } |
||||
140 | if (!$api_version || !$this->alessthanb($api_version,'1.0.1.019')) |
||||
141 | { |
||||
142 | $this->db->Link_ID->SetCharSet($this->system_charset); |
||||
143 | } |
||||
144 | } |
||||
145 | } |
||||
146 | catch (Api\Db\Exception $e) { |
||||
147 | // table might not be created at that stage |
||||
148 | } |
||||
149 | } |
||||
150 | } |
||||
151 | |||||
152 | /** |
||||
153 | * Set the domain used for cookies |
||||
154 | * |
||||
155 | * @return string domain |
||||
156 | */ |
||||
157 | static function cookiedomain() |
||||
158 | { |
||||
159 | // Use HTTP_X_FORWARDED_HOST if set, which is the case behind a none-transparent proxy |
||||
160 | $cookie_domain = Api\Header\Http::host(); |
||||
161 | |||||
162 | // remove port from HTTP_HOST |
||||
163 | $arr = null; |
||||
164 | if (preg_match("/^(.*):(.*)$/",$cookie_domain,$arr)) |
||||
165 | { |
||||
166 | $cookie_domain = $arr[1]; |
||||
167 | } |
||||
168 | if (count(explode('.',$cookie_domain)) <= 1) |
||||
169 | { |
||||
170 | // setcookie dont likes domains without dots, leaving it empty, gets setcookie to fill the domain in |
||||
171 | $cookie_domain = ''; |
||||
172 | } |
||||
173 | return $cookie_domain; |
||||
174 | } |
||||
175 | |||||
176 | /** |
||||
177 | * Set a cookie |
||||
178 | * |
||||
179 | * @param string $cookiename name of cookie to be set |
||||
180 | * @param string $cookievalue value to be used, if unset cookie is cleared (optional) |
||||
181 | * @param int $cookietime when cookie should expire, 0 for session only (optional) |
||||
182 | */ |
||||
183 | function set_cookie($cookiename,$cookievalue='',$cookietime=0) |
||||
184 | { |
||||
185 | if(!isset($this->cookie_domain)) |
||||
186 | { |
||||
187 | $this->cookie_domain = self::cookiedomain(); |
||||
188 | } |
||||
189 | setcookie($cookiename, $cookievalue, $cookietime, '/', $this->cookie_domain, |
||||
190 | // if called via HTTPS, only send cookie for https and only allow cookie access via HTTP (true) |
||||
191 | Api\Header\Http::schema() === 'https', true); |
||||
192 | } |
||||
193 | |||||
194 | /** |
||||
195 | * Get configuration language from $_POST or $_SESSION and validate it |
||||
196 | * |
||||
197 | * @param boolean $use_accept_language =false true: use Accept-Language header as fallback |
||||
198 | * @return string |
||||
199 | */ |
||||
200 | static function get_lang($use_accept_language=false) |
||||
201 | { |
||||
202 | if (isset($_POST['ConfigLang'])) |
||||
203 | { |
||||
204 | $ConfigLang = $_POST['ConfigLang']; |
||||
205 | } |
||||
206 | else |
||||
207 | { |
||||
208 | if (!isset($_SESSION)) self::session_start(); |
||||
209 | $ConfigLang = $_SESSION['ConfigLang']; |
||||
210 | } |
||||
211 | $matches = null; |
||||
212 | if ($use_accept_language && empty($ConfigLang) && |
||||
213 | preg_match_all('/(^|,)([a-z-]+)/', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']), $matches)) |
||||
214 | { |
||||
215 | $available = Api\Translation::get_available_langs(false); |
||||
216 | foreach($matches[2] as $lang) |
||||
217 | { |
||||
218 | if (isset($available[$lang])) |
||||
219 | { |
||||
220 | $ConfigLang = $lang; |
||||
221 | break; |
||||
222 | } |
||||
223 | } |
||||
224 | } |
||||
225 | if (!preg_match('/^[a-z]{2}(-[a-z]{2})?$/',$ConfigLang)) |
||||
226 | { |
||||
227 | $ConfigLang = null; // not returning 'en', as it suppresses the language selection in check_install and manageheader |
||||
228 | } |
||||
229 | //error_log(__METHOD__."() \$_POST['ConfigLang']=".array2string($_POST['ConfigLang']).", \$_SESSION['ConfigLang']=".array2string($_SESSION['ConfigLang']).", HTTP_ACCEPT_LANGUAGE=$_SERVER[HTTP_ACCEPT_LANGUAGE] --> returning ".array2string($ConfigLang)); |
||||
230 | return $ConfigLang; |
||||
231 | } |
||||
232 | |||||
233 | /** |
||||
234 | * Name of session cookie |
||||
235 | */ |
||||
236 | const SESSIONID = 'sessionid'; |
||||
237 | |||||
238 | /** |
||||
239 | * Session timeout in secs (1200 = 20min) |
||||
240 | */ |
||||
241 | const TIMEOUT = 1200; |
||||
242 | |||||
243 | /** |
||||
244 | * Start session |
||||
245 | */ |
||||
246 | private static function session_start() |
||||
247 | { |
||||
248 | // make sure we have session extension available, otherwise fail with exception that we need it |
||||
249 | check_load_extension('session', true); |
||||
250 | |||||
251 | switch(session_status()) |
||||
252 | { |
||||
253 | case PHP_SESSION_DISABLED: |
||||
254 | throw new \ErrorException('EGroupware requires PHP session extension!'); |
||||
255 | case PHP_SESSION_NONE: |
||||
256 | if (headers_sent()) return false; |
||||
257 | ini_set('session.use_cookie', true); |
||||
258 | session_name(self::SESSIONID); |
||||
259 | session_set_cookie_params(0, '/', self::cookiedomain(), |
||||
260 | // if called via HTTPS, only send cookie for https and only allow cookie access via HTTP (true) |
||||
261 | Api\Header\Http::schema() === 'https', true); |
||||
262 | |||||
263 | if (isset($_COOKIE[self::SESSIONID])) session_id($_COOKIE[self::SESSIONID]); |
||||
264 | |||||
265 | $ok = @session_start(); // suppress notice if session already started or warning in CLI |
||||
266 | break; |
||||
267 | case PHP_SESSION_ACTIVE: |
||||
268 | $ok = true; |
||||
269 | } |
||||
270 | // need to decrypt session, in case session encryption is switched on in header.inc.php |
||||
271 | Api\Session::decrypt(); |
||||
272 | //error_log(__METHOD__."() returning ".array2string($ok).' _SESSION='.array2string($_SESSION)); |
||||
273 | return $ok; |
||||
274 | } |
||||
275 | |||||
276 | /** |
||||
277 | * authenticate the setup user |
||||
278 | * |
||||
279 | * @param string $_auth_type ='config' 'config' or 'header' (caseinsensitiv) |
||||
280 | */ |
||||
281 | function auth($_auth_type='config') |
||||
282 | { |
||||
283 | $auth_type = strtolower($_auth_type); |
||||
284 | $GLOBALS['egw_info']['setup']['HeaderLoginMSG'] = $GLOBALS['egw_info']['setup']['ConfigLoginMSG'] = ''; |
||||
285 | |||||
286 | if(!$this->checkip(isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? |
||||
287 | $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'])) |
||||
288 | { |
||||
289 | //error_log(__METHOD__."('$auth_type') invalid IP"); |
||||
290 | return false; |
||||
291 | } |
||||
292 | |||||
293 | if (!self::session_start() || isset($_REQUEST['FormLogout']) || |
||||
294 | empty($_SESSION['egw_setup_auth_type']) || $_SESSION['egw_setup_auth_type'] != $auth_type) |
||||
295 | { |
||||
296 | //error_log(__METHOD__."('$auth_type') \$_COOKIE['".self::SESSIONID."'] = ".array2string($_COOKIE[self::SESSIONID]).", \$_SESSION=".array2string($_SESSION).", \$_POST=".array2string($_POST)); |
||||
297 | if (isset($_REQUEST['FormLogout'])) |
||||
298 | { |
||||
299 | $this->set_cookie(self::SESSIONID, '', time()-86400); |
||||
300 | session_destroy(); |
||||
301 | if ($_REQUEST['FormLogout'] == 'config') |
||||
302 | { |
||||
303 | $GLOBALS['egw_info']['setup']['ConfigLoginMSG'] = lang('You have successfully logged out'); |
||||
304 | } |
||||
305 | else |
||||
306 | { |
||||
307 | $GLOBALS['egw_info']['setup']['HeaderLoginMSG'] = lang('You have successfully logged out'); |
||||
308 | } |
||||
309 | return false; |
||||
310 | } |
||||
311 | if (!isset($_POST['FormUser']) || !isset($_POST['FormPW'])) |
||||
312 | { |
||||
313 | return false; |
||||
314 | } |
||||
315 | switch($auth_type) |
||||
316 | { |
||||
317 | case 'config': |
||||
318 | if (!isset($GLOBALS['egw_domain'][$_POST['FormDomain']]) || |
||||
319 | !$this->check_auth($_POST['FormUser'], $_POST['FormPW'], |
||||
320 | $GLOBALS['egw_domain'][$_POST['FormDomain']]['config_user'], |
||||
321 | $GLOBALS['egw_domain'][$_POST['FormDomain']]['config_passwd']) && |
||||
322 | !$this->check_auth($_POST['FormUser'], $_POST['FormPW'], |
||||
323 | $GLOBALS['egw_info']['server']['header_admin_user'], |
||||
324 | $GLOBALS['egw_info']['server']['header_admin_password'])) |
||||
325 | { |
||||
326 | //error_log(__METHOD__."() Invalid password: $_POST[FormDomain]: used $_POST[FormUser]/md5($_POST[FormPW])=".md5($_POST['FormPW'])." != {$GLOBALS['egw_info']['server']['header_admin_user']}/{$GLOBALS['egw_info']['server']['header_admin_password']}"); |
||||
327 | $GLOBALS['egw_info']['setup']['ConfigLoginMSG'] = lang('Invalid password'); |
||||
328 | return false; |
||||
329 | } |
||||
330 | $this->ConfigDomain = $_SESSION['egw_setup_domain'] = $_POST['FormDomain']; |
||||
331 | break; |
||||
332 | |||||
333 | default: |
||||
334 | case 'header': |
||||
335 | if (!$this->check_auth($_POST['FormUser'], $_POST['FormPW'], |
||||
336 | $GLOBALS['egw_info']['server']['header_admin_user'], |
||||
337 | $GLOBALS['egw_info']['server']['header_admin_password'])) |
||||
338 | { |
||||
339 | $GLOBALS['egw_info']['setup']['ConfigLoginMSG'] = lang('Invalid password'); |
||||
340 | return false; |
||||
341 | } |
||||
342 | break; |
||||
343 | } |
||||
344 | $_SESSION['egw_setup_auth_type'] = $auth_type; |
||||
345 | $_SESSION['ConfigLang'] = self::get_lang(); |
||||
346 | $_SESSION['egw_last_action_time'] = time(); |
||||
347 | session_regenerate_id(true); |
||||
348 | $this->set_cookie(self::SESSIONID, session_id(), 0); |
||||
349 | |||||
350 | return true; |
||||
351 | } |
||||
352 | //error_log(__METHOD__."('$auth_type') \$_COOKIE['".self::SESSIONID."'] = ".array2string($_COOKIE[self::SESSIONID]).", \$_SESSION=".array2string($_SESSION)); |
||||
353 | if ($_SESSION['egw_last_action_time'] < time() - self::TIMEOUT) |
||||
354 | { |
||||
355 | $this->set_cookie(self::SESSIONID, '', time()-86400); |
||||
356 | session_destroy(); |
||||
357 | $GLOBALS['egw_info']['setup'][$_SESSION['egw_setup_auth_type'] == 'config' ? 'ConfigLoginMSG' : 'HeaderLoginMSG'] = |
||||
358 | lang('Session expired'); |
||||
359 | return false; |
||||
360 | } |
||||
361 | if ($auth_type == 'config') |
||||
362 | { |
||||
363 | $this->ConfigDomain = $_SESSION['egw_setup_domain']; |
||||
364 | } |
||||
365 | // update session timeout |
||||
366 | $_SESSION['egw_last_action_time'] = time(); |
||||
367 | |||||
368 | // we have a valid session for $auth_type |
||||
369 | return true; |
||||
370 | } |
||||
371 | |||||
372 | /** |
||||
373 | * check if username and password is valid |
||||
374 | * |
||||
375 | * this function compares the supplied and stored username and password |
||||
376 | * as any of the passwords can be clear text or md5 we convert them to md5 |
||||
377 | * internal and compare always the md5 hashs |
||||
378 | * |
||||
379 | * @param string $user the user supplied username |
||||
380 | * @param string $pw the user supplied password |
||||
381 | * @param string $conf_user the configured username |
||||
382 | * @param string $hash hash to check password agains (no {prefix} for plain and md5!) |
||||
383 | * @returns bool true on success |
||||
384 | */ |
||||
385 | static function check_auth($user, $pw, $conf_user, $hash) |
||||
386 | { |
||||
387 | if ($user !== $conf_user) |
||||
388 | { |
||||
389 | $ret = false; // wrong username |
||||
390 | } |
||||
391 | else |
||||
392 | { |
||||
393 | // support for old plain-text passwords without "{plain}" prefix |
||||
394 | if ($hash[0] !== '{' && !preg_match('/^[0-9a-f]{32}$/', $hash)) |
||||
395 | { |
||||
396 | $hash = '{plain}'.$hash; |
||||
397 | } |
||||
398 | $ret = Api\Auth::compare_password($pw, $hash, 'md5'); |
||||
399 | } |
||||
400 | //error_log(__METHOD__."('$user', '$pw', '$conf_user', '$hash') returning ".array2string($ret)); |
||||
401 | return $ret; |
||||
402 | } |
||||
403 | |||||
404 | /** |
||||
405 | * Check for correct IP, if an IP address should be enforced |
||||
406 | * |
||||
407 | * @param string $remoteip |
||||
408 | * @return boolean |
||||
409 | */ |
||||
410 | function checkip($remoteip='') |
||||
411 | { |
||||
412 | //echo "<p>setup::checkip($remoteip) against setup_acl='".$GLOBALS['egw_info']['server']['setup_acl']."'</p>\n"; |
||||
413 | $allowed_ips = explode(',',@$GLOBALS['egw_info']['server']['setup_acl']); |
||||
414 | if(empty($GLOBALS['egw_info']['server']['setup_acl']) || !is_array($allowed_ips)) |
||||
415 | { |
||||
416 | return True; // no test |
||||
417 | } |
||||
418 | $remotes = explode('.',$remoteip); |
||||
419 | foreach($allowed_ips as $value) |
||||
420 | { |
||||
421 | if (!preg_match('/^[0-9.]+$/',$value)) |
||||
422 | { |
||||
423 | $value = gethostbyname($was=$value); // resolve domain-name, eg. a dyndns account |
||||
424 | //echo "resolving '$was' to '$value'<br>\n"; |
||||
425 | } |
||||
426 | $values = explode('.',$value); |
||||
427 | for($i = 0; $i < count($values); ++$i) |
||||
0 ignored issues
–
show
|
|||||
428 | { |
||||
429 | if ((int) $values[$i] != (int) $remotes[$i]) |
||||
430 | { |
||||
431 | break; |
||||
432 | } |
||||
433 | } |
||||
434 | if ($i == count($values)) |
||||
435 | { |
||||
436 | return True; // match |
||||
437 | } |
||||
438 | } |
||||
439 | $GLOBALS['egw_info']['setup']['ConfigLoginMSG'] = lang('Invalid IP address').' '.$remoteip; |
||||
440 | error_log(__METHOD__.'-> checking IP failed:'.print_r($remoteip,true)); |
||||
441 | return False; |
||||
442 | } |
||||
443 | |||||
444 | /** |
||||
445 | * Return X.X.X major version from X.X.X.X versionstring |
||||
446 | * |
||||
447 | * @param string $versionstring |
||||
448 | */ |
||||
449 | function get_major($versionstring) |
||||
450 | { |
||||
451 | if(!$versionstring) |
||||
452 | { |
||||
453 | return False; |
||||
454 | } |
||||
455 | |||||
456 | $version = str_replace('pre','.',$versionstring); |
||||
457 | $varray = explode('.',$version); |
||||
458 | $major = implode('.',array($varray[0],$varray[1],$varray[2])); |
||||
459 | |||||
460 | return $major; |
||||
461 | } |
||||
462 | |||||
463 | /** |
||||
464 | * Clear system/user level cache so as to have it rebuilt with the next access |
||||
465 | * |
||||
466 | * @deprecated AFAIK this code is not used anymore -- RalfBecker 2005/11/04 |
||||
467 | */ |
||||
468 | function clear_session_cache() |
||||
469 | { |
||||
470 | } |
||||
471 | |||||
472 | /** |
||||
473 | * Add an application to the phpgw_applications table |
||||
474 | * |
||||
475 | * @param string $appname Application 'name' with a matching $setup_info[$appname] array slice |
||||
476 | * @param $_enable =99 set to True/False to override setup.inc.php setting |
||||
0 ignored issues
–
show
|
|||||
477 | * @param array $setup_info =null default use $GLOBALS['setup_info'] |
||||
478 | */ |
||||
479 | function register_app($appname, $_enable=99, array $setup_info=null) |
||||
480 | { |
||||
481 | if (!isset($setup_info)) $setup_info = $GLOBALS['setup_info']; |
||||
482 | |||||
483 | if(!$appname) |
||||
484 | { |
||||
485 | return False; |
||||
486 | } |
||||
487 | |||||
488 | if($_enable == 99) |
||||
489 | { |
||||
490 | $_enable = $setup_info[$appname]['enable']; |
||||
491 | } |
||||
492 | $enable = (int)$_enable; |
||||
493 | |||||
494 | if($GLOBALS['DEBUG']) |
||||
495 | { |
||||
496 | echo '<br>register_app(): ' . $appname . ', version: ' . $setup_info[$appname]['version'] . ', tables: ' . implode(', ',$setup_info[$appname]['tables']) . '<br>'; |
||||
497 | // _debug_array($setup_info[$appname]); |
||||
498 | } |
||||
499 | |||||
500 | if($setup_info[$appname]['version']) |
||||
501 | { |
||||
502 | if($setup_info[$appname]['tables']) |
||||
503 | { |
||||
504 | $tables = implode(',',$setup_info[$appname]['tables']); |
||||
505 | } |
||||
506 | if ($setup_info[$appname]['tables_use_prefix'] == True) |
||||
507 | { |
||||
508 | if($GLOBALS['DEBUG']) |
||||
509 | { |
||||
510 | echo "<br>$appname uses tables_use_prefix, storing ". $setup_info[$appname]['tables_prefix']." as prefix for tables\n"; |
||||
511 | } |
||||
512 | $this->db->insert($this->config_table,array( |
||||
513 | 'config_app' => $appname, |
||||
514 | 'config_name' => $appname.'_tables_prefix', |
||||
515 | 'config_value' => $setup_info[$appname]['tables_prefix'], |
||||
516 | ),False,__LINE__,__FILE__); |
||||
517 | } |
||||
518 | try { |
||||
519 | $this->db->insert($this->applications_table,array( |
||||
520 | 'app_name' => $appname, |
||||
521 | 'app_enabled' => $enable, |
||||
522 | 'app_order' => $setup_info[$appname]['app_order'], |
||||
523 | 'app_tables' => (string)$tables, // app_tables is NOT NULL |
||||
524 | 'app_version' => $setup_info[$appname]['version'], |
||||
525 | 'app_index' => $setup_info[$appname]['index'], |
||||
526 | 'app_icon' => $setup_info[$appname]['icon'], |
||||
527 | 'app_icon_app' => $setup_info[$appname]['icon_app'], |
||||
528 | ),False,__LINE__,__FILE__); |
||||
529 | } |
||||
530 | catch (Api\Db\Exception\InvalidSql $e) |
||||
531 | { |
||||
532 | // ease update from pre 1.6 eg. 1.4 not having app_index, app_icon, app_icon_app columns |
||||
533 | _egw_log_exception($e); |
||||
534 | |||||
535 | $this->db->insert($this->applications_table,array( |
||||
536 | 'app_name' => $appname, |
||||
537 | 'app_enabled' => $enable, |
||||
538 | 'app_order' => $setup_info[$appname]['app_order'], |
||||
539 | 'app_tables' => (string)$tables, // app_tables is NOT NULL |
||||
540 | 'app_version' => $setup_info[$appname]['version'], |
||||
541 | ),False,__LINE__,__FILE__); |
||||
542 | } |
||||
543 | Api\Egw\Applications::invalidate(); |
||||
544 | } |
||||
545 | } |
||||
546 | |||||
547 | /** |
||||
548 | * Check if an application has info in the db |
||||
549 | * |
||||
550 | * @param $appname Application 'name' with a matching $setup_info[$appname] array slice |
||||
0 ignored issues
–
show
The type
Application 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. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths
Loading history...
|
|||||
551 | * @param $enabled optional, set to False to not enable this app |
||||
0 ignored issues
–
show
The type
optional 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. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths
Loading history...
|
|||||
552 | */ |
||||
553 | function app_registered($appname) |
||||
554 | { |
||||
555 | if(!$appname) |
||||
556 | { |
||||
557 | return False; |
||||
558 | } |
||||
559 | |||||
560 | if(@$GLOBALS['DEBUG']) |
||||
561 | { |
||||
562 | echo '<br>app_registered(): checking ' . $appname . ', table: ' . $this->applications_table; |
||||
563 | // _debug_array($setup_info[$appname]); |
||||
564 | } |
||||
565 | |||||
566 | if ($this->db->select($this->applications_table,'COUNT(*)',array('app_name' => $appname),__LINE__,__FILE__)->fetchColumn()) |
||||
567 | { |
||||
568 | if(@$GLOBALS['DEBUG']) |
||||
569 | { |
||||
570 | echo '... app previously registered.'; |
||||
571 | } |
||||
572 | return True; |
||||
573 | } |
||||
574 | if(@$GLOBALS['DEBUG']) |
||||
575 | { |
||||
576 | echo '... app not registered'; |
||||
577 | } |
||||
578 | return False; |
||||
579 | } |
||||
580 | |||||
581 | /** |
||||
582 | * Update application info in the db |
||||
583 | * |
||||
584 | * @param string $appname Application 'name' with a matching $setup_info[$appname] array slice |
||||
585 | * @param array $setup_info =null default use $GLOBALS['setup_info'] |
||||
586 | */ |
||||
587 | function update_app($appname, array $setup_info=null) |
||||
588 | { |
||||
589 | if (!isset($setup_info)) $setup_info = $GLOBALS['setup_info']; |
||||
590 | |||||
591 | if(!$appname) |
||||
592 | { |
||||
593 | return False; |
||||
594 | } |
||||
595 | |||||
596 | if($GLOBALS['DEBUG']) |
||||
597 | { |
||||
598 | echo '<br>update_app(): ' . $appname . ', version: ' . $setup_info[$appname]['currentver'] . ', table: ' . $this->applications_table . '<br>'; |
||||
599 | // _debug_array($setup_info[$appname]); |
||||
600 | } |
||||
601 | |||||
602 | if(!$this->app_registered($appname)) |
||||
603 | { |
||||
604 | return False; |
||||
605 | } |
||||
606 | |||||
607 | if($setup_info[$appname]['version']) |
||||
608 | { |
||||
609 | //echo '<br>' . $setup_info[$appname]['version']; |
||||
610 | if($setup_info[$appname]['tables']) |
||||
611 | { |
||||
612 | $tables = implode(',',$setup_info[$appname]['tables']); |
||||
613 | } |
||||
614 | $this->db->update($this->applications_table,array( |
||||
615 | 'app_enabled' => $setup_info[$appname]['enable'], |
||||
616 | 'app_order' => $setup_info[$appname]['app_order'], |
||||
617 | 'app_tables' => (string)$tables, // app_tables is NOT NULL |
||||
618 | 'app_version' => $setup_info[$appname]['version'], |
||||
619 | 'app_index' => $setup_info[$appname]['index'], |
||||
620 | 'app_icon' => $setup_info[$appname]['icon'], |
||||
621 | 'app_icon_app' => $setup_info[$appname]['icon_app'], |
||||
622 | ),array('app_name'=>$appname),__LINE__,__FILE__); |
||||
623 | |||||
624 | Api\Egw\Applications::invalidate(); |
||||
625 | } |
||||
626 | } |
||||
627 | |||||
628 | /** |
||||
629 | * Update application version in applications table, post upgrade |
||||
630 | * |
||||
631 | * @param $setup_info * Array of application information (multiple apps or single) |
||||
632 | * @param $appname * Application 'name' with a matching $setup_info[$appname] array slice |
||||
633 | * @param $tableschanged ??? |
||||
0 ignored issues
–
show
|
|||||
634 | */ |
||||
635 | function update_app_version($setup_info, $appname, $tableschanged = True) |
||||
636 | { |
||||
637 | if(!$appname) |
||||
638 | { |
||||
639 | return False; |
||||
640 | } |
||||
641 | |||||
642 | if($tableschanged == True) |
||||
643 | { |
||||
644 | $GLOBALS['egw_info']['setup']['tableschanged'] = True; |
||||
645 | } |
||||
646 | if($setup_info[$appname]['currentver']) |
||||
647 | { |
||||
648 | $this->db->update($this->applications_table,array( |
||||
649 | 'app_version' => $setup_info[$appname]['currentver'], |
||||
650 | ),array('app_name'=>$appname),__LINE__,__FILE__); |
||||
651 | |||||
652 | Api\Egw\Applications::invalidate(); |
||||
653 | } |
||||
654 | return $setup_info; |
||||
655 | } |
||||
656 | |||||
657 | /** |
||||
658 | * de-Register an application |
||||
659 | * |
||||
660 | * @param $appname Application 'name' with a matching $setup_info[$appname] array slice |
||||
661 | */ |
||||
662 | function deregister_app($appname) |
||||
663 | { |
||||
664 | if(!$appname) |
||||
665 | { |
||||
666 | return False; |
||||
667 | } |
||||
668 | |||||
669 | // Remove categories |
||||
670 | $this->db->delete(Api\Categories::TABLE, array('cat_appname'=>$appname),__LINE__,__FILE__); |
||||
671 | Api\Categories::invalidate_cache($appname); |
||||
672 | |||||
673 | // Remove config, if we are not deinstalling old phpgwapi (as that's global api config!) |
||||
674 | if ($appname != 'phpgwapi') |
||||
675 | { |
||||
676 | $this->db->delete(Api\Config::TABLE, array('config_app'=>$appname),__LINE__,__FILE__); |
||||
677 | } |
||||
678 | //echo 'DELETING application: ' . $appname; |
||||
679 | $this->db->delete($this->applications_table,array('app_name'=>$appname),__LINE__,__FILE__); |
||||
680 | |||||
681 | Api\Egw\Applications::invalidate(); |
||||
682 | |||||
683 | // Remove links to the app |
||||
684 | Link::unlink(0, $appname); |
||||
685 | } |
||||
686 | |||||
687 | /** |
||||
688 | * Register an application's hooks |
||||
689 | * |
||||
690 | * @param $appname Application 'name' with a matching $setup_info[$appname] array slice |
||||
691 | */ |
||||
692 | function register_hooks($appname) |
||||
693 | { |
||||
694 | if(!$appname) |
||||
695 | { |
||||
696 | return False; |
||||
697 | } |
||||
698 | |||||
699 | Api\Hooks::read(true); |
||||
700 | } |
||||
701 | |||||
702 | /** |
||||
703 | * Setup default and forced preferences, when an application gets installed |
||||
704 | * |
||||
705 | * @param string $appname |
||||
706 | * @return boolean false app not found or no hook settings, true settings found and defaull & forced prefs stored, if there are any defined |
||||
707 | */ |
||||
708 | function set_default_preferences($appname) |
||||
709 | { |
||||
710 | $setup_info = $GLOBALS['setup_info'][$appname]; |
||||
711 | |||||
712 | if (!isset($setup_info) || !isset($setup_info['hooks'])) |
||||
713 | { |
||||
714 | return false; // app not found or no hook |
||||
715 | } |
||||
716 | $GLOBALS['settings'] = array(); |
||||
717 | $hook_data = array('location' => 'settings','setup' => true); |
||||
718 | if (isset($setup_info['hooks']['settings'])) |
||||
719 | { |
||||
720 | $settings = ExecMethod($setup_info['hooks']['settings'],$hook_data); |
||||
0 ignored issues
–
show
The function
ExecMethod() has been deprecated: use autoloadable class-names, instanciate and call method or use static methods
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.
Loading history...
|
|||||
721 | } |
||||
722 | elseif(in_array('settings',$setup_info['hooks']) && file_exists($file = EGW_INCLUDE_ROOT.'/'.$appname.'/inc/hook_settings.inc.php')) |
||||
723 | { |
||||
724 | include_once($file); |
||||
725 | } |
||||
726 | if (!isset($settings) || !is_array($settings)) |
||||
727 | { |
||||
728 | $settings = $GLOBALS['settings']; // old file hook or not updated new hook |
||||
729 | } |
||||
730 | if (!is_array($settings) || !count($settings)) |
||||
731 | { |
||||
732 | return false; |
||||
733 | } |
||||
734 | // include idots template prefs for (common) preferences |
||||
735 | if ($appname == 'preferences' && (file_exists($file = EGW_INCLUDE_ROOT.'/pixelegg/hook_settings.inc.php') || |
||||
736 | file_exists($file = EGW_INCLUDE_ROOT.'/jdots/hook_settings.inc.php') || |
||||
737 | file_exists($file = EGW_INCLUDE_ROOT.'/phpgwapi/templates/idots/hook_settings.inc.php'))) |
||||
738 | { |
||||
739 | $GLOBALS['settings'] = array(); |
||||
740 | include_once($file); |
||||
741 | if ($GLOBALS['settings']) $settings = array_merge($settings,$GLOBALS['settings']); |
||||
742 | } |
||||
743 | $default = $forced = array(); |
||||
744 | foreach($settings as $name => $setting) |
||||
745 | { |
||||
746 | if (isset($setting['default'])) |
||||
747 | { |
||||
748 | $default[$name] = $setting['default'] === false && $setting['type'] === 'check' ? '0' : (string)$setting['default']; |
||||
749 | } |
||||
750 | if (isset($setting['forced'])) |
||||
751 | { |
||||
752 | $forced[$name] = $setting['forced'] === false && $setting['type'] === 'check' ? '0' : (string)$setting['forced']; |
||||
753 | } |
||||
754 | } |
||||
755 | // store default/forced preferences, if any found |
||||
756 | $preferences = new Api\Preferences(); |
||||
757 | $preferences->read_repository(false); |
||||
758 | foreach(array( |
||||
759 | 'default' => $default, |
||||
760 | 'forced' => $forced, |
||||
761 | ) as $type => $prefs) |
||||
762 | { |
||||
763 | if ($prefs) |
||||
764 | { |
||||
765 | foreach($prefs as $name => $value) |
||||
766 | { |
||||
767 | $preferences->add($appname == 'preferences' ? 'common' : $appname, $name, $value, $type); |
||||
768 | } |
||||
769 | $preferences->save_repository(false, $type); |
||||
770 | //error_log(__METHOD__."('$appname') storing ".($owner==preferences::DEFAULT_ID?'default':'forced')." prefs=".array2string($prefs)); |
||||
771 | } |
||||
772 | } |
||||
773 | return true; |
||||
774 | } |
||||
775 | |||||
776 | /** |
||||
777 | * call the hooks for a single application |
||||
778 | * |
||||
779 | * @param $location hook location - required |
||||
0 ignored issues
–
show
The type
hook 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. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths
Loading history...
|
|||||
780 | * @param $appname application name - optional |
||||
0 ignored issues
–
show
The type
application 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. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths
Loading history...
|
|||||
781 | */ |
||||
782 | static function hook($location, $appname='') |
||||
783 | { |
||||
784 | return Api\Hooks::single($location,$appname,True,True); |
||||
785 | } |
||||
786 | |||||
787 | /** |
||||
788 | * egw version checking, is param 1 < param 2 in phpgw versionspeak? |
||||
789 | * @param $a phpgw version number to check if less than $b |
||||
790 | * @param $b phpgw version number to check $a against |
||||
791 | * @return True if $a < $b |
||||
792 | */ |
||||
793 | function alessthanb($a,$b,$DEBUG=False) |
||||
794 | { |
||||
795 | $num = array('1st','2nd','3rd','4th'); |
||||
796 | |||||
797 | if($DEBUG) |
||||
798 | { |
||||
799 | echo'<br>Input values: ' |
||||
800 | . 'A="'.$a.'", B="'.$b.'"'; |
||||
801 | } |
||||
802 | $newa = str_replace('pre','.',$a); |
||||
803 | $newb = str_replace('pre','.',$b); |
||||
804 | $testa = explode('.',$newa); |
||||
805 | if(@$testa[1] == '') |
||||
806 | { |
||||
807 | $testa[1] = 0; |
||||
808 | } |
||||
809 | |||||
810 | $testb = explode('.',$newb); |
||||
811 | if(@$testb[1] == '') |
||||
812 | { |
||||
813 | $testb[1] = 0; |
||||
814 | } |
||||
815 | if(@$testb[3] == '') |
||||
816 | { |
||||
817 | $testb[3] = 0; |
||||
818 | } |
||||
819 | $less = 0; |
||||
820 | |||||
821 | for($i=0;$i<count($testa);$i++) |
||||
0 ignored issues
–
show
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...
|
|||||
822 | { |
||||
823 | if($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is less than ' . (int)$testb[$i] . ' ...'; } |
||||
824 | if((int)$testa[$i] < (int)$testb[$i]) |
||||
825 | { |
||||
826 | if ($DEBUG) { echo ' yes.'; } |
||||
827 | $less++; |
||||
828 | if($i<3) |
||||
829 | { |
||||
830 | /* Ensure that this is definitely smaller */ |
||||
831 | if($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; } |
||||
832 | $less = 5; |
||||
833 | break; |
||||
834 | } |
||||
835 | } |
||||
836 | elseif((int)$testa[$i] > (int)$testb[$i]) |
||||
837 | { |
||||
838 | if($DEBUG) { echo ' no.'; } |
||||
839 | $less--; |
||||
840 | if($i<2) |
||||
841 | { |
||||
842 | /* Ensure that this is definitely greater */ |
||||
843 | if($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; } |
||||
844 | $less = -5; |
||||
845 | break; |
||||
846 | } |
||||
847 | } |
||||
848 | else |
||||
849 | { |
||||
850 | if($DEBUG) { echo ' no, they are equal or of different length.'; } |
||||
851 | // makes sure eg. '1.0.0' is counted less the '1.0.0.xxx' ! |
||||
852 | $less = count($testa) < count($testb) ? 1 : 0; |
||||
853 | } |
||||
854 | } |
||||
855 | if($DEBUG) { echo '<br>Check value is: "'.$less.'"'; } |
||||
856 | if($less>0) |
||||
857 | { |
||||
858 | if($DEBUG) { echo '<br>A is less than B'; } |
||||
859 | return True; |
||||
860 | } |
||||
861 | elseif($less<0) |
||||
862 | { |
||||
863 | if($DEBUG) { echo '<br>A is greater than B'; } |
||||
864 | return False; |
||||
865 | } |
||||
866 | else |
||||
867 | { |
||||
868 | if($DEBUG) { echo '<br>A is equal to B'; } |
||||
869 | return False; |
||||
870 | } |
||||
871 | } |
||||
872 | |||||
873 | /** |
||||
874 | * egw version checking, is param 1 > param 2 in phpgw versionspeak? |
||||
875 | * |
||||
876 | * @param $a phpgw version number to check if more than $b |
||||
877 | * @param $b phpgw version number to check $a against |
||||
878 | * @return True if $a < $b |
||||
879 | */ |
||||
880 | function amorethanb($a,$b,$DEBUG=False) |
||||
881 | { |
||||
882 | $num = array('1st','2nd','3rd','4th'); |
||||
883 | |||||
884 | if($DEBUG) |
||||
885 | { |
||||
886 | echo'<br>Input values: ' |
||||
887 | . 'A="'.$a.'", B="'.$b.'"'; |
||||
888 | } |
||||
889 | $newa = str_replace('pre','.',$a); |
||||
890 | $newb = str_replace('pre','.',$b); |
||||
891 | $testa = explode('.',$newa); |
||||
892 | if($testa[3] == '') |
||||
893 | { |
||||
894 | $testa[3] = 0; |
||||
895 | } |
||||
896 | $testb = explode('.',$newb); |
||||
897 | if($testb[3] == '') |
||||
898 | { |
||||
899 | $testb[3] = 0; |
||||
900 | } |
||||
901 | $less = 0; |
||||
902 | |||||
903 | for($i=0;$i<count($testa);$i++) |
||||
0 ignored issues
–
show
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...
|
|||||
904 | { |
||||
905 | if($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is more than ' . (int)$testb[$i] . ' ...'; } |
||||
906 | if((int)$testa[$i] > (int)$testb[$i]) |
||||
907 | { |
||||
908 | if($DEBUG) { echo ' yes.'; } |
||||
909 | $less++; |
||||
910 | if($i<3) |
||||
911 | { |
||||
912 | /* Ensure that this is definitely greater */ |
||||
913 | if($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; } |
||||
914 | $less = 5; |
||||
915 | break; |
||||
916 | } |
||||
917 | } |
||||
918 | elseif((int)$testa[$i] < (int)$testb[$i]) |
||||
919 | { |
||||
920 | if($DEBUG) { echo ' no.'; } |
||||
921 | $less--; |
||||
922 | if($i<2) |
||||
923 | { |
||||
924 | /* Ensure that this is definitely smaller */ |
||||
925 | if($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; } |
||||
926 | $less = -5; |
||||
927 | break; |
||||
928 | } |
||||
929 | } |
||||
930 | else |
||||
931 | { |
||||
932 | if($DEBUG) { echo ' no, they are equal.'; } |
||||
933 | $less = 0; |
||||
934 | } |
||||
935 | } |
||||
936 | if($DEBUG) { echo '<br>Check value is: "'.$less.'"'; } |
||||
937 | if($less>0) |
||||
938 | { |
||||
939 | if($DEBUG) { echo '<br>A is greater than B'; } |
||||
940 | return True; |
||||
941 | } |
||||
942 | elseif($less<0) |
||||
943 | { |
||||
944 | if($DEBUG) { echo '<br>A is less than B'; } |
||||
945 | return False; |
||||
946 | } |
||||
947 | else |
||||
948 | { |
||||
949 | if($DEBUG) { echo '<br>A is equal to B'; } |
||||
950 | return False; |
||||
951 | } |
||||
952 | } |
||||
953 | |||||
954 | /** |
||||
955 | * Own instance of the accounts class |
||||
956 | * |
||||
957 | * @var Api\Accounts |
||||
958 | */ |
||||
959 | var $accounts; |
||||
960 | |||||
961 | function setup_account_object(array $config=array()) |
||||
962 | { |
||||
963 | if (!isset($this->accounts) || $this->accounts->config || $config) |
||||
0 ignored issues
–
show
The expression
$this->accounts->config of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
The expression
$config of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||||
964 | { |
||||
965 | if (!is_object($this->db)) |
||||
966 | { |
||||
967 | $this->loaddb(); |
||||
968 | } |
||||
969 | if (!$config) |
||||
0 ignored issues
–
show
The expression
$config of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||||
970 | { |
||||
971 | // load the configuration from the database |
||||
972 | foreach($this->db->select($this->config_table,'config_name,config_value', |
||||
973 | "config_name LIKE 'ads%' OR config_name LIKE 'ldap%' OR config_name LIKE 'account_%' OR config_name LIKE '%encryption%' OR config_name='auth_type'", |
||||
974 | __LINE__,__FILE__) as $row) |
||||
975 | { |
||||
976 | $GLOBALS['egw_info']['server'][$row['config_name']] = $config[$row['config_name']] = $row['config_value']; |
||||
977 | } |
||||
978 | } |
||||
979 | try { |
||||
980 | $this->accounts = new Api\Accounts($config); |
||||
981 | } |
||||
982 | catch (Exception $e) { |
||||
983 | echo "<p><b>".$e->getMessage()."</b></p>\n"; |
||||
984 | return false; |
||||
985 | } |
||||
986 | if (!isset($GLOBALS['egw']->accounts)) $GLOBALS['egw']->accounts = $this->accounts; |
||||
987 | Api\Accounts::cache_invalidate(); // the cache is shared for all instances of the class |
||||
988 | } |
||||
989 | return true; |
||||
990 | } |
||||
991 | |||||
992 | /** |
||||
993 | * Used to store and share password of user "anonymous" between calls to add_account from different app installs |
||||
994 | * @var unknown |
||||
0 ignored issues
–
show
The type
unknown 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. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths
Loading history...
|
|||||
995 | */ |
||||
996 | protected $anonpw; |
||||
997 | |||||
998 | /** |
||||
999 | * add an user account or a user group |
||||
1000 | * |
||||
1001 | * If the $username already exists, only the id is returned, no new user / group gets created, |
||||
1002 | * but if a non-empty password is given it will be changed to that. |
||||
1003 | * |
||||
1004 | * @param string $username alphanumerical username or groupname (account_lid) |
||||
1005 | * @param string $first first name |
||||
1006 | * @param string $last last name |
||||
1007 | * @param string $_passwd cleartext pw or empty or '*unchanged*', to not change pw for existing users |
||||
1008 | * @param string/boolean $primary_group Groupname for users primary group or False for a group, default 'Default' |
||||
0 ignored issues
–
show
|
|||||
1009 | * @param boolean $changepw user has right to change pw, default False = Pw change NOT allowed |
||||
1010 | * @param string $email |
||||
1011 | * @param string &$anonpw=null on return password for anonymous user |
||||
1012 | * @return int the numerical user-id |
||||
1013 | */ |
||||
1014 | function add_account($username,$first,$last,$_passwd,$primary_group='Default',$changepw=False,$email='',&$anonpw=null) |
||||
1015 | { |
||||
1016 | $this->setup_account_object(); |
||||
1017 | |||||
1018 | $primary_group_id = $primary_group ? $this->accounts->name2id($primary_group) : False; |
||||
1019 | |||||
1020 | $passwd = $_passwd; |
||||
1021 | if ($username == 'anonymous') |
||||
1022 | { |
||||
1023 | if (!isset($this->anonpw)) $this->anonpw = Api\Auth::randomstring(16); |
||||
0 ignored issues
–
show
It seems like
EGroupware\Api\Auth::randomstring(16) of type string is incompatible with the declared type unknown of property $anonpw .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..
Loading history...
|
|||||
1024 | $passwd = $anonpw = $this->anonpw; |
||||
1025 | } |
||||
1026 | |||||
1027 | if(!($accountid = $this->accounts->name2id($username, 'account_lid', $primary_group ? 'u' : 'g'))) |
||||
1028 | { |
||||
1029 | $account = array( |
||||
1030 | 'account_type' => $primary_group ? 'u' : 'g', |
||||
1031 | 'account_lid' => $username, |
||||
1032 | 'account_passwd' => $passwd, |
||||
1033 | 'account_firstname' => $first, |
||||
1034 | 'account_lastname' => $last, |
||||
1035 | 'account_status' => 'A', |
||||
1036 | 'account_primary_group' => $primary_group_id, |
||||
1037 | 'account_expires' => -1, |
||||
1038 | 'account_email' => $email, |
||||
1039 | 'account_members' => array() |
||||
1040 | ); |
||||
1041 | |||||
1042 | // check if egw_accounts.account_description already exists, as the update otherwise fails |
||||
1043 | $meta = $GLOBALS['egw_setup']->db->metadata('egw_accounts', true); |
||||
1044 | if (!isset($meta['meta']['account_description'])) |
||||
1045 | { |
||||
1046 | $GLOBALS['egw_setup']->oProc->AddColumn('egw_accounts','account_description',array( |
||||
1047 | 'type' => 'varchar', |
||||
1048 | 'precision' => '255', |
||||
1049 | 'comment' => 'group description' |
||||
1050 | )); |
||||
1051 | } |
||||
1052 | |||||
1053 | if (!($accountid = $this->accounts->save($account))) |
||||
1054 | { |
||||
1055 | error_log("setup::add_account('$username','$first','$last',\$passwd,'$primary_group',$changepw,'$email') failed! accountid=$accountid"); |
||||
1056 | return false; |
||||
1057 | } |
||||
1058 | } |
||||
1059 | // set password for existing account, if given and not '*unchanged*' |
||||
1060 | elseif($_passwd && $_passwd != '*unchanged*') |
||||
1061 | { |
||||
1062 | try { |
||||
1063 | $auth = new Api\Auth; |
||||
1064 | $pw_changed = $auth->change_password(null, $passwd, $accountid); |
||||
1065 | } |
||||
1066 | catch (Exception $e) |
||||
1067 | { |
||||
1068 | unset($e); |
||||
1069 | $pw_changed = false; |
||||
1070 | } |
||||
1071 | if (!$pw_changed) |
||||
1072 | { |
||||
1073 | error_log("setup::add_account('$username','$first','$last',\$passwd,'$primary_group',$changepw,'$email') changin password of exisiting account #$accountid failed!"); |
||||
1074 | return false; |
||||
1075 | } |
||||
1076 | } |
||||
1077 | // call Vfs\Hooks::add{account|group} hook to create the vfs-home-dirs |
||||
1078 | // calling general add{account|group} hook fails, as we are only in setup |
||||
1079 | // --> setup_cmd_admin execs "admin/admin-cli.php --edit-user" to run them |
||||
1080 | if ($primary_group) |
||||
1081 | { |
||||
1082 | Vfs\Hooks::addAccount(array( |
||||
1083 | 'account_id' => $accountid, |
||||
1084 | 'account_lid' => $username, |
||||
1085 | )); |
||||
1086 | } |
||||
1087 | else |
||||
1088 | { |
||||
1089 | Vfs\Hooks::addGroup(array( |
||||
1090 | 'account_id' => $accountid, |
||||
1091 | 'account_lid' => $username, |
||||
1092 | )); |
||||
1093 | } |
||||
1094 | if ($primary_group) // only for users, NOT groups |
||||
1095 | { |
||||
1096 | $this->set_memberships(array($primary_group_id), $accountid); |
||||
1097 | |||||
1098 | if (!$changepw) $this->add_acl('preferences','nopasswordchange',$accountid); |
||||
1099 | } |
||||
1100 | //error_log("setup::add_account('$username','$first','$last',\$passwd,'$primary_group',$changepw,'$email') successfull created accountid=$accountid"); |
||||
1101 | return $accountid; |
||||
1102 | } |
||||
1103 | |||||
1104 | /** |
||||
1105 | * Adding memberships to an account (keeping existing ones!) |
||||
1106 | * |
||||
1107 | * @param array $_groups array of group-id's to add |
||||
1108 | * @param int $user account_id |
||||
1109 | */ |
||||
1110 | function set_memberships($_groups, $user) |
||||
1111 | { |
||||
1112 | $this->setup_account_object(); |
||||
1113 | |||||
1114 | if (!($groups = $this->accounts->memberships($user, true))) |
||||
1115 | { |
||||
1116 | $groups = $_groups; |
||||
1117 | } |
||||
1118 | else |
||||
1119 | { |
||||
1120 | $groups = array_unique(array_merge($groups, $_groups)); |
||||
1121 | } |
||||
1122 | $this->accounts->set_memberships($groups, $user); |
||||
1123 | } |
||||
1124 | |||||
1125 | /** |
||||
1126 | * Check if accounts other then the automatically installed anonymous account exist |
||||
1127 | * |
||||
1128 | * We check via the account object, to deal with different account-storages |
||||
1129 | * |
||||
1130 | * @return boolean |
||||
1131 | */ |
||||
1132 | function accounts_exist() |
||||
1133 | { |
||||
1134 | try { |
||||
1135 | if (!$this->setup_account_object()) return false; |
||||
1136 | |||||
1137 | $this->accounts->search(array( |
||||
1138 | 'type' => 'accounts', |
||||
1139 | 'start' => 0, |
||||
1140 | 'offset' => 2 // we only need to check 2 accounts, if we just check for not anonymous |
||||
1141 | )); |
||||
1142 | |||||
1143 | if ($this->accounts->total != 1) |
||||
1144 | { |
||||
1145 | return $this->accounts->total > 1; |
||||
1146 | } |
||||
1147 | |||||
1148 | // one account, need to check it's not the anonymous one |
||||
1149 | $this->accounts->search(array( |
||||
1150 | 'type' => 'accounts', |
||||
1151 | 'start' => 0, |
||||
1152 | 'offset' => 0, |
||||
1153 | 'query_type' => 'lid', |
||||
1154 | 'query' => 'anonymous', |
||||
1155 | )); |
||||
1156 | } |
||||
1157 | catch (Api\Db\Exception $e) { |
||||
1158 | _egw_log_exception($e); |
||||
1159 | return false; |
||||
1160 | } |
||||
1161 | return !$this->accounts->total; |
||||
1162 | } |
||||
1163 | |||||
1164 | /** |
||||
1165 | * Add ACL rights |
||||
1166 | * |
||||
1167 | * Dont use it to set group-membership, use set_memberships instead! |
||||
1168 | * |
||||
1169 | * @param string|array $apps app-names |
||||
1170 | * @param string $location eg. "run" |
||||
1171 | * @param int|string $account accountid or account_lid |
||||
1172 | * @param int $rights rights to set, default 1 |
||||
1173 | */ |
||||
1174 | function add_acl($apps,$location,$account,$rights=1) |
||||
1175 | { |
||||
1176 | //error_log("setup::add_acl(".(is_array($apps) ? "array('".implode("','",$apps)."')" : "'$apps'").",'$location',$account,$rights)"); |
||||
1177 | if (!is_numeric($account)) |
||||
1178 | { |
||||
1179 | $this->setup_account_object(); |
||||
1180 | $account = $this->accounts->name2id($account); |
||||
1181 | } |
||||
1182 | if(!is_object($this->db)) |
||||
1183 | { |
||||
1184 | $this->loaddb(); |
||||
1185 | } |
||||
1186 | |||||
1187 | if(!is_array($apps)) |
||||
1188 | { |
||||
1189 | $apps = array($apps); |
||||
1190 | } |
||||
1191 | foreach($apps as $app) |
||||
1192 | { |
||||
1193 | $this->db->delete($this->acl_table,array( |
||||
1194 | 'acl_appname' => $app, |
||||
1195 | 'acl_location' => $location, |
||||
1196 | 'acl_account' => $account |
||||
1197 | ),__LINE__,__FILE__); |
||||
1198 | |||||
1199 | if ((int) $rights) |
||||
1200 | { |
||||
1201 | $this->db->insert($this->acl_table,array( |
||||
1202 | 'acl_rights' => $rights |
||||
1203 | ),array( |
||||
1204 | 'acl_appname' => $app, |
||||
1205 | 'acl_location' => $location, |
||||
1206 | 'acl_account' => $account, |
||||
1207 | ),__LINE__,__FILE__); |
||||
1208 | } |
||||
1209 | } |
||||
1210 | } |
||||
1211 | |||||
1212 | /** |
||||
1213 | * checks if one of the given tables exist, returns the first match |
||||
1214 | * |
||||
1215 | * @param array $tables array with possible table-names |
||||
1216 | * @return string/boolean tablename or false |
||||
0 ignored issues
–
show
|
|||||
1217 | */ |
||||
1218 | function table_exist($tables,$force_refresh=False) |
||||
1219 | { |
||||
1220 | static $table_names = False; |
||||
1221 | |||||
1222 | if (!$table_names || $force_refresh) $table_names = $this->db->table_names(); |
||||
1223 | |||||
1224 | if (!$table_names) return false; |
||||
1225 | |||||
1226 | foreach($table_names as $data) |
||||
1227 | { |
||||
1228 | if (($key = array_search($data['table_name'],$tables)) !== false) |
||||
1229 | { |
||||
1230 | return $tables[$key]; |
||||
1231 | } |
||||
1232 | } |
||||
1233 | return false; |
||||
1234 | } |
||||
1235 | |||||
1236 | /** |
||||
1237 | * Checks and set the names of the tables, which get accessed before an update: eg. config- and applications-table |
||||
1238 | * |
||||
1239 | * Other tables can always use the most up to date name |
||||
1240 | */ |
||||
1241 | function set_table_names($force_refresh=False) |
||||
1242 | { |
||||
1243 | foreach(array( |
||||
1244 | 'config_table' => array('egw_config','phpgw_config','config'), |
||||
1245 | 'applications_table' => array('egw_applications','phpgw_applications','applications'), |
||||
1246 | 'accounts_table' => array('egw_accounts','phpgw_accounts'), |
||||
1247 | 'acl_table' => array('egw_acl','phpgw_acl'), |
||||
1248 | 'lang_table' => array('egw_lang','phpgw_lang','lang'), |
||||
1249 | 'languages_table' => array('egw_languages','phpgw_languages','languages'), |
||||
1250 | ) as $name => $tables) |
||||
1251 | { |
||||
1252 | $table = $this->table_exist($tables,$force_refresh); |
||||
1253 | |||||
1254 | if ($table && $table != $this->$name) // only overwrite the default name, if we realy got one (important for new installs) |
||||
1255 | { |
||||
1256 | $this->$name = $table; |
||||
1257 | } |
||||
1258 | //echo "<p>setup::set_table_names: $name = '{$this->$name}'</p>\n"; |
||||
1259 | } |
||||
1260 | } |
||||
1261 | } |
||||
1262 |
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: