MDL-18167 towareds reimplementing of win installer support
[moodle.git] / install.php
1 <?php /// $Id$
2       /// install.php - helps admin user to create a config.php file
5 if (isset($_REQUEST['lang'])) {
6     $lang = eregi_replace('[^A-Za-z0-9_-]', '', $_REQUEST['lang']);
7 } else {
8     $lang = 'en_utf8';
9 }
11 if (isset($_REQUEST['admin'])) {
12     $admin = eregi_replace('[^A-Za-z0-9_-]', '', $_REQUEST['admin']);
13 } else {
14     $admin = 'admin';
15 }
17 /// If config.php exists we just created config.php and need to redirect to continue installation
18 $configfile = './config.php';
19 if (file_exists($configfile)) {
20     header("Location: $admin/index.php?lang=$lang");
21     die;
22 }
24 /// make sure PHP errors are displayed - helps with diagnosing of problems
25 @error_reporting(E_ALL);
26 @ini_set('display_errors', '1');
27 // we need a lot of memory
28 @ini_set('memory_limit', '40M');
30 /// Check that PHP is of a sufficient version
31 if (version_compare(phpversion(), "5.2.0") < 0) {
32     $phpversion = phpversion();
33     // do NOT localise - lang strings would not work here and we CAN not move it after installib
34     echo "Sorry, Moodle 2.0 requires PHP 5.2.8 or later (currently using version $phpversion). ";
35     echo "Please upgrade your server software or install latest Moodle 1.9.x instead.";
36     die;
37 }
39 require dirname(__FILE__).'/lib/installlib.php';
41 // TODO: add lang detection here if empty $_REQUEST['lang']
43 // distro specific customisation
44 $distro = null;
45 if (file_exists('install/versions.php')) {
46     $a = null;
47     include('install/versions.php');
48     if ($a) {
49         $distro = $a;
50         unset($a);
51     }
52 }
54 $config = new stdClass();
55 $config->lang = $lang;
57 if (!empty($_POST)) {
58     if (install_ini_get_bool('magic_quotes_gpc')) {
59         $_POST = array_map('stripslashes', $_POST);
60     }
62     $config->stage = (int)$_POST['stage'];
64     if (isset($_POST['previous'])) {
65         $config->stage--;
66         if ($config->stage == INSTALL_ENVIRONMENT or $config->stage == INSTALL_DOWNLOADLANG) {
67             $config->stage--;
68         }
69         if (INSTALL_DISTRIBUTION and empty($distro)) {
70             $config->stage--;
71         }
72     } else if (isset($_POST['next'])) {
73         $config->stage++;
74     }
76     $config->dbtype   = trim($_POST['dbtype']);
77     $config->dbhost   = trim($_POST['dbhost']);
78     $config->dbuser   = trim($_POST['dbuser']);
79     $config->dbpass   = trim($_POST['dbpass']);
80     $config->dbname   = trim($_POST['dbname']);
81     $config->prefix   = trim($_POST['prefix']);
82     $config->dbsocket = (int)(!empty($_POST['dbsocket']));
84     $config->dirroot  = trim($_POST['dirroot']);
85     $config->admin    = empty($_POST['admin']) ? 'admin' : trim($_POST['admin']);
87     $config->dataroot = trim($_POST['dataroot']);
89 } else {
90     $config->stage    = INSTALL_WELCOME;
92     $config->dbtype   = '';
93     $config->dbhost   = 'localhost';
94     $config->dbuser   = '';
95     $config->dbpass   = '';
96     $config->dbname   = 'moodle';
97     $config->prefix   = 'mdl_';
98     $config->dbsocket = 0;
100     $config->dirroot  = dirname(__FILE__);
101     $config->admin    = 'admin';
103     $config->dataroot = null; // initialised later after including libs
106 /// Fake some settings so that we can use selected functions from moodlelib.php and weblib.php
107 $CFG = new stdClass();
108 $CFG->lang                 = $config->lang;
109 $CFG->dirroot              = dirname(__FILE__);
110 $CFG->libdir               = "$CFG->dirroot/lib";
111 $CFG->wwwroot              = install_guess_wwwroot(); // can not be changed - ppl must use the real address when installing
112 $CFG->httpswwwroot         = $CFG->wwwroot;
113 $CFG->httpsthemewww        = $CFG->wwwroot;
114 $CFG->dataroot             = $config->dataroot;
115 $CFG->admin                = $config->admin;
116 $CFG->docroot              = 'http://docs.moodle.org';
117 $CFG->directorypermissions = 00777;
118 $CFG->running_installer    = true;
120 /// Require all needed libs
121 require_once($CFG->libdir.'/setuplib.php');
122 require_once($CFG->libdir.'/textlib.class.php');
123 require_once($CFG->libdir.'/weblib.php');
124 require_once($CFG->libdir.'/dmllib.php');
125 require_once($CFG->libdir.'/moodlelib.php');
126 require_once($CFG->libdir.'/deprecatedlib.php');
127 require_once($CFG->libdir.'/adminlib.php');
128 require_once($CFG->libdir.'/environmentlib.php');
129 require_once($CFG->libdir.'/xmlize.php');
130 require_once($CFG->libdir.'/componentlib.class.php');
132 require('version.php');
133 $CFG->release = $release;
135 $SESSION = new object();
136 $SESSION->lang = $CFG->lang;
138 $USER = new object();
139 $USER->id = 0;
141 $COURSE = new object();
142 $COURSE->id = 0;
144 $SITE = $COURSE;
145 define('SITEID', 0);
147 $hint_dataroot = '';
148 $hint_dirroot  = '';
149 $hint_admindir = '';
150 $hint_database = '';
152 /// Are we in help mode?
153 if (isset($_GET['help'])) {
154     install_print_help_page($_GET['help']);
157 /// send css?
158 if (isset($_GET['css'])) {
159     install_css_styles();
162 ///first time here? find out suitable dataroot
163 if (is_null($CFG->dataroot)) {
164     $CFG->dataroot = str_replace('\\', '/', dirname(dirname(__FILE__)).'/moodledata');
166     $i = 0; //safety check - dirname might return some unexpected results
167     while(is_dataroot_insecure()) {
168         $parrent = dirname($CFG->dataroot);
169         $i++;
170         if ($parrent == '/' or $parrent == '.' or preg_match('/^[a-z]:\\\?$/i', $parrent) or ($i > 100)) {
171             $CFG->dataroot = ''; //can not find secure location for dataroot
172             break;
173         }
174         $CFG->dataroot = dirname($parrent).'/moodledata';
175     }
176     $config->dataroot = $CFG->dataroot;
177     $config->stage    = INSTALL_WELCOME;
180 // now let's do the stage work
181 if ($config->stage < INSTALL_WELCOME) {
182     $config->stage = INSTALL_WELCOME;
184 if ($config->stage > INSTALL_SAVE) {
185     $config->stage = INSTALL_SAVE;
190 if ($config->stage == INSTALL_SAVE) {
191     $database = moodle_database::get_driver_instance($config->dbtype, 'native');
192     if (!$database->driver_installed()) {
193         $config->stage = INSTALL_DATABASETYPE;
194     } else {
195         $hint_database = install_db_validate($database, $config->dbhost, $config->dbuser, $config->dbpass, $config->dbname, $config->prefix, array('dbpersit'=>0, 'dbsocket'=>$config->dbsocket));
197         if ($hint_database === '') {
198             $configphp = '<?php  /// Moodle Configuration File ' . "\r\n\r\n";
200             $configphp .= 'unset($CFG);'."\r\n";
201             $configphp .= '$CFG = new stdClass();'."\r\n\r\n"; // prevent PHP5 strict warnings
203             $dbconfig = $database->export_dbconfig();
205             foreach ($dbconfig as $key=>$value) {
206                 $key = str_pad($key, 9);
207                 $configphp .= '$CFG->'.$key.' = '.var_export($value, true).";\r\n";
208             }
209             $configphp .= "\r\n";
211             $configphp .= '$CFG->wwwroot   = '.var_export($CFG->wwwroot, true).";\r\n";
213             if ($CFG->dirroot !== $config->dirroot) {
214                 $configphp .= '$CFG->dirroot   = realpath('.var_export($config->dirroot, true).");\r\n"; // fix for sym links
215             } else {
216                 $dirroot = str_replace('\\', '/', $CFG->dirroot); // win32 fix
217                 $dirroot = rtrim($dirroot, '/');  // no trailing /
218                 $configphp .= '$CFG->dirroot   = '.var_export($dirroot, true).";\r\n";
219             }
221             $dataroot = str_replace('\\', '/', $config->dataroot); // win32 fix
222             $dataroot = rtrim($dataroot, '/');  // no trailing /
223             $configphp .= '$CFG->dataroot  = '.var_export($dataroot, true).";\r\n";
225             $configphp .= '$CFG->admin     = '.var_export($config->admin, true).";\r\n\r\n";
227             $configphp .= '$CFG->directorypermissions = 00777;  // try 02777 on a server in Safe Mode'."\r\n";
228             $configphp .= "\r\n";
230             $configphp .= 'require_once("$CFG->dirroot/lib/setup.php");'."\r\n\r\n";
231             $configphp .= '// There is no php closing tag in this file,'."\r\n";
232             $configphp .= '// it is intentional because it prevents trailing whitespace problems!'."\r\n";
234             umask(0137);
235     
236             if (($fh = @fopen($configfile, 'w')) !== false) {
237                 fwrite($fh, $configphp);
238                 fclose($fh);
239             }
240     
241             if (file_exists($configfile)) {
242                 // config created, let's continue!
243                 redirect("$CFG->wwwroot/$config->admin/index.php?lang=$config->lang");
244             }
246             install_print_header($config, 'config.php',
247                                           get_string('configurationcompletehead', 'install'),
248                                           get_string('configurationcompletesub', 'install').get_string('configfilenotwritten', 'install'));
249             echo '<div class="configphp"><pre>';
250             echo p($configphp);
251             echo '</pre></div>';
253             install_print_footer($config);
254             die;
256         } else {
257             $config->stage = INSTALL_DATABASE;
258         }
259     }
264 if ($config->stage == INSTALL_DATABASE) {
265     $database = moodle_database::get_driver_instance($config->dbtype, 'native');
267     $sub = '<h3>'.$database->get_name().'</h3>'.$database->get_configuration_help();
269     install_print_header($config, get_string('database', 'install'), get_string('databasehead', 'install'), $sub);
271     $strdbhost   = get_string('databasehost', 'install');
272     $strdbname   = get_string('databasename', 'install');
273     $strdbuser   = get_string('databaseuser', 'install');
274     $strdbpass   = get_string('databasepass', 'install');
275     $strprefix   = get_string('dbprefix', 'install');
276     $strdbsocket = get_string('databasesocket', 'install');
278     echo '<div class="userinput">';
279     echo '<div class="formrow"><label for="id_dbhost" class="formlabel">'.$strdbhost.'</label>';
280     echo '<input id="id_dbhost" name="dbhost" type="text" value="'.s($config->dbhost).'" size="30" class="forminput" />';
281     echo '</div>';
283     echo '<div class="formrow"><label for="id_dbname" class="formlabel">'.$strdbname.'</label>';
284     echo '<input id="id_dbname" name="dbname" type="text" value="'.s($config->dbname).'" size="30" class="forminput" />';
285     echo '</div>';
287     echo '<div class="formrow"><label for="id_dbuser" class="formlabel">'.$strdbuser.'</label>';
288     echo '<input id="id_dbuser" name="dbuser" type="text" value="'.s($config->dbuser).'" size="30" class="forminput" />';
289     echo '</div>';
291     echo '<div class="formrow"><label for="id_dbpass" class="formlabel">'.$strdbpass.'</label>';
292     // no password field here, the password may be visible in config.php if we can not write it to disk
293     echo '<input id="id_dbpass" name="dbpass" type="text" value="'.s($config->dbpass).'" size="30" class="forminput" />';
294     echo '</div>';
296     echo '<div class="formrow"><label for="id_prefix" class="formlabel">'.$strprefix.'</label>';
297     echo '<input id="id_prefix" name="prefix" type="text" value="'.s($config->prefix).'" size="10" class="forminput" />';
298     echo '</div>';
300     if (!(stristr(PHP_OS, 'win') && !stristr(PHP_OS, 'darwin'))) {
301         $checked = $config->dbsocket ? 'checked="checked' : '';
302         echo '<div class="formrow"><label for="id_dbsocket" class="formlabel">'.$strdbsocket.'</label>';
303         echo '<input type="hidden" value="0" name="dbsocket" />';
304         echo '<input type="checkbox" id="id_dbsocket" value="1" name="dbsocket" '.$checked.' class="forminput" />';
305         echo '</div>';
306     }
308     echo '<div class="hint">'.$hint_database.'</div>';
309     echo '</div>';
310     install_print_footer($config);
311     die;
316 if ($config->stage == INSTALL_DOWNLOADLANG) {
317     if (empty($CFG->dataroot)) {
318         $config->stage = INSTALL_PATHS;
320     } else if (is_dataroot_insecure()) {
321         $hint_dataroot = get_string('pathsunsecuredataroot', 'install');
322         $config->stage = INSTALL_PATHS;
324     } else if (!is_writable($CFG->dataroot)) {
325         $hint_dataroot = get_string('pathsrodataroot', 'install');
326         $config->stage = INSTALL_PATHS;
327     }
329     if ($config->dirroot === '' or !file_exists($config->dirroot)) {
330         $hint_dirroot = get_string('pathswrongdirroot', 'install');
331         $config->stage = INSTALL_PATHS;
332     }
334     if ($config->admin === '' or !file_exists($config->dirroot.'/'.$config->admin.'/environment.xml')) {
335         $hint_admindir = get_string('pathswrongadmindir', 'install');
336         $config->stage = INSTALL_PATHS;
337     }
342 if ($config->stage == INSTALL_DOWNLOADLANG) {
343     if ($CFG->lang == 'en_utf8') {
344         $config->stage = INSTALL_DATABASETYPE;
345     }
350 if ($config->stage == INSTALL_DOWNLOADLANG) {
351     $downloaderror = '';
353 /// Create necessary lang dir
354     if (!make_upload_directory('lang', false)) {
355         $downloaderror = get_string('cannotcreatelangdir', 'error');
357 /// Download and install lang component
358     } else if ($cd = new component_installer('http://download.moodle.org', 'lang16', $CFG->lang.'.zip', 'languages.md5', 'lang')) {
359         if ($cd->install() == COMPONENT_ERROR) {
360             if ($cd->get_error() == 'remotedownloaderror') {
361                 $a = new stdClass();
362                 $a->url  = 'http://download.moodle.org/lang16/'.$INSTALL['language'].'.zip';
363                 $a->dest = $CFG->dataroot.'/lang';
364                 $downloaderror = get_string($cd->get_error(), 'error', $a);
365             } else {
366                 $downloaderror = get_string($cd->get_error(), 'error');
367             }
368         }
369     }
371     if ($downloaderror !== '') {
372         install_print_header($config, get_string('language'), get_string('langdownloaderror', 'install', $CFG->lang), $downloaderror);
373         install_print_footer($config);
374         die;
375     } else {
376         $config->stage = INSTALL_DATABASETYPE;
377     }
382 if ($config->stage == INSTALL_DATABASETYPE) {
383     /// Finally ask for DB type
384     install_print_header($config, get_string('database', 'install'),
385                                   get_string('databasetypehead', 'install'),
386                                   get_string('databasetypesub', 'install'));
388     // TODO: move this PHP5 code to lib/installib.php so that this file parses in PHP4
389     $databases = array('mysqli' => moodle_database::get_driver_instance('mysqli', 'native'),
390                        'pgsql'  => moodle_database::get_driver_instance('pgsql',  'native'),
391                        'oci'    => moodle_database::get_driver_instance('oci',    'native'),
392                        //'sqlsrv' => moodle_database::get_driver_instance('sqlsrv', 'native'), // new MS sql driver - win32 only
393                        //'mssql'  => moodle_database::get_driver_instance('mssql',  'native'), // FreeTDS driver
394                       );
396     echo '<div class="userinput">';
397     echo '<div class="formrow"><label class="formlabel" for="dbtype">'.get_string('dbtype', 'install').'</label>';
398     echo '<select id="dbtype" name="dbtype" class="forminput">';
399     $disabled = array();
400     $options = array();
401     foreach ($databases as $type=>$database) {
402         if ($database->driver_installed() !== true) {
403             $disabled[$type] = $database;
404             continue;
405         }
406         echo '<option value="'.s($type).'">'.$database->get_name().'</option>';
407     }
408     if ($disabled) {
409         echo '<optgroup label="'.s(get_string('notavailable')).'">';
410         foreach ($disabled as $type=>$database) {
411             echo '<option value="'.s($type).'" class="notavailable">'.$database->get_name().'</option>';
412         }
413         echo '</optgroup>';
414     }
415     echo '</select></div>';
416     echo '</div>';
418     install_print_footer($config);
419     die;
424 if ($config->stage == INSTALL_ENVIRONMENT or $config->stage == INSTALL_PATHS) {
425     $version_fail = (version_compare(phpversion(), "5.2.8") < 0);
426     $curl_fail    = ($lang !== 'en_utf8' and !extension_loaded('curl')); // needed for lang pack download
427     $zip_fail     = ($lang !== 'en_utf8' and !extension_loaded('zip'));  // needed for lang pack download
429     if ($version_fail or $curl_fail or $zip_fail) {
430         $config->stage = INSTALL_ENVIRONMENT;
432         install_print_header($config, get_string('environment', 'install'),
433                                       get_string('errorsinenvironment', 'install'),
434                                       get_string('environmentsub2', 'install'));
436         echo '<div id="envresult"><dl>';
437         if ($version_fail) {
438             $a = (object)array('needed'=>'5.2.8', 'current'=>phpversion());
439             echo '<dt>'.get_string('phpversion', 'install').'</dt><dd>'.get_string('environmentrequireversion', 'admin', $a).'</dd>';
440         }
441         if ($curl_fail) {
442             echo '<dt>'.get_string('phpextension', 'install', 'cURL').'</dt><dd>'.get_string('environmentrequireinstall', 'admin').'</dd>';
443         }
444         if ($zip_fail) {
445             echo '<dt>'.get_string('phpextension', 'install', 'Zip').'</dt><dd>'.get_string('environmentrequireinstall', 'admin').'</dd>';
446         }
447         echo '</dl></div>';
449         install_print_footer($config, true);
450         die;
452     } else {
453         $config->stage = INSTALL_PATHS;
454     }
459 if ($config->stage == INSTALL_DISTRIBUTION) {
460     if (!$distro) {
461         $config->stage = INSTALL_PATHS;
462     } else {
463         include('install/distribution.html');
464         die;
465     }
470 if ($config->stage == INSTALL_PATHS) {
471     $paths = array('wwwroot'  => get_string('wwwroot', 'install'),
472                    'dirroot'  => get_string('dirroot', 'install'),
473                    'dataroot' => get_string('dataroot', 'install'),
474                    'admindir' => get_string('admindirname', 'install'));
476     $sub = '<dl>';
477     foreach ($paths as $path=>$name) {
478         $sub .= '<dt>'.$name.'</dt><dd>'.get_string('pathssub'.$path, 'install').'</dd>';
479     }
480     $sub .= '</dl>';
482     install_print_header($config, get_string('paths', 'install'), get_string('pathshead', 'install'), $sub);
484     $strwwwroot      = get_string('wwwroot', 'install');
485     $strdirroot      = get_string('dirroot', 'install');
486     $strdataroot     = get_string('dataroot', 'install');
487     $stradmindirname = get_string('admindirname', 'install');
489     echo '<div class="userinput">';
490     echo '<div class="formrow"><label for="id_wwwroot" class="formlabel">'.$paths['wwwroot'].'</label>';
491     echo '<input id="id_wwwroot" name="wwwroot" type="text" value="'.s($CFG->wwwroot).'" disabled="disabled" size="45" class="forminput" />';
492     echo '</div>';
494     echo '<div class="formrow"><label for="id_dirroot" class="formlabel">'.$paths['dirroot'].'</label>';
495     echo '<input id="id_dirroot" name="dirroot" type="text" value="'.s($config->dirroot).'" size="45"class="forminput" />';
496     if ($hint_dirroot !== '') {
497         echo '<div class="hint">'.$hint_dirroot.'</div>';
498     }
499     echo '</div>';
501     echo '<div class="formrow"><label for="id_dataroot" class="formlabel">'.$paths['dataroot'].'</label>';
502     echo '<input id="id_dataroot" name="dataroot" type="text" value="'.s($config->dataroot).'" size="45" class="forminput" />';
503     if ($hint_dataroot !== '') {
504         echo '<div class="hint">'.$hint_dataroot.'</div>';
505     }
506     echo '</div>';
509     if (file_exists("$CFG->dirroot/admin/environment.xml")) {
510         $disabled = 'disabled="disabled"';
511     } else {
512         $disabled = '';
513     }
514     echo '<div class="formrow"><label for="id_admin" class="formlabel">'.$paths['admindir'].'</label>';
515     echo '<input id="id_admin" name="admin" type="text" value="'.s($config->admin).'" '.$disabled.' size="10" class="forminput" />';
516     if ($hint_admindir !== '') {
517         echo '<div class="hint">'.$hint_admindir.'</div>';
518     }
519     echo '</div>';
521     echo '</div>';
523     install_print_footer($config);
524     die;
529 $config->stage = INSTALL_WELCOME;
530 install_print_header($config, get_string('language'),
531                               get_string('chooselanguagehead', 'install'),
532                               get_string('chooselanguagesub', 'install'));
534 $languages = install_get_list_of_languages();
535 echo '<div class="userinput">';
536 echo '<div class="formrow"><label class="formlabel" for="langselect">'.get_string('language').'</label>';
537 echo '<select id="langselect" name="lang" class="forminput" onchange="this.form.submit()">';
538 foreach ($languages as $name=>$value) {
539     $selected = ($name == $CFG->lang) ? 'selected="selected"' : '';
540     echo '<option value="'.s($name).'" '.$selected.'>'.$value.'</option>';
542 echo '</select></div>';
543 echo '</div>';
545 install_print_footer($config);
546 die;