diff --git a/actions/admin/settings/131.ssl.php b/actions/admin/settings/131.ssl.php index eee8d887..f23defe4 100644 --- a/actions/admin/settings/131.ssl.php +++ b/actions/admin/settings/131.ssl.php @@ -233,7 +233,7 @@ return array( 'save_method' => 'storeSettingField', 'advanced_mode' => true ), - 'system_disable_le_selfcheck' => array( + 'system_le_domain_dnscheck' => array( 'label' => $lng['serversettings']['le_domain_dnscheck'], 'settinggroup' => 'system', 'varname' => 'le_domain_dnscheck', diff --git a/admin_autoupdate.php b/admin_autoupdate.php index ddcea413..e4593905 100644 --- a/admin_autoupdate.php +++ b/admin_autoupdate.php @@ -29,20 +29,30 @@ define('UPDATE_URI', "https://version.froxlor.org/Froxlor/api/" . \Froxlor\Froxl define('RELEASE_URI', "https://autoupdate.froxlor.org/froxlor-{version}.zip"); define('CHECKSUM_URI', "https://autoupdate.froxlor.org/froxlor-{version}.zip.sha256"); -// check for archive-stuff -if (!extension_loaded('zip')) { - \Froxlor\UI\Response::redirectTo($filename, array( - 'page' => 'error', - 'errno' => 2 - )); -} +if ($page != 'error') { + // check for archive-stuff + if (!extension_loaded('zip')) { + \Froxlor\UI\Response::redirectTo($filename, array( + 'page' => 'error', + 'errno' => 2 + )); + } -// 0.11.x requires 7.4 at least -if (version_compare("7.4.0", PHP_VERSION, ">=")) { - \Froxlor\UI\Response::redirectTo($filename, array( - 'page' => 'error', - 'errno' => 10 - )); + // 0.11.x requires 7.4 at least + if (version_compare("7.4.0", PHP_VERSION, ">=")) { + \Froxlor\UI\Response::redirectTo($filename, array( + 'page' => 'error', + 'errno' => 10 + )); + } + + // check for webupdate to be enabled + if (\Froxlor\Settings::Config('enable_webupdate') != true) { + \Froxlor\UI\Response::redirectTo($filename, array( + 'page' => 'error', + 'errno' => 11 + )); + } } // display initial version check @@ -281,5 +291,6 @@ elseif ($page == 'error') { // 8 = could not extract archive // 9 = checksum mismatch // 10 = handle(@file_get_contents('php://input')); + echo (new Api)->formatMiddleware(@file_get_contents('php://input'))->handle(); } catch (Exception $e) { echo \Froxlor\Api\Response::jsonErrorResponse($e->getMessage(), $e->getCode()); } diff --git a/lib/Froxlor/Api/Api.php b/lib/Froxlor/Api/Api.php index 53655b07..8b470f94 100644 --- a/lib/Froxlor/Api/Api.php +++ b/lib/Froxlor/Api/Api.php @@ -1,4 +1,5 @@ headers = getallheaders(); + protected $request = null; - // set header for the response - header("Accept: application/json"); - header("Content-Type: application/json"); + /** + * Api constructor. + * + * @throws Exception + */ + public function __construct() + { + $this->headers = getallheaders(); - // check whether API interface is enabled after all - if (\Froxlor\Settings::Get('api.enabled') != 1) { - throw new Exception('API is not enabled. Please contact the administrator if you think this is wrong.', 400); - } - } + // set header for the response + header("Accept: application/json"); + header("Content-Type: application/json"); - /** - * Handle incoming api request to our backend. - * - * @param mixed $request - * @throws Exception - */ - public function handle($request) - { - // validate content - $request = \Froxlor\Api\FroxlorRPC::validateRequest($request); - $request = (new AntiXSS())->xss_clean( - $this->stripcslashesDeep($request) - ); + // check whether API interface is enabled after all + if (\Froxlor\Settings::Get('api.enabled') != 1) { + throw new Exception('API is not enabled. Please contact the administrator if you think this is wrong.', 400); + } + } - // now actually do it - $cls = "\\Froxlor\\Api\\Commands\\" . $request['command']['class']; - $method = $request['command']['method']; - $apiObj = new $cls([ - 'apikey' => $_SERVER['PHP_AUTH_USER'], - 'secret' => $_SERVER['PHP_AUTH_PW'] - ], $request['params']); + /** + * @param mixed $request + * + * @return Api + */ + public function formatMiddleware($request): Api + { + // check auf RESTful api call + $this->request = $request; - // call the method with the params if any - return $apiObj->$method(); - } + $uri = parse_url($_SERVER["REQUEST_URI"], PHP_URL_QUERY); + // map /module/command to internal request array if match + if (!empty($uri) && preg_match("/^\/([a-z]+)\/([a-z]+)\/?/", $uri, $matches)) { + $request = []; + $request['command'] = ucfirst($matches[1]) . '.' . $matches[2]; + $request['params'] = !empty($this->request) ? json_decode($this->request, true) : null; + $this->request = json_encode($request); + } + return $this; + } + /** + * Handle incoming api request to our backend. + * + * @throws Exception + */ + public function handle() + { + $request = $this->request; + // validate content + $request = \Froxlor\Api\FroxlorRPC::validateRequest($request); + $request = (new AntiXSS())->xss_clean( + $this->stripcslashesDeep($request) + ); - private function stripcslashesDeep($value) - { - return is_array($value) ? array_map([$this, 'stripcslashesDeep'], $value) : stripcslashes($value); - } + // now actually do it + $cls = "\\Froxlor\\Api\\Commands\\" . $request['command']['class']; + $method = $request['command']['method']; + $apiObj = new $cls([ + 'apikey' => $_SERVER['PHP_AUTH_USER'], + 'secret' => $_SERVER['PHP_AUTH_PW'] + ], $request['params']); + + // call the method with the params if any + return $apiObj->$method(); + } + + private function stripcslashesDeep($value) + { + return is_array($value) ? array_map([$this, 'stripcslashesDeep'], $value) : stripcslashes($value); + } } diff --git a/lib/Froxlor/Cron/Http/Lighttpd.php b/lib/Froxlor/Cron/Http/Lighttpd.php index d6a08d6e..3cd5cf07 100644 --- a/lib/Froxlor/Cron/Http/Lighttpd.php +++ b/lib/Froxlor/Cron/Http/Lighttpd.php @@ -760,6 +760,7 @@ class Lighttpd extends HttpConfigBase 'customerid' => $domain['customerid'] )); + $diroption_text = ''; while ($row_htpasswds = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { if ($this->auth_backend_loaded[$domain['ipandport']] != 'yes' && $this->auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') { $filename = $domain['customerid'] . '.htpasswd'; @@ -836,6 +837,7 @@ class Lighttpd extends HttpConfigBase } } + $servernames_text = ''; for ($i = 0; $i < sizeof($server_string); $i ++) { $data = $server_string[$i]; diff --git a/lib/Froxlor/Cron/System/TasksCron.php b/lib/Froxlor/Cron/System/TasksCron.php index 99c93944..b2690c86 100644 --- a/lib/Froxlor/Cron/System/TasksCron.php +++ b/lib/Froxlor/Cron/System/TasksCron.php @@ -324,8 +324,8 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron if (file_exists($logsdir) && $logsdir != '/' && $logsdir != \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.logfiles_directory')) && substr($logsdir, 0, strlen(Settings::Get('system.logfiles_directory'))) == Settings::Get('system.logfiles_directory')) { // build up wildcard for webX-{access,error}.log{*} - $logfiles .= '-*'; - \Froxlor\FileDir::safe_exec('rm -f ' . escapeshellarg($logfiles)); + $logsdir .= '-*'; + \Froxlor\FileDir::safe_exec('rm -f ' . escapeshellarg($logsdir)); } } } diff --git a/lib/Froxlor/FileDir.php b/lib/Froxlor/FileDir.php index ae334bf6..18c97980 100644 --- a/lib/Froxlor/FileDir.php +++ b/lib/Froxlor/FileDir.php @@ -496,7 +496,7 @@ class FileDir }; // create RecursiveIteratorIterator - $its = new \RecursiveIteratorIterator(new \RecursiveCallbackFilterIterator(new System\IgnorantRecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), $filter)); + $its = new \RecursiveIteratorIterator(new \RecursiveCallbackFilterIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), $filter)); // we can limit the recursion-depth, but will it be helpful or // will people start asking "why do I only see 2 subdirectories, i want to use /a/b/c" // let's keep this in mind and see whether it will be useful diff --git a/lib/Froxlor/Settings.php b/lib/Froxlor/Settings.php index 2d9b80c3..025a061f 100644 --- a/lib/Froxlor/Settings.php +++ b/lib/Froxlor/Settings.php @@ -1,4 +1,5 @@ false + ]; + + $configfile = Froxlor::getInstallDir() . '/lib/config.inc.php'; + if (@file_exists($configfile) && is_readable($configfile)) { + self::$conf = include $configfile; + } + return true; + } + /** * update a value in the database * @@ -122,7 +149,7 @@ class Settings self::init(); $sstr = explode(".", $setting); // no separator - do'h - if (! isset($sstr[1])) { + if (!isset($sstr[1])) { return null; } $result = null; @@ -170,7 +197,7 @@ class Settings if (self::Get($setting) !== null) { // set new value in array $sstr = explode(".", $setting); - if (! isset($sstr[1])) { + if (!isset($sstr[1])) { return false; } self::$data[$sstr[0]][$sstr[1]] = $value; @@ -179,12 +206,12 @@ class Settings self::storeSetting($sstr[0], $sstr[1], $value); } else { // set temporary data for usage - if (! isset(self::$data[$sstr[0]]) || ! is_array(self::$data[$sstr[0]])) { + if (!isset(self::$data[$sstr[0]]) || !is_array(self::$data[$sstr[0]])) { self::$data[$sstr[0]] = array(); } self::$data[$sstr[0]][$sstr[1]] = $value; // set update-data when invoking Flush() - if (! isset(self::$updatedata[$sstr[0]]) || ! is_array(self::$updatedata[$sstr[0]])) { + if (!isset(self::$updatedata[$sstr[0]]) || !is_array(self::$updatedata[$sstr[0]])) { self::$updatedata[$sstr[0]] = array(); } self::$updatedata[$sstr[0]][$sstr[1]] = $value; @@ -210,7 +237,7 @@ class Settings if (self::Get($setting) === null) { // validate parameter $sstr = explode(".", $setting); - if (! isset($sstr[1])) { + if (!isset($sstr[1])) { return false; } // prepare statement @@ -291,7 +318,7 @@ class Settings 'varname' => $field_details['varname'] )); - if (! empty($row)) { + if (!empty($row)) { $varvalue = $row['value']; } else { $varvalue = $field_details['default']; @@ -306,4 +333,19 @@ class Settings } } } + + /** + * get value from config by identifier + */ + public static function Config(string $config) + { + self::init(); + $sstr = explode(".", $config); + $result = self::$conf; + foreach ($sstr as $key) { + $result = $result[$key] ?? null; + if (empty($result)) break; + } + return $result; + } } diff --git a/lib/Froxlor/System/IgnorantRecursiveDirectoryIterator.php b/lib/Froxlor/System/IgnorantRecursiveDirectoryIterator.php deleted file mode 100644 index 97f8a6ba..00000000 --- a/lib/Froxlor/System/IgnorantRecursiveDirectoryIterator.php +++ /dev/null @@ -1,21 +0,0 @@ -getPathname()); - } catch (\UnexpectedValueException $e) { - return new \RecursiveArrayIterator(array()); - } - } -} diff --git a/lib/config.inc.php b/lib/config.inc.php new file mode 100644 index 00000000..26d1be34 --- /dev/null +++ b/lib/config.inc.php @@ -0,0 +1,8 @@ + false +]; diff --git a/lib/formfields/admin/domains/formfield.domains_add.php b/lib/formfields/admin/domains/formfield.domains_add.php index 266cf1f1..2de32729 100644 --- a/lib/formfields/admin/domains/formfield.domains_add.php +++ b/lib/formfields/admin/domains/formfield.domains_add.php @@ -119,7 +119,6 @@ return array( 'image' => 'icons/domain_add.png', 'fields' => array( 'documentroot' => array( - 'visible' => $userinfo['change_serversettings'] == '1', 'label' => 'DocumentRoot', 'desc' => $lng['panel']['emptyfordefault'], 'type' => 'text' diff --git a/lib/formfields/admin/domains/formfield.domains_edit.php b/lib/formfields/admin/domains/formfield.domains_edit.php index e88a9681..79cea3df 100644 --- a/lib/formfields/admin/domains/formfield.domains_edit.php +++ b/lib/formfields/admin/domains/formfield.domains_edit.php @@ -129,7 +129,6 @@ return array( 'image' => 'icons/domain_edit.png', 'fields' => array( 'documentroot' => array( - 'visible' => $userinfo['change_serversettings'] == '1', 'label' => 'DocumentRoot', 'desc' => $lng['panel']['emptyfordefault'], 'type' => 'text', diff --git a/lib/navigation/00.froxlor.main.php b/lib/navigation/00.froxlor.main.php index 7260665e..0ee610e5 100644 --- a/lib/navigation/00.froxlor.main.php +++ b/lib/navigation/00.froxlor.main.php @@ -228,7 +228,7 @@ return array( 'url' => 'admin_autoupdate.php?page=overview', 'label' => $lng['admin']['autoupdate'], 'required_resources' => 'change_serversettings', - 'show_element' => extension_loaded('zip') + 'show_element' => extension_loaded('zip') && \Froxlor\Settings::Config('enable_webupdate') ), array( 'url' => 'admin_settings.php?page=wipecleartextmailpws', diff --git a/lng/english.lng.php b/lng/english.lng.php index 6e36e933..730c5055 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -898,7 +898,7 @@ $lng['serversettings']['session_allow_multiple_login']['description'] = 'If acti $lng['serversettings']['panel_allow_domain_change_admin']['title'] = 'Allow moving domains between admins'; $lng['serversettings']['panel_allow_domain_change_admin']['description'] = 'If activated you can change the admin of a domain at domainsettings.
Attention: If a customer isn\'t assigned to the same admin as the domain, the admin can see every other domain of that customer!'; $lng['serversettings']['panel_allow_domain_change_customer']['title'] = 'Allow moving domains between customers'; -$lng['serversettings']['panel_allow_domain_change_customer']['description'] = 'If activated you can change the customer of a domain at domainsettings.
Attention: Froxlor won\'t change any paths. This could render a domain unusable!'; +$lng['serversettings']['panel_allow_domain_change_customer']['description'] = 'If activated you can change the customer of a domain at domainsettings.
Attention: Froxlor changes the documentroot to the new customer\'s default homedir (+ domain-folder if activated)'; $lng['domains']['associated_with_domain'] = 'Associated'; $lng['domains']['aliasdomains'] = 'Alias domains'; $lng['error']['ipportdoesntexist'] = 'The ip/port combination you have chosen doesn\'t exist.'; @@ -1878,6 +1878,7 @@ $lng['error']['autoupdate_7'] = 'The downloaded archive could not be found :('; $lng['error']['autoupdate_8'] = 'The archive could not be extracted :('; $lng['error']['autoupdate_9'] = 'The downloaded file did not pass the integrity check. Please try to update again.'; $lng['error']['autoupdate_10'] = 'Minimum supported version of PHP is 7.4.0'; +$lng['error']['autoupdate_11'] = 'Webupdate is disabled'; $lng['admin']['server_php'] = 'PHP'; $lng['domains']['termination_date'] = 'Date of termination'; diff --git a/lng/german.lng.php b/lng/german.lng.php index bed2dfeb..563dbea3 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -892,7 +892,7 @@ $lng['serversettings']['session_allow_multiple_login']['description'] = 'Wenn di $lng['serversettings']['panel_allow_domain_change_admin']['title'] = 'Erlaube Verschieben von Domains unter Admins'; $lng['serversettings']['panel_allow_domain_change_admin']['description'] = 'Wenn diese Option aktiviert ist, kann unter Domaineinstellungen die Domain einem anderen Admin zugewiesen werden.
Achtung: Wenn der Kunde einer Domain nicht dem gleichen Admin zugeordnet ist wie die Domain selbst, kann dieser Admin alle anderen Domains des Kunden sehen!'; $lng['serversettings']['panel_allow_domain_change_customer']['title'] = 'Erlaube Verschieben von Domains unter Kunden'; -$lng['serversettings']['panel_allow_domain_change_customer']['description'] = 'Wenn diese Option aktiviert ist, kann unter Domaineinstellungen die Domain einem anderen Kunden zugewiesen werden.
Achtung: Es werden keine Pfade bei dieser Aktion angepasst. Das kann dazu führen, dass die Domain nach dem Verschieben nicht mehr richtig funktioniert!'; +$lng['serversettings']['panel_allow_domain_change_customer']['description'] = 'Wenn diese Option aktiviert ist, kann unter Domaineinstellungen die Domain einem anderen Kunden zugewiesen werden.
Achtung: Der Dokumenten-Pfad der Domain wird auf den Heimatpfad (+ Domain-Ordner, sofern aktiviert) des neuen Kunden gesetzt.'; $lng['domains']['associated_with_domain'] = 'Verbunden mit'; $lng['domains']['aliasdomains'] = 'Aliasdomains'; $lng['error']['ipportdoesntexist'] = 'Die gewählte IP/Port-Kombination existiert nicht.'; @@ -1525,6 +1525,7 @@ $lng['error']['autoupdate_7'] = 'Das heruntergeladene Archiv konnte nicht gefund $lng['error']['autoupdate_8'] = 'Das Archiv konnte nicht entpackt werden :('; $lng['error']['autoupdate_9'] = 'Die heruntergeladene Datei konnte nicht verifiziert werden. Bitte erneut versuchen zu aktualisieren.'; $lng['error']['autoupdate_10'] = 'Minimum unterstützte Version von PHP ist 7.4.0'; +$lng['error']['autoupdate_11'] = 'Webupdate ist deaktiviert'; $lng['domains']['termination_date'] = 'Kündigungsdatum'; $lng['domains']['termination_date_overview'] = 'gekündigt zum ';