]> git.datanom.net - webcal.git/blob - install/install.php
Initial upload
[webcal.git] / install / install.php
1 <?php
2 /* $Id$ */
3
4 if (version_compare(PHP_VERSION, '5.1.3') === -1) {
5 die("PHP >= 5.1.3 is required to run this application");
6 }
7
8 error_reporting(E_ALL);
9 ini_set('display_errors', 0);
10
11 session_start();
12
13 $root = getcwd();
14 chdir('..');
15 $top = getcwd();
16 chdir($root);
17
18 ini_set('include_path', "$top:$top/navigate:$top/utils:$top/include:$top/caldav:$top/caldav/awl:$top/templates:$top/events");
19
20 include_once "$top/utils/timezone.php";
21 include_once "$top/utils/helper.php";
22
23 $db_drivers = array('sqlite','pgsql');
24
25 /* Test for an existing config.inc.php */
26 function remove_config() {
27 if (file_exists("../config.inc.php")) {
28 $postfix = date("c");
29 copy("../config.inc.php", "../$postfix-config.inc.php");
30 unlink("../config.inc.php");
31 }
32 }
33
34 $config_inc = <<<_CONFIG
35 /*******************************************************************
36 * Change only below this line.
37 * But in generel you should not changes these settings
38 * except via the setup script.
39 ******************************************************************/
40
41 define('TITLE', __TITLE__);
42 define('TIMEZONE', __TIMEZONE__);
43 define('ERROR_DISPLAY', __ERROR_DISPLAY__);
44 define('ERROR_LOG', __ERROR_LOG__);
45 define('LOG_FILE', __LOG_FILE__);
46 define('TOP_FOLDER', __TOP_FOLDER__);
47 /* / at the end of WEB_ROOT is mandatory */
48 define('WEB_ROOT', __WEB_ROOT__);
49 define('DBDRIVER', __DBDRIVER__);
50 define('DNS', __DNS__);
51 define('ADMIN_MAIL', __ADMIN_MAIL__);
52
53 /* Settings which can be change by individual users.
54 * Settings are change in config from the menu
55 */
56 define('VIEW_STYLE', __VIEW_STYLE__);
57 define('TIMEOUT', __TIMEOUT__);
58 define('WEEK_START_SUNDAY', __WEEK_START_SUNDAY__);
59 define('START_HOUR', __START_HOUR__);
60 define('END_HOUR', __END_HOUR__);
61
62 /*******************************************************************
63 * Do not change below this line
64 * All changes should be done above
65 ******************************************************************/
66
67 require_once 'include/user_settings.inc.php';
68 require_once 'utils/authenticate.php';
69 require_once 'utils/helper.php';
70
71 session_cache_limiter('private');
72 if (isset(\$_COOKIE['WEBCAL_EXPIRE'])) {
73 \$expire = \$_COOKIE['WEBCAL_EXPIRE'];
74 session_cache_expire(\$expire);
75 unset(\$_COOKIE['WEBCAL_EXPIRE']);
76 setcookie('WEBCAL_EXPIRE', FALSE);
77 }
78 else
79 session_cache_expire(TIMEOUT);
80 session_start();
81 header('Cache-Control: private');
82 \$_SESSION['WEB_ROOT'] = WEB_ROOT;
83
84 error_reporting(E_ALL ^ E_NOTICE ^ E_USER_NOTICE);
85
86 if (isset(\$_SESSION['user_settings'])) {
87 ini_set('date.timezone', \$_SESSION['user_settings']->getTimezone());
88 }
89 else if (defined('TIMEZONE')) {
90 ini_set('date.timezone', TIMEZONE);
91 }
92 else {
93 ini_set('date.timezone', 'Etc/UTC');
94 }
95
96 if (defined('ERROR_DISPLAY')) {
97 if (ERROR_DISPLAY) {
98 ini_set('display_errors', 'on');
99 }
100 else {
101 ini_set('display_errors', 'off');
102 }
103 }
104 if (defined('ERROR_LOG') && ERROR_LOG) {
105 ini_set('log_errors', 'on');
106 ini_set('error_log', LOG_FILE);
107 }
108
109 if (! isset(\$_SESSION['isTimeout'])) {
110 if (isset(\$_SESSION['user_settings']))
111 \$_SESSION['user_settings']->isTimeout();
112 }
113 else
114 unset(\$_SESSION['isTimeout']);
115 _CONFIG;
116
117 $config_apache = <<<_CONFIG
118 Alias __ALIAS__ "__TOP__"
119 <Directory "__TOP__">
120 Options Multiviews SymLinksIfOwnerMatch
121 php_value include_path '.:__TOP__:__TOP__navigate:__TOP__utils:__TOP__include:__TOP__caldav:__TOP__caldav/awl:__TOP__templates:__TOP__events'
122 </Directory>
123 _CONFIG;
124
125 $htaccess = <<<_HTACCESS
126 Options None
127 Order deny,allow
128 Deny from all
129 Allow from 127.0.0.1/32 ::1/128
130 _HTACCESS;
131
132 $head = <<<_HEAD
133 <?xml version="1.0" encoding="utf-8"?>
134 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
135 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
136 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
137 <head>
138 <title>Web Calendar Installation</title>
139 <meta name="generator" content="Bluefish 1.0.7"/>
140 <meta name="author" content="Michael Rasmussen"/>
141 <meta name="date" content="2009-03-23T20:45:48+0100"/>
142 <meta name="copyright" content="© 2007, Michael Rasmussen. Licensed under GPL"/>
143 <meta name="keywords" content=""/>
144 <meta name="description" content=""/>
145 <meta name="ROBOTS" content="NOINDEX, NOFOLLOW"/>
146 <meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8"/>
147 <meta http-equiv="content-style-type" content="text/css"/>
148 <meta http-equiv="expires" content="-1"/>
149 <meta http-equiv="Pragma" content="no-cache"/>
150 <link rel="stylesheet" type="text/css" href="../css/top_level.css" />
151 <link rel="shortcut icon" href="../pixmaps/favicon.ico" />
152 </head>
153 <body>
154 <table style="width: 100%;">
155 <tr>
156 <td style="width: 33%"><img src="../pixmaps/calendar.png" alt="calendar.png" /></td>
157 <td style="width: 33%; text-align: center;"><img style="border: 0" src="../pixmaps/stock_init.png" width="48" height="48" alt="Setup"/></td>
158 <td style="text-align: right"><span style="font-size: 1.6em">DAViCal Web Calendar</span><br/> - A Web Interface for <a href="javascript: newwin('http://rscds.sourceforge.net/');">DAViCal</a></td>
159 </tr>
160 </table>
161 _HEAD;
162
163 $foot = <<<_FOOTER
164 <div id="footer">
165 <p>
166 <a href="http://validator.w3.org/check?uri=referer">
167 <img src="http://www.w3.org/Icons/valid-xhtml10-blue.png"
168 alt="Valid XHTML 1.0 Strict" height="31" width="88" />
169 </a>
170 <a href="http://jigsaw.w3.org/css-validator/check/referer">
171 <img src="http://www.w3.org/Icons/valid-css2-blue.png"
172 alt="Valid CSS 2.0" height="31" width="88" />
173 </a>
174 </p>
175 </div>
176 </body>
177 </html>
178 _FOOTER;
179
180 function shutdown() {
181 global $head, $foot;
182
183 $isError = false;
184 if ($error = error_get_last()) {
185 switch($error['type']) {
186 case E_ERROR:
187 case E_CORE_ERROR:
188 case E_COMPILE_ERROR:
189 case E_USER_ERROR:
190 $isError = true;
191 break;
192 }
193 }
194
195 if ($isError) {
196 print $head;
197 print '<div id=\"ui\">';
198 if ($error['message'] == "Class 'PDO' not found") {
199 echo '<p style="text-align: center; font-size: 1.5em">
200 This install cannot continue because the module PDO is not installed</p>';
201 }
202 else
203 echo "<p style=\"text-align: center; font-size: 1.5em\">Script execution halted ({$error['message']})</p>";
204 print '</div>';
205 print $foot;
206 }
207 remove_config();
208 }
209
210 register_shutdown_function('shutdown');
211
212 function get_server_timezone() {
213 $tz_abbr = date('T');
214 return timezone_name_from_abbr($tz_abbr);
215 }
216
217 function stage_1() {
218 switch ($_POST['driver']) {
219 case 'sqlite':
220 $dns = <<<_DNS
221 <tr>
222 <td class="config">Database file</td>
223 <td class="config">
224 <input type="text" name="dns"/>
225 <input type="hidden" name="driver" value="{$_POST['driver']}"/>
226 </td>
227 </tr>
228 _DNS;
229 break;
230 case 'pgsql':
231 $dns = <<<_DNS
232 <tr>
233 <td class="config" colspan="3">
234 Below you will find reasonable default values for most.<br/>
235 <span style="font-weight: bold">database name</span>: Name of an exiting database used as template<br/>
236 on Postgresql this database is normally named template1<br/>
237 You should normally not need any other information than the following:<br/>
238 <span style="font-weight: bold">postgresql dba</span>: An existing postgresql user with permission to create<br/>
239 new databases and users.<br/>
240 <span style="font-weight: bold">postgresql dba password</span>: Password for this user<br/>
241 <span style="font-weight: bold">Password for webcal admin</span>: Password for the webcal admin user<br/>
242 </td>
243 </tr>
244 <tr>
245 <td class="config">host</td>
246 <td class="config">
247 <input type="text" name="dns[]" value="localhost"/>
248 </td>
249 </tr>
250 <tr>
251 <td class="config">port</td>
252 <td class="config">
253 <input type="text" name="dns[]" value="5432"/>
254 </td>
255 </tr>
256 <tr>
257 <td class="config">database name</td>
258 <td class="config">
259 <input type="text" name="dns[]" value="template1"/>
260 </td>
261 </tr>
262 <tr>
263 <td class="config">postgresql dba</td>
264 <td class="config">
265 <input type="text" name="dns[]" value="root"/>
266 </td>
267 </tr>
268 <tr>
269 <td class="config">postgresql dba password</td>
270 <td class="config">
271 <input type="password" name="dns[]" value="password"/>
272 <input type="hidden" name="driver" value="{$_POST['driver']}"/>
273 </td>
274 </tr>
275 _DNS;
276 break;
277 }
278 return <<<__FORM
279 <h1 style="text-align: center">Setup: Stage 1/4</h1>
280 <form action="{$_SERVER['PHP_SELF']}" method="post">
281 <table class="config">
282 $dns
283 <tr>
284 <td class="config">Password for webcal admin</td>
285 <td class="config"><input name="pwd1" type="password"/></td>
286 </tr>
287 <tr>
288 <td class="config">Repeat Password</td>
289 <td class="config"><input name="pwd2" type="password"/></td>
290 </tr>
291 <tr>
292 <td class="config" colspan="2" style="text-align: center">
293 <input type="hidden" name="stage" value="2"/>
294 <input type="submit" name="action" value=">> Next"/>
295 </td>
296 </tr>
297 </table>
298 </form>
299 __FORM;
300 }
301
302 function stage_2($top, $root) {
303 include_once "$top/utils/persistens.php";
304 global $timezones, $VERSION;
305 $dns = '';
306 $tz = '';
307
308 try {
309 if ($_POST['pwd1'] != $_POST['pwd2'])
310 throw new Exception("Password does not compare");
311 if ($_POST['driver'] == 'sqlite') {
312 $dns = $_POST['dns'];
313 $db = Persistens::getInstance($_POST['driver'], "$top/$dns");
314 $name = NULL;
315 $pwd = NULL;
316 }
317 else {
318 $dns = "host={$_POST['dns'][0]} port={$_POST['dns'][1]} dbname={$_POST['dns'][2]} user={$_POST['dns'][3]} password={$_POST['dns'][4]}";
319 $db = Persistens::getInstance($_POST['driver'], $dns);
320 $name = "webcal";
321 $user = "webcal";
322 $pwd = $_POST['pwd1'];
323 $db->initDatabase($name, $pwd);
324 $db = NULL;
325 $dns = "host={$_POST['dns'][0]} port={$_POST['dns'][1]} dbname=$name user=$user password=$pwd";
326 $db = Persistens::getInstance($_POST['driver'], $dns);
327 //throw new Exception(var_export($dns, true));
328 }
329 $db->createDatabase($name);
330 $db->execute("insert into about (version) values ('$VERSION')");
331 $data['uid'] = 'admin';
332 $data['pwd'] = sha1($_POST['pwd1']);
333 $data['timezone'] = get_server_timezone();
334 $data['userrole'] = 0;
335 $data['seckey'] = '';
336 $data['pubkey'] = '';
337 $data['timeout'] = 15 * 60;
338 $data['view'] = 'week';
339 $data['week_start'] = false;
340 $data['start'] = 8;
341 $data['end'] = 17;
342 $db->newUser($data);
343 }
344 catch (Exception $ex) {
345 remove_config();
346 $result = "<p style=\"text-align: center\">stage2: {$ex->getMessage()}</p>";
347 $result .= "<p style=\"text-align: center\">
348 <input type=\"button\" value=\"Back\"
349 onclick=\"javascript: history.back()\"/></p>";
350 return $result;
351 }
352 $config['DBDRIVER'] = $_POST['driver'];
353 $config['DNS'] = $dns;
354 $_SESSION['config'] = $config;
355 foreach ($timezones as $timezone) {
356 $tz .= "<option value=\"$timezone\"";
357 if ($timezone == get_server_timezone())
358 $tz .= ' selected="true"';
359 $tz .= ">$timezone</option>";
360 }
361 return <<<__FORM
362 <h1 style="text-align: center">Setup: Stage 2/4</h1>
363 <form action="{$_SERVER['PHP_SELF']}" method="post">
364 <table class="config">
365 <tr>
366 <td class="config">Application web root</td>
367 <td class="config"><input name="web_root" type="text"/></td>
368 </tr>
369 <tr>
370 <td class="config">Application title</td>
371 <td class="config"><input name="title" type="text"/></td>
372 </tr>
373 <tr>
374 <td class="config">Server timezone</td>
375 <td class="config"><select name="timezone">$tz</select></td>
376 </tr>
377 <tr>
378 <td class="config">Display errors in browser</td>
379 <td class="config">
380 <select name="display_error">
381 <option value="no">No</option>
382 <option value="yes">Yes</option>
383 </select>
384 </td>
385 </tr>
386 <tr>
387 <td class="config">Log errors</td>
388 <td class="config">
389 <select name="log_error">
390 <option value="no">No</option>
391 <option value="yes">Yes</option>
392 </select>
393 </td>
394 </tr>
395 <tr>
396 <td class="config">Log file</td>
397 <td class="config"><input name="log_file" type="text"/></td>
398 </tr>
399 <tr>
400 <td class="config">Administrator email</td>
401 <td class="config"><input name="admin_email" type="text"/></td>
402 </tr>
403 <tr>
404 <td class="config" colspan="2" style="text-align: center">
405 <input type="hidden" name="stage" value="3"/>
406 <input type="submit" name="action" value=">> Next"/>
407 </td>
408 </tr>
409 </table>
410 </form>
411 __FORM;
412 }
413
414 function stage_3($top, $root) {
415 $config = $_SESSION['config'];
416 $config['WEB_ROOT'] = $_POST['web_root'];
417 $config['TITLE'] = $_POST['title'];
418 $config['TIMEZONE'] = $_POST['timezone'];
419 $config['ERROR_DISPLAY'] = ($_POST['display_error'] == 'yes')? 'TRUE' : 'FALSE';
420 $config['ERROR_LOG'] = ($_POST['log_error'] == 'yes')? 'TRUE' : 'FALSE';
421 $config['LOG_FILE'] = $_POST['log_file'];
422 $config['ADMIN_MAIL'] = $_POST['admin_email'];
423 $_SESSION['config'] = $config;
424 return <<<__FORM
425 <h1 style="text-align: center">Setup: Stage 3/4</h1>
426 <form action="{$_SERVER['PHP_SELF']}" method="post">
427 <table class="config">
428 <tr>
429 <td class="config">Default view</td>
430 <td class="config">
431 <select name="view_style">
432 <option value="day">Day</option>
433 <option value="week" selected="true">Week</option>
434 <option value="month">Month</option>
435 </select>
436 </td>
437 </tr>
438 <tr>
439 <td class="config">Default session timeout in minuts</td>
440 <td class="config"><input name="timeout" type="text" value="60"/></td>
441 </tr>
442 <tr>
443 <td class="config">Default start of week Sunday</td>
444 <td class="config">
445 <select name="week_start_sunday">
446 <option value="no" selected="true">No</option>
447 <option value="yes">Yes</option>
448 </select>
449 </td>
450 </tr>
451 <tr>
452 <td class="config">Default day start</td>
453 <td class="config"><input name="start_day" type="text" value="8"/></td>
454 </tr>
455 <tr>
456 <td class="config">Default day end</td>
457 <td class="config"><input name="end_day" type="text" value="17"/></td>
458 </tr>
459 <tr>
460 <td class="config" colspan="2" style="text-align: center">
461 <input type="hidden" name="stage" value="4"/>
462 <input type="submit" name="action" value=">> Next"/>
463 </td>
464 </tr>
465 </table>
466 </form>
467 __FORM;
468 }
469
470 function stage_4($top, $root) {
471 include_once "$top/utils/persistens.php";
472 global $config_inc, $config_apache, $htaccess;
473
474 $config = $_SESSION['config'];
475 $config['VIEW_STYLE'] = $_POST['view_style'];
476 $config['TIMEOUT'] = $_POST['timeout'] * 60;
477 $config['WEEK_START_SUNDAY'] =
478 ($_POST['week_start_sunday'] == 'yes')? 'TRUE' : 'FALSE';
479 $config['START_HOUR'] = $_POST['start_day'];
480 $config['END_HOUR'] = $_POST['end_day'];
481 $config['TOP_FOLDER'] = $top;
482 $start = strpos($config['WEB_ROOT'], "/");
483 if ($start != 0 || $start === FALSE)
484 $config['WEB_ROOT'] = '/'.$config['WEB_ROOT'];
485 $end = strrpos($config['WEB_ROOT'], "/");
486 if ($end != strlen($config['WEB_ROOT']) - 1 || $end == FALSE)
487 $config['WEB_ROOT'] = $config['WEB_ROOT'].'/';
488 foreach ($config as $key => $value) {
489 if ($value !== 'TRUE' && $value !== 'FALSE')
490 $value = "'$value'";
491 $config_inc = str_replace('__'.$key.'__', $value, $config_inc);
492 }
493 // Create config.inc.php
494 $file = "<?php\n" . $config_inc . "\n?>\n";
495 file_put_contents("$top/config.inc.php", $file);
496 // Create .htaccess in install
497 if (! file_exists("$root/.htaccess"))
498 file_put_contents("$root/.htaccess", $htaccess);
499 // Create webcal in conf.d
500 $root = $config['WEB_ROOT'];
501 $root = substr($root, 0, -1);
502 $config_apache = str_replace('__ALIAS__', $root, $config_apache);
503 $config_apache =
504 str_replace('__TOP__', $config['TOP_FOLDER'].'/', $config_apache);
505 $result = '<p style="text-align: center">If you haven\'t done basic setup
506 by executing the setup script you must Copy/paste the following
507 to /etc/[apache config]/conf.d/webcal.conf and restart apache<br/>';
508 $result .= '<textarea rows="10" cols="60">';
509 $result .= htmlspecialchars($config_apache);
510 $result .= '</textarea></p>';
511 $result .= '<p style="text-align: center">After restart of
512 apache follow this link to webcal';
513 $url = getServerUrl($config['WEB_ROOT']);
514 $webroot = getServerUrl($config['WEB_ROOT'], $root);
515 $result .= " <a href=\"$url\">webcal</a></p>";
516 $result .= '<p style="text-align: center">Remember to disable ' .
517 'write access to ' . "$top/install";
518 // update database
519 if ($config['DBDRIVER'] == 'sqlite') {
520 $db = Persistens::getInstance($config['DBDRIVER'], $top."/".$config['DNS']);
521 }
522 else {
523 $db = Persistens::getInstance($config['DBDRIVER'], $config['DNS']);
524 }
525 $db->changeDefault($config);
526 $_SESSION = array();
527 if (isset($_COOKIE[session_name()])) {
528 setcookie(session_name(), '', time()-42000, '/');
529 }
530 session_destroy();
531 return $result;
532 }
533
534 if (count($_POST) > 0) {
535 if (isset($_POST['stage'])) {
536 switch ($_POST['stage']) {
537 case '1': $page = stage_1(); break;
538 case '2': $page = stage_2($top, $root); break;
539 case '3': $page = stage_3($top, $root); break;
540 case '4': $page = stage_4($top, $root); break;
541 case '5': $page = stage_4($top, $root); break;
542 default: trigger_error("Unknown stage", E_USER_ERROR);
543 }
544 }
545 else {
546 remove_config();
547 trigger_error("Unknown stage", E_USER_ERROR);
548 }
549 }
550 else {
551 remove_config();
552
553 $error = FALSE;
554 $page = '<h1 style="text-align: center">Setup: Stage 0/4</h1>';
555 $page .= '<table class="config">';
556 $page .= '<tr><td>Checking if module mcrypt is available</td>';
557 try {
558 $mcrypt = MCRYPT_ENCRYPT;
559 if (is_integer($mcrypt)) {
560 $page .= '<td><span style="font-size: 1.2em; font-weight: bold;
561 background: green">OK</span></td></tr>';
562 }
563 else {
564 $page .= '<td><span style="font-size: 1.2em; font-weight: bold;
565 background: red">NO</span></td></tr>';
566 $error = TRUE;
567 }
568 } catch (ErrorException $ex) {
569 $page .= '<td><span style="font-size: 1.2em; font-weight: bold;
570 background: red">NO</span></td></tr>';
571 $error = TRUE;
572 }
573 $page .= '<tr><td>Checking if module PDO is available</td>';
574 try {
575 $avail = PDO::getAvailableDrivers();
576 $page .= '<td><span style="font-size: 1.2em; font-weight: bold;
577 background: green">OK</span></td></tr>';
578 }
579 catch (PDOException $ex) {
580 $page .= '<td><span style="font-size: 1.2em; font-weight: bold;
581 background: red">NO</span></td></tr>';
582 $error = TRUE;
583 }
584 //$page .= "<tr><td cols=\"2\">".var_export($avail, true)."</td></tr>";
585 $page .= "<tr><td>Checking if a suitable PDO driver is available</td>";
586 $dbms = NULL;
587 foreach ($db_drivers as $driver) {
588 $driver = strtolower($driver);
589 if (in_array($driver, $avail))
590 $dbms .= "<option value=\"$driver\">$driver</option>";
591 }
592 if ($dbms)
593 $page .= '<td><span style="font-size: 1.2em; font-weight: bold;
594 background: green">OK</span></td></tr>';
595 else {
596 $page .= '<td><span style="font-size: 1.2em; font-weight: bold;
597 background: red">NO</span></td></tr>';
598 $error = TRUE;
599 }
600 $page .= "<tr><td>Checking if application root is writeable</td>";
601 try {
602 if (@file_put_contents("$top/config.inc.php", "") === FALSE)
603 throw new Exception();
604 $page .= '<td><span style="font-size: 1.2em; font-weight: bold;
605 background: green">OK</span></td></tr>';
606 }
607 catch (Exception $ex) {
608 $page .= '<td><span style="font-size: 1.2em; font-weight: bold;
609 background: red">NO</span></td></tr>';
610 $error = TRUE;
611 }
612 $page .= "<tr><td>Checking if install folder is writeable</td>";
613 try {
614 $test_file = hash("md5", date("r", time()));
615 if (@file_put_contents("$root/$test_file", "") === FALSE)
616 throw new Exception();
617 if (unlink("$root/$test_file") === FALSE)
618 throw new Exception();
619 $page .= '<td><span style="font-size: 1.2em; font-weight: bold;
620 background: green">OK</span></td></tr>';
621 }
622 catch (Exception $ex) {
623 $page .= '<td><span style="font-size: 1.2em; font-weight: bold;
624 background: red">NO</span></td></tr>';
625 $error = TRUE;
626 }
627 $page .= '</table><br/><br/>';
628
629 if (! $error) {
630 $page .= <<<__FORM
631 <form action="{$_SERVER['PHP_SELF']}" method="post">
632 <table class="config">
633 <tr>
634 <td class="config">
635 Choose Database system
636 </td>
637 <td class="config">
638 <select name="driver">
639 $dbms
640 </select>
641 </td>
642 </tr>
643 <tr>
644 <td class="config" colspan="2" style="text-align: center">
645 <input type="hidden" name="stage" value="1"/>
646 <input type="submit" name="action" value=">> Next"/>
647 </td>
648 </tr>
649 </table>
650 </form>
651 __FORM;
652 }
653 else {
654 remove_config();
655 $page .= '<p style="text-align: center">Install missing modules or correct
656 errors marked by
657 <span style="font-size: 1.2em; font-weight: bold;background: red">NO</span> to
658 continue installation</p>';
659 }
660 }
661
662 print $head;
663
664 echo "<div id=\"ui\">$page</div>";
665
666 print $foot;
667 ?>
This page took 0.151368 seconds and 6 git commands to generate.