* @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ use Froxlor\Database\Database; use Froxlor\FileDir; use Froxlor\Froxlor; use Froxlor\Install\Update; use Froxlor\Settings; if (!defined('_CRON_UPDATE')) { if (!defined('AREA') || (defined('AREA') && AREA != 'admin') || !isset($userinfo['loginname']) || (isset($userinfo['loginname']) && $userinfo['loginname'] == '')) { header('Location: ../../../../index.php'); exit(); } } // last 0.10.x release if (Froxlor::isFroxlorVersion('0.10.38.3')) { $update_to = '2.0.0-beta1'; Update::showUpdateStep("Updating from 0.10.38.3 to " . $update_to, false); Update::showUpdateStep("Removing unused table"); Database::query("DROP TABLE IF EXISTS `panel_sessions`;"); Database::query("DROP TABLE IF EXISTS `panel_languages`;"); Update::lastStepStatus(0); Update::showUpdateStep("Updating froxlor - theme"); Database::query("UPDATE `" . TABLE_PANEL_ADMINS . "` SET `theme` = 'Froxlor' WHERE `theme` <> 'Froxlor';"); Database::query("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `theme` = 'Froxlor' WHERE `theme` <> 'Froxlor';"); Settings::Set('panel.default_theme', 'Froxlor'); Update::lastStepStatus(0); Update::showUpdateStep("Creating new tables and fields"); Database::query("DROP TABLE IF EXISTS `panel_usercolumns`;"); $sql = "CREATE TABLE `panel_usercolumns` ( `adminid` int(11) NOT NULL default '0', `customerid` int(11) NOT NULL default '0', `section` varchar(500) NOT NULL default '', `columns` text NOT NULL, UNIQUE KEY `user_section` (`adminid`, `customerid`, `section`), KEY adminid (adminid), KEY customerid (customerid) ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;"; Database::query($sql); // new customer allowed_mysqlserver field Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ROW_FORMAT=DYNAMIC;"); Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE COLUMN `customernumber` `customernumber` varchar(100) NOT NULL default '';"); Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE COLUMN `allowed_phpconfigs` `allowed_phpconfigs` text NOT NULL;"); Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `allowed_mysqlserver` text NOT NULL;"); $has_customer_table_update_200 = true; // ftp_users adjustments Database::query("ALTER TABLE `" . TABLE_FTP_USERS . "` CHANGE COLUMN `password` `password` varchar(255) NOT NULL default '';"); Database::query("ALTER TABLE `" . TABLE_FTP_QUOTALIMITS . "` CHANGE COLUMN `name` `name` varchar(255) default NULL;"); Database::query("ALTER TABLE `" . TABLE_FTP_QUOTATALLIES . "` CHANGE COLUMN `name` `name` varchar(255) default NULL;"); // mail_users adjustments Database::query("ALTER TABLE `" . TABLE_MAIL_USERS . "` CHANGE COLUMN `password` `password` varchar(255) NOT NULL default '';"); Database::query("ALTER TABLE `" . TABLE_MAIL_USERS . "` CHANGE COLUMN `password_enc` `password_enc` varchar(255) NOT NULL default '';"); // drop domains_see_all field from panel_admins Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` DROP COLUMN `domains_see_all`;"); Update::lastStepStatus(0); Update::showUpdateStep("Checking for multiple mysql-servers to allow access to customers for existing databases"); $dbservers_stmt = Database::query(" SELECT `customerid`, GROUP_CONCAT(DISTINCT `dbserver` SEPARATOR ',') as allowed_mysqlserver FROM `" . TABLE_PANEL_DATABASES . "` GROUP BY `customerid`; "); $upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `allowed_mysqlserver` = :allowed_mysqlserver WHERE `customerid` = :customerid"); while ($dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC)) { if (isset($dbserver['allowed_mysqlserver']) && !empty($dbserver['allowed_mysqlserver'])) { $allowed_mysqlserver = json_encode(explode(",", $dbserver['allowed_mysqlserver'])); Database::pexecute($upd_stmt, ['allowed_mysql_server' => $allowed_mysqlserver, 'customerid' => $dbserver['customerid']]); } } Update::lastStepStatus(0); Update::showUpdateStep("Cleaning up old files"); $to_clean = array( "install/lib", "install/lng", "install/updates/froxlor/0.9", "install/updates/froxlor/0.10", "install/updates/preconfig/0.9", "install/updates/preconfig/0.10", "install/updates/preconfig.php", "templates/Sparkle", "lib/version.inc.php", "lng/czech.lng.php", "lng/dutch.lng.php", "lng/english.lng.php", "lng/french.lng.php", "lng/german.lng.php", "lng/italian.lng.php", "lng/lng_references.php", "lng/portugues.lng.php", "lng/swedish.lng.php", "scripts", ); $disabled = explode(',', ini_get('disable_functions')); $exec_allowed = !in_array('exec', $disabled); $del_list = ""; foreach ($to_clean as $filedir) { $complete_filedir = Froxlor::getInstallDir() . $filedir; if (file_exists($complete_filedir)) { if ($exec_allowed) { FileDir::safe_exec("rm -rf " . escapeshellarg($complete_filedir)); } else { $del_list .= "rm -rf " . escapeshellarg($complete_filedir) . PHP_EOL; } } } if ($exec_allowed) { Update::lastStepStatus(0); } else { if (empty($del_list)) { // none of the files existed Update::lastStepStatus(0); } else { Update::lastStepStatus(1, 'manual commands needed', 'Please run the following commands manually:
' . $del_list . '
'); } } Update::showUpdateStep("Adding new settings"); $panel_settings_mode = isset($_POST['panel_settings_mode']) ? (int)$_POST['panel_settings_mode'] : 0; Settings::AddNew("panel.settings_mode", $panel_settings_mode); $system_distribution = isset($_POST['system_distribution']) ? $_POST['system_distribution'] : 'bullseye'; Settings::AddNew("system.distribution", $system_distribution); Settings::AddNew("system.update_channel", 'stable'); Settings::AddNew("system.updatecheck_data", ''); Settings::AddNew("system.update_notify_last", $update_to); Settings::AddNew("panel.phpconfigs_hidesubdomains", '1'); Update::lastStepStatus(0); Update::showUpdateStep("Adjusting existing settings"); Settings::Set('system.passwordcryptfunc', PASSWORD_DEFAULT); // remap default-language $lang_map = [ 'Deutsch' => 'de', 'English' => 'en', 'Français' => 'fr', 'Português' => 'pt', 'Italiano' => 'it', 'Nederlands' => 'nl', 'Svenska' => 'se', 'Česká republika' => 'cz' ]; // update user default languages $upd_adm_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_ADMINS . "` SET `def_language` = :nv WHERE `def_language` = :ov"); $upd_cus_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `def_language` = :nv WHERE `def_language` = :ov"); foreach ($lang_map as $old_val => $new_val) { Database::pexecute($upd_adm_stmt, ['nv' => $new_val, 'ov' => $old_val]); Database::pexecute($upd_cus_stmt, ['nv' => $new_val, 'ov' => $old_val]); } Settings::Set('panel.standardlanguage', $lang_map[Settings::Get('panel_standardlanguage')] ?? 'en'); Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'system' AND `varname` = 'debug_cron'"); Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'system' AND `varname` = 'letsencryptcountrycode'"); Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'system' AND `varname` = 'letsencryptstate'"); Update::lastStepStatus(0); Update::showUpdateStep("Updating email account password-hashes"); Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$1$', '{MD5-CRYPT}$1$') WHERE SUBSTRING(`password_enc`, 1, 3) = '$1$'"); Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$5$', '{SHA256-CRYPT}$5$') WHERE SUBSTRING(`password_enc`, 1, 3) = '$5$'"); Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$6$', '{SHA512-CRYPT}$6$') WHERE SUBSTRING(`password_enc`, 1, 3) = '$6$'"); Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$2y$', '{BLF-CRYPT}$2y$') WHERE SUBSTRING(`password_enc`, 1, 4) = '$2y$'"); Update::lastStepStatus(0); Froxlor::updateToVersion($update_to); } if (Froxlor::isDatabaseVersion('202112310')) { Update::showUpdateStep("Adjusting traffic tool settings"); $traffic_tool = Settings::Get('system.awstats_enabled') == 1 ? 'awstats' : 'webalizer'; Settings::AddNew("system.traffictool", $traffic_tool); Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'system' AND `varname` = 'awstats_enabled'"); Update::lastStepStatus(0); Froxlor::updateToDbVersion('202211030'); } if (Froxlor::isDatabaseVersion('202211030')) { Update::showUpdateStep("Creating backward compatibility for cronjob"); $disabled = explode(',', ini_get('disable_functions')); $exec_allowed = !in_array('exec', $disabled); // check whether old files could be deleted in previous updates and if not, // user should run cron to regenerate cron.d-file manually as he will run // the other commands manually only after the update so this file would be deleted too if ($exec_allowed) { $complete_filedir = Froxlor::getInstallDir() . '/scripts'; mkdir($complete_filedir, 0750, true); $newCronBin = Froxlor::getInstallDir() . '/bin/froxlor-cli'; $compCron = <<
' . $cron_run_cmd . '
'); } Froxlor::updateToDbVersion('202212060'); } if (Froxlor::isFroxlorVersion('2.0.0-beta1')) { Update::showUpdateStep("Updating from 2.0.0-beta1 to 2.0.0", false); Froxlor::updateToVersion('2.0.0'); } if (Froxlor::isFroxlorVersion('2.0.0')) { Update::showUpdateStep("Updating from 2.0.0 to 2.0.1", false); if (!isset($has_customer_table_update_200)) { Update::showUpdateStep("Creating new tables and fields"); // new customer allowed_mysqlserver field Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE COLUMN `allowed_mysqlserver` `allowed_mysqlserver` text NOT NULL;"); Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE COLUMN `allowed_phpconfigs` `allowed_phpconfigs` text NOT NULL;"); Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE COLUMN `customernumber` `customernumber` varchar(100) NOT NULL default '';"); Update::lastStepStatus(0); } Froxlor::updateToVersion('2.0.1'); } if (Froxlor::isFroxlorVersion('2.0.1')) { Update::showUpdateStep("Updating from 2.0.1 to 2.0.2", false); Froxlor::updateToVersion('2.0.2'); } if (Froxlor::isFroxlorVersion('2.0.2')) { Update::showUpdateStep("Updating from 2.0.2 to 2.0.3", false); Froxlor::updateToVersion('2.0.3'); } if (Froxlor::isFroxlorVersion('2.0.3')) { Update::showUpdateStep("Updating from 2.0.3 to 2.0.4", false); $complete_filedir = Froxlor::getInstallDir() . '/scripts'; // check if compat. cronjob still exists (most likely didn't run successfully b/c of error from former 2.0 release) if (@file_exists($complete_filedir . '/froxlor_master_cronjob.php')) { Update::showUpdateStep("Adjusting backward compatibility for cronjob"); $disabled = explode(',', ini_get('disable_functions')); $exec_allowed = !in_array('exec', $disabled); if ($exec_allowed) { $newCronBin = Froxlor::getInstallDir() . '/bin/froxlor-cli'; $compCron = <<
' . $cron_run_cmd . '
'); } } Froxlor::updateToVersion('2.0.4'); } if (Froxlor::isFroxlorVersion('2.0.4')) { Update::showUpdateStep("Updating from 2.0.4 to 2.0.5", false); Froxlor::updateToVersion('2.0.5'); } if (Froxlor::isFroxlorVersion('2.0.5')) { Update::showUpdateStep("Updating from 2.0.5 to 2.0.6", false); Update::showUpdateStep("Updating possible missing email account password-hashes"); Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$1$', '{MD5-CRYPT}$1$') WHERE SUBSTRING(`password_enc`, 1, 3) = '$1$'"); Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$5$', '{SHA256-CRYPT}$5$') WHERE SUBSTRING(`password_enc`, 1, 3) = '$5$'"); Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$6$', '{SHA512-CRYPT}$6$') WHERE SUBSTRING(`password_enc`, 1, 3) = '$6$'"); Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$2y$', '{BLF-CRYPT}$2y$') WHERE SUBSTRING(`password_enc`, 1, 4) = '$2y$'"); Update::lastStepStatus(0); Froxlor::updateToVersion('2.0.6'); } if (Froxlor::isFroxlorVersion('2.0.6')) { Update::showUpdateStep("Updating from 2.0.6 to 2.0.7", false); Update::showUpdateStep("Correcting allowed_mysqlserver for customers"); Database::query("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `allowed_mysqlserver` = '[0]' WHERE `allowed_mysqlserver` = ''"); Update::lastStepStatus(0); Froxlor::updateToVersion('2.0.7'); } if (Froxlor::isDatabaseVersion('202212060')) { Update::showUpdateStep("Validating acme.sh challenge path"); $acmesh_challenge_dir = Settings::Get('system.letsencryptchallengepath'); $system_letsencryptchallengepath_upd = isset($_POST['system_letsencryptchallengepath_upd']) ? $_POST['system_letsencryptchallengepath_upd'] : $acmesh_challenge_dir; if ($acmesh_challenge_dir != $system_letsencryptchallengepath_upd) { Settings::Set('system.letsencryptchallengepath', $system_letsencryptchallengepath_upd); if ((int)Settings::Get('system.leenabled') == 1) { // create JSON string for --apply $dist = Settings::Get('system.distribution'); $webserver = Settings::Get('system.webserver'); if ($webserver == 'apache2') { $webserver = 'apache22'; if (Settings::Get('system.apache24')) { $webserver = 'apache24'; } } $apply_json = '{"http":"' . $webserver . '","dns":"x","smtp":"x","mail":"x","ftp":"x","distro":"' . $dist . '","system":[]}'; Update::lastStepStatus(1, 'manual commands needed', "Please reconfigure webserver service using
bin/froxlor-cli froxlor:config-services --apply='" . $apply_json . "'
" . '
or adjust the path manually in
' . Settings::Get('system.letsencryptacmeconf') . '
' . '

