r3036 - reloadDictionary(): act off target release name (or nothing)
[racktables] / install.php
CommitLineData
0e7f2155 1<?php
5b4523dc 2
d3372430
DO
3// This script is intended for execution through a web-browser, e.g.:
4// https://example.com/racktables/install.php
5// See README file for more information.
5b4523dc 6
0e7f2155
DO
7$stepfunc[1] = 'not_already_installed';
8$stepfunc[2] = 'platform_is_ok';
9$stepfunc[3] = 'init_config';
96e102b2
DO
10$stepfunc[4] = 'init_database_static';
11$stepfunc[5] = 'init_database_dynamic';
12$stepfunc[6] = 'congrats';
13$dbxlink = NULL;
0e7f2155
DO
14
15if (isset ($_REQUEST['step']))
16 $step = $_REQUEST['step'];
17else
18 $step = 1;
19
20if ($step > count ($stepfunc))
21{
22 require 'inc/init.php';
23 global $root;
24 header ("Location: " . $root);
25 exit;
26}
27$title = "RackTables installation: step ${step} of " . count ($stepfunc);
3fb336f6 28require_once ('inc/dictionary.php');
0e7f2155 29?>
f48dc2cc
DO
30<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
31<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
0e7f2155 32<head><title><?php echo $title; ?></title>
21fd978f 33<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
f48dc2cc
DO
34<link rel=stylesheet type='text/css' href=pi.css />
35</head>
36<body>
0e7f2155 37<center>
f48dc2cc 38<?php
f92287f4
DO
39echo "<h1>${title}</h1><p>";
40
41echo "</p><form method=post>\n";
42$testres = $stepfunc[$step] ();
43if ($testres)
44{
45 $next_step = $step + 1;
46 echo "<input type=submit value='proceed'>";
47}
48else
49{
50 $next_step = $step;
51 echo "<input type=submit value='retry'>";
52}
53echo "<input type=hidden name=step value='${next_step}'>\n";
54
55?>
56</form>
57</center>
58</body>
59</html>
60
61<?php
0e7f2155
DO
62// Check if the software is already installed.
63function not_already_installed()
f48dc2cc 64{
80138748 65 @include ('inc/secret.php');
f92287f4
DO
66 if (isset ($pdo_dsn))
67 {
68 echo 'Your configuration file exists and seems to hold necessary data already.<br>';
69 return FALSE;
70 }
71 else
72 {
43f06d53 73 echo 'There seem to be no existing installation here, I am going to setup one now.<br>';
f92287f4
DO
74 return TRUE;
75 }
f48dc2cc
DO
76}
77
e4675d3a
DO
78function extension_issues ($funcname, $extname)
79{
80 echo "<tr><td>${extname}</td>";
81 if (function_exists ($funcname))
82 {
83 echo '<td class=msg_success>Ok</td></tr>';
84 return 0;
85 }
86 echo '<td class=msg_error>not found</td></tr>';
87 return 1;
88}
89
0e7f2155
DO
90// Check for PHP extensions.
91function platform_is_ok ()
f48dc2cc 92{
0e7f2155
DO
93 $nerrs = 0;
94 echo "<table border=1><tr><th>check item</th><th>result</th></tr>\n";
95
96 echo '<tr><td>PDO extension</td>';
97 if (class_exists ('PDO'))
98 echo '<td class=msg_success>Ok';
99 else
f48dc2cc 100 {
0e7f2155
DO
101 echo '<td class=msg_error>not found';
102 $nerrs++;
103 }
104 echo '</td></tr>';
f48dc2cc 105
0e7f2155
DO
106 echo '<tr><td>PDO-MySQL</td>';
107 if (defined ('PDO::MYSQL_ATTR_READ_DEFAULT_FILE'))
108 echo '<td class=msg_success>Ok';
109 else
110 {
111 echo '<td class=msg_error>not found';
112 $nerrs++;
113 }
114 echo '</td></tr>';
f48dc2cc 115
e4675d3a
DO
116 $nerrs += extension_issues ('sha1', 'hash function');
117 $nerrs += extension_issues ('preg_match', 'PCRE extension');
118 $nerrs += extension_issues ('ereg', 'POSIX Regex extension');
f48dc2cc 119
0e7f2155
DO
120 echo '<tr><td>SNMP extension</td>';
121 if (defined ('SNMP_NULL'))
122 echo '<td class=msg_success>Ok';
123 else
124 echo '<td class=msg_warning>Not found. Live SNMP tab will not function properly until the extension is installed.';
125 echo '</td></tr>';
f48dc2cc 126
e4675d3a 127 $nerrs += extension_issues ('gd_info', 'GD extension');
f48dc2cc 128
01539ac3 129 echo '<tr><td>HTTP scheme</td>';
fff18256 130 if (!empty($_SERVER['HTTPS']) and $_SERVER['HTTPS'] != 'off')
01539ac3
DO
131 echo '<td class=msg_success>HTTPs';
132 else
133 echo '<td class=msg_warning>HTTP (all your passwords will be transmitted in cleartext)';
134 echo '</td></tr>';
135
e4675d3a 136 $nerrs += extension_issues ('mb_strlen', 'Multibyte string extension');
9ddee5ea
DO
137
138 echo '<tr><td>LDAP extension</td>';
139 if (defined ('LDAP_OPT_DEREF'))
140 echo '<td class=msg_success>Ok';
141 else
142 {
143 echo '<td class=msg_warning>not found, LDAP authentication will not work';
144 }
145 echo '</td></tr>';
146
0e7f2155
DO
147 echo "</table>\n";
148 return !$nerrs;
149}
f48dc2cc 150
0e7f2155
DO
151// Check that we can write to configuration file.
152// If so, ask for DB connection paramaters and test
153// the connection. Neither save the parameters nor allow
154// going further until we succeed with the given
155// credentials.
156function init_config ()
157{
80138748 158 if (!is_writable ('inc/secret.php'))
f92287f4 159 {
80138748
DO
160 echo "The inc/secret.php file is not writable by web-server. Make sure it is.";
161 echo "The following commands should suffice:<pre>touch inc/secret.php\nchmod 666 inc/secret.php</pre>";
9b16b1f1 162 echo 'Fedora Linux with SELinux may require this file to be owned by specific user (apache) and/or executing "setenforce 0" for the time of installation. ';
029563a4 163 echo 'SELinux may be turned back on with "setenforce 1" command.';
f92287f4
DO
164 return FALSE;
165 }
166 if
167 (
168 !isset ($_REQUEST['save_config']) or
169 empty ($_REQUEST['mysql_host']) or
170 empty ($_REQUEST['mysql_db']) or
171 empty ($_REQUEST['mysql_username']) or
172 empty ($_REQUEST['mysql_password'])
173 )
174 {
175 echo "<input type=hidden name=save_config value=1>\n";
176 echo '<table>';
177 echo "<tr><td><label for=mysql_host>MySQL host:</label></td>";
178 echo "<td><input type=text name=mysql_host id=mysql_host value=localhost></td></tr>\n";
179 echo "<tr><td><label for=mysql_host>database:</label></td>";
180 echo "<td><input type=text name=mysql_db id=mysql_db value=racktables></td></tr>\n";
181 echo "<tr><td><label for=mysql_username>username:</label></td>";
182 echo "<td><input type=text name=mysql_username></td></tr>\n";
183 echo "<tr><td><label for=mysql_password>password:</label></td>";
184 echo "<td><input type=password name=mysql_password></td></tr>\n";
185 echo '</table>';
186 return FALSE;
187 }
188 $pdo_dsn = 'mysql:host=' . $_REQUEST['mysql_host'] . ';dbname=' . $_REQUEST['mysql_db'];
189 try
190 {
191 $dbxlink = new PDO ($pdo_dsn, $_REQUEST['mysql_username'], $_REQUEST['mysql_password']);
192 }
193 catch (PDOException $e)
194 {
195 echo "<input type=hidden name=save_config value=1>\n";
196 echo '<table>';
197 echo "<tr><td><label for=mysql_host>MySQL host:</label></td>";
198 echo "<td><input type=text name=mysql_host id=mysql_host value='" . $_REQUEST['mysql_host'] . "'></td></tr>\n";
199 echo "<tr><td><label for=mysql_host>database:</label></td>";
200 echo "<td><input type=text name=mysql_db id=mysql_db value='" . $_REQUEST['mysql_db'] . "'></td></tr>\n";
201 echo "<tr><td><label for=mysql_username>username:</label></td>";
202 echo "<td><input type=text name=mysql_username value='" . $_REQUEST['mysql_username'] . "'></td></tr>\n";
203 echo "<tr><td><label for=mysql_password>password:</label></td>";
204 echo "<td><input type=password name=mysql_password value='" . $_REQUEST['mysql_password'] . "'></td></tr>\n";
205 echo "<tr><td colspan=2>The above parameters did not work. Check and try again.</td></tr>\n";
206 echo '</table>';
207 return FALSE;
208 }
e1ae3fb4
AD
209
210 // Make sure InnoDB is supported
211 require_once 'inc/database.php';
212 if (!isInnoDBSupported ($dbxlink))
213 {
214 echo 'Error: InnoDB support is disabled. See the README for details.';
215 return FALSE;
216 }
217
80138748 218 $conf = fopen ('inc/secret.php', 'w+');
f92287f4
DO
219 if ($conf === FALSE)
220 {
80138748 221 echo "Error: failed to open inc/secret.php for writing";
f92287f4
DO
222 return FALSE;
223 }
224 fwrite ($conf, "<?php\n/* This file has been generated automatically by RackTables installer.\n");
225 fwrite ($conf, " * you shouldn't normally edit it unless your database setup has changed.\n");
226 fwrite ($conf, " */\n");
227 fwrite ($conf, "\$pdo_dsn = '${pdo_dsn}';\n");
228 fwrite ($conf, "\$db_username = '" . $_REQUEST['mysql_username'] . "';\n");
e0dcbf1e 229 fwrite ($conf, "\$db_password = '" . $_REQUEST['mysql_password'] . "';\n\n");
2a622048
DO
230 fwrite ($conf, <<<ENDOFTEXT
231// Default setting is to authenticate users locally, but it is possible to
232// employ existing LDAP or Apache userbase. Uncommenting below two lines MAY
233// help in switching authentication to LDAP completely.
234// More info: http://racktables.org/trac/wiki/RackTablesUserAuthentication
235#\$user_auth_src = 'ldap';
236#\$require_local_account = FALSE;
237
238// This is only necessary for 'ldap' authentication source
239\$LDAP_options = array
240(
241 'server' => 'some.server',
242 'domain' => 'some.domain',
243# 'search_dn' => 'ou=people,O=YourCompany',
244 'search_attr' => 'uid',
245# 'displayname_attrs' => 'givenname familyname',
246
247// LDAP cache, values in seconds. Refresh, retry and expiry values are
248// treated exactly as those for DNS SOA record. Example values 300-15-600:
249// unconditionally remeber successful auth for 5 minutes, after that still
250// permit user access, but try to revalidate username and password on the
251// server (not more often, than once in 15 seconds). After 10 minutes of
252// unsuccessful retries give up and deny access, so someone goes to fix
253// LDAP server.
254 'cache_refresh' => 300,
255 'cache_retry' => 15,
256 'cache_expiry' => 600,
257);
258
259
260ENDOFTEXT
261);
f92287f4
DO
262 fwrite ($conf, "?>\n");
263 fclose ($conf);
264 echo "The configuration file has been written successfully.<br>";
0e7f2155 265 return TRUE;
f48dc2cc
DO
266}
267
96e102b2
DO
268function connect_to_db ()
269{
80138748 270 require ('inc/secret.php');
96e102b2
DO
271 global $dbxlink;
272 try
273 {
274 $dbxlink = new PDO ($pdo_dsn, $db_username, $db_password);
275 }
276 catch (PDOException $e)
277 {
278 die ('Error connecting to the database');
279 }
280}
281
282function init_database_static ()
0e7f2155 283{
01539ac3
DO
284 connect_to_db ();
285 global $dbxlink;
286 $result = $dbxlink->query ('show tables');
287 $tables = $result->fetchAll (PDO::FETCH_NUM);
288 $result->closeCursor();
289 unset ($result);
290 if (count ($tables))
291 {
292 echo 'Your database is already holding ' . count ($tables);
293 echo ' tables, so I will stop here and let you check it yourself.<br>';
294 echo 'There is some important data there probably.<br>';
295 return FALSE;
296 }
0e7f2155 297 echo 'Initializing the database...<br>';
96e102b2 298 echo '<table border=1>';
b2bdfd89
DO
299 echo "<tr><th>file</th><th>queries</th><th>errors</th></tr>";
300 $errlist = array();
3fb336f6 301 foreach (array ('structure', 'dictbase') as $part)
f92287f4 302 {
96e102b2
DO
303 $filename = "install/init-${part}.sql";
304 echo "<tr><td>${filename}</td>";
305 $f = fopen ("install/init-${part}.sql", 'r');
96e102b2
DO
306 if ($f === FALSE)
307 {
308 echo "Failed to open install/init-${part}.sql for reading";
309 return FALSE;
310 }
b2bdfd89 311 $longq = '';
96e102b2
DO
312 while (!feof ($f))
313 {
314 $line = fgets ($f);
315 if (ereg ('^--', $line))
316 continue;
b2bdfd89 317 $longq .= $line;
96e102b2
DO
318 }
319 fclose ($f);
b2bdfd89 320 $nq = $nerrs = 0;
5fe42ae4 321 foreach (preg_split ("/;\s*\n/", $longq) as $query)
96e102b2 322 {
5fe42ae4 323 $query = trim($query);
96e102b2
DO
324 if (empty ($query))
325 continue;
326 $nq++;
b2bdfd89
DO
327 if ($dbxlink->exec ($query) === FALSE)
328 {
329 $nerrs++;
330 $errlist[] = $query;
331 }
96e102b2 332 }
b2bdfd89 333 echo "<td>${nq}</td><td>${nerrs}</td></tr>\n";
f92287f4 334 }
3fb336f6
DO
335 // (re)load dictionary by pure PHP means w/o any external file
336 echo "<tr><th>dictionary</th>";
337 $nq = $nerrs = 0;
3fb336f6 338 $dictq = array();
ca3d68bd
DO
339 foreach (reloadDictionary() as $query)
340 {
341 $nq++;
342 if ($dbxlink->exec ($query) === FALSE)
3fb336f6 343 {
ca3d68bd
DO
344 $nerrs++;
345 $errlist[] = $query;
3fb336f6 346 }
ca3d68bd 347 }
3fb336f6
DO
348 echo "<td>${nq}</td><td>${nerrs}</td></tr>\n";
349
96e102b2 350 echo '</table>';
b2bdfd89
DO
351 if (count ($errlist))
352 {
353 echo '<pre>The following queries failed:\n';
354 foreach ($errlist as $q)
355 echo "${q}\n\n";
356 echo '</pre>';
357 return FALSE;
358 }
0e7f2155
DO
359 return TRUE;
360}
f48dc2cc 361
96e102b2
DO
362function init_database_dynamic ()
363{
364 connect_to_db();
365 global $dbxlink;
43f06d53 366 if (!isset ($_REQUEST['password']) or empty ($_REQUEST['password']))
96e102b2
DO
367 {
368 $result = $dbxlink->query ('select count(user_id) from UserAccount where user_id = 1');
369 $row = $result->fetch (PDO::FETCH_NUM);
370 $nrecs = $row[0];
371 $result->closeCursor();
372 if (!$nrecs)
373 {
374 echo '<table border=1>';
375 echo '<caption>Administrator password not set</caption>';
376 echo '<tr><td><input type=password name=password></td></tr>';
377 echo '</table>';
378 }
43f06d53 379 return FALSE;
96e102b2
DO
380 }
381 else
382 {
93bdb7ba
DO
383 // Never send cleartext password over the wire.
384 $hash = sha1 ($_REQUEST['password']);
79b8ad1e 385 $query = "INSERT INTO `UserAccount` (`user_id`, `user_name`, `user_password_hash`, `user_realname`) " .
93bdb7ba 386 "VALUES (1,'admin','${hash}','RackTables Administrator')";
43f06d53
DO
387 $result = $dbxlink->exec ($query);
388 echo "Administrator password has been set successfully.<br>";
389 return TRUE;
96e102b2 390 }
96e102b2
DO
391}
392
0e7f2155 393function congrats ()
f48dc2cc 394{
01539ac3
DO
395 echo 'Congratulations! RackTables installation is complete. After pressing Proceed you will ';
396 echo 'enter the system. Authenticate with <strong>admin</strong> username.<br>';
397 echo "RackTables web-site runs some <a href='http://racktables.org/trac/wiki'>wiki</a> pages ";
398 echo "and <a href='http://racktables.org/trac/report/1'>a bug tracker</a>.<br>We have also got ";
399 echo "a <a href='http://www.freelists.org/list/racktables-users'>mailing list</a> for users. Have fun.<br>";
0e7f2155 400 return TRUE;
f48dc2cc
DO
401}
402
403?>