1 | <?php |
||||
2 | /** |
||||
3 | * EGroupware Setup - Manage the EGw config file header.inc.php |
||||
4 | * |
||||
5 | * @link http://www.egroupware.org |
||||
6 | * @package setup |
||||
7 | * @author Ralf Becker <RalfBecker-AT-outdoor-training.de> |
||||
8 | * @author Miles Lott <[email protected]> |
||||
9 | * @author Tony Puglisi (Angles) |
||||
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 | |||||
16 | /** |
||||
17 | * Functions to manage the EGw config file header.inc.php |
||||
18 | * |
||||
19 | * Used by manageheader.php and the new setup command line interface setup-cli.php |
||||
20 | * |
||||
21 | * @package setup |
||||
22 | * @author Ralf Becker <RalfBecker-AT-outdoor-training.de> |
||||
23 | * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License |
||||
24 | */ |
||||
25 | class setup_header |
||||
26 | { |
||||
27 | /** |
||||
28 | * @var array with php-extension / ADOdb drive names => describtiv label |
||||
29 | */ |
||||
30 | var $db_fullnames = array( |
||||
31 | 'mysqli' => 'MySQLi (recommended, incl. transactions)', |
||||
32 | 'mysql' => 'MySQL (deprecated)', |
||||
33 | 'mysqlt' => 'MySQL (deprecated, transactions)', |
||||
34 | 'pgsql' => 'PostgreSQL', |
||||
35 | 'mssql' => 'MS SQL Server', |
||||
36 | 'odbc_mssql' => 'MS SQL Server via ODBC', |
||||
37 | 'oracle' => 'Oracle', |
||||
38 | 'odbc_oracle' => 'Oracle via ODBC', |
||||
39 | 'sapdb' => 'SAP/Max DB via ODBC', |
||||
40 | ); |
||||
41 | |||||
42 | /** |
||||
43 | * @var array with php-extension / ADOdb drive names => default port used by database |
||||
44 | */ |
||||
45 | var $default_db_ports = array( |
||||
46 | 'pgsql' => 5432, |
||||
47 | 'mysql' => 3306, |
||||
48 | 'mysqli' => 3306, |
||||
49 | 'mysqlt' => 3306, |
||||
50 | 'mssql' => 1433, |
||||
51 | 'odbc_mssql' => '', |
||||
52 | 'oracle' => 1521, |
||||
53 | 'odbc_oracle' => '', |
||||
54 | 'sapdb' => '', |
||||
55 | ); |
||||
56 | |||||
57 | /** |
||||
58 | * Detect settings or set defaults for the header.inc.php file (used if it does not yet exist) |
||||
59 | * |
||||
60 | * Sets $GLOBALS['egw_info'], $GLOBALS['egw_domains'] and the defines EGW_SERVER_ROOT and EGW_INCLUDE_ROOT, |
||||
61 | * as if the header has been included |
||||
62 | * |
||||
63 | * @param string $domain ='default' domain to set |
||||
64 | */ |
||||
65 | function defaults($domain='default') |
||||
66 | { |
||||
67 | $egw_root = realpath(__DIR__.'/../..'); |
||||
68 | $GLOBALS['egw_info']['server']['server_root'] = $GLOBALS['egw_info']['server']['include_root'] = $egw_root; |
||||
69 | define('EGW_SERVER_ROOT',$egw_root); // this is usally already defined by setup and cant be changed |
||||
70 | define('EGW_INCLUDE_ROOT',$egw_root); |
||||
71 | |||||
72 | $GLOBALS['egw_info']['server']['header_admin_user'] = 'admin'; |
||||
73 | $GLOBALS['egw_info']['server']['header_admin_password'] = ''; |
||||
74 | $GLOBALS['egw_info']['server']['setup_acl'] = ''; |
||||
75 | |||||
76 | if ($domain) $GLOBALS['egw_domain'][$domain] = $this->domain_defaults(); |
||||
77 | |||||
78 | $GLOBALS['egw_info']['server']['show_domain_selectbox'] = false; |
||||
79 | $GLOBALS['egw_info']['server']['db_persistent'] = True; |
||||
80 | $GLOBALS['egw_info']['login_template_set'] = 'default'; |
||||
81 | $GLOBALS['egw_info']['server']['mcrypt_enabled'] = False; |
||||
82 | $GLOBALS['egw_info']['server']['versions']['mcrypt'] = ''; |
||||
83 | $GLOBALS['egw_info']['server']['mcrypt_iv'] = $this->generate_mcyrpt_iv(); |
||||
84 | } |
||||
85 | |||||
86 | function domain_defaults($user='admin',$passwd='',$supported_db=null) |
||||
87 | { |
||||
88 | $null = null; |
||||
89 | if (is_null($supported_db)) $supported_db = $this->check_db_support($null); |
||||
90 | $default_db = count($supported_db) ? $supported_db[0] : 'mysqli'; |
||||
91 | |||||
92 | return array( |
||||
93 | 'db_host' => 'localhost', |
||||
94 | 'db_port' => $this->default_db_ports[$default_db], |
||||
95 | 'db_name' => 'egroupware', |
||||
96 | 'db_user' => 'egroupware', |
||||
97 | 'db_pass' => '', |
||||
98 | 'db_type' => $default_db, |
||||
99 | 'config_user' => $user, |
||||
100 | 'config_passwd' => $passwd, |
||||
101 | ); |
||||
102 | } |
||||
103 | |||||
104 | /** |
||||
105 | * Checks the values of the (included) header.inc.php file |
||||
106 | * |
||||
107 | * The values are set in $GLOBALS['egw_info'], $GLOBALS['egw_domain'] and EGW_SERVER_ROOT |
||||
108 | * |
||||
109 | * @return array with errors or null if no errors |
||||
110 | */ |
||||
111 | function validation_errors($path=EGW_SERVER_ROOT) |
||||
112 | { |
||||
113 | $errors = null; |
||||
114 | |||||
115 | if (!is_dir($path) || !is_readable($path) || !is_dir($path.'/api')) |
||||
116 | { |
||||
117 | $errors[] = lang("%1 '%2' does NOT exist, is not readable by the webserver or contains no EGroupware installation!",lang('Server root'),$path); |
||||
0 ignored issues
–
show
|
|||||
118 | } |
||||
119 | if(!$GLOBALS['egw_info']['server']['header_admin_password']) |
||||
120 | { |
||||
121 | $errors[] = lang("You didn't enter a header admin password"); |
||||
122 | } |
||||
123 | if(!$GLOBALS['egw_info']['server']['header_admin_user']) |
||||
124 | { |
||||
125 | $errors[] = lang("You didn't enter a header admin username"); |
||||
126 | } |
||||
127 | if (!is_array($GLOBALS['egw_domain']) || !count($GLOBALS['egw_domain'])) |
||||
128 | { |
||||
129 | $errors[] = lang('You need to add at least one EGroupware domain / database instance.'); |
||||
130 | } |
||||
131 | else |
||||
132 | { |
||||
133 | foreach($GLOBALS['egw_domain'] as $domain => $data) |
||||
134 | { |
||||
135 | if (!$data['config_passwd']) |
||||
136 | { |
||||
137 | $errors[] = lang("You didn't enter a config password for domain %1",$domain); |
||||
138 | } |
||||
139 | if(!$data['config_user']) |
||||
140 | { |
||||
141 | $errors[] = lang("You didn't enter a config username for domain %1",$domain); |
||||
142 | } |
||||
143 | } |
||||
144 | } |
||||
145 | return $errors; |
||||
146 | } |
||||
147 | |||||
148 | /** |
||||
149 | * Check if any domain using mysql(i) gives a warning about disabled persistent connections |
||||
150 | * |
||||
151 | * @param array $egw_domains |
||||
152 | * @param boolean $persistent =true current value |
||||
153 | * @return boolean |
||||
154 | */ |
||||
155 | function check_db_persistent(array $egw_domains, $persistent=true) |
||||
156 | { |
||||
157 | if ($persistent !== false) |
||||
158 | { |
||||
159 | foreach($egw_domains as $data) |
||||
160 | { |
||||
161 | // check if persistent connections are allowed |
||||
162 | if (substr($data['db_type'], 0, 5) === 'mysql' && !ini_get('mysqli.allow_persistent')) |
||||
163 | { |
||||
164 | $persistent = false; |
||||
165 | break; |
||||
166 | } |
||||
167 | } |
||||
168 | } |
||||
169 | return $persistent; |
||||
170 | } |
||||
171 | |||||
172 | /** |
||||
173 | * generate header.inc.php file from given values |
||||
174 | * |
||||
175 | * setup_header::generate($GLOBALS['egw_info'],$GLOBALS['egw_domains']) |
||||
176 | * should write an identical header.inc.php as the one include |
||||
177 | * |
||||
178 | * @param array $egw_info usual content (in server key) plus keys server_root and include_root |
||||
179 | * @param array $egw_domain info about the existing EGw domains / DB instances |
||||
180 | * @return string content of header.inc.php |
||||
181 | */ |
||||
182 | function generate($egw_info,$egw_domain) |
||||
183 | { |
||||
184 | $tpl = new Framework\Template('../', 'keep'); // 'keep' to not loose '{hash}' prefix of password-hashes! |
||||
185 | $tpl->set_file(array('header' => 'header.inc.php.template')); |
||||
186 | $tpl->set_block('header','domain','domain'); |
||||
187 | |||||
188 | $most_secure_pw_hash = null; |
||||
189 | Api\Auth::passwdhashes($most_secure_pw_hash); |
||||
190 | |||||
191 | foreach($egw_domain as $domain => $data) |
||||
192 | { |
||||
193 | $var = array('DB_DOMAIN' => $domain); |
||||
194 | foreach($data as $name => $value) |
||||
195 | { |
||||
196 | if ($name == 'db_port' && !$value) $value = $this->default_db_ports[$data['db_type']]; |
||||
197 | if ($name == 'config_passwd') |
||||
198 | { |
||||
199 | $var['CONFIG_PASS'] = self::is_hashed($value) ? $value : Api\Auth::encrypt_sql($value, $most_secure_pw_hash); |
||||
200 | } |
||||
201 | else |
||||
202 | { |
||||
203 | $var[strtoupper($name)] = addslashes($value); |
||||
204 | } |
||||
205 | } |
||||
206 | $tpl->set_var($var); |
||||
207 | $tpl->parse('domains','domain',True); |
||||
208 | } |
||||
209 | $tpl->set_var('domain',''); |
||||
210 | |||||
211 | $var = Array(); |
||||
212 | foreach($egw_info['server'] as $name => $value) |
||||
213 | { |
||||
214 | if ($name == 'header_admin_password' && $value && !self::is_hashed($value)) |
||||
215 | { |
||||
216 | $value = Api\Auth::encrypt_sql($value, $most_secure_pw_hash); |
||||
217 | } |
||||
218 | if ($name == 'versions') |
||||
219 | { |
||||
220 | $name = 'mcrypt_version'; |
||||
221 | $value = $value['mcrypt']; |
||||
222 | } |
||||
223 | static $bools = array( |
||||
224 | 'mcrypt_enabled' => 'ENABLE_MCRYPT', |
||||
225 | 'db_persistent' => 'db_persistent', |
||||
226 | 'show_domain_selectbox' => 'DOMAIN_SELECTBOX', |
||||
227 | ); |
||||
228 | if (isset($bools[$name])) |
||||
229 | { |
||||
230 | $name = $bools[$name]; |
||||
231 | $value = $value ? 'true' : 'false'; |
||||
232 | } |
||||
233 | $var[strtoupper($name)] = addslashes($value); |
||||
234 | } |
||||
235 | $tpl->set_var($var); |
||||
236 | |||||
237 | return $tpl->parse('out','header'); |
||||
238 | } |
||||
239 | |||||
240 | /** |
||||
241 | * Generate a random mcrypt_iv vector |
||||
242 | * |
||||
243 | * @return string |
||||
244 | */ |
||||
245 | function generate_mcyrpt_iv() |
||||
246 | { |
||||
247 | /*$mcrypt = mcrypt_module_open(Api\Session::MCRYPT_ALGO, '', Api\Session::MCRYPT_MODE, ''); |
||||
248 | $size = mcrypt_enc_get_iv_size($mcrypt); |
||||
249 | if (function_exists('mcrypt_create_iv')) // PHP 5.3+ |
||||
250 | { |
||||
251 | $iv = mcrypt_create_iv($size, MCRYPT_DEV_URANDOM); |
||||
252 | error_log(__METHOD__."() size=$size returning ".array2string($iv)); |
||||
253 | return $iv; |
||||
254 | }*/ |
||||
255 | $size = 30; |
||||
256 | srand((double)microtime()*1000000); |
||||
257 | $random_char = array( |
||||
258 | '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f', |
||||
259 | 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', |
||||
260 | 'w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L', |
||||
261 | 'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' |
||||
262 | ); |
||||
263 | |||||
264 | $iv = ''; |
||||
265 | for($i=0; $i < $size; $i++) |
||||
266 | { |
||||
267 | $iv .= $random_char[rand(1,count($random_char))]; |
||||
268 | } |
||||
269 | //error_log(__METHOD__."() size=$size returning ".array2string($iv)); |
||||
270 | return $iv; |
||||
271 | } |
||||
272 | |||||
273 | function check_db_support(&$detected) |
||||
274 | { |
||||
275 | $supported_db = $detected = array(); |
||||
276 | foreach(array( |
||||
277 | // short => array(extension,func_to_check,supported_db(s)) |
||||
278 | 'mysqli' => array('mysql','mysqli_connect','mysqli'), |
||||
279 | 'mysql' => array('mysql','mysql_connect','mysql'), |
||||
280 | 'mysqlt' => array('mysql','mysql_connect','mysqlt'), |
||||
281 | 'pgsql' => array('pgsql','pg_connect','pgsql'), |
||||
282 | 'mssql' => array('mssql','mssql_connect','mssql'), |
||||
283 | 'odbc' => array('odbc',false,'sapdb','odbc_mssql','odbc_oracle'), |
||||
284 | 'oracle' => array('oci8',false,'oracle'), |
||||
285 | ) as $db => $data) |
||||
286 | { |
||||
287 | $ext = array_shift($data); |
||||
288 | $func_to_check = array_shift($data); |
||||
289 | $name = isset($this->db_fullnames[$db]) ? $this->db_fullnames[$db] : strtoupper($db); |
||||
290 | if (check_load_extension($ext) || $func_to_check && function_exists($func_to_check)) |
||||
291 | { |
||||
292 | $detected[] = lang('You appear to have %1 support.',$name); |
||||
0 ignored issues
–
show
The call to
lang() has too many arguments starting with $name .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||
293 | $supported_db = array_merge($supported_db,$data); |
||||
294 | } |
||||
295 | else |
||||
296 | { |
||||
297 | $detected[] .= lang('No %1 support found. Disabling',$name); |
||||
298 | } |
||||
299 | } |
||||
300 | return $supported_db; |
||||
301 | } |
||||
302 | |||||
303 | /** |
||||
304 | * Check if pw is hashed |
||||
305 | * |
||||
306 | * @param string $pw |
||||
307 | * @return boolean |
||||
308 | */ |
||||
309 | static function is_hashed($pw) |
||||
310 | { |
||||
311 | $ret = $pw[0] == '{' || preg_match('/^[0-9a-f]{32}$/', $pw); |
||||
312 | //error_log(__METHOD__."('$pw') returning ".array2string($ret)); |
||||
313 | return $ret; |
||||
314 | } |
||||
315 | } |
||||
316 | |||||
317 | // some constanst for pre php4.3 |
||||
318 | if (!defined('PHP_SHLIB_SUFFIX')) |
||||
319 | { |
||||
320 | define('PHP_SHLIB_SUFFIX',strtoupper(substr(PHP_OS, 0,3)) == 'WIN' ? 'dll' : 'so'); |
||||
321 | } |
||||
322 | if (!defined('PHP_SHLIB_PREFIX')) |
||||
323 | { |
||||
324 | define('PHP_SHLIB_PREFIX',PHP_SHLIB_SUFFIX == 'dll' ? 'php_' : ''); |
||||
325 | } |
||||
326 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.