In case you already have certificates issued, run the following command to validate and correct the webroot used for renewal:
' . '
bin/froxlor-cli froxlor:validate-acme-webroot

' ); } else { Update::lastStepStatus(0); } } else { Update::lastStepStatus(0); } Froxlor::updateToDbVersion('202301120'); } if (Froxlor::isFroxlorVersion('2.0.7')) { Update::showUpdateStep("Updating from 2.0.7 to 2.0.8", false); // adjust file-logging to be set to froxlor/logs/ $logtypes = explode(',', Settings::Get('logger.logtypes')); if (in_array('file', $logtypes)) { Update::showUpdateStep("Adjusting froxlor logfile for system-logging to be stored in logs/froxlor.log"); Settings::Set('logger.logfile', 'froxlor.log'); Update::lastStepStatus(0); } Froxlor::updateToVersion('2.0.8'); } if (Froxlor::isDatabaseVersion('202301120')) { Update::showUpdateStep("Adding new setting for DNS resolver when using Let's Encrypt"); $system_le_domain_dnscheck_resolver = isset($_POST['system_le_domain_dnscheck_resolver']) ? $_POST['system_le_domain_dnscheck_resolver'] : '1.1.1.1'; Settings::AddNew("system.le_domain_dnscheck_resolver", $system_le_domain_dnscheck_resolver); Update::lastStepStatus(0); Froxlor::updateToDbVersion('202301180'); } if (Froxlor::isFroxlorVersion('2.0.8')) { Update::showUpdateStep("Updating from 2.0.8 to 2.0.9", false); Froxlor::updateToVersion('2.0.9'); } if (Froxlor::isFroxlorVersion('2.0.9')) { Update::showUpdateStep("Updating from 2.0.9 to 2.0.10", false); Froxlor::updateToVersion('2.0.10'); } if (Froxlor::isDatabaseVersion('202301180')) { Update::showUpdateStep("Adding new setting for 'Allow API access' default value for new customers"); Settings::AddNew("api.customer_default", "1"); Update::lastStepStatus(0); Froxlor::updateToDbVersion('202302030'); } if (Froxlor::isFroxlorVersion('2.0.10')) { Update::showUpdateStep("Updating from 2.0.10 to 2.0.11", false); Froxlor::updateToVersion('2.0.11'); } if (Froxlor::isFroxlorVersion('2.0.11')) { Update::showUpdateStep("Updating from 2.0.11 to 2.0.12", false); Froxlor::updateToVersion('2.0.12'); } if (Froxlor::isFroxlorVersion('2.0.12')) { Update::showUpdateStep("Updating from 2.0.12 to 2.0.13", false); Froxlor::updateToVersion('2.0.13'); } if (Froxlor::isDatabaseVersion('202302030')) { Update::showUpdateStep("Correcting language mapping of templates created pre 2.0.x"); // languages from 0.10.x $language_mapping_comp = [ 'de' => 'Deutsch', 'en' => 'English', 'fr' => 'Français', 'pt' => 'Português', 'it' => 'Italiano', 'nl' => 'Nederlands', 'se' => 'Svenska', 'cz' => 'Česká republika' ]; $upd_tpl_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_TEMPLATES . "` SET `language` = :iso WHERE `language` = :lng"); foreach ($language_mapping_comp as $iso => $lang) { Database::pexecute($upd_tpl_stmt, ['iso' => $iso, 'lng' => $lang]); } Update::lastStepStatus(0); Update::showUpdateStep("Enhancing ssl data table"); Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` CHANGE `expirationdate` `validtodate` datetime DEFAULT NULL;"); Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` ADD `validfromdate` datetime DEFAULT NULL AFTER `ssl_fullchain_file`;"); Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` ADD `issuer` varchar(255) NOT NULL default '' AFTER `validtodate`;"); Update::lastStepStatus(0); Update::showUpdateStep("Filling new ssl data fields with existing certificate data"); $crt_upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` SET `validfromdate` = :validfromdate, `issuer` = :issuer WHERE `id` = :id"); $crt_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`"); Database::pexecute($crt_stmt); while ($cert = $crt_stmt->fetch(\PDO::FETCH_ASSOC)) { $cert_content = openssl_x509_parse($cert['ssl_cert_file']); if (is_array($cert_content)) { $validfromdate = empty($cert_content['validFrom_time_t']) ? null : date("Y-m-d H:i:s", $cert_content['validFrom_time_t']); $issuer = $cert_content['issuer']['O'] ?? ""; Database::pexecute($crt_upd_stmt, ['validfromdate' => $validfromdate, 'issuer' => $issuer, 'id' => $cert['id']]); } } // clear possible user customized columns Database::query("DELETE FROM `" . TABLE_PANEL_USERCOLUMNS . "` WHERE `section` = 'sslcertificates_list'"); Update::lastStepStatus(0); Froxlor::updateToDbVersion('202303150'); } if (Froxlor::isFroxlorVersion('2.0.13')) { Update::showUpdateStep("Updating from 2.0.13 to 2.0.14", false); Froxlor::updateToVersion('2.0.14'); } if (Froxlor::isFroxlorVersion('2.0.14')) { Update::showUpdateStep("Updating from 2.0.14 to 2.0.15", false); Froxlor::updateToVersion('2.0.15'); } if (Froxlor::isDatabaseVersion('202303150')) { Update::showUpdateStep("Adding new request rate limit settings"); Settings::AddNew("system.req_limit_per_interval", "60"); Settings::AddNew("system.req_limit_interval", "60"); Update::lastStepStatus(0); Froxlor::updateToDbVersion('202304260'); } if (Froxlor::isFroxlorVersion('2.0.15')) { Update::showUpdateStep("Updating from 2.0.15 to 2.0.16", false); Froxlor::updateToVersion('2.0.16'); } if (Froxlor::isFroxlorVersion('2.0.16')) { Update::showUpdateStep("Updating from 2.0.16 to 2.0.17", false); Froxlor::updateToVersion('2.0.17'); } if (Froxlor::isFroxlorVersion('2.0.17')) { Update::showUpdateStep("Updating from 2.0.17 to 2.0.18", false); Froxlor::updateToVersion('2.0.18'); } if (Froxlor::isFroxlorVersion('2.0.18')) { Update::showUpdateStep("Updating from 2.0.18 to 2.0.19", false); Froxlor::updateToVersion('2.0.19'); } if (Froxlor::isFroxlorVersion('2.0.19')) { Update::showUpdateStep("Updating from 2.0.19 to 2.0.20", false); Froxlor::updateToVersion('2.0.20'); } if (Froxlor::isFroxlorVersion('2.0.20')) { Update::showUpdateStep("Updating from 2.0.20 to 2.0.21", false); Froxlor::updateToVersion('2.0.21'); } if (Froxlor::isFroxlorVersion('2.0.21')) { Update::showUpdateStep("Updating from 2.0.21 to 2.0.22", false); Froxlor::updateToVersion('2.0.22'); } if (Froxlor::isFroxlorVersion('2.0.22')) { Update::showUpdateStep("Updating from 2.0.22 to 2.0.23", false); Froxlor::updateToVersion('2.0.23'); }