r3845 NotUniqueException: sayonara
[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{
790a60e8
DO
22 $root = (empty($_SERVER['HTTPS']) or $_SERVER['HTTPS'] == 'off') ? 'http://' : 'https://';
23 $root .= isset ($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ($_SERVER['SERVER_NAME'].($_SERVER['SERVER_PORT']=='80'?'':$_SERVER['SERVER_PORT']));
24 // "Since PHP 4.3.0, you will often get a slash or a dot back from
25 // dirname() in situations where the older functionality would have given
26 // you the empty string."
27 // "On Windows, both slash (/) and backslash (\) are used as directory
28 // separator character."
29 $root .= strtr (dirname ($_SERVER['PHP_SELF']), '\\', '/');
30 if (substr ($root, -1) != '/')
31 $root .= '/';
32 header ("Location: ${root}");
0e7f2155
DO
33 exit;
34}
35$title = "RackTables installation: step ${step} of " . count ($stepfunc);
3fb336f6 36require_once ('inc/dictionary.php');
878512c6 37header ('Content-Type: text/html; charset=UTF-8');
0e7f2155 38?>
f48dc2cc
DO
39<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
40<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
0e7f2155 41<head><title><?php echo $title; ?></title>
fffc0727 42<link rel=stylesheet type='text/css' href='pi.css' />
f48dc2cc
DO
43</head>
44<body>
0e7f2155 45<center>
f48dc2cc 46<?php
f92287f4
DO
47echo "<h1>${title}</h1><p>";
48
49echo "</p><form method=post>\n";
50$testres = $stepfunc[$step] ();
51if ($testres)
52{
53 $next_step = $step + 1;
ae067ef3 54 echo "<br><input type=submit value='proceed'>";
f92287f4
DO
55}
56else
57{
58 $next_step = $step;
ae067ef3 59 echo "<br><input type=submit value='retry'>";
f92287f4
DO
60}
61echo "<input type=hidden name=step value='${next_step}'>\n";
62
63?>
64</form>
65</center>
66</body>
67</html>
68
69<?php
0e7f2155
DO
70// Check if the software is already installed.
71function not_already_installed()
f48dc2cc 72{
80138748 73 @include ('inc/secret.php');
f92287f4
DO
74 if (isset ($pdo_dsn))
75 {
76 echo 'Your configuration file exists and seems to hold necessary data already.<br>';
77 return FALSE;
78 }
79 else
80 {
43f06d53 81 echo 'There seem to be no existing installation here, I am going to setup one now.<br>';
f92287f4
DO
82 return TRUE;
83 }
f48dc2cc
DO
84}
85
0e7f2155
DO
86// Check that we can write to configuration file.
87// If so, ask for DB connection paramaters and test
88// the connection. Neither save the parameters nor allow
89// going further until we succeed with the given
90// credentials.
91function init_config ()
92{
80138748 93 if (!is_writable ('inc/secret.php'))
f92287f4 94 {
80138748 95 echo "The inc/secret.php file is not writable by web-server. Make sure it is.";
e826d3d8 96 echo "The following commands should suffice:<pre>touch inc/secret.php; chmod 666 inc/secret.php</pre>";
9b16b1f1 97 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. ';
b836a843 98 echo 'SELinux may be turned back on with "setenforce 1" command.<br>';
f92287f4
DO
99 return FALSE;
100 }
101 if
102 (
103 !isset ($_REQUEST['save_config']) or
104 empty ($_REQUEST['mysql_host']) or
105 empty ($_REQUEST['mysql_db']) or
106 empty ($_REQUEST['mysql_username']) or
107 empty ($_REQUEST['mysql_password'])
108 )
109 {
110 echo "<input type=hidden name=save_config value=1>\n";
ae067ef3
DO
111 echo '<h3>Hint on setting up a database:</h3><pre>';
112 echo "mysql&gt; CREATE DATABASE racktables_db CHARACTER SET utf8 COLLATE utf8_general_ci;\n";
113 echo "mysql&gt; grant all privileges on racktables_db.* to racktables_user@localhost identified by 'MY_SECRET_PASSWORD';\n</pre>";
f92287f4
DO
114 echo '<table>';
115 echo "<tr><td><label for=mysql_host>MySQL host:</label></td>";
116 echo "<td><input type=text name=mysql_host id=mysql_host value=localhost></td></tr>\n";
117 echo "<tr><td><label for=mysql_host>database:</label></td>";
ae067ef3 118 echo "<td><input type=text name=mysql_db id=mysql_db value=racktables_db></td></tr>\n";
f92287f4 119 echo "<tr><td><label for=mysql_username>username:</label></td>";
ae067ef3 120 echo "<td><input type=text name=mysql_username value=racktables_user></td></tr>\n";
f92287f4
DO
121 echo "<tr><td><label for=mysql_password>password:</label></td>";
122 echo "<td><input type=password name=mysql_password></td></tr>\n";
123 echo '</table>';
124 return FALSE;
125 }
126 $pdo_dsn = 'mysql:host=' . $_REQUEST['mysql_host'] . ';dbname=' . $_REQUEST['mysql_db'];
127 try
128 {
129 $dbxlink = new PDO ($pdo_dsn, $_REQUEST['mysql_username'], $_REQUEST['mysql_password']);
130 }
131 catch (PDOException $e)
132 {
133 echo "<input type=hidden name=save_config value=1>\n";
134 echo '<table>';
135 echo "<tr><td><label for=mysql_host>MySQL host:</label></td>";
136 echo "<td><input type=text name=mysql_host id=mysql_host value='" . $_REQUEST['mysql_host'] . "'></td></tr>\n";
137 echo "<tr><td><label for=mysql_host>database:</label></td>";
138 echo "<td><input type=text name=mysql_db id=mysql_db value='" . $_REQUEST['mysql_db'] . "'></td></tr>\n";
139 echo "<tr><td><label for=mysql_username>username:</label></td>";
140 echo "<td><input type=text name=mysql_username value='" . $_REQUEST['mysql_username'] . "'></td></tr>\n";
141 echo "<tr><td><label for=mysql_password>password:</label></td>";
142 echo "<td><input type=password name=mysql_password value='" . $_REQUEST['mysql_password'] . "'></td></tr>\n";
143 echo "<tr><td colspan=2>The above parameters did not work. Check and try again.</td></tr>\n";
144 echo '</table>';
145 return FALSE;
146 }
e1ae3fb4 147
80138748 148 $conf = fopen ('inc/secret.php', 'w+');
f92287f4
DO
149 if ($conf === FALSE)
150 {
80138748 151 echo "Error: failed to open inc/secret.php for writing";
f92287f4
DO
152 return FALSE;
153 }
154 fwrite ($conf, "<?php\n/* This file has been generated automatically by RackTables installer.\n");
155 fwrite ($conf, " * you shouldn't normally edit it unless your database setup has changed.\n");
156 fwrite ($conf, " */\n");
157 fwrite ($conf, "\$pdo_dsn = '${pdo_dsn}';\n");
158 fwrite ($conf, "\$db_username = '" . $_REQUEST['mysql_username'] . "';\n");
e0dcbf1e 159 fwrite ($conf, "\$db_password = '" . $_REQUEST['mysql_password'] . "';\n\n");
2a622048
DO
160 fwrite ($conf, <<<ENDOFTEXT
161// Default setting is to authenticate users locally, but it is possible to
162// employ existing LDAP or Apache userbase. Uncommenting below two lines MAY
163// help in switching authentication to LDAP completely.
ad592f37 164// More info: http://sourceforge.net/apps/mediawiki/racktables/index.php?title=RackTablesAdminGuide
2a622048
DO
165#\$user_auth_src = 'ldap';
166#\$require_local_account = FALSE;
167
168// This is only necessary for 'ldap' authentication source
169\$LDAP_options = array
170(
171 'server' => 'some.server',
172 'domain' => 'some.domain',
173# 'search_dn' => 'ou=people,O=YourCompany',
174 'search_attr' => 'uid',
175# 'displayname_attrs' => 'givenname familyname',
176
177// LDAP cache, values in seconds. Refresh, retry and expiry values are
178// treated exactly as those for DNS SOA record. Example values 300-15-600:
179// unconditionally remeber successful auth for 5 minutes, after that still
180// permit user access, but try to revalidate username and password on the
181// server (not more often, than once in 15 seconds). After 10 minutes of
182// unsuccessful retries give up and deny access, so someone goes to fix
183// LDAP server.
184 'cache_refresh' => 300,
185 'cache_retry' => 15,
186 'cache_expiry' => 600,
187);
188
189
190ENDOFTEXT
191);
f92287f4
DO
192 fwrite ($conf, "?>\n");
193 fclose ($conf);
194 echo "The configuration file has been written successfully.<br>";
0e7f2155 195 return TRUE;
f48dc2cc
DO
196}
197
96e102b2
DO
198function connect_to_db ()
199{
80138748 200 require ('inc/secret.php');
96e102b2
DO
201 global $dbxlink;
202 try
203 {
204 $dbxlink = new PDO ($pdo_dsn, $db_username, $db_password);
205 }
206 catch (PDOException $e)
207 {
208 die ('Error connecting to the database');
209 }
210}
211
212function init_database_static ()
0e7f2155 213{
01539ac3
DO
214 connect_to_db ();
215 global $dbxlink;
485cf8a8
DO
216 if (!isInnoDBSupported())
217 {
218 echo 'InnoDB test failed! Please configure MySQL server properly and retry.';
219 return FALSE;
220 }
01539ac3
DO
221 $result = $dbxlink->query ('show tables');
222 $tables = $result->fetchAll (PDO::FETCH_NUM);
223 $result->closeCursor();
224 unset ($result);
225 if (count ($tables))
226 {
227 echo 'Your database is already holding ' . count ($tables);
228 echo ' tables, so I will stop here and let you check it yourself.<br>';
229 echo 'There is some important data there probably.<br>';
230 return FALSE;
231 }
0e7f2155 232 echo 'Initializing the database...<br>';
96e102b2 233 echo '<table border=1>';
b2bdfd89
DO
234 echo "<tr><th>file</th><th>queries</th><th>errors</th></tr>";
235 $errlist = array();
3fb336f6 236 foreach (array ('structure', 'dictbase') as $part)
f92287f4 237 {
96e102b2
DO
238 $filename = "install/init-${part}.sql";
239 echo "<tr><td>${filename}</td>";
240 $f = fopen ("install/init-${part}.sql", 'r');
96e102b2
DO
241 if ($f === FALSE)
242 {
243 echo "Failed to open install/init-${part}.sql for reading";
244 return FALSE;
245 }
b2bdfd89 246 $longq = '';
96e102b2
DO
247 while (!feof ($f))
248 {
249 $line = fgets ($f);
84986395 250 if ('--' == substr ($line, 0, 2))
96e102b2 251 continue;
b2bdfd89 252 $longq .= $line;
96e102b2
DO
253 }
254 fclose ($f);
b2bdfd89 255 $nq = $nerrs = 0;
5fe42ae4 256 foreach (preg_split ("/;\s*\n/", $longq) as $query)
96e102b2 257 {
5fe42ae4 258 $query = trim($query);
96e102b2
DO
259 if (empty ($query))
260 continue;
261 $nq++;
b2bdfd89
DO
262 if ($dbxlink->exec ($query) === FALSE)
263 {
264 $nerrs++;
265 $errlist[] = $query;
266 }
96e102b2 267 }
b2bdfd89 268 echo "<td>${nq}</td><td>${nerrs}</td></tr>\n";
f92287f4 269 }
3fb336f6 270 // (re)load dictionary by pure PHP means w/o any external file
20ba7f38 271 echo "<tr><td>dictionary</td>";
3fb336f6 272 $nq = $nerrs = 0;
3fb336f6 273 $dictq = array();
ca3d68bd
DO
274 foreach (reloadDictionary() as $query)
275 {
276 $nq++;
277 if ($dbxlink->exec ($query) === FALSE)
3fb336f6 278 {
ca3d68bd
DO
279 $nerrs++;
280 $errlist[] = $query;
3fb336f6 281 }
ca3d68bd 282 }
3fb336f6
DO
283 echo "<td>${nq}</td><td>${nerrs}</td></tr>\n";
284
96e102b2 285 echo '</table>';
b2bdfd89
DO
286 if (count ($errlist))
287 {
288 echo '<pre>The following queries failed:\n';
289 foreach ($errlist as $q)
290 echo "${q}\n\n";
291 echo '</pre>';
292 return FALSE;
293 }
0e7f2155
DO
294 return TRUE;
295}
f48dc2cc 296
96e102b2
DO
297function init_database_dynamic ()
298{
299 connect_to_db();
300 global $dbxlink;
43f06d53 301 if (!isset ($_REQUEST['password']) or empty ($_REQUEST['password']))
96e102b2
DO
302 {
303 $result = $dbxlink->query ('select count(user_id) from UserAccount where user_id = 1');
304 $row = $result->fetch (PDO::FETCH_NUM);
305 $nrecs = $row[0];
306 $result->closeCursor();
307 if (!$nrecs)
308 {
309 echo '<table border=1>';
310 echo '<caption>Administrator password not set</caption>';
311 echo '<tr><td><input type=password name=password></td></tr>';
312 echo '</table>';
313 }
43f06d53 314 return FALSE;
96e102b2
DO
315 }
316 else
317 {
93bdb7ba
DO
318 // Never send cleartext password over the wire.
319 $hash = sha1 ($_REQUEST['password']);
79b8ad1e 320 $query = "INSERT INTO `UserAccount` (`user_id`, `user_name`, `user_password_hash`, `user_realname`) " .
93bdb7ba 321 "VALUES (1,'admin','${hash}','RackTables Administrator')";
43f06d53
DO
322 $result = $dbxlink->exec ($query);
323 echo "Administrator password has been set successfully.<br>";
324 return TRUE;
96e102b2 325 }
96e102b2
DO
326}
327
0e7f2155 328function congrats ()
f48dc2cc 329{
01539ac3 330 echo 'Congratulations! RackTables installation is complete. After pressing Proceed you will ';
ad592f37
DO
331 echo 'enter the system. Authenticate with <strong>admin</strong> username.<br>RackTables project has a ';
332 echo "<a href='http://sourceforge.net/apps/mediawiki/racktables/index.php?title=RackTablesAdminGuide'>";
333 echo "wiki</a> and a ";
334 echo "<a href='http://www.freelists.org/list/racktables-users'>mailing list</a> for users. Have fun.<br>";
0e7f2155 335 return TRUE;
f48dc2cc
DO
336}
337
338?>