root/trunk/wifidog-auth/wifidog/install.php @ 916

Revision 916, 66.7 KB (checked in by max-horvath, 7 years ago)

2006-01-21 Max Horvath <max.horvath@…>

  • Removed compiled PHPdoc documentation
  • moved createDoc.sh to "doc" directory, documentation can be generated on the fly now, in the future we'll be generating a nightly PHPdoc on wifidog.org
  • renamed "ChangeLog" to CHANGELOG, resulting this file being parsed by PHPdoc
  • moved "header.gif" image to its own folder in the images directory
  • touched almost every PHP file in WiFiDog auth server for PHPdoc generating compiling without any warnings
  • Initialized uninitialized variables in Node class
  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1<?php
2
3
4/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
5
6// +-------------------------------------------------------------------+
7// | WiFiDog Authentication Server                                     |
8// | =============================                                     |
9// |                                                                   |
10// | The WiFiDog Authentication Server is part of the WiFiDog captive  |
11// | portal suite.                                                     |
12// +-------------------------------------------------------------------+
13// | PHP version 5 required.                                           |
14// +-------------------------------------------------------------------+
15// | Homepage:     http://www.wifidog.org/                             |
16// | Source Forge: http://sourceforge.net/projects/wifidog/            |
17// +-------------------------------------------------------------------+
18// | This program is free software; you can redistribute it and/or     |
19// | modify it under the terms of the GNU General Public License as    |
20// | published by the Free Software Foundation; either version 2 of    |
21// | the License, or (at your option) any later version.               |
22// |                                                                   |
23// | This program is distributed in the hope that it will be useful,   |
24// | but WITHOUT ANY WARRANTY; without even the implied warranty of    |
25// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     |
26// | GNU General Public License for more details.                      |
27// |                                                                   |
28// | You should have received a copy of the GNU General Public License |
29// | along with this program; if not, contact:                         |
30// |                                                                   |
31// | Free Software Foundation           Voice:  +1-617-542-5942        |
32// | 59 Temple Place - Suite 330        Fax:    +1-617-542-2652        |
33// | Boston, MA  02111-1307,  USA       gnu@gnu.org                    |
34// |                                                                   |
35// +-------------------------------------------------------------------+
36
37/**
38 * WiFiDog Authentication Server installation and configuration script
39 *
40 * @package    WiFiDogAuthServer
41 * @author     Pascal Leclerc <isf@plec.ca>
42 * @copyright  2005-2006 Pascal Leclerc
43 * @version    Subversion $Id$
44 * @link       http://www.wifidog.org/
45 */
46
47/**
48 * Load required files
49 */
50require_once ('include/path_defines_base.php');
51
52empty ($_REQUEST['page']) ? $page = 'Welcome' : $page = $_REQUEST['page']; # The page to be loaded
53empty ($_REQUEST['action']) ? $action = '' : $action = $_REQUEST['action']; # The action to be done (in page)
54empty ($_REQUEST['debug']) ? $debug = 0 : $debug = $_REQUEST['debug']; # Use for MySQL debugging
55empty ($_REQUEST['config']) ? $config = '' : $config = $_REQUEST['config']; # Store data to be saved in config.php
56
57# 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.
58
59# Random password generator
60$password_file = '/tmp/dog_cookie.txt';
61$random_password = null;
62if (!file_exists($password_file)) {
63    srand(date("s"));
64    $possible_charactors = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
65    $password = "";
66    while (strlen($random_password) < 8) {
67        $random_password .= substr($possible_charactors, rand() % (strlen($possible_charactors)), 1);
68    }
69    $fd = fopen($password_file, 'w');
70    fwrite($fd, $random_password);
71    fclose($fd);
72}
73
74# Read password file
75$fd = fopen($password_file, "rb");
76$password = fread($fd, filesize($password_file));
77fclose($fd);
78
79$auth = false;
80
81if ($page != 'Welcome') {
82    if (isset ($_SERVER['PHP_AUTH_PW'])) {
83        #echo "PHP_AUTH_USER=(" . $_SERVER['PHP_AUTH_USER'] . ") PHP_AUTH_PW=(" . $_SERVER['PHP_AUTH_PW'] . ")"; # DEBUG
84        if ($password == $_SERVER['PHP_AUTH_PW'])
85            $auth = true;
86    }
87}
88else
89    $auth = true;
90
91if (!$auth) { # Ask user for the passorwd
92    header('WWW-Authenticate: Basic realm="Private"');
93    header('HTTP/1.0 401 Unauthorized');
94    echo "Authorization Required !";
95    exit;
96}
97# End of Security validation
98
99print<<<EndHTML
100<HTML>
101<HEAD>
102  <TITLE>$page - Wifidog Auth-server configuration</TITLE>
103
104  <SCRIPT type="text/javascript">
105    // This function add new configuration value to the "config" hidden input
106    // On submit, config will be parsed and value saved to config.php file
107    function newConfig(dataAdd) {
108      // TODO : Validate input data
109      if (document.myform.config.value == '') {
110        document.myform.config.value = dataAdd;
111      }
112      else {
113        document.myform.config.value = document.myform.config.value + '|' + dataAdd;
114      }
115      //alert(document.myform.config.value);  // DEBUG
116    }
117  </SCRIPT>
118
119</HEAD>
120<BODY text="black" bgcolor="#CFCFCF">
121
122<style type="text/css">
123<!--
124.button
125{
126  font-size: 12pt;
127  font-weight: bold;
128  color: black;
129  background: #D4D0C8;
130  text-decoration: none;
131  border-top: 1px solid white;
132  border-right: 2px solid gray;
133  border-bottom: 2px solid gray;
134  border-left: 1px solid white;
135  padding: 3px 5px 3px 5px;
136}
137
138td
139{
140  padding: 1px 4px 1px 4px;
141}
142//-->
143</style>
144
145<FORM NAME="myform" METHOD="post">
146<INPUT TYPE="HIDDEN" NAME="page">
147<INPUT TYPE="HIDDEN" NAME="action">
148<INPUT TYPE="HIDDEN" NAME="debug">
149<INPUT TYPE="HIDDEN" NAME="config">
150
151EndHTML;
152
153#print "<PRE>";      # DEBUG
154#print_r($_SERVER);  # DEBUG
155#print_r($_REQUEST); # DEBUG
156#print "</PRE>";     # DEBUG
157#exit();
158
159# Minimal version needed
160$requiredPHPVersion = '5.0.0';
161$requiredMySQLVersion = '0.0.0'; // Todo
162$requiredPostgeSQLVersion = '0.0.0'; // Todo
163
164# Needed files/directories with write access
165$dir_array = array ('tmp', 'tmp/magpie_cache', 'lib/smarty', 'tmp/smarty/templates_c', 'lib/magpie', 'lib/Phlickr', 'config.php');
166
167$smarty_full_url    = 'http://smarty.php.net/do_download.php?download_file=Smarty-2.6.7.tar.gz';
168$magpierss_full_url = 'http://easynews.dl.sourceforge.net/sourceforge/magpierss/magpierss-0.71.1.tar.gz';
169$phlickr_full_url   = 'http://easynews.dl.sourceforge.net/sourceforge/phlickr/Phlickr-0.2.4.tgz';
170
171$neededPackages = array(
172  'smarty'    => array('needed' => 1, 'available' => 0, 'message' => '', 'file' => 'lib/smarty/Smarty.class.php'),
173  'magpierss' => array('needed' => 0, 'available' => 0, 'message' => '', 'file' => 'lib/magpie/rss_fetch.inc'),
174  'phlickr'   => array('needed' => 0, 'available' => 0, 'message' => '', 'file' => 'lib/Phlickr/Photo.php')
175);
176
177$neededExtentions = array(
178  'xml'      => array('needed'    => 0,
179                      'available' => 0,
180                      'message'   => '<B>xml</B> extention is missing',
181                      'note'      => 'Required for RSS support'),
182  'pgsql'    => array('needed'    => 1,
183                      'available' => 0,
184                      'message'   => '<B>Posgresql</B> extention is missing',
185                      'note'      => 'Required to connect to Postgresql database'),
186  'mysql'    => array('needed'    => 0,
187                      'available' => 0,
188                      'message'   => '<B>MySQL</B> extention is missing',
189                      'note'      => 'Required to connect to MySQL database (experimental and not working)'),
190  'dom'      => array('needed'    => 1,
191                      'available' => 0,
192                      'message'   => '<B>DOM</B> extention is missing',
193                      'note'      => 'Required if you want to export the list of HotSpots as a RSS feed'),
194  'gettext'  => array('needed'    => 0,
195                      'available' => 0,
196                      'message'   => 'Gettext is unavailable, the auth-server will work, but you will loose internationalization',
197                      'note'      => 'Internationalization support'),
198  'mbstring' => array('needed'    => 1,
199                      'available' => 0,
200                      'message'   => '<B>mbstring</B> extention is missing',
201                      'note'      => 'Required for core auth-server and RSS support'),
202  'mcrypt'   => array('needed'    => 0,
203                      'available' => 0,
204                      'message'   => '<B>mcrypt</B> extention is missing',
205                      'note'      => 'Required for RADIUS support'),
206  'mhash'    => array('needed'    => 0,
207                      'available' => 0,
208                      'message'   => '<B>mhash</B> extention is missing',
209                      'note'      => 'Required for RADIUS support'),
210  'xmlrpc'   => array('needed'    => 0,
211                      'available' => 0,
212                      'message'   => '<B>xmlrpc</B> extention is missing',
213                      'note'      => 'Required for RADIUS support')
214);
215
216$loadedExtensions = array_flip(get_loaded_extensions()); # Debug : An empty array for $loadedExtensions will show needed dependencies
217
218$neededPEARPackages = array(
219  'radius'      => array('needed' => 0, 'available' => 0, 'command' => "return dl('radius.so');",                'message' => 'Try in command line : pear install radius'),
220  'Auth_RADIUS' => array('needed' => 0, 'available' => 0, 'command' => "return include_once 'Auth/RADIUS.php';", 'message' => 'Try in command line : pear install Auth_RADIUS'),
221  'Crypt_CHAP'  => array('needed' => 0, 'available' => 0, 'command' => "return include_once 'Crypt/CHAP.php';",  'message' => 'Try in command line : pear install Crypt_CHAP (mhash and mcrypt extensions are needed)')
222);
223
224$optionsInfo = array(
225  'SSL_AVAILABLE'                => array('title'   => 'SSL Support',
226                                          'depend'  => 'return 1;',
227                                          'message' => '&nbsp;'),
228  'RSS_SUPPORT'                  => array('title'   => 'RSS Support',
229                                          'depend'  => 'return ($neededExtentions[\'xml\'][\'available\'] && $neededPackages[\'magpierss\'][\'available\']);',
230                                          'message' => 'Missing <B>xml</B> extentions or <B>MagpieRSS</B>'),
231  'PHLICKR_SUPPORT'              => array('title'   => 'Flickr Photostream content support',
232                                          'depend'  => 'return $neededPackages[\'phlickr\'][\'available\'];',
233                                          'message' => '<B>Phlickr</B> library not installed'),
234  'CONF_USE_CRON_FOR_DB_CLEANUP' => array('title'   => 'Use cron for DB cleanup',
235                                          'depend'  => 'return 1;',
236                                          'message' => '&nbsp;'),
237  'XSLT_SUPPORT'                 => array('title'   => 'XSLT Support',
238                                          'depend'  => 'return 1;',
239                                          'message' => '&nbsp;'),
240  'GMAPS_HOTSPOTS_MAP_ENABLED'   => array('title'   => 'Google Maps Support',
241                                          'depend'  => 'return 1;',
242                                          'message' => '&nbsp;')
243);
244
245foreach ($neededExtentions as $key => $value) { # Detect availables extentions
246    if (array_key_exists($key, $loadedExtensions))
247        $neededExtentions[$key]['available'] = 1;
248}
249
250foreach ($neededPEARPackages as $key => $value) { # Detect availables PEAR Packages
251    if (@ eval ($neededPEARPackages[$key]['command']))
252        $neededPEARPackages[$key]['available'] = 1;
253}
254
255foreach ($neededPackages as $key => $value) { # Detect installed libraries (smarty, ...)
256    if (file_exists(WIFIDOG_ABS_FILE_PATH.$neededPackages[$key]['file']))
257        $neededPackages[$key]['available'] = 1;
258}
259
260$CONFIG_FILE = 'config.php';
261$LOCAL_CONFIG_FILE = 'local.config.php';
262
263if (!empty ($config)) # If not empty, save javascript 'config' variable to config.php file
264    saveConfig($config);
265
266### Read Configuration file. Keys and Values => define('FOO', 'BRAK');
267# Use config.php if local.config.php does not exist
268//if(!file_exists(WIFIDOG_ABS_FILE_PATH."$LOCAL_CONFIG_FILE"))
269$contentArray = file(WIFIDOG_ABS_FILE_PATH."$CONFIG_FILE");
270//else
271//  $contentArray = file(WIFIDOG_ABS_FILE_PATH."$LOCAL_CONFIG_FILE");
272
273$configArray = array ();
274
275foreach ($contentArray as $line) {
276    #print "$line<BR>"; # Debug
277    if (preg_match("/^define\((.+)\);/", $line, $matchesArray)) {
278        list ($key, $value) = explode(',', $matchesArray[1]);
279        $pattern = array ("/^'/", "/'$/");
280        $replacement = array ('', '');
281        $key = preg_replace($pattern, $replacement, trim($key));
282        $value = preg_replace($pattern, $replacement, trim($value));
283        $configArray[$key] = $value;
284    }
285}
286
287# Database connections variables
288$CONF_DBMS = $configArray['CONF_DBMS'];
289$CONF_DATABASE_HOST = $configArray['CONF_DATABASE_HOST'];
290$CONF_DATABASE_NAME = $configArray['CONF_DATABASE_NAME'];
291$CONF_DATABASE_USER = $configArray['CONF_DATABASE_USER'];
292$CONF_DATABASE_PASSWORD = $configArray['CONF_DATABASE_PASSWORD'];
293
294//foreach($configArray as $key => $value) { print "K=$key V=$value<BR>"; } exit(); # DEBUG
295
296###################################
297# array (array1(name1, page1), array2(name2, page2), ..., arrayN(nameN, pageN));
298# Todo : Supporter HTTP_REFERER (j'me comprends)
299function navigation($dataArray) {
300    $SERVER = $_SERVER['HTTP_HOST'];
301    $SCRIPT = $_SERVER['SCRIPT_NAME'];
302    print "\n<P>";
303    foreach ($dataArray as $num => $navArray) {
304        $title = $navArray['title'];
305        $page = $navArray['page'];
306        empty ($navArray['action']) ? $action = '' : $action = $navArray['action'];
307        print<<<EndHTML
308<A HREF="#" ONCLICK="document.myform.page.value = '$page'; document.myform.action.value = '$action'; document.myform.submit();" CLASS="button">$title</A>
309
310EndHTML;
311        if (array_key_exists($num +1, $dataArray))
312            print "&nbsp;-&nbsp;";
313    }
314    print "</P>\n";
315}
316
317###################################
318#
319function refreshButton() {
320    print<<<EndHTML
321
322<P><A HREF="#" ONCLICK="javascript: window.location.reload(true);" CLASS="button">Refresh</A></P>
323EndHTML;
324}
325
326###################################
327#
328/*function debugButton() {
329  print <<<EndHTML
330<P><INPUT TYPE="button" VALUE="Debug" ONCLICK="javascript: window.location.reload(true);"></P>
331EndHTML;
332} */
333
334###################################
335# In development
336/*function installPackage($pkg_name, $full_url, $copy) {
337    print "<H1>$pkg_name installation</H1>\n";
338    chdir(WIFIDOG_ABS_FILE_PATH."tmp");
339    list($url, $filename) = split ("=", $full_url);
340
341    print "Download source code ($filename) : ";
342    if (!file_exists($filename))
343      exec("wget \"$url\"", $output, $return);
344    if (!file_exists($filename)) // wget success if file exists
345      exec("wget \"$full_url\" 2>&1", $output_array, $return);
346    if (!file_exists($filename)) {
347      print "<B STYLE=\"color:red\">Error</B><P>Current working directory : <B>$basepath/tmp/smarty</B>";
348      $output = implode("\n", $output_array);
349      print "<PRE><B>wget \"$full_url\"</B>\n$output</PRE>";
350      exit();
351    } else {
352      print "OK<BR>";
353    }
354
355    print "Uncompressing : ";
356    $dirname = array_shift(split(".tar.gz", $filename));
357
358    if (!file_exists($dirname))
359      exec("tar -xzf $dirname.tar.gz &>/tmp/tar.output", $output, $return);
360    print "OK<BR>";
361
362    exec("pwd", $output, $return);
363    print "Copying : ";
364    if (!file_exists('../../lib/smarty/Smarty.class.php'));
365      exec("cp -r $dirname/libs/* ../../lib/smarty &>/tmp/cp.output", $output, $return);
366      exec("cp -r $dirname/libs/* ../../lib/smarty &>/tmp/cp.output", $output, $return);
367      $copy
368    print "OK<BR>";
369}*/
370
371###################################
372#
373function saveConfig($data) {
374    print "<!-- saveConfig DATA=($data) -->\n"; # DEBUG
375
376    global $CONFIG_FILE;
377
378    $contentArray = file(WIFIDOG_ABS_FILE_PATH."$CONFIG_FILE");
379    $fd = fopen(WIFIDOG_ABS_FILE_PATH."$CONFIG_FILE", 'w');
380
381    $defineArrayToken = array ();
382    $defineArrayToken = explode('|', $data);
383
384    foreach ($defineArrayToken as $nameValue) {
385        list ($name, $value) = explode('=', $nameValue);
386        $defineArray[$name] = $value; # New define value ($name and value)
387        #print "K=$name V=$value<BR>"; # DEBUG
388    }
389
390    foreach ($contentArray as $line) {
391        #print "L=$line<BR>\n";
392        if (preg_match("/^define\((.+)\);/", $line, $matchesArray)) {
393            list ($key, $value) = explode(',', $matchesArray[1]);
394            $pattern = array ("/^'/", "/'$/");
395            $replacement = array ('', '');
396            $key = preg_replace($pattern, $replacement, trim($key));
397            //$value = preg_replace($pattern, $replacement, trim($value));
398
399            if (array_key_exists($key, $defineArray)) { // A new value is defined
400                #print "$key EXISTS<BR>";
401                #print "define => (" . $defineArray[$key] . ")<BR>";
402                $pattern = array ("/^\\\'/", "/\\\'$/");
403                $replacement = array ("'", "'");
404                $value = preg_replace($pattern, $replacement, trim($defineArray[$key]));
405                #print "(define('$key', $value);)<BR>";
406                fwrite($fd, "define('$key', $value);\n"); # Write the new define($name, $value)
407            }
408            else { // The key does not exist (no new value to be saved)
409                fwrite($fd, $line); # Write the same line in config.php
410            }
411        }
412        else {
413            fwrite($fd, $line); # Write the line (not a define line). Ex: Commented text
414        }
415    }
416}
417
418###################################
419# MAIN
420switch ($page) {
421    case 'version' :
422        /*  TODO : Valider qu'au moins une extention de DB est existante (pgsql, mysql, etc)
423                   Definir les versions minimales de Posgres et MySQL */
424
425        print "<H1>Version validation</H1>";
426        print "<TABLE BORDER=\"1\">";
427
428        $phpVersion = phpversion();
429        $okMsg = '<TD ALIGN="CENTER" STYLE="background:lime;">OK</TD>';
430        $errorMsg = '<TD ALIGN="CENTER" STYLE="background:red;">ERROR</TD>';
431        $warningMsg = '<TD ALIGN="CENTER" STYLE="background:yellow;">Warning</TD>';
432        $error = 0;
433
434        print "<TR><TD>PHP</TD>";
435        if (version_compare($phpVersion, $requiredPHPVersion, ">=")) {
436            print "$okMsg<TD>$phpVersion</TD>"; // Version 5.0.0 or later
437        }
438        else {
439            print "$errorMsg<TD>Version $requiredPHPVersion needed</TD>"; // Version < 5.0.0
440            $error = 1;
441        }
442        print "</TR></TABLE><BR>";
443
444        print "<TABLE BORDER=\"1\"><TR><TD><B>Extention</B></TD><TD><B>Status</B></TD><TD><B>Note</B></TD><TD><B>Message</B></TD></TR>";
445        foreach ($neededExtentions as $key => $value) {
446            print "<TR><TD><A HREF=\"http://www.php.net/$key\">$key</A></TD>";
447            $note = $neededExtentions[$key]['note'];
448            if ($neededExtentions[$key]['available']) {
449                print "$okMsg<TD>$note</TD><TD>&nbsp;</TD></TR>";
450            }
451            else {
452                $message = $neededExtentions[$key]['message'];
453                if ($neededExtentions[$key]['needed'] == 1) {
454                    print "$errorMsg<TD>$note</TD><TD>$message</TD></TR>";
455                    $error = 1;
456                }
457                else {
458                    print "$warningMsg<TD>$note</TD><TD>$message</TD></TR>";
459                }
460            }
461        }
462        print "</TABLE><BR>";
463
464        /************************************
465        * PEAR Components
466        *************************************/
467        print "<TABLE BORDER=\"1\"><TR><TD COLSPAN=\"3\"><CENTER><B>PEAR</B></CENTER></TD></TR>";
468        print "<TR><TD><B>Component</B></TD><TD><B>Status</B></TD><TD><B>Note</B></TD></TR>";
469
470        foreach ($neededPEARPackages as $key => $value) {
471            $return = 0;
472            print "<TR><TD><A HREF=\"http://pear.php.net/package/$key\">$key</A></TD>";
473            if ($neededPEARPackages[$key]['available']) {
474                print "$okMsg<TD>&nbsp;</TD></TR>";
475            }
476            else {
477                $message = $neededPEARPackages[$key]['message'];
478                if ($neededPEARPackages[$key]['needed'] == 1) {
479                    print "$errorMsg<TD>$message</TD></TR>";
480                    $error = 1;
481                }
482                else {
483                    print "$warningMsg<TD>$message</TD></TR>";
484                }
485            }
486        }
487        print "</TABLE><BR>";
488
489        /************************************
490        * GD with PNG and JPEG support (will be needed by stats and graphics)
491        *************************************/
492        /*  $gdInfo = @gd_info();
493            print "<TABLE BORDER=\"1\"><TR><TD><PRE>";
494            print_r($gdInfo);
495            print "</PRE></TD></TR></TABLE>";
496        */
497
498        #    if (!($neededExtentions['pgsql']['available'] && $neededExtentions['mysql']['available']))
499        #      print "At least one DB extentions is nedded<BR>";
500
501        //TODO: PostgreSQL and MySQL version are not validated";
502        print "We recommend you use PostgreSQL 8.0 or newer";
503
504        refreshButton();
505        if ($error != 1) {
506            navigation(array (array ("title" => "Next", "page" => "permission")));
507        }
508
509        break;
510        ###################################
511    case 'permission' :
512        print "<H1>Permissions</H1>";
513
514        $process_info_user_id = posix_getpwuid(posix_getuid());
515        $process_info_group_id = posix_getgrgid(posix_getegid());
516        $process_username = $process_info_user_id['name'];
517        $process_group = $process_info_group_id['name'];
518        $cmd_mkdir = '';
519        $cmd_chown = '';
520        $error = 0;
521
522        print "<P><B>Installation directory</B>: ".WIFIDOG_ABS_FILE_PATH."</P>";
523        print "<P><B>HTTP daemon UNIX username/group</B>: $process_username/$process_group</P>";
524        #    print "<P><B>HTTPD group</B>: $process_group<BR</P>";
525        print "<P><TABLE BORDER=\"1\"><TR><TD><B>Directory</B></TD></TD><TD><B>Owner</B></TD><TD><B>Writable</B></TD></TR>\n";
526
527        foreach ($dir_array as $dir) {
528            print "<TR><TD>$dir</TD>";
529            if (!file_exists(WIFIDOG_ABS_FILE_PATH."$dir")) {
530                print "<TD COLSPAN=\"2\" STYLE=\"text-align:center;\">Missing</TD></TR>\n";
531                $cmd_mkdir .= WIFIDOG_ABS_FILE_PATH."$dir ";
532                $cmd_chown .= WIFIDOG_ABS_FILE_PATH."$dir ";
533                $error = 1;
534                continue;
535            }
536
537            $dir_info = posix_getpwuid(fileowner(WIFIDOG_ABS_FILE_PATH."$dir"));
538            $dir_owner_username = $dir_info['name'];
539            print "<TD>$dir_owner_username</TD>";
540
541            if (is_writable(WIFIDOG_ABS_FILE_PATH."$dir")) {
542                print "<TD>YES</TD>";
543            }
544            else {
545                print "<TD>NO</TD>";
546                $cmd_chown .= WIFIDOG_ABS_FILE_PATH."$dir ";
547                $error = 1;
548            }
549            print "</TR>\n";
550        }
551        print "</TABLE>\n";
552
553        if ($error != 1) {
554            print "<P><B>Note:</B> Please validate that 'Installation directory' value is the right one. If this value is wrong, the PATH de automatic detection will not work as expected";
555            navigation(array (array ("title" => "Back", "page" => "version"), array ("title" => "Next", "page" => "smarty")));
556        }
557        else {
558            refreshButton();
559            print "<P>You need to allow UNIX user <B>$process_username</B> to write to these directories (mkdir, chown or chmod)</P>";
560            if (!empty ($cmd_mkdir))
561                print "<P><B>For instance</B> : mkdir $cmd_mkdir";
562            if (!empty ($cmd_chown))
563                print "<P><B>For instance</B> : chown -R $process_username:$process_group $cmd_chown";
564            print "<P>After permissions modification done, hit the REFRESH button to see the NEXT button and continue with the installation";
565        }
566        break;
567        ###################################
568    case 'smarty' : // Download, uncompress and install Smarty
569        print<<< EndHTML
570    <H1>Smarty template engine installation</H1>
571    <P><A HREF="http://smarty.php.net/">Smarty</A> is Template Engine. WifiDog requires you install it before you continue.</P>
572EndHTML;
573        if ($neededPackages['smarty']['available']) {
574            print "Already installed !<br/>";
575        }
576        else {
577            chdir(WIFIDOG_ABS_FILE_PATH."tmp");
578            list ($url, $filename) = split("=", $smarty_full_url);
579
580            print "Download source code ($filename) : ";
581            if (!file_exists($filename))
582                exec("wget \"$smarty_full_url\" 2>&1", $output, $return);
583            if (!file_exists($filename)) {
584                print "<B STYLE=\"color:red\">Error</B><P>Current working directory : <B>$basepath/tmp/smarty</B>";
585                $output = implode("\n", $output);
586                print "<PRE><B>wget \"$smarty_full_url\"</B>\n$output</PRE>";
587                exit ();
588            }
589            else {
590                print "OK<BR>";
591            }
592
593            print "Uncompressing : ";
594            $dir_array = split(".tar.gz", $filename);
595            $dirname = array_shift($dir_array);
596
597            if (!file_exists($dirname))
598                exec("tar -xzf $dirname.tar.gz &>/tmp/tar.output", $output, $return);
599            print "OK<BR>";
600
601            exec("pwd", $output, $return);
602            print "Copying : ";
603            if (!file_exists(WIFIDOG_ABS_FILE_PATH."lib/smarty"));
604            exec("cp -r $dirname/libs/* ".WIFIDOG_ABS_FILE_PATH."/lib/smarty &>/tmp/cp.output", $output, $return); # TODO : Utiliser SMARTY_REL_PATH
605            print "OK<BR>";
606
607            refreshButton();
608        }
609        navigation(array (array ("title" => "Back", "page" => "permission"), array ("title" => "Next", "page" => "magpierss")));
610        break;
611        ###################################
612    case 'magpierss' : // Download, uncompress and install MagpieRSS
613        print "<H1>MagpieRSS installation</H1>\n";
614
615        if ($neededPackages['magpierss']['available']) {
616            print "Already installed !<BR>";
617            navigation(array (array ("title" => "Back", "page" => "smarty"), array ("title" => "Next", "page" => "phlickr")));
618        }
619        elseif ($action == 'install') {
620            chdir(WIFIDOG_ABS_FILE_PATH."tmp");
621            $filename_array = preg_split("/\//", $magpierss_full_url);
622            $filename = array_pop($filename_array);
623
624            print "Download source code ($filename) : ";
625            if (!file_exists($filename))
626                exec("wget \"$magpierss_full_url\" 2>&1", $output, $return);
627            if (!file_exists($filename)) {
628                print "<B STYLE=\"color:red\">Error</B><P>Current working directory : <B>$basepath/tmp/smarty</B>";
629                $output = implode("\n", $output);
630                print "<PRE><B>wget \"$magpierss_full_url\"</B>\n$output</PRE>";
631                exit ();
632            }
633            else {
634                print "OK<BR>";
635            }
636
637            print "Uncompressing : ";
638            $dir_array = split(".tar.gz", $filename);
639            $dirname = array_shift($dir_array);
640            if (!file_exists($dirname))
641                exec("tar -xzf $dirname.tar.gz &>/tmp/tar.output", $output, $return);
642            print "OK<BR>";
643
644            print "Copying : ";
645            exec("cp -r $dirname/* ../lib/magpie &>/tmp/cp.output", $output, $return); # TODO : Utiliser MAGPIE_REL_PATH
646            print "OK<BR>";
647
648            refreshButton();
649            navigation(array (array ("title" => "Back", "page" => "smarty"), array ("title" => "Next", "page" => "phlickr")));
650        }
651        else {
652            print<<< EndHTML
653<P><A HREF="http://magpierss.sourceforge.net/">MagpieRSS</A> provides an XML-based (expat) RSS parser in PHP. MagpieRSS is needed by Wifidog for RSS feeds. It's is recommended to install MagpieRSS, if you don't, RSS feeds options will be disable.
654
655<P>Do you want to install MagpieRSS ?
656EndHTML;
657            navigation(array (array ("title" => "Back", "page" => "smarty"), array ("title" => "Install", "page" => "magpierss", "action" => "install"), array ("title" => "Next", "page" => "phlickr")));
658        }
659        break;
660        ###################################
661    case 'phlickr' : // Download, uncompress and install phlickr library
662        print "<H1>Phlickr installation</H1>\n";
663
664        if ($neededPackages['phlickr']['available']) {
665            print "Already installed !<BR>";
666            navigation(array (array ("title" => "Back", "page" => "magpierss"), array ("title" => "Next", "page" => "database")));
667        }
668        elseif ($action == 'install') {
669            chdir(WIFIDOG_ABS_FILE_PATH."tmp");
670            $filename_array = preg_split("/\//", $phlickr_full_url);
671            $filename = array_pop($filename_array);
672
673            print "Download source code ($filename) : ";
674            if (!file_exists($filename))
675                exec("wget \"$phlickr_full_url\" 2>&1", $output, $return);
676            if (!file_exists($filename)) { # Error occured, print output of wget
677                print "<B STYLE=\"color:red\">Error</B><P>Current working directory : <B>$basepath/tmp/smarty</B>";
678                $output = implode("\n", $output);
679                print "<PRE><B>wget \"$phlickr_full_url\"</B>\n$output</PRE>";
680                exit ();
681            }
682            else {
683                print "OK<BR>";
684            }
685
686            print "Uncompressing : ";
687            $dirname_array = split(".tgz", $filename);
688            $dirname = array_shift($dirname_array);
689            if (!file_exists($dirname))
690                exec("tar -xzf $dirname.tgz &>/tmp/tar.output", $output, $return);
691            print "OK<BR>";
692
693            print "Copying : ";
694            if (!file_exists('../../lib/Phlickr/Photo.php'))
695                exec("cp -r $dirname/* ../lib/Phlickr &>/tmp/cp.output", $output, $return); # TODO : Utiliser PHLICKR_REL_PATH
696            print "OK<BR>";
697
698            refreshButton();
699            // Skipping jpgraph install
700            navigation(array (array ("title" => "Back", "page" => "magpierss"), array ("title" => "Next", "page" => "database")));
701        }
702        else {
703            print<<< EndHTML
704<P><A HREF="http://phlickr.sourceforge.net/">Phlickr</A> is an Open Source PHP 5 interface to the Flickr API. <A HREF="http://flickr.com/">Flickr</A> is a digital photo sharing website. Phlickr allows WifiDog to display pictures from Flickr on its portal pages. Phlickr is thus an optional package..
705
706<P>Do you want to install Phlickr ?
707EndHTML;
708            navigation(array (array ("title" => "Back", "page" => "magpierss"), array ("title" => "Install", "page" => "phlickr", "action" => "install"), array ("title" => "Next", "page" => "database")));
709        }
710        break;
711        ###################################
712    case 'jpgraph' : // Download, uncompress and install JpGraph library
713        print "<H1>JpGraph installation</H1>\n";
714
715        if ($neededPackages['jpgraph']['available']) {
716            print "Already installed !<BR>";
717            navigation(array (array ("title" => "Back", "page" => "phlickr"), array ("title" => "Next", "page" => "database")));
718        }
719        elseif ($action == 'install') {
720            chdir(WIFIDOG_ABS_FILE_PATH."tmp");
721            $filename = array_pop(preg_split("/\//", $jpgraph_full_url));
722
723            print "Download source code ($filename) : ";
724            if (!file_exists($filename))
725                exec("wget \"$jpgraph_full_url\" 2>&1", $output, $return);
726            if (!file_exists($filename)) { # Error occured, print output of wget
727                print "<B STYLE=\"color:red\">Error</B><P>Current working directory : <B>$basepath/tmp</B>";
728                $output = implode("\n", $output);
729                print "<PRE><B>wget \"$jpgraph_full_url\"</B>\n$output</PRE>";
730                exit ();
731            }
732            else {
733                print "OK<BR>";
734            }
735
736            print "Uncompressing : ";
737            $dirname = array_shift(split(".tar.gz", $filename));
738            if (!file_exists($dirname))
739                exec("tar -xzf $dirname.tar.gz &>/tmp/tar.output", $output, $return);
740            print "OK<BR>";
741
742            print "Copying : ";
743            if (!file_exists('../../lib/jpgraph/jpgraph.php'))
744                exec("cp $dirname/src/* ../lib/jpgraph &>/tmp/cp.output", $output, $return); # TODO : Utiliser JPGRAPH_REL_PATH
745
746            print "OK<BR>";
747
748            refreshButton();
749            navigation(array (array ("title" => "Back", "page" => "phlickr"), array ("title" => "Next", "page" => "database")));
750        }
751        else {
752            print<<< EndHTML
753<P><A HREF="http://www.aditus.nu/jpgraph/">JpGraph</A> is a Object-Oriented Graph creating library for PHP.
754JpGraph is not currently use by Wifidog (will be use for statistique graph in a later version). You can skip this installation if your not a developper.
755
756<P>Do you want to install JpGraph ?
757EndHTML;
758            navigation(array (array ("title" => "Back", "page" => "phlickr"), array ("title" => "Install", "page" => "jpgraph", "action" => "install"), array ("title" => "Next", "page" => "database")));
759        }
760        break;
761        ###################################
762    case 'database' :
763        ### TODO : Valider en javascript que les champs soumit ne sont pas vide
764        #          Pouvoir choisir le port de la DB ???
765        print<<< EndHTML
766<H1>Database access configuration</H1>
767<BR>
768<TABLE border="1">
769  <TR><TD>DB</TD><TD><SELECT name="CONF_DBMS">
770
771EndHTML;
772
773        foreach ($configArray as $key => $value) { # In config.php, find all DBMS_* define
774            if (preg_match("/^(DBMS_)(.*)/", $key, $matchesArray)) {
775                $dbname_lower = strtolower($matchesArray[2]);
776                if ($dbname_lower == 'postgres') # config.php use postgres and PHP use pgsql
777                    $dbname_lower = 'pgsql';
778                if ($neededExtentions[$dbname_lower]['available'] == 0) # Validate dependencie
779                    continue;
780                if ($CONF_DBMS == $key)
781                    print "    <OPTION value=\"$key\" SELECTED>".$matchesArray[2]."</OPTION>\n";
782                else
783                    print "    <OPTION value=\"$key\">".$matchesArray[2]."</OPTION>\n";
784            }
785        }
786
787        print<<< EndHTML
788  </TD></TR>
789  <TR><TD>Host</TD><TD><INPUT type="text" name="CONF_DATABASE_HOST" value="$CONF_DATABASE_HOST"></TD></TR>
790  <TR><TD>DB Name</TD><TD><INPUT type="text" name="CONF_DATABASE_NAME" value="$CONF_DATABASE_NAME"></TD></TR>
791  <TR><TD>Username</TD><TD><INPUT type="text" name="CONF_DATABASE_USER" value="$CONF_DATABASE_USER"></TD></TR>
792  <TR><TD>Password</TD><TD><INPUT type="text" name="CONF_DATABASE_PASSWORD" value="$CONF_DATABASE_PASSWORD"></TD></TR>
793</TABLE>
794
795<P>By clicking Next, your configuration will be automaticaly saved
796
797<script type="text/javascript">
798  function submitDatabaseValue() {
799    newConfig("CONF_DBMS=" + document.myform.CONF_DBMS.value);
800    newConfig("CONF_DATABASE_HOST='" + document.myform.CONF_DATABASE_HOST.value + "'");
801    newConfig("CONF_DATABASE_NAME='" + document.myform.CONF_DATABASE_NAME.value + "'");
802    newConfig("CONF_DATABASE_USER='" + document.myform.CONF_DATABASE_USER.value + "'");
803    newConfig("CONF_DATABASE_PASSWORD='" + document.myform.CONF_DATABASE_PASSWORD.value + "'");
804  }
805</script>
806
807<P><B>Note</B> : MySQL support is currently broken</P>
808
809EndHTML;
810
811        navigation(array (array ("title" => "Back", "page" => "magpierss"))); #, array("title" => "Next", "page" => "testdatabase")));
812        print<<< EndHTML
813<P><A HREF="#" ONCLICK="javascript: document.myform.page.value='testdatabase'; submitDatabaseValue(); document.myform.submit();" CLASS="button">Next</A></P>
814
815EndHTML;
816
817        break;
818        ###################################
819    case 'testdatabase' :
820        print "<H1>Database connection</H1>";
821        /* TODO : Tester la version minimale requise de MySQL et Postgresql
822                  Tester si MySQL supporte InnoDB                           */
823
824        switch ($CONF_DBMS) {
825            case 'DBMS_POSTGRES' :
826                print "<UL><LI>Postgresql database connection : ";
827
828                $conn_string = "host=$CONF_DATABASE_HOST dbname=$CONF_DATABASE_NAME user=$CONF_DATABASE_USER password=$CONF_DATABASE_PASSWORD";
829                $ptr_connexion = pg_connect($conn_string) or die(); # or die("Couldn't Connect ==".pg_last_error()."==<BR>");
830
831                #if ($ptr_connexion == TRUE) {
832                print "Success<BR>";
833                #}
834                #        } else {
835                #          print "Unable to connect to database on $CONF_DATABASE_HOST<BR>The database must be online to continue.<BR>Please go back and retry with correct values";
836                #          navigation(array(array("title" => "Back", "page" => "database")));
837                #        }
838
839                $postgresql_info = pg_version();
840                #        $postgresql_info['server'];
841                #        if ($postgresql_info['server'] > $requiredPostgeSQLVersion) { Todo : Do something }
842
843                print "</UL>";
844                refreshButton();
845                navigation(array (array ("title" => "Back", "page" => "database"), array ("title" => "Next", "page" => "dbinit")));
846                break;
847                ###################################
848            case 'DBMS_MYSQL' :
849                $ptr_connexion = @ mysql_connect($CONF_DATABASE_HOST, $CONF_DATABASE_USER, $CONF_DATABASE_PASSWORD);
850                print "<UL>\n";
851
852                if ($ptr_connexion == TRUE) {
853                    print "<LI>MySQL database connection : Success";
854
855                    $mysql_server_version = mysql_get_server_info();
856                    print ("<LI>MySQL server version: $mysql_server_version");
857
858                    #if ($mysql_server_version > $requiredMySQLVersion) { Todo : Do something }
859
860                    #printf("<LI>MySQL host info: %s\n", mysql_get_host_info());
861
862                    print "<LI>Select DB $CONF_DATABASE_NAME : ";
863                    $select_db = mysql_select_db($CONF_DATABASE_NAME);
864
865                    if ($select_db == TRUE) {
866                        print "Success</UL>";
867                        navigation(array (array ("title" => "Back", "page" => "database"), array ("title" => "Next", "page" => "dbinit")));
868                    }
869                    else {
870                        print "</UL>ERROR (Unable to select the database)<BR>";
871                        refreshButton();
872                        navigation(array (array ("title" => "Back", "page" => "database")));
873                    }
874                }
875                else {
876                    print "Unable to connect to database on <B>$CONF_DATABASE_HOST</B><BR>The database must be online to continue.<P>Please go back and retry with correct values";
877                    refreshButton();
878                    navigation(array (array ("title" => "Back", "page" => "database")));
879                }
880                break;
881            default :
882                print<<<EndHTML
883          The CONF_DBMS value <B>$CONF_DBMS</B> is not currently suported by this install script.
884EndHTML;
885                navigation(array (array ("title" => "Back", "page" => "database")));
886        }
887        break;
888        ###################################
889    case 'dbinit' :
890        print "<H1>Database initialisation</H1>";
891
892        # SQL are executed with PHP, some lignes need to be commented
893        $file_db_version = 'UNKNOW';
894        $patterns[0] = '/CREATE DATABASE wifidog/';
895        $patterns[1] = '/\\\connect/';
896        $patterns[2] = '/COMMENT/';
897        $patterns[3] = '/SET default_tablespace/';
898        $patterns[4] = '/SET default_with_oids/';
899        $replacements[0] = '-- ';
900        $replacements[1] = '-- ';
901        $replacements[2] = '-- ';
902        $replacements[3] = '-- ';
903        $replacements[4] = '-- ';
904
905        $content_schema_array = file(WIFIDOG_ABS_FILE_PATH."../sql/wifidog-postgres-schema.sql") or die("<B>Error</B>: Can not open $basepath/../sql/wifidog-postgres-schema.sql"); # Read SQL schema file
906        $content_schema = implode("", $content_schema_array);
907        $content_data_array = file(WIFIDOG_ABS_FILE_PATH."../sql/wifidog-postgres-initial-data.sql"); # Read SQL initial data file
908        $content_data = implode("", $content_data_array);
909
910        $db_schema_version = ''; # Schema version query from database
911        $file_schema_version = ''; # Schema version from define(REQUIRED_SCHEMA_VERSION) in schema_validate.php
912
913        switch ($CONF_DBMS) {
914            case 'DBMS_POSTGRES' :
915                $conn_string = "host=$CONF_DATABASE_HOST dbname=$CONF_DATABASE_NAME user=$CONF_DATABASE_USER password=$CONF_DATABASE_PASSWORD";
916                $connection = pg_connect($conn_string) or die(); # or die("Couldn't Connect ==".pg_last_error()."==<BR>");
917
918                if (preg_match("/\('schema_version', '(\d+)'\);/", $content_data, $matchesArray)) # Get schema_version from initial data file
919                    $file_db_version = $matchesArray[1];
920
921                $contentArray = file(WIFIDOG_ABS_FILE_PATH."include/schema_validate.php");
922                foreach ($contentArray as $line) {
923                    #print "$line<BR>"; # Debug
924                    if (preg_match("/^define\('REQUIRED_SCHEMA_VERSION', (\d+)\);/", $line, $matchesArray)) {
925                        #print "REQUIRED_SCHEMA_VERSION = " . $matchesArray[1] . "<BR>";
926                        $file_schema_version = $matchesArray[1];
927                    }
928                }
929
930                # Get current database schema version (if defined)
931                $sql = "SELECT * FROM schema_info WHERE tag='schema_version'";
932                if ($result = @ pg_query($connection, $sql)) { # The @ remove warning display
933                    $result_array = pg_fetch_all($result);
934                    $db_shema_version = $result_array[0]['value'];
935
936                    print "<P>On <B>$CONF_DATABASE_HOST</B>, Database <B>$CONF_DATABASE_NAME</B> exists and is ";
937                    if ($db_shema_version == $file_schema_version) {
938                        print "up to date (shema version <B>$db_shema_version</B>).";
939                        navigation(array (array ("title" => "Back", "page" => "database"), array ("title" => "Next", "page" => "options")));
940                    }
941                    elseif ($db_shema_version < $file_schema_version) {
942                        print "at schema version <B>$db_shema_version</B>. The required schema version is <B>$file_schema_version</B><P>Please upgrade the database";
943                        navigation(array (array ("title" => "Back", "page" => "database"), array ("title" => "Upgrade", "page" => "schema_validate"), array ("title" => "Next", "page" => "options")));
944                    }
945                    else {
946                        print "Error : Unexpected result";
947                    }
948                    exit ();
949                }
950
951                print "<UL><LI>Creating wifidog database schema : ";
952                $content_schema = preg_replace($patterns, $replacements, $content_schema); # Comment bad SQL lines
953
954                $result = pg_query($connection, $content_schema) or die("<B>".pg_last_error()."</B> <=<BR>");
955                print "OK";
956
957                print "<LI>Creating wifidog database initial data : ";
958                $content_data = preg_replace($patterns, $replacements, $content_data); # Comment bad SQL lines
959
960                $result = pg_query($connection, $content_data) or die("<B>".pg_last_error()."</B> <=<BR>");
961                print "OK</UL>";
962
963                navigation(array (array ("title" => "Back", "page" => "database"), array ("title" => "Next", "page" => "options")));
964                break;
965                ###################################
966            case 'DBMS_MYSQL' :
967                print "MYSQL ... (Not working)<BR>\n";
968                $ptr_connexion = @ mysql_connect($CONF_DATABASE_HOST, $CONF_DATABASE_USER, $CONF_DATABASE_PASSWORD);
969                $select_db = mysql_select_db($CONF_DATABASE_NAME);
970
971                $previous_line = ''; # Used to remove "," on the line before CONSTRAINT removed line.
972
973                if ($debug)
974                    print "<PRE>";
975
976                $inTable = 0;
977                foreach ($content_schema_array as $lineNum => $line) {
978                    #          if (preg_match("/^--/", $line)) continue; # Remove commented lines
979                    #          if (preg_match("/^$/", $line))  continue; # Remove empty lines
980                    if ($debug)
981                        print "<B>ORI</B> $line";
982                    if (preg_match("/^CREATE TABLE/", $line, $matchesArray))
983                        $inTable = 1;
984                    if ($inTable) {
985                        if ($inTable && preg_match("/^\);$/", $line, $matchesArray)) {
986                            #print "<B STYLE=\"color:#FF0000;\">OUT</B>\n";
987
988                            # PG    => );
989                            # MySQL => ) TYPE=InnoDB;
990                            $line = preg_replace("/^\);$/", ") TYPE=InnoDB;", $line);
991                            $inTable = 0;
992                        }
993                        else {
994                            #print "<B>IN  \n</B>"; # The line is in CREATE TABLE
995
996                            if (preg_match("/\s*CONSTRAINT.*\n$/", $line)) { # Remove CONSTRAINT. TODO : support constraint
997                                $line = preg_replace("/\s*CONSTRAINT.*\n$/", "", $line);
998                                $previous_line = preg_replace("/,$/", "", $previous_line);
999                                #print "<B STYLE=\"color:#FF0000;\">ICI : L=$line PL=$previous_line</B>";
1000                            }
1001                            # Mettre TYPE=InnoDB uniquement pour table avec CONSTRAINT ???
1002
1003                            # PG    =>  token_status character varying(10) NOT NULL
1004                            # MySQL => `token_status` character varying(10) NOT NULL
1005                            $line = preg_replace("/^(\s+)(\w+)/", "\${1}`\${2}`", $line);
1006
1007                            $line = preg_replace("/DEFAULT ('.*')::character varying NOT NULL/", "NOT NULL default \${1}", $line);
1008
1009                            $line = preg_replace("/text DEFAULT [\w':]+/", "text DEFAULT ''", $line); # MySQL does not support "text" default value
1010                            #??? Erreur : 1101 - BLOB/TEXT column 'venue_type' can't have a default value. Solution : Changer 'text' pour varchar ???
1011
1012                            # PG    =>  token_status character varying(10) NOT NULL
1013                            # MySQL =>  token_status VARCHAR(10) NOT NULL
1014                            $line = preg_replace("/character varying\(/", "VARCHAR(", $line);
1015
1016                            $line = preg_replace("/::character varying/", "", $line); # Remove string "::character varying"
1017
1018                            # PG    => account_status integer,
1019                            # MySQL => account_status int,
1020                            $line = preg_replace("/integer/", "int", $line);
1021
1022                            # TODO : Comprendre : Le timestamp de postgres est sous le format '2005-04-07 16:33:49.917127'
1023                            #                     datetime de MySQL est '0000-00-00 00:00:00'
1024                            $line = preg_replace("/timestamp without time zone/", "datetime", $line);
1025
1026                            $line = preg_replace("/now\(\)/", "'NOW()'", $line);
1027
1028                            #$line = preg_replace("/::text/", "", $line);
1029
1030                            $line = preg_replace("/false/", "0", $line); # Change "false" strings for 0 (zero)
1031                            $line = preg_replace("/true/", "1", $line); # Change "true" strings for 1 (one)
1032                            $line = preg_replace("/WITHOUT OIDS/", "", $line); # Remove "WITHOUT OIDS"
1033
1034                            # PG    => binary_data bytea,
1035                            # MySQL => binary_data MEDIUMBLOB
1036                            # Uploading, Saving and Downloading Binary Data in a MySQL Database http://www.onlamp.com/lpt/a/370
1037                            $line = preg_replace("/bytea/", "MEDIUMBLOB", $line); # maximum 16777215 (2^24 - 1) bytes
1038                        } ### End of else. Regex in CREATE TABLE {};
1039                    } ### End of if ($inTable).
1040
1041                    # PG    => CREATE INDEX idx_token ON connections USING btree (token);
1042                    # MySQL => CREATE INDEX idx_token USING btree ON connections (token);
1043                    $line = preg_replace("/(ON \w+) USING btree/", "USING btree \${1}", $line);
1044
1045                    # SQL-query : CREATE UNIQUE INDEX idx_unique_username_and_account_origin USING btree ON users(username,account_origin)
1046                    # MySQL said: #1170 - BLOB/TEXT column 'username' used in key specification without a key length
1047                    # Solution : http://www.dbforums.com/t1100992.html
1048                    $line = preg_replace("/CREATE UNIQUE INDEX idx_unique_username_and_account_origin USING btree ON users \(username, account_origin\);/", "CREATE UNIQUE INDEX idx_unique_username_and_account_origin USING btree ON users (username(100), account_origin(100));", $line);
1049
1050                    $line = preg_replace("/CREATE INDEX idx_content_group_element_content_group_id USING btree ON content_group_element \(content_group_id\);/", "CREATE INDEX idx_content_group_element_content_group_id USING btree ON content_group_element (content_group_id(100));", $line);
1051
1052                    if ($debug)
1053                        print "NEW $line";
1054                    $content_mysql .= $previous_line;
1055                    $previous_line = $line;
1056                } ### End of foreach ($content_schema_array as $lineNum => $line)
1057
1058                $content_mysql .= $previous_line; # TODO: verif save the last line ?
1059                if ($debug)
1060                    print "<B STYLE=\"color:#FF0000;\">####################################################################</B>\n\n$content_mysql"; # Debug
1061                if ($debug)
1062                    print "</PRE>";
1063
1064                #        $content_data = implode("", $content_mysql);
1065
1066                $patterns[3] = '/SET client_encoding/';
1067                $patterns[4] = '/SET check_function_bodies/';
1068                $patterns[5] = '/SET search_path/';
1069                $replacements[3] = '-- ';
1070                $replacements[4] = '-- ';
1071                $replacements[5] = '-- ';
1072
1073                $content_mysql = preg_replace($patterns, $replacements, $content_mysql);
1074
1075                print "<PRE>$content_mysql</PRE>"; # Debug
1076
1077                exit ();
1078
1079                $result = mysql_query($content_mysql);
1080                if (!$result) {
1081                    die('Invalid query: '.mysql_error());
1082                }
1083
1084                navigation(array (array ("title" => "Back", "page" => "database"), array ("title" => "Next", "page" => "dbinit")));
1085                break;
1086            default :
1087                print<<<EndHTML
1088          The CONF_DBMS value <B>$CONF_DBMS</B> is not currently suported by this install script.
1089EndHTML;
1090                navigation(array (array ("title" => "Back", "page" => "database")));
1091        }
1092        break;
1093
1094        ###################################
1095    case 'schema_validate' :
1096        print "<H1>Database schema upgrade</H1>\n";
1097
1098        require_once (dirname(__FILE__).'/include/common.php');
1099
1100        require_once ('classes/AbstractDb.php');
1101        require_once ('classes/Session.php');
1102        require_once ('include/schema_validate.php');
1103
1104        validate_schema();
1105
1106        navigation(array (array ("title" => "Back", "page" => "dbinit"), array ("title" => "Next", "page" => "options")));
1107
1108        //navigation(array(array("title" => "Back", "page" => "dbinit")));
1109        break;
1110
1111        ###################################
1112    case 'options' :
1113        # TODO : Tester que la connection SSL est fonctionnelle
1114        #        Options avancees : Supporter les define de [SMARTY|MAGPIE|PHLICKR|JPGRAPH]_REL_PATH
1115        print<<< EndHTML
1116<H1>Options</H1>
1117  <TABLE border="1">
1118
1119EndHTML;
1120
1121        #$neededPackages['phlickr']['available'] = 0;
1122        #$neededExtentions['xml']['available'] = 0;
1123        foreach ($optionsInfo as $name => $foo) { # Foreach generate all <TABLE> fields
1124            $value = $configArray[$name]; # Value of option in config.php
1125            $title = $optionsInfo[$name]['title']; # Field Title
1126            $message = $optionsInfo[$name]['message']; # Message why option is disable
1127            $depend = @ eval ($optionsInfo[$name]['depend']); # Evaluate the dependencie
1128            $selectedTrue = '';
1129            $selectedFalse = ''; # Initialize value
1130            $value == 'true' ? $selectedTrue = 'SELECTED' : $selectedFalse = 'SELECTED'; # Use to select the previous saved option
1131            $depend == 1 ? $disabled = '' : $disabled = 'DISABLED'; # Disable <SELECT> if dependencie is not satisfied
1132            $jscript = "<script type=\"text/javascript\"> newConfig(\"$name=false\"); </script>\n"; # Use to save a failed dependencie (option=false)
1133            if ($disabled == '') # Dependencie ok, erase $jscript value
1134                $jscript = '';
1135
1136            print<<< EndHTML
1137  <TR>
1138    <TD>$title</TD>
1139    <TD><SELECT name="$name" $disabled>
1140          <OPTION value="true" $selectedTrue>true</OPTION>
1141          <OPTION value="false" $selectedFalse>false</OPTION>
1142        </SELECT>
1143    </TD>
1144    <TD>$message</TD>
1145  </TR>
1146  $jscript
1147EndHTML;
1148        } # End or foreach
1149        print<<< EndHTML
1150    </TABLE>
1151
1152<script type="text/javascript">
1153  function submitOptionsValue() {
1154
1155EndHTML;
1156
1157        foreach ($optionsInfo as $name => $foo) { # Generate the javascript to save value on submit
1158            print<<< EndHTML
1159    if (!document.myform.$name.disabled)
1160      newConfig("$name=" + document.myform.$name.value);
1161
1162EndHTML;
1163        } # End Foreach
1164
1165        print<<< EndHTML
1166  }
1167</script>
1168
1169EndHTML;
1170        navigation(array (array ("title" => "Back", "page" => "dbinit")));
1171
1172        print<<< EndHTML
1173<P><A HREF="#" ONCLICK="javascript: document.myform.page.value='languages'; submitOptionsValue(); document.myform.submit();" CLASS="button">Next</A></P>
1174EndHTML;
1175
1176        break;
1177
1178        ###################################
1179    case 'languages' :
1180        print "<H1>Languages configuration</H1>";
1181        print<<< EndHTML
1182      <P>Not yet implemented ...</P>
1183      <P>Will allow selecting language to use.</P>
1184<B>Error message example</B> : <BR>
1185<DIV style="border:solid black;">Warning: language.php: Unable to setlocale() to fr, return value: , current locale: LC_CTYPE=en_US.UTF-8;LC_NUMERIC=C; [...]</DIV>
1186<P><B>I repeat</B> : This is an example of message you can see in the top of your working auth-server if language are not set correctly. To change these values please edit <B>config.php</B> in auth-server install directory. Look for "Available locales" and "Default language" header in config.php.
1187EndHTML;
1188        //    exec("locale -a 2>&1", $output, $return);
1189
1190        navigation(array (array ("title" => "Back", "page" => "options"), array ("title" => "Next", "page" => "radius")));
1191        break;
1192
1193        ###################################
1194    case 'radius' :
1195        print "<H1>Radius Authenticator configuration</H1>";
1196        print "<P>Not yet implemented ...";
1197
1198        # Dependencies
1199        #$neededExtentions['mcrypt']['available'];
1200        #$neededExtentions['mhash']['available'];
1201        #$neededExtentions['xmlrpc']['available'];
1202        #$neededPEARPackages['radius']['available'];
1203        #$neededPEARPackages['Auth_RADIUS']['available'];
1204        #$neededPEARPackages['Crypt_CHAP']['available'];
1205
1206        navigation(array (array ("title" => "Back", "page" => "languages"), array ("title" => "Next", "page" => "admin")));
1207        break;
1208
1209        ###################################
1210    case 'admin' :
1211        print "<H1>Administration account</H1>";
1212        # TODO : Allow to create more than one admin account and list the current admin users
1213        #        Allow admin to choose to show or not is username
1214        empty ($_REQUEST['username']) ? $username = 'admin' : $username = $_REQUEST['username'];
1215        empty ($_REQUEST['password']) ? $password = '' : $password = $_REQUEST['password'];
1216        empty ($_REQUEST['password2']) ? $password2 = '' : $password2 = $_REQUEST['password2'];
1217        empty ($_REQUEST['email']) ? $email = $_SERVER['SERVER_ADMIN'] : $email = $_REQUEST['email'];
1218
1219        $conn_string = "host=$CONF_DATABASE_HOST dbname=$CONF_DATABASE_NAME user=$CONF_DATABASE_USER password=$CONF_DATABASE_PASSWORD";
1220        $connection = pg_connect($conn_string) or die();
1221
1222        if ($action == 'create') {
1223            //      require_once(dirname(__FILE__) . '/config.php');
1224            require_once (dirname(__FILE__).'/include/common.php');
1225            require_once (dirname(__FILE__).'/classes/User.php');
1226
1227            $created_user = User :: createUser(get_guid(), $username, Network :: getDefaultNetwork(), $email, $password);
1228            $user_id = $created_user->getId();
1229
1230            # Add user to admin table, hide his username and set his account status to 1 (allowed)
1231            $sql = "INSERT INTO administrators (user_id) VALUES ('$user_id'); UPDATE users SET  account_status='1', never_show_username=true WHERE user_id='$user_id'";
1232            $result = pg_query($connection, $sql);
1233        }
1234
1235        $sql = "SELECT * FROM users NATURAL JOIN administrators WHERE account_origin = 'default-network'";
1236        $result = pg_query($connection, $sql);
1237        $result_array = pg_fetch_all($result);
1238        $username_db = $result_array[0]['username'];
1239
1240        if (!empty ($username_db)) {
1241            print "<P>Your administrator user account is <B>$username_db</B>";
1242            navigation(array (array ("title" => "Back", "page" => "radius"), array ("title" => "Next", "page" => "network")));
1243        }
1244        else {
1245            print<<<EndHTML
1246        <P>
1247        <TABLE BORDER="1">
1248        <TR>
1249          <TD>Username</TD><TD><INPUT type="text" name="username" value="$username"></TD>
1250        </TR>
1251        <TR>
1252          <TD>Password</TD><TD><INPUT type="password" name="password"></TD>
1253        </TR>
1254        <TR>
1255          <TD>Password again</TD><TD><INPUT type="password" name="password2"></TD>
1256        </TR>
1257        <TR>
1258          <TD>Email</TD><TD><INPUT type="text" name="email" value="$email"></TD>
1259        </TR>
1260        </TABLE>
1261
1262        <script type="text/javascript">
1263          function submitValue() {
1264            if (document.myform.password.value != document.myform.password2.value) {
1265              alert('Password mismatch, Please retry');
1266              exit();
1267            }
1268            if (document.myform.password.value == '') {
1269              alert('You need to type a password');
1270              exit();
1271            }
1272            if (document.myform.email.value == '') {
1273              alert('You need to type a email');
1274              exit();
1275            }
1276            document.myform.page.value='admin';
1277            document.myform.action.value='create';
1278            document.myform.submit();
1279          }
1280        </script>
1281
1282EndHTML;
1283            navigation(array (array ("title" => "Back", "page" => "radius")));
1284            print "<P><A HREF=\"#\" ONCLICK=\"javascript: submitValue();\" CLASS=\"button\">Next</A></P>\n";
1285        }
1286        break;
1287
1288        ###################################
1289    case 'network' :
1290        print "<H1>Network</H1>";
1291
1292        //$HOTSPOT_NETWORK_NAME          = $configArray['HOTSPOT_NETWORK_NAME'];
1293        //$HOTSPOT_NETWORK_URL           = $configArray['HOTSPOT_NETWORK_URL'];
1294        //$TECH_SUPPORT_EMAIL            = $configArray['TECH_SUPPORT_EMAIL'];
1295        //$VALIDATION_GRACE_TIME         = $configArray['VALIDATION_GRACE_TIME'];
1296        //$VALIDATION_EMAIL_FROM_ADDRESS = $configArray['VALIDATION_EMAIL_FROM_ADDRESS'];
1297
1298        /**
1299         * @deprecated 2005-12-26 Needs to use network abstraction
1300         *
1301         *
1302         * <P>
1303        <TABLE border="1">
1304        <TR>
1305        <TD>Network Name</TD><TD><INPUT type="text" name="HOTSPOT_NETWORK_NAME" value="" size="30"></TD>
1306        </TR>
1307        <TR>
1308        <TD>Network URL</TD><TD><INPUT type="text" name="HOTSPOT_NETWORK_URL" value="" size="30"></TD>
1309        </TR>
1310        <TR>
1311        <TD>Tech Support Email</TD><TD><INPUT type="text" name="TECH_SUPPORT_EMAIL" value="" size="30"></TD>
1312        </TR>
1313        <TR>
1314        <TD>Validation Grace Time (min)</TD><TD><INPUT type="text" name="VALIDATION_GRACE_TIME" value="" size="30"></TD>
1315        </TR>
1316        <TR>
1317        <TD>Validation Email (send from)</TD><TD><INPUT type="text" name="VALIDATION_EMAIL_FROM_ADDRESS" value="" size="30"></TD>
1318        </TR>
1319        </TABLE>
1320         */
1321        print "Need to reimplement this... Until then connect to the administration pages and modify it by yourself.";
1322
1323        print<<< EndHTML
1324
1325
1326<script type="text/javascript">
1327  function submitOptionsValue() {
1328    //newConfig("HOTSPOT_NETWORK_NAME='" + document.myform.HOTSPOT_NETWORK_NAME.value + "'");
1329    //newConfig("HOTSPOT_NETWORK_URL='" + document.myform.HOTSPOT_NETWORK_URL.value + "'");
1330    //newConfig("TECH_SUPPORT_EMAIL='" + document.myform.TECH_SUPPORT_EMAIL.value + "'");
1331    //newConfig("VALIDATION_GRACE_TIME=" + document.myform.VALIDATION_GRACE_TIME.value);
1332    //newConfig("VALIDATION_EMAIL_FROM_ADDRESS='" + document.myform.VALIDATION_EMAIL_FROM_ADDRESS.value + "'");
1333  }
1334</script>
1335
1336EndHTML;
1337
1338        navigation(array (array ("title" => "Back", "page" => "admin")));
1339
1340        print<<< EndHTML
1341<P><A HREF="#" ONCLICK="javascript: document.myform.page.value='hotspot'; submitOptionsValue(); document.myform.submit();" CLASS="button">Next</A></P>
1342EndHTML;
1343        #navigation(array(array("title" => "Back", "page" => "admin"), array("title" => "Next", "page" => "hotspot")));
1344        break;
1345
1346        ###################################
1347    case 'hotspot' :
1348        print "<H1>Hotspot</H1>";
1349        print "<P>A default hotspot has already been created<P>Use administration interface to add more hotspots.";
1350        navigation(array (array ("title" => "Back", "page" => "network"), array ("title" => "Next", "page" => "end")));
1351        break;
1352
1353        ###################################
1354    case 'delete' :
1355        print<<<EndHTML
1356  <H1>Delete temporary files</H1>
1357  ...
1358EndHTML;
1359        #navigation(array(array("title" => "Back", "page" => "hotspot")));
1360        break;
1361
1362        ###################################
1363    case 'end' :
1364        $url = 'http://'.$_SERVER['HTTP_HOST'].SYSTEM_PATH;
1365        print<<<EndHTML
1366  <H1>Thanks for using Wifidog</H1>
1367  Redirection to your new WifiDog Authentification Server in 3 seconds
1368  <meta http-equiv="REFRESH" content="3;url=$url">
1369  <PRE>
1370
1371               |\   /|              _
1372               |A\_/A|            z   z
1373            ___|     |           ( (o) )
1374           o    6     \           z _ z
1375           |___        \           /|
1376               |        \         / |
1377                \        \_______/  |
1378                |                   |
1379                |      WIFIDOG      |
1380                |   Captive Portal  |
1381                |   _____________   |
1382                |  /             \  |
1383                |  |             |  |
1384                |  |             |  |
1385              _/   |           _/   |
1386             ?_____|          ?_____|
1387</PRE>
1388EndHTML;
1389        #navigation(array(array("title" => "Back", "page" => "hotspot")));
1390        break;
1391
1392        ###################################
1393    case 'toc' :
1394        print "<H1>Table of content</H1>";
1395        $contentArray = file(__file__); # Read myself
1396        print "<UL>\n";
1397        foreach ($contentArray as $line) {
1398            if (preg_match("/^  case '(\w+)':/", $line, $matchesArray)) { # Parse for "case" regex
1399                if ($matchesArray[1] == 'toc')
1400                    continue;
1401                print "<LI><A HREF=\"".$_SERVER['SCRIPT_NAME']."?page=".$matchesArray[1]."\">".$matchesArray[1]."</A>\n"; # Display a Table of Content
1402            }
1403        }
1404        print "</UL>\n";
1405        break;
1406        ###################################
1407    case 'notes' :
1408        print<<<EndHTML
1409<!-- /* Editor highlighting trick -->
1410<PRE>
1411<B>TODO</B>
1412  -Support des define de Google Maps dans config.php
1413  -Faire une fonction d'execution avec gestion de retour d'erreur et d'affichage de l'exection pour chaque "exec"
1414  -Ajouter une veritable validation (user/password admin provenant de la DB)
1415     Pour une meilleur securite du script d'installation.
1416       Au chargement, valider que la connection DB est fonctionnel, que la DB existe et que l'usager admin existe
1417         Si oui, on demande l'authentification
1418         Si non, on creer l'usager admin
1419  -Faire un vrai menu pour acceder directement aux pages desirees (pas une TOC poche)
1420  -Ameliorer le javascript et arreter de faire des document.myform.submit();
1421  -Generate valid HTML code
1422  -Integrate this script with the portal skin
1423  -Tester que les donnees de AVAIL_LOCALE_ARRAY dans config.php sont valides (fonctionnelles)
1424     Regarder le code dans include/language.php
1425  -Support pour l'option CUSTOM_SIGNUP_URL
1426  -Effacer repertoires/fichiers temporaires des installations
1427
1428  -Nice2Have : Si test d'integrite et de fonctionnement existent, les integrer pour assurer le bon fonctionnement
1429  -Nice2Have : Si donnees de tests exitent (pour les developpeurs) Permettre d'en ajouter a la DB
1430  -Nice2Have : Creer un wifidog.conf (client) selon config + questions si necessaires
1431
1432<B>Change Log</B>
1433  15-08-2005 : Bugs correction + comments added
1434  11-08-2005 : Options rewrite with foreach and dependencies
1435  09-08-2005 : Admin user creation + network configuration
1436  27-07-2005 : Added jpgraph install
1437  26-07-2005 : Added minimal security password validation
1438  14-07-2005 : saveConfig and all javascript code
1439  09-07-2005 : Added Phlickr installation
1440  05-07-2005 : Better PHP extention validation process
1441  17-06-2005 : MySQL schema and data submission
1442  17-06-2005 : Postgresql schema and data submission
1443  24-04-2005 : CSS button
1444
1445</PRE>
1446<!-- Editor highlighting trick */ -->
1447EndHTML;
1448        break;
1449        ###################################
1450        /*  case 'phpinfo': // Use for debugging, to be removed
1451            print "<PRE>";
1452            print_r(get_loaded_extensions());
1453            print "</PRE><BR><BR>";
1454            phpinfo();
1455          break;*/
1456
1457    default :
1458        $WIFIDOG_VERSION = $configArray['WIFIDOG_VERSION'];
1459        # TODO : Add links to auth-server web documents
1460        print<<<EndHTML
1461<H1>Welcome to WifiDog Auth-Server installation and configuration script.</H1>
1462<P>This installation still needs improvement, so please any report bug to the mailing list for better support.<BR/>
1463The current auth-server version is <B>$WIFIDOG_VERSION</B>.</P>
1464
1465<P><strong>Before going any further</strong> with this installation you need to have/create a valid user and database.
1466<P>Here is a command line example for PostgreSQL (or use the way you like) :</P>
1467
1468<B>Create the PostgreSQL databaser user for WifiDog</B> (createuser and createdb need to be in you PATH) :
1469<PRE>  <I>postgres@yourserver $></I> createuser wifidog --pwprompt
1470  Enter password for new user:
1471  Enter it again:
1472  Shall the new user be allowed to create databases? (y/n) n
1473  Shall the new user be allowed to create more new users? (y/n) n
1474  CREATE USER
1475</PRE>
1476
1477<B>Create the WifiDog database</B>
1478<PRE>  <I>postgres@yourserver $></I> createdb wifidog --encoding=UTF-8 --owner=wifidog
1479  CREATE DATABASE
1480</PRE>
1481
1482<B>Security</B> : A password is needed to continue with the installation. You need to read the random password in <B>$password_file</B> file. No username needed, only the password. This password is only usefull for the installation, you will never use it in Auth-Server administration pages.
1483</PRE>
1484
1485<P>When you are ready click next</P>
1486
1487EndHTML;
1488
1489        navigation(array (array ("title" => "Next", "page" => "version")));
1490}
1491?>
1492
1493</form>
1494</body>
1495</html>
1496
Note: See TracBrowser for help on using the browser.