From 6973aaefc205b286cd7b465ff162042c20ea2b15 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Mon, 23 Apr 2018 22:56:59 +0200 Subject: [PATCH 1/7] Add Install Mode - Added $install_mode in Class App instead - Extracted the install business logic to a new Class Install - Replaced all $a->module == 'install' with $a->install_mode --- include/text.php | 4 +- mod/install.php | 301 +------------------ src/App.php | 1 + src/Core/Console/AutomaticInstallation.php | 18 +- src/Core/Install.php | 331 +++++++++++++++++++++ 5 files changed, 349 insertions(+), 306 deletions(-) create mode 100644 src/Core/Install.php diff --git a/include/text.php b/include/text.php index 2ec017caff..796acffcef 100644 --- a/include/text.php +++ b/include/text.php @@ -637,7 +637,7 @@ function logger($msg, $level = 0) { // turn off logger in install mode if ( - $a->module == 'install' + $a->install_mode || !dba::$connected ) { return; @@ -709,7 +709,7 @@ function dlogger($msg, $level = 0) { // turn off logger in install mode if ( - $a->module == 'install' + $a->install_mode || !dba::$connected ) { return; diff --git a/mod/install.php b/mod/install.php index eb740c7b64..3b09da6e4a 100644 --- a/mod/install.php +++ b/mod/install.php @@ -5,11 +5,9 @@ use Friendica\App; use Friendica\Core\L10n; +use Friendica\Core\Install; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Database\DBStructure; -use Friendica\Object\Image; -use Friendica\Util\Network; use Friendica\Util\Temporal; $install_wizard_pass = 1; @@ -27,6 +25,8 @@ function install_init(App $a) { $a->config['system']['theme'] = "../install"; $a->theme['stylesheet'] = System::baseUrl()."/view/install/style.css"; + Install::setInstallMode(); + global $install_wizard_pass; if (x($_POST, 'pass')) { $install_wizard_pass = intval($_POST['pass']); @@ -72,34 +72,7 @@ function install_post(App $a) { // connect to db dba::connect($dbhost, $dbuser, $dbpass, $dbdata, true); - $tpl = get_markup_template('htconfig.tpl'); - $txt = replace_macros($tpl,[ - '$dbhost' => $dbhost, - '$dbuser' => $dbuser, - '$dbpass' => $dbpass, - '$dbdata' => $dbdata, - '$timezone' => $timezone, - '$language' => $language, - '$urlpath' => $urlpath, - '$phpath' => $phpath, - '$adminmail' => $adminmail, - '$rino' => $rino - ]); - - - $result = file_put_contents('.htconfig.php', $txt); - if (! $result) { - $a->data['txt'] = $txt; - } - - $errors = load_database(); - - - if ($errors) { - $a->data['db_failed'] = $errors; - } else { - $a->data['db_installed'] = true; - } + Install::install($urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $phpath, $timezone, $language, $adminmail, $rino); return; break; @@ -167,37 +140,11 @@ function install_content(App $a) { switch ($install_wizard_pass) { case 1: { // System check - - $checks = []; - - check_funcs($checks); - - check_imagik($checks); - - check_htconfig($checks); - - check_smarty3($checks); - - check_keys($checks); - if (x($_POST, 'phpath')) { $phpath = notags(trim($_POST['phpath'])); } - check_php($phpath, $checks); - - check_htaccess($checks); - - /// @TODO Maybe move this out? - function check_passed($v, $c) { - if ($c['required']) { - $v = $v && $c['status']; - } - return $v; - } - $checkspassed = array_reduce($checks, "check_passed", true); - - + list($checks, $checkspassed) = Install::check($phpath); $tpl = get_markup_template('install_checks.tpl'); $o .= replace_macros($tpl, [ @@ -296,238 +243,6 @@ function install_content(App $a) { } } -/** - * checks : array passed to template - * title : string - * status : boolean - * required : boolean - * help : string optional - */ -function check_add(&$checks, $title, $status, $required, $help) { - $checks[] = [ - 'title' => $title, - 'status' => $status, - 'required' => $required, - 'help' => $help, - ]; -} - -function check_php(&$phpath, &$checks) { - $passed = $passed2 = $passed3 = false; - if (strlen($phpath)) { - $passed = file_exists($phpath); - } else { - $phpath = trim(shell_exec('which php')); - $passed = strlen($phpath); - } - $help = ""; - if (!$passed) { - $help .= L10n::t('Could not find a command line version of PHP in the web server PATH.'). EOL; - $help .= L10n::t("If you don't have a command line version of PHP installed on your server, you will not be able to run the background processing. See 'Setup the worker'") . EOL; - $help .= EOL . EOL; - $tpl = get_markup_template('field_input.tpl'); - $help .= replace_macros($tpl, [ - '$field' => ['phpath', L10n::t('PHP executable path'), $phpath, L10n::t('Enter full path to php executable. You can leave this blank to continue the installation.')], - ]); - $phpath = ""; - } - - check_add($checks, L10n::t('Command line PHP').($passed?" ($phpath)":""), $passed, false, $help); - - if ($passed) { - $cmd = "$phpath -v"; - $result = trim(shell_exec($cmd)); - $passed2 = ( strpos($result, "(cli)") !== false); - list($result) = explode("\n", $result); - $help = ""; - if (!$passed2) { - $help .= L10n::t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29"). EOL; - $help .= L10n::t('Found PHP version: ')."$result"; - } - check_add($checks, L10n::t('PHP cli binary'), $passed2, true, $help); - } - - - if ($passed2) { - $str = autoname(8); - $cmd = "$phpath testargs.php $str"; - $result = trim(shell_exec($cmd)); - $passed3 = $result == $str; - $help = ""; - if (!$passed3) { - $help .= L10n::t('The command line version of PHP on your system does not have "register_argc_argv" enabled.'). EOL; - $help .= L10n::t('This is required for message delivery to work.'); - } - check_add($checks, L10n::t('PHP register_argc_argv'), $passed3, true, $help); - } - - -} - -function check_keys(&$checks) { - - $help = ''; - - $res = false; - - if (function_exists('openssl_pkey_new')) { - $res = openssl_pkey_new([ - 'digest_alg' => 'sha1', - 'private_key_bits' => 4096, - 'encrypt_key' => false - ]); - } - - // Get private key - - if (! $res) { - $help .= L10n::t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys'). EOL; - $help .= L10n::t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".'); - } - check_add($checks, L10n::t('Generate encryption keys'), $res, true, $help); - -} - - -function check_funcs(&$checks) { - $ck_funcs = []; - check_add($ck_funcs, L10n::t('libCurl PHP module'), true, true, ""); - check_add($ck_funcs, L10n::t('GD graphics PHP module'), true, true, ""); - check_add($ck_funcs, L10n::t('OpenSSL PHP module'), true, true, ""); - check_add($ck_funcs, L10n::t('PDO or MySQLi PHP module'), true, true, ""); - check_add($ck_funcs, L10n::t('mb_string PHP module'), true, true, ""); - check_add($ck_funcs, L10n::t('XML PHP module'), true, true, ""); - check_add($ck_funcs, L10n::t('iconv PHP module'), true, true, ""); - check_add($ck_funcs, L10n::t('POSIX PHP module'), true, true, ""); - - if (function_exists('apache_get_modules')) { - if (! in_array('mod_rewrite',apache_get_modules())) { - check_add($ck_funcs, L10n::t('Apache mod_rewrite module'), false, true, L10n::t('Error: Apache webserver mod-rewrite module is required but not installed.')); - } else { - check_add($ck_funcs, L10n::t('Apache mod_rewrite module'), true, true, ""); - } - } - - if (! function_exists('curl_init')) { - $ck_funcs[0]['status'] = false; - $ck_funcs[0]['help'] = L10n::t('Error: libCURL PHP module required but not installed.'); - } - if (! function_exists('imagecreatefromjpeg')) { - $ck_funcs[1]['status'] = false; - $ck_funcs[1]['help'] = L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.'); - } - if (! function_exists('openssl_public_encrypt')) { - $ck_funcs[2]['status'] = false; - $ck_funcs[2]['help'] = L10n::t('Error: openssl PHP module required but not installed.'); - } - if (! function_exists('mysqli_connect') && !class_exists('pdo')) { - $ck_funcs[3]['status'] = false; - $ck_funcs[3]['help'] = L10n::t('Error: PDO or MySQLi PHP module required but not installed.'); - } - if (!function_exists('mysqli_connect') && class_exists('pdo') && !in_array('mysql', PDO::getAvailableDrivers())) { - $ck_funcs[3]['status'] = false; - $ck_funcs[3]['help'] = L10n::t('Error: The MySQL driver for PDO is not installed.'); - } - if (! function_exists('mb_strlen')) { - $ck_funcs[4]['status'] = false; - $ck_funcs[4]['help'] = L10n::t('Error: mb_string PHP module required but not installed.'); - } - if (! function_exists('iconv_strlen')) { - $ck_funcs[6]['status'] = false; - $ck_funcs[6]['help'] = L10n::t('Error: iconv PHP module required but not installed.'); - } - if (! function_exists('posix_kill')) { - $ck_funcs[7]['status'] = false; - $ck_funcs[7]['help'] = L10n::t('Error: POSIX PHP module required but not installed.'); - } - - $checks = array_merge($checks, $ck_funcs); - - // check for XML DOM Documents being able to be generated - try { - $xml = new DOMDocument(); - } catch (Exception $e) { - $ck_funcs[5]['status'] = false; - $ck_funcs[5]['help'] = L10n::t('Error, XML PHP module required but not installed.'); - } -} - - -function check_htconfig(&$checks) { - $status = true; - $help = ""; - if ((file_exists('.htconfig.php') && !is_writable('.htconfig.php')) || - (!file_exists('.htconfig.php') && !is_writable('.'))) { - - $status = false; - $help = L10n::t('The web installer needs to be able to create a file called ".htconfig.php" in the top folder of your web server and it is unable to do so.') .EOL; - $help .= L10n::t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.').EOL; - $help .= L10n::t('At the end of this procedure, we will give you a text to save in a file named .htconfig.php in your Friendica top folder.').EOL; - $help .= L10n::t('You can alternatively skip this procedure and perform a manual installation. Please see the file "INSTALL.txt" for instructions.').EOL; - } - - check_add($checks, L10n::t('.htconfig.php is writable'), $status, false, $help); - -} - -function check_smarty3(&$checks) { - $status = true; - $help = ""; - if (!is_writable('view/smarty3')) { - - $status = false; - $help = L10n::t('Friendica uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') .EOL; - $help .= L10n::t('In order to store these compiled templates, the web server needs to have write access to the directory view/smarty3/ under the Friendica top level folder.').EOL; - $help .= L10n::t("Please ensure that the user that your web server runs as \x28e.g. www-data\x29 has write access to this folder.").EOL; - $help .= L10n::t("Note: as a security measure, you should give the web server write access to view/smarty3/ only--not the template files \x28.tpl\x29 that it contains.").EOL; - } - - check_add($checks, L10n::t('view/smarty3 is writable'), $status, true, $help); - -} - -function check_htaccess(&$checks) { - $status = true; - $help = ""; - if (function_exists('curl_init')) { - $test = Network::fetchUrl(System::baseUrl()."/install/testrewrite"); - - if ($test != "ok") { - $test = Network::fetchUrl(normalise_link(System::baseUrl()."/install/testrewrite")); - } - - if ($test != "ok") { - $status = false; - $help = L10n::t('Url rewrite in .htaccess is not working. Check your server configuration.'); - } - check_add($checks, L10n::t('Url rewrite is working'), $status, true, $help); - } else { - // cannot check modrewrite if libcurl is not installed - /// @TODO Maybe issue warning here? - } -} - -function check_imagik(&$checks) { - $imagick = false; - $gif = false; - - if (class_exists('Imagick')) { - $imagick = true; - $supported = Image::supportedTypes(); - if (array_key_exists('image/gif', $supported)) { - $gif = true; - } - } - if ($imagick == false) { - check_add($checks, L10n::t('ImageMagick PHP extension is not installed'), $imagick, false, ""); - } else { - check_add($checks, L10n::t('ImageMagick PHP extension is installed'), $imagick, false, ""); - if ($imagick) { - check_add($checks, L10n::t('ImageMagick supports GIF'), $gif, false, ""); - } - } -} - function manual_config(App $a) { $data = htmlentities($a->data['txt'],ENT_COMPAT, 'UTF-8'); $o = L10n::t('The database configuration file ".htconfig.php" could not be written. Please use the enclosed text to create a configuration file in your web server root.'); @@ -544,12 +259,6 @@ function load_database_rem($v, $i) { } } -function load_database() { - $errors = DBStructure::update(false, true, true); - - return $errors; -} - function what_next() { $baseurl = System::baseUrl(); return diff --git a/src/App.php b/src/App.php index d76351b97a..5ff7eab04d 100644 --- a/src/App.php +++ b/src/App.php @@ -52,6 +52,7 @@ class App public $argv; public $argc; public $module; + public $install_mode = false; public $pager; public $strings; public $basepath; diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php index 6318b19a88..ff27782302 100644 --- a/src/Core/Console/AutomaticInstallation.php +++ b/src/Core/Console/AutomaticInstallation.php @@ -5,9 +5,9 @@ namespace Friendica\Core\Console; use Asika\SimpleConsole\Console; use dba; use Friendica\App; +use Friendica\Core\Install; require_once 'mod/install.php'; -require_once 'include/dba.php'; class AutomaticInstallation extends Console { @@ -43,6 +43,8 @@ HELP; $db_data = ''; require_once 'htconfig.php'; + Install::setInstallMode(); + $this->out(" Complete!\n\n"); // Check basic setup @@ -74,7 +76,7 @@ HELP; // Install database $this->out("Inserting data into database...\n"); - $checkResults['data'] = load_database(); + $checkResults['data'] = Install::loadDatabase(); if ($checkResults['data'] !== '') { throw new \RuntimeException("ERROR: DB Database creation error. Is the DB empty?\n"); @@ -101,14 +103,14 @@ HELP; { $checks = []; - check_funcs($checks); - check_imagik($checks); - check_htconfig($checks); - check_smarty3($checks); - check_keys($checks); + Install::checkFunctions($checks); + Install::checkImagik($checks); + Install::checkHtConfig($checks); + Install::checkSmarty3($checks); + Install::checkKeys($checks); if (!empty($app->config['php_path'])) { - check_php($app->config['php_path'], $checks); + Install::checkPHP($app->config['php_path'], $checks); } else { throw new \RuntimeException(" ERROR: The php_path is not set in the config. Please check the file .htconfig.php.\n"); } diff --git a/src/Core/Install.php b/src/Core/Install.php new file mode 100644 index 0000000000..25ecb02b4f --- /dev/null +++ b/src/Core/Install.php @@ -0,0 +1,331 @@ +install_mode = $mode; + } + + public static function check($phpath = 'php') + { + $checks = []; + + self::checkFunctions($checks); + + self::checkImagik($checks); + + self::checkHtConfig($checks); + + self::checkSmarty3($checks); + + self::checkKeys($checks); + + self::checkPHP($phpath, $checks); + + self::checkHtAccess($checks); + + $checkspassed = array_reduce($checks, + function ($v, $c) { + if ($c['require']) { + $v = $v && $c['status']; + } + return $v; + }, + true); + + return array($checks, $checkspassed); + } + + public static function install($urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $phpath, $timezone, $language, $adminmail, $rino = 1) + { + $tpl = get_markup_template('htconfig.tpl'); + $txt = replace_macros($tpl,[ + '$dbhost' => $dbhost, + '$dbuser' => $dbuser, + '$dbpass' => $dbpass, + '$dbdata' => $dbdata, + '$timezone' => $timezone, + '$language' => $language, + '$urlpath' => $urlpath, + '$phpath' => $phpath, + '$adminmail' => $adminmail, + '$rino' => $rino + ]); + + + $result = file_put_contents('config/.htconfig.php', $txt); + if (! $result) { + self::getApp()->data['txt'] = $txt; + } + + $errors = self::loadDatabase(); + + if ($errors) { + self::getApp()->data['db_failed'] = $errors; + } else { + self::getApp()->data['db_installed'] = true; + } + } + + /** + * checks : array passed to template + * title : string + * status : boolean + * required : boolean + * help : string optional + */ + private static function addCheck(&$checks, $title, $status, $required, $help) + { + $checks[] = [ + 'title' => $title, + 'status' => $status, + 'required' => $required, + 'help' => $help, + ]; + } + + public static function checkPHP(&$phpath, &$checks) + { + $passed = $passed2 = $passed3 = false; + if (strlen($phpath)) { + $passed = file_exists($phpath); + } else { + $phpath = trim(shell_exec('which php')); + $passed = strlen($phpath); + } + $help = ""; + if (!$passed) { + $help .= L10n::t('Could not find a command line version of PHP in the web server PATH.'). EOL; + $help .= L10n::t("If you don't have a command line version of PHP installed on your server, you will not be able to run the background processing. See 'Setup the worker'") . EOL; + $help .= EOL . EOL; + $tpl = get_markup_template('field_input.tpl'); + $help .= replace_macros($tpl, [ + '$field' => ['phpath', L10n::t('PHP executable path'), $phpath, L10n::t('Enter full path to php executable. You can leave this blank to continue the installation.')], + ]); + $phpath = ""; + } + + self::addCheck($checks, L10n::t('Command line PHP').($passed?" ($phpath)":""), $passed, false, $help); + + if ($passed) { + $cmd = "$phpath -v"; + $result = trim(shell_exec($cmd)); + $passed2 = ( strpos($result, "(cli)") !== false); + list($result) = explode("\n", $result); + $help = ""; + if (!$passed2) { + $help .= L10n::t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29"). EOL; + $help .= L10n::t('Found PHP version: ')."$result"; + } + self::addCheck($checks, L10n::t('PHP cli binary'), $passed2, true, $help); + } + + + if ($passed2) { + $str = autoname(8); + $cmd = "$phpath testargs.php $str"; + $result = trim(shell_exec($cmd)); + $passed3 = $result == $str; + $help = ""; + if (!$passed3) { + $help .= L10n::t('The command line version of PHP on your system does not have "register_argc_argv" enabled.'). EOL; + $help .= L10n::t('This is required for message delivery to work.'); + } + self::addCheck($checks, L10n::t('PHP register_argc_argv'), $passed3, true, $help); + } + + + } + + public static function checkKeys(&$checks) + { + + $help = ''; + + $res = false; + + if (function_exists('openssl_pkey_new')) { + $res = openssl_pkey_new([ + 'digest_alg' => 'sha1', + 'private_key_bits' => 4096, + 'encrypt_key' => false + ]); + } + + // Get private key + + if (! $res) { + $help .= L10n::t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys'). EOL; + $help .= L10n::t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".'); + } + self::addCheck($checks, L10n::t('Generate encryption keys'), $res, true, $help); + + } + + + public static function checkFunctions(&$checks) + { + $ck_funcs = []; + self::addCheck($ck_funcs, L10n::t('libCurl PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('GD graphics PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('OpenSSL PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('PDO or MySQLi PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('mb_string PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('XML PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('iconv PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('POSIX PHP module'), true, true, ""); + + if (function_exists('apache_get_modules')) { + if (! in_array('mod_rewrite',apache_get_modules())) { + self::addCheck($ck_funcs, L10n::t('Apache mod_rewrite module'), false, true, L10n::t('Error: Apache webserver mod-rewrite module is required but not installed.')); + } else { + self::addCheck($ck_funcs, L10n::t('Apache mod_rewrite module'), true, true, ""); + } + } + + if (! function_exists('curl_init')) { + $ck_funcs[0]['status'] = false; + $ck_funcs[0]['help'] = L10n::t('Error: libCURL PHP module required but not installed.'); + } + if (! function_exists('imagecreatefromjpeg')) { + $ck_funcs[1]['status'] = false; + $ck_funcs[1]['help'] = L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.'); + } + if (! function_exists('openssl_public_encrypt')) { + $ck_funcs[2]['status'] = false; + $ck_funcs[2]['help'] = L10n::t('Error: openssl PHP module required but not installed.'); + } + if (! function_exists('mysqli_connect') && !class_exists('pdo')) { + $ck_funcs[3]['status'] = false; + $ck_funcs[3]['help'] = L10n::t('Error: PDO or MySQLi PHP module required but not installed.'); + } + if (!function_exists('mysqli_connect') && class_exists('pdo') && !in_array('mysql', PDO::getAvailableDrivers())) { + $ck_funcs[3]['status'] = false; + $ck_funcs[3]['help'] = L10n::t('Error: The MySQL driver for PDO is not installed.'); + } + if (! function_exists('mb_strlen')) { + $ck_funcs[4]['status'] = false; + $ck_funcs[4]['help'] = L10n::t('Error: mb_string PHP module required but not installed.'); + } + if (! function_exists('iconv_strlen')) { + $ck_funcs[6]['status'] = false; + $ck_funcs[6]['help'] = L10n::t('Error: iconv PHP module required but not installed.'); + } + if (! function_exists('posix_kill')) { + $ck_funcs[7]['status'] = false; + $ck_funcs[7]['help'] = L10n::t('Error: POSIX PHP module required but not installed.'); + } + + $checks = array_merge($checks, $ck_funcs); + + // check for XML DOM Documents being able to be generated + try { + $xml = new DOMDocument(); + } catch (Exception $e) { + $ck_funcs[5]['status'] = false; + $ck_funcs[5]['help'] = L10n::t('Error, XML PHP module required but not installed.'); + } + } + + + public static function checkHtConfig(&$checks) + { + $status = true; + $help = ""; + if ((file_exists('config/.htconfig.php') && !is_writable('.htconfig.php')) || + (!file_exists('config/.htconfig.php') && !is_writable('.'))) { + + $status = false; + $help = L10n::t('The web installer needs to be able to create a file called ".htconfig.php" in the "config/" folder of your web server and it is unable to do so.') .EOL; + $help .= L10n::t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.').EOL; + $help .= L10n::t('At the end of this procedure, we will give you a text to save in a file named .htconfig.php in your Friendica "config/" folder.').EOL; + $help .= L10n::t('You can alternatively skip this procedure and perform a manual installation. Please see the file "INSTALL.txt" for instructions.').EOL; + } + + self::addCheck($checks, L10n::t('config/.htconfig.php is writable'), $status, false, $help); + + } + + public static function checkSmarty3(&$checks) + { + $status = true; + $help = ""; + if (!is_writable('view/smarty3')) { + + $status = false; + $help = L10n::t('Friendica uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') .EOL; + $help .= L10n::t('In order to store these compiled templates, the web server needs to have write access to the directory view/smarty3/ under the Friendica top level folder.').EOL; + $help .= L10n::t("Please ensure that the user that your web server runs as \x28e.g. www-data\x29 has write access to this folder.").EOL; + $help .= L10n::t("Note: as a security measure, you should give the web server write access to view/smarty3/ only--not the template files \x28.tpl\x29 that it contains.").EOL; + } + + self::addCheck($checks, L10n::t('view/smarty3 is writable'), $status, true, $help); + + } + + public static function checkHtAccess(&$checks) + { + $status = true; + $help = ""; + if (function_exists('curl_init')) { + $test = Network::fetchUrl(System::baseUrl()."/install/testrewrite"); + + if ($test != "ok") { + $test = Network::fetchUrl(normalise_link(System::baseUrl()."/install/testrewrite")); + } + + if ($test != "ok") { + $status = false; + $help = L10n::t('Url rewrite in .htaccess is not working. Check your server configuration.'); + } + self::addCheck($checks, L10n::t('Url rewrite is working'), $status, true, $help); + } else { + // cannot check modrewrite if libcurl is not installed + /// @TODO Maybe issue warning here? + } + } + + public static function checkImagik(&$checks) + { + $imagick = false; + $gif = false; + + if (class_exists('Imagick')) { + $imagick = true; + $supported = Image::supportedTypes(); + if (array_key_exists('image/gif', $supported)) { + $gif = true; + } + } + if ($imagick == false) { + self::addCheck($checks, L10n::t('ImageMagick PHP extension is not installed'), $imagick, false, ""); + } else { + self::addCheck($checks, L10n::t('ImageMagick PHP extension is installed'), $imagick, false, ""); + if ($imagick) { + self::addCheck($checks, L10n::t('ImageMagick supports GIF'), $gif, false, ""); + } + } + } + + public static function loadDatabase() + { + $errors = DBStructure::update(false, true, true); + + return $errors; + } +} \ No newline at end of file From d5b68cd146c722706663ffd30562668dbdcea4b1 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Fri, 27 Apr 2018 21:07:04 +0200 Subject: [PATCH 2/7] Add a App-Mode with defined constants - Normal Mode = 0 - Install Mode = 1 - Maintenance Mode = 2 Moved Install-Mode check to class `App` Replaced all maintenance and install checks with $a->mode checks --- include/dba.php | 1 + include/text.php | 4 ++-- index.php | 24 ++++++++---------------- src/App.php | 14 +++++++++++++- src/Core/Install.php | 6 +++--- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/include/dba.php b/include/dba.php index b24d9b409d..1fe4cab400 100644 --- a/include/dba.php +++ b/include/dba.php @@ -93,6 +93,7 @@ class dba { // No suitable SQL driver was found. if (!self::$connected) { + self::$driver = null; self::$db = null; } $a->save_timestamp($stamp1, "network"); diff --git a/include/text.php b/include/text.php index 796acffcef..23ce0f3d78 100644 --- a/include/text.php +++ b/include/text.php @@ -637,7 +637,7 @@ function logger($msg, $level = 0) { // turn off logger in install mode if ( - $a->install_mode + $a->mode == APP_MODE_INSTALL || !dba::$connected ) { return; @@ -709,7 +709,7 @@ function dlogger($msg, $level = 0) { // turn off logger in install mode if ( - $a->install_mode + $a->mode == APP_MODE_INSTALL || !dba::$connected ) { return; diff --git a/index.php b/index.php index 2f23ea791a..d45704c937 100644 --- a/index.php +++ b/index.php @@ -31,16 +31,8 @@ BaseObject::setApp($a); // The value is set to "true" by default in boot.php $a->backend = false; -/** - * Load the configuration file which contains our DB credentials. - * Ignore errors. If the file doesn't exist or is empty, we are running in - * installation mode. - */ - -$install = ((file_exists('.htconfig.php') && filesize('.htconfig.php')) ? false : true); - -// Only load config if found, don't surpress errors -if (!$install) { +// Only load config if found, don't suppress errors +if (!$a->mode == APP_MODE_INSTALL) { include ".htconfig.php"; } @@ -50,7 +42,7 @@ if (!$install) { require_once "include/dba.php"; -if (!$install) { +if (!$a->mode == APP_MODE_INSTALL) { $result = dba::connect($db_host, $db_user, $db_pass, $db_data); unset($db_host, $db_user, $db_pass, $db_data); @@ -85,7 +77,7 @@ if (!$install) { Addon::loadHooks(); Addon::callHooks('init_1'); - $maintenance = Config::get('system', 'maintenance'); + $a->mode = ((Config::get('system', 'maintenance')) ? APP_MODE_MAINTENANCE : APP_MODE_NORMAL); } $lang = L10n::getBrowserLanguage(); @@ -129,7 +121,7 @@ if ((x($_SESSION, 'language')) && ($_SESSION['language'] !== $lang)) { L10n::loadTranslationTable($lang); } -if ((x($_GET, 'zrl')) && (!$install && !$maintenance)) { +if ((x($_GET, 'zrl')) && $a->mode == APP_MODE_NORMAL) { // Only continue when the given profile link seems valid // Valid profile links contain a path with "/profile/" and no query parameters if ((parse_url($_GET['zrl'], PHP_URL_QUERY) == "") @@ -181,9 +173,9 @@ $_SESSION['last_updated'] = defaults($_SESSION, 'last_updated', []); // in install mode, any url loads install module // but we need "view" module for stylesheet -if ($install && $a->module!="view") { +if ($a->mode == APP_MODE_INSTALL && $a->module!="view") { $a->module = 'install'; -} elseif ($maintenance && $a->module!="view") { +} elseif ($a->mode == APP_MODE_MAINTENANCE && $a->module!="view") { $a->module = 'maintenance'; } else { check_url($a); @@ -342,7 +334,7 @@ if (! x($a->page, 'content')) { $a->page['content'] = ''; } -if (!$install && !$maintenance) { +if ($a->mode == APP_MODE_NORMAL) { Addon::callHooks('page_content_top', $a->page['content']); } diff --git a/src/App.php b/src/App.php index 5ff7eab04d..4ad3f62b63 100644 --- a/src/App.php +++ b/src/App.php @@ -14,6 +14,10 @@ use Detection\MobileDetect; use Exception; +define ('APP_MODE_NORMAL', 0); +define ('APP_MODE_INSTALL', 1); +define ('APP_MODE_MAINTENANCE', 2); + require_once 'boot.php'; require_once 'include/text.php'; @@ -52,7 +56,7 @@ class App public $argv; public $argc; public $module; - public $install_mode = false; + public $mode = APP_MODE_NORMAL; public $pager; public $strings; public $basepath; @@ -289,6 +293,14 @@ class App // Register template engines $this->register_template_engine('Friendica\Render\FriendicaSmartyEngine'); + /** + * Load the configuration file which contains our DB credentials. + * Ignore errors. If the file doesn't exist or is empty, we are running in + * installation mode. * + */ + $this->mode = ((file_exists('.htconfig.php') && filesize('.htconfig.php')) ? APP_MODE_NORMAL : APP_MODE_INSTALL); + + self::$a = $this; } diff --git a/src/Core/Install.php b/src/Core/Install.php index 25ecb02b4f..56e423595d 100644 --- a/src/Core/Install.php +++ b/src/Core/Install.php @@ -17,8 +17,8 @@ use DOMDocument; */ class Install extends BaseObject { - public static function setInstallMode($mode = true) { - self::getApp()->install_mode = $mode; + public static function setInstallMode() { + self::getApp()->mode = APP_MODE_INSTALL; } public static function check($phpath = 'php') @@ -328,4 +328,4 @@ class Install extends BaseObject return $errors; } -} \ No newline at end of file +} From a97ad9dc422556d0679ff066fb378570183ed57e Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 28 Apr 2018 12:36:40 +0200 Subject: [PATCH 3/7] Add Install Mode (Part 2) - Added constants to class `App` - Added global App-Mode to `dba:connect()` instead parameter `$install` --- include/dba.php | 5 ++-- include/text.php | 4 ++-- index.php | 14 +++++------ mod/install.php | 4 ++-- src/App.php | 27 +++++++++++++++++----- src/Core/Console/AutomaticInstallation.php | 2 +- src/Core/Install.php | 3 ++- 7 files changed, 38 insertions(+), 21 deletions(-) diff --git a/include/dba.php b/include/dba.php index 1fe4cab400..6446bb444b 100644 --- a/include/dba.php +++ b/include/dba.php @@ -1,5 +1,6 @@ mode == App::MODE_INSTALL) { // server has to be a non-empty string that is not 'localhost' and not an IP if (strlen($server) && ($server !== 'localhost') && filter_var($server, FILTER_VALIDATE_IP) === false) { if (! dns_get_record($server, DNS_A + DNS_CNAME)) { diff --git a/include/text.php b/include/text.php index 23ce0f3d78..a37d5815d5 100644 --- a/include/text.php +++ b/include/text.php @@ -637,7 +637,7 @@ function logger($msg, $level = 0) { // turn off logger in install mode if ( - $a->mode == APP_MODE_INSTALL + $a->mode == App::MODE_INSTALL || !dba::$connected ) { return; @@ -709,7 +709,7 @@ function dlogger($msg, $level = 0) { // turn off logger in install mode if ( - $a->mode == APP_MODE_INSTALL + $a->mode == App::MODE_INSTALL || !dba::$connected ) { return; diff --git a/index.php b/index.php index d45704c937..717ae41c0e 100644 --- a/index.php +++ b/index.php @@ -32,7 +32,7 @@ BaseObject::setApp($a); $a->backend = false; // Only load config if found, don't suppress errors -if (!$a->mode == APP_MODE_INSTALL) { +if (!$a->mode == App::MODE_INSTALL) { include ".htconfig.php"; } @@ -42,7 +42,7 @@ if (!$a->mode == APP_MODE_INSTALL) { require_once "include/dba.php"; -if (!$a->mode == APP_MODE_INSTALL) { +if (!$a->mode == App::MODE_INSTALL) { $result = dba::connect($db_host, $db_user, $db_pass, $db_data); unset($db_host, $db_user, $db_pass, $db_data); @@ -77,7 +77,7 @@ if (!$a->mode == APP_MODE_INSTALL) { Addon::loadHooks(); Addon::callHooks('init_1'); - $a->mode = ((Config::get('system', 'maintenance')) ? APP_MODE_MAINTENANCE : APP_MODE_NORMAL); + $a->checkMaintenanceMode(); } $lang = L10n::getBrowserLanguage(); @@ -121,7 +121,7 @@ if ((x($_SESSION, 'language')) && ($_SESSION['language'] !== $lang)) { L10n::loadTranslationTable($lang); } -if ((x($_GET, 'zrl')) && $a->mode == APP_MODE_NORMAL) { +if ((x($_GET, 'zrl')) && $a->mode == App::MODE_NORMAL) { // Only continue when the given profile link seems valid // Valid profile links contain a path with "/profile/" and no query parameters if ((parse_url($_GET['zrl'], PHP_URL_QUERY) == "") @@ -173,9 +173,9 @@ $_SESSION['last_updated'] = defaults($_SESSION, 'last_updated', []); // in install mode, any url loads install module // but we need "view" module for stylesheet -if ($a->mode == APP_MODE_INSTALL && $a->module!="view") { +if ($a->mode == App::MODE_INSTALL && $a->module!="view") { $a->module = 'install'; -} elseif ($a->mode == APP_MODE_MAINTENANCE && $a->module!="view") { +} elseif ($a->mode == App::MODE_MAINTENANCE && $a->module!="view") { $a->module = 'maintenance'; } else { check_url($a); @@ -334,7 +334,7 @@ if (! x($a->page, 'content')) { $a->page['content'] = ''; } -if ($a->mode == APP_MODE_NORMAL) { +if ($a->mode == App::MODE_NORMAL) { Addon::callHooks('page_content_top', $a->page['content']); } diff --git a/mod/install.php b/mod/install.php index 3b09da6e4a..4596f9a251 100644 --- a/mod/install.php +++ b/mod/install.php @@ -51,7 +51,7 @@ function install_post(App $a) { $phpath = notags(trim($_POST['phpath'])); require_once("include/dba.php"); - if (!dba::connect($dbhost, $dbuser, $dbpass, $dbdata, true)) { + if (!dba::connect($dbhost, $dbuser, $dbpass, $dbdata)) { $a->data['db_conn_failed'] = true; } @@ -70,7 +70,7 @@ function install_post(App $a) { $rino = 1; // connect to db - dba::connect($dbhost, $dbuser, $dbpass, $dbdata, true); + dba::connect($dbhost, $dbuser, $dbpass, $dbdata); Install::install($urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $phpath, $timezone, $language, $adminmail, $rino); diff --git a/src/App.php b/src/App.php index 4ad3f62b63..b285218f48 100644 --- a/src/App.php +++ b/src/App.php @@ -14,10 +14,6 @@ use Detection\MobileDetect; use Exception; -define ('APP_MODE_NORMAL', 0); -define ('APP_MODE_INSTALL', 1); -define ('APP_MODE_MAINTENANCE', 2); - require_once 'boot.php'; require_once 'include/text.php'; @@ -36,6 +32,10 @@ require_once 'include/text.php'; */ class App { + const MODE_NORMAL = 0; + const MODE_INSTALL = 1; + const MODE_MAINTENANCE = 2; + public $module_loaded = false; public $module_class = null; public $query_string; @@ -56,7 +56,7 @@ class App public $argv; public $argc; public $module; - public $mode = APP_MODE_NORMAL; + public $mode = App::MODE_NORMAL; public $pager; public $strings; public $basepath; @@ -298,7 +298,7 @@ class App * Ignore errors. If the file doesn't exist or is empty, we are running in * installation mode. * */ - $this->mode = ((file_exists('.htconfig.php') && filesize('.htconfig.php')) ? APP_MODE_NORMAL : APP_MODE_INSTALL); + $this->mode = ((file_exists('.htconfig.php') && filesize('.htconfig.php')) ? App::MODE_NORMAL : App::MODE_INSTALL); self::$a = $this; @@ -1080,4 +1080,19 @@ class App return $sender_email; } + + /** + * @note Checks, if the App is in the Maintenance-Mode + * + * @return boolean + */ + public function checkMaintenanceMode() + { + if (Config::get('system', 'maintenance')) { + $this->mode = App::MODE_MAINTENANCE; + return true; + } + + return false; + } } diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php index ff27782302..e08491b805 100644 --- a/src/Core/Console/AutomaticInstallation.php +++ b/src/Core/Console/AutomaticInstallation.php @@ -137,7 +137,7 @@ HELP; ); - if (!dba::connect($db_host, $db_user, $db_pass, $db_data, true)) { + if (!dba::connect($db_host, $db_user, $db_pass, $db_data)) { $result['status'] = false; $result['help'] = 'Failed, please check your MySQL settings and credentials.'; } diff --git a/src/Core/Install.php b/src/Core/Install.php index 56e423595d..ad600a70a2 100644 --- a/src/Core/Install.php +++ b/src/Core/Install.php @@ -5,6 +5,7 @@ namespace Friendica\Core; use Friendica\BaseObject; +use Friendica\App; use Friendica\Database\DBStructure; use Friendica\Object\Image; use Friendica\Util\Network; @@ -18,7 +19,7 @@ use DOMDocument; class Install extends BaseObject { public static function setInstallMode() { - self::getApp()->mode = APP_MODE_INSTALL; + self::getApp()->mode = App::MODE_INSTALL; } public static function check($phpath = 'php') From 41c6d63052cee87a79d47e1b41592e13aed0d608 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 28 Apr 2018 15:15:54 +0200 Subject: [PATCH 4/7] Add Install Mode - merged `friendica/develop` to `nupplaPhil/install_mode` - content merged `mod/install.php` to `src/Class/` --- mod/install.php | 28 +--------------- src/Core/Install.php | 76 ++++++++++++++++++++++++-------------------- 2 files changed, 43 insertions(+), 61 deletions(-) diff --git a/mod/install.php b/mod/install.php index 323cb31fdd..f8a0fd16fe 100644 --- a/mod/install.php +++ b/mod/install.php @@ -140,37 +140,11 @@ function install_content(App $a) { switch ($install_wizard_pass) { case 1: { // System check - - $checks = []; - - check_funcs($checks); - - check_imagik($checks); - - check_htconfig($checks); - - check_smarty3($checks); - - check_keys($checks); - if (x($_POST, 'phpath')) { $phpath = notags(trim($_POST['phpath'])); } - check_php($phpath, $checks); - - check_htaccess($checks); - - /// @TODO Maybe move this out? - function check_passed($v, $c) { - if ($c['required']) { - $v = $v && $c['status']; - } - return $v; - } - $checkspassed = array_reduce($checks, "check_passed", true); - - + list($checks, $checkspassed) = Install::check($phpath); $tpl = get_markup_template('install_checks.tpl'); $o .= replace_macros($tpl, [ diff --git a/src/Core/Install.php b/src/Core/Install.php index ad600a70a2..8dd354eb91 100644 --- a/src/Core/Install.php +++ b/src/Core/Install.php @@ -18,7 +18,8 @@ use DOMDocument; */ class Install extends BaseObject { - public static function setInstallMode() { + public static function setInstallMode() + { self::getApp()->mode = App::MODE_INSTALL; } @@ -69,7 +70,7 @@ class Install extends BaseObject ]); - $result = file_put_contents('config/.htconfig.php', $txt); + $result = file_put_contents('.htconfig.php', $txt); if (! $result) { self::getApp()->data['txt'] = $txt; } @@ -96,7 +97,8 @@ class Install extends BaseObject 'title' => $title, 'status' => $status, 'required' => $required, - 'help' => $help, + 'help' => $help, + 'error_msg' => $error_msg, ]; } @@ -111,7 +113,7 @@ class Install extends BaseObject } $help = ""; if (!$passed) { - $help .= L10n::t('Could not find a command line version of PHP in the web server PATH.'). EOL; + $help .= L10n::t('Could not find a command line version of PHP in the web server PATH.') . EOL; $help .= L10n::t("If you don't have a command line version of PHP installed on your server, you will not be able to run the background processing. See 'Setup the worker'") . EOL; $help .= EOL . EOL; $tpl = get_markup_template('field_input.tpl'); @@ -126,12 +128,12 @@ class Install extends BaseObject if ($passed) { $cmd = "$phpath -v"; $result = trim(shell_exec($cmd)); - $passed2 = ( strpos($result, "(cli)") !== false); + $passed2 = (strpos($result, "(cli)") !== false); list($result) = explode("\n", $result); $help = ""; if (!$passed2) { - $help .= L10n::t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29"). EOL; - $help .= L10n::t('Found PHP version: ')."$result"; + $help .= L10n::t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29") . EOL; + $help .= L10n::t('Found PHP version: ') . "$result"; } self::addCheck($checks, L10n::t('PHP cli binary'), $passed2, true, $help); } @@ -144,7 +146,7 @@ class Install extends BaseObject $passed3 = $result == $str; $help = ""; if (!$passed3) { - $help .= L10n::t('The command line version of PHP on your system does not have "register_argc_argv" enabled.'). EOL; + $help .= L10n::t('The command line version of PHP on your system does not have "register_argc_argv" enabled.') . EOL; $help .= L10n::t('This is required for message delivery to work.'); } self::addCheck($checks, L10n::t('PHP register_argc_argv'), $passed3, true, $help); @@ -162,16 +164,16 @@ class Install extends BaseObject if (function_exists('openssl_pkey_new')) { $res = openssl_pkey_new([ - 'digest_alg' => 'sha1', + 'digest_alg' => 'sha1', 'private_key_bits' => 4096, - 'encrypt_key' => false + 'encrypt_key' => false ]); } // Get private key - if (! $res) { - $help .= L10n::t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys'). EOL; + if (!$res) { + $help .= L10n::t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys') . EOL; $help .= L10n::t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".'); } self::addCheck($checks, L10n::t('Generate encryption keys'), $res, true, $help); @@ -199,19 +201,19 @@ class Install extends BaseObject } } - if (! function_exists('curl_init')) { + if (!function_exists('curl_init')) { $ck_funcs[0]['status'] = false; $ck_funcs[0]['help'] = L10n::t('Error: libCURL PHP module required but not installed.'); } - if (! function_exists('imagecreatefromjpeg')) { + if (!function_exists('imagecreatefromjpeg')) { $ck_funcs[1]['status'] = false; $ck_funcs[1]['help'] = L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.'); } - if (! function_exists('openssl_public_encrypt')) { + if (!function_exists('openssl_public_encrypt')) { $ck_funcs[2]['status'] = false; $ck_funcs[2]['help'] = L10n::t('Error: openssl PHP module required but not installed.'); } - if (! function_exists('mysqli_connect') && !class_exists('pdo')) { + if (!function_exists('mysqli_connect') && !class_exists('pdo')) { $ck_funcs[3]['status'] = false; $ck_funcs[3]['help'] = L10n::t('Error: PDO or MySQLi PHP module required but not installed.'); } @@ -219,15 +221,15 @@ class Install extends BaseObject $ck_funcs[3]['status'] = false; $ck_funcs[3]['help'] = L10n::t('Error: The MySQL driver for PDO is not installed.'); } - if (! function_exists('mb_strlen')) { + if (!function_exists('mb_strlen')) { $ck_funcs[4]['status'] = false; $ck_funcs[4]['help'] = L10n::t('Error: mb_string PHP module required but not installed.'); } - if (! function_exists('iconv_strlen')) { + if (!function_exists('iconv_strlen')) { $ck_funcs[6]['status'] = false; $ck_funcs[6]['help'] = L10n::t('Error: iconv PHP module required but not installed.'); } - if (! function_exists('posix_kill')) { + if (!function_exists('posix_kill')) { $ck_funcs[7]['status'] = false; $ck_funcs[7]['help'] = L10n::t('Error: POSIX PHP module required but not installed.'); } @@ -248,17 +250,17 @@ class Install extends BaseObject { $status = true; $help = ""; - if ((file_exists('config/.htconfig.php') && !is_writable('.htconfig.php')) || - (!file_exists('config/.htconfig.php') && !is_writable('.'))) { + if ((file_exists('.htconfig.php') && !is_writable('.htconfig.php')) || + (!file_exists('.htconfig.php') && !is_writable('.'))) { $status = false; - $help = L10n::t('The web installer needs to be able to create a file called ".htconfig.php" in the "config/" folder of your web server and it is unable to do so.') .EOL; - $help .= L10n::t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.').EOL; - $help .= L10n::t('At the end of this procedure, we will give you a text to save in a file named .htconfig.php in your Friendica "config/" folder.').EOL; - $help .= L10n::t('You can alternatively skip this procedure and perform a manual installation. Please see the file "INSTALL.txt" for instructions.').EOL; + $help = L10n::t('The web installer needs to be able to create a file called ".htconfig.php" in the top folder of your web server and it is unable to do so.') . EOL; + $help .= L10n::t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.') . EOL; + $help .= L10n::t('At the end of this procedure, we will give you a text to save in a file named .htconfig.php in your Friendica top folder.') . EOL; + $help .= L10n::t('You can alternatively skip this procedure and perform a manual installation. Please see the file "INSTALL.txt" for instructions.') . EOL; } - self::addCheck($checks, L10n::t('config/.htconfig.php is writable'), $status, false, $help); + self::addCheck($checks, L10n::t('.htconfig.php is writable'), $status, false, $help); } @@ -269,10 +271,10 @@ class Install extends BaseObject if (!is_writable('view/smarty3')) { $status = false; - $help = L10n::t('Friendica uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') .EOL; - $help .= L10n::t('In order to store these compiled templates, the web server needs to have write access to the directory view/smarty3/ under the Friendica top level folder.').EOL; - $help .= L10n::t("Please ensure that the user that your web server runs as \x28e.g. www-data\x29 has write access to this folder.").EOL; - $help .= L10n::t("Note: as a security measure, you should give the web server write access to view/smarty3/ only--not the template files \x28.tpl\x29 that it contains.").EOL; + $help = L10n::t('Friendica uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') . EOL; + $help .= L10n::t('In order to store these compiled templates, the web server needs to have write access to the directory view/smarty3/ under the Friendica top level folder.') . EOL; + $help .= L10n::t("Please ensure that the user that your web server runs as \x28e.g. www-data\x29 has write access to this folder.") . EOL; + $help .= L10n::t("Note: as a security measure, you should give the web server write access to view/smarty3/ only--not the template files \x28.tpl\x29 that it contains.") . EOL; } self::addCheck($checks, L10n::t('view/smarty3 is writable'), $status, true, $help); @@ -283,16 +285,22 @@ class Install extends BaseObject { $status = true; $help = ""; + $error_msg = ""; if (function_exists('curl_init')) { - $test = Network::fetchUrl(System::baseUrl()."/install/testrewrite"); + $test = Network::fetchUrlFull(System::baseUrl() . "/install/testrewrite"); - if ($test != "ok") { - $test = Network::fetchUrl(normalise_link(System::baseUrl()."/install/testrewrite")); + $url = normalise_link(System::baseUrl() . "/install/testrewrite"); + if ($test['body'] != "ok") { + $test = Network::fetchUrlFull($url); } - if ($test != "ok") { + if ($test['body'] != "ok") { $status = false; $help = L10n::t('Url rewrite in .htaccess is not working. Check your server configuration.'); + $error_msg = []; + $error_msg['head'] = L10n::t('Error message from Curl when fetching'); + $error_msg['url'] = $test['redirect_url']; + $error_msg['msg'] = $test['error']; } self::addCheck($checks, L10n::t('Url rewrite is working'), $status, true, $help); } else { From 8815d077656aafa78b33bc15722f25dacb18f61e Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 28 Apr 2018 17:06:08 +0200 Subject: [PATCH 5/7] Add Install Mode - fixed mistake --- mod/install.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/install.php b/mod/install.php index f8a0fd16fe..4596f9a251 100644 --- a/mod/install.php +++ b/mod/install.php @@ -51,7 +51,7 @@ function install_post(App $a) { $phpath = notags(trim($_POST['phpath'])); require_once("include/dba.php"); - if (!dba::connect($dbhost, $dbuser, $dbpass, $dbdata, true)) { + if (!dba::connect($dbhost, $dbuser, $dbpass, $dbdata)) { $a->data['db_conn_failed'] = true; } From 6cb277b0bbc738c5adcbb3fe1d296f04fb4cce5e Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 29 Apr 2018 18:11:24 +0200 Subject: [PATCH 6/7] Add Install Mode - added PHP docBlock to methods - increased code quality --- src/Core/Console/AutomaticInstallation.php | 5 +- src/Core/Install.php | 133 +++++++++++++++++---- 2 files changed, 114 insertions(+), 24 deletions(-) diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php index e08491b805..e888d5a490 100644 --- a/src/Core/Console/AutomaticInstallation.php +++ b/src/Core/Console/AutomaticInstallation.php @@ -8,6 +8,7 @@ use Friendica\App; use Friendica\Core\Install; require_once 'mod/install.php'; +require_once 'include/dba.php'; class AutomaticInstallation extends Console { @@ -76,7 +77,7 @@ HELP; // Install database $this->out("Inserting data into database...\n"); - $checkResults['data'] = Install::loadDatabase(); + $checkResults['data'] = Install::installDatabaseStructure(); if ($checkResults['data'] !== '') { throw new \RuntimeException("ERROR: DB Database creation error. Is the DB empty?\n"); @@ -104,7 +105,7 @@ HELP; $checks = []; Install::checkFunctions($checks); - Install::checkImagik($checks); + Install::checkImagick($checks); Install::checkHtConfig($checks); Install::checkSmarty3($checks); Install::checkKeys($checks); diff --git a/src/Core/Install.php b/src/Core/Install.php index 8dd354eb91..f23254f465 100644 --- a/src/Core/Install.php +++ b/src/Core/Install.php @@ -14,22 +14,33 @@ use Exception; use DOMDocument; /** - * @brief Contains the class with install relevant stuff * + * Contains methods for installation purpose of Friendica */ class Install extends BaseObject { + /** + * Sets the install-mode for further methods + */ public static function setInstallMode() { self::getApp()->mode = App::MODE_INSTALL; } + /** + * Checks the current installation environment. There are optional and mandatory checks. + * + * @param string $phpath Optional path to the PHP binary (Default is 'php') + * + * @return array First element is a list of all checks and their results, + * the second element is a list of passed checks + */ public static function check($phpath = 'php') { $checks = []; self::checkFunctions($checks); - self::checkImagik($checks); + self::checkImagick($checks); self::checkHtConfig($checks); @@ -53,6 +64,22 @@ class Install extends BaseObject return array($checks, $checkspassed); } + /** + * Executes the installation of Friendica in the given environment. + * - Creates `.htconfig.php` + * - Installs Database Structure + * + * @param string $urlpath Path based on the URL of Friendica (e.g. '/friendica') + * @param string $dbhost Hostname/IP of the Friendica Database + * @param string $dbuser Username of the Database connection credentials + * @param string $dbpass Password of the Database connection credentials + * @param string $dbdata Name of the Database + * @param string $phpath Path to the PHP-Binary (e.g. 'php' or '/usr/bin/php') + * @param string $timezone Timezone of the Friendica Installaton (e.g. 'Europe/Berlin') + * @param string $language 2-letter ISO 639-1 code (eg. 'en') + * @param string $adminmail Mail-Adress of the administrator + * @param int $rino Rino-enabled (1 = true, 0 = false) + */ public static function install($urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $phpath, $timezone, $language, $adminmail, $rino = 1) { $tpl = get_markup_template('htconfig.tpl'); @@ -69,13 +96,12 @@ class Install extends BaseObject '$rino' => $rino ]); - $result = file_put_contents('.htconfig.php', $txt); if (! $result) { self::getApp()->data['txt'] = $txt; } - $errors = self::loadDatabase(); + $errors = self::installDatabaseStructure(); if ($errors) { self::getApp()->data['db_failed'] = $errors; @@ -85,13 +111,16 @@ class Install extends BaseObject } /** - * checks : array passed to template - * title : string - * status : boolean - * required : boolean - * help : string optional + * Adds new checks to the array $checks + * + * @param array $checks The list of all checks (by-ref parameter!) + * @param string $title The title of the current check + * @param bool $status 1 = check passed, 0 = check not passed + * @param bool $required 1 = check is mandatory, 0 = check is optional + * @param string $help A help-string for the current check + * @param string $error_msg Optional. A error message, if the current check failed */ - private static function addCheck(&$checks, $title, $status, $required, $help) + private static function addCheck(&$checks, $title, $status, $required, $help, $error_msg = "") { $checks[] = [ 'title' => $title, @@ -102,6 +131,18 @@ class Install extends BaseObject ]; } + /** + * PHP Check + * + * Checks the PHP environment. + * + * - Checks if a PHP binary is available + * - Checks if it is the CLI version + * - Checks if "register_argc_argv" is enabled + * + * @param string $phpath Optional. The Path to the PHP-Binary + * @param array $checks The list of all checks (by-ref parameter!) + */ public static function checkPHP(&$phpath, &$checks) { $passed = $passed2 = $passed3 = false; @@ -138,7 +179,6 @@ class Install extends BaseObject self::addCheck($checks, L10n::t('PHP cli binary'), $passed2, true, $help); } - if ($passed2) { $str = autoname(8); $cmd = "$phpath testargs.php $str"; @@ -151,15 +191,20 @@ class Install extends BaseObject } self::addCheck($checks, L10n::t('PHP register_argc_argv'), $passed3, true, $help); } - - } + /** + * OpenSSL Check + * + * Checks the OpenSSL Environment + * + * - Checks, if the command "openssl_pkey_new" is available + * + * @param array $checks The list of all checks (by-ref parameter!) + */ public static function checkKeys(&$checks) { - $help = ''; - $res = false; if (function_exists('openssl_pkey_new')) { @@ -171,16 +216,28 @@ class Install extends BaseObject } // Get private key - if (!$res) { $help .= L10n::t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys') . EOL; $help .= L10n::t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".'); } self::addCheck($checks, L10n::t('Generate encryption keys'), $res, true, $help); - } - + /** + * PHP functions Check + * + * Checks the following PHP functions + * - libCurl + * - GD Graphics + * - OpenSSL + * - PDO or MySQLi + * - mb_string + * - XML + * - iconv + * - POSIX + * + * @param array $checks The list of all checks (by-ref parameter!) + */ public static function checkFunctions(&$checks) { $ck_funcs = []; @@ -245,7 +302,13 @@ class Install extends BaseObject } } - + /** + * ".htconfig.php" - Check + * + * Checks if it's possible to create the ".htconfig.php" + * + * @param array $checks The list of all checks (by-ref parameter!) + */ public static function checkHtConfig(&$checks) { $status = true; @@ -264,6 +327,13 @@ class Install extends BaseObject } + /** + * Smarty3 Template Check + * + * Checks, if the directory of Smarty3 is writable + * + * @param array $checks The list of all checks (by-ref parameter!) + */ public static function checkSmarty3(&$checks) { $status = true; @@ -281,6 +351,13 @@ class Install extends BaseObject } + /** + * ".htaccess" - Check + * + * Checks, if "url_rewrite" is enabled in the ".htaccess" file + * + * @param array $checks The list of all checks (by-ref parameter!) + */ public static function checkHtAccess(&$checks) { $status = true; @@ -302,14 +379,21 @@ class Install extends BaseObject $error_msg['url'] = $test['redirect_url']; $error_msg['msg'] = $test['error']; } - self::addCheck($checks, L10n::t('Url rewrite is working'), $status, true, $help); + self::addCheck($checks, L10n::t('Url rewrite is working'), $status, true, $help, $error_msg); } else { // cannot check modrewrite if libcurl is not installed /// @TODO Maybe issue warning here? } } - public static function checkImagik(&$checks) + /** + * Imagick Check + * + * Checks, if the imagick module is available + * + * @param array $checks The list of all checks (by-ref parameter!) + */ + public static function checkImagick(&$checks) { $imagick = false; $gif = false; @@ -331,7 +415,12 @@ class Install extends BaseObject } } - public static function loadDatabase() + /** + * Installs the Database structure + * + * @return string A possible error + */ + public static function installDatabaseStructure() { $errors = DBStructure::update(false, true, true); From da9ac7b879f787cdf1b76e5863734e592193bb75 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 29 Apr 2018 18:13:24 +0200 Subject: [PATCH 7/7] Add Install Mode - increased code quality --- src/Core/Install.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Core/Install.php b/src/Core/Install.php index f23254f465..4ebc663e80 100644 --- a/src/Core/Install.php +++ b/src/Core/Install.php @@ -348,7 +348,6 @@ class Install extends BaseObject } self::addCheck($checks, L10n::t('view/smarty3 is writable'), $status, true, $help); - } /**