root/wifidogadmin/wifidog/install.php

Revision 479, 41.3 kB (checked in by insultant, 8 months ago)

--

Line 
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 // +-------------------------------------------------------------------+
6 // | WiFiDog Authentication Server                                     |
7 // | =============================                                     |
8 // |                                                                   |
9 // | The WiFiDog Authentication Server is part of the WiFiDog captive  |
10 // | portal suite.                                                     |
11 // +-------------------------------------------------------------------+
12 // | PHP version 5 required.                                           |
13 // +-------------------------------------------------------------------+
14 // | Homepage:     http://www.wifidog.org/                             |
15 // | Source Forge: http://sourceforge.net/projects/wifidog/            |
16 // +-------------------------------------------------------------------+
17 // | This program is free software; you can redistribute it and/or     |
18 // | modify it under the terms of the GNU General Public License as    |
19 // | published by the Free Software Foundation; either version 2 of    |
20 // | the License, or (at your option) any later version.               |
21 // |                                                                   |
22 // | This program is distributed in the hope that it will be useful,   |
23 // | but WITHOUT ANY WARRANTY; without even the implied warranty of    |
24 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     |
25 // | GNU General Public License for more details.                      |
26 // |                                                                   |
27 // | You should have received a copy of the GNU General Public License |
28 // | along with this program; if not, contact:                         |
29 // |                                                                   |
30 // | Free Software Foundation           Voice:  +1-617-542-5942        |
31 // | 59 Temple Place - Suite 330        Fax:    +1-617-542-2652        |
32 // | Boston, MA  02111-1307,  USA       gnu@gnu.org                    |
33 // |                                                                   |
34 // +-------------------------------------------------------------------+
35
36 /**
37  * WiFiDog Authentication Server installation and configuration script
38  *
39  * @package    WiFiDogAuthServer
40  * @author     Pascal Leclerc <isf@plec.ca>, Robin Jones and Benoit Grégoire
41  * @copyright  2005-2006 Pascal Leclerc, 2006-2007 Technologies Coeus inc., 2007 Robin Jones
42  * @version    Subversion $Id: install.php 1333 2008-03-11 19:27:39Z papril $
43  * @link       http://www.wifidog.org/
44  */
45
46 /**
47  * Load required files
48  */
49 require_once ('include/path_defines_base.php');
50 empty ($_REQUEST['page']) ? $page = 'Welcome' : $page = $_REQUEST['page']; # The page to be loaded
51 empty ($_REQUEST['action']) ? $action = '' : $action = $_REQUEST['action']; # The action to be done (in page)
52 empty ($_REQUEST['debug']) ? $debug = 0 : $debug = $_REQUEST['debug']; # Use for MySQL debugging
53 empty ($_REQUEST['config']) ? $config = '' : $config = $_REQUEST['config']; # Store data to be saved in config.php
54
55 # Security : Minimal access validation is use by asking user to retreive a random password in a local file. This prevent remote user to access unprotected installation script. It's dummy, easy to implement and better than nothing.
56
57 # Random password generator
58 $password_file = '/tmp/dog_cookie.txt';
59 $random_password = null;
60 if (!file_exists($password_file)) {
61     srand(date("s"));
62     $possible_charactors = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
63     $password = "";
64     while (strlen($random_password) < 8) {
65         $random_password .= substr($possible_charactors, rand() % (strlen($possible_charactors)), 1);
66     }
67     $fd = fopen($password_file, 'w');
68     fwrite($fd, $random_password."\n");
69     fclose($fd);
70 }
71
72 #Read password file
73 $fd = fopen($password_file, "rb");
74 $password = trim(fread($fd, filesize($password_file)));
75 fclose($fd);
76
77 $auth = true;
78
79 if ($page != 'Welcome') {
80     if (isset ($_SERVER['PHP_AUTH_PW'])) {
81         #echo "PHP_AUTH_USER=(" . $_SERVER['PHP_AUTH_USER'] . ") PHP_AUTH_PW=(" . $_SERVER['PHP_AUTH_PW'] . ")"; # DEBUG
82         if ($password == $_SERVER['PHP_AUTH_PW'])
83         $auth = true;
84     }
85 }
86 else
87 $auth = true;
88
89 if (!$auth) {     # Ask user for the password
90     header('WWW-Authenticate: Basic realm="Private"');
91     header('HTTP/1.0 401 Unauthorized');
92     echo "Restricted Access - Authorisation Required!";
93     exit;
94 }
95 # End of Security validation
96
97
98 /************************************************************************************
99  * Begin Dynamic HTML Page Header
100  ************************************************************************************/
101 print<<<EndHTML
102 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
103 <HTML>
104 <HEAD>
105   <TITLE>$page - Wifidog Auth-server installation and configuration</TITLE>
106
107   <SCRIPT type="text/javascript">
108     // This function adds a new configuration value to the "config" hidden input
109     // On submit, the config will be parsed and the value saved to the config.php file
110     function newConfig(dataAdd) {
111       // TODO : Validate input data
112       if (document.myform.config.value == '') {
113         document.myform.config.value = dataAdd;
114       }
115       else {
116         document.myform.config.value = document.myform.config.value + '|' + dataAdd;
117       }
118       //alert(document.myform.config.value);  // DEBUG
119     }
120   </SCRIPT>
121
122 <link rel="stylesheet" type="text/css" href="media/base_theme/stylesheet.css" />
123 </HEAD>
124 <BODY id='page' class='{$page}'>
125
126 <style type="text/css">
127 <!--
128
129 .submit
130 {
131   font-size: 14pt;
132   text-decoration: none;
133   padding: 3px 5px 3px 5px;
134   background-color: #ccccff;
135 }
136
137 table {
138 border-collapse: collapse;
139 }
140
141 -->
142 </style>
143
144
145 <FORM NAME="myform" METHOD="post">
146 <INPUT TYPE="HIDDEN" NAME="action">
147 <INPUT TYPE="HIDDEN" NAME="debug">
148 <INPUT TYPE="HIDDEN" NAME="config">
149 <div id="page_body">
150     <div id="left_area">
151         <div id="left_area_top">
152             <h1>Installation status</h1>
153
154 EndHTML;
155 $pageindex = array("Welcome"=>"Welcome",
156         "Prerequisites"=>"Prerequisites",
157         "Permissions"=>"Permissions",
158             "Dependencies"=> "Dependencies",
159             "Database Access"=> "Database",
160         "Database Connection"=>"testdatabase",
161         "Database Initialisation"=>"dbinit",
162         "Global Options"=>"options",
163         "Language Locale"=>"languages",
164         "User Creation"=>"admin",
165         "Review"=>"Review",
166         "Finish"=>"finish",);
167 foreach($pageindex as $pagekey => $pagevalue){
168     if ($pagevalue != $page){
169         print "$pagekey <br>";
170     }
171     else {
172         print "<strong>$pagekey</strong> <br>";
173     }
174 }
175 print<<<EndHTML
176         </div>
177         <div id="left_area_bottom">
178             <p><a href="../CHANGELOG">Change Log</a><BR>
179             <a href="http://dev.wifidog.org/report/10">Known issues</a></p>
180         </div>
181     </div>
182 <div id="main_area">
183
184     <div id="main_area_top">
185         <table align="center"><tr><td><img src="media/base_theme/images/wifidog_logo_banner.png" /></td></tr></table>
186     </div>
187     <div id="main_area_middle">
188 EndHTML;
189
190 //print "<pre>";      # DEBUG
191 //print_r($_SERVER);  # DEBUG
192 //print_r($_REQUEST); # DEBUG
193 //print "</pre>";     # DEBUG
194 #exit();
195
196 #Begin Perquisite Array     (Needed files/directories with write access)
197 $dir_array = array (
198 'tmp',
199 'tmp/simplepie_cache',
200 'lib/',
201 'tmp/smarty/templates_c',
202 'tmp/smarty/cache',
203 'tmp/openidserver',
204 'lib/simplepie',
205 'lib/feedpressreview',
206 'config.php'
207 );
208 #end perquisite array
209
210
211 #Begin Global Options Array
212 $optionsInfo = array (
213 /*********************************************************************************************
214 TODO:  SSL is now configured in the DB, but should still be handled by the install script
215 'SSL_AVAILABLE' => array (
216 'title' => 'SSL Support',
217 'depend' => 'return 1;',
218 'message' => '&nbsp;'
219 ),
220 ************************************************************************/
221 'CONF_USE_CRON_FOR_DB_CLEANUP' => array (
222 'title' => 'Use cron for DB cleanup',
223 'depend' => 'return 1;',
224 'message' => '&nbsp;'
225 ),
226 'GMAPS_HOTSPOTS_MAP_ENABLED' => array (
227 'title' => 'Google Maps Support',
228 'depend' => 'return 1;',
229 'message' => '&nbsp;'
230 )
231 );
232
233
234
235 $CONFIG_FILE = 'config.php';
236 $LOCAL_CONFIG_FILE = 'local.config.php';
237
238 if (!empty ($config)) # If not empty, save javascript 'config' variable to config.php file
239 saveConfig($config);
240
241 ### Read Configuration file. Keys and Values => define('FOO', 'BRAK');
242 # Use config.php if local.config.php does not exist
243 //if(!file_exists(WIFIDOG_ABS_FILE_PATH."$LOCAL_CONFIG_FILE"))
244 $contentArray = file(WIFIDOG_ABS_FILE_PATH . "$CONFIG_FILE");
245 //else
246 //  $contentArray = file(WIFIDOG_ABS_FILE_PATH."$LOCAL_CONFIG_FILE");
247
248 $configArray = array ();
249
250 foreach ($contentArray as $line) {
251     #print "$line<BR>"; # Debug
252     if (preg_match("/^define\((.+)\);/", $line, $matchesArray)) {
253         //echo '<pre>';print_r($matchesArray);echo '</pre>';
254         list ($key, $value) = explode(',', $matchesArray[1]);
255         $pattern = array (
256         "/^'/",
257         "/'$/"
258         );
259         $replacement = array (
260         '',
261         ''
262         );
263         $key = preg_replace($pattern, $replacement, trim($key));
264         $value = preg_replace($pattern, $replacement, trim($value));
265         $configArray[$key] = $value;
266     }
267 }
268 //echo '<pre>';print_r($configArray);echo '</pre>';
269 # Database connections variables
270 $CONF_DATABASE_HOST = $configArray['CONF_DATABASE_HOST'];
271 $CONF_DATABASE_NAME = $configArray['CONF_DATABASE_NAME'];
272 $CONF_DATABASE_USER = $configArray['CONF_DATABASE_USER'];
273 $CONF_DATABASE_PASSWORD = $configArray['CONF_DATABASE_PASSWORD'];
274
275 //foreach($configArray as $key => $value) { print "K=$key V=$value<BR>"; } exit(); # DEBUG
276
277 ###################################
278 # array (array1(name1, page1), array2(name2, page2), ..., arrayN(nameN, pageN));
279 function navigation($dataArray) {
280     $SERVER = $_SERVER['HTTP_HOST'];
281     $SCRIPT = $_SERVER['SCRIPT_NAME'];
282     print "<p><br></p>";
283     foreach ($dataArray as $num => $navArray) {
284         $title = $navArray['title'];
285         $page = $navArray['page'];
286         empty ($navArray['action']) ? $action = '' : $action = $navArray['action'];
287         print<<<EndHTML
288 <A HREF="#" ONCLICK="document.myform.page.value = '$page'; document.myform.action.value = '$action'; document.myform.submit();" CLASS="submit">$title</A>
289
290 EndHTML;
291         if (array_key_exists($num +1, $dataArray))
292         print "&nbsp; &nbsp;";
293     }
294
295 }
296
297 ###################################
298 #
299 function refreshButton() {
300     print<<<EndHTML
301
302 <p><A HREF="#" ONCLICK="javascript: window.location.reload(true);" CLASS="submit">Refresh</A></p>
303 EndHTML;
304 }
305
306
307 ###################################
308 #
309 /*function debugButton() {
310  print <<<EndHTML
311  <p><INPUT TYPE="button" VALUE="Debug" ONCLICK="javascript: window.location.reload(true);"></p>
312  EndHTML;
313  } */
314
315 ###################################
316 #
317 function saveConfig($data) {
318     print "<!-- saveConfig DATA=($data) -->\n"; # DEBUG
319
320     global $CONFIG_FILE;
321
322     $contentArray = file(WIFIDOG_ABS_FILE_PATH . "$CONFIG_FILE");
323     $fd = fopen(WIFIDOG_ABS_FILE_PATH . "$CONFIG_FILE", 'w');
324
325     $defineArrayToken = array ();
326     $defineArrayToken = explode('|', $data);
327
328     foreach ($defineArrayToken as $nameValue) {
329         list ($name, $value) = explode('=', $nameValue);
330         $defineArray[$name] = $value; # New define value ($name and value)
331         #print "K=$name V=$value<BR>"; # DEBUG
332     }
333
334     foreach ($contentArray as $line) {
335         #print "L=$line<BR>\n";
336         if (preg_match("/^define\((.+)\);/", $line, $matchesArray)) {
337             list ($key, $value) = explode(',', $matchesArray[1]);
338             $pattern = array (
339                 "/^'/",
340                 "/'$/"
341             );
342             $replacement = array (
343                 '',
344                 ''
345                 );
346                 $key = preg_replace($pattern, $replacement, trim($key));
347                 //$value = preg_replace($pattern, $replacement, trim($value));
348
349                 if (array_key_exists($key, $defineArray)) { // A new value is defined
350                     #print "$key EXISTS<BR>";
351                     #print "define => (" . $defineArray[$key] . ")<BR>";
352                     $pattern = array (
353                     "/^\\\'/",
354                     "/\\\'$/"
355                     );
356                     $replacement = array (
357                     "'",
358                     "'"
359                     );
360                     $value = preg_replace($pattern, $replacement, trim($defineArray[$key]));
361                     #print "(define('$key', $value);)<BR>";
362                     fwrite($fd, "define('$key', $value);\n"); # Write the new define($name, $value)
363                 }
364                 else { // The key does not exist (no new value to be saved)
365                     fwrite($fd, $line); # Write the same line in config.php
366                 }
367         }
368         else {
369             fwrite($fd, $line); # Write the line (not a define line). Ex: Commented text
370         }
371     }
372 }
373
374
375
376 /********************************************************************************
377  * MAIN PROCEDURE                                                                *
378  * case statement to navigate through install script
379  *                                                                                *
380  *********************************************************************************/
381 switch ($page) {
382     case 'Permissions' :
383         print "<h1>Permissions</h1>";
384
385         if (function_exists(posix_getpwuid)) {
386             $process_info_user_id = posix_getpwuid(posix_getuid());
387         }
388
389         if ($process_info_user_id) {
390             $process_username = $process_info_user_id['name'];
391         } else {
392             // Posix functions aren't available on windows or couldn't be read
393             $process_username = 'unknown_user';
394         }
395
396         if (function_exists(posix_getgrgid)) {
397             $process_info_group_id = posix_getgrgid(posix_getegid());
398         }
399
400         if ($process_info_group_id) {
401             $process_group = $process_info_group_id['name'];
402         } else {
403             //Posix functions aren't available on windows or couldn't be read
404             $process_group = 'unknown_group';
405         }
406
407         $cmd_mkdir = '';
408         $cmd_chown = '';
409         $error = 0;
410
411         print "<p><em>HTTP daemon UNIX username/group</em>: $process_username/$process_group</p>";
412         #    print "<p><em>HTTPD group</em>: $process_group<BR</p>";
413         print "<p><table BORDER=\"1\"><tr><td><b>Directory</b></td></td><td><b>Owner</b></td><td><b>Writable</b></td></tr>\n";
414
415         foreach ($dir_array as $dir) {
416             print "<tr><td>$dir</td>";
417             if (!file_exists(WIFIDOG_ABS_FILE_PATH . "$dir")) {
418                 print "<TD COLSPAN=\"2\" STYLE=\"text-align:center;\">Missing</td></tr>\n";
419                 $cmd_mkdir .= WIFIDOG_ABS_FILE_PATH . "$dir ";
420                 $cmd_chown .= WIFIDOG_ABS_FILE_PATH . "$dir ";
421                 $error = 1;
422                 continue;
423             }
424
425             if (function_exists(posix_getpwuid)) {
426                 $dir_info = posix_getpwuid(fileowner(WIFIDOG_ABS_FILE_PATH . "$dir"));
427             }
428
429             if ($dir_info) {
430                 $dir_owner_username = $dir_info['name'];
431             } else {
432                 //Posix functions aren't available on windows or couldn't be read
433                 $dir_owner_username = fileowner(WIFIDOG_ABS_FILE_PATH . "$dir");
434             }
435
436             print "<td>$dir_owner_username</td>";
437
438             if (is_writable(WIFIDOG_ABS_FILE_PATH . "$dir")) {
439                 print "<td>YES</td>";
440             } else {
441                 print "<td>NO</td>";
442                 $cmd_chown .= WIFIDOG_ABS_FILE_PATH . "$dir ";
443                 $error = 1;
444             }
445
446             print "</tr>\n";
447         }
448         print "</table>\n";
449
450         if ($error != 1) {
451             navigation(array (
452             array (
453                 "title" => "Back",
454                 "page" => "Prerequisites"
455                 ),
456                 array (
457                 "title" => "Next",
458                 "page" => "Dependencies"
459                 )
460                 ));
461         }
462         else {
463             refreshButton();
464             navigation(array (
465             array (
466                 "title" => "Back",
467                 "page" => "Prerequisites"
468                 )
469                 ));
470                 print "<p>UNIX user <em>$process_username</em> must be able to write to these directories (mkdir, chown or chmod)</p>";
471                 if (!empty ($cmd_mkdir) || !empty ($cmd_mkdir))
472                 print "<p><b>For instance, you may want to use the following commands</b> :</p>\n";
473                 if (!empty ($cmd_mkdir))
474                 print "mkdir $cmd_mkdir <br />";
475                 if (!empty ($cmd_chown))
476                 print "chgrp -R $process_group $cmd_chown;<br/>chmod g+wx $cmd_chown;<br/>";
477                 print "<p>After permission modifications have been preformed, click the REFRESH button to check they have been completed successfully. The NEXT button will then appear to continue with the installation.";
478         }
479         break;
480         ###########################################
481     case 'Dependencies' :
482         print "<h1>Checking Dependencies</h1>";
483         $error = 0;
484         $userData['error']=&$error;
485         require_once("classes/DependenciesList.php");
486         print DependenciesList::getAdminUIStatic($userData);
487         refreshButton();
488         if ($error != 1) {
489             navigation(array (
490             array (
491                 "title" => "Back",
492                 "page" => "Permissions"
493                 ),
494                 array (
495                 "title" => "Next",
496                 "page" => "Database"
497                 )
498                 ));
499         }
500
501         break;
502
503         ###########################################
504     case 'Database' :
505         ### TODO : Valider en javascript que les champs soumit ne sont pas vide
506         #          Pouvoir choisir le port de la DB ???
507         print<<< EndHTML
508 <h1>Database Access Configuration</h1>
509 <BR>
510 <table border="1">
511   <tr><td>Host</td><td><INPUT type="text" name="CONF_DATABASE_HOST" value="$CONF_DATABASE_HOST"></td></tr>
512   <tr><td>DB Name</td><td><INPUT type="text" name="CONF_DATABASE_NAME" value="$CONF_DATABASE_NAME"></td></tr>
513   <tr><td>Username</td><td><INPUT type="text" name="CONF_DATABASE_USER" value="$CONF_DATABASE_USER"></td></tr>
514   <tr><td>Password</td><td><INPUT type="text" name="CONF_DATABASE_PASSWORD" value="$CONF_DATABASE_PASSWORD"></td></tr>
515 </table>
516
517 <p>By clicking Next, your configuration will be automatically saved.</p>
518
519 <script type="text/javascript">
520   function submitDatabaseValue() {
521     newConfig("CONF_DATABASE_HOST='" + document.myform.CONF_DATABASE_HOST.value + "'");
522     newConfig("CONF_DATABASE_NAME='" + document.myform.CONF_DATABASE_NAME.value + "'");
523     newConfig("CONF_DATABASE_USER='" + document.myform.CONF_DATABASE_USER.value + "'");
524     newConfig("CONF_DATABASE_PASSWORD='" + document.myform.CONF_DATABASE_PASSWORD.value + "'");
525   }
526 </script>
527
528 EndHTML;
529
530         navigation(array (
531         array (
532             "title" => "Back",
533             "page" => "Dependencies"
534             ),
535             )); #, array("title" => "Next", "page" => "testdatabase")));
536             print<<< EndHTML
537 <A HREF="#" ONCLICK="javascript: document.myform.page.value='testdatabase'; submitDatabaseValue(); document.myform.submit();" CLASS="submit">Next</A>
538
539 EndHTML;
540
541             break;
542             ###########################################
543     case 'testdatabase' :
544         print "<h1>Database connection</h1>";
545         /* TODO : Tester la version minimale requise de Postgresql                */
546
547         print "<UL><LI>Trying to open a Postgresql database connection : ";
548
549         $conn_string = "host=$CONF_DATABASE_HOST dbname=$CONF_DATABASE_NAME user=$CONF_DATABASE_USER password=$CONF_DATABASE_PASSWORD";
550         $ptr_connexion = pg_connect($conn_string);
551
552         if ($ptr_connexion == TRUE) {
553             print "Success!<BR>";
554         }
555         else {
556             printf ("<p>Unable to connect to database!  Please make sure the server is online and the database \"%s\" exists. Also 'postgresql.conf' and 'pg_hba.conf' must allow the user \"%s\" to open a connection to it on host \"%s\" to continue.  See the error above for clues on what the problem may be.</p>", $CONF_DATABASE_NAME, $CONF_DATABASE_USER, $CONF_DATABASE_HOST);
557             print "<p>Please go back and retry with correct values, or fix your server configuration.</p>";
558             refreshButton();
559             navigation(array(array("title" => "Back", "page" => "Database")));
560             die();
561             break;
562         }
563         print "</li>";
564         print "<li>";
565         $postgresql_info = pg_version();
566         printf ("PostgreSQL server version: %s", $postgresql_info['server']);        print "</li>";
567
568         #        if ($postgresql_info['server'] > $requiredPostgeSQLVersion) { Todo : Do something }
569
570
571         print "</UL>";
572         refreshButton();
573         navigation(array (
574         array (
575             "title" => "Back",
576             "page" => "Database"
577             ),
578             array (
579             "title" => "Next",
580             "page" => "dbinit"
581             )
582             ));
583             break;
584             ###########################################
585     case 'dbinit' :
586         print "<h1>Database Initialisation</h1>";
587         # SQL are executed with PHP, some lines need to be commented out.
588         $file_db_version = 'UNKNOW';
589         $patterns[0] = '/CREATE DATABASE wifidog/';
590         $patterns[1] = '/\\\connect/';
591         //The following is strictly for compatibility with postgresql 7.4
592         $patterns[2] = '/COMMENT/';
593         $patterns[3] = '/^SET /m';
594         $patterns[4] = '/CREATE PROCEDURAL LANGUAGE/';
595         $patterns[5] = '/ALTER SEQUENCE/';
596         $patterns[6] = '/::regclass/';//To fix incompatibility of postgres < 8.1 with later nextval() calling convention
597         $replacements[0] = '-- ';
598         $replacements[1] = '-- ';
599