. /** * This script creates config.php file and prepares database. * * This script is not intended for beginners! * Potential problems: * - environment check is not present yet * - su to apache account or sudo before execution * - not compatible with Windows platform * * @package moodlecore * @subpackage cli * @copyright 2009 Petr Skoda (http://skodak.org) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ if (isset($_SERVER['REMOTE_ADDR'])) { error_log("admin/cli/install.php can not be called from web server!"); exit; } $olddir = getcwd(); // change directory so that includes bellow work properly chdir(dirname($_SERVER['argv'][0])); // Nothing to do if config.php exists $configfile = dirname(dirname(dirname(__FILE__))).'/config.php'; if (file_exists($configfile)) { die("Moodle already installed, please use admin/cli/upgrade.php if you want to upgrade your site.\n"); } // make sure PHP errors are displayed - helps with diagnosing of problems @error_reporting(E_ALL); @ini_set('display_errors', '1'); // we need a lot of memory @ini_set('memory_limit', '128M'); // Check that PHP is of a sufficient version if (version_compare(phpversion(), "5.2.8") < 0) { $phpversion = phpversion(); // do NOT localise - lang strings would not work here and we CAN NOT move it after installib echo "Sorry, Moodle 2.0 requires PHP 5.2.8 or later (currently using version $phpversion).\n"; echo "Please upgrade your server software or install latest Moodle 1.9.x instead."; die; } // set up configuration $CFG = new stdClass(); $CFG->lang = 'en_utf8'; $CFG->dirroot = str_replace('\\', '/', dirname(dirname(dirname(__FILE__)))); // Fix for win32 $CFG->libdir = "$CFG->dirroot/lib"; $CFG->wwwroot = "http://localhost"; $CFG->httpswwwroot = $CFG->wwwroot; $CFG->httpsthemewww = $CFG->wwwroot; $CFG->dataroot = str_replace('\\', '/', dirname(dirname(dirname(__FILE__))).'/moodledata'); $CFG->docroot = 'http://docs.moodle.org'; $CFG->directorypermissions = 00777; $CFG->running_installer = true; $parts = explode('/', str_replace('\\', '/', dirname(dirname(__FILE__)))); $CFG->admin = array_pop($parts); require($CFG->dirroot.'/version.php'); $CFG->target_release = $release; //point pear include path to moodles lib/pear so that includes and requires will search there for files before anywhere else //the problem is that we need specific version of quickforms and hacked excel files :-( ini_set('include_path', $CFG->libdir.'/pear' . PATH_SEPARATOR . ini_get('include_path')); require_once($CFG->libdir.'/installlib.php'); require_once($CFG->libdir.'/clilib.php'); require_once($CFG->libdir.'/setuplib.php'); require_once($CFG->libdir.'/textlib.class.php'); require_once($CFG->libdir.'/weblib.php'); require_once($CFG->libdir.'/dmllib.php'); require_once($CFG->libdir.'/moodlelib.php'); require_once($CFG->libdir.'/deprecatedlib.php'); require_once($CFG->libdir.'/adminlib.php'); require_once($CFG->libdir.'/environmentlib.php'); require_once($CFG->libdir.'/xmlize.php'); require_once($CFG->libdir.'/componentlib.class.php'); require_once($CFG->libdir.'/upgradelib.php'); //Database types $databases = array('mysqli' => moodle_database::get_driver_instance('mysqli', 'native'), 'pgsql' => moodle_database::get_driver_instance('pgsql', 'native'), 'oci' => moodle_database::get_driver_instance('oci', 'native'), //'sqlsrv' => moodle_database::get_driver_instance('sqlsrv', 'native'), // new MS sql driver - win32 only //'mssql' => moodle_database::get_driver_instance('mssql', 'native'), // FreeTDS driver ); foreach ($databases as $type=>$database) { if ($database->driver_installed() !== true) { unset($databases[$type]); } } if (empty($databases)) { cli_error('No db drivers available!'); // TODO: localize } reset($databases); $defaultdb = key($databases); // now get cli options list($options, $unrecognized) = cli_get_params(array('lang'=>$CFG->lang, 'wwwroot'=>'', 'dataroot'=>$CFG->dataroot, 'dbtype'=>$defaultdb, 'dbhost'=>'localhost', 'dbname'=>'moodle', 'dbuser'=>'root', 'dbpass'=>'', 'dbsocket'=>false, 'prefix'=>'mdl_', 'admin-password'=>'', 'non-interactive'=>false, 'agreelicense'=>false, 'help'=>false), array('h'=>'help')); $interactive = empty($options['non-interactive']); // set up language $lang = clean_param($options['lang'], PARAM_SAFEDIR); if (file_exists($CFG->dirroot.'/install/lang/'.$lang)) { $CFG->lang = $lang; } else { if (file_exists($CFG->dirroot.'/install/lang/'.$lang.'_utf8')) { $CFG->lang = $lang.'_utf8'; } } if ($unrecognized) { $error = implode("\n ", $unrecognized); cli_error("Unrecognized options:\n $error \n. Please use --help option."); // TODO: localize, mark as needed in install } if ($options['help']) { $help = "Command line Moodle installer, creates config.php and initializes database. Please note you must execute this script with the same uid as apache or use chmod/chown after installation. Site defaults may be changed via local/defaults.php. Options: --lang=CODE Installation and default site language. --wwwroot=URL Web address for the Moodle site, required in non-interactive mode. --dataroot=DIR Location of the moodle data folder, must not be web accessible. Default is moodleroot in parent directory. --dbtype=TYPE Database type. Default is mysqli --dbhost=HOST Database host. Default is localhost --dbname=NAME Database name. Default is moodle --dbuser=USERNAME Database user. Default is root --dbpass=PASSWORD Database password. Default is blank --dbsocket Use database sockets. Available for some databases only. --prefix=STRING Table prefix for above database tables. Default is mdl_ --admin-password=PASS Password for the moodle admin account, required in non-interactive mode. --non-interactive No interactive questions, installation fails if any problem encountered. --agreelicense Indicates agreement with software license, required in non-interactive mode. -h, --help Print out this help Example: \$sudo -u wwwrun /usr/bin/php admin/cli/install.php --lang=cs "; //TODO: localize, mark as needed in install echo $help; die; } $separator = str_repeat('=', 79)."\n"; //Print header echo "Moodle $CFG->target_release command line installation program.\n"; // TODO: localize, mark as needed in install //Fist select language if ($interactive) { echo $separator; $languages = install_get_list_of_languages(); // fomrat the langs nicely - 4 per line $c = 0; $langlist = ''; foreach ($languages as $key=>$lang) { $c++; $length = iconv_strlen($lang, 'UTF-8'); $padded = $lang.str_repeat(' ', 28-$length); $langlist .= $padded; if ($c % 3 == 0) { $langlist .= "\n"; } } $default = str_replace('_utf8', '', $CFG->lang); $prompt = "Available languages:\n$langlist\nType language code or press Enter to use default value ($default)"; // TODO: localize, mark as needed in install $error = ''; do { echo $error; $input = cli_input($prompt, $default); $input = clean_param($input, PARAM_SAFEDIR); if (!file_exists($CFG->dirroot.'/install/lang/'.$input.'_utf8')) { $error = "Incorrect value, please retry.\n"; // TODO: localize, mark as needed in install } else { $error = ''; } } while ($error !== ''); $CFG->lang = $input.'_utf8'; } else { // already verified } //We need wwwroot before we test dataroot $wwwroot = clean_param($options['wwwroot'], PARAM_URL); $wwwroot = trim($wwwroot, '/'); if ($interactive) { echo $separator; if (strpos($wwwroot, 'http') === 0) { $prompt = "Type URL of your site \nor press Enter to use default value ($wwwroot)"; // TODO: localize, mark as needed in install } else { $prompt = "Type URL of your site"; // TODO: localize, mark as needed in install } $error = ''; do { echo $error; $input = cli_input($prompt, $wwwroot); $input = clean_param($input, PARAM_URL); $input = trim($input, '/'); if (strpos($input, 'http') !== 0) { $error = "Incorrect value, please retry.\n"; // TODO: localize, mark as needed in install } else { $error = ''; } } while ($error !== ''); $wwwroot = $input; } else { if (strpos($wwwroot, 'http') !== 0) { cli_error("Error:\n wwwroot parametr value \"$wwwroot\" in not correct. Please use different value."); // TODO: localize, mark as needed in install } } $CFG->wwwroot = $wwwroot; $CFG->httpswwwroot = $CFG->wwwroot; $CFG->httpsthemewww = $CFG->wwwroot; //We need dataroot before lang download if ($interactive) { echo $separator; $i=0; while(is_dataroot_insecure()) { $parrent = dirname($CFG->dataroot); $i++; if ($parrent == '/' or $parrent == '.' or preg_match('/^[a-z]:\\\?$/i', $parrent) or ($i > 100)) { $CFG->dataroot = ''; //can not find secure location for dataroot break; } $CFG->dataroot = dirname($parrent).'/moodledata'; } $error = ''; do { if ($CFG->dataroot !== '') { $prompt = "Type Moodle data directory \nor press Enter to use default value ($CFG->dataroot)"; // TODO: localize, mark as needed in install } else { $prompt = "Type Moodle data directory"; // TODO: localize, mark as needed in install } echo $error; $CFG->dataroot = cli_input($prompt, $CFG->dataroot); if ($CFG->dataroot === '') { $error = "Incorrect value, please retry.\n"; // TODO: localize, mark as needed in install } else if (is_dataroot_insecure()) { $CFG->dataroot = ''; $error = "Directory may not be secure, please retry.\n"; // TODO: localize, mark as needed in install } else { if (make_upload_directory('lang', false)) { $error = ''; } else { $error = "Can not create dataroot directory, verify permissions or create directory manually.\n"; // TODO: localize, mark as needed in install } } } while ($error !== ''); } else { if (is_dataroot_insecure()) { cli_error("Error:\n directory $CFG->dataroot may be directly accessible via web. Please use different directory."); // TODO: localize, mark as needed in install } } //download lang pack with optional notification if ($CFG->lang != 'en_utf8') { if ($interactive) { echo $separator; echo "Downloading latest language package from moodle.org...\n"; // TODO: localize, mark as needed in install } if ($cd = new component_installer('http://download.moodle.org', 'lang16', $CFG->lang.'.zip', 'languages.md5', 'lang')) { if ($cd->install() == COMPONENT_ERROR) { if ($cd->get_error() == 'remotedownloaderror') { $a = new stdClass(); $a->url = 'http://download.moodle.org/lang16/'.$CFG->lang.'.zip'; $a->dest = $CFG->dataroot.'/lang'; cli_problem(get_string($cd->get_error(), 'error', $a)); } else { cli_problem(get_string($cd->get_error(), 'error')); } } else { // install parent lang if defined if ($parentlang = get_parent_language()) { if ($cd = new component_installer('http://download.moodle.org', 'lang16', $parentlang.'.zip', 'languages.md5', 'lang')) { $cd->install(); } } } } if ($interactive) { echo "...finished lang download.\n"; // TODO: localize } } unset($CFG->running_installer); // we use full lang packs from now on // ask for db type - show only drivers available if ($interactive) { $options['dbtype'] = strtolower($options['dbtype']); echo $separator; echo "Available database drivers\n"; foreach ($databases as $type=>$database) { echo " $type:".$database->get_name()."\n"; } echo "\n"; if (!empty($databases[$options['dbtype']])) { $prompt = "Type driver short name\nor press Enter to use default value (".$options['dbtype'].")"; // TODO: localize } else { $prompt = "Type driver short name"; // TODO: localize } $CFG->dbtype = cli_input($prompt, $options['dbtype'], array_keys($databases)); } else { if (empty($databases[$options['dbtype']])) { cli_error("Error:\n dbtype parametr value \"".$options['dbtype']."\" in not correct. Please use different value."); // TODO: localize } $CFG->dbtype = $options['dbtype']; } $database = $databases[$CFG->dbtype]; // ask for db host if ($interactive) { echo $separator; if ($options['dbhost'] !== '') { $prompt = "Type database host\nor press Enter to use default value (".$options['dbhost'].")"; // TODO: localize } else { $prompt = "Type database host"; // TODO: localize } $CFG->dbhost = cli_input($prompt, $options['dbhost']); } else { $CFG->dbhost = $options['dbhost']; } // ask for db name if ($interactive) { echo $separator; if ($options['dbname'] !== '') { $prompt = "Type database name\nor press Enter to use default value (".$options['dbname'].")"; // TODO: localize } else { $prompt = "Type database name"; // TODO: localize } $CFG->dbname = cli_input($prompt, $options['dbname']); } else { $CFG->dbname = $options['dbname']; } // ask for db prefix if ($interactive) { echo $separator; //TODO: solve somehow the prefix trouble for oci if ($options['prefix'] !== '') { $prompt = "Type table prefix\nor press Enter to use default value (".$options['prefix'].")"; // TODO: localize } else { $prompt = "Type table prefix"; // TODO: localize } $CFG->prefix = cli_input($prompt, $options['prefix']); } else { $CFG->prefix = $options['prefix']; } // ask for db user if ($interactive) { echo $separator; if ($options['dbuser'] !== '') { $prompt = "Type database user name\nor press Enter to use default value (".$options['dbuser'].")"; // TODO: localize } else { $prompt = "Type database user name"; // TODO: localize } $CFG->dbuser = cli_input($prompt, $options['dbuser']); } else { $CFG->dbuser = $options['dbuser']; } // ask for db password if ($interactive) { echo $separator; do { if ($options['dbpass'] !== '') { $prompt = "Type database user password\nor press Enter to use default value (".$options['dbpass'].")"; // TODO: localize } else { $prompt = "Type database user password"; // TODO: localize } $CFG->dbpass = cli_input($prompt, $options['dbpass']); $hint_database = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, array('dbpersit'=>0, 'dbsocket'=>$options['dbsocket'])); } while ($hint_database !== ''); } else { $CFG->dbpass = $options['dbpass']; $hint_database = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, array('dbpersit'=>0, 'dbsocket'=>$options['dbsocket'])); if ($hint_database !== '') { cli_error('Can not open connection to database!'); } } // ask for admin user password if ($interactive) { echo $separator; $prompt = "Type requested password for user 'admin'"; // TODO: localize do { $options['admin-password'] = cli_input($prompt); } while (empty($options['admin-password']) or $options['admin-password'] === 'admin'); } else { if (empty($options['admin-password']) or $options['admin-password'] === 'admin') { cli_error('Requested administrator password must not be empty or easy to guess..'); //TODO: localize } } if ($interactive) { echo $separator; if (!$options['agreelicense']) { echo "Do you agree to Moodle license blah blah blah?\n"; //TODO: localize and use real license $input = cli_input('Type yes or y if you agree, ctrl+c if not', '', array('yes', 'y')); // TODO: localize including yes/y } } else { if (!$options['agreelicense']) { cli_error('You must aggree to license by specifying --agreelicense'); //TODO: localize } } // Finally we have all info needed for config.php $configphp = install_generate_configphp($database, $CFG); umask(0137); if (($fh = fopen($configfile, 'w')) !== false) { fwrite($fh, $configphp); fclose($fh); } if (!file_exists($configfile)) { cli_error('Can not create config file.'); } else if ($interactive) { echo $separator; echo "config.php created\n"; } // return back to original dir before executing setup.php chich changes the dir again chdir($olddir); // We have config.php, it is a real php script from now on :-) require($configfile); // show as much debug as possible @error_reporting(1023); @ini_set('display_errors', '1'); $CFG->debug = 38911; $CFG->debugdisplay = true; $CFG->version = ""; $CFG->release = ""; // read $version adn $release require($CFG->dirroot.'/version.php'); if ($DB->get_tables() ) { cli_error('Database tables already present, cli installation can not continue.'); } if (!$DB->setup_is_unicodedb()) { if (!$DB->change_db_encoding()) { // If could not convert successfully, throw error, and prevent installation cli_error(get_string('unicoderequired', 'admin')); } } if ($interactive) { echo $separator; echo get_string('databasesetup')."\n"; } // install core install_core($version, true); set_config('release', $release); // install all plugins types, local, etc. upgrade_noncore(true); // set up admin user password $DB->set_field('user', 'password', hash_internal_user_password($options['admin-password'], array('username'=>'admin'))); // indicate that this site is fully configured set_config('rolesactive', 1); upgrade_finished(); // log in as admin - we need do anything when applying defaults $admins = get_admins(); $admin = reset($admins); session_set_user($admin); message_set_default_message_preferences($admin); // apply all default settings, do it twice to fill all defaults - some settings depend on other setting admin_apply_default_settings(NULL, true); admin_apply_default_settings(NULL, true); set_config('registerauth', ''); echo "yay!!!\n"; exit(0); // 0 means success