HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //opt/1filellm/compressed_output.txt
<?xml version='1.0' encoding='utf-8'?>
<source type="local_directory" path="/opt/librepanel"><file name="error_report.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ (!defined('area')) { header("location: index.php"); exit(); } use froxlor\filedir; use froxlor\froxlor; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\database\database; // file included admin_domains customer_domains // therefore need require lib/init.php $errid = request::any('errorid'); (!empty($errid)) { // read error file $err_dir = filedir::makecorrectdir(froxlor::getinstalldir() . "/logs/"); $err_file = filedir::makecorrectfile($err_dir . "/" . $errid . "_sql-error.log"); (file_exists($err_file)) { $error_content = file_get_contents($err_file); $error = explode("|", $error_content); $_error = [ 'code' =&gt; str_replace("\n", "", substr($error[1], 5)), 'message' =&gt; str_replace("\n", "", substr($error[2], 4)), 'file' =&gt; str_replace("\n", "", substr($error[3], 5 + strlen(froxlor::getinstalldir()))), 'line' =&gt; str_replace("\n", "", substr($error[4], 5)), 'trace' =&gt; str_replace(froxlor::getinstalldir(), "", substr($error[5], 6)) ]; // build mail-content $mail_body = "dear froxlor-team,\n\n"; $mail_body .= "the following error reported user:\n\n"; $mail_body .= "-------------------------------------------------------------\n"; $mail_body .= $_error['code'] . ' ' . $_error['message'] . "\n\n"; $mail_body .= "file: " . $_error['file'] . ':' . $_error['line'] . "\n\n"; $mail_body .= "trace:\n" . trim($_error['trace']) . "\n\n"; $mail_body .= "-------------------------------------------------------------\n\n"; $mail_body .= "user-area: " . area . "\n"; $mail_body .= "froxlor-version: " . froxlor::version . "\n"; $mail_body .= "db-version: " . froxlor::dbversion . "\n\n"; try { $mail_body .= "database: " . database::getattribute(pdo::attr_server_version); } catch (\exception $e) { /* ignore */ } $mail_body .= "end report"; $mail_html = nl2br($mail_body); // send actual report dev-team (request::post('send') == 'send') { // send mail say thanks $_mailerror = false; try { $mail-&gt;subject = '[froxlor] error report user'; $mail-&gt;altbody = $mail_body; $mail-&gt;msghtml($mail_html); $mail-&gt;addaddress('error-reports@froxlor.org', 'froxlor developer team'); $mail-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { // error reporting error...lolfuq response::standarderror('send_report_error', $mailerr_msg); } // finally remove error fs @unlink($err_file); response::standardsuccess('sent_error_report', '', ['filename' =&gt; 'index.php']); } // show nice summary error-report // actually sending anything ui::view('user/error_report.html.twig', [ 'mail_html' =&gt; $mail_body, 'errorid' =&gt; $errid ]); } else { response::redirectto($filename); } } else { response::redirectto($filename); }</file><file name="admin_updates.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\cron\taskid; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\install\preconfig; use froxlor\install\update; use froxlor\settings; use froxlor\system\cronjob; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\user; ($page == 'overview') { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "viewed admin_updates"); (!froxlor::isfroxlor()) { throw new exception('syscp/customized upgrades supported'); } (froxlor::hasdbupdates() || froxlor::hasupdates()) { $successful_update = false; $message = ''; (request::post('send') == 'send') { ((!empty(request::post('update_preconfig')) &amp;&amp; intval(request::post('update_changesagreed', 0)) != 0) || empty(request::post('update_preconfig'))) { include_once froxlor::getinstalldir() . 'install/updatesql.php'; user::updatecounters(); cronjob::inserttask(taskid::rebuild_vhost); @chmod(froxlor::getinstalldir() . '/lib/userdata.inc.php', 0400); ui::view('install/update.html.twig', [ 'checks' =&gt; update::getupdatetasks() ]); exit; } else { $message = '&lt;br&gt;&lt;br&gt;&lt;strong&gt;you agree read update notifications.&lt;/strong&gt;'; } } $current_version = settings::get('panel.version'); $current_db_version = settings::get('panel.db_version'); (empty($current_db_version)) { $current_db_version = "0"; } $new_version = froxlor::version; $new_db_version = froxlor::dbversion; (froxlor::version != $current_version) { $replacer_currentversion = $current_version; $replacer_newversion = $new_version; } else { // show db version $replacer_currentversion = $current_db_version; $replacer_newversion = $new_db_version; } $ui_text = lng('update.update_information.part_a', [$replacer_newversion, $replacer_currentversion]); $ui_text .= lng('update.update_information.part_b'); $upd_formfield = [ 'updates' =&gt; [ 'title' =&gt; lng('update.update'), 'image' =&gt; 'fa-solid fa-download', 'description' =&gt; lng('update.description'), 'sections' =&gt; [], 'buttons' =&gt; [ [ 'label' =&gt; lng('update.proceed') ] ] ] ]; $preconfig = preconfig::getpreconfig(); (!empty($preconfig)) { $upd_formfield['updates']['sections'] = $preconfig; } ui::view('user/form-note.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'updates']), 'formdata' =&gt; $upd_formfield['updates'], // alert 'type' =&gt; !empty($message) ? 'danger' : 'info', 'alert_msg' =&gt; $ui_text . $message ]); } else { response::standardsuccess('update.noupdatesavail', settings::get('system.update_channel') == 'testing' ? lng('serversettings.uc_testing') . ' ' : ''); } }</file><file name="logfiles_viewer.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ (!defined('area')) { header("location: index.php"); exit(); } use froxlor\api\commands\subdomains; use froxlor\customer\customer; use froxlor\filedir; use froxlor\settings; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; // file included admin_domains customer_domains // therefore need require lib/init.php $domain_id = (int)request::any('domain_id'); $last_n = (int)request::any('number_of_lines', 100); // user's logviewenabled = false (area != 'admin' &amp;&amp; $userinfo['logviewenabled'] != '1') { // back domain overview response::redirectto($filename, [ 'page' =&gt; 'domains' ]); } (function_exists('exec')) { // get domain-info try { $json_result = subdomains::getlocal($userinfo, [ 'id' =&gt; $domain_id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $domain = json_decode($json_result, true)['data']; ($domain['email_only']) { response::dynamicerror("there webserver logfiles email domains."); } $speciallogfile = ''; ($domain['speciallogfile'] == '1') { ($domain['parentdomainid'] == '0') { $speciallogfile = '-' . $domain['domain']; } else { $speciallogfile = '-' . $domain['parentdomain']; } } // normal access/error - logging enabled $error_log = filedir::makecorrectfile(settings::get('system.logfiles_directory') . customer::getcustomerdetail($domain['customerid'], 'loginname') . $speciallogfile . '-error.log'); $access_log = filedir::makecorrectfile(settings::get('system.logfiles_directory') . customer::getcustomerdetail($domain['customerid'], 'loginname') . $speciallogfile . '-access.log'); // error log (file_exists($error_log)) { $result = filedir::safe_exec('tail -n ' . $last_n . ' ' . escapeshellarg($error_log)); $error_log_content = implode("\n", $result); } else { $error_log_content = "error-log" . (area == 'admin' ? " '" . $error_log . "'" : "") . " seem exist"; } // access log (file_exists($access_log)) { $result = filedir::safe_exec('tail -n ' . $last_n . ' ' . escapeshellarg($access_log)); $access_log_content = implode("\n", $result); } else { $access_log_content = "access-log" . (area == 'admin' ? " '" . $access_log . "'" : "") . " seem exist"; } ui::view('user/logfiles.html.twig', [ 'error_log_content' =&gt; $error_log_content, 'access_log_content' =&gt; $access_log_content, 'actions_links' =&gt; [ [ 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'domains', 'page' =&gt; 'domains', 'action' =&gt; 'edit', 'id' =&gt; $domain_id ]), 'label' =&gt; lng('admin.domain_edit'), 'icon' =&gt; 'fa-solid fa-pen' ], [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains', 'page' =&gt; 'domains']), 'label' =&gt; lng('panel.backtooverview'), 'icon' =&gt; 'fa-solid fa-reply' ] ] ]); } else { (area == 'admin') { response::dynamicerror('you need allow exec() function froxlor-vhost php-config'); } else { response::dynamicerror('required function exec() allowed. please contact system administrator.'); } }</file><file name="index.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'login'; require __dir__ . '/lib/init.php'; use froxlor\api\froxlorrpc; use froxlor\currentuser; use froxlor\customer\customer; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\froxlortwofactorauth; use froxlor\phphelper; use froxlor\settings; use froxlor\system\crypt; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\user; use froxlor\validate\validate; ($action == '') { $action = 'login'; } ($action == '2fa_entercode') { // page entering 2fa code successful login (!isset($_session) || !isset($_session['secret_2fa'])) { // session - redirect index response::redirectto('index.php'); exit(); } $smessage = (int)request::get('showmessage', 0); $message = ""; ($smessage &gt; 0) { $message = lng('error.2fa_wrongcode'); } // show template enter code ui::view('login/enter2fa.html.twig', [ 'pagetitle' =&gt; lng('login.2fa'), 'remember_me' =&gt; (settings::get('panel.db_version') &gt;= 202407200) ? true : false, 'message' =&gt; $message ]); } elseif ($action == '2fa_verify') { // verify code 2fa code-enter form (!isset($_session) || !isset($_session['secret_2fa'])) { // session - redirect index response::redirectto('index.php'); exit(); } $code = request::post('2fa_code'); $remember = request::post('2fa_remember'); // verify entered code $tfa = new froxlortwofactorauth('froxlor ' . settings::get('system.hostname')); // get user-data $table = $_session['uidtable_2fa']; $field = $_session['uidfield_2fa']; $uid = $_session['uid_2fa']; $isadmin = $_session['unfo_2fa']; ($_session['secret_2fa'] == 'email') { // verify code set user's data_2fa field $sel_stmt = database::prepare("select `data_2fa` " . $table . " `" . $field . "` = :uid"); $userinfo_code = database::pexecute_first($sel_stmt, ['uid' =&gt; $uid]); // 60sec discrepancy (possible slow email delivery) $result = $tfa-&gt;verifycode($userinfo_code['data_2fa'], $code, 60); } else { $result = $tfa-&gt;verifycode($_session['secret_2fa'], $code, 3); } // either code valid using authenticator-app, select userdata id entered code // temporarily stored customer using email-2fa ($result) { $sel_param = [ 'uid' =&gt; $uid ]; $sel_stmt = database::prepare("select * " . $table . " `" . $field . "` = :uid"); $userinfo = database::pexecute_first($sel_stmt, $sel_param); // whoops, (valid) user? start (empty($userinfo)) { response::redirectto('index.php', [ 'showmessage' =&gt; '2' ]); } // set fields $userinfo required finishlogin() $userinfo['adminsession'] = $isadmin; $userinfo['userid'] = $uid; // using email-2fa, remove one-time-code ($userinfo['type_2fa'] == '1') { $del_stmt = database::prepare("update " . $table . " set `data_2fa` = '' `" . $field . "` = :uid"); database::pexecute_first($del_stmt, [ 'uid' =&gt; $uid ]); } // remember activated, set cookie ($remember) { $selector = base64_encode(froxlor::gensessionid(9)); $authenticator = froxlor::gensessionid(33); $valid_until = time()+60*60*24*30; $ins_stmt = database::prepare(" insert `".table_panel_2fa_tokens."` set `selector` = :selector, `token` = :authenticator, `userid` = :userid, `valid_until` = :valid_until "); database::pexecute($ins_stmt, [ 'selector' =&gt; $selector, 'authenticator' =&gt; hash('sha256', $authenticator), 'userid' =&gt; $uid, 'valid_until' =&gt; $valid_until ]); $cookie_params = [ 'expires' =&gt; $valid_until, // 30 days 'path' =&gt; '/', 'domain' =&gt; ui::getcookiehost(), 'secure' =&gt; ui::requestishttps(), 'httponly' =&gt; true, 'samesite' =&gt; 'strict' ]; setcookie('frx_2fa_remember', $selector.':'.base64_encode($authenticator), $cookie_params); } // successful somehow - start (!finishlogin($userinfo)) { response::redirectto('index.php', [ 'showmessage' =&gt; '2' ]); } exit(); } // wrong 2fa code - treat like "wrong password" $stmt = database::prepare(" update " . $table . " set `lastlogin_fail`= :lastlogin_fail, `loginfail_count`=`loginfail_count`+1 `" . $field . "`= :uid "); database::pexecute($stmt, [ "lastlogin_fail" =&gt; time(), "uid" =&gt; $uid ]); // get data processing $stmt = database::prepare(" select `loginname`, `loginfail_count`, `lastlogin_fail` " . $table . " `" . $field . "`= :uid "); $fail_user = database::pexecute_first($stmt, [ "uid" =&gt; $uid ]); ($fail_user['loginfail_count'] &gt;= settings::get('login.maxloginattempts') &amp;&amp; $fail_user['lastlogin_fail'] &gt; (time() - settings::get('login.deactivatetime'))) { // log failed login $rstlog = froxlorlogger::getinstanceof([ 'loginname' =&gt; $_server['remote_addr'] ]); $rstlog-&gt;logaction(froxlorlogger::login_action, log_warning, "user '" . $fail_user['loginname'] . "' entered wrong 2fa code often."); unset($fail_user); response::redirectto('index.php', [ 'showmessage' =&gt; '3' ]); exit(); } unset($fail_user); // back form response::redirectto('index.php', [ 'action' =&gt; '2fa_entercode', 'showmessage' =&gt; '1' ]); exit(); } elseif ($action == 'login') { (!empty($_post)) { $loginname = validate::validate(request::post('loginname'), 'loginname'); $password = validate::validate(request::post('password'), 'password'); $select_additional = ''; (settings::get('panel.db_version') &gt;= 202312230) { $select_additional = ' `gui_access` = 1'; } $stmt = database::prepare(" select `loginname` `customer` `" . table_panel_customers . "` `loginname`= :loginname" . $select_additional ); database::pexecute($stmt, [ "loginname" =&gt; $loginname ]); $row = $stmt-&gt;fetch(pdo::fetch_assoc); $is_admin = false; $table = ""; ($row &amp;&amp; $row['customer'] == $loginname) { $table = "`" . table_panel_customers . "`"; $uid = 'customerid'; $adminsession = '0'; } else { ((int)settings::get('login.domain_login') == 1) { $domainname = $idna_convert-&gt;encode(preg_replace([ '/\:(\d)+$/', '/^https?\:\/\//' ], '', $loginname)); $stmt = database::prepare(" select `customerid` `" . table_panel_domains . "` `domain` = :domain "); database::pexecute($stmt, [ "domain" =&gt; $domainname ]); $row2 = $stmt-&gt;fetch(pdo::fetch_assoc); (isset($row2['customerid']) &amp;&amp; $row2['customerid'] &gt; 0) { $loginname = customer::getcustomerdetail($row2['customerid'], 'loginname'); ($loginname !== false) { $stmt = database::prepare(" select `loginname` `customer` `" . table_panel_customers . "` `loginname`= :loginname "); database::pexecute($stmt, [ "loginname" =&gt; $loginname ]); $row3 = $stmt-&gt;fetch(pdo::fetch_assoc); ($row3 &amp;&amp; $row3['customer'] == $loginname) { $table = "`" . table_panel_customers . "`"; $uid = 'customerid'; $adminsession = '0'; } } } } } (empty($table)) { // try login admin customer-login method worked $is_admin = true; } ((froxlor::hasupdates() || froxlor::hasdbupdates()) &amp;&amp; $is_admin == false) { response::redirectto('index.php'); exit(); } ($is_admin) { (froxlor::hasupdates() || froxlor::hasdbupdates()) { $stmt = database::prepare(" select `loginname` `admin` `" . table_panel_admins . "` `loginname`= :loginname `change_serversettings` = '1' "); database::pexecute($stmt, [ "loginname" =&gt; $loginname ]); $row = $stmt-&gt;fetch(pdo::fetch_assoc); (!isset($row['admin'])) { // admin see updates response::redirectto('index.php'); exit(); } } else { $select_additional = ''; (settings::get('panel.db_version') &gt;= 202312230) { $select_additional = ' `gui_access` = 1'; } $stmt = database::prepare(" select `loginname` `admin` `" . table_panel_admins . "` `loginname`= :loginname" . $select_additional ); database::pexecute($stmt, [ "loginname" =&gt; $loginname ]); $row = $stmt-&gt;fetch(pdo::fetch_assoc); } ($row &amp;&amp; $row['admin'] == $loginname) { $table = "`" . table_panel_admins . "`"; $uid = 'adminid'; $adminsession = '1'; } else { // log failed login $rstlog = froxlorlogger::getinstanceof([ 'loginname' =&gt; $_server['remote_addr'] ]); $rstlog-&gt;logaction(froxlorlogger::login_action, log_warning, "unknown user tried login."); response::redirectto('index.php', [ 'showmessage' =&gt; '2' ]); exit(); } } $userinfo_stmt = database::prepare(" select * $table `loginname`= :loginname "); database::pexecute($userinfo_stmt, [ "loginname" =&gt; $loginname ]); $userinfo = $userinfo_stmt-&gt;fetch(pdo::fetch_assoc); ($userinfo['loginfail_count'] &gt;= settings::get('login.maxloginattempts') &amp;&amp; $userinfo['lastlogin_fail'] &gt; (time() - settings::get('login.deactivatetime'))) { response::redirectto('index.php', [ 'showmessage' =&gt; '3' ]); exit(); } elseif (crypt::validatepasswordlogin($userinfo, $password, $table, $uid)) { // show "you're banned" login successful // want publish user exist ($userinfo['deactivated']) { unset($userinfo); response::redirectto('index.php', [ 'showmessage' =&gt; '5' ]); exit(); } else { // login correct // reset loginfail_counter, set lastlogin_succ $stmt = database::prepare(" update $table set `lastlogin_succ`= :lastlogin_succ, `loginfail_count`='0' `$uid`= :uid "); database::pexecute($stmt, [ "lastlogin_succ" =&gt; time(), "uid" =&gt; $userinfo[$uid] ]); $userinfo['userid'] = $userinfo[$uid]; $userinfo['adminsession'] = $adminsession; } } else { // login incorrect $stmt = database::prepare(" update $table set `lastlogin_fail`= :lastlogin_fail, `loginfail_count`=`loginfail_count`+1 `$uid`= :uid "); database::pexecute($stmt, [ "lastlogin_fail" =&gt; time(), "uid" =&gt; $userinfo[$uid] ]); // log failed login $rstlog = froxlorlogger::getinstanceof([ 'loginname' =&gt; $_server['remote_addr'] ]); $rstlog-&gt;logaction(froxlorlogger::login_action, log_warning, "user tried login wrong password."); unset($userinfo); response::redirectto('index.php', [ 'showmessage' =&gt; '2' ]); exit(); } // 2fa activated (settings::get('2fa.enabled') == '1' &amp;&amp; $userinfo['type_2fa'] &gt; 0) { // check remember cookie (!empty($_cookie['frx_2fa_remember'])) { list($selector, $authenticator) = explode(':', $_cookie['frx_2fa_remember']); $sel_stmt = database::prepare("select `token` `".table_panel_2fa_tokens."` `selector` = :selector `userid` = :uid `valid_until` &gt;= unix_timestamp()"); $token_check = database::pexecute_first($sel_stmt, ['selector' =&gt; $selector, 'uid' =&gt; $userinfo[$uid]]); ($token_check &amp;&amp; hash_equals($token_check['token'], hash('sha256', base64_decode($authenticator)))) { (!finishlogin($userinfo)) { response::redirectto('index.php', [ 'showmessage' =&gt; '2' ]); } exit(); } // found invalid, cookie useless, get rid unset($_cookie['frx_2fa_remember']); setcookie('frx_2fa_remember', "", time()-3600); } // redirect code-enter-page $_session['secret_2fa'] = ($userinfo['type_2fa'] == 2 ? $userinfo['data_2fa'] : 'email'); $_session['uid_2fa'] = $userinfo[$uid]; $_session['uidfield_2fa'] = $uid; $_session['uidtable_2fa'] = $table; $_session['unfo_2fa'] = $is_admin; // send mail type_2fa = 1 (email) ($userinfo['type_2fa'] == 1) { // generate code $tfa = new froxlortwofactorauth('froxlor ' . settings::get('system.hostname')); $secret = $tfa-&gt;createsecret(); $code = $tfa-&gt;getcode($secret); // set code user $stmt = database::prepare("update $table set `data_2fa` = :d2fa `$uid` = :uid"); database::pexecute($stmt, [ "d2fa" =&gt; $secret, "uid" =&gt; $userinfo[$uid] ]); // build &amp; send email $_mailerror = false; $mailerr_msg = ""; $replace_arr = [ 'code' =&gt; $code ]; $mail_body = html_entity_decode(phphelper::replacevariables(lng('mails.2fa.mailbody'), $replace_arr)); try { $mail-&gt;subject = lng('mails.2fa.subject'); $mail-&gt;altbody = $mail_body; $mail-&gt;msghtml(str_replace("\n", "&lt;br /&gt;", $mail_body)); $mail-&gt;addaddress($userinfo['email'], user::getcorrectusersalutation($userinfo)); $mail-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { $rstlog = froxlorlogger::getinstanceof([ 'loginname' =&gt; '2fa code-sending' ]); $rstlog-&gt;logaction(froxlorlogger::adm_action, log_err, "error sending mail: " . $mailerr_msg); response::redirectto('index.php', [ 'showmessage' =&gt; '4', 'customermail' =&gt; $userinfo['email'] ]); exit(); } $mail-&gt;clearaddresses(); } response::redirectto('index.php', [ 'action' =&gt; '2fa_entercode' ]); exit(); } (!finishlogin($userinfo)) { response::redirectto('index.php', [ 'showmessage' =&gt; '2' ]); } exit(); } else { $smessage = (int)request::get('showmessage', 0); $message = ''; $successmessage = ''; switch ($smessage) { case 1: $successmessage = lng('pwdreminder.success'); break; case 2: $message = lng('error.login'); break; case 3: $message = lng('error.login_blocked', [settings::get('login.deactivatetime')]); break; case 4: $message = lng('error.errorsendingmailpub'); break; case 5: $message = lng('error.user_banned'); break; case 6: $successmessage = lng('pwdreminder.changed'); break; case 7: $message = lng('pwdreminder.wrongcode'); break; case 8: $message = lng('pwdreminder.notallowed'); break; } $update_in_progress = false; (froxlor::hasupdates() || froxlor::hasdbupdates()) { $update_in_progress = true; } // pass last used page needed $lastscript = request::any('script', ''); (!empty($lastscript)) { $lastscript = str_replace("..", "", $lastscript); $lastscript = htmlspecialchars($lastscript, ent_quotes); (file_exists(__dir__ . "/" . $lastscript)) { $_session['lastscript'] = $lastscript; } else { $lastscript = ""; } } $lastqrystr = request::any('qrystr', ''); (!empty($lastqrystr)) { $lastqrystr = urlencode($lastqrystr); $_session['lastqrystr'] = $lastqrystr; } ui::view('login/login.html.twig', [ 'pagetitle' =&gt; 'login', 'upd_in_progress' =&gt; $update_in_progress, 'message' =&gt; $message, 'successmsg' =&gt; $successmessage ]); } } ($action == 'forgotpwd') { $adminchecked = false; $message = ''; (!empty($_post)) { $loginname = validate::validate(request::post('loginname'), 'loginname'); $email = validate::validateemail(request::post('loginemail')); $result_stmt = database::prepare("select `adminid`, `customerid`, `customernumber`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` `" . table_panel_customers . "` `loginname`= :loginname `email`= :email"); database::pexecute($result_stmt, [ "loginname" =&gt; $loginname, "email" =&gt; $email ]); (database::num_rows() == 0) { $result_stmt = database::prepare("select `adminid`, `name`, `email`, `loginname`, `def_language`, `deactivated` `" . table_panel_admins . "` `loginname`= :loginname `email`= :email"); database::pexecute($result_stmt, [ "loginname" =&gt; $loginname, "email" =&gt; $email ]); (database::num_rows() &gt; 0) { $adminchecked = true; } else { $result_stmt = null; } } ($adminchecked) { (settings::get('panel.allow_preset_admin') != '1') { $message = lng('pwdreminder.notallowed'); unset($adminchecked); } } else { (settings::get('panel.allow_preset') != '1') { $message = lng('pwdreminder.notallowed'); } } (empty($message)) { ($result_stmt !== null) { $user = $result_stmt-&gt;fetch(pdo::fetch_assoc); /* check whether user banned */ ($user['deactivated']) { $message = lng('pwdreminder.notallowed'); } else { (($adminchecked &amp;&amp; settings::get('panel.allow_preset_admin') == '1') || $adminchecked == false) { ($user !== false) { // build activation code $timestamp = time(); $first = substr(md5($user['loginname'] . $timestamp . phphelper::randomstr(16)), 0, 15); $third = substr(md5($user['email'] . $timestamp . phphelper::randomstr(16)), -15); $activationcode = $first . $timestamp . $third . substr(md5($third . $timestamp), 0, 10); // drop existing activation codes user $stmt = database::prepare("delete `" . table_panel_activation . "` `userid` = :userid `admin` = :admin"); $params = [ "userid" =&gt; $adminchecked ? $user['adminid'] : $user['customerid'], "admin" =&gt; $adminchecked ? 1 : 0 ]; database::pexecute($stmt, $params); // add new activation code database $stmt = database::prepare("insert `" . table_panel_activation . "` (userid, admin, creation, activationcode) values (:userid, :admin, :creation, :activationcode)"); $params = [ "userid" =&gt; $adminchecked ? $user['adminid'] : $user['customerid'], "admin" =&gt; $adminchecked ? 1 : 0, "creation" =&gt; $timestamp, "activationcode" =&gt; $activationcode ]; database::pexecute($stmt, $params); $rstlog = froxlorlogger::getinstanceof([ 'loginname' =&gt; 'password_reset' ]); $rstlog-&gt;logaction(froxlorlogger::usr_action, log_warning, "user '" . $user['loginname'] . "' requested link setting new password."); // set together activation link $protocol = empty($_server['https']) ? 'http' : 'https'; // fixed value avoid potential exploiting modifying headers $host = settings::get('system.hostname'); // $_server['http_host']; $port = $_server['server_port'] != 80 ? ':' . $_server['server_port'] : ''; // add :443 https used, default (and looks weird!) ($protocol == 'https' &amp;&amp; $_server['server_port'] == '443') { $port = ''; } // one script handle use fixed value $script = "/index.php"; // $_server['script_name']; (settings::get('system.froxlordirectlyviahostname') == 0) { $script = filedir::makecorrectfile("/" . basename(__dir__) . "/" . $script); } $activationlink = $protocol . '://' . $host . $port . $script . '?action=resetpwd&amp;resetcode=' . $activationcode; $replace_arr = [ 'salutation' =&gt; user::getcorrectusersalutation($user), 'name' =&gt; $user['name'], 'firstname' =&gt; $user['firstname'] ?? "", 'company' =&gt; $user['company'] ?? "", 'customer_no' =&gt; $user['customernumber'] ?? 0, 'username' =&gt; $loginname, 'link' =&gt; $activationlink ]; $def_language = ($user['def_language'] != '') ? $user['def_language'] : settings::get('panel.standardlanguage'); $result_stmt = database::prepare('select `value` `' . table_panel_templates . '` `adminid`= :adminid `language`= :lang `templategroup`=\'mails\' `varname`=\'password_reset_subject\''); database::pexecute($result_stmt, [ "adminid" =&gt; $user['adminid'], "lang" =&gt; $def_language ]); $result = $result_stmt-&gt;fetch(pdo::fetch_assoc); $mail_subject = html_entity_decode(phphelper::replacevariables((($result['value'] != '') ? $result['value'] : lng('mails.password_reset.subject')), $replace_arr)); $result_stmt = database::prepare('select `value` `' . table_panel_templates . '` `adminid`= :adminid `language`= :lang `templategroup`=\'mails\' `varname`=\'password_reset_mailbody\''); database::pexecute($result_stmt, [ "adminid" =&gt; $user['adminid'], "lang" =&gt; $def_language ]); $result = $result_stmt-&gt;fetch(pdo::fetch_assoc); $mail_body = html_entity_decode(phphelper::replacevariables((($result['value'] != '') ? $result['value'] : lng('mails.password_reset.mailbody')), $replace_arr)); $_mailerror = false; $mailerr_msg = ""; try { $mail-&gt;subject = $mail_subject; $mail-&gt;altbody = $mail_body; $mail-&gt;msghtml(str_replace("\n", "&lt;br /&gt;", $mail_body)); $mail-&gt;addaddress($user['email'], user::getcorrectusersalutation($user)); $mail-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { $rstlog = froxlorlogger::getinstanceof([ 'loginname' =&gt; 'password_reset' ]); $rstlog-&gt;logaction(froxlorlogger::adm_action, log_err, "error sending mail: " . $mailerr_msg); response::redirectto('index.php', [ 'showmessage' =&gt; '4', 'customermail' =&gt; $user['email'] ]); exit(); } $mail-&gt;clearaddresses(); response::redirectto('index.php', [ 'showmessage' =&gt; '1' ]); exit(); } else { $rstlog = froxlorlogger::getinstanceof([ 'loginname' =&gt; 'password_reset' ]); $rstlog-&gt;logaction(froxlorlogger::usr_action, log_warning, "unknown user requested set new password, found database!"); $message = lng('login.usernotfound'); } unset($user); } } } else { $message = lng('pwdreminder.notallowed'); } } } ui::view('login/fpwd.html.twig', [ 'pagetitle' =&gt; lng('login.presend'), 'formaction' =&gt; 'index.php?action=' . $action, 'message' =&gt; $message, ]); } ($action == 'resetpwd') { $message = ''; // remove old activation codes $stmt = database::prepare("delete `" . table_panel_activation . "` creation &lt; :oldest"); database::pexecute($stmt, [ "oldest" =&gt; time() - 86400 ]); $activationcode = request::get('resetcode'); (!empty($activationcode) &amp;&amp; strlen($activationcode) == 50) { // check activation code valid $timestamp = substr($activationcode, 15, 10); $third = substr($activationcode, 25, 15); $check = substr($activationcode, 40, 10); (substr(md5($third . $timestamp), 0, 10) == $check &amp;&amp; $timestamp &gt;= time() - 86400) { (!empty($_post)) { $stmt = database::prepare("select `userid`, `admin` `" . table_panel_activation . "` `activationcode` = :activationcode"); $result = database::pexecute_first($stmt, [ "activationcode" =&gt; $activationcode ]); ($result !== false) { try { $new_password = crypt::validatepassword(request::post('new_password'), true); $new_password_confirm = crypt::validatepassword(request::post('new_password_confirm'), true); } catch (exception $e) { $message = $e-&gt;getmessage(); } (empty($message) &amp;&amp; (empty($new_password) || $new_password != $new_password_confirm)) { $message = lng('error.newpasswordconfirmerror'); } (empty($message)) { // update user password ($result['admin'] == 1) { $stmt = database::prepare("update `" . table_panel_admins . "` set `password` = :newpassword `adminid` = :userid"); } else { $stmt = database::prepare("update `" . table_panel_customers . "` set `password` = :newpassword `customerid` = :userid"); } database::pexecute($stmt, [ "newpassword" =&gt; crypt::makecryptpassword($new_password), "userid" =&gt; $result['userid'] ]); $rstlog = froxlorlogger::getinstanceof([ 'loginname' =&gt; 'password_reset' ]); $rstlog-&gt;logaction(froxlorlogger::usr_action, log_notice, "changed password using password reset."); // remove activation code db $stmt = database::prepare("delete `" . table_panel_activation . "` `activationcode` = :activationcode `userid` = :userid"); database::pexecute($stmt, [ "activationcode" =&gt; $activationcode, "userid" =&gt; $result['userid'] ]); response::redirectto('index.php', [ "showmessage" =&gt; '6' ]); } } else { response::redirectto('index.php', [ "showmessage" =&gt; '7' ]); } } ui::view('login/rpwd.html.twig', [ 'pagetitle' =&gt; lng('pwdreminder.choosenew'), 'formaction' =&gt; 'index.php?action=resetpwd&amp;resetcode=' . $activationcode, 'message' =&gt; $message, ]); } else { response::redirectto('index.php', [ "showmessage" =&gt; '7' ]); } } else { response::redirectto('index.php'); } } // one-time link login ($action == 'll') { (!froxlor::hasupdates() &amp;&amp; !froxlor::hasdbupdates()) { $loginname = request::get('ln'); $hash = request::get('h'); ($loginname &amp;&amp; $hash) { $sel_stmt = database::prepare(" select * `" . table_panel_loginlinks . "` `loginname` = :loginname `hash` = :hash "); try { $entry = database::pexecute_first($sel_stmt, ['loginname' =&gt; $loginname, 'hash' =&gt; $hash]); } catch (exception $e) { $entry = false; } ($entry) { // delete entry $del_stmt = database::prepare("delete `" . table_panel_loginlinks . "` `loginname` = :loginname `hash` = :hash"); database::pexecute($del_stmt, ['loginname' =&gt; $loginname, 'hash' =&gt; $hash]); (time() &lt;= $entry['valid_until']) { $valid = true; // validate source ip specified (!empty($entry['allowed_from'])) { $valid = false; $ip_list = explode(",", $entry['allowed_from']); (froxlorrpc::validateallowedfrom($ip_list, $_server['remote_addr'])) { $valid = true; } } ($valid) { // login user / select non-deactivated (in case user got deactivated generating link) $userinfo_stmt = database::prepare("select * `" . table_panel_customers . "` `loginname`= :loginname `deactivated` = 0"); try { $userinfo = database::pexecute_first($userinfo_stmt, [ "loginname" =&gt; $loginname ]); } catch (exception $e) { $userinfo = false; } ($userinfo) { $userinfo['userid'] = $userinfo['customerid']; $userinfo['adminsession'] = 0; finishlogin($userinfo); } } } } } } response::redirectto('index.php'); } function finishlogin($userinfo) { (isset($userinfo['userid']) &amp;&amp; $userinfo['userid'] != '') { session_regenerate_id(true); currentuser::setdata($userinfo); $language = $userinfo['def_language'] ?? settings::get('panel.standardlanguage'); currentuser::setfield('language', $language); (isset($userinfo['theme']) &amp;&amp; $userinfo['theme'] != '') { $theme = $userinfo['theme']; } else { $theme = settings::get('panel.default_theme'); } currentuser::setfield('theme', $theme); $qryparams = []; (!empty($_session['lastqrystr'])) { parse_str(urldecode($_session['lastqrystr']), $qryparams); unset($_session['lastqrystr']); } ($userinfo['adminsession'] == '1') { (froxlor::hasupdates() || froxlor::hasdbupdates()) { response::redirectto('admin_updates.php?page=overview'); } else { (!empty($_session['lastscript'])) { $lastscript = $_session['lastscript']; unset($_session['lastscript']); (preg_match("/customer\_/", $lastscript) === 1) { response::redirectto('admin_customers.php', [ "page" =&gt; "customers" ]); } else { response::redirectto($lastscript, $qryparams); } } else { response::redirectto('admin_index.php', $qryparams); } } } else { (!empty($_session['lastscript'])) { $lastscript = $_session['lastscript']; unset($_session['lastscript']); response::redirectto($lastscript, $qryparams); } else { response::redirectto('customer_index.php', $qryparams); } } } return false; }</file><file name="admin_logger.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\syslog; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; ($page == 'log' &amp;&amp; $userinfo['change_serversettings'] == '1') { ($action == '') { try { $syslog_list_data = include_once dirname(__file__) . '/lib/tablelisting/tablelisting.syslog.php'; $collection = (new collection(syslog::class, $userinfo)) -&gt;withpagination($syslog_list_data['syslog_list']['columns'], $syslog_list_data['syslog_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $syslog_list_data, 'syslog_list'), 'actions_links' =&gt; [ [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'logger', 'page' =&gt; 'log', 'action' =&gt; 'truncate']), 'label' =&gt; lng('logger.truncate'), 'icon' =&gt; 'fa-solid fa-recycle', 'class' =&gt; 'btn-warning' ] ] ]); } elseif ($action == 'truncate') { (request::post('send') == 'send') { try { syslog::getlocal($userinfo, [ 'min_to_keep' =&gt; 10 ])-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesno('logger_reallytruncate', $filename, [ 'page' =&gt; $page, 'action' =&gt; $action ], table_panel_log); } } }</file><file name="customer_traffic.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'customer'; require __dir__ . '/lib/init.php'; use froxlor\traffic\traffic; use froxlor\settings; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; // redirect customer page hidden via settings (settings::isinlist('panel.customer_hide_options', 'traffic')) { response::redirectto('customer_index.php'); } $range = request::any('range', 'currentyear'); ($page == 'current') { $range = 'currentmonth'; } try { $context = traffic::getcustomerstats($userinfo, $range); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } // pass metrics view ui::view('user/traffic.html.twig', $context);</file><file name="admin_mysqlserver.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\mysqlserver; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; $id = (int)request::any('id'); (($page == 'mysqlserver' || $page == 'overview') &amp;&amp; $userinfo['change_serversettings'] == '1') { ($action == '') { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "viewed admin_mysqlserver"); try { $mysqlserver_list_data = include_once dirname(__file__) . '/lib/tablelisting/admin/tablelisting.mysqlserver.php'; $collection = (new collection(mysqlserver::class, $userinfo)) -&gt;withpagination($mysqlserver_list_data['mysqlserver_list']['columns'], $mysqlserver_list_data['mysqlserver_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $mysqlserver_list_data, 'mysqlserver_list'), 'actions_links' =&gt; [ [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'mysqlserver', 'page' =&gt; $page, 'action' =&gt; 'add']), 'label' =&gt; lng('admin.mysqlserver.add') ] ] ]); } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = mysqlserver::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['id']) &amp;&amp; $result['id'] == $id) { (request::post('send') == 'send') { try { mysqlserver::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesno('admin_mysqlserver_reallydelete', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $result['caption'] . ' (' . $result['host'] . ')'); } } } elseif ($action == 'add') { (request::post('send') == 'send') { try { mysqlserver::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $mysqlserver_add_data = include_once dirname(__file__) . '/lib/formfields/admin/mysqlserver/formfield.mysqlserver_add.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'mysqlserver']), 'formdata' =&gt; $mysqlserver_add_data['mysqlserver_add'] ]); } } elseif ($action == 'edit' &amp;&amp; $id &gt;= 0) { try { $json_result = mysqlserver::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['id']) &amp;&amp; $result['id'] == $id) { (request::post('send') == 'send') { try { mysqlserver::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $result = phphelper::htmlentitiesarray($result); $mysqlserver_edit_data = include_once dirname(__file__) . '/lib/formfields/admin/mysqlserver/formfield.mysqlserver_edit.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'mysqlserver', 'id' =&gt; $id]), 'formdata' =&gt; $mysqlserver_edit_data['mysqlserver_edit'], 'editid' =&gt; $id ]); } } } }</file><file name="api_keys.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ (!defined('area')) { header("location: index.php"); exit(); } use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; // redirect customer permission api usage ($userinfo['adminsession'] == 0 &amp;&amp; $userinfo['api_allowed'] == 0) { response::redirectto('customer_index.php'); } // redirect admin permission api usage ($userinfo['adminsession'] == 1 &amp;&amp; $userinfo['api_allowed'] == 0) { response::redirectto('admin_index.php'); } // file included admin_index customer_index // therefore need require lib/init.php $del_stmt = database::prepare("delete `" . table_api_keys . "` id = :id"); $id = (int)request::any('id'); // delete show success-message apikeys list ($action == 'delete' &amp;&amp; $id &gt; 0) { html::askyesno('apikey_reallydelete', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; 'deletesure' ], '', [ 'section' =&gt; 'index', 'page' =&gt; $page ]); } elseif (request::post('send') == 'send' &amp;&amp; $action == 'deletesure' &amp;&amp; $id &gt; 0) { $chk = (area == 'admin' &amp;&amp; $userinfo['customers_see_all'] == '1') ? true : false; (area == 'customer') { $chk_stmt = database::prepare(" select c.customerid `" . table_panel_customers . "` c left join `" . table_api_keys . "` ak ak.customerid = c.customerid ak.`id` = :id c.`customerid` = :cid "); $chk = database::pexecute_first($chk_stmt, [ 'id' =&gt; $id, 'cid' =&gt; $userinfo['customerid'] ]); } elseif (area == 'admin' &amp;&amp; $userinfo['customers_see_all'] == '0') { $chk_stmt = database::prepare(" select a.adminid `" . table_panel_admins . "` left join `" . table_api_keys . "` ak ak.adminid = a.adminid ak.`id` = :id a.`adminid` = :aid "); $chk = database::pexecute_first($chk_stmt, [ 'id' =&gt; $id, 'aid' =&gt; $userinfo['adminid'] ]); } ($chk !== false) { database::pexecute($del_stmt, [ 'id' =&gt; $id ]); response::standardsuccess('apikeys.apikey_removed', $id, [ 'filename' =&gt; $filename, 'page' =&gt; $page ]); } } elseif ($action == 'add') { (request::post('send') == 'send') { $ins_stmt = database::prepare(" insert `" . table_api_keys . "` set `apikey` = :key, `secret` = :secret, `adminid` = :aid, `customerid` = :cid, `valid_until` = '-1', `allowed_from` = '' "); // customer generates himself, admins see customer-select-box later (area == 'admin') { $cid = 0; } elseif (area == 'customer') { $cid = $userinfo['customerid']; } $key = hash('sha256', openssl_random_pseudo_bytes(64 * 64)); $secret = hash('sha512', openssl_random_pseudo_bytes(64 * 64 * 4)); database::pexecute($ins_stmt, [ 'key' =&gt; $key, 'secret' =&gt; $secret, 'aid' =&gt; $userinfo['adminid'], 'cid' =&gt; $cid ]); response::standardsuccess('apikeys.apikey_added', '', [ 'filename' =&gt; $filename, 'page' =&gt; $page ]); } html::askyesno('apikey_reallyadd', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], '', [ 'section' =&gt; 'index', 'page' =&gt; $page ]); exit; } $log-&gt;logaction(froxlorlogger::usr_action, log_notice, "viewed api::api_keys"); // select (accessible) api-keys $keys_stmt_query = "select ak.*, c.loginname, a.loginname adminname `" . table_api_keys . "` ak left join `" . table_panel_customers . "` c `c`.`customerid` = `ak`.`customerid` left join `" . table_panel_admins . "` `a`.`adminid` = `ak`.`adminid` "; $qry_params = []; (area == 'admin' &amp;&amp; $userinfo['customers_see_all'] == '0') { // admin customer-specific permissions $keys_stmt_query .= "ak.adminid = :adminid "; $qry_params['adminid'] = $userinfo['adminid']; $fields = [ 'a.loginname' =&gt; lng('login.username') ]; } elseif (area == 'customer') { // customer-area $keys_stmt_query .= "ak.customerid = :cid "; $qry_params['cid'] = $userinfo['customerid']; $fields = [ 'c.loginname' =&gt; lng('login.username') ]; } else { // admin see customers / reseller / admins $keys_stmt_query .= "1 "; $fields = [ 'a.loginname' =&gt; lng('login.username') ]; } //$keys_stmt_query .= $paging-&gt;getsqlwhere(true) . " " . $paging-&gt;getsqlorderby() . " " . $paging-&gt;getsqllimit(); $keys_stmt = database::prepare($keys_stmt_query); database::pexecute($keys_stmt, $qry_params); $all_keys = $keys_stmt-&gt;fetchall(pdo::fetch_assoc); $apikeys_list_data = include_once dirname(__file__) . '/lib/tablelisting/tablelisting.apikeys.php'; $collection = [ 'data' =&gt; $all_keys, 'pagination' =&gt; [] ]; $tpl = 'user/table.html.twig'; ui::view($tpl, [ 'listing' =&gt; listing::formatfromarray($collection, $apikeys_list_data['apikeys_list'], 'apikeys_list'), 'actions_links' =&gt; (int)$userinfo['api_allowed'] == 1 ? [ [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'index', 'page' =&gt; $page, 'action' =&gt; 'add']), 'label' =&gt; lng('apikeys.key_add') ] ] : null, ]);</file><file name="admin_cronjobs.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\cronjobs; use froxlor\froxlorlogger; use froxlor\ui\collection; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; $id = (int)request::any('id'); (($page == 'cronjobs' || $page == 'overview') &amp;&amp; $userinfo['change_serversettings'] == '1') { ($action == '') { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, 'viewed admin_cronjobs'); try { $cron_list_data = include_once dirname(__file__) . '/lib/tablelisting/admin/tablelisting.cronjobs.php'; $collection = (new collection(cronjobs::class, $userinfo)) -&gt;withpagination($cron_list_data['cron_list']['columns'], $cron_list_data['cron_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } ui::view('user/table-note.html.twig', [ 'listing' =&gt; listing::format($collection, $cron_list_data, 'cron_list'), // alert-box 'type' =&gt; 'warning', 'alert_msg' =&gt; lng('cron.changewarning') ]); } elseif ($action == 'new') { /* * @todo later */ } elseif ($action == 'edit' &amp;&amp; $id != 0) { try { $json_result = cronjobs::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($result['cronfile'] != '') { (request::post('send') == 'send') { try { cronjobs::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $cronjobs_edit_data = include_once dirname(__file__) . '/lib/formfields/admin/cronjobs/formfield.cronjobs_edit.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'cronjobs', 'id' =&gt; $id]), 'formdata' =&gt; $cronjobs_edit_data['cronjobs_edit'], 'editid' =&gt; $id ]); } } } elseif ($action == 'delete' &amp;&amp; $id != 0) { /* * @todo later */ } }</file><file name="admin_domains.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\customers customers; use froxlor\api\commands\domains domains; use froxlor\bulk\domainbulkaction; use froxlor\cron\taskid; use froxlor\currentuser; use froxlor\customer\customer; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\system\cronjob; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\user; use froxlor\validate\validate; $id = (int)request::any('id'); ($page == 'domains' || $page == 'overview') { ($action == '') { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "viewed admin_domains"); try { $customercollection = (new collection(customers::class, $userinfo)); $domain_list_data = include_once dirname(__file__) . '/lib/tablelisting/admin/tablelisting.domains.php'; $collection = (new collection(domains::class, $userinfo)) -&gt;has('customer', customers::class, 'customerid', 'customerid') -&gt;withpagination($domain_list_data['domain_list']['columns'], $domain_list_data['domain_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $actions_links = false; (currentuser::canaddresource('domains')) { $actions_links = []; $actions_links[] = [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains', 'page' =&gt; $page, 'action' =&gt; 'add']), 'label' =&gt; lng('admin.domain_add') ]; $actions_links[] = [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains', 'page' =&gt; $page, 'action' =&gt; 'import']), 'label' =&gt; lng('domains.domain_import'), 'icon' =&gt; 'fa-solid fa-file-import', 'class' =&gt; 'btn-outline-secondary' ]; } ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $domain_list_data, 'domain_list'), 'actions_links' =&gt; $actions_links ]); } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = domains::getlocal($userinfo, [ 'id' =&gt; $id, 'no_std_subdomain' =&gt; true ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; $alias_check_stmt = database::prepare(" select count(`id`) `count` `" . table_panel_domains . "` `aliasdomain`= :id"); $alias_check = database::pexecute_first($alias_check_stmt, [ 'id' =&gt; $id ]); ($result['domain'] != '') { (request::post('send') == 'send' &amp;&amp; $alias_check['count'] == 0) { try { domains::getlocal($userinfo, request::postall())-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } elseif ($alias_check['count'] &gt; 0) { response::standarderror('domains_cantdeletedomainwithaliases'); } else { html::askyesnowithcheckbox('admin_domain_reallydelete', 'admin_customer_alsoremovemail', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $idna_convert-&gt;decode($result['domain'])); } } } elseif ($action == 'add') { (request::post('send') == 'send') { try { domains::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $customers = [ 0 =&gt; lng('panel.please_choose') ]; $result_customers_stmt = database::prepare(" select `customerid`, `loginname`, `name`, `firstname`, `company` `" . table_panel_customers . "` " . ($userinfo['customers_see_all'] ? '' : " `adminid` = :adminid ") . " order coalesce(nullif(`name`,''), `company`) asc"); $params = []; ($userinfo['customers_see_all'] == '0') { $params['adminid'] = $userinfo['adminid']; } database::pexecute($result_customers_stmt, $params); ($row_customer = $result_customers_stmt-&gt;fetch(pdo::fetch_assoc)) { $customers[$row_customer['customerid']] = user::getcorrectfulluserdetails($row_customer) . ' (' . $row_customer['loginname'] . ')'; } $admins = []; ($userinfo['customers_see_all'] == '1') { $result_admins_stmt = database::query(" select `adminid`, `loginname`, `name` `" . table_panel_admins . "` `domains_used` &lt; `domains` `domains` = '-1' order `name` asc"); ($row_admin = $result_admins_stmt-&gt;fetch(pdo::fetch_assoc)) { $admins[$row_admin['adminid']] = user::getcorrectfulluserdetails($row_admin) . ' (' . $row_admin['loginname'] . ')'; } } ($userinfo['ip'] == "-1") { $result_ipsandports_stmt = database::query(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `ssl`='0' order `ip`, `port` asc "); $result_ssl_ipsandports_stmt = database::query(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `ssl`='1' order `ip`, `port` asc "); } else { $admin_ip_stmt = database::prepare(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `id` = :ipid order `ip`, `port` asc "); $admin_ip = database::pexecute_first($admin_ip_stmt, [ 'ipid' =&gt; $userinfo['ip'] ]); $result_ipsandports_stmt = database::prepare(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `ssl`='0' `ip` = :ipid order `ip`, `port` asc "); database::pexecute($result_ipsandports_stmt, [ 'ipid' =&gt; $admin_ip['ip'] ]); $result_ssl_ipsandports_stmt = database::prepare(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `ssl`='1' `ip` = :ipid order `ip`, `port` asc "); database::pexecute($result_ssl_ipsandports_stmt, [ 'ipid' =&gt; $admin_ip['ip'] ]); } // build array holding ips ports available admin $ipsandports = []; ($row_ipandport = $result_ipsandports_stmt-&gt;fetch(pdo::fetch_assoc)) { (filter_var($row_ipandport['ip'], filter_validate_ip, filter_flag_ipv6)) { $row_ipandport['ip'] = '[' . $row_ipandport['ip'] . ']'; } $ipsandports[] = [ 'label' =&gt; $row_ipandport['ip'] . ':' . $row_ipandport['port'], 'value' =&gt; $row_ipandport['id'] ]; } $ssl_ipsandports = []; ($row_ssl_ipandport = $result_ssl_ipsandports_stmt-&gt;fetch(pdo::fetch_assoc)) { (filter_var($row_ssl_ipandport['ip'], filter_validate_ip, filter_flag_ipv6)) { $row_ssl_ipandport['ip'] = '[' . $row_ssl_ipandport['ip'] . ']'; } $ssl_ipsandports[] = [ 'label' =&gt; $row_ssl_ipandport['ip'] . ':' . $row_ssl_ipandport['port'], 'value' =&gt; $row_ssl_ipandport['id'] ]; } $standardsubdomains = []; $result_standardsubdomains_stmt = database::query(" select `id` `" . table_panel_domains . "` `d`, `" . table_panel_customers . "` `c` `d`.`id` = `c`.`standardsubdomain` "); ($row_standardsubdomain = $result_standardsubdomains_stmt-&gt;fetch(pdo::fetch_assoc)) { $standardsubdomains[$row_standardsubdomain['id']] = $row_standardsubdomain['id']; } (count($standardsubdomains) &gt; 0) { $standardsubdomains = " `d`.`id` (" . join(',', $standardsubdomains) . ") "; } else { $standardsubdomains = ''; } $domains = [ 0 =&gt; lng('domains.noaliasdomain') ]; $result_domains_stmt = database::prepare(" select `d`.`id`, `d`.`domain`, `c`.`loginname` `" . table_panel_domains . "` `d`, `" . table_panel_customers . "` `c` `d`.`aliasdomain` null `d`.`parentdomainid` = 0" . $standardsubdomains . ($userinfo['customers_see_all'] ? '' : " `d`.`adminid` = :adminid") . " `d`.`customerid`=`c`.`customerid` order `loginname`, `domain` asc "); $params = []; ($userinfo['customers_see_all'] == '0') { $params['adminid'] = $userinfo['adminid']; } database::pexecute($result_domains_stmt, $params); ($row_domain = $result_domains_stmt-&gt;fetch(pdo::fetch_assoc)) { $domains[$row_domain['id']] = $idna_convert-&gt;decode($row_domain['domain']) . ' (' . $row_domain['loginname'] . ')'; } $phpconfigs = []; $configs = database::query(" select c.*, fc.description interpreter `" . table_panel_phpconfigs . "` c left join `" . table_panel_fpmdaemons . "` fc fc.id = c.fpmsettingid "); ($row = $configs-&gt;fetch(pdo::fetch_assoc)) { ((int)settings::get('phpfpm.enabled') == 1) { $phpconfigs[$row['id']] = $row['description'] . " [" . $row['interpreter'] . "]"; } else { $phpconfigs[$row['id']] = $row['description']; } } $openbasedir = [ 0 =&gt; lng('domain.docroot'), 1 =&gt; lng('domain.homedir'), 2 =&gt; lng('domain.docparent') ]; // create serveralias options $serveraliasoptions = [ 0 =&gt; lng('domains.serveraliasoption_wildcard'), 1 =&gt; lng('domains.serveraliasoption_www'), 2 =&gt; lng('domains.serveraliasoption_none') ]; $subcanemaildomain = [ 0 =&gt; lng('admin.subcanemaildomain.never'), 1 =&gt; lng('admin.subcanemaildomain.choosableno'), 2 =&gt; lng('admin.subcanemaildomain.choosableyes'), 3 =&gt; lng('admin.subcanemaildomain.always') ]; $domain_add_data = include_once dirname(__file__) . '/lib/formfields/admin/domains/formfield.domains_add.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains']), 'formdata' =&gt; $domain_add_data['domain_add'] ]); } } elseif ($action == 'edit' &amp;&amp; $id != 0) { try { $json_result = domains::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($result['domain'] != '') { $subdomains_stmt = database::prepare(" select count(`id`) count `" . table_panel_domains . "` `parentdomainid` = :resultid "); $subdomains = database::pexecute_first($subdomains_stmt, [ 'resultid' =&gt; $result['id'] ]); $subdomains = $subdomains['count']; $alias_check_stmt = database::prepare(" select count(`id`) count `" . table_panel_domains . "` `aliasdomain` = :resultid "); $alias_check = database::pexecute_first($alias_check_stmt, [ 'resultid' =&gt; $result['id'] ]); $alias_check = $alias_check['count']; $domain_emails_result_stmt = database::prepare(" select `email`, `email_full`, `destination`, `popaccountid` `" . table_mail_virtual . "` `customerid` = :customerid `domainid` = :id "); database::pexecute($domain_emails_result_stmt, [ 'customerid' =&gt; $result['customerid'], 'id' =&gt; $result['id'] ]); $emails = database::num_rows(); $email_forwarders = 0; $email_accounts = 0; ($domain_emails_row = $domain_emails_result_stmt-&gt;fetch(pdo::fetch_assoc)) { ($domain_emails_row['destination'] != '') { $domain_emails_row['destination'] = explode(' ', filedir::makecorrectdestination($domain_emails_row['destination'])); $email_forwarders += count($domain_emails_row['destination']); (in_array($domain_emails_row['email_full'], $domain_emails_row['destination'])) { $email_forwarders -= 1; $email_accounts++; } } } $ipsresult_stmt = database::prepare(" select `id_ipandports` `" . table_domaintoip . "` `id_domain` = :id "); database::pexecute($ipsresult_stmt, [ 'id' =&gt; $result['id'] ]); $usedips = []; ($ipsresultrow = $ipsresult_stmt-&gt;fetch(pdo::fetch_assoc)) { $usedips[] = $ipsresultrow['id_ipandports']; } (request::post('send') == 'send') { try { // remove ssl ip/ports set empty (empty(request::post('ssl_ipandport'))) { $_post['remove_ssl_ipandport'] = true; } domains::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { (settings::get('panel.allow_domain_change_customer') == '1') { $customers = []; $result_customers_stmt = database::prepare(" select `customerid`, `loginname`, `name`, `firstname`, `company` `" . table_panel_customers . "` ( (`subdomains_used` + :subdomains &lt;= `subdomains` `subdomains` = '-1' ) (`emails_used` + :emails &lt;= `emails` `emails` = '-1' ) (`email_forwarders_used` + :forwarders &lt;= `email_forwarders` `email_forwarders` = '-1' ) (`email_accounts_used` + :accounts &lt;= `email_accounts` `email_accounts` = '-1' ) " . ($userinfo['customers_see_all'] ? '' : " `adminid` = :adminid ") . ") `customerid` = :customerid order `name` asc "); $params = [ 'subdomains' =&gt; $subdomains, 'emails' =&gt; $emails, 'forwarders' =&gt; $email_forwarders, 'accounts' =&gt; $email_accounts, 'customerid' =&gt; $result['customerid'] ]; ($userinfo['customers_see_all'] == '0') { $params['adminid'] = $userinfo['adminid']; } database::pexecute($result_customers_stmt, $params); ($row_customer = $result_customers_stmt-&gt;fetch(pdo::fetch_assoc)) { $customers[$row_customer['customerid']] = user::getcorrectfulluserdetails($row_customer) . ' (' . $row_customer['loginname'] . ')'; } } else { $customer_stmt = database::prepare(" select `customerid`, `loginname`, `name`, `firstname`, `company` `" . table_panel_customers . "` `customerid` = :customerid "); $customer = database::pexecute_first($customer_stmt, [ 'customerid' =&gt; $result['customerid'] ]); $result['customername'] = user::getcorrectfulluserdetails($customer); } ($userinfo['customers_see_all'] == '1') { (settings::get('panel.allow_domain_change_admin') == '1') { $admins = []; $result_admins_stmt = database::prepare(" select `adminid`, `loginname`, `name` `" . table_panel_admins . "` (`domains_used` &lt; `domains` `domains` = '-1') `adminid` = :adminid order `name` asc "); database::pexecute($result_admins_stmt, [ 'adminid' =&gt; $result['adminid'] ]); ($row_admin = $result_admins_stmt-&gt;fetch(pdo::fetch_assoc)) { $admins[$row_admin['adminid']] = user::getcorrectfulluserdetails($row_admin) . ' (' . $row_admin['loginname'] . ')'; } } else { $admin_stmt = database::prepare(" select `adminid`, `loginname`, `name` `" . table_panel_admins . "` `adminid` = :adminid "); $admin = database::pexecute_first($admin_stmt, [ 'adminid' =&gt; $result['adminid'] ]); $result['adminname'] = user::getcorrectfulluserdetails($admin) . ' (' . $admin['loginname'] . ')'; } } $domains = [ 0 =&gt; lng('domains.noaliasdomain') ]; $result_domains_stmt = database::prepare(" select `d`.`id`, `d`.`domain` `" . table_panel_domains . "` `d`, `" . table_panel_customers . "` `c` `d`.`aliasdomain` null `d`.`parentdomainid` = '0' `d`.`id` &lt;&gt; :id `c`.`standardsubdomain`&lt;&gt;`d`.`id` `d`.`customerid` = :customerid `c`.`customerid`=`d`.`customerid` order `d`.`domain` asc "); database::pexecute($result_domains_stmt, [ 'id' =&gt; $result['id'], 'customerid' =&gt; $result['customerid'] ]); ($row_domain = $result_domains_stmt-&gt;fetch(pdo::fetch_assoc)) { $domains[$row_domain['id']] = $idna_convert-&gt;decode($row_domain['domain']); } ($userinfo['ip'] == "-1") { $result_ipsandports_stmt = database::query(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `ssl`='0' order `ip`, `port` asc "); $result_ssl_ipsandports_stmt = database::query(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `ssl`='1' order `ip`, `port` asc "); } else { $admin_ip_stmt = database::prepare(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `id` = :ipid order `ip`, `port` asc "); $admin_ip = database::pexecute_first($admin_ip_stmt, [ 'ipid' =&gt; $userinfo['ip'] ]); $result_ipsandports_stmt = database::prepare(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `ssl`='0' `ip` = :ipid order `ip`, `port` asc "); database::pexecute($result_ipsandports_stmt, [ 'ipid' =&gt; $admin_ip['ip'] ]); $result_ssl_ipsandports_stmt = database::prepare(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `ssl`='1' `ip` = :ipid order `ip`, `port` asc "); database::pexecute($result_ssl_ipsandports_stmt, [ 'ipid' =&gt; $admin_ip['ip'] ]); } $ipsandports = []; ($row_ipandport = $result_ipsandports_stmt-&gt;fetch(pdo::fetch_assoc)) { (filter_var($row_ipandport['ip'], filter_validate_ip, filter_flag_ipv6)) { $row_ipandport['ip'] = '[' . $row_ipandport['ip'] . ']'; } $ipsandports[] = [ 'label' =&gt; $row_ipandport['ip'] . ':' . $row_ipandport['port'], 'value' =&gt; $row_ipandport['id'] ]; } $ssl_ipsandports = []; ($row_ssl_ipandport = $result_ssl_ipsandports_stmt-&gt;fetch(pdo::fetch_assoc)) { (filter_var($row_ssl_ipandport['ip'], filter_validate_ip, filter_flag_ipv6)) { $row_ssl_ipandport['ip'] = '[' . $row_ssl_ipandport['ip'] . ']'; } $ssl_ipsandports[] = [ 'label' =&gt; $row_ssl_ipandport['ip'] . ':' . $row_ssl_ipandport['port'], 'value' =&gt; $row_ssl_ipandport['id'] ]; } // check letsencrypt activated wildcard domain ($result['iswildcarddomain'] == '1') { $letsencrypt = 0; } // fudge result ssl_redirect hide let's encrypt steps $result['temporary_ssl_redirect'] = $result['ssl_redirect']; $result['ssl_redirect'] = ($result['ssl_redirect'] == 0 ? 0 : 1); $openbasedir = [ 0 =&gt; lng('domain.docroot'), 1 =&gt; lng('domain.homedir'), 2 =&gt; lng('domain.docparent') ]; $serveraliasoptions = [ 0 =&gt; lng('domains.serveraliasoption_wildcard'), 1 =&gt; lng('domains.serveraliasoption_www'), 2 =&gt; lng('domains.serveraliasoption_none') ]; $subcanemaildomain = [ 0 =&gt; lng('admin.subcanemaildomain.never'), 1 =&gt; lng('admin.subcanemaildomain.choosableno'), 2 =&gt; lng('admin.subcanemaildomain.choosableyes'), 3 =&gt; lng('admin.subcanemaildomain.always') ]; $phpconfigs = []; $phpconfigs_result_stmt = database::query(" select c.*, fc.description interpreter `" . table_panel_phpconfigs . "` c left join `" . table_panel_fpmdaemons . "` fc fc.id = c.fpmsettingid "); $c_allowed_configs = customer::getcustomerdetail($result['customerid'], 'allowed_phpconfigs'); (!empty($c_allowed_configs)) { $c_allowed_configs = json_decode($c_allowed_configs, true); } else { $c_allowed_configs = []; } ($phpconfigs_row = $phpconfigs_result_stmt-&gt;fetch(pdo::fetch_assoc)) { $disabled = !empty($c_allowed_configs) &amp;&amp; !in_array($phpconfigs_row['id'], $c_allowed_configs); (!$disabled) { ((int)settings::get('phpfpm.enabled') == 1) { $phpconfigs[$phpconfigs_row['id']] = $phpconfigs_row['description'] . " [" . $phpconfigs_row['interpreter'] . "]"; } else { $phpconfigs[$phpconfigs_row['id']] = $phpconfigs_row['description']; } } } (settings::get('panel.allow_domain_change_customer') != '1') { $result['customername'] .= ' (&lt;a href="' . $linker-&gt;getlink([ 'section' =&gt; 'customers', 'page' =&gt; 'customers', 'action' =&gt; 'su', 'id' =&gt; $customer['customerid'] ]) . '" rel="external"&gt;' . $customer['loginname'] . '&lt;/a&gt;)'; } $domain_edit_data = include_once dirname(__file__) . '/lib/formfields/admin/domains/formfield.domains_edit.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains', 'id' =&gt; $id]), 'formdata' =&gt; $domain_edit_data['domain_edit'], 'editid' =&gt; $id ]); } } } elseif ($action == 'jqgetcustomerphpconfigs') { $customerid = intval(request::post('customerid')); $allowed_phpconfigs = customer::getcustomerdetail($customerid, 'allowed_phpconfigs'); echo !empty($allowed_phpconfigs) ? $allowed_phpconfigs : json_encode([]); exit(); } elseif ($action == 'jqspeciallogfilenote') { $domainid = intval(request::post('id')); $newval = intval(request::post('newval')); try { $json_result = domains::getlocal($userinfo, [ 'id' =&gt; $domainid ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($newval != $result['speciallogfile']) { echo json_encode(['changed' =&gt; true, 'info' =&gt; lng('admin.speciallogwarning')]); exit(); } echo 0; exit(); } elseif ($action == 'jqemaildomainnote') { $domainid = intval(request::post('id')); $newval = intval(request::post('newval')); try { $json_result = domains::getlocal($userinfo, [ 'id' =&gt; $domainid ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ((int)$newval == 0 &amp;&amp; $newval != $result['isemaildomain']) { echo json_encode(['changed' =&gt; true, 'info' =&gt; lng('admin.emaildomainwarning')]); exit(); } echo 0; exit(); } elseif ($action == 'import') { (request::post('send') == 'send') { $separator = validate::validate(request::post('separator'), 'separator'); $offset = (int)validate::validate(request::post('offset'), 'offset', "/[0-9]/i"); $file_name = $_files['file']['tmp_name']; $result = []; try { $bulk = new domainbulkaction($file_name, $userinfo); $result = $bulk-&gt;doimport($separator, $offset); } catch (exception $e) { response::standarderror('domain_import_error', $e-&gt;getmessage()); } (!empty($bulk-&gt;geterrors())) { response::dynamicerror(implode("&lt;br&gt;", $bulk-&gt;geterrors())); } // update customer/admin counters user::updatecounters(false); cronjob::inserttask(taskid::rebuild_vhost); cronjob::inserttask(taskid::rebuild_dns); $result_str = $result['imported'] . ' / ' . $result['all'] . (!empty($result['note']) ? ' (' . $result['note'] . ')' : ''); response::standardsuccess('domain_import_successfully', $result_str, [ 'filename' =&gt; $filename, 'action' =&gt; '', 'page' =&gt; 'domains' ]); } else { $domain_import_data = include_once dirname(__file__) . '/lib/formfields/admin/domains/formfield.domains_import.php'; ui::view('user/form-note.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains', 'page' =&gt; $page]), 'formdata' =&gt; $domain_import_data['domain_import'], // alert-box 'type' =&gt; 'info', 'alert_msg' =&gt; lng('domains.import_description') ]); } } elseif ($action == 'duplicate') { (request::post('send') == 'send') { try { domains::getlocal($userinfo, request::postall())-&gt;duplicate(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page, 'searchfield' =&gt; 'd.domain_ace', 'searchtext' =&gt; request::post('domain', "") ]); } else { response::redirectto($filename, [ 'page' =&gt; 'overview' ]); } } } elseif ($page == 'domainssleditor') { require_once __dir__ . '/ssl_editor.php'; } elseif ($page == 'domaindnseditor' &amp;&amp; settings::get('system.dnsenabled') == '1') { require_once __dir__ . '/dns_editor.php'; } elseif ($page == 'sslcertificates') { require_once __dir__ . '/ssl_certificates.php'; } elseif ($page == 'logfiles') { require_once __dir__ . '/logfiles_viewer.php'; }</file><file name="package-lock.json">{ "name": "froxlor", "lockfileversion": 3, "requires": true, "packages": { "": { "name": "froxlor", "devdependencies": { "@fortawesome/fontawesome-free": "^6.4.2", "@popperjs/core": "^2.11.8", "@vitejs/plugin-vue": "^4.0.0", "axios": "^1.7.4", "bootstrap": "^5.3.2", "chart.js": "^4.4.0", "jquery": "^3.6.1", "jquery-validation": "^1.20.0", "laravel-vite-plugin": "^0.8.0", "lodash": "^4.17.19", "postcss": "^8.1.14", "resolve-url-loader": "^5.0.0", "sass": "^1.69.3", "vite": "^4.5.9", "vue": "^3.2.37" }, "engines": { "node": "&gt;=18" } }, "node_modules/@babel/parser": { "version": "7.23.0", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", "integrity": "sha512-vvpkkdmemu85v9we/l5wzemimpctlqbntvqds2u1fj96krxow7krxhnsncblqlg8ck4b85yxdtyelsmugfuxiw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" }, "engines": { "node": "&gt;=6.0.0" } }, "node_modules/@esbuild/android-arm": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", "integrity": "sha512-fyi7tdi/ijkknztujaqqig5t7yjjxgnzkurqmgj13c6dcqckzbldl4h7bkhht/t0wp+zo9/zwrodvanaoqo5sw==", "cpu": [ "arm" ], "dev": true, "optional": true, "os": [ "android" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/android-arm64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", "integrity": "sha512-nz4rjcchgdtenv0emkuna6l12zz2zbdxuhj/vjh18zgqb44bi7mbmsxjgunjgjrhcmkojnpuzp4mb6okqtmhlq==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "android" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/android-x64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", "integrity": "sha512-8gddlepja8d6zlzyjv/jnrrai6roinacc/jclcxpb+kiuvfbn4owltgzy2bsxnx666xjjx2kdpumnttr8qkqug==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "android" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/darwin-arm64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", "integrity": "sha512-bxrhw5khu38zs2lptpoyuytm+s+eobpuntnkdjefaddygecll4xkt8db9d2008dttbl7ujag2hue5nzazgnnea==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "darwin" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/darwin-x64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", "integrity": "sha512-pc5gxlmdxzm513qpgbcbdukodsgtkhfxd1zjkxjcccu7ju50o7meaz8c4krsjcoijgfr+qx21ymmvywiqvytyq==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "darwin" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/freebsd-arm64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", "integrity": "sha512-yqdqhy4qhevpmaaxhhiwypmv1necwovipgczkecn8w2wfhxjewrbn3ceniysibz/izeuemj++m26w3cnr5h+tw==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "freebsd" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/freebsd-x64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", "integrity": "sha512-tgwrppuqsd3rmbzwargvhzqvtzfeborenuxemkfcd5dadn2pbbxfwlcj4+aenoh7ctxcbxmoqin8hi6mcsw5mq==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "freebsd" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/linux-arm": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", "integrity": "sha512-/5bhkmwnq1egkr1v+ybz3s1hwxok7mdfumq4cg10afw3wl02pszi5kfpykrptdsgb2wajivrcdm+qivxf/apvg==", "cpu": [ "arm" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/linux-arm64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", "integrity": "sha512-2ybscf+ul7sqavipnwvywm+3lskydmphe31pe7/aotmfkkzic9llbygupmmb8a8aixol61sq/mfh3jejhyfvda==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/linux-ia32": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", "integrity": "sha512-p4etwwq6isret0e1khu40bonzmhoh73axp96fs8tit6z9hu8g6+0shsw9i2iswrd2nbx2qo5yuqacgdfvgx7ta==", "cpu": [ "ia32" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/linux-loong64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", "integrity": "sha512-nxw8nqbtropdlpgpy9uv+/1djxoq7dob2n8eocyq8i9xuqj7biamdmf9n1xzm9tgw0j8zrquib/a7s3bjv7rjg==", "cpu": [ "loong64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/linux-mips64el": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", "integrity": "sha512-d5neaxzchp8pzyy5vnxv3vsd2d328zb+9deq5he6bw6+n86jvpexra6o68opwobntbnj0pzcpufzto3w0gyetq==", "cpu": [ "mips64el" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/linux-ppc64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", "integrity": "sha512-whpyescrncmannlqkq6afyxrfr5d6n2skgkfo2fqgup44nw2eydlbtdzwd9gyk98dzg9qitiitlflhjhjxp3fa==", "cpu": [ "ppc64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/linux-riscv64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", "integrity": "sha512-wsxo6h5eci5xh34kc7w5vennkkju3zbrleqny7mv5mtbmrp/mjnbcalsm2u5hdbls3ngctqpobvrzqbcrtpq1a==", "cpu": [ "riscv64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/linux-s390x": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", "integrity": "sha512-+8231gms3maeth6ja1ik0a1sq3ohfcpzprlh8uuc5/kvdfneh6jtajlfgafpzpmro6dzj6avxkze9lffmrihvq==", "cpu": [ "s390x" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/linux-x64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", "integrity": "sha512-uyqiqemphjcnsfeskc73jq7b9jgwjwrsayxaws6uvfzgwraatkzjxsqnoclcxxwtfwldzu+vtpcnyhpn43up1w==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/netbsd-x64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", "integrity": "sha512-io1c++vp6xubumlthzomtcudplnpgdbom6iro4gykpffvbkioiimvoor5i83ntew5uoyrk3gijhbzh8x44y06a==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "netbsd" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/openbsd-x64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", "integrity": "sha512-e5e4yssuqfx4cxcygw/ucpiep6wbil+se3sxpdcimbflbwu0eizoj7wod+ptclrmjzbk1wk7i6d/i3nglugoxg==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "openbsd" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/sunos-x64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", "integrity": "sha512-kdbfrfp0yptqvvrqud5ftymwo45zgaxe0x8e1g/lkfc0v8x0vwrhowslitccn63lmzixfomxtcfti/rxn/0wnq==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "sunos" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/win32-arm64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", "integrity": "sha512-ddyfr6itygoaq4v4jmqqaai5s7npztfv4ag6nrhiaw0rrnoxqbkgwzlofvtlq1davtqnhti5oietvkrpfzrepg==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "win32" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/win32-ia32": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", "integrity": "sha512-wv7qbi3id/rrot08sabts7ev4hx26svduqdote1mvgmjnd3ejoz4b7zeexir62gtiekrfjxkl9lfxtygkyeu7g==", "cpu": [ "ia32" ], "dev": true, "optional": true, "os": [ "win32" ], "engines": { "node": "&gt;=12" } }, "node_modules/@esbuild/win32-x64": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", "integrity": "sha512-ktdfrcsidfqca/y9qikng02avj+ncaqvrmejlsb3rrv5se9rroebpisazpkxhelzrxzylvnts1p27w3wv+8geq==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "win32" ], "engines": { "node": "&gt;=12" } }, "node_modules/@fortawesome/fontawesome-free": { "version": "6.4.2", "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.2.tgz", "integrity": "sha512-m5cpn3e2+fdcogi1mz0rextuvvqibbeboululw0+yrmjdtpkij6vtkuka1grsvrw+12kyjndnjj0o4agtxm2pg==", "dev": true, "hasinstallscript": true, "engines": { "node": "&gt;=6" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-ef2rxcrulekxhtridrdy6ermywqnw4lpdq8uqa4huuxaqsverpfl2om8odgxmfhjuwzf9mcpltjasddzb/bpeg==", "dev": true }, "node_modules/@kurkle/color": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", "integrity": "sha512-fuscdxj9g1qb7w8vdhi+iwrqij3lbkosam4ydqtemby58ozhxqqhvlxqekoz0yssnvn38bcprwga9pp+ogoisw==", "dev": true }, "node_modules/@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-p1st0akscrn9sgzhp8gmywbnqsbvawszax44oxnnvlhgqaocovxmjziohstwq7sqknbr47akdni+ulewd8+g6a==", "dev": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" } }, "node_modules/@vitejs/plugin-vue": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.4.0.tgz", "integrity": "sha512-xdguqb+vuwirpsg+nsc2htbausgak25dxyvpqqi4rvu1xq1uworyoh/md9rfd8zmmpr/psghr309qncftuvseg==", "dev": true, "engines": { "node": "^14.18.0 || &gt;=16.0.0" }, "peerdependencies": { "vite": "^4.0.0", "vue": "^3.2.25" } }, "node_modules/@vue/compiler-core": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz", "integrity": "sha512-cquydnvz6jtbf/+x+agm2arrp6g4dzbb0r64jig804hrmfrifxwi6kquvqz6zr0bqhioqjb4+2bhntvwndw15g==", "dev": true, "dependencies": { "@babel/parser": "^7.21.3", "@vue/shared": "3.3.4", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" } }, "node_modules/@vue/compiler-dom": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz", "integrity": "sha512-wym+ojovpuuukiq6p5+nwhytj9cfroz9cwkfmp9o1nzh68benttv0u7/ndggt8ciqlnbeoo6sut/gvhcikla5w==", "dev": true, "dependencies": { "@vue/compiler-core": "3.3.4", "@vue/shared": "3.3.4" } }, "node_modules/@vue/compiler-sfc": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz", "integrity": "sha512-6y/d8uw+5tkcuzbkgls0v3lsm3hjdntfeiuorm11pq/hkvkhskzrxw6i69uyxljqisjxuuejkaweqwbwslenkq==", "dev": true, "dependencies": { "@babel/parser": "^7.20.15", "@vue/compiler-core": "3.3.4", "@vue/compiler-dom": "3.3.4", "@vue/compiler-ssr": "3.3.4", "@vue/reactivity-transform": "3.3.4", "@vue/shared": "3.3.4", "estree-walker": "^2.0.2", "magic-string": "^0.30.0", "postcss": "^8.1.10", "source-map-js": "^1.0.2" } }, "node_modules/@vue/compiler-ssr": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz", "integrity": "sha512-m0v6okpup2nmsehwa6uuu+j+wewcy7qmwmkvnvfrv9p2qe5kshc6rwocq8fjgs/eak/unb8aawekfixxbbb6gq==", "dev": true, "dependencies": { "@vue/compiler-dom": "3.3.4", "@vue/shared": "3.3.4" } }, "node_modules/@vue/reactivity": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz", "integrity": "sha512-kltdlwd0b1jg08nbf3r5rqultv/f8x3rofbytdz4j53ttiqedmalqkqxy0j+xqen0av2fbxy8njdf88yvopaqq==", "dev": true, "dependencies": { "@vue/shared": "3.3.4" } }, "node_modules/@vue/reactivity-transform": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz", "integrity": "sha512-mxgwjako4nu5wflajpbncj/ieqcje2ajbinunqzkzqfziza4xn+0fv1tiybjvvva3n3ovkgofrlvqiweqppaxw==", "dev": true, "dependencies": { "@babel/parser": "^7.20.15", "@vue/compiler-core": "3.3.4", "@vue/shared": "3.3.4", "estree-walker": "^2.0.2", "magic-string": "^0.30.0" } }, "node_modules/@vue/runtime-core": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.4.tgz", "integrity": "sha512-r+bqxmn6pwo7zgi4omlmvepodp2c93gshfm/siji7o2nxfrzj55plwkpcedey+btmgp5miz8cxfizo3s+gfqva==", "dev": true, "dependencies": { "@vue/reactivity": "3.3.4", "@vue/shared": "3.3.4" } }, "node_modules/@vue/runtime-dom": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz", "integrity": "sha512-aj5btj3u5sfsuckrghsnjvttxzq1oymwcr5dzrapijf/0vy4xeorcwlyhxcj4d0ufbj4lbx3gptgg06k/gnpnq==", "dev": true, "dependencies": { "@vue/runtime-core": "3.3.4", "@vue/shared": "3.3.4", "csstype": "^3.1.1" } }, "node_modules/@vue/server-renderer": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.4.tgz", "integrity": "sha512-q6jddzr23viib67v+vm1dqntu+huexqcswkhhqa4arvzxoy2hbc7qrw/ggkdbd5bu+um1sv6xoap0b216o34jq==", "dev": true, "dependencies": { "@vue/compiler-ssr": "3.3.4", "@vue/shared": "3.3.4" }, "peerdependencies": { "vue": "3.3.4" } }, "node_modules/@vue/shared": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz", "integrity": "sha512-7ojdcv8vq74eiz1tzlzzp4jwqm5fa94k6yntps5z25r9hdugnzagdgvwkyq6s+mxwf0tfrwe50fir/mynakdkq==", "dev": true }, "node_modules/adjust-sourcemap-loader": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", "integrity": "sha512-oxwn5b9pcuxnqhjpwwd2qp40byemsgzj8b4ydsn0umnywifmj6x6kwullmmfk8rwu/hjdfr7u8ubswbon0xp0a==", "dev": true, "dependencies": { "loader-utils": "^2.0.0", "regex-parser": "^2.2.11" }, "engines": { "node": "&gt;=8.9" } }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-kmrefur0b4t+d+obkjr3kyqvocp2xaszo55ucb6mgqmd3kbce+mwtyvvv7d/zsdebnnv6aczuutkihqxvtr1rw==", "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" }, "engines": { "node": "&gt;= 8" } }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-oei9oh4trh0yqu3gxhx79dm/mwvgvbzjasnark+bshkj0s5cfhcgyakrebjrhwatxkbz+ioidylxrkim2mjw0q==", "dev": true }, "node_modules/axios": { "version": "1.7.4", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", "integrity": "sha512-dukmafrny6azaalsh4j2m3k6pkac+mfaagdeerrwcc9q3/twqwlphr8zrlktdq3abdl64edlurdjjqkw+bpzew==", "dev": true, "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyl2oymjxmaro8gxmr0mhchso9qgwhynfuu4+mhtaw6czfq9humcb7rkpujdd9yuidpu4mzpyupfsvoclawbmq==", "dev": true, "engines": { "node": "*" } }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jdctj/ivqbzojykoehbhxpolnbqgncwxjkjog42e5hdpuwqtsdjchdihjj0dlnheq7blbt6dhoafnais8ooqka==", "dev": true, "engines": { "node": "&gt;=8" } }, "node_modules/bootstrap": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.2.tgz", "integrity": "sha512-d32nmnwiqho94bkhlmordjll05q1c8oxbtbphqfb9z5to6egrdcm0qgeaz4zfbhzfg2++rqa2jkqccxdy0sh0g==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/twbs" }, { "type": "opencollective", "url": "https://opencollective.com/bootstrap" } ], "peerdependencies": { "@popperjs/core": "^2.11.8" } }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yqbxgo/oszvd2isillro+7hf6q18ejrksesdomzkepkxct3gvd8olcoqdizgupr5fj+ede8go/lxc1bzfmpxva==", "dev": true, "dependencies": { "fill-range": "^7.1.1" }, "engines": { "node": "&gt;=8" } }, "node_modules/chart.js": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.0.tgz", "integrity": "sha512-vqej6d+z0dcskllqvbkimyfhd3t8w/7l2vfjibycfypcrx92cshqecpuen8qvgnlkydcr5wbryayknfu/9q1hq==", "dev": true, "dependencies": { "@kurkle/color": "^0.3.0" }, "engines": { "pnpm": "&gt;=7" } }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-dr3sfkrp6otcjf2jmumfjfevmvxbdegxb0ivq5eb2v10ufjucas8obyzdvayvb8xxnz3gjjtgj9klwsztqe6kw==", "dev": true, "funding": [ { "type": "individual", "url": "https://paulmillr.com/funding/" } ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "engines": { "node": "&gt;= 8.10.0" }, "optionaldependencies": { "fsevents": "~2.3.2" } }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-fqn4mrfujehf7cbbbmjfxhksdq+2kaarblmrbvcvfe5bb1hzkxtsfasdhdlz9zoywxh8lddnvmmoe/+5cdoedg==", "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, "engines": { "node": "&gt;= 0.8" } }, "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-asfbup0mz1uyiijanan1jzlqami9z1poyszciiyw2fczpbenxc45fzdbzlzot+r6+iciuemodtmcti+hjaak0a==", "dev": true }, "node_modules/csstype": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "integrity": "sha512-i7k1uu0mbpzafkg4ni5q7vs2t+3gwww648spaf+rg7pi9ds18ugn+lvg4shczudklhi5lwbxyqfs8+dufybsgq==", "dev": true }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-zysd7nf91alb0rxl4kgrkhbxl7eds1damedcovawxnld7sdhpngtuii2aakg7a7qs41jxpsz17p4vdgnmhk3mq==", "dev": true, "engines": { "node": "&gt;=0.4.0" } }, "node_modules/emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", "integrity": "sha512-/kym18efinwxzbno9fyugefh87kc8hrqbqgildhzbeurywfomv1u10o9bbp8xvzdvnnuqkyigiu5zyaaxj0v2q==", "dev": true, "engines": { "node": "&gt;= 4" } }, "node_modules/esbuild": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", "integrity": "sha512-ceqxoedurcayh7y7zx6ndbbdzgroiyvbgc4prijthbksvpwnnfhzakfi1ljt8qfkowh4qos2sjks4wvpgl8bpa==", "dev": true, "hasinstallscript": true, "bin": { "esbuild": "bin/esbuild" }, "engines": { "node": "&gt;=12" }, "optionaldependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" } }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-rfkk/mp/dl7jvje3u18fxfujqltnr2q6qfmsmb7avcbx91ngj/ba3kcfza0f6dvdbw7ylrf/ndrn7pqrccyq/w==", "dev": true }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-ysgpe3whlk8zyi4twdg2jy3ebrz2rxowdxnld4bkqb00cc/1zw9awnc0i9ztdjitivtqvai9kalykrc+hbw0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, "engines": { "node": "&gt;=8" } }, "node_modules/follow-redirects": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wwn62yiteaopsk584ezxjafh1agpo8rvgelfkuxbtorpx4fifoyepw/csind8jdyraoovafrtoenvso++qcqfa==", "dev": true, "funding": [ { "type": "individual", "url": "https://github.com/sponsors/rubenverborgh" } ], "engines": { "node": "&gt;=4.0" }, "peerdependenciesmeta": { "debug": { "optional": true } } }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-eteklsgi5t0qmzuixoa/q6vcnxclqp5vdugspuayi6svgi2clppp+xgehumahc+zggn31kd235w35f7hykkaww==", "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" }, "engines": { "node": "&gt;= 6" } }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xodfx+fl7faatnagmwppbftwh/r77wmmmqqhgs65c3vvb0yhrgf+b1ymz3441tmj5n63k0212xnojwzlhffqw==", "dev": true, "hasinstallscript": true, "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || &gt;=11.0.0" } }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-aoigsqcepijywp3arngx+5vntu2hbydzbgp45elw1vr3zb3vzleyed1sc9hnbcoc9/srmym5rpqrkgz4as9zow==", "dev": true, "dependencies": { "is-glob": "^4.0.1" }, "engines": { "node": "&gt;= 6" } }, "node_modules/immutable": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", "integrity": "sha512-fsxeu4j4i6wnwsikpi88v/pcvflzz+6kmhufiwc5sy+poqrpnaf5v7qds6suyun3cvxezucab7qioloq+dq1wa==", "dev": true }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-zmeryes6pdydyugidse7oshxtbi7wveueozgr/g7rd0xuimynlvzre/k2mgztjwy725ifellevcem97mmtrgxw==", "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, "engines": { "node": "&gt;=8" } }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-sbkbankn603vi4jezv49levjmn4ygwsbzzworeoyeiutsn3njydbo36zfhgj6qedpozifkdtnq5jrxmvl3jsoq==", "dev": true, "engines": { "node": "&gt;=0.10.0" } }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelsayhh36zge7zwhli7pw34hnbnl8ojv5kvmkjd4hbdd3th8tfk9vyaslm+mxwozhfkgzfxhlsnrwrr4elssg==", "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, "engines": { "node": "&gt;=0.10.0" } }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41cifkg6e8tylspdttpelvmqvsbevzttthverd741+pnz8anv0004mrl43qkpdlk9cgvnp6nzwzublbgxyxxng==", "dev": true, "engines": { "node": "&gt;=0.12.0" } }, "node_modules/jquery": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", "integrity": "sha512-m4avr8yl8kmfn8psrbfffmb/if14in5o9nw/ngnnm+kybdjprsaynv2bsfptyrtrysyudadvd7ckuuizgkplfg==", "dev": true }, "node_modules/jquery-validation": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/jquery-validation/-/jquery-validation-1.20.0.tgz", "integrity": "sha512-c8tg4ltiip6l7l0bz79srzojyquyjs48kqz6iv8mj2r0oyztxtkwyktrezyu2/zvfyiinb29i0z/irnnujqn1g==", "dev": true, "peerdependencies": { "jquery": "^1.7 || ^2.0 || ^3.1" } }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-xmowe7eyhyh14cldvpoyg+goh3ryx++kpzryljwsw98t3nk+u8xol8fwkogwtzdb8lxgf6zywduzehmwfxasyg==", "dev": true, "bin": { "json5": "lib/cli.js" }, "engines": { "node": "&gt;=6" } }, "node_modules/laravel-vite-plugin": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-0.8.1.tgz", "integrity": "sha512-fxzudjoa37kosyq8dp+3opilw8/kjvxwu0hoxlun82r1lpv02shgewgykx2lbpkffl5i0sfppjfqbyxuqbluaa==", "dev": true, "dependencies": { "picocolors": "^1.0.0", "vite-plugin-full-reload": "^1.0.5" }, "engines": { "node": "&gt;=14" }, "peerdependencies": { "vite": "^3.0.0 || ^4.0.0" } }, "node_modules/loader-utils": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", "integrity": "sha512-xxqpxoinffhgua9xiqd8fpfhgkoq1mmmpe92wldbm9rnrd/ebrb+gqf908t2dmfuhjjjlksik2rbhvodd/mqsw==", "dev": true, "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", "json5": "^2.1.2" }, "engines": { "node": "&gt;=8.9.0" } }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kdee57lectuladiuntpy3ry4glgj6z1o3ve1krgxznrsq+lftghvxvjcxps17lhbzvgedajv8xz1tvj5fvsg==", "dev": true }, "node_modules/magic-string": { "version": "0.30.5", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", "integrity": "sha512-7xlpfbaqap/t6vh8mo/eqxsw5en6inhevexqiuff7gku0pwju3uf6w/j9o7o+spb5foakri5heongwjeo0pfsa==", "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, "engines": { "node": "&gt;=12" } }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-spu4uv7dylvtwjxwwxhd0puihvnie7tyabq5swxdcb9muyvogroqowyqqokpj8cibe+1etvlook1uc2nu3gyvg==", "dev": true, "engines": { "node": "&gt;= 0.6" } }, "node_modules/mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-zdy+bpm5zttf+ypcrau9nk0ugicypt0qtt1nzwfv4s++tnkcgvat0g6+4r2ui4mjqjzyshb1zxuwl50hzaexiw==", "dev": true, "dependencies": { "mime-db": "1.52.0" }, "engines": { "node": "&gt;= 0.6" } }, "node_modules/nanoid": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", "integrity": "sha512-bgcqmmjutof7i1rt+2pwsnvnwikgcu78jbg3rxo/bzlnzpk2cmi2qaffxgo/2rvwi9sl+fairixmgsyxq1dida==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], "bin": { "nanoid": "bin/nanoid.cjs" }, "engines": { "node": "^10 || ^12 || ^13.7 || ^14 || &gt;=15.0.1" } }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6ezs5ls3wtcishwp9s2guy8dqkpgi4bvsz3gaqie6ezub0512esztxuwub6c6ikbqky2pnb/md4wyojcrwcwla==", "dev": true, "engines": { "node": "&gt;=0.10.0" } }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygrotllhu66zi26votdv8yrgm0fccecssto+mhsz0d/dgw2sm8e8ajw7nu5vvtrt5gxbez5qbujr+hylykjq==", "dev": true }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-ju3tehtnjme2vcgfzuy8exzcdvweqb2a8fsivwasthhawjeevd1o1qd80cu6+zdexxslbssulwjjkcbwqrquva==", "dev": true, "engines": { "node": "&gt;=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", "integrity": "sha512-ps08iboia9mts/2ygv3elpy5ghnucflv/extow1e2qyxjkggbutnjn76fyhnms36rmarn41bc0azmn+rr0ovpq==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, "engines": { "node": "^10 || ^12 || &gt;=14" } }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-d+zkorcba9f1tdwrk0racr3gpv50cmxcrz4x8k5ltsud1dkw47mkjezqnunitrtkwwgtauso1rvfrig9zxifyg==", "dev": true }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hos089on8rduqdbhvq5z37a0esjsqz6qnrcffsmu3495futdqsm+7bhj29jviosbdeenan5dpu9t3to9vrlmza==", "dev": true, "dependencies": { "picomatch": "^2.2.1" }, "engines": { "node": "&gt;=8.10.0" } }, "node_modules/regex-parser": { "version": "2.2.11", "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", "integrity": "sha512-jbd/ft0+9mbu2xazlui7w2obs1rbi6p9m83nkozayqxxu9e8robt69fczc7wu4ejd/yftjn1jdck3rbmjajz8q==", "dev": true }, "node_modules/resolve-url-loader": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", "integrity": "sha512-uztduh8/8srhbomx//5bwqjq+rfyouq8zc9nrmugtjbigttfjm42s58/36+htqeqincnye08nj3lkk9lw4n8xg==", "dev": true, "dependencies": { "adjust-sourcemap-loader": "^4.0.0", "convert-source-map": "^1.7.0", "loader-utils": "^2.0.0", "postcss": "^8.2.14", "source-map": "0.6.1" }, "engines": { "node": "&gt;=12" } }, "node_modules/rollup": { "version": "3.29.5", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", "integrity": "sha512-gvsddsbjzzy4s/v3dqwpj7efvzjfchidqe80iyrf59lyup+e6u1ljouqeuqrbwawomnoxivmnenaof5e22va1w==", "dev": true, "bin": { "rollup": "dist/bin/rollup" }, "engines": { "node": "&gt;=14.18.0", "npm": "&gt;=8.0.0" }, "optionaldependencies": { "fsevents": "~2.3.2" } }, "node_modules/sass": { "version": "1.69.3", "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.3.tgz", "integrity": "sha512-x99+a2igdxkdwn1akfps0zmeluzyaqfvqyc2p/mptrjruirotffgzt9w9nfqg00s+c8hxzvmgxhuuhfdrwxkhq==", "dev": true, "dependencies": { "chokidar": "&gt;=3.0.0 &lt;4.0.0", "immutable": "^4.0.0", "source-map-js": "&gt;=0.6.2 &lt;2.0.0" }, "bin": { "sass": "sass.js" }, "engines": { "node": "&gt;=14.0.0" } }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-ujgapumwlbmhkbgzt7ykc5yxut46f0iku8sgxq0bcwp5dz/h0plj6enjqjz1zbq2l5waqynrvbwwowmyf3f47g==", "dev": true, "engines": { "node": "&gt;=0.10.0" } }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-r0xvvj9wusliqtceigcmiccmplcckiwwr11mosd9cr5u+ixydiseeeuxcvajs54zqwklcpnnmu4oej6turwhdw==", "dev": true, "engines": { "node": "&gt;=0.10.0" } }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65p7iz6x5yer1cwcgvqxbbiw7uk3goy5didtz4rdvelqhrdjp+li/hx6tyk0neb+2gcynecmjigqradcsnk8sq==", "dev": true, "dependencies": { "is-number": "^7.0.0" }, "engines": { "node": "&gt;=8.0" } }, "node_modules/vite": { "version": "4.5.9", "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.9.tgz", "integrity": "sha512-qk9w4xjgd3gxbc0nmdnffnvflmwsnir3swj957yutwzzn16xf/e7nmtayp1rt9hvidroqanje4hk3h4wqwdftw==", "dev": true, "license": "mit", "dependencies": { "esbuild": "^0.18.10", "postcss": "^8.4.27", "rollup": "^3.27.1" }, "bin": { "vite": "bin/vite.js" }, "engines": { "node": "^14.18.0 || &gt;=16.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionaldependencies": { "fsevents": "~2.3.2" }, "peerdependencies": { "@types/node": "&gt;= 14", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "peerdependenciesmeta": { "@types/node": { "optional": true }, "less": { "optional": true }, "lightningcss": { "optional": true }, "sass": { "optional": true }, "stylus": { "optional": true }, "sugarss": { "optional": true }, "terser": { "optional": true } } }, "node_modules/vite-plugin-full-reload": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.0.5.tgz", "integrity": "sha512-kvzfdfwr0dxihn6mudvtqf7gnwidetglzh0hvtimxzrn80vgf4pkbonsq8u1d0wthskafodtqgjeaklacopzeq==", "dev": true, "dependencies": { "picocolors": "^1.0.0", "picomatch": "^2.3.1" }, "peerdependencies": { "vite": "^2 || ^3 || ^4" } }, "node_modules/vue": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz", "integrity": "sha512-vtyeyn3yviey1py0waygzsxnz3y5ungi62gjveqvegpl6nxborcxbvotqwbejuqaytuk2uj5jlvnyj6zzgbrsw==", "dev": true, "dependencies": { "@vue/compiler-dom": "3.3.4", "@vue/compiler-sfc": "3.3.4", "@vue/runtime-dom": "3.3.4", "@vue/server-renderer": "3.3.4", "@vue/shared": "3.3.4" } } } }</file><file name="ssl_editor.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ (!defined('area')) { header("location: index.php"); exit(); } use froxlor\api\commands\certificates; use froxlor\api\commands\subdomains; use froxlor\database\database; use froxlor\phphelper; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; // file included admin_domains customer_domains // therefore need require lib/init.php ($action == '' || $action == 'view') { // get domain try { $json_result = subdomains::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result_domain = json_decode($json_result, true)['data']; ($result_domain['email_only']) { response::dynamicerror("there ssl-certificates email domains."); } (request::post('send') == 'send') { $do_insert = request::post('do_insert', 0) == 1; try { ($do_insert) { certificates::getlocal($userinfo, request::postall())-&gt;add(); } else { certificates::getlocal($userinfo, request::postall())-&gt;update(); } } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } // back domain overview response::redirectto($filename, [ 'page' =&gt; 'domains' ]); } $stmt = database::prepare("select * `" . table_panel_domain_ssl_settings . "` `domainid`= :domainid"); $result = database::pexecute_first($stmt, [ "domainid" =&gt; $id ]); $do_insert = false; // entry found, behave like empty values (!is_array($result) || !isset($result['ssl_cert_file'])) { $result = [ 'ssl_cert_file' =&gt; '', 'ssl_key_file' =&gt; '', 'ssl_ca_file' =&gt; '', 'ssl_cert_chainfile' =&gt; '' ]; $do_insert = true; } $result = phphelper::htmlentitiesarray($result); $ssleditor_data = include_once dirname(__file__) . '/lib/formfields/formfield.domain_ssleditor.php'; $title = ['title']; $image = $ssleditor_data['domain_ssleditor']['image']; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains', 'page' =&gt; 'domainssleditor', 'id' =&gt; $id]), 'formdata' =&gt; $ssleditor_data['domain_ssleditor'], 'editid' =&gt; $id, 'actions_links' =&gt; [ [ 'class' =&gt; 'btn-outline-secondary', 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'domains', 'page' =&gt; 'domains', 'action' =&gt; 'edit', 'id' =&gt; $id ]), 'label' =&gt; lng('admin.domain_edit'), 'icon' =&gt; 'fa-solid fa-pen' ], [ 'class' =&gt; 'btn-outline-primary', 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains', 'page' =&gt; 'overview']), 'label' =&gt; lng('admin.domains'), 'icon' =&gt; 'fa-solid fa-globe' ] ] ]); }</file><file name="customer_extras.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'customer'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\datadump datadump; use froxlor\api\commands\diroptions diroptions; use froxlor\api\commands\dirprotections dirprotections; use froxlor\customer\customer; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\settings; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; // redirect customer page hidden via settings (settings::isinlist('panel.customer_hide_options', 'extras')) { response::redirectto('customer_index.php'); } $id = (int)request::any('id'); ($page == 'overview' || $page == 'htpasswds') { // redirect customer sub-page hidden via settings (settings::isinlist('panel.customer_hide_options', 'extras.directoryprotection')) { response::redirectto('customer_index.php'); } ($action == '') { $log-&gt;logaction(froxlorlogger::usr_action, log_notice, "viewed customer_extras::htpasswds"); $fields = [ 'username' =&gt; lng('login.username'), 'path' =&gt; lng('panel.path') ]; try { $htpasswd_list_data = include_once dirname(__file__) . '/lib/tablelisting/customer/tablelisting.htpasswd.php'; $collection = (new collection(dirprotections::class, $userinfo)) -&gt;withpagination($htpasswd_list_data['htpasswd_list']['columns'], $htpasswd_list_data['htpasswd_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $actions_links = []; $actions_links[] = [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'extras', 'page' =&gt; 'htpasswds', 'action' =&gt; 'add']), 'label' =&gt; lng('extras.directoryprotection_add') ]; $actions_links[] = [ 'href' =&gt; \froxlor\froxlor::getdocsurl() . 'user-guide/extras/', 'target' =&gt; '_blank', 'icon' =&gt; 'fa-solid fa-circle-info', 'class' =&gt; 'btn-outline-secondary' ]; ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $htpasswd_list_data, 'htpasswd_list'), 'actions_links' =&gt; $actions_links, 'entity_info' =&gt; lng('extras.description') ]); } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = dirprotections::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['username']) &amp;&amp; $result['username'] != '') { (request::post('send') == 'send') { try { dirprotections::getlocal($userinfo, request::postall())-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { (strpos($result['path'], $userinfo['documentroot']) === 0) { $result['path'] = str_replace($userinfo['documentroot'], "/", $result['path']); } html::askyesno('extras_reallydelete', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $result['username'] . ' (' . $result['path'] . ')'); } } } elseif ($action == 'add') { (request::post('send') == 'send') { try { dirprotections::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $pathselect = filedir::makepathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); $htpasswd_add_data = include_once dirname(__file__) . '/lib/formfields/customer/extras/formfield.htpasswd_add.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'extras']), 'formdata' =&gt; $htpasswd_add_data['htpasswd_add'] ]); } } elseif ($action == 'edit' &amp;&amp; $id != 0) { try { $json_result = dirprotections::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['username']) &amp;&amp; $result['username'] != '') { (request::post('send') == 'send') { try { dirprotections::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { (strpos($result['path'], $userinfo['documentroot']) === 0) { $result['path'] = str_replace($userinfo['documentroot'], "/", $result['path']); } $result = phphelper::htmlentitiesarray($result); $htpasswd_edit_data = include_once dirname(__file__) . '/lib/formfields/customer/extras/formfield.htpasswd_edit.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'extras', 'id' =&gt; $id]), 'formdata' =&gt; $htpasswd_edit_data['htpasswd_edit'], 'editid' =&gt; $id ]); } } } } elseif ($page == 'htaccess') { // redirect customer sub-page hidden via settings (settings::isinlist('panel.customer_hide_options', 'extras.pathoptions')) { response::redirectto('customer_index.php'); } ($action == '') { $log-&gt;logaction(froxlorlogger::usr_action, log_notice, "viewed customer_extras::htaccess"); $cperlenabled = customer::customerhasperlenabled($userinfo['customerid']); try { $htaccess_list_data = include_once dirname(__file__) . '/lib/tablelisting/customer/tablelisting.htaccess.php'; $collection = (new collection(diroptions::class, $userinfo)) -&gt;withpagination($htaccess_list_data['htaccess_list']['columns'], $htaccess_list_data['htaccess_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $actions_links = []; $actions_links[] = [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'extras', 'page' =&gt; 'htaccess', 'action' =&gt; 'add']), 'label' =&gt; lng('extras.pathoptions_add') ]; $actions_links[] = [ 'href' =&gt; \froxlor\froxlor::getdocsurl() . 'user-guide/extras/', 'target' =&gt; '_blank', 'icon' =&gt; 'fa-solid fa-circle-info', 'class' =&gt; 'btn-outline-secondary' ]; ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $htaccess_list_data, 'htaccess_list'), 'actions_links' =&gt; $actions_links, 'entity_info' =&gt; lng('extras.description') ]); } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = diroptions::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['customerid']) &amp;&amp; $result['customerid'] != '' &amp;&amp; $result['customerid'] == $userinfo['customerid']) { (request::post('send') == 'send') { try { diroptions::getlocal($userinfo, request::postall())-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesno('extras_reallydelete_pathoptions', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], str_replace($userinfo['documentroot'], '/', $result['path'])); } } } elseif ($action == 'add') { (request::post('send') == 'send') { try { diroptions::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $pathselect = filedir::makepathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); $cperlenabled = customer::customerhasperlenabled($userinfo['customerid']); $htaccess_add_data = include_once dirname(__file__) . '/lib/formfields/customer/extras/formfield.htaccess_add.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'extras']), 'formdata' =&gt; $htaccess_add_data['htaccess_add'] ]); } } elseif (($action == 'edit') &amp;&amp; ($id != 0)) { try { $json_result = diroptions::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ((isset($result['customerid'])) &amp;&amp; ($result['customerid'] != '') &amp;&amp; ($result['customerid'] == $userinfo['customerid'])) { (request::post('send') == 'send') { try { diroptions::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { (strpos($result['path'], $userinfo['documentroot']) === 0) { $result['path'] = str_replace($userinfo['documentroot'], "/", $result['path']); } $cperlenabled = customer::customerhasperlenabled($userinfo['customerid']); $result = phphelper::htmlentitiesarray($result); $htaccess_edit_data = include_once dirname(__file__) . '/lib/formfields/customer/extras/formfield.htaccess_edit.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'extras', 'id' =&gt; $id]), 'formdata' =&gt; $htaccess_edit_data['htaccess_edit'], 'editid' =&gt; $id ]); } } } } elseif ($page == 'export') { // redirect customer sub-page hidden via settings (settings::isinlist('panel.customer_hide_options', 'extras.export')) { response::redirectto('customer_index.php'); } (settings::get('system.exportenabled') == 1) { ($action == 'abort') { (request::post('send') == 'send') { $log-&gt;logaction(froxlorlogger::usr_action, log_notice, "customer_extras::export - aborted scheduled data export job"); try { datadump::getlocal($userinfo, request::postall())-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page, 'action' =&gt; '' ]); } else { html::askyesno('extras_reallydelete_export', $filename, [ 'job_entry' =&gt; $id, 'section' =&gt; 'extras', 'page' =&gt; $page, 'action' =&gt; $action ]); } } elseif ($action == '') { $log-&gt;logaction(froxlorlogger::usr_action, log_info, "viewed customer_extras::export"); // check whether backup-job customer try { $export_list_data = include_once dirname(__file__) . '/lib/tablelisting/customer/tablelisting.export.php'; $collection = (new collection(datadump::class, $userinfo)); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } (request::post('send') == 'send') { try { datadump::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::standardsuccess('exportscheduled'); } else { $pathselect = filedir::makepathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); $export_data = include_once dirname(__file__) . '/lib/formfields/customer/extras/formfield.export.php'; $actions_links = [ [ 'href' =&gt; \froxlor\froxlor::getdocsurl() . 'user-guide/extras/', 'target' =&gt; '_blank', 'icon' =&gt; 'fa-solid fa-circle-info', 'class' =&gt; 'btn-outline-secondary' ] ]; ui::view('user/form-datatable.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'extras']), 'formdata' =&gt; $export_data['export'], 'actions_links' =&gt; $actions_links, 'tabledata' =&gt; listing::format($collection, $export_list_data, 'export_list'), ]); } } } else { response::standarderror('exportfunctionnotenabled'); } }</file><file name="admin_opcacheinfo.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @author janos muzsi &lt;muzsij@hypernics.hu&gt; * @author andrew collington &lt;andy@amnuts.com&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 * * based https://github.com/amnuts/opcache-gui, * licensed mit licence, viewed * online https://acollington.mit-license.org/ */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\froxlorlogger; use froxlor\ui\html; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; ($action == 'reset' &amp;&amp; function_exists('opcache_reset') &amp;&amp; $userinfo['change_serversettings'] == '1') { (request::post('send') == 'send') { opcache_reset(); $log-&gt;logaction(froxlorlogger::adm_action, log_info, "reset opcache"); header('location: ' . $linker-&gt;getlink([ 'section' =&gt; 'opcacheinfo', 'page' =&gt; 'showinfo' ])); exit(); } else { html::askyesno('cache_reallydelete', $filename, [ 'page' =&gt; $page, 'action' =&gt; 'reset', ], '', [ 'section' =&gt; 'opcacheinfo', 'page' =&gt; 'showinfo' ]); } } (!extension_loaded('zend opcache')) { response::standarderror('no_opcacheinfo'); } $ocenabled = ini_get('opcache.enable'); (empty($ocenabled)) { response::standarderror('inactive_opcacheinfo'); } ($page == 'showinfo' &amp;&amp; $userinfo['change_serversettings'] == '1') { $time = time(); $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "viewed opcache info"); $opcache = (new \amnuts\opcache\service())-&gt;getdata(); ui::view('settings/opcacheinfo.html.twig', [ 'opcacheinfo' =&gt; [ 'version' =&gt; $opcache['version'], 'overview' =&gt; $opcache['overview'], 'files' =&gt; $opcache['files'], 'preload' =&gt; $opcache['preload'], 'directives' =&gt; $opcache['directives'], 'blacklist' =&gt; $opcache['blacklist'], 'functions' =&gt; $opcache['functions'], ] ]); }</file><file name="api.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\api\api; use froxlor\api\response; require __dir__ . '/vendor/autoload.php'; require __dir__ . '/lib/functions.php'; require __dir__ . '/lib/tables.inc.php'; // set error-handler @set_error_handler([ '\\froxlor\\api\\api', 'phperrhandler' ]); // return response try { echo (new api)-&gt;formatmiddleware(@file_get_contents('php://input'))-&gt;handle(); } catch (exception $e) { echo response::jsonerrorresponse($e-&gt;getmessage(), $e-&gt;getcode()); }</file><file name="package.json">{ "name": "froxlor", "private": true, "scripts": { "dev": "vite", "build": "vite build" }, "devdependencies": { "@fortawesome/fontawesome-free": "^6.4.2", "@popperjs/core": "^2.11.8", "@vitejs/plugin-vue": "^4.0.0", "axios": "^1.7.4", "bootstrap": "^5.3.2", "chart.js": "^4.4.0", "jquery": "^3.6.1", "jquery-validation": "^1.20.0", "laravel-vite-plugin": "^0.8.0", "lodash": "^4.17.19", "postcss": "^8.1.14", "resolve-url-loader": "^5.0.0", "sass": "^1.69.3", "vite": "^4.5.9", "vue": "^3.2.37" }, "engines": { "node": "&gt;=18" } }</file><file name="customer_domains.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'customer'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\subdomains; use froxlor\currentuser; use froxlor\database\database; use froxlor\domain\domain; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\settings; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\validate\validate; // redirect customer page hidden via settings (settings::isinlist('panel.customer_hide_options', 'domains')) { response::redirectto('customer_index.php'); } $id = (int)request::any('id'); ($page == 'overview' || $page == 'domains') { ($action == '') { $log-&gt;logaction(froxlorlogger::usr_action, log_info, "viewed customer_domains::domains"); $parentdomain_id = (int)request::any('pid', '0'); try { $domain_list_data = include_once dirname(__file__) . '/lib/tablelisting/customer/tablelisting.domains.php'; $collection = (new collection(subdomains::class, $userinfo)) -&gt;withpagination($domain_list_data['domain_list']['columns'], $domain_list_data['domain_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $actions_links = []; (currentuser::canaddresource('subdomains')) { $actions_links[] = [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains', 'page' =&gt; 'domains', 'action' =&gt; 'add']), 'label' =&gt; lng('domains.subdomain_add') ]; } $actions_links[] = [ 'href' =&gt; \froxlor\froxlor::getdocsurl() . 'user-guide/domains/', 'target' =&gt; '_blank', 'icon' =&gt; 'fa-solid fa-circle-info', 'class' =&gt; 'btn-outline-secondary' ]; $table_tpl = 'table.html.twig'; ($collection-&gt;count() == 0) { $table_tpl = 'table-note.html.twig'; } ui::view('user/' . $table_tpl, [ 'listing' =&gt; listing::format($collection, $domain_list_data, 'domain_list'), 'actions_links' =&gt; $actions_links, 'entity_info' =&gt; lng('domains.description'), // alert-box 'type' =&gt; 'warning', 'alert_msg' =&gt; lng('domains.nodomainsassignedbyadmin') ]); } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = subdomains::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; $alias_stmt = database::prepare("select count(`id`) `count` `" . table_panel_domains . "` `aliasdomain` = :aliasdomain"); $alias_check = database::pexecute_first($alias_stmt, [ "aliasdomain" =&gt; $id ]); (isset($result['parentdomainid']) &amp;&amp; $result['parentdomainid'] != '0' &amp;&amp; $alias_check['count'] == 0) { (request::post('send') == 'send') { try { subdomains::getlocal($userinfo, request::postall())-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesno('domains_reallydelete', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $idna_convert-&gt;decode($result['domain'])); } } else { response::standarderror('domains_cantdeletemaindomain'); } } elseif ($action == 'add') { ($userinfo['subdomains_used'] &lt; $userinfo['subdomains'] || $userinfo['subdomains'] == '-1') { (request::post('send') == 'send') { try { subdomains::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $stmt = database::prepare("select `id`, `domain`, `documentroot`, `ssl_redirect`,`isemaildomain`,`letsencrypt` `" . table_panel_domains . "` `customerid` = :customerid `parentdomainid` = '0' `email_only` = '0' `deactivated` = '0' order `domain` asc"); database::pexecute($stmt, [ "customerid" =&gt; $userinfo['customerid'] ]); $domains = []; ($row = $stmt-&gt;fetch(pdo::fetch_assoc)) { $domains[$row['domain']] = $idna_convert-&gt;decode($row['domain']); } // check domains used (count($domains) &lt;= 0) { // no, possible direct url access, redirect overview response::redirectto($filename, [ 'page' =&gt; $page ]); } $aliasdomains[0] = lng('domains.noaliasdomain'); $domains_stmt = database::prepare("select `d`.`id`, `d`.`domain` `" . table_panel_domains . "` `d`, `" . table_panel_customers . "` `c` `d`.`aliasdomain` null `d`.`id` &lt;&gt; `c`.`standardsubdomain` `d`.`parentdomainid` = '0' `d`.`customerid`=`c`.`customerid` `d`.`email_only`='0' `d`.`customerid`= :customerid order `d`.`domain` asc"); database::pexecute($domains_stmt, [ "customerid" =&gt; $userinfo['customerid'] ]); ($row_domain = $domains_stmt-&gt;fetch(pdo::fetch_assoc)) { $aliasdomains[$row_domain['id']] = $idna_convert-&gt;decode($row_domain['domain']); } $redirectcode = []; (settings::get('customredirect.enabled') == '1') { $codes = domain::getredirectcodesarray(); foreach ($codes $rc) { $redirectcode[$rc['id']] = $rc['code'] . ' (' . lng('redirect_desc.' . $rc['desc']) . ')'; } } // check least one ssl-ip/port, #1179 $ssl_ipsandports = false; $ssl_ip_stmt = database::prepare(" select count(*) countssl `" . table_panel_ipsandports . "` pip left join `" . table_domaintoip . "` dti dti.id_ipandports = pip.id pip.`ssl`='1' "); database::pexecute($ssl_ip_stmt); $resultx = $ssl_ip_stmt-&gt;fetch(pdo::fetch_assoc); (isset($resultx['countssl']) &amp;&amp; (int)$resultx['countssl'] &gt; 0) { $ssl_ipsandports = true; } $openbasedir = [ 0 =&gt; lng('domain.docroot'), 1 =&gt; lng('domain.homedir'), 2 =&gt; lng('domain.docparent') ]; $pathselect = filedir::makepathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); $phpconfigs = []; (isset($userinfo['allowed_phpconfigs']) &amp;&amp; !empty($userinfo['allowed_phpconfigs'])) { $allowed_cfg = json_decode($userinfo['allowed_phpconfigs'], json_object_as_array); $phpconfigs_result_stmt = database::query(" select c.*, fc.description interpreter `" . table_panel_phpconfigs . "` c left join `" . table_panel_fpmdaemons . "` fc fc.id = c.fpmsettingid c.id (" . implode(", ", $allowed_cfg) . ") "); ($phpconfigs_row = $phpconfigs_result_stmt-&gt;fetch(pdo::fetch_assoc)) { ((int)settings::get('phpfpm.enabled') == 1) { $phpconfigs[$phpconfigs_row['id']] = $phpconfigs_row['description'] . " [" . $phpconfigs_row['interpreter'] . "]"; } else { $phpconfigs[$phpconfigs_row['id']] = $phpconfigs_row['description']; } } } $subdomain_add_data = include_once dirname(__file__) . '/lib/formfields/customer/domains/formfield.domains_add.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains']), 'formdata' =&gt; $subdomain_add_data['domain_add'] ]); } } } elseif ($action == 'edit' &amp;&amp; $id != 0) { try { $json_result = subdomains::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['customerid']) &amp;&amp; $result['customerid'] == $userinfo['customerid']) { ((int)$result['caneditdomain'] == 0) { response::standarderror('domaincannotbeedited', $result['domain']); } (request::post('send') == 'send') { try { subdomains::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $result['domain'] = $idna_convert-&gt;decode($result['domain']); $domains[0] = lng('domains.noaliasdomain'); // also check ip/port combination same, #176 $domains_stmt = database::prepare("select `d`.`id`, `d`.`domain` `" . table_panel_domains . "` `d` , `" . table_panel_customers . "` `c` , `" . table_domaintoip . "` `dip` `d`.`aliasdomain` null `d`.`id` &lt;&gt; :id `c`.`standardsubdomain` &lt;&gt; `d`.`id` `d`.`parentdomainid` = '0' `d`.`customerid` = :customerid `c`.`customerid` = `d`.`customerid` `d`.`id` = `dip`.`id_domain` `dip`.`id_ipandports` (select `id_ipandports` `" . table_domaintoip . "` `id_domain` = :id) group `d`.`id`, `d`.`domain` order `d`.`domain` asc"); database::pexecute($domains_stmt, [ "id" =&gt; $result['id'], "customerid" =&gt; $userinfo['customerid'] ]); ($row_domain = $domains_stmt-&gt;fetch(pdo::fetch_assoc)) { $domains[$row_domain['id']] = $idna_convert-&gt;decode($row_domain['domain']); } (preg_match('/^https?\:\/\//', $result['documentroot']) &amp;&amp; validate::validateurl($result['documentroot'])) { (settings::get('panel.pathedit') == 'dropdown') { $urlvalue = $result['documentroot']; $pathselect = filedir::makepathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); } else { $urlvalue = ''; $pathselect = filedir::makepathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid'], $result['documentroot'], true); } } else { $urlvalue = ''; $pathselect = filedir::makepathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid'], $result['documentroot']); } $redirectcode = []; (settings::get('customredirect.enabled') == '1') { $def_code = domain::getdomainredirectid($id); $codes = domain::getredirectcodesarray(); foreach ($codes $rc) { $redirectcode[$rc['id']] = $rc['code'] . ' (' . lng('redirect_desc.' . $rc['desc']) . ')'; } } // check least one ssl-ip/port, #1179 $ssl_ipsandports = false; $ssl_ip_stmt = database::prepare(" select count(*) countssl `" . table_panel_ipsandports . "` pip left join `" . table_domaintoip . "` dti dti.id_ipandports = pip.id `dti`.`id_domain` = :id_domain pip.`ssl`='1' "); database::pexecute($ssl_ip_stmt, [ "id_domain" =&gt; $result['id'] ]); $resultx = $ssl_ip_stmt-&gt;fetch(pdo::fetch_assoc); (isset($resultx['countssl']) &amp;&amp; (int)$resultx['countssl'] &gt; 0) { $ssl_ipsandports = true; } // fudge result ssl_redirect hide let's encrypt steps $result['temporary_ssl_redirect'] = $result['ssl_redirect']; $result['ssl_redirect'] = ($result['ssl_redirect'] == 0 ? 0 : 1); $openbasedir = [ 0 =&gt; lng('domain.docroot'), 1 =&gt; lng('domain.homedir'), 2 =&gt; lng('domain.docparent') ]; // create serveralias options $serveraliasoptions = []; $serveraliasoptions_selected = '2'; ($result['iswildcarddomain'] == '1') { $serveraliasoptions_selected = '0'; } elseif ($result['wwwserveralias'] == '1') { $serveraliasoptions_selected = '1'; } $serveraliasoptions[0] = lng('domains.serveraliasoption_wildcard'); $serveraliasoptions[1] = lng('domains.serveraliasoption_www'); $serveraliasoptions[2] = lng('domains.serveraliasoption_none'); $ips_stmt = database::prepare("select `p`.`ip` `ip` `" . table_panel_ipsandports . "` `p` left join `" . table_domaintoip . "` `dip` ( `dip`.`id_ipandports` = `p`.`id` ) `dip`.`id_domain` = :id_domain group `p`.`ip`"); database::pexecute($ips_stmt, [ "id_domain" =&gt; $result['id'] ]); $domainips = []; ($rowip = $ips_stmt-&gt;fetch(pdo::fetch_assoc)) { $domainips[] = ['item' =&gt; $rowip['ip']]; } $phpconfigs = []; (isset($userinfo['allowed_phpconfigs']) &amp;&amp; !empty($userinfo['allowed_phpconfigs'])) { $allowed_cfg = json_decode($userinfo['allowed_phpconfigs'], json_object_as_array); $phpconfigs_result_stmt = database::query(" select c.*, fc.description interpreter `" . table_panel_phpconfigs . "` c left join `" . table_panel_fpmdaemons . "` fc fc.id = c.fpmsettingid c.id (" . implode(", ", $allowed_cfg) . ") "); ($phpconfigs_row = $phpconfigs_result_stmt-&gt;fetch(pdo::fetch_assoc)) { ((int)settings::get('phpfpm.enabled') == 1) { $phpconfigs[$phpconfigs_row['id']] = $phpconfigs_row['description'] . " [" . $phpconfigs_row['interpreter'] . "]"; } else { $phpconfigs[$phpconfigs_row['id']] = $phpconfigs_row['description']; } } } $alias_stmt = database::prepare("select count(`id`) count `" . table_panel_domains . "` `aliasdomain`= :aliasdomain"); $alias_check = database::pexecute_first($alias_stmt, [ "aliasdomain" =&gt; $result['id'] ]); $alias_check = $alias_check['count']; $result = phphelper::htmlentitiesarray($result); $subdomain_edit_data = include_once dirname(__file__) . '/lib/formfields/customer/domains/formfield.domains_edit.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains', 'id' =&gt; $id]), 'formdata' =&gt; $subdomain_edit_data['domain_edit'], 'editid' =&gt; $id ]); } } else { response::standarderror('domains_canteditdomain'); } } elseif ($action == 'jqspeciallogfilenote') { $domainid = intval(request::post('id')); $newval = intval(request::post('newval')); try { $json_result = subdomains::getlocal($userinfo, [ 'id' =&gt; $domainid ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($newval != $result['speciallogfile']) { echo json_encode(['changed' =&gt; true, 'info' =&gt; lng('admin.speciallogwarning')]); exit(); } echo 0; exit(); } } elseif ($page == 'domainssleditor') { require_once __dir__ . '/ssl_editor.php'; } elseif ($page == 'domaindnseditor' &amp;&amp; $userinfo['dnsenabled'] == '1' &amp;&amp; settings::get('system.dnsenabled') == '1') { require_once __dir__ . '/dns_editor.php'; } elseif ($page == 'sslcertificates') { require_once __dir__ . '/ssl_certificates.php'; } elseif ($page == 'logfiles') { require_once __dir__ . '/logfiles_viewer.php'; }</file><file name="customer_mysql.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'customer'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\mysqls; use froxlor\api\commands\mysqlserver; use froxlor\currentuser; use froxlor\database\database; use froxlor\database\dbmanager; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\system\crypt; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; // redirect customer page hidden via settings resources given (settings::isinlist('panel.customer_hide_options', 'mysql') || $userinfo['mysqls'] == 0) { response::redirectto('customer_index.php'); } // get sql-root access data database::needroot(true); database::needsqldata(); $sql_root = database::getsqldata(); database::needroot(false); $id = (int)request::any('id'); ($page == 'overview' || $page == 'mysqls') { ($action == '') { $log-&gt;logaction(froxlorlogger::usr_action, log_notice, "viewed customer_mysql::mysqls"); $multiple_mysqlservers = count(json_decode($userinfo['allowed_mysqlserver'] ?? '[]', true)) &gt; 1; try { $mysql_list_data = include_once dirname(__file__) . '/lib/tablelisting/customer/tablelisting.mysqls.php'; $collection = (new collection(mysqls::class, $userinfo)) -&gt;withpagination($mysql_list_data['mysql_list']['columns'], $mysql_list_data['mysql_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $actions_links = []; (currentuser::canaddresource('mysqls')) { $actions_links[] = [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'mysql', 'page' =&gt; 'mysqls', 'action' =&gt; 'add']), 'label' =&gt; lng('mysql.database_create') ]; } $view = 'user/table.html.twig'; ($collection-&gt;count() &gt; 0) { $view = 'user/table-note.html.twig'; $actions_links[] = [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'mysql', 'page' =&gt; 'mysqls', 'action' =&gt; 'global_user']), 'label' =&gt; lng('mysql.edit_global_user'), 'icon' =&gt; 'fa-solid fa-user-tie', 'class' =&gt; 'btn-outline-secondary' ]; } $actions_links[] = [ 'href' =&gt; \froxlor\froxlor::getdocsurl() . 'user-guide/databases/', 'target' =&gt; '_blank', 'icon' =&gt; 'fa-solid fa-circle-info', 'class' =&gt; 'btn-outline-secondary' ]; ui::view($view, [ 'listing' =&gt; listing::format($collection, $mysql_list_data, 'mysql_list'), 'actions_links' =&gt; $actions_links, 'entity_info' =&gt; lng('mysql.description'), // alert-box 'type' =&gt; 'info', 'alert_msg' =&gt; lng('mysql.globaluserinfo', [$userinfo['loginname']]), ]); } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = mysqls::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['databasename']) &amp;&amp; $result['databasename'] != '') { database::needroot(true, $result['dbserver'], false); database::needsqldata(); $sql_root = database::getsqldata(); database::needroot(false); (!isset($sql_root[$result['dbserver']]) || !is_array($sql_root[$result['dbserver']])) { $result['dbserver'] = 0; } (request::post('send') == 'send') { try { mysqls::getlocal($userinfo, request::postall())-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $dbnamedesc = $result['databasename']; (isset($result['description']) &amp;&amp; $result['description'] != '') { $dbnamedesc .= ' (' . $result['description'] . ')'; } html::askyesno('mysql_reallydelete', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $dbnamedesc); } } } elseif ($action == 'add') { ($userinfo['mysqls_used'] &lt; $userinfo['mysqls'] || $userinfo['mysqls'] == '-1') { (request::post('send') == 'send') { try { mysqls::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $mysql_servers = []; try { $result_json = mysqlserver::getlocal($userinfo)-&gt;listing(); $result_decoded = json_decode($result_json, true)['data']['list']; foreach ($result_decoded $dbserver =&gt; $dbdata) { $mysql_servers[$dbserver] = $dbdata['caption']; } } catch (exception $e) { /* none */ } $mysql_add_data = include_once dirname(__file__) . '/lib/formfields/customer/mysql/formfield.mysql_add.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'mysql']), 'formdata' =&gt; $mysql_add_data['mysql_add'] ]); } } } elseif ($action == 'edit' &amp;&amp; $id != 0) { try { $json_result = mysqls::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['databasename']) &amp;&amp; $result['databasename'] != '') { (request::post('send') == 'send') { try { $json_result = mysqls::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $mysql_servers = []; try { $result_json = mysqlserver::getlocal($userinfo)-&gt;listing(); $result_decoded = json_decode($result_json, true)['data']['list']; foreach ($result_decoded $dbserver =&gt; $dbdata) { $mysql_servers[$dbserver] = $dbdata['caption'] . ' (' . $dbdata['host'] . (isset($dbdata['port']) &amp;&amp; !empty($dbdata['port']) ? ':' . $dbdata['port'] : '') . ')'; } } catch (exception $e) { /* none */ } $mysql_edit_data = include_once dirname(__file__) . '/lib/formfields/customer/mysql/formfield.mysql_edit.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'mysql', 'id' =&gt; $id]), 'formdata' =&gt; $mysql_edit_data['mysql_edit'], 'editid' =&gt; $id ]); } } } elseif ($action == 'global_user') { $allowed_mysqlservers = json_decode($userinfo['allowed_mysqlserver'] ?? '[]', true); ($userinfo['mysqls'] == 0 || empty($allowed_mysqlservers)) { response::dynamicerror('no permission'); } (request::post('send') == 'send') { $new_password = crypt::validatepassword(request::post('mysql_password')); foreach ($allowed_mysqlservers $dbserver) { // require privileged access target db-server database::needroot(true, $dbserver, true); // get dbmanager $dbm = new dbmanager($log); // give permission user every access-host foreach (array_map('trim', explode(',', settings::get('system.mysql_access_host'))) $mysql_access_host) { ($dbm-&gt;getmanager()-&gt;userexistsonhost($userinfo['loginname'], $mysql_access_host)) { // update password $dbm-&gt;getmanager()-&gt;grantprivilegesto($userinfo['loginname'], $new_password, $mysql_access_host, false, true, true); } else { // create missing user $dbm-&gt;getmanager()-&gt;grantprivilegesto($userinfo['loginname'], $new_password, $mysql_access_host, false, false, true); } } $dbm-&gt;getmanager()-&gt;flushprivileges(); } response::redirectto($filename, [ 'page' =&gt; 'overview' ]); } else { $mysql_global_user_data = include_once dirname(__file__) . '/lib/formfields/customer/mysql/formfield.mysql_global_user.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'mysql', 'page' =&gt; 'mysqls', 'action' =&gt; 'global_user']), 'formdata' =&gt; $mysql_global_user_data['mysql_global_user'], 'editid' =&gt; $id ]); } } }</file><file name="admin_configfiles.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\config\configparser; use froxlor\filedir; use froxlor\froxlor; use froxlor\settings; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\validate\validate; ($userinfo['change_serversettings'] == '1') { ($action == 'setconfigured') { settings::set('panel.is_configured', '1', true); response::redirectto('admin_configfiles.php'); } // get distro url param $distribution = request::any('distribution'); $reselect = request::any('reselect', 0); // check possible setting (empty($distribution)) { $distribution = settings::get('system.distribution') ?? ""; } ($reselect == 1) { $distribution = ''; } $distributions_select = []; $services = []; $config_dir = filedir::makecorrectdir(froxlor::getinstalldir() . '/lib/configfiles/'); (!empty($distribution)) { (!file_exists($config_dir . '/' . $distribution . ".xml")) { // unknown distribution -&gt; redirect select valid distribution config-templates settings::set('system.distribution', ''); response::redirectto('admin_configfiles.php', ['reselect' =&gt; 1]); } // update setting different ($distribution != settings::get('system.distribution')) { settings::set('system.distribution', $distribution); } // create configparser object $configfiles = new configparser($config_dir . '/' . $distribution . ".xml"); // get distro-info $dist_display = $configfiles-&gt;getcompletedistroname(); // get services distro $services = $configfiles-&gt;getservices(); } else { // show list available distro's $distros = glob($config_dir . '*.xml'); // read distros foreach ($distros $_distribution) { // get configparser object $dist = new configparser($_distribution); // store tmp array $distributions_select[str_replace(".xml", "", strtolower(basename($_distribution)))] = $dist-&gt;getcompletedistroname(); } // sort distribution name asort($distributions_select); } ($distribution != "" &amp;&amp; !empty(request::post('finish'))) { $valid_keys = ['http', 'dns', 'smtp', 'mail', 'antispam', 'ftp', 'system', 'distro']; unset($_post['finish']); unset($_post['csrf_token']); $params = request::postall(); $params['distro'] = $distribution; $params['system'] = []; foreach (request::post('system', []) $sysdaemon) { $params['system'][] = $sysdaemon; } // validate params foreach ($params $key =&gt; $value) { (!in_array($key, $valid_keys)) { unset($params[$key]); continue; } (!is_array($value)) { $params[$key] = validate::validate($value, $key); } else { foreach ($value $subkey =&gt; $subvalue) { $params[$key][$subkey] = validate::validate($subvalue, $key.'.'.$subkey); } } } $params_content = json_encode($params); $params_filename = filedir::makecorrectfile(froxlor::getinstalldir() . 'install/' . froxlor::gensessionid() . '.json'); file_put_contents($params_filename, $params_content); ui::twigbuffer('settings/configuration-final.html.twig', [ 'distribution' =&gt; $distribution, // alert 'type' =&gt; 'info', 'alert_msg' =&gt; lng('admin.configfiles.finishnote'), 'basedir' =&gt; froxlor::getinstalldir(), 'params_filename' =&gt; $params_filename ]); } else { (!empty($distribution)) { // show available services configure $fields = $services; $link_params = ['section' =&gt; 'configfiles', 'distribution' =&gt; $distribution]; ui::twigbuffer('settings/configuration.html.twig', [ 'action' =&gt; $linker-&gt;getlink($link_params), 'fields' =&gt; $fields, 'distribution' =&gt; $distribution ]); } else { $cfg_formfield = [ 'config' =&gt; [ 'title' =&gt; lng('admin.configfiles.serverconfiguration'), 'image' =&gt; 'fa-solid fa-wrench', 'description' =&gt; lng('admin.configfiles.description'), 'sections' =&gt; [ 'section_config' =&gt; [ 'fields' =&gt; [ 'distribution' =&gt; [ 'type' =&gt; 'select', 'select_var' =&gt; $distributions_select, 'label' =&gt; lng('admin.configfiles.distribution'), 'selected' =&gt; settings::get('system.distribution') ?? '' ] ] ] ], 'buttons' =&gt; [ [ 'class' =&gt; 'btn-outline-secondary', 'label' =&gt; lng('panel.cancel'), 'type' =&gt; 'reset' ], [ 'label' =&gt; lng('update.proceed') ] ] ] ]; ui::twigbuffer('user/form-note.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'configfiles']), 'formdata' =&gt; $cfg_formfield['config'], 'actions_links' =&gt; (int)settings::get('panel.is_configured') == 0 ? [ [ 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'configfiles', 'page' =&gt; 'overview', 'action' =&gt; 'setconfigured' ]), 'label' =&gt; lng('panel.ihave_configured'), 'class' =&gt; 'btn-outline-warning', 'icon' =&gt; 'fa-solid fa-circle-check' ] ] : [], // alert 'type' =&gt; 'warning', 'alert_msg' =&gt; lng('panel.settings_before_configuration') . ((int)settings::get('panel.is_configured') == 1 ? '&lt;br&gt;&lt;br&gt;' . lng('panel.system_is_configured') : '') ]); } } ui::twigoutputbuffer(); } else { response::redirectto('admin_index.php'); }</file><file name="admin_traffic.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\traffic\traffic; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; $range = request::any('range', 'currentmonth'); ($page == 'overview' || $page == 'customers') { try { $context = traffic::getcustomerstats($userinfo, $range); } catch (exception $e) { ($e-&gt;getcode() === 405) { response::dynamicerror(lng('traffic.nocustomers')); } response::dynamicerror($e-&gt;getmessage()); } // pass metrics view ui::view('user/traffic.html.twig', $context); }</file><file name="composer.json">{ "name": "froxlor/froxlor", "description": "the server administration software needs. developed experienced server administrators, panel simplifies effort managing hosting platform.", "keywords": [ "server", "administration", "php" ], "homepage": "https://www.froxlor.org", "license": "gpl-2.0-or-later", "authors": [ { "name": "michael kaufmann", "email": "team@froxlor.org", "role": "lead developer" } ], "support": { "email": "team@froxlor.org", "issues": "https://github.com/froxlor/froxlor/issues", "forum": "https://forum.froxlor.org/", "source": "https://github.com/froxlor/froxlor", "docs": "https://docs.froxlor.org/", "chat": "https://discord.froxlor.org/" }, "funding": [ { "type": "github", "url": "https://github.com/sponsors/d00p" } ], "require": { "php": "^7.4 || ^8.0", "ext-session": "*", "ext-ctype": "*", "ext-pdo": "*", "ext-pdo_mysql": "*", "ext-simplexml": "*", "ext-xml": "*", "ext-filter": "*", "ext-posix": "*", "ext-mbstring": "*", "ext-curl": "*", "ext-json": "*", "ext-openssl": "*", "ext-fileinfo": "*", "ext-gmp": "*", "ext-gd": "*", "ext-gnupg": "*", "phpmailer/phpmailer": "~6.0", "monolog/monolog": "^1.24", "robthree/twofactorauth": "^1.6", "froxlor/idna-convert-legacy": "^2.1", "voku/anti-xss": "^4.1", "twig/twig": "^3.3", "symfony/console": "^5.4", "pear/net_dns2": "^1.5", "amnuts/opcache-gui": "^3.4", "league/commonmark": "^2.4" }, "require-dev": { "phpunit/phpunit": "^9", "ext-pcntl": "*", "phpcompatibility/php-compatibility": "*", "squizlabs/php_codesniffer": "*", "pdepend/pdepend": "^2.9", "sebastian/phpcpd": "^6.0", "phploc/phploc": "^7.0", "phpmd/phpmd": "^2.10", "phpunit/php-timer" : "^5", "phpstan/phpstan": "^1.8" }, "suggest": { "ext-bcmath": "*", "ext-zip": "*", "ext-apcu": "*", "ext-readline": "*" }, "config": { "platform": { "php": "7.4" } }, "autoload": { "psr-4": { "froxlor\\": [ "lib/froxlor" ] } }, "scripts": { "post-install-cmd": "if [ -f ./vendor/bin/phpcs ]; \"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility ; fi", "post-update-cmd" : "if [ -f ./vendor/bin/phpcs ]; \"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility ; fi" } }</file><file name="dns_editor.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ (!defined('area')) { header("location: index.php"); exit(); } use froxlor\api\commands\domainzones; use froxlor\dns\dns; use froxlor\settings; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; // file included admin_domains customer_domains // therefore need require lib/init.php $domain_id = (int)request::any('domain_id'); $record = request::post('dns_record'); $type = request::post('dns_type', 'a'); $prio = request::post('dns_mxp'); $content = request::post('dns_content'); $ttl = (int)request::post('dns_ttl', settings::get('system.defaultttl')); // get domain-name $domain = dns::getalloweddomainentry($domain_id, area, $userinfo); $errors = ""; $success_message = ""; // action adding new entry ($action == 'add_record' &amp;&amp; !empty($_post)) { try { domainzones::getlocal($userinfo, [ 'id' =&gt; $domain_id, 'record' =&gt; $record, 'type' =&gt; $type, 'prio' =&gt; $prio, 'content' =&gt; $content, 'ttl' =&gt; $ttl ])-&gt;add(); $success_message = lng('success.dns_record_added'); $record = $prio = $content = ""; } catch (exception $e) { $errors = str_replace("\n", "&lt;br&gt;", $e-&gt;getmessage()); } } elseif ($action == 'delete') { $entry_id = (int)request::get('id', 0); html::askyesno('dnsentry_reallydelete', $filename, [ 'id' =&gt; $entry_id, 'domain_id' =&gt; $domain_id, 'page' =&gt; $page, 'action' =&gt; 'deletesure' ], '', [ 'section' =&gt; 'domains', 'page' =&gt; $page, 'domain_id' =&gt; $domain_id ]); } elseif (request::post('send') == 'send' &amp;&amp; $action == 'deletesure' &amp;&amp; !empty($_post)) { $entry_id = (int)request::post('id', 0); $domain_id = (int)request::post('domain_id', 0); // remove entry ($entry_id &gt; 0 &amp;&amp; $domain_id &gt; 0) { try { domainzones::getlocal($userinfo, [ 'entry_id' =&gt; $entry_id, 'id' =&gt; $domain_id ])-&gt;delete(); // success message (inline) $success_message = lng('success.dns_record_deleted'); } catch (exception $e) { $errors = str_replace("\n", "&lt;br&gt;", $e-&gt;getmessage()); } } } // select entries try { $dns_list_data = include_once dirname(__file__) . '/lib/tablelisting/tablelisting.dns.php'; $collection = (new collection(domainzones::class, $userinfo, ['id' =&gt; $domain_id])) -&gt;withpagination($dns_list_data['dns_list']['columns'], $dns_list_data['dns_list']['default_sorting'], ['domain_id='.$domain_id]); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } try { $json_result = domainzones::getlocal($userinfo, [ 'id' =&gt; $domain_id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; $zonefile = implode("\n", $result); $dns_add_data = include_once dirname(__file__) . '/lib/formfields/formfield.dns_add.php'; ui::view('user/dns-editor.html.twig', [ 'listing' =&gt; listing::format($collection, $dns_list_data, 'dns_list', ['domain_id' =&gt; $domain_id]), 'actions_links' =&gt; [ [ 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'domains', 'page' =&gt; 'domains', 'action' =&gt; 'edit', 'id' =&gt; $domain_id ]), 'label' =&gt; lng('admin.domain_edit'), 'icon' =&gt; 'fa-solid fa-pen' ], [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains', 'page' =&gt; 'domains']), 'label' =&gt; lng('panel.backtooverview'), 'icon' =&gt; 'fa-solid fa-reply' ] ], 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains', 'action' =&gt; 'add_record', 'domain_id' =&gt; $domain_id]), 'formdata' =&gt; $dns_add_data['dns_add'], // alert-box 'type' =&gt; (!empty($errors) ? 'danger' : (!empty($success_message) ? 'success' : 'warning')), 'alert_msg' =&gt; (!empty($errors) ? $errors : (!empty($success_message) ? $success_message : lng('dns.howitworks'))), 'zonefile' =&gt; $zonefile, ]);</file><file name="admin_autoupdate.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\filedir; use froxlor\install\autoupdate; use froxlor\settings; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; ($page != 'error') { // check webupdate enabled (settings::config('enable_webupdate') != true) { response::redirectto($filename, [ 'page' =&gt; 'error', 'errno' =&gt; 11 ]); } } // display initial version check ($page == 'overview') { // log actions $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "checking auto-update"); // check new version try { $result = autoupdate::checkversion(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } ($result == 1) { // anzeige ber version-status mit ggfls. formular // zum update schritt #1 -&gt; download $text = lng('admin.newerversionavailable') . ' ' . lng('admin.newerversiondetails', [autoupdate::getfromresult('version'), froxlor::version]); $upd_formfield = [ 'updates' =&gt; [ 'title' =&gt; lng('update.update'), 'image' =&gt; 'fa-solid fa-download', 'sections' =&gt; [ 'section_autoupd' =&gt; [ 'fields' =&gt; [ 'newversion' =&gt; ['type' =&gt; 'hidden', 'value' =&gt; autoupdate::getfromresult('version')] ] ] ], 'buttons' =&gt; [ [ 'class' =&gt; 'btn-outline-secondary', 'label' =&gt; lng('panel.cancel'), 'type' =&gt; 'reset' ], [ 'label' =&gt; lng('update.proceed') ] ] ] ]; ui::view('user/form-note.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'autoupdate', 'page' =&gt; 'getdownload']), 'formdata' =&gt; $upd_formfield['updates'], // alert 'type' =&gt; 'warning', 'alert_msg' =&gt; $text ]); } else ($result &lt; 0 || $result &gt; 1) { // remote errors ($result &lt; 0) { response::dynamicerror(autoupdate::getlasterror()); } else { response::redirectto($filename, [ 'page' =&gt; 'error', 'errno' =&gt; $result ]); } } else { // new version response::standardsuccess('update.noupdatesavail', (settings::get('system.update_channel') == 'testing' ? lng('serversettings.uc_testing') . ' ' : '')); } } // download new archive elseif ($page == 'getdownload') { // retrieve new version form $newversion = request::post('newversion'); $result = 6; // valid? ($newversion !== null) { $result = autoupdate::downloadzip($newversion); (!is_numeric($result)) { // next step response::redirectto($filename, [ 'page' =&gt; 'extract', 'archive' =&gt; $result ]); } } response::redirectto($filename, [ 'page' =&gt; 'error', 'errno' =&gt; $result ]); } // extract install new version elseif ($page == 'extract') { (request::post('send') == 'send') { $toextract = request::post('archive'); $localarchive = filedir::makecorrectfile(froxlor::getinstalldir() . '/updates/' . $toextract); $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "extracting " . $localarchive . " " . froxlor::getinstalldir()); $result = autoupdate::extractzip($localarchive); ($result &gt; 0) { // error response::redirectto($filename, [ 'page' =&gt; 'error', 'errno' =&gt; $result ]); } // redirect update-page response::redirectto('admin_updates.php'); } else { $toextract = request::get('archive'); $localarchive = filedir::makecorrectfile(froxlor::getinstalldir() . '/updates/' . $toextract); } (!file_exists($localarchive)) { response::redirectto($filename, [ 'page' =&gt; 'error', 'errno' =&gt; 7 ]); } $text = lng('admin.extractdownloadedzip', [$toextract]); $upd_formfield = [ 'updates' =&gt; [ 'title' =&gt; lng('update.update'), 'image' =&gt; 'fa-solid fa-download', 'sections' =&gt; [ 'section_autoupd' =&gt; [ 'fields' =&gt; [ 'archive' =&gt; ['type' =&gt; 'hidden', 'value' =&gt; $toextract] ] ] ], 'buttons' =&gt; [ [ 'class' =&gt; 'btn-outline-secondary', 'label' =&gt; lng('panel.cancel'), 'type' =&gt; 'reset' ], [ 'label' =&gt; lng('update.proceed') ] ] ] ]; ui::view('user/form-note.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'autoupdate', 'page' =&gt; 'extract']), 'formdata' =&gt; $upd_formfield['updates'], // alert 'type' =&gt; 'warning', 'alert_msg' =&gt; $text ]); } // display error elseif ($page == 'error') { // retrieve error-number via url-parameter $errno = request::get('errno', 0); // 2 = zlib // 3 = custom version detected // 4 = could store archive local hdd // 5 = weird value came version.froxlor.org // 6 = download without valid version // 7 = local archive exist // 8 = could extract archive // 9 = checksum mismatch // 10 = &lt;php-7.4 // 11 = enable_webupdate = false $errmsg = 'autoupdate_' . $errno; ($errno == 3) { $errmsg = 'customized_version'; } response::standarderror($errmsg); }</file><file name="admin_index.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\admins admins; use froxlor\api\commands\froxlor froxlor; use froxlor\currentuser; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\language; use froxlor\settings; use froxlor\system\cronjob; use froxlor\system\crypt; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\validate\validate; $id = (int)request::any('id'); ($action == 'logout') { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "logged out"); unset($_session['userinfo']); currentuser::setdata(); session_destroy(); response::redirectto('index.php'); } elseif ($action == 'suback') { (is_array(currentuser::getfield('switched_user'))) { $result = currentuser::getdata(); $result = $result['switched_user']; session_regenerate_id(true); currentuser::setdata($result); $target = request::get('target', 'index'); $redirect = "admin_" . $target . ".php"; (!file_exists(\froxlor\froxlor::getinstalldir() . "/" . $redirect)) { $redirect = "admin_index.php"; } response::redirectto($redirect, null, true); } else { response::dynamicerror("cannot change back - never switched another user :-)"); } } ($page == 'overview') { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "viewed admin_index"); $params = []; ($userinfo['customers_see_all'] == '0') { $params = [ 'adminid' =&gt; $userinfo['adminid'] ]; } $overview_stmt = database::prepare("select count(*) `number_customers`, sum(case `diskspace` &gt; 0 `diskspace` else 0 end) `diskspace_assigned`, sum(`diskspace_used`) `diskspace_used`, sum(case `mysqls` &gt; 0 `mysqls` else 0 end) `mysqls_assigned`, sum(`mysqls_used`) `mysqls_used`, sum(case `emails` &gt; 0 `emails` else 0 end) `emails_assigned`, sum(`emails_used`) `emails_used`, sum(case `email_accounts` &gt; 0 `email_accounts` else 0 end) `email_accounts_assigned`, sum(`email_accounts_used`) `email_accounts_used`, sum(case `email_forwarders` &gt; 0 `email_forwarders` else 0 end) `email_forwarders_assigned`, sum(`email_forwarders_used`) `email_forwarders_used`, sum(case `email_quota` &gt; 0 `email_quota` else 0 end) `email_quota_assigned`, sum(`email_quota_used`) `email_quota_used`, sum(case `ftps` &gt; 0 `ftps` else 0 end) `ftps_assigned`, sum(`ftps_used`) `ftps_used`, sum(case `subdomains` &gt; 0 `subdomains` else 0 end) `subdomains_assigned`, sum(`subdomains_used`) `subdomains_used`, sum(case `traffic` &gt; 0 `traffic` else 0 end) `traffic_assigned`, sum(`traffic_used`) `traffic_used` `" . table_panel_customers . "`" . ($userinfo['customers_see_all'] ? '' : " `adminid` = :adminid ")); $overview = database::pexecute_first($overview_stmt, $params); $userinfo['diskspace_bytes'] = ($userinfo['diskspace'] &gt; -1) ? $userinfo['diskspace'] * 1024 : -1; $overview['diskspace_bytes'] = $overview['diskspace_assigned'] * 1024; $overview['diskspace_bytes_used'] = $overview['diskspace_used'] * 1024; $userinfo['traffic_bytes'] = ($userinfo['traffic'] &gt; -1) ? $userinfo['traffic'] * 1024 : -1; $overview['traffic_bytes'] = $overview['traffic_assigned'] * 1024; $overview['traffic_bytes_used'] = $overview['traffic_used'] * 1024; $number_domains_stmt = database::prepare(" select count(*) `number_domains` `" . table_panel_domains . "` `parentdomainid`='0'" . ($userinfo['customers_see_all'] ? '' : " `adminid` = :adminid")); $number_domains = database::pexecute_first($number_domains_stmt, $params); $overview['number_domains'] = $number_domains['number_domains']; (request::get('lookfornewversion') == 'yes' || (isset($lookfornewversion) &amp;&amp; $lookfornewversion == 'yes')) { try { $json_result = froxlor::getlocal($userinfo)-&gt;checkupdate(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; $lookfornewversion_lable = $result['version']; $lookfornewversion_link = $result['link']; $lookfornewversion_message = $result['message']; $lookfornewversion_addinfo = $result['additional_info']; $isnewerversion = $result['isnewerversion']; } else { $lookfornewversion_lable = lng('admin.lookfornewversion.clickhere'); $lookfornewversion_link = htmlspecialchars($filename . '?page=' . urlencode($page) . '&amp;lookfornewversion=yes'); $lookfornewversion_message = ''; $lookfornewversion_addinfo = ''; $isnewerversion = 0; } $cron_last_runs = cronjob::getcronjobslastrun(); $outstanding_tasks = cronjob::getoutstandingtasks(); // additional sys-infos $meminfo = explode("\n", @file_get_contents("/proc/meminfo")); $memory = ""; ($i = 0; $i &lt; count($meminfo); ++$i) { (substr($meminfo[$i], 0, 3) === "mem") { $memory .= $meminfo[$i] . php_eol; } } (function_exists('sys_getloadavg')) { $loadarray = sys_getloadavg(); $load = number_format($loadarray[0], 2, '.', '') . " / " . number_format($loadarray[1], 2, '.', '') . " / " . number_format($loadarray[2], 2, '.', ''); } else { $load = @file_get_contents('/proc/loadavg'); (!$load) { $load = lng('admin.noloadavailable'); } } $kernel = ''; (function_exists('posix_uname')) { $kernel_nfo = posix_uname(); $kernel = $kernel_nfo['release'] . ' (' . $kernel_nfo['machine'] . ')'; } // try get uptime // first: exec (let's hope enabled froxlor - vhost) $uptime_array = explode(" ", @file_get_contents("/proc/uptime")); $uptime = ''; (is_array($uptime_array) &amp;&amp; isset($uptime_array[0]) &amp;&amp; is_numeric($uptime_array[0])) { // calculatioon get nicly formatted display $seconds = round($uptime_array[0], 0); $minutes = $seconds / 60; $hours = $minutes / 60; $days = floor($hours / 24); $hours = floor($hours - ($days * 24)); $minutes = floor($minutes - ($days * 24 * 60) - ($hours * 60)); $seconds = floor($seconds - ($days * 24 * 60 * 60) - ($hours * 60 * 60) - ($minutes * 60)); $uptime = "{$days}d, {$hours}h, {$minutes}m, {$seconds}s"; // cleanup unset($uptime_array, $seconds, $minutes, $hours, $days); } $sysinfo = [ 'webserver' =&gt; $_server['server_software'] ?? 'unknown', 'phpversion' =&gt; phpversion(), 'mysqlserverversion' =&gt; database::getattribute(pdo::attr_server_version), 'phpsapi' =&gt; strtoupper(@php_sapi_name()), 'hostname' =&gt; gethostname(), 'memory' =&gt; $memory, 'load' =&gt; $load, 'kernel' =&gt; $kernel, 'uptime' =&gt; $uptime ]; ui::twig()-&gt;addglobal('userinfo', $userinfo); ui::view('user/index.html.twig', [ 'sysinfo' =&gt; $sysinfo, 'overview' =&gt; $overview, 'outstanding_tasks' =&gt; $outstanding_tasks, 'cron_last_runs' =&gt; $cron_last_runs ]); } elseif ($page == 'profile') { $languages = language::getlanguages(); (!empty($_post)) { (request::post('send') == 'changepassword') { $old_password = validate::validate(request::post('old_password'), 'old password'); (!crypt::validatepasswordlogin($userinfo, $old_password, table_panel_admins, 'adminid')) { response::standarderror('oldpasswordnotcorrect'); } try { $new_password = crypt::validatepassword(request::post('new_password'), 'new password'); $new_password_confirm = crypt::validatepassword(request::post('new_password_confirm'), 'new password confirm'); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } ($old_password == '') { response::standarderror([ 'stringisempty', 'changepassword.old_password' ]); } elseif ($new_password == '') { response::standarderror([ 'stringisempty', 'changepassword.new_password' ]); } elseif ($new_password_confirm == '') { response::standarderror([ 'stringisempty', 'changepassword.new_password_confirm' ]); } elseif ($new_password != $new_password_confirm) { response::standarderror('newpasswordconfirmerror'); } else { try { admins::getlocal($userinfo, [ 'id' =&gt; $userinfo['adminid'], 'admin_password' =&gt; $new_password ])-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $log-&gt;logaction(froxlorlogger::adm_action, log_notice, 'changed password'); response::redirectto($filename); } } elseif (request::post('send') == 'changetheme') { (settings::get('panel.allow_theme_change_admin') == 1) { $theme = validate::validate(request::post('theme'), 'theme'); try { admins::getlocal($userinfo, [ 'id' =&gt; $userinfo['adminid'], 'theme' =&gt; $theme ])-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "changed his/her theme '" . $theme . "'"); } response::redirectto($filename); } elseif (request::post('send') == 'changelanguage') { $def_language = validate::validate(request::post('def_language'), 'default language'); (isset($languages[$def_language])) { try { admins::getlocal($userinfo, [ 'id' =&gt; $userinfo['adminid'], 'def_language' =&gt; $def_language ])-&gt;update(); currentuser::setfield('language', $def_language); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } } $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "changed his/her default language '" . $def_language . "'"); response::redirectto($filename); } } else { // change theme $default_theme = settings::get('panel.default_theme'); ($userinfo['theme'] != '') { $default_theme = $userinfo['theme']; } $themes_avail = ui::getthemes(); // change language $default_lang = settings::get('panel.standardlanguage'); ($userinfo['def_language'] != '') { $default_lang = $userinfo['def_language']; } ui::view('user/profile.html.twig', [ 'themes' =&gt; $themes_avail, 'default_theme' =&gt; $default_theme, 'languages' =&gt; $languages, 'default_lang' =&gt; $default_lang, ]); } } elseif ($page == 'send_error_report' &amp;&amp; settings::get('system.allow_error_report_admin') == '1') { require_once __dir__ . '/error_report.php'; } elseif ($page == 'apikeys' &amp;&amp; settings::get('api.enabled') == 1) { require_once __dir__ . '/api_keys.php'; } elseif ($page == '2fa' &amp;&amp; settings::get('2fa.enabled') == 1) { require_once __dir__ . '/2fa.php'; }</file><file name="admin_ipsandports.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\ipsandports; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; $id = (int)request::any('id'); (($page == 'ipsandports' || $page == 'overview') &amp;&amp; $userinfo['change_serversettings'] == '1') { ($action == '') { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "viewed admin_ipsandports"); try { $ipsandports_list_data = include_once dirname(__file__) . '/lib/tablelisting/admin/tablelisting.ipsandports.php'; $collection = (new collection(ipsandports::class, $userinfo)) -&gt;withpagination($ipsandports_list_data['ipsandports_list']['columns'], $ipsandports_list_data['ipsandports_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $ipsandports_list_data, 'ipsandports_list'), 'actions_links' =&gt; [ [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'ipsandports', 'page' =&gt; $page, 'action' =&gt; 'add']), 'label' =&gt; lng('admin.ipsandports.add') ] ] ]); } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = ipsandports::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['id']) &amp;&amp; $result['id'] == $id) { (request::post('send') == 'send') { try { ipsandports::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesno('admin_ip_reallydelete', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $result['ip'] . ':' . $result['port']); } } } elseif ($action == 'add') { (request::post('send') == 'send') { try { ipsandports::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $ipsandports_add_data = include_once dirname(__file__) . '/lib/formfields/admin/ipsandports/formfield.ipsandports_add.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'ipsandports']), 'formdata' =&gt; $ipsandports_add_data['ipsandports_add'] ]); } } elseif ($action == 'edit' &amp;&amp; $id != 0) { try { $json_result = ipsandports::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($result['ip'] != '') { (request::post('send') == 'send') { try { ipsandports::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $result = phphelper::htmlentitiesarray($result); $ipsandports_edit_data = include_once dirname(__file__) . '/lib/formfields/admin/ipsandports/formfield.ipsandports_edit.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'ipsandports', 'id' =&gt; $id]), 'formdata' =&gt; $ipsandports_edit_data['ipsandports_edit'], 'editid' =&gt; $id ]); } } } elseif ($action == 'jqcheckip') { $ip = request::post('ip', ''); (!filter_var($ip, filter_validate_ip, filter_flag_ipv4 | filter_flag_ipv6)) { echo json_encode('&lt;div id="ipnote" class="invalid-feedback"&gt;'.lng('error.invalidip', [$ip]).'&lt;/div&gt;'); } elseif (!filter_var($ip, filter_validate_ip, filter_flag_no_res_range | filter_flag_no_priv_range)) { // returns notice private network detected, display echo json_encode(lng('admin.ipsandports.ipnote')); } else { echo 0; } exit(); } }</file><file name="admin_message.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\user; $id = (int)request::any('id'); $note_type = null; $note_msg = null; ($page == 'message') { ($action == '') { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, 'viewed panel_message'); (request::post('send') == 'send') { (request::post('recipient', -1) == 0 &amp;&amp; $userinfo['customers_see_all'] == '1') { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, 'sending messages admins'); $result = database::query('select `name`, `email` `' . table_panel_admins . "`"); } elseif (request::post('recipient', -1) == 1) { ($userinfo['customers_see_all'] == '1') { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, 'sending messages customers'); $result = database::query('select `firstname`, `name`, `company`, `email` `' . table_panel_customers . "`"); } else { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, 'sending messages customers'); $result = database::prepare(' select `firstname`, `name`, `company`, `email` `' . table_panel_customers . "` `adminid` = :adminid"); database::pexecute($result, [ 'adminid' =&gt; $userinfo['adminid'] ]); } } else { response::standarderror('norecipientsgiven'); } $subject = request::post('subject'); $message = wordwrap(request::post('message'), 70); (!empty($message)) { $mailcounter = 0; $mail-&gt;body = $message; $mail-&gt;subject = $subject; ($row = $result-&gt;fetch(pdo::fetch_assoc)) { $row['firstname'] = isset($row['firstname']) ? $row['firstname'] : ''; $row['company'] = isset($row['company']) ? $row['company'] : ''; $mail-&gt;addaddress($row['email'], user::getcorrectusersalutation([ 'firstname' =&gt; $row['firstname'], 'name' =&gt; $row['name'], 'company' =&gt; $row['company'] ])); $mail-&gt;from = $userinfo['email']; $mail-&gt;fromname = (isset($userinfo['firstname']) ? $userinfo['firstname'] . ' ' : '') . $userinfo['name']; (!$mail-&gt;send()) { ($mail-&gt;errorinfo != '') { $mailerr_msg = $mail-&gt;errorinfo; } else { $mailerr_msg = $row['email']; } $log-&gt;logaction(froxlorlogger::adm_action, log_err, 'error sending mail: ' . $mailerr_msg); response::standarderror('errorsendingmail', $row['email']); } $mailcounter++; $mail-&gt;clearaddresses(); } response::redirectto($filename, [ 'page' =&gt; $page, 'action' =&gt; 'showsuccess', 'sentitems' =&gt; $mailcounter ]); } else { response::standarderror('nomessagetosend'); } } } elseif ($action == 'showsuccess') { $sentitems = request::get('sentitems', 0); ($sentitems == 0) { $note_type = 'info'; $note_msg = lng('message.norecipients'); } else { $note_type = 'success'; $note_msg = lng('message.success', [$sentitems]); } } $recipients = []; ($userinfo['customers_see_all'] == '1') { $recipients[0] = lng('panel.reseller'); } $recipients[1] = lng('panel.customer'); $messages_add_data = include_once dirname(__file__) . '/lib/formfields/admin/messages/formfield.messages_add.php'; ui::view('user/form-note.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'message', 'action' =&gt; '']), 'formdata' =&gt; $messages_add_data['messages_add'], 'actions_links' =&gt; [ [ 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'settings', 'page' =&gt; 'overview', 'part' =&gt; 'system', 'em' =&gt; 'system_mail_use_smtp' ]), 'label' =&gt; lng('admin.smtpsettings'), 'icon' =&gt; 'fa-solid fa-gears', 'class' =&gt; 'btn-outline-secondary' ] ], // alert-box 'type' =&gt; $note_type, 'alert_msg' =&gt; $note_msg ]); }</file><file name="admin_templates.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\language; use froxlor\phphelper; use froxlor\settings; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\validate\validate; use froxlor\currentuser; $id = (int)request::any('id'); $subjectid = intval(request::any('subjectid')); $mailbodyid = intval(request::any('mailbodyid')); $available_templates = [ 'createcustomer', 'pop_success', 'new_database_by_customer', 'new_ftpaccount_by_customer', 'password_reset' ]; // show templates features enabled #1191 ((int)settings::get('system.report_enable') == 1) { array_push($available_templates, 'trafficmaxpercent', 'diskmaxpercent'); } (settings::get('panel.sendalternativemail') == 1) { array_push($available_templates, 'pop_success_alternative'); } $file_templates = [ 'index_html', 'unconfigured_html' ]; $languages = language::getlanguages(); ($action == '') { // email templates $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "viewed admin_templates"); $templates_array = []; $result_stmt = database::prepare(" select `id`, `language`, `varname` `" . table_panel_templates . "` `adminid` = :adminid `templategroup`='mails' order `language`, `varname` "); database::pexecute($result_stmt, [ 'adminid' =&gt; $userinfo['adminid'] ]); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $parts = []; preg_match('/^([a-z]([a-z_]+[a-z])*)_(mailbody|subject)$/', $row['varname'], $parts); $templates_array[$row['language']][$parts[1]][$parts[3]] = $row['id']; } $templates = []; foreach ($templates_array $language =&gt; $template_defs) { foreach ($template_defs $action =&gt; $email) { $templates[] = [ 'subjectid' =&gt; $email['subject'], 'mailbodyid' =&gt; $email['mailbody'], 'template' =&gt; lng('admin.templates.' . $action), 'language' =&gt; $language ]; } } $mail_actions_links = false; foreach ($languages $language_file =&gt; $language_name) { $templates_done = []; $result_stmt = database::prepare(" select `varname` `" . table_panel_templates . "` `adminid` = :adminid `language`= :lang `templategroup` = 'mails' `varname` like '%_subject' "); database::pexecute($result_stmt, [ 'adminid' =&gt; $userinfo['adminid'], 'lang' =&gt; $language_name ]); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $templates_done[] = str_replace('_subject', '', $row['varname']); } (count(array_diff($available_templates, $templates_done)) &gt; 0) { $mail_actions_links = [ [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'templates', 'page' =&gt; $page, 'action' =&gt; 'add']), 'label' =&gt; lng('admin.templates.template_add') ] ]; } } $mailtpl_list_data = include_once dirname(__file__) . '/lib/tablelisting/admin/tablelisting.mailtemplates.php'; $collection_mail = [ 'data' =&gt; $templates, 'pagination' =&gt; [] ]; // filetemplates $result_stmt = database::prepare(" select `id`, `varname` `" . table_panel_templates . "` `adminid` = :adminid `templategroup`='files'"); database::pexecute($result_stmt, [ 'adminid' =&gt; $userinfo['adminid'] ]); $filetemplates = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $filetemplates[] = [ 'id' =&gt; $row['id'], 'template' =&gt; lng('admin.templates.' . $row['varname']) ]; } $file_actions_links = false; (database::num_rows() != count($file_templates)) { $file_actions_links = [ [ 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'templates', 'page' =&gt; $page, 'action' =&gt; 'add', 'files' =&gt; 'files' ]), 'label' =&gt; lng('admin.templates.template_fileadd') ] ]; } $filetpl_list_data = include_once dirname(__file__) . '/lib/tablelisting/admin/tablelisting.filetemplates.php'; $collection_file = [ 'data' =&gt; $filetemplates, 'pagination' =&gt; [] ]; ($mail_actions_links === false) { $mail_actions_links = []; } ($file_actions_links === false) { $file_actions_links = []; } ui::view('user/table-tpl.html.twig', [ 'maillisting' =&gt; listing::formatfromarray($collection_mail, $mailtpl_list_data['mailtpl_list'], 'mailtpl_list'), 'filelisting' =&gt; listing::formatfromarray($collection_file, $filetpl_list_data['filetpl_list'], 'filetpl_list'), 'actions_links' =&gt; array_merge($mail_actions_links, $file_actions_links) ]); } elseif ($action == 'delete' &amp;&amp; $subjectid != 0 &amp;&amp; $mailbodyid != 0) { // email templates $result_stmt = database::prepare(" select `language`, `varname` `" . table_panel_templates . "` `adminid` = :adminid `id` = :id"); database::pexecute($result_stmt, [ 'adminid' =&gt; $userinfo['adminid'], 'id' =&gt; $subjectid ]); $result = $result_stmt-&gt;fetch(pdo::fetch_assoc); ($result['varname'] != '') { (request::post('send') == 'send') { $del_stmt = database::prepare(" delete `" . table_panel_templates . "` `adminid` = :adminid (`id` = :ida `id` = :idb)"); database::pexecute($del_stmt, [ 'adminid' =&gt; $userinfo['adminid'], 'ida' =&gt; $subjectid, 'idb' =&gt; $mailbodyid ]); $log-&gt;logaction(froxlorlogger::adm_action, log_info, "deleted template '" . $result['language'] . ' - ' . lng('admin.templates.' . str_replace('_subject', '', $result['varname'])) . "'"); response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesno('admin_template_reallydelete', $filename, [ 'subjectid' =&gt; $subjectid, 'mailbodyid' =&gt; $mailbodyid, 'page' =&gt; $page, 'action' =&gt; $action ], $result['language'] . ' - ' . lng('admin.templates.' . str_replace('_subject', '', $result['varname']))); } } } elseif ($action == 'deletef' &amp;&amp; $id != 0) { // file templates $result_stmt = database::prepare(" select * `" . table_panel_templates . "` `adminid` = :adminid `id` = :id"); database::pexecute($result_stmt, [ 'adminid' =&gt; $userinfo['adminid'], 'id' =&gt; $id ]); (database::num_rows() &gt; 0) { $row = $result_stmt-&gt;fetch(pdo::fetch_assoc); (request::post('send') == 'send') { $del_stmt = database::prepare(" delete `" . table_panel_templates . "` `adminid` = :adminid `id` = :id"); database::pexecute($del_stmt, [ 'adminid' =&gt; $userinfo['adminid'], 'id' =&gt; $id ]); $log-&gt;logaction(froxlorlogger::adm_action, log_info, "deleted template '" . lng('admin.templates.' . $row['varname']) . "'"); response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesno('admin_template_reallydelete', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], lng('admin.templates.' . $row['varname'])); } } else { response::standarderror('templatenotfound'); } } elseif ($action == 'add') { (request::post('prepare') == 'prepare') { // email templates $language = htmlentities(validate::validate(request::post('language'), 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect')); (!array_key_exists($language, $languages)) { response::standarderror('templatelanguageinvalid'); } $template = validate::validate(request::post('template'), 'template'); $result_stmt = database::prepare(" select count(*) def `" . table_panel_templates . "` `adminid` = :adminid `language` = :lang `templategroup` = 'mails' `varname` like :template "); $result = database::pexecute_first($result_stmt, [ 'adminid' =&gt; $userinfo['adminid'], 'lang' =&gt; $language, 'template' =&gt; $template . '%' ]); ($result &amp;&amp; $result['def'] &gt; 0) { response::standarderror('templatelanguagecombodefined'); } // set target language language::setlanguage($language); $subject = lng('mails.' . $template . '.subject'); $body = str_replace('\n', "\n", lng('mails.' . $template . '.mailbody')); // set language user language::setlanguage(currentuser::getfield('def_language')); $template_add_data = include_once dirname(__file__) . '/lib/formfields/admin/templates/formfield.template_add.php'; ui::view('user/form-replacers.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'templates']), 'formdata' =&gt; $template_add_data['template_add'], 'replacers' =&gt; $template_add_data['template_replacers'] ]); } elseif (request::post('send') == 'send' &amp;&amp; empty(request::post('filesend'))) { // email templates $language = htmlentities(validate::validate(request::post('language'), 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect')); (!array_key_exists($language, $languages)) { response::standarderror('templatelanguageinvalid'); } $template = validate::validate(request::post('template'), 'template'); $subject = validate::validate(request::post('subject'), 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate'); $mailbody = validate::validate(request::post('mailbody'), 'mailbody', '/^[^\0]+$/', 'nomailbodycreate'); $templates = []; $result_stmt = database::prepare(" select `varname` `" . table_panel_templates . "` `adminid` = :adminid `language` = :lang `templategroup` = 'mails' `varname` like '%_subject'"); database::pexecute($result_stmt, [ 'adminid' =&gt; $userinfo['adminid'], 'lang' =&gt; $language ]); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $templates[] = str_replace('_subject', '', $row['varname']); } $templates = array_diff($available_templates, $templates); (!in_array($template, $templates)) { response::standarderror('templatenotfound'); } else { $ins_stmt = database::prepare(" insert `" . table_panel_templates . "` set `adminid` = :adminid, `language` = :lang, `templategroup` = 'mails', `varname` = :var, `value` = :value"); // mail-subject $ins_data = [ 'adminid' =&gt; $userinfo['adminid'], 'lang' =&gt; $language, 'var' =&gt; $template . '_subject', 'value' =&gt; $subject ]; database::pexecute($ins_stmt, $ins_data); // mail-body $ins_data = [ 'adminid' =&gt; $userinfo['adminid'], 'lang' =&gt; $language, 'var' =&gt; $template . '_mailbody', 'value' =&gt; $mailbody ]; database::pexecute($ins_stmt, $ins_data); $log-&gt;logaction(froxlorlogger::adm_action, log_info, "added template '" . $language . ' - ' . $template . "'"); response::redirectto($filename, [ 'page' =&gt; $page ]); } } elseif (request::post('filesend') == 'filesend') { // file templates $template = validate::validate(request::post('template'), 'template'); $filecontent = validate::validate(request::post('filecontent'), 'filecontent', '/^[^\0]+$/', 'filecontentnotset'); $ins_stmt = database::prepare(" insert `" . table_panel_templates . "` set `adminid` = :adminid, `language` = '', `templategroup` = 'files', `varname` = :var, `value` = :value"); $ins_data = [ 'adminid' =&gt; $userinfo['adminid'], 'var' =&gt; $template, 'value' =&gt; $filecontent ]; database::pexecute($ins_stmt, $ins_data); $log-&gt;logaction(froxlorlogger::adm_action, log_info, "added template '" . $template . "'"); response::redirectto($filename, [ 'page' =&gt; $page ]); } elseif (empty(request::get('files'))) { // email templates $add = false; $language_options = []; $template_options = []; foreach ($languages $language_file =&gt; $language_name) { $templates = []; $result_stmt = database::prepare(" select `varname` `" . table_panel_templates . "` `adminid` = :adminid `language` = :lang `templategroup` = 'mails' `varname` like '%_subject'"); database::pexecute($result_stmt, [ 'adminid' =&gt; $userinfo['adminid'], 'lang' =&gt; $language_name ]); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $templates[] = str_replace('_subject', '', $row['varname']); } (count(array_diff($available_templates, $templates)) &gt; 0) { $add = true; $language_options[$language_file] = $language_name; $templates = array_diff($available_templates, $templates); foreach ($templates $template) { $template_options[$template] = lng('admin.templates.' . $template); } } } ($add) { ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'templates']), 'formdata' =&gt; [ 'title' =&gt; lng('admin.templates.template_add'), 'image' =&gt; 'fa-solid fa-plus', 'self_overview' =&gt; ['section' =&gt; 'templates', 'page' =&gt; 'email'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.templates.template_add'), 'fields' =&gt; [ 'language' =&gt; [ 'label' =&gt; lng('login.language'), 'type' =&gt; 'select', 'select_var' =&gt; $language_options, 'selected' =&gt; $userinfo['language'] ], 'template' =&gt; [ 'label' =&gt; lng('admin.templates.action'), 'type' =&gt; 'select', 'select_var' =&gt; $template_options ], 'prepare' =&gt; [ 'type' =&gt; 'hidden', 'value' =&gt; 'prepare' ] ] ] ] ], 'editid' =&gt; $id ]); } else { response::standarderror('alltemplatesdefined'); } } else { // filetemplates $result_stmt = database::prepare(" select `id`, `varname` `" . table_panel_templates . "` `adminid` = :adminid `templategroup`='files'"); database::pexecute($result_stmt, [ 'adminid' =&gt; $userinfo['adminid'] ]); (database::num_rows() == count($file_templates)) { response::standarderror('alltemplatesdefined'); } else { $templatesdefined = []; $free_templates = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $templatesdefined[] = $row['varname']; } foreach (array_diff($file_templates, $templatesdefined) $template) { $free_templates[$template] = lng('admin.templates.' . $template); } $filetemplate_add_data = include_once dirname(__file__) . '/lib/formfields/admin/templates/formfield.filetemplate_add.php'; ui::view('user/form-replacers.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'templates']), 'formdata' =&gt; $filetemplate_add_data['filetemplate_add'], 'replacers' =&gt; $filetemplate_add_data['filetemplate_replacers'] ]); } } } elseif ($action == 'edit' &amp;&amp; $subjectid != 0 &amp;&amp; $mailbodyid != 0) { // email templates $result_stmt = database::prepare(" select `language`, `varname`, `value` `" . table_panel_templates . "` `adminid` = :adminid `id` = :subjectid"); database::pexecute($result_stmt, [ 'adminid' =&gt; $userinfo['adminid'], 'subjectid' =&gt; $subjectid ]); $result = $result_stmt-&gt;fetch(pdo::fetch_assoc); ($result['varname'] != '') { (request::post('send') == 'send') { $subject = validate::validate(request::post('subject'), 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate'); $mailbody = validate::validate(request::post('mailbody'), 'mailbody', '/^[^\0]+$/', 'nomailbodycreate'); $upd_stmt = database::prepare(" update `" . table_panel_templates . "` set `value` = :value `adminid` = :adminid `id` = :id"); // subject database::pexecute($upd_stmt, [ 'value' =&gt; $subject, 'adminid' =&gt; $userinfo['adminid'], 'id' =&gt; $subjectid ]); // query mailbody database::pexecute($upd_stmt, [ 'value' =&gt; $mailbody, 'adminid' =&gt; $userinfo['adminid'], 'id' =&gt; $mailbodyid ]); $log-&gt;logaction(froxlorlogger::adm_action, log_info, "edited template '" . $result['varname'] . "'"); response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $result = phphelper::htmlentitiesarray($result); $template_name = lng('admin.templates.' . str_replace('_subject', '', $result['varname'])); $subject = $result['value']; $result_stmt = database::prepare(" select `language`, `varname`, `value` `" . table_panel_templates . "` `id` = :id"); database::pexecute($result_stmt, [ 'id' =&gt; $mailbodyid ]); $result = $result_stmt-&gt;fetch(pdo::fetch_assoc); $template = str_replace('_mailbody', '', $result['varname']); // escape already escaped language-string save htmlentities() $language = $result['language']; $result = phphelper::htmlentitiesarray($result); $mailbody = $result['value']; $template_edit_data = include_once dirname(__file__) . '/lib/formfields/admin/templates/formfield.template_edit.php'; ui::view('user/form-replacers.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'templates']), 'formdata' =&gt; $template_edit_data['template_edit'], 'replacers' =&gt; $template_edit_data['template_replacers'] ]); } } } elseif ($action == 'editf' &amp;&amp; $id != 0) { // file templates $result_stmt = database::prepare(" select * `" . table_panel_templates . "` `adminid` = :adminid `id` = :id"); database::pexecute($result_stmt, [ 'adminid' =&gt; $userinfo['adminid'], 'id' =&gt; $id ]); (database::num_rows() &gt; 0) { $row = $result_stmt-&gt;fetch(pdo::fetch_assoc); // filetemplates (request::post('filesend') == 'filesend') { $filecontent = validate::validate(request::post('filecontent'), 'filecontent', '/^[^\0]+$/', 'filecontentnotset'); $upd_stmt = database::prepare(" update `" . table_panel_templates . "` set `value` = :value `adminid` = :adminid `id` = :id"); database::pexecute($upd_stmt, [ 'value' =&gt; $filecontent, 'adminid' =&gt; $userinfo['adminid'], 'id' =&gt; $id ]); $log-&gt;logaction(froxlorlogger::adm_action, log_info, "edited template '" . $row['varname'] . "'"); response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $row = phphelper::htmlentitiesarray($row); $filetemplate_edit_data = include_once dirname(__file__) . '/lib/formfields/admin/templates/formfield.filetemplate_edit.php'; ui::view('user/form-replacers.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'templates']), 'formdata' =&gt; $filetemplate_edit_data['filetemplate_edit'], 'replacers' =&gt; $filetemplate_edit_data['filetemplate_replacers'], 'editid' =&gt; $id ]); } } else { response::standarderror('templatenotfound'); } }</file><file name="customer_ftp.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'customer'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\ftps ftps; use froxlor\currentuser; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; // redirect customer page hidden via settings (settings::isinlist('panel.customer_hide_options', 'ftp')) { response::redirectto('customer_index.php'); } $id = (int)request::any('id', 0); ($page == 'overview' || $page == 'accounts') { ($action == '') { $log-&gt;logaction(froxlorlogger::usr_action, log_notice, "viewed customer_ftp::accounts"); try { $ftp_list_data = include_once dirname(__file__) . '/lib/tablelisting/customer/tablelisting.ftps.php'; $collection = (new collection(ftps::class, $userinfo)) -&gt;withpagination($ftp_list_data['ftp_list']['columns'], $ftp_list_data['ftp_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $actions_links = []; (currentuser::canaddresource('ftps')) { $actions_links[] = [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'ftp', 'page' =&gt; 'accounts', 'action' =&gt; 'add']), 'label' =&gt; lng('ftp.account_add') ]; } $actions_links[] = [ 'href' =&gt; \froxlor\froxlor::getdocsurl() . 'user-guide/ftp-accounts/', 'target' =&gt; '_blank', 'icon' =&gt; 'fa-solid fa-circle-info', 'class' =&gt; 'btn-outline-secondary' ]; ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $ftp_list_data, 'ftp_list'), 'actions_links' =&gt; $actions_links, 'entity_info' =&gt; lng('ftp.description') ]); } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = ftps::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['username']) &amp;&amp; $result['username'] != $userinfo['loginname']) { (request::post('send') == 'send') { try { ftps::getlocal($userinfo, request::postall())-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesnowithcheckbox('ftp_reallydelete', 'admin_customer_alsoremoveftphomedir', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $result['username']); } } else { response::standarderror('ftp_cantdeletemainaccount'); } } elseif ($action == 'add') { ($userinfo['ftps_used'] &lt; $userinfo['ftps'] || $userinfo['ftps'] == '-1') { (request::post('send') == 'send') { try { ftps::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $pathselect = filedir::makepathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid'], '/'); (settings::get('customer.ftpatdomain') == '1') { $domainlist = []; $result_domains_stmt = database::prepare("select `domain` `" . table_panel_domains . "` `customerid`= :customerid order `domain` asc"); database::pexecute($result_domains_stmt, [ "customerid" =&gt; $userinfo['customerid'] ]); ($row_domain = $result_domains_stmt-&gt;fetch(pdo::fetch_assoc)) { $domainlist[$row_domain['domain']] = $idna_convert-&gt;decode($row_domain['domain']); } } (settings::get('system.allow_customer_shell') == '1') { $shells['/bin/false'] = "/bin/false"; $shells_avail = settings::get('system.available_shells'); (!empty($shells_avail)) { $shells_avail_arr = explode(",", $shells_avail); $shells_avail_arr = array_map("trim", $shells_avail_arr); foreach ($shells_avail_arr $shell) { $shells[$shell] = $shell; } } } $ftp_add_data = include_once dirname(__file__) . '/lib/formfields/customer/ftp/formfield.ftp_add.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'ftp']), 'formdata' =&gt; $ftp_add_data['ftp_add'] ]); } } } elseif ($action == 'edit' &amp;&amp; $id != 0) { try { $json_result = ftps::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['username']) &amp;&amp; $result['username'] != '') { (request::post('send') == 'send') { try { ftps::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { (strpos($result['homedir'], $userinfo['documentroot']) === 0) { $homedir = str_replace($userinfo['documentroot'], "/", $result['homedir']); } else { $homedir = $result['homedir']; } $homedir = filedir::makecorrectdir($homedir); $pathselect = filedir::makepathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid'], $homedir); (settings::get('system.allow_customer_shell') == '1') { $shells['/bin/false'] = "/bin/false"; $shells_avail = settings::get('system.available_shells'); (!empty($shells_avail)) { $shells_avail_arr = explode(",", $shells_avail); $shells_avail_arr = array_map("trim", $shells_avail_arr); foreach ($shells_avail_arr $shell) { $shells[$shell] = $shell; } } } $ftp_edit_data = include_once dirname(__file__) . '/lib/formfields/customer/ftp/formfield.ftp_edit.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'ftp', 'id' =&gt; $id]), 'formdata' =&gt; $ftp_edit_data['ftp_edit'], 'editid' =&gt; $id ]); } } } }</file><file name="admin_admins.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\admins; use froxlor\currentuser; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\settings; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; $id = (int)request::any('id'); (($page == 'admins' || $page == 'overview') &amp;&amp; $userinfo['change_serversettings'] == '1') { ($action == '') { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "viewed admin_admins"); try { $admin_list_data = include_once dirname(__file__) . '/lib/tablelisting/admin/tablelisting.admins.php'; $collection = (new collection(admins::class, $userinfo)) -&gt;withpagination($admin_list_data['admin_list']['columns'], $admin_list_data['admin_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $admin_list_data, 'admin_list'), 'actions_links' =&gt; [ [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'admins', 'page' =&gt; $page, 'action' =&gt; 'add']), 'label' =&gt; lng('admin.admin_add') ] ] ]); } elseif ($action == 'su') { try { $json_result = admins::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; $destination_admin = $result['loginname']; ($destination_admin != '' &amp;&amp; $result['adminid'] != $userinfo['userid']) { $result['switched_user'] = currentuser::getdata(); $result['adminsession'] = 1; $result['userid'] = $result['adminid']; session_regenerate_id(true); currentuser::setdata($result); $log-&gt;logaction( froxlorlogger::adm_action, log_info, "switched adminuser '" . $destination_admin . "'" ); response::redirectto('admin_index.php'); } else { response::redirectto('index.php', [ 'action' =&gt; 'login' ]); } } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = admins::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($result['loginname'] != '') { ($result['adminid'] == $userinfo['userid']) { response::standarderror('youcantdeleteyourself'); } (request::post('send') == 'send') { admins::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;delete(); response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesno('admin_admin_reallydelete', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $result['loginname']); } } } elseif ($action == 'add') { (request::post('send') == 'send') { try { admins::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $ipaddress = []; $ipaddress[-1] = lng('admin.allips'); $ipsandports_stmt = database::query(" select `id`, `ip` `" . table_panel_ipsandports . "` group `ip` order `ip` asc "); ($row = $ipsandports_stmt-&gt;fetch(pdo::fetch_assoc)) { $ipaddress[$row['id']] = $row['ip']; } $admin_add_data = include_once dirname(__file__) . '/lib/formfields/admin/admin/formfield.admin_add.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'admins']), 'formdata' =&gt; $admin_add_data['admin_add'] ]); } } elseif ($action == 'edit' &amp;&amp; $id != 0) { try { $json_result = admins::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($result['loginname'] != '') { (request::post('send') == 'send') { try { admins::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $dec_places = settings::get('panel.decimal_places'); $result['traffic'] = round($result['traffic'] / (1024 * 1024), $dec_places); $result['diskspace'] = round($result['diskspace'] / 1024, $dec_places); $result['email'] = $idna_convert-&gt;decode($result['email']); $ipaddress = []; $ipaddress[-1] = lng('admin.allips'); $ipsandports_stmt = database::query(" select `id`, `ip` `" . table_panel_ipsandports . "` group `ip` order `ip` asc "); ($row = $ipsandports_stmt-&gt;fetch(pdo::fetch_assoc)) { $ipaddress[$row['id']] = $row['ip']; } $result = phphelper::htmlentitiesarray($result); $admin_edit_data = include_once dirname(__file__) . '/lib/formfields/admin/admin/formfield.admin_edit.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'admins', 'id' =&gt; $id]), 'formdata' =&gt; $admin_edit_data['admin_edit'], 'editid' =&gt; $id ]); } } } }</file><file name="README.md">[![librepanel - build (mariadb)](https://github.com/atxcowboy/librepanel/actions/workflows/build-mariadb.yml/badge.svg?branch=main)](https://github.com/atxcowboy/librepanel/actions/workflows/build-mariadb.yml) [![librepanel - build (mysql)](https://github.com/atxcowboy/librepanel/actions/workflows/build-mysql.yml/badge.svg?branch=main)](https://github.com/atxcowboy/librepanel/actions/workflows/build-mysql.yml) # librepanel modern, open-source hosting control panel, forked froxlor, developed [panomity gmbh](https://www.panomity.com). goal simplify effort managing hosting platform providing flexibility transparency. ## installation ### fast install 1. ensure webserver serves `/var/www/html`. 2. extract librepanel `/var/www/html` (for example `/var/www/html/librepanel`). 3. point browser `http://[ip-of-webserver]/librepanel`. 4. follow installer. 5. log administrator. 6. fun! **note:** choose manual configuration installation, additional steps may required: 1. adjust **system &gt; settings** according needs. 2. choose distribution **system &gt; configuration**. 3. follow steps services (web server, php, etc.). ### detailed installation coming soon [librepanel.com](https://librepanel.com/) (in development). *(for reference froxlors docs, may still look [docs.froxlor.org](https://docs.froxlor.org/latest/general/installation/) librepanels docs fully available.)* ## help &amp; community may find help following places: ### github issues discussions found github repository: [https://github.com/atxcowboy/librepanel](https://github.com/atxcowboy/librepanel) *(community forums, dedicated discord, support channels may added librepanel grows.)* ## license librepanel open-source software. see [copying](copying) file license details. ## downloads *(as new project/fork, official packages may still progress. example section future reference.)* - **latest tarball** *coming soon [librepanel.com](https://librepanel.com/downloads)* - **debian repository** *planned future release. stay tuned!* ## contributing welcome contributions! check [contributing.md](.github/contributing.md) (to updated) open issue/pr github.</file><file name="2fa.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ (!defined('area')) { header("location: index.php"); exit(); } use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\froxlortwofactorauth; use froxlor\settings; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\phphelper; use froxlor\user; (settings::get('2fa.enabled') != '1') { response::dynamicerror('2fa.2fa_not_activated'); } // file included admin_index customer_index // therefore need require lib/init.php (area == 'admin') { $upd_stmt = database::prepare("update `" . table_panel_admins . "` set `type_2fa` = :t2fa, `data_2fa` = :d2fa adminid = :id"); $uid = $userinfo['adminid']; } elseif (area == 'customer') { $upd_stmt = database::prepare("update `" . table_panel_customers . "` set `type_2fa` = :t2fa, `data_2fa` = :d2fa customerid = :id"); $uid = $userinfo['customerid']; } $success_message = ""; $tfa = new froxlortwofactorauth('froxlor ' . settings::get('system.hostname')); // delete show success-message ($action == 'delete') { database::pexecute($upd_stmt, [ 't2fa' =&gt; 0, 'd2fa' =&gt; "", 'id' =&gt; $uid ]); response::standardsuccess('2fa.2fa_removed'); } elseif ($action == 'preadd') { $type = request::post('type_2fa', '0'); $data = ""; ($type &gt; 0) { // generate secret totp $data = $tfa-&gt;createsecret(); $userinfo['type_2fa'] = $type; $userinfo['data_2fa'] = $data; $userinfo['2fa_unsaved'] = true; // type = email, send code confirmation ($type == 1) { $code = $tfa-&gt;getcode($data); $_mailerror = false; $mailerr_msg = ""; $replace_arr = [ 'code' =&gt; $code ]; $mail_body = html_entity_decode(phphelper::replacevariables(lng('mails.2fa.mailbody'), $replace_arr)); try { $mail-&gt;subject = lng('mails.2fa.subject'); $mail-&gt;altbody = $mail_body; $mail-&gt;msghtml(str_replace("\n", "&lt;br /&gt;", $mail_body)); $mail-&gt;addaddress($userinfo['email'], user::getcorrectusersalutation($userinfo)); $mail-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { response::dynamicerror($mailerr_msg); } } ui::twig()-&gt;addglobal('userinfo', $userinfo); } else { response::dynamicerror('select one possible values 2fa'); } } elseif ($action == 'add') { $type = request::post('type_2fa', '0'); $data = request::post('data_2fa', ''); $code = request::post('codevalidation', ''); // validate $result = $tfa-&gt;verifycode($data, $code, 3); ($result) { ($type == 0 || $type == 1) { // fixed secret email validation, validation code set fly $data = ""; } database::pexecute($upd_stmt, [ 't2fa' =&gt; $type, 'd2fa' =&gt; $data, 'id' =&gt; $uid ]); response::standardsuccess('2fa.2fa_added', $filename); } response::dynamicerror('invalid/wrong code'); } $log-&gt;logaction(froxlorlogger::usr_action, log_notice, "viewed 2fa::overview"); $type_select_values = []; $ga_qrcode = ''; ($userinfo['type_2fa'] == '0') { // available types $type_select_values = [ 0 =&gt; '-', 1 =&gt; 'e-mail', 2 =&gt; 'authenticator' ]; asort($type_select_values); } elseif ($userinfo['type_2fa'] == '1') { // email 2fa enabled } elseif ($userinfo['type_2fa'] == '2') { // authenticator 2fa enabled $ga_qrcode = $tfa-&gt;getqrcodeimageasdatauri($userinfo['loginname'], $userinfo['data_2fa']); } ui::view('user/2fa.html.twig', [ 'type_select_values' =&gt; $type_select_values, 'ga_qrcode' =&gt; $ga_qrcode ]);</file><file name="customer_index.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'customer'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\customers customers; use froxlor\cron\taskid; use froxlor\currentuser; use froxlor\database\database; use froxlor\database\dbmanager; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\language; use froxlor\settings; use froxlor\system\cronjob; use froxlor\system\crypt; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\validate\validate; ($action == 'logout') { $log-&gt;logaction(froxlorlogger::usr_action, log_info, 'logged out'); unset($_session['userinfo']); currentuser::setdata(); session_destroy(); response::redirectto('index.php'); } elseif ($action == 'suback') { (is_array(currentuser::getfield('switched_user'))) { $result = currentuser::getdata(); $result = $result['switched_user']; session_regenerate_id(true); currentuser::setdata($result); $target = request::get('target', 'index'); $redirect = "admin_" . $target . ".php"; (!file_exists(froxlor::getinstalldir() . "/" . $redirect)) { $redirect = "admin_index.php"; } response::redirectto($redirect, null, true); } else { response::dynamicerror("cannot change back - never switched another user :-)"); } } ($page == 'overview') { $log-&gt;logaction(froxlorlogger::usr_action, log_info, "viewed customer_index"); $domain_stmt = database::prepare("select `domain` `" . table_panel_domains . "` `customerid` = :customerid `parentdomainid` = '0' `id` &lt;&gt; :standardsubdomain "); database::pexecute($domain_stmt, [ "customerid" =&gt; $userinfo['customerid'], "standardsubdomain" =&gt; $userinfo['standardsubdomain'] ]); $domainarray = []; ($row = $domain_stmt-&gt;fetch(pdo::fetch_assoc)) { $domainarray[] = $idna_convert-&gt;decode($row['domain']); } natsort($domainarray); // standard-subdomain $stdsubdomain = ''; ($userinfo['standardsubdomain'] != '0') { $std_domain_stmt = database::prepare(" select `domain` `" . table_panel_domains . "` `customerid` = :customerid `id` = :standardsubdomain "); $std_domain = database::pexecute_first($std_domain_stmt, [ "customerid" =&gt; $userinfo['customerid'], "standardsubdomain" =&gt; $userinfo['standardsubdomain'] ]); $stdsubdomain = $std_domain['domain']; } $userinfo['email'] = $idna_convert-&gt;decode($userinfo['email']); $yesterday = time() - (60 * 60 * 24); $month = date('m y', $yesterday); // get disk-space usages web, mysql mail $usages_stmt = database::prepare("select * `" . table_panel_diskspace . "` `customerid` = :cid order `stamp` desc limit 1"); $usages = database::pexecute_first($usages_stmt, [ 'cid' =&gt; $userinfo['customerid'] ]); // get everything bytes percentage calculation dashboard $userinfo['diskspace_bytes'] = ($userinfo['diskspace'] &gt; -1) ? $userinfo['diskspace'] * 1024 : -1; $userinfo['traffic_bytes'] = ($userinfo['traffic'] &gt; -1) ? $userinfo['traffic'] * 1024 : -1; $userinfo['traffic_bytes_used'] = $userinfo['traffic_used'] * 1024; (settings::get('system.mail_quota_enabled')) { $userinfo['email_quota_bytes'] = ($userinfo['email_quota'] &gt; -1) ? $userinfo['email_quota'] * 1024 * 1024 : -1; $userinfo['email_quota_bytes_used'] = $userinfo['email_quota_used'] * 1024 * 1024; } ($usages) { $userinfo['diskspace_bytes_used'] = $usages['webspace'] * 1024; $userinfo['mailspace_used'] = $usages['mail'] * 1024; $userinfo['dbspace_used'] = $usages['mysql'] * 1024; $userinfo['total_bytes_used'] = ($usages['webspace'] + $usages['mail'] + $usages['mysql']) * 1024; } else { $userinfo['diskspace_bytes_used'] = 0; $userinfo['total_bytes_used'] = 0; $userinfo['mailspace_used'] = 0; $userinfo['dbspace_used'] = 0; } ui::twig()-&gt;addglobal('userinfo', $userinfo); ui::view('user/index.html.twig', [ 'domains' =&gt; $domainarray, 'stdsubdomain' =&gt; $stdsubdomain ]); } elseif ($page == 'profile') { $languages = language::getlanguages(); (!empty($_post)) { (request::post('send') == 'changepassword') { $old_password = validate::validate(request::post('old_password'), 'old password'); (!crypt::validatepasswordlogin($userinfo, $old_password, table_panel_customers, 'customerid')) { response::standarderror('oldpasswordnotcorrect'); } try { $new_password = crypt::validatepassword(request::post('new_password'), 'new password'); $new_password_confirm = crypt::validatepassword(request::post('new_password_confirm'), 'new password confirm'); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } ($old_password == '') { response::standarderror([ 'stringisempty', 'changepassword.old_password' ]); } elseif ($new_password == '') { response::standarderror([ 'stringisempty', 'changepassword.new_password' ]); } elseif ($new_password_confirm == '') { response::standarderror([ 'stringisempty', 'changepassword.new_password_confirm' ]); } elseif ($new_password != $new_password_confirm) { response::standarderror('newpasswordconfirmerror'); } else { // update user password try { customers::getlocal($userinfo, [ 'id' =&gt; $userinfo['customerid'], 'new_customer_password' =&gt; $new_password ])-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $log-&gt;logaction(froxlorlogger::usr_action, log_notice, 'changed password'); // update ftp password (request::post('change_main_ftp') == 'true') { $cryptpassword = crypt::makecryptpassword($new_password); $stmt = database::prepare("update `" . table_ftp_users . "` set `password` = :password `customerid` = :customerid `username` = :username"); $params = [ "password" =&gt; $cryptpassword, "customerid" =&gt; $userinfo['customerid'], "username" =&gt; $userinfo['loginname'] ]; database::pexecute($stmt, $params); $log-&gt;logaction(froxlorlogger::usr_action, log_notice, 'changed main ftp password'); } // update statistics password (request::post('change_stats') == 'true') { $new_stats_password = crypt::makecryptpassword($new_password, true); $stmt = database::prepare("update `" . table_panel_htpasswds . "` set `password` = :password `customerid` = :customerid `username` = :username"); $params = [ "password" =&gt; $new_stats_password, "customerid" =&gt; $userinfo['customerid'], "username" =&gt; $userinfo['loginname'] ]; database::pexecute($stmt, $params); cronjob::inserttask(taskid::rebuild_vhost); } // update global myqsl user password ($userinfo['mysqls'] != 0 &amp;&amp; request::post('change_global_mysql') == 'true') { $allowed_mysqlservers = json_decode($userinfo['allowed_mysqlserver'] ?? '[]', true); foreach ($allowed_mysqlservers $dbserver) { // require privileged access target db-server database::needroot(true, $dbserver, false); // get dbmanager $dbm = new dbmanager($log); // give permission user every access-host foreach (array_map('trim', explode(',', settings::get('system.mysql_access_host'))) $mysql_access_host) { ($dbm-&gt;getmanager()-&gt;userexistsonhost($userinfo['loginname'], $mysql_access_host)) { $dbm-&gt;getmanager()-&gt;grantprivilegesto($userinfo['loginname'], $new_password, $mysql_access_host, false, true); } else { // create global mysql user exists $dbm-&gt;getmanager()-&gt;grantprivilegesto($userinfo['loginname'], $new_password, $mysql_access_host, false, false, true); } } $dbm-&gt;getmanager()-&gt;flushprivileges(); } } response::redirectto($filename); } } elseif (request::post('send') == 'changetheme') { (settings::get('panel.allow_theme_change_customer') == 1) { $theme = validate::validate(request::post('theme'), 'theme'); try { customers::getlocal($userinfo, [ 'id' =&gt; $userinfo['customerid'], 'theme' =&gt; $theme ])-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $log-&gt;logaction(froxlorlogger::usr_action, log_notice, "changed default theme '" . $theme . "'"); } response::redirectto($filename); } elseif (request::post('send') == 'changelanguage') { $def_language = validate::validate(request::post('def_language'), 'default language'); (isset($languages[$def_language])) { try { customers::getlocal($userinfo, [ 'id' =&gt; $userinfo['customerid'], 'def_language' =&gt; $def_language ])-&gt;update(); currentuser::setfield('language', $def_language); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } } $log-&gt;logaction(froxlorlogger::usr_action, log_notice, "changed default language '" . $def_language . "'"); response::redirectto($filename); } } else { // change theme $default_theme = settings::get('panel.default_theme'); ($userinfo['theme'] != '') { $default_theme = $userinfo['theme']; } $themes_avail = ui::getthemes(); // change language $default_lang = settings::get('panel.standardlanguage'); ($userinfo['def_language'] != '') { $default_lang = $userinfo['def_language']; } ui::view('user/profile.html.twig', [ 'themes' =&gt; $themes_avail, 'default_theme' =&gt; $default_theme, 'languages' =&gt; $languages, 'default_lang' =&gt; $default_lang, ]); } } elseif ($page == 'send_error_report' &amp;&amp; settings::get('system.allow_error_report_customer') == '1') { require_once __dir__ . '/error_report.php'; } elseif ($page == 'apikeys' &amp;&amp; settings::get('api.enabled') == 1) { require_once __dir__ . '/api_keys.php'; } elseif ($page == '2fa' &amp;&amp; settings::get('2fa.enabled') == 1) { require_once __dir__ . '/2fa.php'; }</file><file name="customer_logger.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'customer'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\syslog; use froxlor\settings; use froxlor\ui\collection; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\response; // redirect customer page hidden via settings (settings::isinlist('panel.customer_hide_options', 'extras.logger')) { response::redirectto('customer_index.php'); } ($page == 'log') { ($action == '') { try { $syslog_list_data = include_once dirname(__file__) . '/lib/tablelisting/tablelisting.syslog.php'; $collection = (new collection(syslog::class, $userinfo)) -&gt;withpagination($syslog_list_data['syslog_list']['columns'], $syslog_list_data['syslog_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $syslog_list_data, 'syslog_list') ]); } }</file><file name="customer_email.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'customer'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\emailaccounts; use froxlor\api\commands\emaildomains; use froxlor\api\commands\emailforwarders; use froxlor\api\commands\emails; use froxlor\cron\mail\rspamd; use froxlor\currentuser; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\settings; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\validate\check; // redirect customer page hidden via settings (settings::isinlist('panel.customer_hide_options', 'email') || $userinfo['emails'] == 0) { response::redirectto('customer_index.php'); } $id = (int)request::any('id'); ($page == 'overview' || $page == 'emails') { $result_stmt = database::prepare(" select count(distinct `domainid`) maildomains `" . table_mail_virtual . "` `customerid`= :cid "); $domain_count = database::pexecute_first($result_stmt, [ "cid" =&gt; $userinfo['customerid'] ]); ($domain_count['maildomains'] &amp;&amp; $domain_count['maildomains'] &gt; 1) { try { $emaildomain_list_data = include_once dirname(__file__) . '/lib/tablelisting/customer/tablelisting.emails_overview.php'; $collection = (new collection(emaildomains::class, $userinfo)) -&gt;withpagination($emaildomain_list_data['emaildomain_list']['columns'], $emaildomain_list_data['emaildomain_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $actions_links = []; (currentuser::canaddresource('emails')) { $actions_links[] = [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'email', 'page' =&gt; 'email_domain', 'action' =&gt; 'add']), 'label' =&gt; lng('emails.emails_add') ]; } $actions_links[] = [ 'href' =&gt; \froxlor\froxlor::getdocsurl() . 'user-guide/emails/', 'target' =&gt; '_blank', 'icon' =&gt; 'fa-solid fa-circle-info', 'class' =&gt; 'btn-outline-secondary' ]; ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $emaildomain_list_data, 'emaildomain_list'), 'actions_links' =&gt; $actions_links, ]); } else { // emails one domain -&gt; show email address listing directly $page = 'email_domain'; } } ($page == 'email_domain') { $email_domainid = request::any('domainid', 0); ($action == '') { $log-&gt;logaction(froxlorlogger::usr_action, log_info, "viewed customer_email::emails"); $sql_search = []; ($email_domainid &gt; 0) { $sql_search = ['sql_search' =&gt; ['m.domainid' =&gt; ['op' =&gt; '=', 'value' =&gt; $email_domainid]]]; } try { $email_list_data = include_once dirname(__file__) . '/lib/tablelisting/customer/tablelisting.emails.php'; $collection = (new collection(emails::class, $userinfo, $sql_search)) -&gt;withpagination($email_list_data['email_list']['columns'], $email_list_data['email_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result_stmt = database::prepare(" select count(`id`) emaildomains `" . table_panel_domains . "` `customerid`= :cid `isemaildomain` = '1' "); $result2 = database::pexecute_first($result_stmt, [ "cid" =&gt; $userinfo['customerid'] ]); $emaildomains_count = $result2['emaildomains']; $actions_links = []; ($email_domainid &gt; 0) { $actions_links[] = [ 'class' =&gt; 'btn-outline-primary', 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'email', 'page' =&gt; 'emails', ]), 'label' =&gt; lng('emails.back_to_overview'), 'icon' =&gt; 'fa-solid fa-reply' ]; } (currentuser::canaddresource('emails')) { $actions_links[] = [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'email', 'page' =&gt; 'email_domain', 'action' =&gt; 'add', 'domainid' =&gt; $email_domainid]), 'label' =&gt; lng('emails.emails_add') ]; } $actions_links[] = [ 'href' =&gt; \froxlor\froxlor::getdocsurl() . 'user-guide/emails/', 'target' =&gt; '_blank', 'icon' =&gt; 'fa-solid fa-circle-info', 'class' =&gt; 'btn-outline-secondary' ]; ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $email_list_data, 'email_list'), 'actions_links' =&gt; $actions_links, 'entity_info' =&gt; lng('emails.description') ]); } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = emails::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['email']) &amp;&amp; $result['email'] != '') { (request::post('send') == 'send') { try { emails::getlocal($userinfo, [ 'id' =&gt; $id, 'delete_userfiles' =&gt; request::post('delete_userfiles', 0) ])-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { ($result['popaccountid'] != '0') { $show_checkbox = true; } else { $show_checkbox = false; } html::askyesnowithcheckbox('email_reallydelete', 'admin_customer_alsoremovemail', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $idna_convert-&gt;decode($result['email_full']), $show_checkbox); } } } elseif ($action == 'add') { ($userinfo['emails_used'] &lt; $userinfo['emails'] || $userinfo['emails'] == '-1') { (request::post('send') == 'send') { try { $json_result = emails::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; response::redirectto($filename, [ 'page' =&gt; $page, 'action' =&gt; 'edit', 'id' =&gt; $result['id'] ]); } else { $result_stmt = database::prepare("select `id`, `domain`, `customerid` `" . table_panel_domains . "` `customerid`= :cid `isemaildomain`='1' order `domain_ace` asc"); database::pexecute($result_stmt, [ "cid" =&gt; $userinfo['customerid'] ]); $domains = []; $selected_domain = ""; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { ($email_domainid == $row['id']) { $selected_domain = $row['domain']; } $domains[$row['domain']] = $idna_convert-&gt;decode($row['domain']); } (count($domains) &gt; 0) { $email_add_data = include_once dirname(__file__) . '/lib/formfields/customer/email/formfield.emails_add.php'; (settings::get('catchall.catchall_enabled') != '1') { unset($email_add_data['emails_add']['sections']['section_a']['fields']['iscatchall']); } ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'email']), 'formdata' =&gt; $email_add_data['emails_add'] ]); } else { response::standarderror('emails.noemaildomainaddedyet'); } } } else { response::standarderror('allresourcesused'); } } elseif ($action == 'edit' &amp;&amp; $id != 0) { try { $json_result = emails::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['email']) &amp;&amp; $result['email'] != '') { (request::post('send') == 'send') { try { emails::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } $result['email'] = $idna_convert-&gt;decode($result['email']); $result['email_full'] = $idna_convert-&gt;decode($result['email_full']); $result['destination'] = explode(' ', $result['destination']); uasort($result['destination'], 'strcasecmp'); $forwarders = []; $forwarders_count = 0; foreach ($result['destination'] $dest_id =&gt; $destination) { $destination = $idna_convert-&gt;decode($destination); ($destination != $result['email_full'] &amp;&amp; $destination != '') { $forwarders[] = [ 'item' =&gt; $destination, 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'email', 'page' =&gt; 'forwarders', 'action' =&gt; 'delete', 'id' =&gt; $id, 'forwarderid' =&gt; $dest_id ]), 'label' =&gt; lng('panel.delete'), 'classes' =&gt; 'btn btn-sm btn-danger' ]; $forwarders_count++; } $result['destination'][$dest_id] = $destination; } $destinations_count = count($result['destination']); $result = phphelper::htmlentitiesarray($result); $email_edit_data = include_once dirname(__file__) . '/lib/formfields/customer/email/formfield.emails_edit.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'email']), 'formdata' =&gt; $email_edit_data['emails_edit'], 'editid' =&gt; $id ]); } } } elseif ($page == 'accounts') { $email_domainid = request::any('domainid', 0); ($action == 'add' &amp;&amp; $id != 0) { ($userinfo['email_accounts'] == '-1' || ($userinfo['email_accounts_used'] &lt; $userinfo['email_accounts'])) { try { $json_result = emails::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (request::post('send') == 'send') { try { emailaccounts::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid, 'action' =&gt; 'edit', 'id' =&gt; $id ]); } else { (check::checkmailaccdeletionstate($result['email_full'])) { response::standarderror([ 'mailaccistobedeleted' ], $result['email_full']); } $result['email_full'] = $idna_convert-&gt;decode($result['email_full']); $result = phphelper::htmlentitiesarray($result); $quota = settings::get('system.mail_quota'); $account_add_data = include_once dirname(__file__) . '/lib/formfields/customer/email/formfield.emails_addaccount.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'email', 'id' =&gt; $id]), 'formdata' =&gt; $account_add_data['emails_addaccount'], 'actions_links' =&gt; [ [ 'class' =&gt; 'btn-secondary', 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'email', 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid, 'action' =&gt; 'edit', 'id' =&gt; $id ]), 'label' =&gt; lng('emails.emails_edit'), 'icon' =&gt; 'fa-solid fa-pen' ], [ 'class' =&gt; 'btn-secondary', 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'email', 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid ]), 'label' =&gt; lng('menue.email.emails'), 'icon' =&gt; 'fa-solid fa-envelope' ] ], ]); } } else { response::standarderror([ 'allresourcesused', 'allocatetoomuchquota' ], $quota); } } elseif ($action == 'changepw' &amp;&amp; $id != 0) { try { $json_result = emails::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['popaccountid']) &amp;&amp; $result['popaccountid'] != '') { (request::post('send') == 'send') { try { emailaccounts::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid, 'action' =&gt; 'edit', 'id' =&gt; $id ]); } else { $result['email_full'] = $idna_convert-&gt;decode($result['email_full']); $result = phphelper::htmlentitiesarray($result); $account_changepw_data = include_once dirname(__file__) . '/lib/formfields/customer/email/formfield.emails_accountchangepasswd.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'email', 'id' =&gt; $id]), 'formdata' =&gt; $account_changepw_data['emails_accountchangepasswd'], 'actions_links' =&gt; [ [ 'class' =&gt; 'btn-secondary', 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'email', 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid, 'action' =&gt; 'edit', 'id' =&gt; $id ]), 'label' =&gt; lng('emails.emails_edit'), 'icon' =&gt; 'fa-solid fa-pen' ], [ 'class' =&gt; 'btn-secondary', 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'email', 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid ]), 'label' =&gt; lng('menue.email.emails'), 'icon' =&gt; 'fa-solid fa-envelope' ] ], ]); } } } elseif ($action == 'changequota' &amp;&amp; settings::get('system.mail_quota_enabled') == '1' &amp;&amp; $id != 0) { try { $json_result = emails::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['popaccountid']) &amp;&amp; $result['popaccountid'] != '') { (request::post('send') == 'send') { try { emailaccounts::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid, 'action' =&gt; 'edit', 'id' =&gt; $id ]); } else { $result['email_full'] = $idna_convert-&gt;decode($result['email_full']); $result = phphelper::htmlentitiesarray($result); $quota_edit_data = include_once dirname(__file__) . '/lib/formfields/customer/email/formfield.emails_accountchangequota.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'email', 'id' =&gt; $id]), 'formdata' =&gt; $quota_edit_data['emails_accountchangequota'], 'actions_links' =&gt; [ [ 'class' =&gt; 'btn-secondary', 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'email', 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid, 'action' =&gt; 'edit', 'id' =&gt; $id ]), 'label' =&gt; lng('emails.emails_edit'), 'icon' =&gt; 'fa-solid fa-pen' ], [ 'class' =&gt; 'btn-secondary', 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'email', 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid ]), 'label' =&gt; lng('menue.email.emails'), 'icon' =&gt; 'fa-solid fa-envelope' ] ], ]); } } } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = emails::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['popaccountid']) &amp;&amp; $result['popaccountid'] != '') { (request::post('send') == 'send') { try { emailaccounts::getlocal($userinfo, request::postall())-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid, 'action' =&gt; 'edit', 'id' =&gt; $id ]); } else { html::askyesnowithcheckbox('email_reallydelete_account', 'admin_customer_alsoremovemail', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'domainid' =&gt; $email_domainid, 'action' =&gt; $action ], $idna_convert-&gt;decode($result['email_full'])); } } } } elseif ($page == 'forwarders') { $email_domainid = request::any('domainid', 0); ($action == 'add' &amp;&amp; $id != 0) { ($userinfo['email_forwarders_used'] &lt; $userinfo['email_forwarders'] || $userinfo['email_forwarders'] == '-1') { try { $json_result = emails::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['email']) &amp;&amp; $result['email'] != '') { (request::post('send') == 'send') { try { emailforwarders::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid, 'action' =&gt; 'edit', 'id' =&gt; $id ]); } else { $result['email_full'] = $idna_convert-&gt;decode($result['email_full']); $result = phphelper::htmlentitiesarray($result); $forwarder_add_data = include_once dirname(__file__) . '/lib/formfields/customer/email/formfield.emails_addforwarder.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'email', 'id' =&gt; $id]), 'formdata' =&gt; $forwarder_add_data['emails_addforwarder'], 'actions_links' =&gt; [ [ 'class' =&gt; 'btn-secondary', 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'email', 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid, 'action' =&gt; 'edit', 'id' =&gt; $id ]), 'label' =&gt; lng('emails.emails_edit'), 'icon' =&gt; 'fa-solid fa-pen' ], [ 'class' =&gt; 'btn-secondary', 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'email', 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid ]), 'label' =&gt; lng('menue.email.emails'), 'icon' =&gt; 'fa-solid fa-envelope' ] ], ]); } } } else { response::standarderror('allresourcesused'); } } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = emails::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (isset($result['destination']) &amp;&amp; $result['destination'] != '') { $forwarderid = request::any('forwarderid', 0); $result['destination'] = explode(' ', $result['destination']); (isset($result['destination'][$forwarderid]) &amp;&amp; $result['email'] != $result['destination'][$forwarderid]) { $forwarder = $result['destination'][$forwarderid]; (request::post('send') == 'send') { try { emailforwarders::getlocal($userinfo, request::postall())-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; 'email_domain', 'domainid' =&gt; $email_domainid, 'action' =&gt; 'edit', 'id' =&gt; $id ]); } else { html::askyesno('email_reallydelete_forwarder', $filename, [ 'id' =&gt; $id, 'forwarderid' =&gt; $forwarderid, 'page' =&gt; $page, 'domainid' =&gt; $email_domainid, 'action' =&gt; $action ], $idna_convert-&gt;decode($result['email_full']) . ' -&gt; ' . $idna_convert-&gt;decode($forwarder)); } } } } }</file><file name="admin_plans.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\hostingplans; use froxlor\api\commands\mysqlserver; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\settings; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; $id = (int)request::any('id'); ($page == '' || $page == 'overview') { ($action == '') { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "viewed admin_plans"); try { $plan_list_data = include_once dirname(__file__) . '/lib/tablelisting/admin/tablelisting.plans.php'; $collection = (new collection(hostingplans::class, $userinfo)) -&gt;withpagination($plan_list_data['plan_list']['columns'], $plan_list_data['plan_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $plan_list_data, 'plan_list'), 'actions_links' =&gt; [ [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'plans', 'page' =&gt; $page, 'action' =&gt; 'add']), 'label' =&gt; lng('admin.plans.add') ] ] ]); } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = hostingplans::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($result['id'] != 0 &amp;&amp; $result['id'] == $id &amp;&amp; (int)$userinfo['adminid'] == $result['adminid']) { (request::post('send') == 'send') { try { hostingplans::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesno('plan_reallydelete', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $result['name']); } } else { response::standarderror('nopermissionsorinvalidid'); } } elseif ($action == 'add') { (request::post('send') == 'send') { try { hostingplans::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $mysql_servers = []; try { $result_json = mysqlserver::getlocal($userinfo)-&gt;listing(); $result_decoded = json_decode($result_json, true)['data']['list']; foreach ($result_decoded $dbserver =&gt; $dbdata) { $mysql_servers[] = [ 'label' =&gt; $dbdata['caption'], 'value' =&gt; $dbserver ]; } } catch (exception $e) { /* none */ } $phpconfigs = []; $configs = database::query(" select c.*, fc.description interpreter `" . table_panel_phpconfigs . "` c left join `" . table_panel_fpmdaemons . "` fc fc.id = c.fpmsettingid "); ($row = $configs-&gt;fetch(pdo::fetch_assoc)) { ((int)settings::get('phpfpm.enabled') == 1) { $phpconfigs[] = [ 'label' =&gt; $row['description'] . " [" . $row['interpreter'] . "]", 'value' =&gt; $row['id'] ]; } else { $phpconfigs[] = [ 'label' =&gt; $row['description'], 'value' =&gt; $row['id'] ]; } } // dummy avoid unknown variables $hosting_plans = null; $plans_add_data = include_once __dir__ . '/lib/formfields/admin/plans/formfield.plans_add.php'; $cust_add_data = include_once __dir__ . '/lib/formfields/admin/customer/formfield.customer_add.php'; // unset unneeded stuff unset($cust_add_data['customer_add']['sections']['section_a']); unset($cust_add_data['customer_add']['sections']['section_b']); unset($cust_add_data['customer_add']['sections']['section_cpre']); // merge $plans_add_data['plans_add']['sections'] = array_merge($plans_add_data['plans_add']['sections'], $cust_add_data['customer_add']['sections']); ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'plans']), 'formdata' =&gt; $plans_add_data['plans_add'] ]); } } elseif ($action == 'edit' &amp;&amp; $id != 0) { try { $json_result = hostingplans::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($result['name'] != '') { $result['value'] = json_decode($result['value'], true); $result = phphelper::htmlentitiesarray($result); foreach ($result['value'] $index =&gt; $value) { $result[$index] = $value; } $result['allowed_phpconfigs'] = json_encode($result['allowed_phpconfigs']); (request::post('send') == 'send') { try { hostingplans::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $mysql_servers = []; try { $result_json = mysqlserver::getlocal($userinfo)-&gt;listing(); $result_decoded = json_decode($result_json, true)['data']['list']; foreach ($result_decoded $dbserver =&gt; $dbdata) { $mysql_servers[] = [ 'label' =&gt; $dbdata['caption'], 'value' =&gt; $dbserver ]; } } catch (exception $e) { /* none */ } $phpconfigs = []; $configs = database::query(" select c.*, fc.description interpreter `" . table_panel_phpconfigs . "` c left join `" . table_panel_fpmdaemons . "` fc fc.id = c.fpmsettingid "); ($row = $configs-&gt;fetch(pdo::fetch_assoc)) { ((int)settings::get('phpfpm.enabled') == 1) { $phpconfigs[] = [ 'label' =&gt; $row['description'] . " [" . $row['interpreter'] . "]", 'value' =&gt; $row['id'] ]; } else { $phpconfigs[] = [ 'label' =&gt; $row['description'], 'value' =&gt; $row['id'] ]; } } $result['imap'] = $result['email_imap']; $result['pop3'] = $result['email_pop3']; // dummy avoid unknown variables $result['loginname'] = null; $result['documentroot'] = null; $result['standardsubdomain'] = null; $result['deactivated'] = null; $result['def_language'] = null; $result['firstname'] = null; $result['gender'] = null; $result['company'] = null; $result['street'] = null; $result['zipcode'] = null; $result['city'] = null; $result['phone'] = null; $result['fax'] = null; $result['email'] = null; $result['customernumber'] = null; $result['custom_notes'] = null; $result['custom_notes_show'] = null; $result['api_allowed'] = null; $hosting_plans = null; $admin_select = []; $plans_edit_data = include_once __dir__ . '/lib/formfields/admin/plans/formfield.plans_edit.php'; $cust_edit_data = include_once __dir__ . '/lib/formfields/admin/customer/formfield.customer_edit.php'; // unset unneeded stuff unset($cust_edit_data['customer_edit']['sections']['section_a']); unset($cust_edit_data['customer_edit']['sections']['section_b']); unset($cust_edit_data['customer_edit']['sections']['section_cpre']); unset($cust_edit_data['customer_edit']['sections']['section_d']); // merge $plans_edit_data['plans_edit']['sections'] = array_merge($plans_edit_data['plans_edit']['sections'], $cust_edit_data['customer_edit']['sections']); ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'plans', 'id' =&gt; $id]), 'formdata' =&gt; $plans_edit_data['plans_edit'], 'editid' =&gt; $id ]); } } } elseif ($action == 'jqgetplanvalues') { $planid = (int)request::any('planid', 0); try { $json_result = hostingplans::getlocal($userinfo, [ 'id' =&gt; $planid ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; echo $result['value']; exit(); } }</file><file name="ssl_certificates.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ (!defined('area')) { header("location: index.php"); exit(); } use froxlor\api\commands\certificates; use froxlor\api\commands\domains; use froxlor\api\commands\subdomains; use froxlor\froxlorlogger; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; // file included admin_domains customer_domains // therefore need require lib/init.php $success_message = ""; $id = (int)request::any('id'); // delete show success-message certificates list ($action == 'delete') { html::askyesno('certificate_reallydelete', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; 'deletesure' ], '', [ 'section' =&gt; 'domains', 'page' =&gt; $page ]); } elseif (request::post('send') == 'send' &amp;&amp; $action == 'deletesure' &amp;&amp; $id &gt; 0) { try { $json_result = certificates::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;delete(); $success_message = lng('domains.ssl_certificate_removed', [$id]); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } } $log-&gt;logaction(froxlorlogger::usr_action, log_notice, "viewed domains::ssl_certificates"); try { $certificates_list_data = include_once dirname(__file__) . '/lib/tablelisting/tablelisting.sslcertificates.php'; $collection = (new collection(certificates::class, $userinfo)) -&gt;withpagination($certificates_list_data['sslcertificates_list']['columns'], $certificates_list_data['sslcertificates_list']['default_sorting']); ($userinfo['adminsession'] == 1) { $collection-&gt;has('domains', domains::class, 'domainid', 'id'); } else { $collection-&gt;has('domains', subdomains::class, 'domainid', 'id'); } } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $certificates_list_data, 'sslcertificates_list'), ]);</file><file name="admin_apcuinfo.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @author janos muzsi &lt;muzsij@hypernics.hu&gt; * @author ralf becker &lt;beckerr@php.net&gt; * @author rasmus lerdorf &lt;rasmus@php.net&gt; * @author ilia alshanetsky &lt;ilia@prohost.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 * * based https://github.com/krakjoe/apcu/blob/master/apc.php, * licensed php licence (version 3.01), viewed * online https://www.php.net/license/3_01.txt */ use froxlor\froxlorlogger; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\ui\html; const area = 'admin'; require __dir__ . '/lib/init.php'; $horizontal_bar_size = 950; // 1280px window width ($action == 'delete' &amp;&amp; function_exists('apcu_clear_cache') &amp;&amp; $userinfo['change_serversettings'] == '1') { (request::post('send') == 'send') { apcu_clear_cache(); $log-&gt;logaction(froxlorlogger::adm_action, log_info, "cleared apcu cache"); header('location: ' . $linker-&gt;getlink([ 'section' =&gt; 'apcuinfo', 'page' =&gt; 'showinfo' ])); exit(); } else { html::askyesno('cache_reallydelete', $filename, [ 'page' =&gt; $page, 'action' =&gt; 'delete', ], '', [ 'section' =&gt; 'apcuinfo', 'page' =&gt; 'showinfo' ]); } } (!function_exists('apcu_cache_info') || !function_exists('apcu_sma_info')) { response::standarderror('no_apcuinfo'); } ($page == 'showinfo' &amp;&amp; $userinfo['change_serversettings'] == '1') { $cache = apcu_cache_info(); $mem = apcu_sma_info(); $time = time(); $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "viewed admin_apcuinfo"); // check possible empty values used templates (!isset($cache['file_upload_progress'])) { $cache['file_upload_progress'] = lng('logger.unknown'); } (!isset($cache['num_expunges'])) { $cache['num_expunges'] = lng('logger.unknown'); } $overview = [ 'mem_size' =&gt; $mem['num_seg'] * $mem['seg_size'], 'mem_avail' =&gt; $mem['avail_mem'], 'mem_used' =&gt; ($mem['num_seg'] * $mem['seg_size']) - $mem['avail_mem'], 'seg_size' =&gt; bsize($mem['seg_size']), 'num_hits' =&gt; $cache['num_hits'], 'num_misses' =&gt; $cache['num_misses'], 'num_inserts' =&gt; $cache['num_inserts'], 'req_rate_user' =&gt; sprintf("%.2f", $cache['num_hits'] ? (($cache['num_hits'] + $cache['num_misses']) / ($time - $cache['start_time'])) : 0), 'hit_rate_user' =&gt; sprintf("%.2f", $cache['num_hits'] ? (($cache['num_hits']) / ($time - $cache['start_time'])) : 0), 'miss_rate_user' =&gt; sprintf("%.2f", $cache['num_misses'] ? (($cache['num_misses']) / ($time - $cache['start_time'])) : 0), 'insert_rate_user' =&gt; sprintf("%.2f", $cache['num_inserts'] ? (($cache['num_inserts']) / ($time - $cache['start_time'])) : 0), 'apcversion' =&gt; phpversion('apcu'), 'phpversion' =&gt; phpversion(), 'number_vars' =&gt; $cache['num_entries'], 'size_vars' =&gt; bsize($cache['mem_size']), 'num_hits_and_misses' =&gt; 0 &gt;= ($cache['num_hits'] + $cache['num_misses']) ? 1 : ($cache['num_hits'] + $cache['num_misses']), 'file_upload_progress' =&gt; $cache['file_upload_progress'], 'num_expunges' =&gt; $cache['num_expunges'], 'host' =&gt; (function_exists('gethostname') ? gethostname() : (php_uname('n') ?: (empty($_server['server_name']) ? $_server['host_name'] : $_server['server_name'] ) ) ), 'server' =&gt; $_server['server_software'] ?: '', 'start_time' =&gt; $cache['start_time'], 'uptime' =&gt; duration($cache['start_time']) ]; $overview['mem_used_percentage'] = number_format(($overview['mem_used'] / $overview['mem_size']) * 100, 1); $overview['num_hits_percentage'] = number_format(($overview['num_hits'] / $overview['num_hits_and_misses']) * 100, 1); $overview['num_misses_percentage'] = number_format(($overview['num_misses'] / $overview['num_hits_and_misses']) * 100, 1); $overview['readable'] = [ 'mem_size' =&gt; bsize($overview['mem_size']), 'mem_avail' =&gt; bsize($overview['mem_avail']), 'mem_used' =&gt; bsize($overview['mem_used']), 'num_hits' =&gt; number_format($overview['num_hits']), 'num_misses' =&gt; number_format($overview['num_misses']), 'number_vars' =&gt; number_format($overview['number_vars']), ]; $overview['runtimelines'] = []; foreach (ini_get_all('apcu') $name =&gt; $v) { $value = $v['local_value']; $overview['runtimelines'][$name] = $value; } // fragementation: (freeseg - 1) / total_seg $nseg = $freeseg = $fragsize = $freetotal = 0; ($i = 0; $i &lt; $mem['num_seg']; $i++) { $ptr = 0; foreach ($mem['block_lists'][$i] $block) { ($block['offset'] != $ptr) { ++$nseg; } $ptr = $block['offset'] + $block['size']; /* consider blocks &lt;5m fragmentation % */ ($block['size'] &lt; (5 * 1024 * 1024)) { $fragsize += $block['size']; } $freetotal += $block['size']; } $freeseg += count($mem['block_lists'][$i]); } $overview['fragmentation'] = []; ($freeseg &gt; 1) { $overview['fragmentation']['used_percentage'] = number_format(($fragsize / $freetotal) * 100, 1); $overview['fragmentation']['used_bytes'] = $fragsize; $overview['fragmentation']['total_bytes'] = $freetotal; $overview['fragmentation']['num_frags'] = $freeseg; $overview['fragmentation']['readable'] = [ 'used_bytes' =&gt; bsize($fragsize), 'total_bytes' =&gt; bsize($freetotal), 'num_frags' =&gt; number_format($freeseg) ]; } else { $overview['fragmentation'] = 0; } ui::view('settings/apcuinfo.html.twig', [ 'apcuinfo' =&gt; $overview ]); } // pretty printer byte values function bsize($size) { $i = 0; $val = ['b', 'kb', 'mb', 'gb', 'tb', 'pb', 'eb', 'zb', 'yb']; (($size / 1024) &gt; 1) { $size /= 1024; ++$i; } return sprintf( '%.2f%s%s', $size, '', $val[$i] ); } function duration($ts) { global $time; $years = (int)((($time - $ts) / (7 * 86400)) / 52.177457); $rem = (int)(($time - $ts) - ($years * 52.177457 * 7 * 86400)); $weeks = (int)(($rem) / (7 * 86400)); $days = (int)(($rem) / 86400) - $weeks * 7; $hours = (int)(($rem) / 3600) - $days * 24 - $weeks * 7 * 24; $mins = (int)(($rem) / 60) - $hours * 60 - $days * 24 * 60 - $weeks * 7 * 24 * 60; $str = ''; ($years == 1) { $str .= "$years year, "; } ($years &gt; 1) { $str .= "$years years, "; } ($weeks == 1) { $str .= "$weeks week, "; } ($weeks &gt; 1) { $str .= "$weeks weeks, "; } ($days == 1) { $str .= "$days day,"; } ($days &gt; 1) { $str .= "$days days,"; } ($hours == 1) { $str .= " $hours hour and"; } ($hours &gt; 1) { $str .= " $hours hours and"; } ($mins == 1) { $str .= " 1 minute"; } else { $str .= " $mins minutes"; } return $str; }</file><file name="admin_settings.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\api\commands\froxlor; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\database\integritycheck; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\settings; use froxlor\system\cronjob; use froxlor\ui\form; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\user; use phpmailer\phpmailer\phpmailer; const area = 'admin'; require __dir__ . '/lib/init.php'; ($page == 'overview' &amp;&amp; $userinfo['change_serversettings'] == '1') { $settings_data = phphelper::loadconfigarraydir('./actions/admin/settings/'); settings::loadsettingsinto($settings_data); (request::post('send') == 'send') { $_part = request::get('part', ''); ($_part == '') { $_part = request::post('part', ''); } ($_part != '') { ($_part == 'all') { $settings_all = true; $settings_part = false; } else { $settings_all = false; $settings_part = true; } $only_enabledisable = false; } else { $settings_all = false; $settings_part = false; $only_enabledisable = true; } // check session timeout low #815 (!empty(request::post('session_sessiontimeout')) &amp;&amp; intval(request::post('session_sessiontimeout', 0)) &lt; 60) { response::standarderror(['session_timeout', 'session_timeout_desc']); } try { (form::processform($settings_data, request::postall(), [ 'filename' =&gt; $filename, 'action' =&gt; $action, 'page' =&gt; $page, 'part' =&gt; $_part, ], $_part, $settings_all, $settings_part, $only_enabledisable)) { $log-&gt;logaction(froxlorlogger::adm_action, log_info, "rebuild configfiles due changed setting"); cronjob::inserttask(taskid::rebuild_vhost); // using nameserver, insert task rebuilds server config cronjob::inserttask(taskid::rebuild_dns); // cron.d file cronjob::inserttask(taskid::rebuild_cron); response::standardsuccess('settingssaved', '', [ 'filename' =&gt; $filename, 'action' =&gt; $action, 'page' =&gt; $page ]); } } catch (exception $e) { response::dynamicerror($e-&gt;getmessage(), $e-&gt;getcode()); } } else { $_part = request::get('part', ''); ($_part == '') { $_part = request::post('part', ''); } $fields = form::buildform($settings_data, $_part); ($_part == '' || $_part == 'all') { ui::view('settings/index.html.twig', ['fields' =&gt; $fields]); } else { $em = request::any('em', ''); ui::view('settings/detailpart.html.twig', ['fields' =&gt; $fields, 'em' =&gt; $em]); } } } elseif ($page == 'phpinfo' &amp;&amp; $userinfo['change_serversettings'] == '1') { ob_start(); phpinfo(); $phpinfo = [ 'phpinfo' =&gt; [] ]; (preg_match_all('#(?:&lt;h2&gt;(?:&lt;a name=".*?"&gt;)?(.*?)(?:&lt;/a&gt;)?&lt;/h2&gt;)|(?:&lt;tr(?: class=".*?")?&gt;&lt;t[hd](?: class=".*?")?&gt;(.*?)\s*&lt;/t[hd]&gt;(?:&lt;t[hd](?: class=".*?")?&gt;(.*?)\s*&lt;/t[hd]&gt;(?:&lt;t[hd](?: class=".*?")?&gt;(.*?)\s*&lt;/t[hd]&gt;)?)?&lt;/tr&gt;)#s', ob_get_clean(), $matches, preg_set_order)) { foreach ($matches $match) { $end = array_keys($phpinfo); $end = end($end); (strlen($match[1])) { $phpinfo[$match[1]] = []; } elseif (isset($match[3])) { $phpinfo[$end][$match[2]] = isset($match[4]) ? [ $match[3], $match[4] ] : $match[3]; } else { $phpinfo[$end][] = $match[2]; } } } else { response::standarderror('error.no_phpinfo'); } ui::view('settings/phpinfo.html.twig', [ 'phpversion' =&gt; php_version, 'phpinfo' =&gt; $phpinfo ]); } elseif ($page == 'rebuildconfigs' &amp;&amp; $userinfo['change_serversettings'] == '1') { (request::post('send') == 'send') { $log-&gt;logaction(froxlorlogger::adm_action, log_info, "rebuild configfiles"); cronjob::inserttask(taskid::rebuild_vhost); cronjob::inserttask(taskid::create_quota); // using nameserver, insert task rebuilds server config cronjob::inserttask(taskid::rebuild_dns); // cron.d file cronjob::inserttask(taskid::rebuild_cron); response::standardsuccess('rebuildingconfigs', '', [ 'filename' =&gt; 'admin_index.php' ]); } else { html::askyesno('admin_configs_reallyrebuild', $filename, [ 'page' =&gt; $page ]); } } elseif ($page == 'updatecounters' &amp;&amp; $userinfo['change_serversettings'] == '1') { (request::post('send') == 'send') { $log-&gt;logaction(froxlorlogger::adm_action, log_info, "updated resource-counters"); $updatecounters = user::updatecounters(true); ui::view('user/resource-counter.html.twig', [ 'counters' =&gt; $updatecounters ]); } else { html::askyesno('admin_counters_reallyupdate', $filename, [ 'page' =&gt; $page ]); } } elseif ($page == 'wipecleartextmailpws' &amp;&amp; $userinfo['change_serversettings'] == '1') { (request::post('send') == 'send') { $log-&gt;logaction(froxlorlogger::adm_action, log_warning, "wiped cleartext mail passwords"); database::query("update `" . table_mail_users . "` set `password` = '';"); database::query("update `" . table_panel_settings . "` set `value` = '0' `settinggroup` = 'system' `varname` = 'mailpwcleartext'"); response::redirectto($filename); } else { html::askyesno('admin_cleartextmailpws_reallywipe', $filename, [ 'page' =&gt; $page ]); } } elseif ($page == 'wipequotas' &amp;&amp; $userinfo['change_serversettings'] == '1') { (request::post('send') == 'send') { $log-&gt;logaction(froxlorlogger::adm_action, log_warning, "wiped mailquotas"); // set quota 0 means unlimited database::query("update `" . table_mail_users . "` set `quota` = '0';"); database::query("update `" . table_panel_customers . "` set `email_quota_used` = '0'"); response::redirectto($filename); } else { html::askyesno('admin_quotas_reallywipe', $filename, [ 'page' =&gt; $page ]); } } elseif ($page == 'enforcequotas' &amp;&amp; $userinfo['change_serversettings'] == '1') { (request::post('send') == 'send') { // fetch accounts $result_stmt = database::query("select `quota`, `customerid` `" . table_mail_users . "`"); (database::num_rows() &gt; 0) { $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `email_quota_used` = `email_quota_used` + :diff `customerid` = :customerid "); ($array = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $difference = settings::get('system.mail_quota') - $array['quota']; database::pexecute($upd_stmt, [ 'diff' =&gt; $difference, 'customerid' =&gt; $customerid ]); } } // set new quota $upd_stmt = database::prepare(" update `" . table_mail_users . "` set `quota` = :quota "); database::pexecute($upd_stmt, [ 'quota' =&gt; settings::get('system.mail_quota') ]); // update customer, used quota bigger allowed quota database::query("update `" . table_panel_customers . "` set `email_quota` = `email_quota_used` `email_quota` &lt; `email_quota_used`"); $log-&gt;logaction(froxlorlogger::adm_action, log_warning, 'enforcing mailquota customers: ' . settings::get('system.mail_quota') . ' mb'); response::redirectto($filename); } else { html::askyesno('admin_quotas_reallyenforce', $filename, [ 'page' =&gt; $page ]); } } elseif ($page == 'integritycheck' &amp;&amp; $userinfo['change_serversettings'] == '1') { $integrity = new integritycheck(); (request::post('send') == 'send') { $integrity-&gt;fixall(); } elseif (request::get('action') == "fix") { html::askyesno('admin_integritycheck_reallyfix', $filename, [ 'page' =&gt; $page ]); } $integritycheck = []; foreach ($integrity-&gt;available $id =&gt; $check) { $integritycheck[] = [ 'displayid' =&gt; $id + 1, 'result' =&gt; $integrity-&gt;$check(), 'checkdesc' =&gt; lng('integrity_check.' . $check) ]; } $integrity_list_data = include_once dirname(__file__) . '/lib/tablelisting/admin/tablelisting.integrity.php'; $collection = [ 'data' =&gt; $integritycheck, 'pagination' =&gt; [] ]; ui::view('user/table.html.twig', [ 'listing' =&gt; listing::formatfromarray($collection, $integrity_list_data['integrity_list'], 'integrity_list'), 'actions_links' =&gt; [ [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'settings', 'page' =&gt; $page, 'action' =&gt; 'fix']), 'label' =&gt; lng('admin.integrityfix'), 'icon' =&gt; 'fa-solid fa-screwdriver-wrench', 'class' =&gt; 'btn-warning' ] ] ]); } elseif ($page == 'importexport' &amp;&amp; $userinfo['change_serversettings'] == '1') { // check json-stuff (!extension_loaded('json')) { response::standarderror('jsonextensionnotfound'); } (request::get('action') == "export") { // export try { $json_result = froxlor::getlocal($userinfo)-&gt;exportsettings(); $json_export = json_decode($json_result, true)['data']; } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } header('content-disposition: attachment; filename=froxlor_settings-' . \froxlor\froxlor::version . '-' . \froxlor\froxlor::dbversion . '_' . date('d.m.y') . '.json'); header('content-type: application/json'); echo $json_export; exit(); } elseif (request::get('action') == "import") { // import (request::post('send') == 'send') { // get uploaded file (isset($_files["import_file"]["tmp_name"])) { $imp_content = file_get_contents($_files["import_file"]["tmp_name"]); try { froxlor::getlocal($userinfo, [ 'json_str' =&gt; $imp_content ])-&gt;importsettings(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::standardsuccess('settingsimported', '', [ 'filename' =&gt; 'admin_settings.php' ]); } response::dynamicerror("upload failed"); } } else { $settings_data = include_once dirname(__file__) . '/lib/formfields/admin/settings/formfield.settings_import.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'settings', 'page' =&gt; $page, 'action' =&gt; 'import']), 'formdata' =&gt; $settings_data['settings_import'], 'actions_links' =&gt; [ [ 'class' =&gt; 'btn-outline-primary', 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'settings', 'page' =&gt; 'overview']), 'label' =&gt; lng('admin.configfiles.overview'), 'icon' =&gt; 'fa-solid fa-grip' ], [ 'class' =&gt; 'btn-outline-secondary', 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'settings', 'page' =&gt; $page, 'action' =&gt; 'export']), 'label' =&gt; 'download/export ' . lng('admin.serversettings'), 'icon' =&gt; 'fa-solid fa-file-import' ] ] ]); } } elseif ($page == 'testmail') { $note_type = 'info'; $note_msg = lng('admin.smtptestnote'); (request::post('send') == 'send') { $test_addr = request::post('test_addr'); // initialize mailingsystem $testmail = new phpmailer(true); $testmail-&gt;charset = "utf-8"; (settings::get('system.mail_use_smtp')) { $testmail-&gt;issmtp(); $testmail-&gt;host = settings::get('system.mail_smtp_host'); $testmail-&gt;smtpauth = settings::get('system.mail_smtp_auth') == '1'; $testmail-&gt;username = settings::get('system.mail_smtp_user'); $testmail-&gt;password = settings::get('system.mail_smtp_passwd'); (settings::get('system.mail_smtp_usetls')) { $testmail-&gt;smtpsecure = 'tls'; } else { $testmail-&gt;smtpautotls = false; } $testmail-&gt;port = settings::get('system.mail_smtp_port'); } $_mailerror = false; (phpmailer::validateaddress(settings::get('panel.adminmail')) !== false) { // set return-to address custom sender-name, see #76 $testmail-&gt;setfrom(settings::get('panel.adminmail'), settings::get('panel.adminmail_defname')); (settings::get('panel.adminmail_return') != '') { $testmail-&gt;addreplyto(settings::get('panel.adminmail_return'), settings::get('panel.adminmail_defname')); } try { $testmail-&gt;subject = "froxlor test-mail"; $mail_body = "yay, worked :)"; $testmail-&gt;altbody = $mail_body; $testmail-&gt;msghtml(str_replace("\n", "&lt;br /&gt;", $mail_body)); $testmail-&gt;addaddress($test_addr); $testmail-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $note_type = 'danger'; $note_msg = $e-&gt;getmessage(); $_mailerror = true; } catch (exception $e) { $note_type = 'danger'; $note_msg = $e-&gt;getmessage(); $_mailerror = true; } (!$_mailerror) { // success $mail-&gt;clearaddresses(); response::standardsuccess('testmailsent', '', [ 'filename' =&gt; 'admin_settings.php', 'page' =&gt; 'testmail' ]); } } else { // invalid sender e-mail $note_type = 'warning'; $note_msg = "invalid sender e-mail address: " . settings::get('panel.adminmail'); } } $mailtest_add_data = include_once dirname(__file__) . '/lib/formfields/admin/settings/formfield.settings_mailtest.php'; ui::view('user/form-note.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'settings']), 'formdata' =&gt; $mailtest_add_data['mailtest'], 'actions_links' =&gt; [ [ 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'settings', 'page' =&gt; 'overview', 'part' =&gt; 'system', 'em' =&gt; 'system_mail_use_smtp' ]), 'label' =&gt; lng('admin.smtpsettings'), 'icon' =&gt; 'fa-solid fa-gears', 'class' =&gt; 'btn-outline-secondary' ] ], // alert-box 'type' =&gt; $note_type, 'alert_msg' =&gt; $note_msg ]); } elseif ($page == 'togglesettingsmode') { ($userinfo['change_serversettings'] == '1') { $cmode = settings::get('panel.settings_mode'); settings::set('panel.settings_mode', (int)(!(bool)$cmode)); } response::redirectto($filename); }</file><file name="SECURITY.md"># froxlor's security policy welcome thanks taking interest [froxlor](https://www.froxlor.org)! mostly interested reports actual froxlor users high quality contributions welcome. please try best describe clear realistic impact report please open public issues github social media, we're best respond huntr quickly can. that, good luck hacking us ;) ## supported versions - **2.2.x** (`main` git-branch) - **2.1.x** (`v2.1` git-branch) - 2.0.x (`2.0.x`-tags) - 0.10.x (`0.10.x`-tags) - git-branches ## qualifying vulnerabilities ### vulnerabilities really care - sql injection bugs - server-side code execution bugs - cross-site scripting vulnerabilities - cross-site request forgery vulnerabilities - authentication authorization flaws - sensitive information disclosure ### vulnerabilities accept reproducible issues default/clean setup latest stable release supported version accepted. ## non-qualifying vulnerabilities - reports automated tools scanners - theoretical attacks without proof exploitability - attacks result third party library reported library maintainers - social engineering - attacks require disabling security features reducing security level environment - exploits admin user (privileged user implicitly trusted) - reflected file download - physical attacks - weak ssl/tls/ssh algorithms protocols - attacks involving physical access users device, involving device network thats already seriously compromised (eg man-in-the-middle). - user attacks - anything `/doc` - anything `/tests` ## reporting vulnerability think found vulnerability froxlor, please head [https://github.com/froxlor/froxlor/security/advisories](https://github.com/froxlor/froxlor/security/advisories/new) use reporting possibilities there. also, please give us appropriate time fix issue build update-packages publishing anything wild. alternatively email us [team@froxlor.org](team@froxlor.org).</file><file name="admin_phpsettings.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\fpmdaemons; use froxlor\api\commands\phpsettings; use froxlor\database\database; use froxlor\froxlor; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; $id = (int)request::any('id'); ($page == 'overview') { ($action == '') { try { $phpconf_list_data = include_once dirname(__file__) . '/lib/tablelisting/admin/tablelisting.phpconfigs.php'; $collection = (new collection(phpsettings::class, $userinfo, ['with_subdomains' =&gt; true])) -&gt;withpagination($phpconf_list_data['phpconf_list']['columns'], $phpconf_list_data['phpconf_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $phpconf_list_data, 'phpconf_list'), 'actions_links' =&gt; (bool)$userinfo['change_serversettings'] ? [ [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'phpsettings', 'page' =&gt; $page, 'action' =&gt; 'add']), 'label' =&gt; lng('admin.phpsettings.addnew') ] ] : [] ]); } ($action == 'add') { ((int)$userinfo['change_serversettings'] == 1) { (request::post('send') == 'send') { try { phpsettings::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { (file_exists(froxlor::getinstalldir() . '/templates/misc/php/default.ini.php')) { include froxlor::getinstalldir() . '/templates/misc/php/default.ini.php'; $result = [ 'phpsettings' =&gt; $phpini ]; } else { // use first php-config fallback $result_stmt = database::query("select * `" . table_panel_phpconfigs . "` `id` = 1"); $result = $result_stmt-&gt;fetch(pdo::fetch_assoc); } $fpmconfigs = []; $configs = database::query("select * `" . table_panel_fpmdaemons . "` order `description` asc"); ($row = $configs-&gt;fetch(pdo::fetch_assoc)) { $fpmconfigs[$row['id']] = $row['description']; } $phpconfig_add_data = include_once dirname(__file__) . '/lib/formfields/admin/phpconfig/formfield.phpconfig_add.php'; ui::view('user/form-replacers.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'phpsettings']), 'formdata' =&gt; $phpconfig_add_data['phpconfig_add'], 'replacers' =&gt; $phpconfig_add_data['phpconfig_replacers'] ]); } } else { response::standarderror('nopermissionsorinvalidid'); } } ($action == 'delete') { try { $json_result = phpsettings::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($result['id'] != 0 &amp;&amp; $result['id'] == $id &amp;&amp; (int)$userinfo['change_serversettings'] == 1 &amp;&amp; $id != 1) // cannot delete default php.config { (request::post('send') == 'send') { try { phpsettings::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesno('phpsetting_reallydelete', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $result['description']); } } else { response::standarderror('nopermissionsorinvalidid'); } } ($action == 'edit') { try { $json_result = phpsettings::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($result['id'] != 0 &amp;&amp; $result['id'] == $id &amp;&amp; (int)$userinfo['change_serversettings'] == 1) { (request::post('send') == 'send') { try { phpsettings::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $fpmconfigs = []; $configs = database::query("select * `" . table_panel_fpmdaemons . "` order `description` asc"); ($row = $configs-&gt;fetch(pdo::fetch_assoc)) { $fpmconfigs[$row['id']] = $row['description']; } $phpconfig_edit_data = include_once dirname(__file__) . '/lib/formfields/admin/phpconfig/formfield.phpconfig_edit.php'; ui::view('user/form-replacers.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'phpsettings', 'id' =&gt; $id]), 'formdata' =&gt; $phpconfig_edit_data['phpconfig_edit'], 'replacers' =&gt; $phpconfig_edit_data['phpconfig_replacers'], 'editid' =&gt; $id ]); } } else { response::standarderror('nopermissionsorinvalidid'); } } } elseif ($page == 'fpmdaemons') { ($action == '') { try { $fpmconf_list_data = include_once dirname(__file__) . '/lib/tablelisting/admin/tablelisting.fpmconfigs.php'; $collection = (new collection(fpmdaemons::class, $userinfo)) -&gt;withpagination($fpmconf_list_data['fpmconf_list']['columns'], $fpmconf_list_data['fpmconf_list']['default_sorting']); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $fpmconf_list_data, 'fpmconf_list'), 'actions_links' =&gt; (bool)$userinfo['change_serversettings'] ? [ [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'phpsettings', 'page' =&gt; $page, 'action' =&gt; 'add']), 'label' =&gt; lng('admin.fpmsettings.addnew') ] ] : [] ]); } ($action == 'add') { ((int)$userinfo['change_serversettings'] == 1) { (request::post('send') == 'send') { try { fpmdaemons::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $fpmconfig_add_data = include_once dirname(__file__) . '/lib/formfields/admin/phpconfig/formfield.fpmconfig_add.php'; ui::view('user/form-replacers.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'phpsettings', 'page' =&gt; 'fpmdaemons']), 'formdata' =&gt; $fpmconfig_add_data['fpmconfig_add'], 'replacers' =&gt; $fpmconfig_add_data['fpmconfig_replacers'] ]); } } else { response::standarderror('nopermissionsorinvalidid'); } } ($action == 'delete') { try { $json_result = fpmdaemons::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($id == 1) { response::standarderror('cannotdeletedefaultphpconfig'); } ($result['id'] != 0 &amp;&amp; $result['id'] == $id &amp;&amp; (int)$userinfo['change_serversettings'] == 1 &amp;&amp; $id != 1) // cannot delete default php.config { (request::post('send') == 'send') { try { fpmdaemons::getlocal($userinfo, request::postall())-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesno('fpmsetting_reallydelete', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $result['description']); } } else { response::standarderror('nopermissionsorinvalidid'); } } ($action == 'edit') { try { $json_result = fpmdaemons::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($result['id'] != 0 &amp;&amp; $result['id'] == $id &amp;&amp; (int)$userinfo['change_serversettings'] == 1) { (request::post('send') == 'send') { try { fpmdaemons::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $fpmconfig_edit_data = include_once dirname(__file__) . '/lib/formfields/admin/phpconfig/formfield.fpmconfig_edit.php'; ui::view('user/form-replacers.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'phpsettings', 'page' =&gt; 'fpmdaemons', 'id' =&gt; $id]), 'formdata' =&gt; $fpmconfig_edit_data['fpmconfig_edit'], 'replacers' =&gt; $fpmconfig_edit_data['fpmconfig_replacers'], 'editid' =&gt; $id ]); } } else { response::standarderror('nopermissionsorinvalidid'); } } }</file><file name="vite.config.js">import { defineconfig } 'vite'; import laravel 'laravel-vite-plugin'; import vue '@vitejs/plugin-vue'; export default defineconfig({ build: { chunksizewarninglimit: 1000, }, base: "./", plugins: [ laravel({ input: [ 'templates/froxlor/assets/scss/app.scss', 'templates/froxlor/assets/js/app.js', ], hotfile: 'templates/froxlor/hot', builddirectory: '../templates/froxlor/build', refresh: true, }), vue({ template: { transformasseturls: { base: null, includeabsolute: false, }, }, }), ], resolve: { alias: { vue: 'vue/dist/vue.esm-bundler.js', }, }, });</file><file name="admin_customers.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const area = 'admin'; require __dir__ . '/lib/init.php'; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\mysqlserver; use froxlor\currentuser; use froxlor\database\database; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\settings; use froxlor\ui\collection; use froxlor\ui\html; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; $id = (int)request::any('id'); (($page == 'customers' || $page == 'overview') &amp;&amp; $userinfo['customers'] != '0') { ($action == '') { $log-&gt;logaction(froxlorlogger::adm_action, log_notice, "viewed admin_customers"); try { $customer_list_data = include_once dirname(__file__) . '/lib/tablelisting/admin/tablelisting.customers.php'; $collection = (new collection(customers::class, $userinfo, ['show_usages' =&gt; true])) -&gt;withpagination($customer_list_data['customer_list']['columns'], $customer_list_data['customer_list']['default_sorting']); ($userinfo['change_serversettings']) { $collection-&gt;has('admin', admins::class, 'adminid', 'adminid'); } } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $actions_links = false; (currentuser::canaddresource('customers')) { $actions_links = [ [ 'href' =&gt; $linker-&gt;getlink(['section' =&gt; 'customers', 'page' =&gt; $page, 'action' =&gt; 'add']), 'label' =&gt; lng('admin.customer_add') ] ]; } ui::view('user/table.html.twig', [ 'listing' =&gt; listing::format($collection, $customer_list_data, 'customer_list'), 'actions_links' =&gt; $actions_links ]); } elseif ($action == 'su' &amp;&amp; $id != 0) { try { $json_result = customers::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; $destination_user = $result['loginname']; ($destination_user != '') { ($result['deactivated'] == '1') { response::standarderror("usercurrentlydeactivated", $destination_user); } $result['switched_user'] = currentuser::getdata(); $result['adminsession'] = 0; $result['userid'] = $result['customerid']; session_regenerate_id(true); currentuser::setdata($result); $log-&gt;logaction(froxlorlogger::adm_action, log_info, "switched user '" . $destination_user . "'"); $target = request::get('target', 'index'); $redirect = "customer_" . $target . ".php"; (!file_exists(froxlor::getinstalldir() . "/" . $redirect)) { $redirect = "customer_index.php"; } response::redirectto($redirect, null, true); } else { response::redirectto('index.php', [ 'action' =&gt; 'login' ]); } } elseif ($action == 'unlock' &amp;&amp; $id != 0) { try { $json_result = customers::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (request::post('send') == 'send') { try { $json_result = customers::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;unlock(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesno('customer_reallyunlock', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $result['loginname']); } } elseif ($action == 'delete' &amp;&amp; $id != 0) { try { $json_result = customers::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; (request::post('send') == 'send') { try { $json_result = customers::getlocal($userinfo, [ 'id' =&gt; $id, 'delete_userfiles' =&gt; request::post('delete_userfiles', 0) ])-&gt;delete(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { html::askyesnowithcheckbox('admin_customer_reallydelete', 'admin_customer_alsoremovefiles', $filename, [ 'id' =&gt; $id, 'page' =&gt; $page, 'action' =&gt; $action ], $result['loginname']); } } elseif ($action == 'add') { (request::post('send') == 'send') { try { customers::getlocal($userinfo, request::postall())-&gt;add(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $mysql_servers = []; try { $result_json = mysqlserver::getlocal($userinfo)-&gt;listing(); $result_decoded = json_decode($result_json, true)['data']['list']; foreach ($result_decoded $dbserver =&gt; $dbdata) { $mysql_servers[] = [ 'label' =&gt; $dbdata['caption'], 'value' =&gt; $dbserver ]; } } catch (exception $e) { /* none */ } $phpconfigs = []; $configs = database::query(" select c.*, fc.description interpreter `" . table_panel_phpconfigs . "` c left join `" . table_panel_fpmdaemons . "` fc fc.id = c.fpmsettingid "); ($row = $configs-&gt;fetch(pdo::fetch_assoc)) { ((int)settings::get('phpfpm.enabled') == 1) { $phpconfigs[] = [ 'label' =&gt; $row['description'] . " [" . $row['interpreter'] . "]", 'value' =&gt; $row['id'] ]; } else { $phpconfigs[] = [ 'label' =&gt; $row['description'], 'value' =&gt; $row['id'] ]; } } // hosting plans $hosting_plans = []; $plans = database::query(" select * `" . table_panel_plans . "` order name asc "); $hosting_plans = [ 0 =&gt; "---" ]; ($row = $plans-&gt;fetch(pdo::fetch_assoc)) { $hosting_plans[$row['id']] = $row['name']; } $customer_add_data = include_once dirname(__file__) . '/lib/formfields/admin/customer/formfield.customer_add.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'customers']), 'formdata' =&gt; $customer_add_data['customer_add'] ]); } } elseif ($action == 'edit' &amp;&amp; $id != 0) { try { $json_result = customers::getlocal($userinfo, [ 'id' =&gt; $id ])-&gt;get(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } $result = json_decode($json_result, true)['data']; ($result['loginname'] != '') { (request::post('send') == 'send') { try { customers::getlocal($userinfo, request::postall())-&gt;update(); } catch (exception $e) { response::dynamicerror($e-&gt;getmessage()); } response::redirectto($filename, [ 'page' =&gt; $page ]); } else { $dec_places = settings::get('panel.decimal_places'); $result['traffic'] = round($result['traffic'] / (1024 * 1024), $dec_places); $result['diskspace'] = round($result['diskspace'] / 1024, $dec_places); $result['email'] = $idna_convert-&gt;decode($result['email']); $result = phphelper::htmlentitiesarray($result); $mysql_servers = []; try { $result_json = mysqlserver::getlocal($userinfo)-&gt;listing(); $result_decoded = json_decode($result_json, true)['data']['list']; foreach ($result_decoded $dbserver =&gt; $dbdata) { $mysql_servers[] = [ 'label' =&gt; $dbdata['caption'], 'value' =&gt; $dbserver ]; } } catch (exception $e) { /* none */ } $phpconfigs = []; $configs = database::query(" select c.*, fc.description interpreter `" . table_panel_phpconfigs . "` c left join `" . table_panel_fpmdaemons . "` fc fc.id = c.fpmsettingid "); ($row = $configs-&gt;fetch(pdo::fetch_assoc)) { ((int)settings::get('phpfpm.enabled') == 1) { $phpconfigs[] = [ 'label' =&gt; $row['description'] . " [" . $row['interpreter'] . "]", 'value' =&gt; $row['id'] ]; } else { $phpconfigs[] = [ 'label' =&gt; $row['description'], 'value' =&gt; $row['id'] ]; } } // hosting plans $plans = database::query(" select * `" . table_panel_plans . "` order name asc "); $hosting_plans = [ 0 =&gt; "---" ]; ($row = $plans-&gt;fetch(pdo::fetch_assoc)) { $hosting_plans[$row['id']] = $row['name']; } $available_admins_stmt = database::prepare(" select * `" . table_panel_admins . "` (`customers` = '-1' `customers` &gt; `customers_used`) adminid &lt;&gt; :currentadmin "); database::pexecute($available_admins_stmt, ['currentadmin' =&gt; $result['adminid']]); $admin_select = [ 0 =&gt; "---" ]; ($available_admin = $available_admins_stmt-&gt;fetch()) { $admin_select[$available_admin['adminid']] = $available_admin['name'] . " (" . $available_admin['loginname'] . ")"; } $customer_edit_data = include_once dirname(__file__) . '/lib/formfields/admin/customer/formfield.customer_edit.php'; ui::view('user/form.html.twig', [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'customers', 'id' =&gt; $id]), 'formdata' =&gt; $customer_edit_data['customer_edit'], 'editid' =&gt; $id ]); } } } }</file><file name="actions/index.html" /><file name="actions/admin/index.html" /><file name="actions/admin/settings/100.panel.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'groups' =&gt; [ 'panel' =&gt; [ 'title' =&gt; lng('admin.panelsettings'), 'icon' =&gt; 'fa-solid fa-chalkboard-user', 'fields' =&gt; [ 'panel_standardlanguage' =&gt; [ 'label' =&gt; [ 'title' =&gt; lng('login.language'), 'description' =&gt; lng('serversettings.language.description') ], 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'standardlanguage', 'type' =&gt; 'select', 'default' =&gt; 'en', 'option_options_method' =&gt; [ '\\froxlor\\language', 'getlanguages' ], 'save_method' =&gt; 'storesettingfield' ], 'panel_default_theme' =&gt; [ 'label' =&gt; [ 'title' =&gt; lng('panel.theme'), 'description' =&gt; lng('serversettings.default_theme') ], 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'default_theme', 'type' =&gt; 'select', 'default' =&gt; 'froxlor', 'option_options_method' =&gt; [ '\\froxlor\\ui\\panel\\ui', 'getthemes' ], 'save_method' =&gt; 'storesettingdefaulttheme' ], 'panel_allow_theme_change_customer' =&gt; [ 'label' =&gt; lng('serversettings.panel_allow_theme_change_customer'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'allow_theme_change_customer', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield' ], 'panel_allow_theme_change_admin' =&gt; [ 'label' =&gt; lng('serversettings.panel_allow_theme_change_admin'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'allow_theme_change_admin', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield' ], 'panel_natsorting' =&gt; [ 'label' =&gt; lng('serversettings.natsorting'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'natsorting', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'panel_paging' =&gt; [ 'label' =&gt; lng('serversettings.paging'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'paging', 'type' =&gt; 'number', 'min' =&gt; 0, 'default' =&gt; 0, 'save_method' =&gt; 'storesettingfield' ], 'panel_pathedit' =&gt; [ 'label' =&gt; lng('serversettings.pathedit'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'pathedit', 'type' =&gt; 'select', 'default' =&gt; 'manual', 'select_var' =&gt; [ 'manual' =&gt; lng('serversettings.manual'), 'dropdown' =&gt; lng('serversettings.dropdown') ], 'save_method' =&gt; 'storesettingfield' ], 'panel_adminmail' =&gt; [ 'label' =&gt; lng('serversettings.adminmail'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'adminmail', 'type' =&gt; 'email', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'panel_adminmail_defname' =&gt; [ 'label' =&gt; lng('serversettings.adminmail_defname'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'adminmail_defname', 'type' =&gt; 'text', 'default' =&gt; 'froxlor administrator', 'save_method' =&gt; 'storesettingfield' ], 'panel_adminmail_return' =&gt; [ 'label' =&gt; lng('serversettings.adminmail_return'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'adminmail_return', 'type' =&gt; 'email', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'panel_decimal_places' =&gt; [ 'label' =&gt; lng('serversettings.decimal_places'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'decimal_places', 'type' =&gt; 'number', 'min' =&gt; 0, 'max' =&gt; 15, 'default' =&gt; 4, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'panel_phpmyadmin_url' =&gt; [ 'label' =&gt; lng('serversettings.phpmyadmin_url'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'phpmyadmin_url', 'type' =&gt; 'url', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'panel_webmail_url' =&gt; [ 'label' =&gt; lng('serversettings.webmail_url'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'webmail_url', 'type' =&gt; 'url', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'panel_webftp_url' =&gt; [ 'label' =&gt; lng('serversettings.webftp_url'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'webftp_url', 'type' =&gt; 'url', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'admin_show_version_login' =&gt; [ 'label' =&gt; lng('admin.show_version_login'), 'settinggroup' =&gt; 'admin', 'varname' =&gt; 'show_version_login', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'admin_show_version_footer' =&gt; [ 'label' =&gt; lng('admin.show_version_footer'), 'settinggroup' =&gt; 'admin', 'varname' =&gt; 'show_version_footer', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'admin_show_news_feed' =&gt; [ 'label' =&gt; lng('admin.show_news_feed'), 'settinggroup' =&gt; 'admin', 'varname' =&gt; 'show_news_feed', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'customer_show_news_feed' =&gt; [ 'label' =&gt; lng('admin.customer_show_news_feed'), 'settinggroup' =&gt; 'customer', 'varname' =&gt; 'show_news_feed', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'customer_news_feed_url' =&gt; [ 'label' =&gt; lng('admin.customer_news_feed_url'), 'settinggroup' =&gt; 'customer', 'varname' =&gt; 'news_feed_url', 'type' =&gt; 'url', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'panel_allow_domain_change_admin' =&gt; [ 'label' =&gt; lng('serversettings.panel_allow_domain_change_admin'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'allow_domain_change_admin', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'panel_allow_domain_change_customer' =&gt; [ 'label' =&gt; lng('serversettings.panel_allow_domain_change_customer'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'allow_domain_change_customer', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'panel_phpconfigs_hidesubdomains' =&gt; [ 'label' =&gt; lng('serversettings.panel_phpconfigs_hidesubdomains'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'phpconfigs_hidesubdomains', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'panel_phpconfigs_hidestdsubdomain' =&gt; [ 'label' =&gt; lng('serversettings.panel_phpconfigs_hidestdsubdomain'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'phpconfigs_hidestdsubdomain', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'panel_customer_hide_options' =&gt; [ 'label' =&gt; lng('serversettings.panel_customer_hide_options'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'customer_hide_options', 'type' =&gt; 'select', 'default' =&gt; '', 'select_mode' =&gt; 'multiple', 'option_emptyallowed' =&gt; true, 'select_var' =&gt; [ 'email' =&gt; lng('menue.email.email'), 'mysql' =&gt; lng('menue.mysql.mysql'), 'domains' =&gt; lng('menue.domains.domains'), 'ftp' =&gt; lng('menue.ftp.ftp'), 'extras' =&gt; lng('menue.extras.extras'), 'extras.directoryprotection' =&gt; lng('menue.extras.extras') . " / " . lng('menue.extras.directoryprotection'), 'extras.pathoptions' =&gt; lng('menue.extras.extras') . " / " . lng('menue.extras.pathoptions'), 'extras.logger' =&gt; lng('menue.extras.extras') . " / " . lng('menue.logger.logger'), 'extras.export' =&gt; lng('menue.extras.extras') . " / " . lng('menue.extras.export'), 'traffic' =&gt; lng('menue.traffic.traffic'), 'traffic.http' =&gt; lng('menue.traffic.traffic') . " / http", 'traffic.ftp' =&gt; lng('menue.traffic.traffic') . " / ftp", 'traffic.mail' =&gt; lng('menue.traffic.traffic') . " / mail", 'misc.documentation' =&gt; lng('admin.documentation'), ], 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'panel_imprint_url' =&gt; [ 'label' =&gt; lng('serversettings.imprint_url'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'imprint_url', 'type' =&gt; 'url', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'panel_terms_url' =&gt; [ 'label' =&gt; lng('serversettings.terms_url'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'terms_url', 'type' =&gt; 'url', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'panel_privacy_url' =&gt; [ 'label' =&gt; lng('serversettings.privacy_url'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'privacy_url', 'type' =&gt; 'url', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'panel_logo_overridetheme' =&gt; [ 'label' =&gt; lng('serversettings.logo_overridetheme'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'logo_overridetheme', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'panel_logo_overridecustom' =&gt; [ 'label' =&gt; lng('serversettings.logo_overridecustom'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'logo_overridecustom', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'panel_logo_image_header' =&gt; [ 'label' =&gt; lng('serversettings.logo_image_header'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'logo_image_header', 'type' =&gt; 'image', 'accept' =&gt; 'image/jpeg, image/jpg, image/png, image/gif', 'image_name' =&gt; 'logo_header', 'default' =&gt; '', 'save_method' =&gt; 'storesettingimage' ], 'panel_logo_image_login' =&gt; [ 'label' =&gt; lng('serversettings.logo_image_login'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'logo_image_login', 'type' =&gt; 'image', 'accept' =&gt; 'image/jpeg, image/jpg, image/png, image/gif', 'image_name' =&gt; 'logo_login', 'default' =&gt; '', 'save_method' =&gt; 'storesettingimage' ], 'panel_menu_collapsed' =&gt; [ 'label' =&gt; lng('serversettings.panel_menu_collapsed'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'menu_collapsed', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', ], ] ] ] ];</file><file name="actions/admin/settings/135.fcgid.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'groups' =&gt; [ 'fcgid' =&gt; [ 'title' =&gt; lng('admin.fcgid_settings'), 'icon' =&gt; 'fa-brands fa-php', 'websrv_avail' =&gt; [ 'apache2', 'lighttpd' ], 'fields' =&gt; [ 'system_mod_fcgid' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mod_fcgid', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'plausibility_check_method' =&gt; [ '\\froxlor\\validate\\check', 'checkfcgidphpfpm' ], 'overview_option' =&gt; true, 'requires_reconf' =&gt; ['http', 'system:fcgid'] ], 'system_mod_fcgid_configdir' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid.configdir'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mod_fcgid_configdir', 'type' =&gt; 'text', 'string_type' =&gt; 'confdir', 'default' =&gt; '/var/www/php-fcgi-scripts/', 'plausibility_check_method' =&gt; [ '\\froxlor\\validate\\check', 'checkpathconflicts' ], 'save_method' =&gt; 'storesettingfield', 'requires_reconf' =&gt; ['system:fcgid'] ], 'system_mod_fcgid_tmpdir' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid.tmpdir'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mod_fcgid_tmpdir', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'default' =&gt; '/var/customers/tmp/', 'save_method' =&gt; 'storesettingfield', 'requires_reconf' =&gt; ['http'] ], 'system_mod_fcgid_peardir' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid.peardir'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mod_fcgid_peardir', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'string_delimiter' =&gt; ':', 'string_emptyallowed' =&gt; true, 'default' =&gt; '/usr/share/php/:/usr/share/php5/', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_mod_fcgid_wrapper' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid.wrapper'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mod_fcgid_wrapper', 'type' =&gt; 'select', 'select_var' =&gt; [ 0 =&gt; 'scriptalias', 1 =&gt; 'fcgidwrapper' ], 'default' =&gt; 1, 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2' ], 'advanced_mode' =&gt; true ], 'system_mod_fcgid_starter' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid.starter'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mod_fcgid_starter', 'type' =&gt; 'number', 'min' =&gt; 0, 'default' =&gt; 0, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_mod_fcgid_maxrequests' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid.maxrequests'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mod_fcgid_maxrequests', 'type' =&gt; 'number', 'default' =&gt; 250, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_mod_fcgid_defaultini' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid.defaultini'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mod_fcgid_defaultini', 'type' =&gt; 'select', 'default' =&gt; '1', 'option_options_method' =&gt; [ '\\froxlor\\http\\phpconfig', 'getphpconfigs' ], 'save_method' =&gt; 'storesettingfield' ], 'system_mod_fcgid_idle_timeout' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid.idle_timeout'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mod_fcgid_idle_timeout', 'type' =&gt; 'number', 'default' =&gt; 30, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ] ] ] ] ];</file><file name="actions/admin/settings/220.quota.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'groups' =&gt; [ 'diskquota' =&gt; [ 'title' =&gt; lng('diskquota'), 'icon' =&gt; 'fa-solid fa-sliders', 'advanced_mode' =&gt; true, 'fields' =&gt; [ 'system_diskquota_enabled' =&gt; [ 'label' =&gt; lng('serversettings.diskquota_enabled'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'diskquota_enabled', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'overview_option' =&gt; true ], 'system_diskquota_repquota_path' =&gt; [ 'label' =&gt; lng('serversettings.diskquota_repquota_path.description'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'diskquota_repquota_path', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'default' =&gt; '/usr/sbin/repquota', 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ], 'system_diskquota_quotatool_path' =&gt; [ 'label' =&gt; lng('serversettings.diskquota_quotatool_path.description'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'diskquota_quotatool_path', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'default' =&gt; '/usr/bin/quotatool', 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ], 'system_diskquota_customer_partition' =&gt; [ 'label' =&gt; lng('serversettings.diskquota_customer_partition.description'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'diskquota_customer_partition', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'default' =&gt; '/dev/root', 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ] ] ] ] ];</file><file name="actions/admin/settings/150.mail.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'groups' =&gt; [ 'mail' =&gt; [ 'title' =&gt; lng('admin.mailserversettings'), 'icon' =&gt; 'fa-solid fa-envelope', 'fields' =&gt; [ 'system_vmail_uid' =&gt; [ 'label' =&gt; lng('serversettings.vmail_uid'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'vmail_uid', 'type' =&gt; 'number', 'default' =&gt; 2000, 'min' =&gt; 2, 'max' =&gt; 65535, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true, 'requires_reconf' =&gt; ['smtp'] ], 'system_vmail_gid' =&gt; [ 'label' =&gt; lng('serversettings.vmail_gid'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'vmail_gid', 'type' =&gt; 'number', 'default' =&gt; 2000, 'min' =&gt; 2, 'max' =&gt; 65535, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true, 'requires_reconf' =&gt; ['smtp'] ], 'system_vmail_homedir' =&gt; [ 'label' =&gt; lng('serversettings.vmail_homedir'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'vmail_homedir', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'default' =&gt; '/var/customers/mail/', 'save_method' =&gt; 'storesettingfield', 'requires_reconf' =&gt; ['smtp'] ], 'system_vmail_maildirname' =&gt; [ 'label' =&gt; lng('serversettings.vmail_maildirname'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'vmail_maildirname', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'default' =&gt; 'maildir', 'string_emptyallowed' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'panel_sendalternativemail' =&gt; [ 'label' =&gt; lng('serversettings.sendalternativemail'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'sendalternativemail', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'system_mail_quota_enabled' =&gt; [ 'label' =&gt; lng('serversettings.mail_quota_enabled'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mail_quota_enabled', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'system_mail_quota' =&gt; [ 'label' =&gt; lng('serversettings.mail_quota'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mail_quota', 'type' =&gt; 'number', 'default' =&gt; 100, 'save_method' =&gt; 'storesettingfield' ], 'catchall_catchall_enabled' =&gt; [ 'label' =&gt; lng('serversettings.catchall_enabled'), 'settinggroup' =&gt; 'catchall', 'varname' =&gt; 'catchall_enabled', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingresetcatchall' ], 'system_mailtraffic_enabled' =&gt; [ 'label' =&gt; lng('serversettings.mailtraffic_enabled'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mailtraffic_enabled', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_mdaserver' =&gt; [ 'label' =&gt; lng('serversettings.mdaserver'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mdaserver', 'type' =&gt; 'select', 'default' =&gt; 'dovecot', 'select_var' =&gt; [ 'courier' =&gt; 'courier', 'dovecot' =&gt; 'dovecot' ], 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_mdalog' =&gt; [ 'label' =&gt; lng('serversettings.mdalog'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mdalog', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'default' =&gt; '/var/log/mail.log', 'string_emptyallowed' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_mtaserver' =&gt; [ 'label' =&gt; lng('serversettings.mtaserver'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mtaserver', 'type' =&gt; 'select', 'default' =&gt; 'postfix', 'select_var' =&gt; [ 'exim4' =&gt; 'exim4', 'postfix' =&gt; 'postfix' ], 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_mtalog' =&gt; [ 'label' =&gt; lng('serversettings.mtalog'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mtalog', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'default' =&gt; '/var/log/mail.log', 'string_emptyallowed' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ] ] ] ] ];</file><file name="actions/admin/settings/131.ssl.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\froxlor; use froxlor\settings; return [ 'groups' =&gt; [ 'ssl' =&gt; [ 'title' =&gt; lng('admin.sslsettings'), 'icon' =&gt; 'fa-solid fa-shield', 'fields' =&gt; [ 'system_use_ssl' =&gt; [ 'label' =&gt; lng('serversettings.ssl.use_ssl'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'use_ssl', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'overview_option' =&gt; true, 'requires_reconf' =&gt; ['http'] ], 'system_ssl_protocols' =&gt; [ 'label' =&gt; lng('serversettings.ssl.ssl_protocols'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'ssl_protocols', 'type' =&gt; 'select', 'default' =&gt; 'tlsv1.2', 'select_mode' =&gt; 'multiple', 'select_var' =&gt; [ 'tlsv1' =&gt; 'tlsv1', 'tlsv1.1' =&gt; 'tlsv1.1', 'tlsv1.2' =&gt; 'tlsv1.2', 'tlsv1.3' =&gt; 'tlsv1.3' ], 'save_method' =&gt; 'storesettingfield' ], 'system_ssl_cipher_list' =&gt; [ 'label' =&gt; lng('serversettings.ssl.ssl_cipher_list'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'ssl_cipher_list', 'type' =&gt; 'text', 'string_emptyallowed' =&gt; false, 'default' =&gt; 'ecdh+aesgcm:ecdh+aes256:!anull:!md5:!dss:!dh:!aes128', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_tlsv13_cipher_list' =&gt; [ 'label' =&gt; lng('serversettings.ssl.tlsv13_cipher_list'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'tlsv13_cipher_list', 'type' =&gt; 'text', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'visible' =&gt; settings::get('system.webserver') == "apache2" &amp;&amp; settings::get('system.apache24') == 1, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_ssl_cert_file' =&gt; [ 'label' =&gt; lng('serversettings.ssl.ssl_cert_file'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'ssl_cert_file', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'string_emptyallowed' =&gt; true, 'default' =&gt; '/etc/ssl/froxlor_selfsigned.pem', 'save_method' =&gt; 'storesettingfield' ], 'system_ssl_key_file' =&gt; [ 'label' =&gt; lng('serversettings.ssl.ssl_key_file'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'ssl_key_file', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'string_emptyallowed' =&gt; true, 'default' =&gt; '/etc/ssl/froxlor_selfsigned.key', 'save_method' =&gt; 'storesettingfield' ], 'system_ssl_cert_chainfile' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_cert_chainfile'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'ssl_cert_chainfile', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'system_ssl_ca_file' =&gt; [ 'label' =&gt; lng('serversettings.ssl.ssl_ca_file'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'ssl_ca_file', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'system_apache24_ocsp_cache_path' =&gt; [ 'label' =&gt; lng('serversettings.ssl.apache24_ocsp_cache_path'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'apache24_ocsp_cache_path', 'type' =&gt; 'text', 'string_emptyallowed' =&gt; false, 'default' =&gt; 'shmcb:/var/run/apache2/ocsp-stapling.cache(131072)', 'visible' =&gt; settings::get('system.webserver') == "apache2" &amp;&amp; settings::get('system.apache24') == 1, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_sessionticketsenabled' =&gt; [ 'label' =&gt; lng('admin.domain_sessionticketsenabled'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'sessionticketsenabled', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.use_ssl') &amp;&amp; (settings::get('system.webserver') == "nginx" || (settings::get('system.webserver') == "apache2" &amp;&amp; settings::get('system.apache24') == 1)), 'advanced_mode' =&gt; true ], 'system_leenabled' =&gt; [ 'label' =&gt; lng('serversettings.leenabled'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'leenabled', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'cronmodule' =&gt; 'froxlor/letsencrypt', 'save_method' =&gt; 'storesettingfield', 'requires_reconf' =&gt; ['http'] ], 'system_acmeshpath' =&gt; [ 'label' =&gt; lng('serversettings.acmeshpath'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'acmeshpath', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'default' =&gt; '/root/.acme.sh/acme.sh', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true, 'required_otp' =&gt; true ], 'system_letsencryptacmeconf' =&gt; [ 'label' =&gt; lng('serversettings.letsencryptacmeconf'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'letsencryptacmeconf', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'default' =&gt; '/etc/apache2/conf-enabled/acme.conf', 'save_method' =&gt; 'storesettingfield', 'requires_reconf' =&gt; ['http'] ], 'system_letsencryptca' =&gt; [ 'label' =&gt; lng('serversettings.letsencryptca'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'letsencryptca', 'type' =&gt; 'select', 'default' =&gt; 'letsencrypt', 'select_var' =&gt; [ 'letsencrypt_test' =&gt; 'let\'s encrypt (test / staging)', 'letsencrypt' =&gt; 'let\'s encrypt (live)', 'buypass_test' =&gt; 'buypass (test / staging)', 'buypass' =&gt; 'buypass (live)', 'zerossl' =&gt; 'zerossl (live)', 'google' =&gt; 'google (live)', 'google_test' =&gt; 'google (test / staging)', ], 'save_method' =&gt; 'storesettingfield' ], 'system_letsencryptchallengepath' =&gt; [ 'label' =&gt; lng('serversettings.letsencryptchallengepath'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'letsencryptchallengepath', 'type' =&gt; 'text', 'string_emptyallowed' =&gt; false, 'default' =&gt; froxlor::getinstalldir(), 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true, 'requires_reconf' =&gt; ['http'] ], 'system_letsencryptkeysize' =&gt; [ 'label' =&gt; lng('serversettings.letsencryptkeysize'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'letsencryptkeysize', 'type' =&gt; 'select', 'default' =&gt; '2048', 'select_var' =&gt; [ '2048' =&gt; '2048', '3072' =&gt; '3072', '4096' =&gt; '4096', '8192' =&gt; '8192' ], 'save_method' =&gt; 'storesettingfield' ], 'system_leecc' =&gt; [ 'label' =&gt; lng('serversettings.letsencryptecc'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'leecc', 'type' =&gt; 'select', 'default' =&gt; '0', 'select_var' =&gt; [ '0' =&gt; '-', '256' =&gt; 'ec-256', '384' =&gt; 'ec-384' ], 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_letsencryptreuseold' =&gt; [ 'label' =&gt; lng('serversettings.letsencryptreuseold'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'letsencryptreuseold', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_le_domain_dnscheck' =&gt; [ 'label' =&gt; lng('serversettings.le_domain_dnscheck'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'le_domain_dnscheck', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield' ], 'system_le_domain_dnscheck_resolver' =&gt; [ 'label' =&gt; lng('serversettings.le_domain_dnscheck_resolver'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'le_domain_dnscheck_resolver', 'type' =&gt; 'text', 'string_type' =&gt; 'validate_ip', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_le_renew_services' =&gt; [ 'label' =&gt; lng('serversettings.le_renew_services'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'le_renew_services', 'type' =&gt; 'select', 'default' =&gt; '', 'select_mode' =&gt; 'multiple', 'option_emptyallowed' =&gt; true, 'select_var' =&gt; [ '' =&gt; lng('panel.none_value'), 'postfix' =&gt; 'postfix (smtp)', 'dovecot' =&gt; 'dovecot (imap/pop3)', 'proftpd' =&gt; 'proftpd (ftp)', ], 'save_method' =&gt; 'storesettingfieldinsertupdateservicestask', 'advanced_mode' =&gt; true ], 'system_le_renew_hook' =&gt; [ 'label' =&gt; lng('serversettings.le_renew_hook'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'le_renew_hook', 'type' =&gt; 'text', 'string_regexp' =&gt; '/^[a-z0-9\/\._\- ]+$/i', 'default' =&gt; 'systemctl restart postfix dovecot proftpd', 'save_method' =&gt; 'storesettingfieldinsertupdateservicestask', 'advanced_mode' =&gt; true, 'required_otp' =&gt; true ], ] ] ] ];</file><file name="actions/admin/settings/155.ftpserver.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'groups' =&gt; [ 'ftpserver' =&gt; [ 'title' =&gt; lng('admin.ftpserversettings'), 'icon' =&gt; 'fa-solid fa-arrow-right-arrow-left', 'fields' =&gt; [ 'system_ftpserver' =&gt; [ 'label' =&gt; lng('admin.ftpserver'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'ftpserver', 'type' =&gt; 'select', 'default' =&gt; 'proftpd', 'select_var' =&gt; [ 'proftpd' =&gt; 'proftpd', 'pureftpd' =&gt; 'pureftpd' ], 'save_method' =&gt; 'storesettingfield' ] ] ] ] ];</file><file name="actions/admin/settings/136.phpfpm.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'groups' =&gt; [ 'phpfpm' =&gt; [ 'title' =&gt; lng('admin.phpfpm_settings'), 'icon' =&gt; 'fa-brands fa-php', 'fields' =&gt; [ 'phpfpm_enabled' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'enabled', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'plausibility_check_method' =&gt; [ '\\froxlor\\validate\\check', 'checkfcgidphpfpm' ], 'overview_option' =&gt; true, 'requires_reconf' =&gt; ['http', 'system:php-fpm'] ], 'phpfpm_defaultini' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid.defaultini'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'defaultini', 'type' =&gt; 'select', 'default' =&gt; '1', 'option_options_method' =&gt; [ '\\froxlor\\http\\phpconfig', 'getphpconfigs' ], 'save_method' =&gt; 'storesettingfield' ], 'phpfpm_aliasconfigdir' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.aliasconfigdir'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'aliasconfigdir', 'type' =&gt; 'text', 'string_type' =&gt; 'confdir', 'default' =&gt; '/var/www/php-fpm/', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'phpfpm_tmpdir' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid.tmpdir'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'tmpdir', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'default' =&gt; '/var/customers/tmp/', 'save_method' =&gt; 'storesettingfield' ], 'phpfpm_peardir' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid.peardir'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'peardir', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'string_delimiter' =&gt; ':', 'string_emptyallowed' =&gt; true, 'default' =&gt; '/usr/share/php/:/usr/share/php5/', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'phpfpm_envpath' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.envpath'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'envpath', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'string_delimiter' =&gt; ':', 'string_emptyallowed' =&gt; true, 'default' =&gt; '/usr/local/bin:/usr/bin:/bin', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'phpfpm_fastcgi_ipcdir' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.ipcdir'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'fastcgi_ipcdir', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'default' =&gt; '/var/lib/apache2/fastcgi/', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'phpfpm_use_mod_proxy' =&gt; [ 'label' =&gt; lng('phpfpm.use_mod_proxy'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'use_mod_proxy', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'visible' =&gt; settings::get('system.apache24'), 'save_method' =&gt; 'storesettingfield' ], 'phpfpm_ini_flags' =&gt; [ 'label' =&gt; lng('phpfpm.ini_flags'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'ini_flags', 'type' =&gt; 'textarea', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true, 'required_otp' =&gt; true ], 'phpfpm_ini_values' =&gt; [ 'label' =&gt; lng('phpfpm.ini_values'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'ini_values', 'type' =&gt; 'textarea', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true, 'required_otp' =&gt; true ], 'phpfpm_ini_admin_flags' =&gt; [ 'label' =&gt; lng('phpfpm.ini_admin_flags'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'ini_admin_flags', 'type' =&gt; 'textarea', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true, 'required_otp' =&gt; true ], 'phpfpm_ini_admin_values' =&gt; [ 'label' =&gt; lng('phpfpm.ini_admin_values'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'ini_admin_values', 'type' =&gt; 'textarea', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true, 'required_otp' =&gt; true ] ] ] ] ];</file><file name="actions/admin/settings/120.system.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'groups' =&gt; [ 'system' =&gt; [ 'title' =&gt; lng('admin.systemsettings'), 'icon' =&gt; 'fa-solid fa-gears', 'fields' =&gt; [ 'system_documentroot_prefix' =&gt; [ 'label' =&gt; lng('serversettings.documentroot_prefix'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'documentroot_prefix', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'default' =&gt; '/var/customers/webs/', 'save_method' =&gt; 'storesettingfield', 'plausibility_check_method' =&gt; [ '\\froxlor\\validate\\check', 'checkpathconflicts' ], 'requires_reconf' =&gt; ['http'] ], 'system_documentroot_use_default_value' =&gt; [ 'label' =&gt; lng('serversettings.documentroot_use_default_value'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'documentroot_use_default_value', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'system_ipaddress' =&gt; [ 'label' =&gt; lng('serversettings.ipaddress'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'ipaddress', 'type' =&gt; 'select', 'option_options_method' =&gt; [ '\\froxlor\\domain\\ipaddr', 'getipaddresses' ], 'default' =&gt; '', 'save_method' =&gt; 'storesettingipaddress' ], 'system_defaultip' =&gt; [ 'label' =&gt; lng('serversettings.defaultip'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'defaultip', 'type' =&gt; 'select', 'select_mode' =&gt; 'multiple', 'option_options_method' =&gt; [ '\\froxlor\\domain\\ipaddr', 'getipportcombinations' ], 'default' =&gt; '', 'save_method' =&gt; 'storesettingdefaultip' ], 'system_defaultsslip' =&gt; [ 'label' =&gt; lng('serversettings.defaultsslip'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'defaultsslip', 'type' =&gt; 'select', 'select_mode' =&gt; 'multiple', 'option_options_method' =&gt; [ '\\froxlor\\domain\\ipaddr', 'getsslipportcombinations' ], 'default' =&gt; '', 'save_method' =&gt; 'storesettingdefaultsslip' ], 'system_hostname' =&gt; [ 'label' =&gt; lng('serversettings.hostname'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'hostname', 'type' =&gt; 'text', 'default' =&gt; '', 'save_method' =&gt; 'storesettinghostname', 'plausibility_check_method' =&gt; [ '\\froxlor\\validate\\check', 'checkhostname' ] ], 'api_enabled' =&gt; [ 'label' =&gt; lng('serversettings.enable_api'), 'settinggroup' =&gt; 'api', 'varname' =&gt; 'enabled', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ], 'api_customer_default' =&gt; [ 'label' =&gt; lng('serversettings.api_customer_default'), 'settinggroup' =&gt; 'api', 'varname' =&gt; 'customer_default', 'type' =&gt; 'select', 'default' =&gt; 1, 'select_var' =&gt; [ 1 =&gt; lng('panel.yes'), 0 =&gt; lng('panel.no') ], 'save_method' =&gt; 'storesettingfield' ], 'system_update_channel' =&gt; [ 'label' =&gt; lng('serversettings.update_channel'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'update_channel', 'type' =&gt; 'select', 'default' =&gt; 'stable', 'select_var' =&gt; [ 'stable' =&gt; lng('serversettings.uc_stable'), 'testing' =&gt; lng('serversettings.uc_testing'), 'nightly' =&gt; lng('serversettings.uc_nightly') ], 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_validate_domain' =&gt; [ 'label' =&gt; lng('serversettings.validate_domain'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'validate_domain', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield' ], 'system_stdsubdomain' =&gt; [ 'label' =&gt; lng('serversettings.stdsubdomainhost'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'stdsubdomain', 'type' =&gt; 'text', 'default' =&gt; '', 'save_method' =&gt; 'storesettinghostname' ], 'system_mysql_access_host' =&gt; [ 'label' =&gt; lng('serversettings.mysql_access_host'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mysql_access_host', 'type' =&gt; 'text', 'default' =&gt; '127.0.0.1,localhost', 'plausibility_check_method' =&gt; [ '\\froxlor\\validate\\check', 'checkmysqlaccesshost' ], 'save_method' =&gt; 'storesettingmysqlaccesshost' ], 'system_nssextrausers' =&gt; [ 'label' =&gt; lng('serversettings.nssextrausers'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'nssextrausers', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'system_store_index_file_subs' =&gt; [ 'label' =&gt; lng('serversettings.system_store_index_file_subs'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'store_index_file_subs', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield' ], 'system_report_enable' =&gt; [ 'label' =&gt; lng('serversettings.report.report'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'report_enable', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'cronmodule' =&gt; 'froxlor/reports', 'save_method' =&gt; 'storesettingfield' ], 'system_report_webmax' =&gt; [ 'label' =&gt; lng('serversettings.report.webmax'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'report_webmax', 'type' =&gt; 'number', 'min' =&gt; 0, 'max' =&gt; 150, 'default' =&gt; 90, 'save_method' =&gt; 'storesettingfield' ], 'system_report_trafficmax' =&gt; [ 'label' =&gt; lng('serversettings.report.trafficmax'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'report_trafficmax', 'type' =&gt; 'number', 'min' =&gt; 0, 'max' =&gt; 150, 'default' =&gt; 90, 'save_method' =&gt; 'storesettingfield' ], 'system_mail_use_smtp' =&gt; [ 'label' =&gt; lng('serversettings.mail_use_smtp'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mail_use_smtp', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'system_mail_smtp_host' =&gt; [ 'label' =&gt; lng('serversettings.mail_smtp_host'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mail_smtp_host', 'type' =&gt; 'text', 'default' =&gt; 'localhost', 'save_method' =&gt; 'storesettingfield' ], 'system_mail_smtp_port' =&gt; [ 'label' =&gt; lng('serversettings.mail_smtp_port'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mail_smtp_port', 'type' =&gt; 'number', 'min' =&gt; 1, 'max' =&gt; 65535, 'default' =&gt; 25, 'save_method' =&gt; 'storesettingfield' ], 'system_mail_smtp_usetls' =&gt; [ 'label' =&gt; lng('serversettings.mail_smtp_usetls'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mail_smtp_usetls', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield' ], 'system_mail_smtp_auth' =&gt; [ 'label' =&gt; lng('serversettings.mail_smtp_auth'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mail_smtp_auth', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield' ], 'system_mail_smtp_user' =&gt; [ 'label' =&gt; lng('serversettings.mail_smtp_user'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mail_smtp_user', 'type' =&gt; 'text', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'system_mail_smtp_passwd' =&gt; [ 'label' =&gt; lng('serversettings.mail_smtp_passwd'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mail_smtp_passwd', 'type' =&gt; 'password', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'system_apply_specialsettings_default' =&gt; [ 'label' =&gt; lng('serversettings.apply_specialsettings_default'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'apply_specialsettings_default', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_apply_phpconfigs_default' =&gt; [ 'label' =&gt; lng('serversettings.apply_phpconfigs_default'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'apply_phpconfigs_default', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_domaindefaultalias' =&gt; [ 'label' =&gt; lng('admin.domaindefaultalias'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'domaindefaultalias', 'type' =&gt; 'select', 'default' =&gt; '0', 'select_var' =&gt; [ '0' =&gt; lng('domains.serveraliasoption_wildcard'), '1' =&gt; lng('domains.serveraliasoption_www'), '2' =&gt; lng('domains.serveraliasoption_none') ], 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_hide_incompatible_settings' =&gt; [ 'label' =&gt; lng('serversettings.hide_incompatible_settings'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'hide_incompatible_settings', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], ] ] ] ];</file><file name="actions/admin/settings/125.cronjob.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'groups' =&gt; [ 'crond' =&gt; [ 'title' =&gt; lng('admin.cronsettings'), 'icon' =&gt; 'fa-solid fa-clock-rotate-left', 'advanced_mode' =&gt; true, 'fields' =&gt; [ 'system_cronconfig' =&gt; [ 'label' =&gt; lng('serversettings.system_cronconfig'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'cronconfig', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'default' =&gt; '/etc/cron.d/froxlor', 'save_method' =&gt; 'storesettingfield' ], 'system_croncmdline' =&gt; [ 'label' =&gt; lng('serversettings.system_croncmdline'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'croncmdline', 'type' =&gt; 'text', 'string_regexp' =&gt; '/^[a-z0-9\/\._\- ]+$/i', 'default' =&gt; '/usr/bin/nice -n 5 /usr/bin/php -q', 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ], 'system_crondreload' =&gt; [ 'label' =&gt; lng('serversettings.system_crondreload'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'crondreload', 'type' =&gt; 'text', 'string_regexp' =&gt; '/^[a-z0-9\/\._\- ]+$/i', 'default' =&gt; '/etc/init.d/cron reload', 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ], 'system_cron_allowautoupdate' =&gt; [ 'label' =&gt; lng('serversettings.system_cron_allowautoupdate'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'cron_allowautoupdate', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ] ] ] ] ];</file><file name="actions/admin/settings/137.perl.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'groups' =&gt; [ 'perl' =&gt; [ 'title' =&gt; lng('admin.perl_settings'), 'icon' =&gt; 'fa-solid fa-code', 'fields' =&gt; [ 'system_perl_path' =&gt; [ 'label' =&gt; lng('serversettings.perl_path'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'perl_path', 'type' =&gt; 'text', 'default' =&gt; '/usr/bin/perl', 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'lighttpd' ] ], 'perl_suexecworkaround' =&gt; [ 'label' =&gt; lng('serversettings.perl.suexecworkaround'), 'settinggroup' =&gt; 'perl', 'varname' =&gt; 'suexecworkaround', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2' ] ], 'perl_suexecpath' =&gt; [ 'label' =&gt; lng('serversettings.perl.suexeccgipath'), 'settinggroup' =&gt; 'perl', 'varname' =&gt; 'suexecpath', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'default' =&gt; '/var/www/cgi-bin/', 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2' ] ], 'serversettings_perl_server' =&gt; [ 'label' =&gt; lng('serversettings.perl_server'), 'settinggroup' =&gt; 'serversettings', 'varname' =&gt; 'perl_server', 'type' =&gt; 'text', 'default' =&gt; 'unix:/var/run/nginx/cgiwrap-dispatch.sock', 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'nginx' ] ] ] ] ] ];</file><file name="actions/admin/settings/140.statistics.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'groups' =&gt; [ 'statistics' =&gt; [ 'title' =&gt; lng('admin.statisticsettings'), 'icon' =&gt; 'fa-solid fa-chart-area', 'fields' =&gt; [ 'system_traffictool' =&gt; [ 'label' =&gt; lng('serversettings.traffictool.toolselect'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'traffictool', 'type' =&gt; 'select', 'default' =&gt; 'goaccess', 'select_var' =&gt; [ 'webalizer' =&gt; lng('serversettings.traffictool.webalizer'), 'awstats' =&gt; lng('serversettings.traffictool.awstats'), 'goaccess' =&gt; lng('serversettings.traffictool.goaccess') ], 'save_method' =&gt; 'storesettingupdatetraffictool', 'requires_reconf' =&gt; ['system'] ], 'system_webalizer_quiet' =&gt; [ 'label' =&gt; lng('serversettings.webalizer_quiet'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'webalizer_quiet', 'type' =&gt; 'select', 'default' =&gt; 2, 'select_var' =&gt; [ 0 =&gt; lng('admin.webalizer.normal'), 1 =&gt; lng('admin.webalizer.quiet'), 2 =&gt; lng('admin.webalizer.veryquiet') ], 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.traffictool') == 'webalizer' ], 'system_awstats_path' =&gt; [ 'label' =&gt; lng('serversettings.awstats_path'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'awstats_path', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'default' =&gt; '/usr/share/awstats/tools/', 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.traffictool') == 'awstats' ], 'system_awstats_awstatspath' =&gt; [ 'label' =&gt; lng('serversettings.awstats_awstatspath'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'awstats_awstatspath', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'default' =&gt; '/usr/lib/cgi-bin/', 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.traffictool') == 'awstats' ], 'system_awstats_conf' =&gt; [ 'label' =&gt; lng('serversettings.awstats_conf'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'awstats_conf', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'default' =&gt; '/etc/awstats/', 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.traffictool') == 'awstats', 'requires_reconf' =&gt; ['system:awstats'] ], 'system_awstats_icons' =&gt; [ 'label' =&gt; lng('serversettings.awstats_icons'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'awstats_icons', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'default' =&gt; '/usr/share/awstats/icon/', 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.traffictool') == 'awstats' ], 'system_awstats_logformat' =&gt; [ 'label' =&gt; lng('serversettings.awstats.logformat'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'awstats_logformat', 'type' =&gt; 'text', 'default' =&gt; '1', 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.traffictool') == 'awstats', 'advanced_mode' =&gt; true ] ] ] ] ];</file><file name="actions/admin/settings/170.logger.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'groups' =&gt; [ 'logging' =&gt; [ 'title' =&gt; lng('admin.loggersettings'), 'icon' =&gt; 'fa-solid fa-file-lines', 'fields' =&gt; [ 'logger_enabled' =&gt; [ 'label' =&gt; lng('serversettings.logger.enable'), 'settinggroup' =&gt; 'logger', 'varname' =&gt; 'enabled', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'overview_option' =&gt; true ], 'logger_severity' =&gt; [ 'label' =&gt; lng('serversettings.logger.severity'), 'settinggroup' =&gt; 'logger', 'varname' =&gt; 'severity', 'type' =&gt; 'select', 'default' =&gt; 1, 'select_var' =&gt; [ 1 =&gt; lng('admin.logger.normal'), 2 =&gt; lng('admin.logger.paranoid') ], 'save_method' =&gt; 'storesettingfield' ], 'logger_logtypes' =&gt; [ 'label' =&gt; lng('serversettings.logger.types'), 'settinggroup' =&gt; 'logger', 'varname' =&gt; 'logtypes', 'type' =&gt; 'select', 'default' =&gt; 'syslog,mysql', 'select_mode' =&gt; 'multiple', 'select_var' =&gt; [ 'syslog' =&gt; 'syslog', 'file' =&gt; 'file', 'mysql' =&gt; 'mysql' ], 'save_method' =&gt; 'storesettingfield' ], 'logger_logfile' =&gt; [ 'label' =&gt; lng('serversettings.logger.logfile'), 'settinggroup' =&gt; 'logger', 'varname' =&gt; 'logfile', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'logger_log_cron' =&gt; [ 'label' =&gt; lng('serversettings.logger.logcron'), 'settinggroup' =&gt; 'logger', 'varname' =&gt; 'log_cron', 'type' =&gt; 'select', 'default' =&gt; 0, 'select_var' =&gt; [ 0 =&gt; lng('serversettings.logger.logcronoption.never'), 1 =&gt; lng('serversettings.logger.logcronoption.once'), 2 =&gt; lng('serversettings.logger.logcronoption.always') ], 'save_method' =&gt; 'storesettingfield' ] ] ] ] ];</file><file name="actions/admin/settings/130.webserver.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'groups' =&gt; [ 'webserver' =&gt; [ 'title' =&gt; lng('admin.webserversettings'), 'icon' =&gt; 'fa-solid fa-server', 'fields' =&gt; [ 'system_webserver' =&gt; [ 'label' =&gt; lng('admin.webserver'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'webserver', 'type' =&gt; 'select', 'default' =&gt; 'apache2', 'select_var' =&gt; [ 'apache2' =&gt; 'apache 2', 'lighttpd' =&gt; 'lighttpd', 'nginx' =&gt; 'nginx' ], 'save_method' =&gt; 'storesettingfield', 'plausibility_check_method' =&gt; [ '\\froxlor\\validate\\check', 'checkphpinterfacesetting' ], 'requires_reconf' =&gt; ['http'] ], 'system_apache24' =&gt; [ 'label' =&gt; lng('serversettings.apache_24'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'apache24', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2' ] ], 'system_apacheitksupport' =&gt; [ 'label' =&gt; lng('serversettings.apache_itksupport'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'apacheitksupport', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; (settings::get('system.mod_fcgid') == 0 &amp;&amp; settings::get('phpfpm.enabled') == 0), 'websrv_avail' =&gt; [ 'apache2' ], 'advanced_mode' =&gt; true ], 'system_http2_support' =&gt; [ 'label' =&gt; lng('serversettings.http2_support'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'http2_support', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2', 'nginx' ], 'visible' =&gt; settings::get('system.use_ssl') ], 'system_dhparams_file' =&gt; [ 'label' =&gt; lng('serversettings.dhparams_file'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'dhparams_file', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.use_ssl'), 'advanced_mode' =&gt; true ], 'system_httpuser' =&gt; [ 'label' =&gt; lng('admin.webserver_user'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'httpuser', 'type' =&gt; 'text', 'default' =&gt; 'www-data', 'save_method' =&gt; 'storesettingwebserverfcgidfpmuser' ], 'system_httpgroup' =&gt; [ 'label' =&gt; lng('admin.webserver_group'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'httpgroup', 'type' =&gt; 'text', 'default' =&gt; 'www-data', 'save_method' =&gt; 'storesettingfield' ], 'system_apacheconf_vhost' =&gt; [ 'label' =&gt; lng('serversettings.apacheconf_vhost'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'apacheconf_vhost', 'type' =&gt; 'text', 'string_type' =&gt; 'filedir', 'default' =&gt; '/etc/apache2/sites-enabled/', 'save_method' =&gt; 'storesettingfield', 'requires_reconf' =&gt; ['http'] ], 'system_apacheconf_diroptions' =&gt; [ 'label' =&gt; lng('serversettings.apacheconf_diroptions'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'apacheconf_diroptions', 'type' =&gt; 'text', 'string_type' =&gt; 'filedir', 'default' =&gt; '/etc/apache2/sites-enabled/', 'save_method' =&gt; 'storesettingfield', 'requires_reconf' =&gt; ['http'] ], 'system_apacheconf_htpasswddir' =&gt; [ 'label' =&gt; lng('serversettings.apacheconf_htpasswddir'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'apacheconf_htpasswddir', 'type' =&gt; 'text', 'string_type' =&gt; 'confdir', 'default' =&gt; '/etc/apache2/htpasswd/', 'save_method' =&gt; 'storesettingfield' ], 'system_logfiles_directory' =&gt; [ 'label' =&gt; lng('serversettings.logfiles_directory'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'logfiles_directory', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'default' =&gt; '/var/customers/logs/', 'save_method' =&gt; 'storesettingfield', 'requires_reconf' =&gt; ['http'] ], 'system_logfiles_script' =&gt; [ 'label' =&gt; lng('serversettings.logfiles_script'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'logfiles_script', 'type' =&gt; 'text', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2' ], 'advanced_mode' =&gt; true ], 'system_logfiles_piped' =&gt; [ 'label' =&gt; lng('serversettings.logfiles_piped'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'logfiles_piped', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2' ], 'advanced_mode' =&gt; true ], 'system_logfiles_format' =&gt; [ 'label' =&gt; lng('serversettings.logfiles_format'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'logfiles_format', 'type' =&gt; (strpos(settings::get('system.logfiles_format'), '"') !== false ? 'textarea' : 'text'), 'string_regexp' =&gt; '/^[^\0\r\n&lt;&gt;]*$/i', 'default' =&gt; '', 'string_emptyallowed' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2', 'nginx' ], 'visible' =&gt; settings::get('system.traffictool') != 'webalizer', 'advanced_mode' =&gt; true ], 'system_logfiles_type' =&gt; [ 'label' =&gt; lng('serversettings.logfiles_type'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'logfiles_type', 'type' =&gt; 'select', 'default' =&gt; '1', 'select_var' =&gt; [ '1' =&gt; 'combined', '2' =&gt; 'vhost_combined' ], 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2' ] ], 'system_errorlog_level' =&gt; [ 'label' =&gt; lng('serversettings.errorlog_level'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'errorlog_level', 'type' =&gt; 'select', 'default' =&gt; (settings::get('system.webserver') == 'nginx' ? 'error' : 'warn'), 'select_var' =&gt; [ 'emerg' =&gt; 'emerg', 'alert' =&gt; 'alert', 'crit' =&gt; 'crit', 'error' =&gt; 'error', 'warn' =&gt; 'warn', 'notice' =&gt; 'notice', 'info' =&gt; 'info', 'debug' =&gt; 'debug' ], 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2', 'nginx' ] ], 'system_customer_ssl_path' =&gt; [ 'label' =&gt; lng('serversettings.customerssl_directory'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'customer_ssl_path', 'type' =&gt; 'text', 'string_type' =&gt; 'confdir', 'default' =&gt; '/etc/ssl/froxlor-custom/', 'save_method' =&gt; 'storesettingfield' ], 'system_phpappendopenbasedir' =&gt; [ 'label' =&gt; lng('serversettings.phpappendopenbasedir'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'phpappendopenbasedir', 'type' =&gt; 'text', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_deactivateddocroot' =&gt; [ 'label' =&gt; lng('serversettings.deactivateddocroot'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'deactivateddocroot', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'requires_reconf' =&gt; ['http'] ], 'system_default_vhostconf' =&gt; [ 'label' =&gt; lng('serversettings.default_vhostconf'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'default_vhostconf', 'type' =&gt; 'textarea', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_default_sslvhostconf' =&gt; [ 'label' =&gt; lng('serversettings.default_sslvhostconf'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'default_sslvhostconf', 'type' =&gt; 'textarea', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.use_ssl') == 1, 'advanced_mode' =&gt; true ], 'system_include_default_vhostconf' =&gt; [ 'label' =&gt; lng('serversettings.includedefault_sslvhostconf'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'include_default_vhostconf', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_apacheglobaldiropt' =&gt; [ 'label' =&gt; lng('serversettings.apache_globaldiropt'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'apacheglobaldiropt', 'type' =&gt; 'textarea', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; (settings::get('system.mod_fcgid') == 0 &amp;&amp; settings::get('phpfpm.enabled') == 0), 'websrv_avail' =&gt; [ 'apache2' ], 'advanced_mode' =&gt; true ], 'system_apachereload_command' =&gt; [ 'label' =&gt; lng('serversettings.apachereload_command'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'apachereload_command', 'type' =&gt; 'text', 'string_regexp' =&gt; '/^[a-z0-9\/\._\- ]+$/i', 'default' =&gt; '/etc/init.d/apache2 reload', 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ], 'system_phpreload_command' =&gt; [ 'label' =&gt; lng('serversettings.phpreload_command'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'phpreload_command', 'type' =&gt; 'text', 'string_regexp' =&gt; '/^[a-z0-9\/\._\- ]+$/i', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'nginx' ], 'required_otp' =&gt; true ], 'system_nginx_php_backend' =&gt; [ 'label' =&gt; lng('serversettings.nginx_php_backend'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'nginx_php_backend', 'type' =&gt; 'text', 'default' =&gt; '127.0.0.1:8888', 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'nginx' ] ], 'nginx_fastcgiparams' =&gt; [ 'label' =&gt; lng('serversettings.nginx_fastcgiparams'), 'settinggroup' =&gt; 'nginx', 'varname' =&gt; 'fastcgiparams', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'default' =&gt; '/etc/nginx/fastcgi_params', 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'nginx' ] ], 'defaultwebsrverrhandler_enabled' =&gt; [ 'label' =&gt; lng('serversettings.defaultwebsrverrhandler_enabled'), 'settinggroup' =&gt; 'defaultwebsrverrhandler', 'varname' =&gt; 'enabled', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'defaultwebsrverrhandler_err401' =&gt; [ 'label' =&gt; lng('serversettings.defaultwebsrverrhandler_err401'), 'settinggroup' =&gt; 'defaultwebsrverrhandler', 'varname' =&gt; 'err401', 'type' =&gt; 'text', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2', 'nginx' ], 'advanced_mode' =&gt; true ], 'defaultwebsrverrhandler_err403' =&gt; [ 'label' =&gt; lng('serversettings.defaultwebsrverrhandler_err403'), 'settinggroup' =&gt; 'defaultwebsrverrhandler', 'varname' =&gt; 'err403', 'type' =&gt; 'text', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2', 'nginx' ], 'advanced_mode' =&gt; true ], 'defaultwebsrverrhandler_err404' =&gt; [ 'label' =&gt; lng('serversettings.defaultwebsrverrhandler_err404'), 'settinggroup' =&gt; 'defaultwebsrverrhandler', 'varname' =&gt; 'err404', 'type' =&gt; 'text', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'defaultwebsrverrhandler_err500' =&gt; [ 'label' =&gt; lng('serversettings.defaultwebsrverrhandler_err500'), 'settinggroup' =&gt; 'defaultwebsrverrhandler', 'varname' =&gt; 'err500', 'type' =&gt; 'text', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2', 'nginx' ], 'advanced_mode' =&gt; true ], 'customredirect_enabled' =&gt; [ 'label' =&gt; lng('serversettings.customredirect_enabled'), 'settinggroup' =&gt; 'customredirect', 'varname' =&gt; 'enabled', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'customredirect_default' =&gt; [ 'label' =&gt; lng('serversettings.customredirect_default'), 'settinggroup' =&gt; 'customredirect', 'varname' =&gt; 'default', 'type' =&gt; 'select', 'default' =&gt; '1', 'option_options_method' =&gt; ['\\froxlor\\domain\\domain', 'getredirectcodes'], 'save_method' =&gt; 'storesettingfield' ] ] ] ] ];</file><file name="actions/admin/settings/180.antispam.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'groups' =&gt; [ 'antispam' =&gt; [ 'title' =&gt; lng('admin.antispam_settings'), 'icon' =&gt; 'fa-solid fa-clipboard-check', 'fields' =&gt; [ 'antispam_activated' =&gt; [ 'label' =&gt; lng('antispam.activated'), 'settinggroup' =&gt; 'antispam', 'varname' =&gt; 'activated', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'overview_option' =&gt; true, 'save_method' =&gt; 'storesettingfieldinsertantispamtask', ], 'antispam_config_file' =&gt; [ 'label' =&gt; lng('antispam.config_file'), 'settinggroup' =&gt; 'antispam', 'varname' =&gt; 'config_file', 'type' =&gt; 'text', 'string_type' =&gt; 'file', 'default' =&gt; '/etc/rspamd/local.d/froxlor_settings.conf', 'save_method' =&gt; 'storesettingfieldinsertantispamtask', 'requires_reconf' =&gt; ['antispam'] ], 'antispam_reload_command' =&gt; [ 'label' =&gt; lng('antispam.reload_command'), 'settinggroup' =&gt; 'antispam', 'varname' =&gt; 'reload_command', 'type' =&gt; 'text', 'string_regexp' =&gt; '/^[a-z0-9\/\._\- ]+$/i', 'default' =&gt; 'service rspamd restart', 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ], 'antispam_default_bypass_spam' =&gt; [ 'label' =&gt; lng('antispam.default_bypass_spam'), 'settinggroup' =&gt; 'antispam', 'varname' =&gt; 'default_bypass_spam', 'type' =&gt; 'select', 'default' =&gt; 2, 'select_var' =&gt; [ 1 =&gt; lng('antispam.default_select.on_changeable'), 2 =&gt; lng('antispam.default_select.off_changeable'), 3 =&gt; lng('antispam.default_select.on_unchangeable'), 4 =&gt; lng('antispam.default_select.off_unchangeable'), ], 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'antispam_default_spam_rewrite_subject' =&gt; [ 'label' =&gt; lng('antispam.default_spam_rewrite_subject'), 'settinggroup' =&gt; 'antispam', 'varname' =&gt; 'default_spam_rewrite_subject', 'type' =&gt; 'select', 'default' =&gt; 1, 'select_var' =&gt; [ 1 =&gt; lng('antispam.default_select.on_changeable'), 2 =&gt; lng('antispam.default_select.off_changeable'), 3 =&gt; lng('antispam.default_select.on_unchangeable'), 4 =&gt; lng('antispam.default_select.off_unchangeable'), ], 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'antispam_default_policy_greylist' =&gt; [ 'label' =&gt; lng('antispam.default_policy_greylist'), 'settinggroup' =&gt; 'antispam', 'varname' =&gt; 'default_policy_greylist', 'type' =&gt; 'select', 'default' =&gt; 1, 'select_var' =&gt; [ 1 =&gt; lng('antispam.default_select.on_changeable'), 2 =&gt; lng('antispam.default_select.off_changeable'), 3 =&gt; lng('antispam.default_select.on_unchangeable'), 4 =&gt; lng('antispam.default_select.off_unchangeable'), ], 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'antispam_dkim_keylength' =&gt; [ 'label' =&gt; lng('antispam.dkim_keylength'), 'settinggroup' =&gt; 'antispam', 'varname' =&gt; 'dkim_keylength', 'type' =&gt; 'select', 'default' =&gt; '1024', 'select_var' =&gt; [ '1024' =&gt; '1024 bit', '2048' =&gt; '2048 bit' ], 'save_method' =&gt; 'storesettingfieldinsertbindtask', 'advanced_mode' =&gt; true, ], 'spf_use_spf' =&gt; [ 'label' =&gt; lng('spf.use_spf'), 'settinggroup' =&gt; 'spf', 'varname' =&gt; 'use_spf', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', ], 'spf_spf_entry' =&gt; [ 'label' =&gt; lng('spf.spf_entry'), 'settinggroup' =&gt; 'spf', 'varname' =&gt; 'spf_entry', 'type' =&gt; 'text', 'string_regexp' =&gt; '/^v=spf[a-z0-9:~?\s\.\-\/]+$/i', 'default' =&gt; 'v=spf1 mx -all', 'save_method' =&gt; 'storesettingfield' ], 'dmarc_use_dmarc' =&gt; [ 'label' =&gt; lng('dmarc.use_dmarc'), 'settinggroup' =&gt; 'dmarc', 'varname' =&gt; 'use_dmarc', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', ], 'dmarc_dmarc_entry' =&gt; [ 'label' =&gt; lng('dmarc.dmarc_entry'), 'settinggroup' =&gt; 'dmarc', 'varname' =&gt; 'dmarc_entry', 'type' =&gt; 'text', 'string_regexp' =&gt; '/^v=dmarc1(.+)$/i', 'default' =&gt; 'v=dmarc1; p=none;', 'save_method' =&gt; 'storesettingfield' ] ] ] ] ];</file><file name="actions/admin/settings/index.html" /><file name="actions/admin/settings/210.security.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'groups' =&gt; [ 'security' =&gt; [ 'title' =&gt; lng('admin.security_settings'), 'icon' =&gt; 'fa-solid fa-user-lock', 'fields' =&gt; [ 'panel_unix_names' =&gt; [ 'label' =&gt; lng('serversettings.unix_names'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'unix_names', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ], 'system_mailpwcleartext' =&gt; [ 'label' =&gt; lng('serversettings.mailpwcleartext'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mailpwcleartext', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true, 'required_otp' =&gt; true ], 'system_passwordcryptfunc' =&gt; [ 'label' =&gt; lng('serversettings.passwordcryptfunc'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'passwordcryptfunc', 'type' =&gt; 'select', 'default' =&gt; password_default, 'option_options_method' =&gt; [ '\\froxlor\\system\\crypt', 'getavailablepasswordhashes' ], 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true, 'required_otp' =&gt; true ], 'system_allow_error_report_admin' =&gt; [ 'label' =&gt; lng('serversettings.allow_error_report_admin'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'allow_error_report_admin', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ], 'system_allow_error_report_customer' =&gt; [ 'label' =&gt; lng('serversettings.allow_error_report_customer'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'allow_error_report_customer', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ], 'system_allow_customer_shell' =&gt; [ 'label' =&gt; lng('serversettings.allow_allow_customer_shell'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'allow_customer_shell', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true, 'required_otp' =&gt; true ], 'system_available_shells' =&gt; [ 'label' =&gt; lng('serversettings.available_shells'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'available_shells', 'type' =&gt; 'text', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true, 'required_otp' =&gt; true ], 'system_froxlorusergroup' =&gt; [ 'label' =&gt; lng('serversettings.froxlorusergroup'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'froxlorusergroup', 'type' =&gt; 'text', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'plausibility_check_method' =&gt; [ '\\froxlor\\validate\\check', 'checklocalgroup' ], 'visible' =&gt; settings::get('system.nssextrausers'), 'advanced_mode' =&gt; true, 'required_otp' =&gt; true ], ] ] ] ];</file><file name="actions/admin/settings/110.accounts.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'groups' =&gt; [ 'accounts' =&gt; [ 'title' =&gt; lng('admin.accountsettings'), 'icon' =&gt; 'fa-solid fa-users-gear', 'fields' =&gt; [ 'session_sessiontimeout' =&gt; [ 'label' =&gt; lng('serversettings.session_timeout'), 'settinggroup' =&gt; 'session', 'varname' =&gt; 'sessiontimeout', 'type' =&gt; 'number', 'min' =&gt; 60, 'max' =&gt; 31536000, 'default' =&gt; 600, 'save_method' =&gt; 'storesettingfield' ], 'session_allow_multiple_login' =&gt; [ 'label' =&gt; lng('serversettings.session_allow_multiple_login'), 'settinggroup' =&gt; 'session', 'varname' =&gt; 'allow_multiple_login', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'login_domain_login' =&gt; [ 'label' =&gt; lng('serversettings.login_domain_login'), 'settinggroup' =&gt; 'login', 'varname' =&gt; 'domain_login', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'login_maxloginattempts' =&gt; [ 'label' =&gt; lng('serversettings.maxloginattempts'), 'settinggroup' =&gt; 'login', 'varname' =&gt; 'maxloginattempts', 'type' =&gt; 'number', 'min' =&gt; 1, 'default' =&gt; 3, 'save_method' =&gt; 'storesettingfield' ], 'login_deactivatetime' =&gt; [ 'label' =&gt; lng('serversettings.deactivatetime'), 'settinggroup' =&gt; 'login', 'varname' =&gt; 'deactivatetime', 'type' =&gt; 'number', 'min' =&gt; 0, 'default' =&gt; 900, 'save_method' =&gt; 'storesettingfield' ], '2fa_enabled' =&gt; [ 'label' =&gt; lng('2fa.2fa_enabled'), 'settinggroup' =&gt; '2fa', 'varname' =&gt; 'enabled', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield' ], 'panel_password_min_length' =&gt; [ 'label' =&gt; lng('serversettings.panel_password_min_length'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'password_min_length', 'type' =&gt; 'number', 'min' =&gt; 0, 'default' =&gt; 0, 'save_method' =&gt; 'storesettingfield' ], 'panel_password_alpha_lower' =&gt; [ 'label' =&gt; lng('serversettings.panel_password_alpha_lower'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'password_alpha_lower', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield' ], 'panel_password_alpha_upper' =&gt; [ 'label' =&gt; lng('serversettings.panel_password_alpha_upper'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'password_alpha_upper', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield' ], 'panel_password_numeric' =&gt; [ 'label' =&gt; lng('serversettings.panel_password_numeric'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'password_numeric', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'panel_password_special_char_required' =&gt; [ 'label' =&gt; lng('serversettings.panel_password_special_char_required'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'password_special_char_required', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'panel_password_special_char' =&gt; [ 'label' =&gt; lng('serversettings.panel_password_special_char'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'password_special_char', 'type' =&gt; 'text', 'default' =&gt; '!?&lt;&gt;$%+#=@', 'save_method' =&gt; 'storesettingfield' ], 'panel_password_regex' =&gt; [ 'label' =&gt; lng('serversettings.panel_password_regex'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'password_regex', 'type' =&gt; 'text', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_req_limit_per_interval' =&gt; [ 'label' =&gt; lng('serversettings.req_limit_per_interval'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'req_limit_per_interval', 'type' =&gt; 'number', 'min' =&gt; 30, 'default' =&gt; 60, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_req_limit_interval' =&gt; [ 'label' =&gt; lng('serversettings.req_limit_interval'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'req_limit_interval', 'type' =&gt; 'number', 'min' =&gt; 5, 'default' =&gt; 60, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'customer_accountprefix' =&gt; [ 'label' =&gt; lng('serversettings.accountprefix'), 'settinggroup' =&gt; 'customer', 'varname' =&gt; 'accountprefix', 'type' =&gt; 'text', 'default' =&gt; '', 'plausibility_check_method' =&gt; [ '\\froxlor\\validate\\check', 'checkusername' ], 'save_method' =&gt; 'storesettingfield' ], 'customer_mysqlprefix' =&gt; [ 'label' =&gt; lng('serversettings.mysqlprefix'), 'settinggroup' =&gt; 'customer', 'varname' =&gt; 'mysqlprefix', 'type' =&gt; 'text', 'default' =&gt; '', 'plausibility_check_method' =&gt; [ '\\froxlor\\validate\\check', 'checkusername' ], 'save_method' =&gt; 'storesettingfield' ], 'customer_ftpprefix' =&gt; [ 'label' =&gt; lng('serversettings.ftpprefix'), 'settinggroup' =&gt; 'customer', 'varname' =&gt; 'ftpprefix', 'type' =&gt; 'text', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'customer_ftpatdomain' =&gt; [ 'label' =&gt; lng('serversettings.ftpdomain'), 'settinggroup' =&gt; 'customer', 'varname' =&gt; 'ftpatdomain', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'panel_allow_preset' =&gt; [ 'label' =&gt; lng('serversettings.allow_password_reset'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'allow_preset', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'dependency' =&gt; [ 'fieldname' =&gt; 'panel_allow_preset_admin', 'fielddata' =&gt; [ 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'allow_preset_admin' ], 'onlyif' =&gt; 0 ] ], 'panel_allow_preset_admin' =&gt; [ 'label' =&gt; lng('serversettings.allow_password_reset_admin'), 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'allow_preset_admin', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'dependency' =&gt; [ 'fieldname' =&gt; 'panel_allow_preset', 'fielddata' =&gt; [ 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'allow_preset' ], 'onlyif' =&gt; 1 ] ], 'system_exportenabled' =&gt; [ 'label' =&gt; lng('serversettings.exportenabled'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'exportenabled', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'cronmodule' =&gt; 'froxlor/export', 'save_method' =&gt; 'storesettingfield' ], 'system_createstdsubdom_default' =&gt; [ 'label' =&gt; lng('serversettings.createstdsubdom_default'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'createstdsubdom_default', 'type' =&gt; 'select', 'default' =&gt; '1', 'select_var' =&gt; [ '0' =&gt; lng('panel.no'), '1' =&gt; lng('panel.yes') ], 'save_method' =&gt; 'storesettingfield' ], ] ] ] ];</file><file name="actions/admin/settings/160.nameserver.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'groups' =&gt; [ 'nameserver' =&gt; [ 'title' =&gt; lng('admin.nameserversettings'), 'icon' =&gt; 'fa-solid fa-globe', 'fields' =&gt; [ 'system_bind_enable' =&gt; [ 'label' =&gt; lng('serversettings.bindenable'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'bind_enable', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'overview_option' =&gt; true, 'requires_reconf' =&gt; ['dns'] ], 'system_dnsenabled' =&gt; [ 'label' =&gt; lng('serversettings.dnseditorenable'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'dnsenabled', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'system_dns_server' =&gt; [ 'label' =&gt; lng('serversettings.dns_server'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'dns_server', 'type' =&gt; 'select', 'default' =&gt; 'bind', 'select_var' =&gt; [ 'bind' =&gt; 'bind9', 'powerdns' =&gt; 'powerdns' ], 'save_method' =&gt; 'storesettingfield', 'requires_reconf' =&gt; ['dns'] ], 'system_bindconf_directory' =&gt; [ 'label' =&gt; lng('serversettings.bindconf_directory'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'bindconf_directory', 'type' =&gt; 'text', 'string_type' =&gt; 'dir', 'default' =&gt; '/etc/bind/', 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.dns_server') == 'bind', 'requires_reconf' =&gt; ['dns:bind'] ], 'system_bindreload_command' =&gt; [ 'label' =&gt; lng('serversettings.bindreload_command'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'bindreload_command', 'type' =&gt; 'text', 'string_regexp' =&gt; '/^[a-z0-9\/\._\- ]+$/i', 'default' =&gt; '/etc/init.d/bind9 reload', 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ], 'system_nameservers' =&gt; [ 'label' =&gt; lng('serversettings.nameservers'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'nameservers', 'type' =&gt; 'text', 'string_regexp' =&gt; '/^(([a-z0-9\-\._]+, ?)*[a-z0-9\-\._]+)?$/i', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfieldinsertbindtask' ], 'system_mxservers' =&gt; [ 'label' =&gt; lng('serversettings.mxservers'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mxservers', 'type' =&gt; 'text', 'string_regexp' =&gt; '/^(([0-9]+ [a-z0-9\-\._]+, ?)*[0-9]+ [a-z0-9\-\._]+)?$/i', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ], 'system_axfrservers' =&gt; [ 'label' =&gt; lng('serversettings.axfrservers'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'axfrservers', 'type' =&gt; 'text', 'string_type' =&gt; 'validate_ip_incl_private', 'string_delimiter' =&gt; ',', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'required_otp' =&gt; true ], 'system_powerdns_mode' =&gt; [ 'label' =&gt; lng('serversettings.powerdns_mode'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'powerdns_mode', 'type' =&gt; 'select', 'default' =&gt; 'native', 'select_var' =&gt; [ 'native' =&gt; 'native', 'master' =&gt; 'master' ], 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true, 'visible' =&gt; settings::get('system.dns_server') == 'powerdns', ], 'system_dns_createmailentry' =&gt; [ 'label' =&gt; lng('serversettings.mail_also_with_mxservers'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'dns_createmailentry', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield' ], 'system_dns_createcaaentry' =&gt; [ 'label' =&gt; lng('serversettings.caa_entry'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'dns_createcaaentry', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'caa_caa_entry' =&gt; [ 'label' =&gt; lng('serversettings.caa_entry_custom'), 'settinggroup' =&gt; 'caa', 'varname' =&gt; 'caa_entry', 'type' =&gt; 'textarea', 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield', 'advanced_mode' =&gt; true ], 'system_defaultttl' =&gt; [ 'label' =&gt; lng('serversettings.defaultttl'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'defaultttl', 'type' =&gt; 'number', 'default' =&gt; 604800, /* 1 week */ 'min' =&gt; 3600, /* 1 hour */ 'max' =&gt; 2147483647, /* integer max */ 'save_method' =&gt; 'storesettingfield' ], 'system_soaemail' =&gt; [ 'label' =&gt; lng('serversettings.soaemail'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'soaemail', 'type' =&gt; 'email', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingfield' ] ] ] ] ];</file><file name="actions/admin/settings/122.froxlorvhost.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'groups' =&gt; [ 'froxlorvhost' =&gt; [ 'title' =&gt; lng('admin.froxlorvhost') . (call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ]) == false ? lng('admin.novhostcontainer') : ''), 'icon' =&gt; 'fa-solid fa-wrench', 'fields' =&gt; [ /** * webserver-vhost */ 'system_froxlordirectlyviahostname' =&gt; [ 'label' =&gt; lng('serversettings.froxlordirectlyviahostname'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'froxlordirectlyviahostname', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield' ], 'system_froxloraliases' =&gt; [ 'label' =&gt; lng('serversettings.froxloraliases'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'froxloraliases', 'type' =&gt; 'text', 'string_regexp' =&gt; '/^(([a-z0-9\-\._]+, ?)*[a-z0-9\-\._]+)?$/i', 'string_emptyallowed' =&gt; true, 'default' =&gt; '', 'save_method' =&gt; 'storesettingclearcertificates', 'advanced_mode' =&gt; true ], /** * ssl / let's encrypt */ 'system_le_froxlor_enabled' =&gt; [ 'label' =&gt; lng('serversettings.le_froxlor_enabled'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'le_froxlor_enabled', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingclearcertificates', 'visible' =&gt; settings::get('system.leenabled') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ], true), 'requires_reconf' =&gt; ['http'] ], 'system_le_froxlor_redirect' =&gt; [ 'label' =&gt; lng('serversettings.le_froxlor_redirect'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'le_froxlor_redirect', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.use_ssl') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ], true) ], 'system_hsts_maxage' =&gt; [ 'label' =&gt; lng('admin.domain_hsts_maxage'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'hsts_maxage', 'type' =&gt; 'number', 'min' =&gt; 0, 'max' =&gt; 94608000, // 3-years 'default' =&gt; 10368000, 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.use_ssl') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ], true), 'advanced_mode' =&gt; true ], 'system_hsts_incsub' =&gt; [ 'label' =&gt; lng('admin.domain_hsts_incsub'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'hsts_incsub', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.use_ssl') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ], true), 'advanced_mode' =&gt; true ], 'system_hsts_preload' =&gt; [ 'label' =&gt; lng('admin.domain_hsts_preload'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'hsts_preload', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.use_ssl') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ], true), 'advanced_mode' =&gt; true ], 'system_honorcipherorder' =&gt; [ 'label' =&gt; lng('admin.domain_honorcipherorder'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'honorcipherorder', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.use_ssl') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ], true), 'advanced_mode' =&gt; true ], 'system_sessiontickets' =&gt; [ 'label' =&gt; lng('admin.domain_sessiontickets'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'sessiontickets', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.use_ssl') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ], true), 'advanced_mode' =&gt; true ], /** * fcgid */ 'system_mod_fcgid_ownvhost' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid_ownvhost'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mod_fcgid_ownvhost', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2' ], 'visible' =&gt; settings::get('system.mod_fcgid') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ]), 'requires_reconf' =&gt; ['system:fcgid'] ], 'system_mod_fcgid_httpuser' =&gt; [ 'label' =&gt; lng('admin.mod_fcgid_user'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mod_fcgid_httpuser', 'type' =&gt; 'text', 'default' =&gt; 'froxlorlocal', 'string_emptyallowed' =&gt; false, 'save_method' =&gt; 'storesettingwebserverfcgidfpmuser', 'websrv_avail' =&gt; [ 'apache2' ], 'visible' =&gt; settings::get('system.mod_fcgid') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ]), 'requires_reconf' =&gt; ['system:fcgid'] ], 'system_mod_fcgid_httpgroup' =&gt; [ 'label' =&gt; lng('admin.mod_fcgid_group'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mod_fcgid_httpgroup', 'type' =&gt; 'text', 'default' =&gt; 'froxlorlocal', 'save_method' =&gt; 'storesettingfield', 'string_emptyallowed' =&gt; false, 'websrv_avail' =&gt; [ 'apache2' ], 'visible' =&gt; settings::get('system.mod_fcgid') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ]), 'requires_reconf' =&gt; ['system:fcgid'] ], 'system_mod_fcgid_defaultini_ownvhost' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid.defaultini_ownvhost'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'mod_fcgid_defaultini_ownvhost', 'type' =&gt; 'select', 'default' =&gt; '2', 'option_options_method' =&gt; [ '\\froxlor\\http\\phpconfig', 'getphpconfigs' ], 'save_method' =&gt; 'storesettingfield', 'websrv_avail' =&gt; [ 'apache2' ], 'visible' =&gt; settings::get('system.mod_fcgid') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ]) ], /** * php-fpm */ 'phpfpm_enabled_ownvhost' =&gt; [ 'label' =&gt; lng('phpfpm.ownvhost'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'enabled_ownvhost', 'type' =&gt; 'checkbox', 'default' =&gt; true, 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('phpfpm.enabled') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ]), 'requires_reconf' =&gt; ['system:php-fpm'] ], 'phpfpm_vhost_httpuser' =&gt; [ 'label' =&gt; lng('phpfpm.vhost_httpuser'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'vhost_httpuser', 'type' =&gt; 'text', 'default' =&gt; 'froxlorlocal', 'string_emptyallowed' =&gt; false, 'save_method' =&gt; 'storesettingwebserverfcgidfpmuser', 'visible' =&gt; settings::get('phpfpm.enabled') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ]), 'requires_reconf' =&gt; ['system:php-fpm'] ], 'phpfpm_vhost_httpgroup' =&gt; [ 'label' =&gt; lng('phpfpm.vhost_httpgroup'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'vhost_httpgroup', 'type' =&gt; 'text', 'default' =&gt; 'froxlorlocal', 'string_emptyallowed' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('phpfpm.enabled') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ]), 'requires_reconf' =&gt; ['system:php-fpm'] ], 'phpfpm_vhost_defaultini' =&gt; [ 'label' =&gt; lng('serversettings.mod_fcgid.defaultini_ownvhost'), 'settinggroup' =&gt; 'phpfpm', 'varname' =&gt; 'vhost_defaultini', 'type' =&gt; 'select', 'default' =&gt; '2', 'option_options_method' =&gt; [ '\\froxlor\\http\\phpconfig', 'getphpconfigs' ], 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('phpfpm.enabled') &amp;&amp; call_user_func([ '\froxlor\settings\froxlorvhostsettings', 'hasvhostcontainerenabled' ]) ], /** * dns */ 'system_dns_createhostnameentry' =&gt; [ 'label' =&gt; lng('serversettings.dns_createhostnameentry'), 'settinggroup' =&gt; 'system', 'varname' =&gt; 'dns_createhostnameentry', 'type' =&gt; 'checkbox', 'default' =&gt; false, 'save_method' =&gt; 'storesettingfield', 'visible' =&gt; settings::get('system.bind_enable') ] ] ] ] ];</file><file name="tests/bootstrap.php">&lt;?php define('dev_froxlor', 1); (file_exists('/etc/froxlor-test.pwd') &amp;&amp; file_exists('/etc/froxlor-test.rpwd')) { // froxlor jenkins test-system $pwd = trim(file_get_contents('/etc/froxlor-test.pwd')); $rpwd = trim(file_get_contents('/etc/froxlor-test.rpwd')); define('travis_ci', 0); } else { // travis-ci.org $pwd = 'fr0xl0r.travisci'; $rpwd = 'fr0xl0r.travisci'; define('travis_ci', 1); } (@php_sapi_name() !== 'cli') { // called via browser die; } $userdata_content = "&lt;?php \$sql['user'] = 'froxlor010'; \$sql['password'] = '$pwd'; \$sql['host'] = '127.0.0.1'; \$sql['db'] = 'froxlor010'; \$sql_root[0]['user'] = 'root'; \$sql_root[0]['password'] = '$rpwd'; \$sql_root[0]['host'] = '127.0.0.1'; \$sql_root[0]['caption'] = 'test default'; \$sql['debug'] = true;" . php_eol; $userdata = dirname(__dir__) . '/lib/userdata.inc.php'; (file_exists($userdata)) { rename($userdata, $userdata . ".bak"); } file_put_contents($userdata, $userdata_content); // include autoloader / api / etc require dirname(__dir__) . '/vendor/autoload.php'; // include functions require dirname(__dir__) . '/lib/functions.php'; // include table definitions require dirname(__dir__) . '/lib/tables.inc.php'; use froxlor\database\database; use froxlor\settings; (travis_ci == 0) { database::needroot(true); database::query("drop database exists `froxlor010`;"); database::query("create database `froxlor010`;"); $sql = include(dirname(__dir__) . "/install/froxlor.sql.php"); file_put_contents("/tmp/froxlor.sql", $sql); exec("mysql -u root -p" . $rpwd . " froxlor010 &lt; /tmp/froxlor.sql"); database::query("drop user exists 'test1sql1'@'localhost';"); database::query("drop user exists 'test1sql1'@'127.0.0.1';"); database::query("drop user exists 'test1sql1'@'172.17.0.1';"); database::query("drop user exists 'test1sql1'@'82.149.225.46';"); database::query("drop user exists 'test1sql1'@'2a01:440:1:12:82:149:225:46';"); database::query("drop user exists 'test1_abc123'@'localhost';"); database::query("drop user exists 'test1_abc123'@'127.0.0.1';"); database::query("drop user exists 'test1_abc123'@'172.17.0.1';"); database::query("drop user exists 'test1_abc123'@'82.149.225.46';"); database::query("drop user exists 'test1_abc123'@'2a01:440:1:12:82:149:225:46';"); database::query("drop database exists `test1sql1`;"); database::query("drop database exists `test1_abc123`;"); database::needroot(false); } // clear tables database::query("truncate table `" . table_panel_customers . "`;"); database::query("truncate table `" . table_panel_domains . "`;"); database::query("truncate table `" . table_domaintoip . "`;"); database::query("truncate table `" . table_domain_dns . "`;"); database::query("truncate table `" . table_ftp_users . "`;"); database::query("truncate table `" . table_ftp_groups . "`;"); database::query("truncate table `" . table_ftp_quotatallies . "`;"); database::query("truncate table `" . table_mail_virtual . "`;"); database::query("truncate table `" . table_mail_users . "`;"); database::query("truncate table `" . table_panel_diskspace . "`;"); database::query("truncate table `" . table_panel_traffic . "`;"); database::query("truncate table `" . table_panel_traffic_admins . "`;"); database::query("truncate table `" . table_panel_tasks . "`;"); database::query("truncate table `" . table_panel_log . "`;"); database::query("truncate table `" . table_panel_htpasswds . "`;"); database::query("truncate table `" . table_panel_htaccess . "`;"); database::query("truncate table `" . table_panel_domain_ssl_settings . "`;"); database::query("truncate table `" . table_panel_domainredirects . "`;"); database::query("truncate table `" . table_panel_admins . "`;"); database::query("truncate table `" . table_panel_ipsandports . "`;"); database::query("truncate table `" . table_api_keys . "`;"); database::query("truncate table `" . table_panel_databases . "`;"); database::query("alter table `" . table_panel_fpmdaemons . "` auto_increment=2;"); // add superadmin database::query("insert `" . table_panel_admins . "` set `loginname` = 'admin', `password` = '" . \froxlor\system\crypt::makecryptpassword('admin') . "', `name` = 'froxlor-administrator', `email` = 'admin@dev.froxlor.org', `def_language` = 'english', `customers` = -1, `customers_see_all` = 1, `caneditphpsettings` = 1, `domains` = -1, `change_serversettings` = 1, `diskspace` = -1024, `mysqls` = -1, `emails` = -1, `email_accounts` = -1, `email_forwarders` = -1, `email_quota` = -1, `ftps` = -1, `subdomains` = -1, `traffic` = -1048576, `ip` = -1 "); $adminid = database::lastinsertid(); // add api-key database::query("insert `" . table_api_keys . "` set `adminid` = '1', `customerid` = '0', `apikey` = 'test', `secret` = 'test', `valid_until` = -1, `allowed_from` = '' "); // add first ip (system default) database::query("insert `" . table_panel_ipsandports . "` set `ip` = '82.149.225.46', `port` = '80', `listen_statement` = '0', `namevirtualhost_statement` = '0', `vhostcontainer` = '1', `vhostcontainer_servername_statement` = '1', `specialsettings` = '', `ssl` = '0' "); $defaultip = database::lastinsertid(); settings::set('system.defaultip', $defaultip, true); // add ssl ip (system default) database::query("insert `" . table_panel_ipsandports . "` set `ip` = '82.149.225.56', `port` = '443', `listen_statement` = '0', `namevirtualhost_statement` = '0', `vhostcontainer` = '1', `vhostcontainer_servername_statement` = '1', `specialsettings` = '', `ssl` = '1' "); $defaultip = database::lastinsertid(); settings::set('system.defaultsslip', $defaultip, true); // get userdata admin 'admin' $sel_stmt = database::prepare("select * `" . table_panel_admins . "` `adminid` = '1'"); $admin_userdata = database::pexecute_first($sel_stmt); $admin_userdata['adminsession'] = 1; $log = \froxlor\froxlorlogger::getinstanceof($admin_userdata); settings::set('panel.standardlanguage', 'english', true); settings::set('panel.adminmail', 'admin@dev.froxlor.org', true); settings::set('panel.allow_domain_change_admin', '1', true); settings::set('panel.allow_domain_change_customer', '1', true); settings::set('system.lastguid', '10000', true); settings::set('system.ipaddress', '82.149.225.46', true); settings::set('system.documentroot_use_default_value', '1', true); settings::set('system.hostname', 'dev.froxlor.org', true); settings::set('system.nameservers', 'dev.froxlor.org', true); settings::set('system.mysql_access_host', 'localhost,127.0.0.1,172.17.0.1,2a01:440:1:12:82:149:225:46,82.149.225.46', true); settings::set('system.use_ssl', '1', true); settings::set('system.froxlordirectlyviahostname', '1', true); settings::set('system.dns_createhostnameentry', '1', true); settings::set('system.bind_enable', '1', true); settings::set('system.dnsenabled', '1', true); settings::set('system.dns_server', 'powerdns', true); settings::set('phpfpm.enabled', '1', true); settings::set('phpfpm.enabled_ownvhost', '1', true); settings::set('system.update_channel', 'testing', true);</file><file name="tests/Traffic/TrafficTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\database\database; use froxlor\api\commands\customers; use froxlor\api\commands\traffic; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\traffic * @covers \froxlor\api\commands\customers * @covers \froxlor\api\commands\admins */ class traffictest extends testcase { public static function setupbeforeclass(): void { $ins_stmt = database::prepare(" insert `" . table_panel_traffic . "` set `customerid` = :cid, `year` = :y, `month` = :m, `day` = :d, `stamp` = :ts, `http` = :http, `ftp_up` = :fup, `ftp_down` = :fdown, `mail` = :mail "); $ins_adm_stmt = database::prepare(" insert `" . table_panel_traffic_admins . "` set `adminid` = :aid, `year` = :y, `month` = :m, `day` = :d, `stamp` = :ts, `http` = :http, `ftp_up` = :fup, `ftp_down` = :fdown, `mail` = :mail "); $http = 5 * 1024 * 1024 * 1024; // 5 gb $fup = 50 * 1024 * 1024; // 50 mb $fdown = 2 * 1024 * 1024 * 1024; // 2 gb $mail = 250 * 1024 * 1024; // 250 mb foreach (array( 1, 2, 3 ) $cid) { database::pexecute($ins_stmt, array( 'cid' =&gt; $cid, 'y' =&gt; date('y'), 'm' =&gt; date('m'), 'd' =&gt; date('d'), 'ts' =&gt; time(), 'http' =&gt; $http, 'fup' =&gt; $fup, 'fdown' =&gt; $fdown, 'mail' =&gt; $mail )); } database::pexecute($ins_adm_stmt, array( 'aid' =&gt; 1, 'y' =&gt; date('y'), 'm' =&gt; date('m'), 'd' =&gt; date('d'), 'ts' =&gt; time(), 'http' =&gt; $http * 2, 'fup' =&gt; $fup * 2, 'fdown' =&gt; $fdown * 2, 'mail' =&gt; $mail * 2 )); } public function testadmintrafficlist() { global $admin_userdata; $json_result = traffic::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $http = 2 * (5 * 1024 * 1024 * 1024 * 1024); // 2x 5 gb $this-&gt;assertequals($http, $result['list'][0]['http']); $this-&gt;expectexceptioncode(303); $this-&gt;expectexceptionmessage("you cannot count traffic data list"); traffic::getlocal($admin_userdata)-&gt;listingcount(); } public function testadmintrafficlistspecificdate() { global $admin_userdata; $json_result = traffic::getlocal($admin_userdata, array( 'year' =&gt; date('y') + 1, 'month' =&gt; date('m'), 'day' =&gt; date('d') ))-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(0, $result['count']); } public function testadmintrafficlistcustomers() { global $admin_userdata; $json_result = traffic::getlocal($admin_userdata, array( 'customer_traffic' =&gt; 1 ))-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['count']); $this-&gt;assertequals(1, $result['list'][0]['customerid']); $this-&gt;assertequals(3, $result['list'][1]['customerid']); } public function testadmintrafficlistcustomersfiltercustomer() { global $admin_userdata; $json_result = traffic::getlocal($admin_userdata, array( 'customer_traffic' =&gt; 1, 'loginname' =&gt; 'test1' ))-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertequals(1, $result['list'][0]['customerid']); } public function testcustomertrafficlist() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = traffic::getlocal($customer_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $mail = 250 * 1024 * 1024 * 1024; // 250 mb $this-&gt;assertequals($mail, $result['list'][0]['mail']); $this-&gt;expectexceptioncode(303); $this-&gt;expectexceptionmessage("you cannot count traffic data list"); traffic::getlocal($admin_userdata)-&gt;listingcount(); } public function testadmintrafficadd() { global $admin_userdata; $this-&gt;expectexceptioncode(303); $this-&gt;expectexceptionmessage("you cannot add traffic data"); traffic::getlocal($admin_userdata)-&gt;add(); } public function testadmintrafficget() { global $admin_userdata; $this-&gt;expectexceptioncode(303); $this-&gt;expectexceptionmessage("to get specific traffic details use year, month and/or day parameter traffic.listing()"); traffic::getlocal($admin_userdata)-&gt;get(); } public function testadmintrafficupdate() { global $admin_userdata; $this-&gt;expectexceptioncode(303); $this-&gt;expectexceptionmessage("you cannot update traffic data"); traffic::getlocal($admin_userdata)-&gt;update(); } public function testadmintrafficdelete() { global $admin_userdata; $this-&gt;expectexceptioncode(303); $this-&gt;expectexceptionmessage("you cannot delete traffic data"); traffic::getlocal($admin_userdata)-&gt;delete(); } }</file><file name="tests/Froxlor/IPToolsTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\system\iptools; /** * * @covers \froxlor\system\iptools */ class iptoolstest extends testcase { public function testvalidateipv6() { $result = iptools::is_ipv6('1.1.1.1/4'); $this-&gt;assertfalse($result); $result = iptools::is_ipv6('1.1.1.1'); $this-&gt;assertfalse($result); $result = iptools::is_ipv6('::ffff:10.20.30.40'); $this-&gt;assertequals('::ffff:10.20.30.40', $result); $result = iptools::is_ipv6('2620:0:2d0:200::7/32'); $this-&gt;assertfalse($result); $result = iptools::is_ipv6('2620:0:2d0:200::7'); $this-&gt;assertequals('2620:0:2d0:200::7', $result); } public function testvalidateipinrange() { $result = iptools::ip_in_range([0=&gt;'82.149.225.46',1=&gt;24], '123.213.132.1'); $this-&gt;assertfalse($result); $result = iptools::ip_in_range([0=&gt;'82.149.225.46',1=&gt;24], '2620:0:2d0:200::7'); $this-&gt;assertfalse($result); $result = iptools::ip_in_range([0=&gt;'82.149.225.46',1=&gt;24], '82.149.225.152'); $this-&gt;asserttrue($result); $result = iptools::ip_in_range([0=&gt;'2620:0:2d0:200::1',1=&gt;116], '2620:0:2d0:200::fff1'); $this-&gt;assertfalse($result); $result = iptools::ip_in_range([0=&gt;'2620:0:2d0:200::1',1=&gt;64], '2620:0:2d0:200::fff1'); $this-&gt;asserttrue($result); } }</file><file name="tests/Froxlor/SettingsTest.php">&lt;?php use phpunit\framework\testcase; /** * * @covers \froxlor\settings * @covers \froxlor\settings\froxlorvhostsettings */ class settingstest extends testcase { protected function setup(): void { // start fresh \froxlor\settings::stash(); } public function testsettingget() { $syshostname = \froxlor\settings::get('system.hostname'); $this-&gt;assertequals("dev.froxlor.org", $syshostname); } public function testsettinggetnoseparator() { $nullval = \froxlor\settings::get('system'); $this-&gt;assertnull($nullval); } public function testsettinggetunknown() { $nullval = \froxlor\settings::get('thissetting.doesnotexist'); $this-&gt;assertnull($nullval); } public function testsettingsaddnew() { \froxlor\settings::addnew('temp.setting', 'empty'); $actval = \froxlor\settings::get('temp.setting'); $this-&gt;assertequals("empty", $actval); } public function testsettingsaddnewsettingexists() { $result = \froxlor\settings::addnew('system.ipaddress', '127.0.0.1'); $this-&gt;assertfalse($result); } /** * * @depends testsettingsaddnew */ public function testsettingsetnosave() { $actval = \froxlor\settings::get('temp.setting'); $this-&gt;assertequals("empty", $actval); \froxlor\settings::set('temp.setting', 'temp-value', false); $tmpval = \froxlor\settings::get('temp.setting'); $this-&gt;assertequals("temp-value", $tmpval); \froxlor\settings::stash(); $actval = \froxlor\settings::get('temp.setting'); $this-&gt;assertequals("empty", $actval); } /** * * @depends testsettingsaddnew */ public function testsettingssetinstantsave() { \froxlor\settings::set('temp.setting', 'temp-value'); \froxlor\settings::stash(); $tmpval = \froxlor\settings::get('temp.setting'); $this-&gt;assertequals("temp-value", $tmpval); } /** * * @depends testsettingsaddnew */ public function testsettingssetflushsave() { \froxlor\settings::set('temp.setting', 'another-temp-value', false); \froxlor\settings::flush(); $actval = \froxlor\settings::get('temp.setting'); $this-&gt;assertequals("another-temp-value", $actval); } public function testsettingsisinlist() { $result = \froxlor\settings::isinlist("system.mysql_access_host", "localhost"); $this-&gt;asserttrue($result); $result = \froxlor\settings::isinlist("system.mysql_access_host", "my-super-domain.de"); $this-&gt;assertfalse($result); } public function testfroxlorvhostsettings() { // bootstrap.php adds two ips, one ssl one non-ssl vhostcontainer = 1 $result = \froxlor\settings\froxlorvhostsettings::hasvhostcontainerenabled(false); $this-&gt;asserttrue($result); $result = \froxlor\settings\froxlorvhostsettings::hasvhostcontainerenabled(true); $this-&gt;asserttrue($result); // disable \froxlor\database\database::query("update `". table_panel_ipsandports . "` set `vhostcontainer` = '0'"); $result = \froxlor\settings\froxlorvhostsettings::hasvhostcontainerenabled(false); $this-&gt;assertfalse($result); $result = \froxlor\settings\froxlorvhostsettings::hasvhostcontainerenabled(true); $this-&gt;assertfalse($result); // change back \froxlor\database\database::query("update `". table_panel_ipsandports . "` set `vhostcontainer` = '1'"); } }</file><file name="tests/Froxlor/ValidateTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\validate\validate; /** * * @covers \froxlor\validate\validate * @covers \froxlor\ui\response * @covers \froxlor\froxlorlogger * @covers \froxlor\idna\idnawrapper */ class validatetest extends testcase { public function testvalidate() { $teststr = validate::validate("user input", "test-field", '', '', [], true); $this-&gt;assertequals("user input", $teststr); } public function testvalidatestrinemptydefault() { $teststr = validate::validate("user input", "test-field", '', '', [ "user test", "user input", "user bla" ], true); $this-&gt;assertequals("user input", $teststr); } public function testvalidateemptydefaultnoarray() { $teststr = validate::validate("user input", "test-field", '', '', "user input", true); $this-&gt;assertequals("user input", $teststr); } public function testvalidateremovenotallowedchar() { $teststr = validate::validate("user " . php_eol . "input", "test-field", '', '', [], true); $this-&gt;assertequals("user input", $teststr); } public function testvalidatestringformaterror() { $this-&gt;expectexception("exception"); $this-&gt;expectexceptioncode(400); validate::validate("user input", "test-field", '/^[a-z]+$/i', '', [], true); } public function testvalidateip() { $result = validate::validate_ip2("12.34.56.78", false, 'invalidip', false, false, false, false, true); $this-&gt;assertequals("12.34.56.78", $result); } public function testvalidateipprivnotallowed() { $this-&gt;expectexception("exception"); $this-&gt;expectexceptioncode(400); validate::validate_ip2("10.0.0.1", false, 'invalidip', false, false, false, false, true); } public function testvalidateipprivnotallowedbool() { $result = validate::validate_ip2("10.0.0.1", true, 'invalidip', false, false, false, false, true); $this-&gt;assertfalse($result); } public function testvalidateipcidrnotallowed() { $this-&gt;expectexception("exception"); $this-&gt;expectexceptioncode(400); validate::validate_ip2("12.34.56.78/24", false, 'invalidip', false, false, false, false, true); } public function testvalidateipcidrnotallowedbool() { $result = validate::validate_ip2("12.34.56.78/24", true, 'invalidip', false, false, false, false, true); $this-&gt;assertfalse($result); } public function testvalidateipcidr() { $result = validate::validate_ip2("12.34.56.78/24", false, 'invalidip', false, false, true, false, true); $this-&gt;assertequals("12.34.56.78/24", $result); } public function testvalidateipv6disallowed() { $this-&gt;expectexception("exception"); $this-&gt;expectexceptioncode(400); validate::validate_ip2("2620:0:2d0:200::7/32", false, 'invalidip', false, false, true, true, true); } public function testvalidateiplocalhostallowed() { $result = validate::validate_ip2("127.0.0.1/32", false, 'invalidip', true, false, true, false, true); $this-&gt;assertequals("127.0.0.1/32", $result); } public function testvalidatecidrnoationtonetmasknotationipv4() { $result = validate::validate_ip2("1.1.1.1/4", false, 'invalidip', true, false, true, true, true); $this-&gt;assertequals("1.1.1.1/240.0.0.0", $result); $result = validate::validate_ip2("8.8.8.8/18", false, 'invalidip', true, false, true, true, true); $this-&gt;assertequals("8.8.8.8/255.255.192.0", $result); $result = validate::validate_ip2("8.8.8.8/1", false, 'invalidip', true, false, true, true, true); $this-&gt;assertequals("8.8.8.8/128.0.0.0", $result); } public function testvalidateiplocalhostallowedwrongip() { $this-&gt;expectexception("exception"); $this-&gt;expectexceptioncode(400); validate::validate_ip2("127.0.0.2", false, 'invalidip', true, false, false, false, true); } public function testvalidateurl() { $result = validate::validateurl("https://froxlor.org/"); $this-&gt;asserttrue($result); $result = validate::validateurl("https://froxlor.org/", true); $this-&gt;asserttrue($result); $result = validate::validateurl("http://forum.froxlor.org/"); $this-&gt;asserttrue($result); $result = validate::validateurl("https://api.froxlor.org/doc/0.10.0/index.php"); $this-&gt;asserttrue($result); $result = validate::validateurl("https://api.froxlor.org/doc/0.10.0/index.php", true); $this-&gt;asserttrue($result); $result = validate::validateurl("#froxlor"); $this-&gt;assertfalse($result); $result = validate::validateurl("https://82.149.225.211/"); $this-&gt;asserttrue($result); $result = validate::validateurl("https://82.149.225.211/", true); $this-&gt;asserttrue($result); $result = validate::validateurl("https://82.149.225.300"); $this-&gt;assertfalse($result); $result = validate::validateurl("82.149.225.211:443"); $this-&gt;asserttrue($result); $result = validate::validateurl("172.16.0.1:8080"); $this-&gt;assertfalse($result); $result = validate::validateurl("172.16.0.1:8080", true); $this-&gt;asserttrue($result); } public function testvalidatedomain() { $result = validate::validatedomain('froxlor.org'); $this-&gt;assertequals('froxlor.org', $result); $result = validate::validatedomain('_dmarc.froxlor.org'); $this-&gt;assertfalse($result); $result = validate::validatedomain('_dmarc.froxlor.org', true); $this-&gt;assertequals('_dmarc.froxlor.org', $result); $result = validate::validatedomain('test._dmarc.froxlor.org', true); $this-&gt;assertequals('test._dmarc.froxlor.org', $result); $result = validate::validatedomain('0815'); $this-&gt;assertfalse($result); $result = validate::validatedomain('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'); $this-&gt;assertfalse($result); } public function testvalidatehostname() { $result = validate::validatelocalhostname('localhost'); $this-&gt;assertequals('localhost', $result); $result = validate::validatelocalhostname('froxlor-srv02'); $this-&gt;assertequals('froxlor-srv02', $result); $result = validate::validatelocalhostname('froxlor_org'); $this-&gt;assertfalse($result); $result = validate::validatelocalhostname('froxlor.org'); $this-&gt;assertfalse($result); $result = validate::validatelocalhostname('a--------------------------------------------------------------'); $this-&gt;assertequals('a--------------------------------------------------------------', $result); $result = validate::validatelocalhostname('-hostname'); $this-&gt;assertfalse($result); $result = validate::validatelocalhostname('a-----------------------------------------------------------------'); $this-&gt;assertfalse($result); } public function testvalidateemail() { $result = validate::validateemail('team@froxlor.org'); $this-&gt;assertequals('team@froxlor.org', $result); $result = validate::validateemail('team.froxlor.org'); $this-&gt;assertfalse($result); } public function testvalidateusername() { $result = validate::validateusername('web123sql2'); $this-&gt;asserttrue($result); $mysql_max = \froxlor\database\database::getsqlusernamelength() - strlen(\froxlor\settings::get('customer.mysqlprefix')); $result = validate::validateusername('web123sql2', true, $mysql_max); $this-&gt;asserttrue($result); // long $result = validate::validateusername('myperfectsuperduperwebuserwhosnameisenormouslylongandprettyandshouldinnowaybeaccepted123sql2', true, $mysql_max); $this-&gt;assertfalse($result); // unix-conform $result = validate::validateusername('web123-sql2', true, $mysql_max); $this-&gt;assertfalse($result); // non-unix-conform $result = validate::validateusername('web123-sql2', false, $mysql_max); $this-&gt;asserttrue($result); $result = validate::validateusername('web123--sql2', false, $mysql_max); $this-&gt;assertfalse($result); $result = validate::validateusername('-web123sql2', false, $mysql_max); $this-&gt;assertfalse($result); $result = validate::validateusername('web123sql2-', false, $mysql_max); $this-&gt;assertfalse($result); } public function testvalidatesqlinterval() { $result = validate::validatesqlinterval('60 hour'); $this-&gt;asserttrue($result); $result = validate::validatesqlinterval('2 month'); $this-&gt;asserttrue($result); $result = validate::validatesqlinterval(); $this-&gt;assertfalse($result); $result = validate::validatesqlinterval('2 quarter'); $this-&gt;assertfalse($result); $result = validate::validatesqlinterval('1day'); $this-&gt;assertfalse($result); } }</file><file name="tests/Froxlor/FroxlorTest.php">&lt;?php use froxlor\api\commands\froxlor; use phpunit\framework\testcase; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\froxlor */ class froxlortest extends testcase { public function testfroxlorcheckupdate() { global $admin_userdata; $json_result = froxlor::getlocal($admin_userdata)-&gt;checkupdate(); $result = json_decode($json_result, true)['data']; $this-&gt;assertcontains($result['isnewerversion'] ?? -1, [0, 1]); $this-&gt;assertnotempty($result['version']); } }</file><file name="tests/Froxlor/StoreTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\settings; use froxlor\api\commands\customers; use froxlor\database\database; use froxlor\settings\store; /** * * @covers \froxlor\settings\store */ class storetest extends testcase { public function teststoresettingclearcertificates() { // froxlor vhost setting "use lets encrypt" set false, corresponding // certificate needs cleaned // testing purposes, let's add entry table database::query("insert `domain_ssl_settings` set `domainid` = '0', `ssl_cert_file` = 'test-content'"); $fielddata = array( 'label' =&gt; 'le_froxlor_enabled', 'settinggroup' =&gt; 'system', 'varname' =&gt; 'le_froxlor_enabled' ); store::storesettingclearcertificates('system_le_froxlor_enabled', $fielddata, 0); // entry domain_ssl_settings $result = database::query("select count(*) entries `domain_ssl_settings` `domainid` = '0'"); $result = $result-&gt;fetch(\pdo::fetch_assoc); $this-&gt;assertequals(0, (int) $result['entries']); // truncate table tests database::query("truncate table `" . table_panel_domain_ssl_settings . "`;"); } public function teststoresettingdefaultip() { global $admin_userdata; // customer std-subdomin customers::getlocal($admin_userdata, array( 'id' =&gt; 1, 'createstdsubdomain' =&gt; 1 ))-&gt;update(); // need second non-ssl ip database::query("insert `panel_ipsandports` set `ip` = '82.149.225.47', `port` = '80'"); $ip_id = database::lastinsertid(); $default_ip = settings::get('system.defaultip'); // get std-subdomains $customerstddomains_result_stmt = database::prepare(" select `standardsubdomain` `" . table_panel_customers . "` `standardsubdomain` &lt;&gt; '0' "); database::pexecute($customerstddomains_result_stmt); $ids = array(); ($customerstddomains_row = $customerstddomains_result_stmt-&gt;fetch(\pdo::fetch_assoc)) { $ids[] = (int) $customerstddomains_row['standardsubdomain']; } (count($ids) &lt;= 0) { $this-&gt;fail("there customer std-subdomains test make sense"); } // check current default ip set $sel_stmt = database::prepare(" select * `" . table_domaintoip . "` `id_domain` (" . implode(', ', $ids) . ") `id_ipandports` = :ipid "); database::pexecute($sel_stmt, array('ipid' =&gt; $default_ip)); $current_result = $sel_stmt-&gt;fetchall(\pdo::fetch_assoc); // assume entries $this-&gt;asserttrue(count($current_result) &gt; 0); $fielddata = array( 'label' =&gt; 'serversettingsipaddress', 'settinggroup' =&gt; 'system', 'varname' =&gt; 'defaultip' ); store::storesettingdefaultip('serversettings_ipaddress', $fielddata, $ip_id); // check current default ip set anymore database::pexecute($sel_stmt, array('ipid' =&gt; $default_ip)); $current_result = $sel_stmt-&gt;fetchall(\pdo::fetch_assoc); // assume entries $this-&gt;asserttrue(count($current_result) == 0); // check new default ip set database::pexecute($sel_stmt, array('ipid' =&gt; $ip_id)); $current_result = $sel_stmt-&gt;fetchall(\pdo::fetch_assoc); // assume entries $this-&gt;asserttrue(count($current_result) &gt; 0); } public function teststoresettingdefaulttheme() { $current_theme = settings::get('panel.default_theme'); // allow theme changing admins/customers new default overwrite settings::set('panel.allow_theme_change_customer', 1); settings::set('panel.allow_theme_change_admin', 1); $fielddata = array( 'label' =&gt; 'panel_default_theme', 'settinggroup' =&gt; 'panel', 'varname' =&gt; 'default_theme' ); store::storesettingdefaulttheme('panel_default_theme', $fielddata, "newtheme"); $this-&gt;asserttrue($current_theme != settings::get('panel.default_theme')); $this-&gt;assertequals("newtheme", settings::get('panel.default_theme')); // validate admin/customer field change $sel_stmt = database::prepare(" select * `" . table_panel_admins . "` `theme` = :newtheme "); database::pexecute($sel_stmt, array('newtheme' =&gt; "newtheme")); $current_result = $sel_stmt-&gt;fetchall(\pdo::fetch_assoc); // assume entries $this-&gt;asserttrue(count($current_result) == 0); $sel_stmt = database::prepare(" select * `" . table_panel_customers . "` `theme` = :newtheme "); database::pexecute($sel_stmt, array('newtheme' =&gt; "newtheme")); $current_result = $sel_stmt-&gt;fetchall(\pdo::fetch_assoc); // assume entries $this-&gt;asserttrue(count($current_result) == 0); // allow changing themes theme get updated admins/customers // allow theme changing admins/customers new default overwrite settings::set('panel.allow_theme_change_customer', 0); settings::set('panel.allow_theme_change_admin', 0); store::storesettingdefaulttheme('panel_default_theme', $fielddata, "newtheme"); // validate admin/customer field change $sel_stmt = database::prepare(" select * `" . table_panel_admins . "` `theme` = :newtheme "); database::pexecute($sel_stmt, array('newtheme' =&gt; "newtheme")); $current_result = $sel_stmt-&gt;fetchall(\pdo::fetch_assoc); // assume entries $this-&gt;asserttrue(count($current_result) &gt; 0); $sel_stmt = database::prepare(" select * `" . table_panel_customers . "` `theme` = :newtheme "); database::pexecute($sel_stmt, array('newtheme' =&gt; "newtheme")); $current_result = $sel_stmt-&gt;fetchall(\pdo::fetch_assoc); // assume entries $this-&gt;asserttrue(count($current_result) &gt; 0); // set back default store::storesettingdefaulttheme('panel_default_theme', $fielddata, $current_theme); } }</file><file name="tests/Mysqls/MysqlsTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\settings; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\mysqls; use froxlor\api\commands\mysqlserver; use froxlor\database\database; use froxlor\settings\store; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\mysqls * @covers \froxlor\api\commands\mysqlserver * @covers \froxlor\api\commands\customers * @covers \froxlor\api\commands\admins * @covers \froxlor\database\dbmanager * @covers \froxlor\database\manager\dbmanagermysql * @covers \froxlor\settings\store */ class mysqlstest extends testcase { public function testcustomermysqlsadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $newpwd = \froxlor\system\crypt::generatepassword(); $data = [ 'mysql_password' =&gt; $newpwd, 'description' =&gt; 'testdb', 'sendinfomail' =&gt; travis_ci == 1 ? 0 : 1 ]; $json_result = mysqls::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('testdb', $result['description']); $this-&gt;assertequals(0, $result['dbserver']); // test connection try { $test_conn = new \pdo("mysql:host=127.0.0.1", 'test1sql1', $newpwd); unset($test_conn); } catch (pdoexception $e) { $this-&gt;fail($e-&gt;getmessage()); } } public function testcustomermysqlsdbnameadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; // set customer.mysqlprefix dbname settings::set('customer.mysqlprefix', 'dbname'); $newpwd = \froxlor\system\crypt::generatepassword(); $data = [ 'mysql_password' =&gt; $newpwd, 'custom_suffix' =&gt; 'abc123', 'description' =&gt; 'testdb', 'sendinfomail' =&gt; travis_ci == 1 ? 0 : 1 ]; $json_result = mysqls::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test1_abc123', $result['databasename']); $this-&gt;assertequals(0, $result['dbserver']); // test connection try { $test_conn = new \pdo("mysql:host=127.0.0.1", 'test1_abc123', $newpwd); unset($test_conn); } catch (pdoexception $e) { $this-&gt;fail($e-&gt;getmessage()); } } /** * * @depends testcustomermysqlsadd */ public function testadminmysqlsget() { global $admin_userdata; $json_result = mysqls::getlocal($admin_userdata, array( 'dbname' =&gt; 'test1sql1' ))-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test1sql1', $result['databasename']); $this-&gt;assertequals('testdb', $result['description']); } /** * * @depends testcustomermysqlsadd */ public function testresellermysqlsget() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $json_result = mysqls::getlocal($reseller_userdata, array( 'dbname' =&gt; 'test1sql1' ))-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test1sql1', $result['databasename']); $this-&gt;assertequals('testdb', $result['description']); } public function testcustomermysqlsgetunknown() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'dbname' =&gt; 'test1sql5' ]; $this-&gt;expectexceptioncode(404); $this-&gt;expectexceptionmessage("mysql database dbname 'test1sql5' could found"); mysqls::getlocal($customer_userdata, $data)-&gt;get(); } /** * * @depends testcustomermysqlsadd */ public function testadminmysqlsupdate() { global $admin_userdata; $newpwd = \froxlor\system\crypt::generatepassword(); $data = [ 'dbname' =&gt; 'test1sql1', 'mysql_password' =&gt; $newpwd, 'description' =&gt; 'testdb-upd', 'loginname' =&gt; 'test1' ]; $json_result = mysqls::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('testdb-upd', $result['description']); // test connection try { $test_conn = new \pdo("mysql:host=127.0.0.1", 'test1sql1', $newpwd); unset($test_conn); } catch (pdoexception $e) { $this-&gt;fail($e-&gt;getmessage()); } } /** * * @depends testcustomermysqlsadd */ public function testadminmysqlsupdatepwdonly() { global $admin_userdata; $newpwd = \froxlor\system\crypt::generatepassword(); $data = [ 'dbname' =&gt; 'test1sql1', 'mysql_password' =&gt; $newpwd, 'loginname' =&gt; 'test1' ]; $json_result = mysqls::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('testdb-upd', $result['description']); } /** * * @depends testcustomermysqlsadd */ public function testcustomermysqlslist() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = mysqls::getlocal($customer_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['count']); $this-&gt;assertequals('test1sql1', $result['list'][0]['databasename']); $this-&gt;assertequals('test1_abc123', $result['list'][1]['databasename']); $json_result = mysqls::getlocal($customer_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result); $data = [ 'mysql_server' =&gt; '0' ]; $json_result = mysqlserver::getlocal($admin_userdata, $data)-&gt;databasesonserver(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('2', $result['count']); $data = [ 'mysql_server' =&gt; '1' ]; $json_result = mysqlserver::getlocal($admin_userdata, $data)-&gt;databasesonserver(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('0', $result['count']); } /** * @depends testcustomermysqlslist */ public function testupdatecustomerallowedmysqlwithexistingdbs() { global $admin_userdata; $this-&gt;expectexceptionmessage("cannot remove database server customers allow-list still databases it."); // reactivate customer // get customer customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1', 'allowed_mysqlserver' =&gt; [1] ))-&gt;update(); } /** * * @depends testcustomermysqlslist */ public function testcustomermysqlsdelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'dbname' =&gt; 'test1sql1' ]; $json_result = mysqls::getlocal($customer_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test1sql1', $result['databasename']); } /** * * @depends testcustomermysqlslist */ public function testcustomermysqlsdbnamedelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'dbname' =&gt; 'test1_abc123' ]; $json_result = mysqls::getlocal($customer_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test1_abc123', $result['databasename']); } /** * * @depends testcustomermysqlsadd */ public function teststoresettingipaddress() { // settings test directly changes mysql users / privileges $fielddata = array( 'label' =&gt; 'serversettings.ipaddress', 'settinggroup' =&gt; 'system', 'varname' =&gt; 'ipaddress' ); store::storesettingipaddress('system_system_ipaddress', $fielddata, '82.149.225.47'); $mysql_access_hosts = settings::get('system.mysql_access_host'); $this-&gt;asserttrue(strpos($mysql_access_hosts, '82.149.225.47') !== false); } /** * * @depends teststoresettingipaddress */ public function testgetallsqlusers() { \froxlor\database\database::needroot(true); $dbm = new \froxlor\database\dbmanager(\froxlor\froxlorlogger::getinstanceof()); $users = $dbm-&gt;getmanager()-&gt;getallsqlusers(false); foreach ($users $user =&gt; $data) { (strtolower($user) == 'mariadb.sys') { // systems seem user mariadb version 10.4 // want test one continue; } $this-&gt;assertnotempty($data['password'], 'no password user "' . $user . '"'); } (travis_ci == 0) { // sure, required travis vm fresh every time database::needroot(true); database::query("drop user exists froxlor010@10.0.0.10;"); } // grant privileges another host $testdata = $users['froxlor010']; $password = [ 'password' =&gt; $testdata['password'], 'plugin' =&gt; $testdata['plugin'] ]; $dbm-&gt;getmanager()-&gt;grantprivilegesto('froxlor010', $password, '10.0.0.10', true); // select entries mysql.user froxlor010 compare password-hashes $sel_stmt = database::prepare("select * mysql.user `user` = :usr"); database::pexecute($sel_stmt, [ 'usr' =&gt; 'froxlor010' ]); $results = $sel_stmt-&gt;fetchall(\pdo::fetch_assoc); foreach ($results $user) { $passwd = $user['password'] ?? $user['authentication_string']; $this-&gt;assertequals($testdata['password'], $passwd); } } }</file><file name="tests/Mysqls/MysqlServerTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\api\commands\mysqlserver; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\mysqlserver */ class mysqlservertest extends testcase { public function testadminmysqlserveradd() { global $admin_userdata; $data = [ 'mysql_host' =&gt; '192.168.1.254', 'privileged_user' =&gt; 'froxroot', 'privileged_password' =&gt; 'p4ssw0rd', 'description' =&gt; 'second mysql-server', 'test_connection' =&gt; false ]; $json_result = mysqlserver::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['dbserver']); } public function testadminmysqlserveraddinvalidhostorip() { global $admin_userdata; $data = [ 'mysql_host' =&gt; 'abc123+', 'privileged_user' =&gt; 'someone', 'privileged_password' =&gt; 'something' ]; $this-&gt;expectexceptioncode(406); $this-&gt;expectexceptionmessage('invalid mysql server ip/hostname'); mysqlserver::getlocal($admin_userdata, $data)-&gt;add(); } /** * @depends testadminmysqlserveradd */ public function testadminmysqlserverdeletedefault() { global $admin_userdata; $data = [ 'dbserver' =&gt; 0 ]; $this-&gt;expectexceptioncode(406); $this-&gt;expectexceptionmessage('cannot delete first/default mysql-server'); mysqlserver::getlocal($admin_userdata, $data)-&gt;delete(); } /** * @depends testadminmysqlserveradd */ public function testadminmysqlserverdeleteunknown() { global $admin_userdata; $data = [ 'dbserver' =&gt; 1337 ]; $this-&gt;expectexceptioncode(404); $this-&gt;expectexceptionmessage('mysql server found'); mysqlserver::getlocal($admin_userdata, $data)-&gt;delete(); } }</file><file name="tests/Extras/DirProtectionsTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\dirprotections; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\dirprotections */ class dirprotectionstest extends testcase { public function testcustomerdirprotectionsadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'path' =&gt; '/test', 'username' =&gt; 'testing', 'directory_password' =&gt; \froxlor\system\crypt::generatepassword(), 'directory_authname' =&gt; 'test1' ]; $json_result = dirprotections::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'test/', $result['path']); $this-&gt;assertequals('test1', $result['authname']); } public function testcustomerdirprotectionsaddsameuserpath() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'path' =&gt; '/test', 'username' =&gt; 'testing', 'directory_password' =&gt; \froxlor\system\crypt::generatepassword(), 'directory_authname' =&gt; 'test2' ]; $this-&gt;expectexceptionmessage("combination username path already exists"); dirprotections::getlocal($customer_userdata, $data)-&gt;add(); } public function testcustomerdirprotectionsaddpasswordequalsusername() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $up = \froxlor\system\crypt::generatepassword(); $data = [ 'path' =&gt; '/test', 'username' =&gt; $up, 'directory_password' =&gt; $up, 'directory_authname' =&gt; 'test3' ]; $this-&gt;expectexceptionmessage("the password username."); dirprotections::getlocal($customer_userdata, $data)-&gt;add(); } /** * * @depends testcustomerdirprotectionsadd */ public function testadmindirprotectionsget() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'username' =&gt; 'testing', 'customerid' =&gt; 1 ]; $json_result = dirprotections::getlocal($admin_userdata, $data)-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'test/', $result['path']); $this-&gt;assertequals('test1', $result['authname']); } /** * * @depends testcustomerdirprotectionsadd */ public function testresellerdirprotectionsget() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'username' =&gt; 'testing' ]; $json_result = dirprotections::getlocal($reseller_userdata, $data)-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'test/', $result['path']); $this-&gt;assertequals('test1', $result['authname']); } /** * * @depends testcustomerdirprotectionsadd */ public function testcustomerdirprotectionsupdate() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = dirprotections::getlocal($customer_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $data_old = json_decode($json_result, true)['data']; $data = [ 'id' =&gt; 1, 'directory_password' =&gt; \froxlor\system\crypt::generatepassword(), 'directory_authname' =&gt; 'test1337' ]; $json_result = dirprotections::getlocal($customer_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue($data_old['password'] != $result['password']); $this-&gt;asserttrue($data_old['authname'] != $result['authname']); $this-&gt;assertequals('test1337', $result['authname']); } /** * * @depends testcustomerdirprotectionsadd */ public function testcustomerdirprotectionslist() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = dirprotections::getlocal($customer_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['count']); $this-&gt;assertequals('test1', $result['list'][0]['username']); $this-&gt;assertequals('testing', $result['list'][1]['username']); $json_result = dirprotections::getlocal($customer_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result); } /** * * @depends testcustomerdirprotectionslist */ public function testcustomerdirprotectionsdelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; dirprotections::getlocal($customer_userdata, array( 'username' =&gt; 'testing' ))-&gt;delete(); $json_result = dirprotections::getlocal($customer_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertequals('test1', $result['list'][0]['username']); } }</file><file name="tests/Extras/DirOptionsTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\diroptions; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\diroptions */ class diroptionstest extends testcase { public function testcustomerdiroptionsadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'path' =&gt; '/test', 'options_indexes' =&gt; 1, 'options_cgi' =&gt; 1, 'error404path' =&gt; '/404.html', 'error403path' =&gt; '/403.html', 'error500path' =&gt; '/500.html' ]; $json_result = diroptions::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'test/', $result['path']); $this-&gt;assertequals('1', $result['options_cgi']); $this-&gt;assertequals('/403.html', $result['error403path']); } public function testcustomerdiroptionsaddduplicatepath() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'path' =&gt; '/test', 'options_indexes' =&gt; 0, 'options_cgi' =&gt; 0, 'error404path' =&gt; '/404a.html', 'error403path' =&gt; '/403a.html', 'error500path' =&gt; '/500a.html' ]; $this-&gt;expectexceptionmessage("option path /test/ already exists"); diroptions::getlocal($customer_userdata, $data)-&gt;add(); } public function testadmindiroptionsget() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'id' =&gt; 1, 'loginname' =&gt; 'test1' ]; $json_result = diroptions::getlocal($admin_userdata, $data)-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'test/', $result['path']); } public function testresellerdiroptionsget() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'id' =&gt; 1, 'loginname' =&gt; 'test1' ]; $json_result = diroptions::getlocal($reseller_userdata, $data)-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'test/', $result['path']); } public function testcustomerdiroptionsgetnotfound() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'id' =&gt; 1337 ]; $this-&gt;expectexceptionmessage("directory option id #1337 could found"); diroptions::getlocal($admin_userdata, $data)-&gt;get(); } public function testcustomerdiroptionsupdate() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'id' =&gt; 1, 'options_indexes' =&gt; 0, 'options_cgi' =&gt; 0, 'error403path' =&gt; '/403-test.html' ]; $json_result = diroptions::getlocal($customer_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'test/', $result['path']); $this-&gt;assertequals('0', $result['options_cgi']); $this-&gt;assertequals('/403-test.html', $result['error403path']); } public function testadmindiroptionslist() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = diroptions::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertequals($customer_userdata['documentroot'] . 'test/', $result['list'][0]['path']); $json_result = diroptions::getlocal($admin_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result); } /** * * @depends testadmindiroptionslist */ public function testcustomerdiroptionsdelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'id' =&gt; 1 ]; $json_result = diroptions::getlocal($customer_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'test/', $result['path']); $data = [ 'id' =&gt; 1 ]; $this-&gt;expectexceptionmessage("directory option id #1 could found"); diroptions::getlocal($admin_userdata, $data)-&gt;get(); } public function testcustomerdiroptionsaddmalformed() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'path' =&gt; '/testmalformed', 'error404path' =&gt; '/"'.php_eol.'something/../../../../weird 404.html'.php_eol.'#' ]; $json_result = diroptions::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $expected = '/"something/././././weird\ 404.html#'; $this-&gt;assertequals($expected, $result['error404path']); } public function testcustomerdiroptionsaddmalformedinvalid() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'path' =&gt; '/testmalformed', 'error404path' =&gt; '"'.php_eol.'includeoptional /something/else/'.php_eol.'#' ]; $this-&gt;expectexceptionmessage("the value given errordocument seem valid file, url string."); diroptions::getlocal($customer_userdata, $data)-&gt;add(); $data = [ 'path' =&gt; '/testmalformed', 'error404path' =&gt; '"something"oh quote within string"' ]; $this-&gt;expectexceptionmessage("the value given errordocument seem valid file, url string."); diroptions::getlocal($customer_userdata, $data)-&gt;add(); } }</file><file name="tests/IpsAndPorts/IpsAndPortsTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\ipsandports; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\ipsandports */ class ipsandportstest extends testcase { public function testadminipsandportslist() { global $admin_userdata; $json_result = ipsandports::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['count']); $this-&gt;assertequals('82.149.225.46', $result['list'][0]['ip']); $json_result = ipsandports::getlocal($admin_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result); } public function testreselleripsandportslisthasnone() { global $admin_userdata; // update reseller allow ip access $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller', 'ipaddress' =&gt; array() ))-&gt;update(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); $json_result = ipsandports::getlocal($reseller_userdata)-&gt;listing(); } public function testadminipsandportsadd() { global $admin_userdata; $data = [ 'ip' =&gt; '82.149.225.47' ]; $json_result = ipsandports::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(3, $result['id']); $this-&gt;assertequals(80, $result['port']); } /** * * @depends testadminipsandportsadd */ public function testadminipsandportsaddexists() { global $admin_userdata; $this-&gt;expectexceptionmessage("this ip/port combination already exists."); $data = [ 'ip' =&gt; '82.149.225.47' ]; ipsandports::getlocal($admin_userdata, $data)-&gt;add(); } public function testadminipsandportsaddipv6() { global $admin_userdata; $data = [ 'ip' =&gt; '2a01:0440:0000:0012:0082:0149:0225:0046', 'docroot' =&gt; '/var/www/html' ]; $json_result = ipsandports::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('2a01:440:0:12:82:149:225:46', $result['ip']); $this-&gt;assertequals('/var/www/html/', $result['docroot']); } public function testadminipsandportsgetnotfound() { global $admin_userdata; $this-&gt;expectexceptioncode(404); $this-&gt;expectexceptionmessage("ip/port id #999 could found"); ipsandports::getlocal($admin_userdata, array( 'id' =&gt; 999 ))-&gt;get(); } /** * * @depends testadminipsandportsadd */ public function testreselleripsandportslist() { global $admin_userdata; // update reseller allow ip access ip id #3 $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller', 'ipaddress' =&gt; array( 3 ) ))-&gt;update(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $json_result = ipsandports::getlocal($reseller_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertequals('82.149.225.47', $result['list'][0]['ip']); $json_result = ipsandports::getlocal($reseller_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result); } /** * * @depends testreselleripsandportslist */ public function testreselleripsandportsget() { global $admin_userdata; // update reseller allow ip access ip id #2 $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $json_result = ipsandports::getlocal($reseller_userdata, array( 'id' =&gt; 3 ))-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('82.149.225.47', $result['ip']); } /** * * @depends testreselleripsandportslist */ public function testreselleripsandportsgetrestrictednotowned() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $this-&gt;expectexceptioncode(405); $this-&gt;expectexceptionmessage("you cannot access resource"); ipsandports::getlocal($reseller_userdata, array( 'id' =&gt; 1 ))-&gt;get(); } public function testreselleripsandportsadd() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); $data = [ 'ip' =&gt; '82.149.225.48' ]; ipsandports::getlocal($reseller_userdata, $data)-&gt;add(); } public function testcustomeripsandportsgetnotallowed() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); ipsandports::getlocal($customer_userdata, array( 'id' =&gt; 1 ))-&gt;get(); } public function testadminipsandportsedit() { global $admin_userdata; $data = [ 'id' =&gt; 1, 'listen_statement' =&gt; 1, 'docroot' =&gt; '/var/www/html' ]; $json_result = ipsandports::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['listen_statement']); $this-&gt;assertequals('/var/www/html/', $result['docroot']); } public function testreselleripsandportseditnotallowed() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $data = [ 'id' =&gt; 1, 'listen_statement' =&gt; 0 ]; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); ipsandports::getlocal($reseller_userdata, $data)-&gt;update(); } public function testcustomeripsandportseditnotallowed() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'id' =&gt; 1, 'listen_statement' =&gt; 0 ]; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); ipsandports::getlocal($customer_userdata, $data)-&gt;update(); } public function testadminipsandportseditcantchangesystemip() { global $admin_userdata; $data = [ 'id' =&gt; 1, 'ip' =&gt; '123.123.123.123' ]; $this-&gt;expectexceptionmessage("you cannot change last system ip, either create another new ip/port combination system ip change system ip."); ipsandports::getlocal($admin_userdata, $data)-&gt;update(); } public function testadminipsandportsdeletecantdeletedefaultip() { global $admin_userdata; $data = [ 'id' =&gt; 1 ]; $this-&gt;expectexceptionmessage("you cannot delete default ip/port combination, please make another ip/port combination default deleting ip/port combination."); ipsandports::getlocal($admin_userdata, $data)-&gt;delete(); } public function testadminipsandportsdelete() { global $admin_userdata; $data = [ 'id' =&gt; 3 ]; $json_result = ipsandports::getlocal($admin_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('82.149.225.47', $result['ip']); } public function testreselleripsandportsdeletenotallowed() { global $admin_userdata; $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $data = [ 'id' =&gt; 1 ]; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); ipsandports::getlocal($reseller_userdata, $data)-&gt;delete(); } }</file><file name="tests/Ftps/FtpsTest.php">&lt;?php use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\ftps; use froxlor\froxlor; use phpunit\framework\testcase; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\admins * @covers \froxlor\api\commands\customers * @covers \froxlor\api\commands\ftps */ class ftpstest extends testcase { public function testadminftpsgetid() { global $admin_userdata; $json_result = ftps::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $result = json_decode($json_result, true)['data']; // ftp user first added customr 'test1' $this-&gt;assertequals('test1', $result['username']); } public function testresellerftpsgetid() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $json_result = ftps::getlocal($reseller_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test1', $result['username']); } public function testcustomerftpsgetid() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = ftps::getlocal($customer_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $result = json_decode($json_result, true)['data']; // ftp user first added customr 'test1' $this-&gt;assertequals('test1', $result['username']); } public function testcustomerftpsgetotherid() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(404); ftps::getlocal($customer_userdata, array( 'id' =&gt; 10 ))-&gt;get(); } public function testadminftpslist() { global $admin_userdata; $json_result = ftps::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['count']); $json_result = ftps::getlocal($admin_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result); } public function testadminftpslistspecificcustomer() { global $admin_userdata; $json_result = ftps::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertequals('test1', $result['list'][0]['username']); } public function testresellerftpslist() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $json_result = ftps::getlocal($reseller_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertequals('test1', $result['list'][0]['username']); $json_result = ftps::getlocal($reseller_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result); } public function testcustomerftpslist() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = ftps::getlocal($customer_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertequals('test1', $result['list'][0]['username']); $json_result = ftps::getlocal($customer_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result); } public function testcustomerftpsadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'ftp_password' =&gt; 'h4xxx0r', 'path' =&gt; '/', 'ftp_description' =&gt; 'testing', 'sendinfomail' =&gt; travis_ci == 1 ? 0 : 1 ]; $json_result = ftps::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'], $result['homedir']); } public function testcustomerftpsaddsymlinkoutsidehomedir() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; // $customer_userdata['documentroot'] = sys_get_temp_dir() . '/'; @unlink($customer_userdata['documentroot'] . '/frx'); symlink(froxlor::getinstalldir(), $customer_userdata['documentroot'] . '/frx'); $data = [ 'ftp_password' =&gt; 'h4xxx0r', 'path' =&gt; '/frx/sub', 'ftp_description' =&gt; 'testing', 'sendinfomail' =&gt; travis_ci == 1 ? 0 : 1 ]; $this-&gt;expectexceptionmessage('found symlink pointing outside customer home directory: /frx'); ftps::getlocal($customer_userdata, $data)-&gt;add(); } public function testcustomerftpsaddnomoreresources() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; // $customer_userdata['ftps_used'] = 100; $this-&gt;expectexceptioncode(406); $this-&gt;expectexceptionmessage('no resources available'); ftps::getlocal($customer_userdata)-&gt;add(); } public function testadminftpsaddcustomerrequired() { global $admin_userdata; $data = [ 'ftp_password' =&gt; 'h4xxx0r', 'path' =&gt; '/', 'ftp_description' =&gt; 'testing', 'sendinfomail' =&gt; 1 ]; $this-&gt;expectexceptioncode(406); $this-&gt;expectexceptionmessage('requested parameter "loginname" empty "customers:get"'); ftps::getlocal($admin_userdata, $data)-&gt;add(); } public function testcustomerftpsedit() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'username' =&gt; 'test1ftp1', 'ftp_password' =&gt; 'h4xxx0r2', 'path' =&gt; '/subfolder', 'ftp_description' =&gt; 'testing2' ]; $json_result = ftps::getlocal($customer_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'subfolder/', $result['homedir']); $this-&gt;assertequals('testing2', $result['description']); } public function testadminftpsedit() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'username' =&gt; 'test1ftp1', 'customerid' =&gt; 1, 'ftp_password' =&gt; 'h4xxx0r2', 'path' =&gt; '/anotherfolder', 'ftp_description' =&gt; 'testing3' ]; $json_result = ftps::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'anotherfolder/', $result['homedir']); $this-&gt;assertequals('testing3', $result['description']); } public function testadminftpsadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'customerid' =&gt; $customer_userdata['customerid'], 'ftp_password' =&gt; 'h4xxx0r', 'path' =&gt; '/', 'ftp_description' =&gt; 'testing', 'sendinfomail' =&gt; travis_ci == 1 ? 0 : 1 ]; $json_result = ftps::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'], $result['homedir']); } public function testcustomerftpsdelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'username' =&gt; 'test1ftp1' ]; $json_result = ftps::getlocal($customer_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test1ftp1', $result['username']); } public function testadminftpsdelete() { global $admin_userdata; $data = [ 'username' =&gt; 'test1ftp2' ]; $json_result = ftps::getlocal($admin_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test1ftp2', $result['username']); } public function testcustomerftpsdeletedefaultuser() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'username' =&gt; 'test1' ]; $this-&gt;expectexceptioncode(400); $this-&gt;expectexceptionmessage('you cannot delete main ftp account'); ftps::getlocal($customer_userdata, $data)-&gt;delete(); } }</file><file name="tests/DomainZones/DomainZonesTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\settings; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\domainzones; use froxlor\api\commands\domains; use froxlor\api\commands\subdomains; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\subdomains * @covers \froxlor\api\commands\domainzones */ class domainzonestest extends testcase { public function testcustomerdomainzonesget() { global $admin_userdata; settings::set('system.dnsenabled', 1, true); settings::set('system.mxservers', 'mx.hostname.tld', true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'test2.local' ]; $json_result = domainzones::getlocal($customer_userdata, $data)-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $this-&gt;assertequals('$origin test2.local.', $result[1]); $resstr = preg_replace('/\s+/', '', $result[count($result)-2]); $against = preg_replace('/\s+/', '', '@ 604800 mx 10 mx.hostname.tld.'); $this-&gt;assertequals($against, $resstr); } /** * * @depends testcustomerdomainzonesget */ public function testcustomerdomainzonesgetnosubdomains() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'mysub2.test2.local' ]; $this-&gt;expectexceptioncode(406); $this-&gt;expectexceptionmessage("dns zones generated main domain, subdomains"); domainzones::getlocal($customer_userdata, $data)-&gt;get(); } /** * * @depends testcustomerdomainzonesget */ public function testcustomerdomainzonesgetwithdmarc() { global $admin_userdata; settings::set('dmarc.use_dmarc', 1, true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'test2.local' ]; $json_result = domainzones::getlocal($customer_userdata, $data)-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $foundcnt = 0; $foundstr = ''; foreach ($result $entry) { (substr($entry, 0, 7) == '_dmarc ') { $foundcnt++; $foundstr = $entry; } } $this-&gt;assertequals(1, $foundcnt); $resstr = preg_replace('/\s+/', '', $foundstr); $against = preg_replace('/\s+/', '', '_dmarc 604800 txt v=dmarc1;p=none;'); $this-&gt;assertequals($against, $resstr); } /** * * @depends testcustomerdomainzonesgetwithdmarc */ public function testcustomerdomainzonesgetwithdmarcsubdomain() { global $admin_userdata; // enable isemaildomain subdomain $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $data = [ 'domainname' =&gt; 'mysub2.test2.local', 'isemaildomain' =&gt; 1, 'customerid' =&gt; 1 ]; $json_result = subdomains::getlocal($reseller_userdata, $data)-&gt;update(); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'test2.local' ]; $json_result = domainzones::getlocal($customer_userdata, $data)-&gt;get(); $result = json_decode($json_result, true)['data']; $foundcnt = 0; $foundstr = ''; $this-&gt;asserttrue(count($result) &gt; 1); foreach ($result $entry) { (substr($entry, 0, 14) == '_dmarc.mysub2 ') { $foundcnt++; $foundstr = $entry; } } $this-&gt;assertequals(1, $foundcnt); $resstr = preg_replace('/\s+/', '', $foundstr); $against = preg_replace('/\s+/', '', '_dmarc.mysub2 604800 txt v=dmarc1;p=none;'); $this-&gt;assertequals($against, $resstr); } public function testadmindomainzonesupdate() { global $admin_userdata; $this-&gt;expectexceptioncode(303); domainzones::getlocal($admin_userdata)-&gt;update(); } /** * * @depends testcustomerdomainzonesget */ public function testcustomerdomainzonesadda() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; 'www2', 'type' =&gt; 'a', 'content' =&gt; '127.0.0.1' ]; $json_result = domainzones::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, 0, 4) == 'www2') { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('www2 18000 127.0.0.1', $entry); } /** * * @depends testcustomerdomainzonesadda */ public function testadmindomainzoneslisting() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; 'www2', 'type' =&gt; 'a', 'content' =&gt; '127.0.0.1' ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertequals('www2', $result['list'][0]['record']); $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result); } /** * * @depends testcustomerdomainzonesadda */ public function testcustomerdomainzonesaddainvalid() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; 'www3', 'type' =&gt; 'a', 'content' =&gt; 'a.b.c.d', 'ttl' =&gt; - 1 ]; $this-&gt;expectexceptionmessage("no valid ip address a-record given"); domainzones::getlocal($customer_userdata, $data)-&gt;add(); } /** * * @depends testcustomerdomainzonesadda */ public function testcustomerdomainzonesaddaduplicate() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; 'www2', 'type' =&gt; 'a', 'content' =&gt; '127.0.0.1', 'ttl' =&gt; - 1 ]; $this-&gt;expectexceptionmessage("record already exists"); domainzones::getlocal($customer_userdata, $data)-&gt;add(); } /** * * @depends testcustomerdomainzonesget */ public function testcustomerdomainzonesaddaaaa() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; 'www3', 'type' =&gt; 'aaaa', 'content' =&gt; '::1' ]; $json_result = domainzones::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, 0, 4) == 'www3') { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('www3 18000 aaaa ::1', $entry); } /** * * @depends testcustomerdomainzonesadda */ public function testcustomerdomainzonesaddaaaainvalid() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; 'www4', 'type' =&gt; 'aaaa', 'content' =&gt; 'z:z123.123', 'ttl' =&gt; - 1 ]; $this-&gt;expectexceptionmessage("no valid ip address aaaa-record given"); domainzones::getlocal($customer_userdata, $data)-&gt;add(); } public function testadmindomainzonesaddmx() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '', 'type' =&gt; 'mx', 'prio' =&gt; 10, 'content' =&gt; 'mail.example.com.' ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, strlen('mail.example.com.') * - 1) == 'mail.example.com.') { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('@ 18000 mx 10 mail.example.com.', $entry); } /** * * @depends testadmindomainzonesaddmx */ public function testadmindomainzonesaddmxnoprio() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '', 'type' =&gt; 'mx', 'content' =&gt; 'mail.example.com.' ]; $this-&gt;expectexceptionmessage("invalid mx priority given"); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadmindomainzonesaddmx */ public function testadmindomainzonesaddmxinvalid() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '', 'type' =&gt; 'mx', 'prio' =&gt; 20, 'content' =&gt; 'localhost' ]; $this-&gt;expectexceptionmessage("the mx content value must valid domain-name"); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmindomainzonesaddcaaissue() { global $admin_userdata; $content = '0 issue "letsencrypt.org"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, - strlen($content)) == $content) { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('@ 18000 caa 0 issue "letsencrypt.org"', $entry); } public function testadmindomainzonesaddcaaissuewithparameters() { global $admin_userdata; $content = '0 issue "letsencrypt.org; account=230123"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, strlen($content) * - 1) == $content) { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('@ 18000 caa ' . $content, $entry); } public function testadmindomainzonesaddcaaissuewithtwoparameters() { global $admin_userdata; $content = '0 issue "letsencrypt.org; account=230123 policy=ev"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, strlen($content) * - 1) == $content) { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('@ 18000 caa ' . $content, $entry); } public function testadmindomainzonesaddcaainvalidissuevalue() { global $admin_userdata; $content = '0 issue ""letsencrypt.org"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $this-&gt;expectexceptionmessage("dns content invalid"); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmindomainzonesaddcaainvalidissuedomain() { global $admin_userdata; $content = '0 issue "no-valid-domain"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $this-&gt;expectexceptionmessage("dns content invalid"); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmindomainzonesaddcaainvalidissuetld() { global $admin_userdata; $content = '0 issue "no-valid-domai.n"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $this-&gt;expectexceptionmessage("dns content invalid"); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmindomainzonesaddcaaissuewild() { global $admin_userdata; $content = '0 issuewild "letsencrypt.org"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, strlen($content) * - 1) == $content) { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('@ 18000 caa ' . $content, $entry); } public function testadmindomainzonesaddcaaissuewildwithparameters() { global $admin_userdata; $content = '0 issuewild "letsencrypt.org; account=230123"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, strlen($content) * - 1) == $content) { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('@ 18000 caa ' . $content, $entry); } public function testadmindomainzonesaddcaaissuewildwithtwoparameters() { global $admin_userdata; $content = '0 issuewild "letsencrypt.org; account=230123 policy=ev"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, strlen($content) * - 1) == $content) { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('@ 18000 caa ' . $content, $entry); } public function testadmindomainzonesaddcaainvalidissuewildvalue() { global $admin_userdata; $content = '0 issuewild ""letsencrypt.org"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $this-&gt;expectexceptionmessage("dns content invalid"); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmindomainzonesaddcaainvalidissuewilddomain() { global $admin_userdata; $content = '0 issuewild "no-valid-domain"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $this-&gt;expectexceptionmessage("dns content invalid"); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmindomainzonesaddcaainvalidissuewildtld() { global $admin_userdata; $content = '0 issuewild "no-valid-domai.n"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $this-&gt;expectexceptionmessage("dns content invalid"); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmindomainzonesaddcaaiodefmail() { global $admin_userdata; $content = '0 iodef "mailto:security@example.com"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, strlen($content) * - 1) == $content) { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('@ 18000 caa ' . $content, $entry); } public function testadmindomainzonesaddcaaiodefmailinvalid() { global $admin_userdata; $content = '0 iodef "mailtosecurity@example.com"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $this-&gt;expectexceptionmessage("dns content invalid"); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmindomainzonesaddcaaiodefhttp() { global $admin_userdata; $content = '0 iodef "http://iodef.example.com/"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, strlen($content) * - 1) == $content) { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('@ 18000 caa ' . $content, $entry); } public function testadmindomainzonesaddcaaiodefhttpinvalid() { global $admin_userdata; $content = '0 iodef "http:/iodef.example.com/"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $this-&gt;expectexceptionmessage("dns content invalid"); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmindomainzonesaddcaaiodefhttps() { global $admin_userdata; $content = '0 iodef "https://iodef.example.com/"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, strlen($content) * - 1) == $content) { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('@ 18000 caa ' . $content, $entry); } public function testadmindomainzonesaddcaaiodefhttpsinvalid() { global $admin_userdata; $content = '0 iodef "https:/iodef.example.com/"'; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '@', 'type' =&gt; 'caa', 'content' =&gt; $content ]; $this-&gt;expectexceptionmessage("dns content invalid"); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmindomainzonesaddcname() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; 'db', 'type' =&gt; 'cname', 'content' =&gt; 'db.example.com.' ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, strlen('db.example.com.') * - 1) == 'db.example.com.') { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('db 18000 cname db.example.com.', $entry); } public function testadmindomainzonesaddcnamelocal() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; 'db', 'type' =&gt; 'cname', 'content' =&gt; 'db2' ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, strlen('db2.test2.local.') * - 1) == 'db2.test2.local.') { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('db 18000 cname db2.test2.local.', $entry); } /** * * @depends testadmindomainzonesaddcname */ public function testadmindomainzonesaddcnameinvalid() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '', 'type' =&gt; 'cname', 'content' =&gt; 'localhost.' ]; $this-&gt;expectexceptionmessage("invalid domain-name cname record"); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadmindomainzonesaddcname */ public function testadmindomainzonesaddcnameinvalidwwwalias() { global $admin_userdata; // set domain www-alias $data = [ 'domainname' =&gt; 'test2.local', 'selectserveralias' =&gt; '1' ]; domains::getlocal($admin_userdata, $data)-&gt;update(); $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; 'www', 'type' =&gt; 'cname', 'content' =&gt; 'testing.local' ]; $this-&gt;expectexceptionmessage('cannot set cname record "www" domain set generate www-alias. please change settings either "no alias" "wildcard alias"'); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadmindomainzonesaddcname */ public function testadmindomainzonesaddforexistingcname() { global $admin_userdata; // set domain www-alias $data = [ 'domainname' =&gt; 'test2.local', 'selectserveralias' =&gt; '1' ]; domains::getlocal($admin_userdata, $data)-&gt;update(); foreach ([ 'a' =&gt; '127.0.0.1', 'aaaa' =&gt; '::1', 'mx' =&gt; 'mail.example.com.', 'ns' =&gt; 'ns.example.com.' ] $type =&gt; $val) { $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; 'db', 'type' =&gt; $type, 'content' =&gt; $val ]; $this-&gt;expectexceptionmessage('there already exists cname record record-name. used another type.'); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } } /** * * @depends testadmindomainzonesaddcname */ public function testadmindomainzonesaddcnameunderscore() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; 'dkimtest', 'type' =&gt; 'cname', 'content' =&gt; 'test._domainkey.myhost.tld.' ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, strlen('test._domainkey.myhost.tld.') * - 1) == 'test._domainkey.myhost.tld.') { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('dkimtest 18000 cname test._domainkey.myhost.tld.', $entry); } public function testadmindomainzonesaddns() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '', 'type' =&gt; 'ns', 'content' =&gt; 'ns.example.com.' ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, strlen('ns.example.com.') * - 1) == 'ns.example.com.') { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('@ 18000 ns ns.example.com.', $entry); } public function testadmindomainzonesaddnsinvalid() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '', 'type' =&gt; 'ns', 'content' =&gt; 'localhost.' ]; $this-&gt;expectexceptionmessage("invalid domain-name ns record"); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmindomainzonesaddtxt() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '_test1', 'type' =&gt; 'txt', 'content' =&gt; 'aw yeah' ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, 0, 6) == '_test1') { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('_test1 18000 txt aw yeah', $entry); } /** * * @depends testcustomerdomainzonesgetwithdmarc */ public function testadmindomainzonesaddtxtcustomdmarc() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '_dmarc', 'type' =&gt; 'txt', 'content' =&gt; 'v=dmarc1;p=none;overwrite=true' ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $foundcnt = 0; $foundstr = ''; foreach ($result $entry) { (substr($entry, 0, 7) == '_dmarc ') { $foundcnt++; $foundstr = $entry; } } $this-&gt;assertequals(1, $foundcnt); $resstr = preg_replace('/\s+/', '', $foundstr); $against = preg_replace('/\s+/', '', '_dmarc 18000 txt v=dmarc1;p=none;overwrite=true'); $this-&gt;assertequals($against, $resstr); } /** * * @depends testcustomerdomainzonesgetwithdmarcsubdomain */ public function testadmindomainzonesaddtxtcustomdmarcsubdomain() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '_dmarc.mysub2', 'type' =&gt; 'txt', 'content' =&gt; 'v=dmarc1;p=none;overwrite=true' ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $foundcnt = 0; $foundstr = ''; foreach ($result $entry) { (substr($entry, 0, 14) == '_dmarc.mysub2 ') { $foundcnt++; $foundstr = $entry; } } $this-&gt;assertequals(1, $foundcnt); $resstr = preg_replace('/\s+/', '', $foundstr); $against = preg_replace('/\s+/', '', '_dmarc.mysub2 18000 txt v=dmarc1;p=none;overwrite=true'); $this-&gt;assertequals($against, $resstr); } public function testadmindomainzonesaddsrv() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '_test2', 'type' =&gt; 'srv', 'prio' =&gt; 50, 'content' =&gt; '2 1 srv.example.com.' ]; $json_result = domainzones::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(count($result) &gt; 1); $found = false; foreach ($result $entry) { (substr($entry, 0, 6) == '_test2') { $found = true; break; } } $this-&gt;asserttrue($found); $this-&gt;assertequals('_test2 18000 srv 50 2 1 srv.example.com.', $entry); } public function testadmindomainzonesaddsrvinvalid() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local', 'record' =&gt; '_test2', 'type' =&gt; 'srv', 'prio' =&gt; 50, 'content' =&gt; 'srv.example.com.' ]; $this-&gt;expectexceptionmessage("invalid srv content, must contain fields weight, port target, e.g.: 5 5060 sipserver.example.com."); domainzones::getlocal($admin_userdata, $data)-&gt;add(); } public function testcustomerdomainzonesdelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'test2.local', 'entry_id' =&gt; 1 ]; $json_result = domainzones::getlocal($customer_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true); $this-&gt;asserttrue($result['data']); $this-&gt;assertequals(200, http_response_code()); } public function testcustomerdomainzonesdeleteunmodified() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'test2.local', 'entry_id' =&gt; 1337 ]; $json_result = domainzones::getlocal($customer_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true); $this-&gt;asserttrue($result['data']); $this-&gt;assertequals(304, http_response_code()); } }</file><file name="tests/Cron/TaskIdTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\cron\taskid; /** * * @covers \froxlor\cron\taskid */ class taskidtest extends testcase { private $fixedids = array( 'rebuild_vhost' =&gt; 1, 'create_home' =&gt; 2, 'rebuild_dns' =&gt; 4, 'create_ftp' =&gt; 5, 'delete_customer_files' =&gt; 6, 'delete_email_data' =&gt; 7, 'delete_ftp_data' =&gt; 8, 'create_quota' =&gt; 10, 'delete_domain_pdns' =&gt; 11, 'delete_domain_ssl' =&gt; 12, 'create_customer_datadump' =&gt; 20, 'rebuild_cron' =&gt; 99, ); public function testvalidtaskid() { $isid99valid = taskid::isvalid(99); $this-&gt;asserttrue($isid99valid, "task id 99 must valid"); $isidstringvalid = taskid::isvalid('99'); $this-&gt;asserttrue($isidstringvalid, "string task ids valid"); $isnegativevalid = taskid::isvalid(-1); $this-&gt;assertfalse($isnegativevalid, "negative task invalid"); } public function testidmappingcorrect() { foreach($this-&gt;fixedids $name =&gt; $expected) { $result = constant("\froxlor\cron\taskid::$name"); $this-&gt;assertequals( $expected, $result, "task $name bad mapping"); } } public function testconverttoconstant() { foreach($this-&gt;fixedids $name =&gt; $taskid) { $result = taskid::converttoconstant($taskid); $this-&gt;assertequals( $name, $result, "task $name bad mapping id name"); } $unknownidresult = taskid::isvalid(10101010); $this-&gt;assertfalse($unknownidresult); } }</file><file name="tests/Domains/DomainsTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\settings; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\domains; use froxlor\database\database; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\domains * @covers \froxlor\api\commands\subdomains */ class domainstest extends testcase { public function testadmindomainsadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domain' =&gt; 'test.local', 'customerid' =&gt; $customer_userdata['customerid'], 'override_tls' =&gt; 1, 'ssl_protocols' =&gt; array( 'tlsv1.2', 'tlsv1.3' ), 'description' =&gt; 'awesome domain' ]; $json_result = domains::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'test.local/', $result['documentroot']); $this-&gt;asserttrue(in_array('tlsv1.3', explode(",", $result['ssl_protocols']))); $this-&gt;assertequals('0', $result['isemaildomain']); $this-&gt;assertequals('awesome domain', $result['description']); } /** * * @depends testadmindomainsadd */ public function testadmindomainslist() { global $admin_userdata; $json_result = domains::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertequals('test.local', $result['list'][0]['domain']); $this-&gt;assertequals(2, count($result['list'][0]['ipsandports'])); $this-&gt;assertequals("82.149.225.56", $result['list'][0]['ipsandports'][1]['ip']); $json_result = domains::getlocal($admin_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result); $json_result = domains::getlocal($admin_userdata, [ 'with_ips' =&gt; false ])-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertempty($result['list'][0]['ipsandports']); } /** * * @depends testadmindomainsadd */ public function testresellerdomainslist() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $json_result = domains::getlocal($reseller_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(0, $result['count']); $json_result = domains::getlocal($reseller_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(0, $result); } public function testresellerdomainsaddwithcaneditphpsettingsdefaultip() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $reseller_userdata['caneditphpsettings'] = 1; $data = [ 'domain' =&gt; 'test2.local', 'customerid' =&gt; 1, 'isbinddomain' =&gt; 1 ]; // reseller allowed use default ip/port $this-&gt;expectexceptionmessage("the ip/port combination chosen exist."); domains::getlocal($reseller_userdata, $data)-&gt;add(); } public function testresellerdomainsaddwithcaneditphpsettingsallowedip() { global $admin_userdata; // first, allow reseller access ip #4 admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller', 'ipaddress' =&gt; 4 ))-&gt;update(); // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $data = [ 'domain' =&gt; 'test2.local', 'customerid' =&gt; 1, 'ipandport' =&gt; 4, 'isemaildomain' =&gt; 1, 'subcanemaildomain' =&gt; 2 ]; $json_result = domains::getlocal($reseller_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test2.local', $result['domain']); $this-&gt;assertequals(2, $result['subcanemaildomain']); } public function testresellerdomainsaddwithabsolutepathnochangeserversettings() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $data = [ 'domain' =&gt; 'test3.local', 'customerid' =&gt; 1, 'documentroot' =&gt; '/some/absolute/directory/the_reseller/cannot/set/', 'ipandport' =&gt; 4 ]; $this-&gt;expectexceptionmessage("the user permission specify directories outside customers home-directory. please specify relative path (no leading /)."); $json_result = domains::getlocal($reseller_userdata, $data)-&gt;add(); } /** * * @depends testadmindomainsadd */ public function testresellerdomainsupdate() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $data = [ 'domainname' =&gt; 'test2.local', 'ssl_protocols' =&gt; 'tlsv1', 'documentroot' =&gt; '/var/customers/webs/test1/sub/' ]; $json_result = domains::getlocal($reseller_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertempty($result['ssl_protocols']); $this-&gt;assertequals('test2.local', $result['domain']); $this-&gt;assertequals('/var/customers/webs/test1/sub/', $result['documentroot']); } /** * * @depends testresellerdomainsupdate */ public function testresellerdomainsupdateaboslutepathnotallowed() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $data = [ 'domainname' =&gt; 'test2.local', 'documentroot' =&gt; '/some/other/dir' ]; $this-&gt;expectexceptionmessage("the user permission specify directories outside customers home-directory. please specify relative path (no leading /)."); $json_result = domains::getlocal($reseller_userdata, $data)-&gt;update(); } public function testadmindomainsaddsyshostname() { global $admin_userdata; $data = [ 'domain' =&gt; 'dev.froxlor.org', 'customerid' =&gt; 1 ]; $this-&gt;expectexceptionmessage('the server-hostname cannot used customer-domain.'); domains::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmindomainsaddnopunycode() { global $admin_userdata; $data = [ 'domain' =&gt; 'xn--asdasd.tld', 'customerid' =&gt; 1 ]; $this-&gt;expectexceptionmessage('you must specify punycode (idna). domain automatically converted'); domains::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmindomainsaddinvaliddomain() { global $admin_userdata; $data = [ 'domain' =&gt; 'dom?*ain.tld', 'customerid' =&gt; 1 ]; $this-&gt;expectexceptionmessage("wrong input field 'domain'"); domains::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadmindomainsadd */ public function testadmindomainsupdate() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'test.local', 'email_only' =&gt; 1, 'override_tls' =&gt; 0, 'documentroot' =&gt; 'web', 'description' =&gt; 'changed desc' ]; $json_result = domains::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['email_only']); $this-&gt;assertfalse(in_array('tlsv1.3', explode(",", $result['ssl_protocols']))); $this-&gt;assertequals('test.local', $result['domain']); $this-&gt;assertequals($customer_userdata['documentroot'] . 'web/', $result['documentroot']); $this-&gt;assertequals('changed desc', $result['description']); } /** * * @depends testadmindomainsadd */ public function testadmindomainsupdateabsolutepath() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test.local', 'documentroot' =&gt; '/web' ]; $json_result = domains::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('/web/', $result['documentroot']); } /** * * @depends testadmindomainsadd */ public function testadmindomainsupdateissue756() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test.local', 'ssl_redirect' =&gt; 1 ]; $json_result = domains::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; // get ssl ip/port domain still exist $sel_stmt = database::prepare(" select count(*) numips `" . table_domaintoip . "` di left join `" . table_panel_ipsandports . "` i.id = di.id_ipandports left join `" . table_panel_domains . "` d.id = di.id_domain d.id = :did i.ssl = 1 "); $result_ips = database::pexecute_first($sel_stmt, [ 'did' =&gt; $result['id'] ], true, true); $this-&gt;assertequals(1, $result_ips['numips']); // test clearing $data = [ 'domainname' =&gt; 'test.local', 'ssl_ipandport' =&gt; array() ]; $json_result = domains::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; // get ssl ip/port domain still exist $result_ips = database::pexecute_first($sel_stmt, [ 'did' =&gt; $result['id'] ], true, true); $this-&gt;assertequals(1, $result_ips['numips']); $data = [ 'domainname' =&gt; 'test.local', 'remove_ssl_ipandport' =&gt; 1 ]; $json_result = domains::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; // get ssl ip/port domain still exist $result_ips = database::pexecute_first($sel_stmt, [ 'did' =&gt; $result['id'] ], true, true); $this-&gt;assertequals(0, $result_ips['numips']); } /** * * @depends testadmindomainsupdate */ public function testadmindomainsmovebutunknowncustomer() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'test.local', 'customerid' =&gt; $customer_userdata['customerid'] + 1 ]; settings::set('panel.allow_domain_change_customer', 1); $this-&gt;expectexceptionmessage("customer id #2 could found"); domains::getlocal($admin_userdata, $data)-&gt;update(); } public function testadmindomainsmove() { global $admin_userdata; // add new customer $data = [ 'new_loginname' =&gt; 'test3', 'email' =&gt; 'test3@froxlor.org', 'firstname' =&gt; 'test', 'name' =&gt; 'testman', 'customernumber' =&gt; 1339, 'new_customer_password' =&gt; 'h0lymo1y' ]; $json_result = customers::getlocal($admin_userdata, $data)-&gt;add(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'test.local', 'customerid' =&gt; $customer_userdata['customerid'] ]; $json_result = domains::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['customerid'], $result['customerid']); $this-&gt;assertequals($customer_userdata['documentroot'] . 'test.local/', $result['documentroot']); } /** * * @depends testadmindomainsmove */ public function testadmindomainsduplicate() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test.local', 'domain' =&gt; 'test.duplicate.local', 'description' =&gt; 'duplicated domain' ]; $json_result = domains::getlocal($admin_userdata, $data)-&gt;duplicate(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('/var/customers/webs/test3/test.duplicate.local/', $result['documentroot']); $this-&gt;assertequals(1, $result['email_only']); $this-&gt;assertequals('test.duplicate.local', $result['domain']); $this-&gt;assertequals('duplicated domain', $result['description']); } /** * * @depends testadmindomainsduplicate */ public function testadmindomainsdelete() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test.local', 'delete_mainsubdomains' =&gt; 1 ]; $json_result = domains::getlocal($admin_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test.local', $result['domain']); // remove customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test3' ))-&gt;delete(); } public function testcustomerdomainslist() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); $json_result = domains::getlocal($customer_userdata)-&gt;listing(); $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); $json_result = domains::getlocal($customer_userdata)-&gt;listingcount(); } public function testadminidndomainsadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domain' =&gt; 'tst.local', 'customerid' =&gt; $customer_userdata['customerid'] ]; $json_result = domains::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'xn--tst-qla.local/', $result['documentroot']); $this-&gt;assertequals('xn--tst-qla.local', $result['domain']); $this-&gt;assertequals('tst.local', $result['domain_ace']); domains::getlocal($admin_userdata, [ 'domainname' =&gt; 'tst.local' ])-&gt;delete(); } /** * * @refs https://github.com/froxlor/froxlor/issues/899 */ public function testadminidn2domainsadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domain' =&gt; '.', 'customerid' =&gt; $customer_userdata['customerid'] ]; $json_result = domains::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'xn--p1b6ci4b4b3a.xn--h2brj9c/', $result['documentroot']); $this-&gt;assertequals('xn--p1b6ci4b4b3a.xn--h2brj9c', $result['domain']); $this-&gt;assertequals('.', $result['domain_ace']); domains::getlocal($admin_userdata, [ 'domainname' =&gt; '.' ])-&gt;delete(); } public function testadmindomainsadddnsletsencryptfail() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); settings::set('system.le_domain_dnscheck', 1); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domain' =&gt; 'no-dns.local', 'customerid' =&gt; $customer_userdata['customerid'], 'letsencrypt' =&gt; 1, 'description' =&gt; 'no dns domain' ]; $this-&gt;expectexceptioncode(400); $this-&gt;expectexceptionmessage('the domains dns include chosen ip addresses. let\'s encrypt certificate generation possible.'); domains::getlocal($admin_userdata, $data)-&gt;add(); } }</file><file name="tests/PhpAndFpm/FpmDaemonsTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\api\commands\customers; use froxlor\api\commands\fpmdaemons; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\fpmdaemons */ class fpmdaemonstest extends testcase { private static $id = 0; public function testadminfpmdaemonsadd() { global $admin_userdata; $data = [ 'description' =&gt; 'test2 fpm', 'reload_cmd' =&gt; 'service php8.1-fpm reload', 'config_dir' =&gt; '/etc/php/8.1/fpm/pool.d', 'limit_extensions' =&gt; '' ]; $json_result = fpmdaemons::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('/etc/php/8.1/fpm/pool.d/', $result['config_dir']); $this-&gt;assertequals('dynamic', $result['pm']); $this-&gt;assertequals(5, $result['max_children']); $this-&gt;assertequals('.php', $result['limit_extensions']); self::$id = $result['id']; } public function testadminfpmdaemonsaddunknownpm() { global $admin_userdata; $data = [ 'description' =&gt; 'test2 fpm', 'reload_cmd' =&gt; 'service php7.3-fpm reload', 'config_dir' =&gt; '/etc/php/7.3/fpm/pool.d', 'pm' =&gt; 'supermegapm' ]; $this-&gt;expectexceptioncode(406); $this-&gt;expectexceptionmessage("unknown process manager"); fpmdaemons::getlocal($admin_userdata, $data)-&gt;add(); } public function testadminfpmdaemonsaddinvaliddesc() { // max 50. characters global $admin_userdata; $data = [ 'description' =&gt; str_repeat('test', 30), 'reload_cmd' =&gt; 'service php7.3-fpm reload', 'config_dir' =&gt; '/etc/php/7.3/fpm/pool.d' ]; $this-&gt;expectexceptionmessage("the description short, long contains illegal characters."); fpmdaemons::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadminfpmdaemonsadd */ public function testadminfpmdaemonsupdate() { global $admin_userdata; $data = [ 'id' =&gt; self::$id, 'description' =&gt; 'test2 fpm edit', 'pm' =&gt; 'dynamic', 'max_children' =&gt; '10', 'start_servers' =&gt; '4', 'limit_extensions' =&gt; '.php .php.xml' ]; $json_result = fpmdaemons::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('/etc/php/8.1/fpm/pool.d/', $result['config_dir']); $this-&gt;assertequals(10, $result['max_children']); $this-&gt;assertequals('.php .php.xml', $result['limit_extensions']); } /** * * @depends testadminfpmdaemonsupdate */ public function testadminfpmdaemonsupdate2() { global $admin_userdata; $data = [ 'id' =&gt; self::$id, 'limit_extensions' =&gt; '' ]; $json_result = fpmdaemons::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('.php', $result['limit_extensions']); } /** * * @depends testadminfpmdaemonsadd */ public function testadminfpmdaemonsupdateunknownpm() { global $admin_userdata; $data = [ 'id' =&gt; self::$id, 'pm' =&gt; 'supermegapm' ]; $this-&gt;expectexceptioncode(406); $this-&gt;expectexceptionmessage("unknown process manager"); fpmdaemons::getlocal($admin_userdata, $data)-&gt;update(); } /** * * @depends testadminfpmdaemonsadd */ public function testadminfpmdaemonsupdateinvaliddesc() { // max 50. characters global $admin_userdata; $data = [ 'id' =&gt; self::$id, 'description' =&gt; str_repeat('test', 30) ]; $this-&gt;expectexceptionmessage("the description short, long contains illegal characters."); fpmdaemons::getlocal($admin_userdata, $data)-&gt;update(); } /** * * @depends testadminfpmdaemonsupdate */ public function testadminfpmdaemonslist() { global $admin_userdata; $json_result = fpmdaemons::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['count']); $this-&gt;assertequals('system default', $result['list'][0]['description']); $this-&gt;assertequals('test2 fpm edit', $result['list'][1]['description']); $json_result = fpmdaemons::getlocal($admin_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result); } public function testadminfpmdaemonsgetnotfound() { global $admin_userdata; $this-&gt;expectexceptioncode(404); $this-&gt;expectexceptionmessage("fpm-daemon id #-1 could found"); fpmdaemons::getlocal($admin_userdata, array( 'id' =&gt; - 1 ))-&gt;get(); } public function testcustomerfpmdaemonsadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); fpmdaemons::getlocal($customer_userdata)-&gt;add(); } public function testcustomerfpmdaemonsget() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); fpmdaemons::getlocal($customer_userdata)-&gt;get(); } public function testcustomerfpmdaemonslist() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); fpmdaemons::getlocal($customer_userdata)-&gt;listing(); $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); fpmdaemons::getlocal($customer_userdata)-&gt;listingcount(); } public function testcustomerfpmdaemonsupdate() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); fpmdaemons::getlocal($customer_userdata)-&gt;update(); } public function testcustomerfpmdaemonsdelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); fpmdaemons::getlocal($customer_userdata)-&gt;delete(); } /** * * @depends testadminfpmdaemonslist */ public function testadminfpmdaemonsdelete() { global $admin_userdata; $data = [ 'id' =&gt; self::$id ]; $json_result = fpmdaemons::getlocal($admin_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('/etc/php/8.1/fpm/pool.d/', $result['config_dir']); $this-&gt;assertequals(10, $result['max_children']); $this-&gt;assertequals('.php', $result['limit_extensions']); } /** * * @depends testadminfpmdaemonsdelete */ public function testadminfpmdaemonsdeletedefaultconfig() { global $admin_userdata; $data = [ 'id' =&gt; 1 ]; $this-&gt;expectexceptionmessage("this php-configuration set default cannot deleted."); fpmdaemons::getlocal($admin_userdata, $data)-&gt;delete(); } }</file><file name="tests/PhpAndFpm/PhpSettingsTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\settings; use froxlor\api\commands\customers; use froxlor\api\commands\phpsettings; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\phpsettings */ class phpsettingstext extends testcase { private static $id = 0; public function testadminphpsettingslist() { global $admin_userdata; $json_result = phpsettings::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals("default config", $result['list'][0]['description']); $this-&gt;assertequals("/usr/bin/php-cgi", $result['list'][0]['binary']); $json_result = phpsettings::getlocal($admin_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result); } public function testcustomerphpsettingslistnotallowed() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); phpsettings::getlocal($customer_userdata)-&gt;listing(); $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); phpsettings::getlocal($customer_userdata)-&gt;listingcount(); } public function testadminphpsettingsadd() { global $admin_userdata; $data = [ 'description' =&gt; 'test php', 'phpsettings' =&gt; 'error_reporting=e_all', 'fpmconfig' =&gt; settings::get('phpfpm.defaultini') ]; $json_result = phpsettings::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('error_reporting=e_all', $result['phpsettings']); $this-&gt;assertequals('60s', $result['fpm_reqterm']); self::$id = $result['id']; } public function testadminphpsettingsget() { global $admin_userdata; $data = [ 'id' =&gt; self::$id ]; $json_result = phpsettings::getlocal($admin_userdata, $data)-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('error_reporting=e_all', $result['phpsettings']); $this-&gt;assertequals('60s', $result['fpm_reqterm']); } public function testadminphpsettingsgetnotfound() { global $admin_userdata; $this-&gt;expectexceptioncode(404); $this-&gt;expectexceptionmessage("php-config id #999 could found"); phpsettings::getlocal($admin_userdata, array( 'id' =&gt; 999 ))-&gt;get(); } public function testcustomerphpsettingsgetnotallowed() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); phpsettings::getlocal($customer_userdata, array( 'id' =&gt; 1 ))-&gt;get(); } /** * @depends testadminphpsettingsadd */ public function testadminphpsettingsaddforall() { global $admin_userdata; $data = [ 'description' =&gt; 'test php #2', 'phpsettings' =&gt; 'error_reporting=e_all', 'fpmconfig' =&gt; settings::get('phpfpm.defaultini'), 'allow_all_customers' =&gt; true ]; $json_result = phpsettings::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $required_id = $result['id']; $json_result = customers::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $allowed_cnt = 0; foreach ($result['list'] $customer) { $cust_phpconfigsallowed = json_decode($customer['allowed_phpconfigs'], true); (!in_array($required_id, $cust_phpconfigsallowed)) { $this-&gt;fail("customer php-config assigned added customers"); } $allowed_cnt++; } $this-&gt;asserttrue($allowed_cnt == $result['count']); } }</file><file name="tests/Cronjobs/CronjobsTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\cronjobs; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\cronjobs */ class cronjobstest extends testcase { public function testadmincronjobslist() { global $admin_userdata; $json_result = cronjobs::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(isset($result['list'][0]['module'])); $this-&gt;asserttrue(isset($result['list'][0]['cronfile'])); $json_result = cronjobs::getlocal($admin_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(6, $result); } public function testcustomercronjobslistnotallowed() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); cronjobs::getlocal($customer_userdata)-&gt;listing(); } public function testadmincronjobsadd() { global $admin_userdata; $data = []; $this-&gt;expectexceptioncode(303); $this-&gt;expectexceptionmessage("you cannot add new cronjobs yet."); cronjobs::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmincronjobsgetnotfound() { global $admin_userdata; $this-&gt;expectexceptioncode(404); $this-&gt;expectexceptionmessage("cronjob id #999 could found"); cronjobs::getlocal($admin_userdata, array( 'id' =&gt; 999 ))-&gt;get(); } public function testcustomercronjobsgetnotallowed() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); cronjobs::getlocal($customer_userdata, array( 'id' =&gt; 1 ))-&gt;get(); } public function testadmincronjobsedit() { global $admin_userdata; $data = [ 'id' =&gt; 1, 'isactive' =&gt; 0, 'interval_value' =&gt; 10 ]; $json_result = cronjobs::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(0, $result['isactive']); $this-&gt;assertequals('10 minute', $result['interval']); } public function testresellercronjobseditnotallowed() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $data = [ 'id' =&gt; 1, 'isactive' =&gt; 1 ]; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); cronjobs::getlocal($reseller_userdata, $data)-&gt;update(); } public function testadmincronjobsdelete() { global $admin_userdata; $data = [ 'id' =&gt; 3 ]; $this-&gt;expectexceptioncode(303); $this-&gt;expectexceptionmessage("you cannot delete system cronjobs."); cronjobs::getlocal($admin_userdata, $data)-&gt;delete(); } }</file><file name="tests/Admins/AdminsTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\database\database; use froxlor\api\commands\admins; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\admins */ class adminstest extends testcase { public function testadminadminsadd() { global $admin_userdata; $data = [ 'new_loginname' =&gt; 'reseller', 'email' =&gt; 'testreseller@froxlor.org', 'name' =&gt; 'testreseller', 'admin_password' =&gt; 'h0lymo1y', 'diskspace' =&gt; - 1, 'traffic' =&gt; - 1, 'customers' =&gt; 15, 'domains' =&gt; 15, 'subdomains' =&gt; 15, 'emails' =&gt; - 1, 'email_accounts' =&gt; 15, 'email_forwarders' =&gt; 15, 'email_imap' =&gt; 1, 'email_pop3' =&gt; 0, 'ftps' =&gt; 15, 'mysqls' =&gt; 15, 'sendpassword' =&gt; 0, 'phpenabled' =&gt; 1, 'ip' =&gt; array() ]; $json_result = admins::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $admin_id = $result['adminid']; // get admin check results $json_result = admins::getlocal($admin_userdata, array( 'id' =&gt; $admin_id ))-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('reseller', $result['loginname']); $this-&gt;assertequals('testreseller@froxlor.org', $result['email']); $this-&gt;assertequals(0, $result['customers_see_all']); } /** * * @depends testadminadminsadd */ public function testadminadminsaddloginnameexists() { global $admin_userdata; $data = [ 'new_loginname' =&gt; 'reseller', 'email' =&gt; 'testreseller@froxlor.org', 'name' =&gt; 'testreseller' ]; $this-&gt;expectexceptionmessage('loginname reseller already exists'); admins::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadminadminsaddloginnameexists */ public function testadminadminsaddloginnameissystemaccount() { global $admin_userdata; $data = [ 'new_loginname' =&gt; 'web2', 'email' =&gt; 'testreseller@froxlor.org', 'name' =&gt; 'testreseller' ]; $this-&gt;expectexceptionmessage('you cannot create accounts begin "web", prefix set used automatic account-naming. please enter another account name.'); admins::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadminadminsaddloginnameissystemaccount */ public function testadminadminsaddloginnameinvalid() { global $admin_userdata; $data = [ 'new_loginname' =&gt; 'reslr-', 'email' =&gt; 'testreseller@froxlor.org', 'name' =&gt; 'testreseller' ]; $this-&gt;expectexceptionmessage('loginname "reslr-" contains illegal characters.'); admins::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadminadminsaddloginnameissystemaccount */ public function testadminadminsaddloginnameinvalidemail() { global $admin_userdata; $data = [ 'new_loginname' =&gt; 'reslr', 'email' =&gt; 'testreseller.froxlor.org', 'name' =&gt; 'testreseller' ]; $this-&gt;expectexceptionmessage('email-address testreseller.froxlor.org contains invalid characters incomplete'); admins::getlocal($admin_userdata, $data)-&gt;add(); } public function testadminadminsaddnotallowed() { global $admin_userdata; $testadmin_userdata = $admin_userdata; $testadmin_userdata['adminsession'] = 0; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); admins::getlocal($testadmin_userdata, array())-&gt;add(); } public function testadminadminsgetnotfound() { global $admin_userdata; $this-&gt;expectexceptioncode(404); $this-&gt;expectexceptionmessage("admin loginname 'unknown' could found"); // get unknown admin admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'unknown' ))-&gt;get(); } public function testadminadminslist() { global $admin_userdata; $json_result = admins::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['count']); $json_result = admins::getlocal($admin_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result); } public function testadminadminslistlimitoffsetordersearch() { global $admin_userdata; $json_result = admins::getlocal($admin_userdata, [ 'sql_orderby' =&gt; [ 'loginname' =&gt; 'desc' ] ])-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['count']); $this-&gt;assertequals('reseller', $result['list'][0]['loginname']); $json_result = admins::getlocal($admin_userdata, [ 'sql_limit' =&gt; 1 ])-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertequals('admin', $result['list'][0]['loginname']); $json_result = admins::getlocal($admin_userdata, [ 'sql_limit' =&gt; 1, 'sql_offset' =&gt; 1 ])-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertequals('reseller', $result['list'][0]['loginname']); $json_result = admins::getlocal($admin_userdata, [ 'sql_search' =&gt; [ 'loginname' =&gt; [ 'value' =&gt; 'adm', 'op' =&gt; null /* like */ ] ] ])-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertequals('admin', $result['list'][0]['loginname']); } public function testreselleradminsget() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; // try read superadmin access-less reseller account $this-&gt;expectexception(exception::class); $this-&gt;expectexceptioncode(403); $json_result = admins::getlocal($reseller_userdata, array( 'loginname' =&gt; 'admin' ))-&gt;get(); } public function testreselleradminslistnotallowed() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); admins::getlocal($reseller_userdata)-&gt;listing(); } public function testadminadminsunlock() { global $admin_userdata; // update reseller correct test-data database::query("update `" . table_panel_admins . "` set `loginfail_count` = '5' `loginname` = 'reseller'"); $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;unlock(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(0, $result['loginfail_count']); } public function testadminadminsunlocknotallowed() { global $admin_userdata; $testadmin_userdata = $admin_userdata; $testadmin_userdata['adminsession'] = 0; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); admins::getlocal($testadmin_userdata, array( 'loginname' =&gt; 'admin' ))-&gt;unlock(); } public function testadminadminsdeletemyown() { global $admin_userdata; $this-&gt;expectexceptionmessage("you cannot delete security reasons."); admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'admin' ))-&gt;delete(); } public function testadminadminsdeletereseller() { global $admin_userdata; // add test reseller $data = [ 'new_loginname' =&gt; 'resellertest', 'email' =&gt; 'testreseller2@froxlor.org', 'name' =&gt; 'testreseller' ]; $json_result = admins::getlocal($admin_userdata, $data)-&gt;add(); $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'resellertest' ))-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('resellertest', $result['loginname']); } public function testreselleradminsdelete() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); admins::getlocal($reseller_userdata, array( 'loginname' =&gt; 'admin' ))-&gt;delete(); } public function testadminadminseditmyown() { global $admin_userdata; // update admin correct test-data database::query("update `" . table_panel_admins . "` set `theme` = 'froxlor', `def_language` = 'deutsch' `loginname` = 'admin'"); $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'admin', 'theme' =&gt; '', 'def_language' =&gt; 'english' ))-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('froxlor', $result['theme']); $this-&gt;assertequals('english', $result['def_language']); } public function testadminadminsedit() { global $admin_userdata; // update admin correct test-data database::query("update `" . table_panel_admins . "` set `deactivated` = '0' `loginname` = 'reseller'"); $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller', 'deactivated' =&gt; '1' ))-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['deactivated']); // reactivate admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller', 'deactivated' =&gt; '0' ))-&gt;update(); } public function testadminsadminseditnotallowed() { global $admin_userdata; $testadmin_userdata = $admin_userdata; $testadmin_userdata['adminsession'] = 0; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); admins::getlocal($testadmin_userdata, array( 'loginname' =&gt; 'admin' ))-&gt;update(); } public function testadminsadminscannotdeletefirstadmin() { global $admin_userdata; $testadmin_userdata = $admin_userdata; $testadmin_userdata['adminid'] = 10; $this-&gt;expectexceptionmessage("the first admin cannot deleted."); admins::getlocal($testadmin_userdata, array( 'loginname' =&gt; 'admin' ))-&gt;delete(); } }</file><file name="tests/Backup/DataDumpTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\settings; use froxlor\database\database; use froxlor\api\commands\customers; use froxlor\api\commands\datadump; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\datadump */ class datadumptest extends testcase { public function testadmindatadumpnotenabled() { global $admin_userdata; settings::set('system.exportenabled', 0, true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(405); $this-&gt;expectexceptionmessage("you cannot access resource"); datadump::getlocal($customer_userdata)-&gt;add(); } /** * * @depends testadmindatadumpnotenabled */ public function testadmindatadumpextrashidden() { global $admin_userdata; settings::set('system.exportenabled', 1, true); settings::set('panel.customer_hide_options', 'extras', true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(405); $this-&gt;expectexceptionmessage("you cannot access resource"); datadump::getlocal($customer_userdata)-&gt;add(); } /** * * @depends testadmindatadumpextrashidden */ public function testadmindatadumpextrasexporthidden() { global $admin_userdata; settings::set('panel.customer_hide_options', 'extras.export', true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(405); $this-&gt;expectexceptionmessage("you cannot access resource"); datadump::getlocal($customer_userdata)-&gt;add(); } /** * * @depends testadmindatadumpextrasexporthidden */ public function testcustomerdatadumpadd() { global $admin_userdata; settings::set('panel.customer_hide_options', '', true); database::query("truncate table `panel_tasks`;"); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'path' =&gt; '/my-dump', 'dump_dbs' =&gt; 2, 'dump_mail' =&gt; 3, 'dump_web' =&gt; 4 ]; $json_result = datadump::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'my-dump/', $result['destdir']); $this-&gt;assertequals('1', $result['dump_dbs']); $this-&gt;assertequals('1', $result['dump_mail']); $this-&gt;assertequals('1', $result['dump_web']); } /** * * @depends testcustomerdatadumpadd */ public function testcustomerdatadumpaddpathnotdocroot() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'path' =&gt; '/' ]; $this-&gt;expectexceptioncode(400); $this-&gt;expectexceptionmessage('the folder data-dumps cannot homedir, please chose folder within homedir, e.g. /dumps'); $json_result = datadump::getlocal($customer_userdata, $data)-&gt;add(); } public function testadmindatadumpget() { global $admin_userdata; $this-&gt;expectexceptioncode(303); datadump::getlocal($admin_userdata)-&gt;get(); } public function testadmindatadumpupdate() { global $admin_userdata; $this-&gt;expectexceptioncode(303); datadump::getlocal($admin_userdata)-&gt;update(); } /** * * @depends testcustomerdatadumpadd */ public function testadmindatadumplisting() { global $admin_userdata; $json_result = datadump::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertequals('1', $result['list'][0]['data']['dump_dbs']); $this-&gt;assertequals('1', $result['list'][0]['data']['dump_mail']); $this-&gt;assertequals('1', $result['list'][0]['data']['dump_web']); $json_result = datadump::getlocal($admin_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result); } /** * * @depends testcustomerdatadumpadd */ public function testcustomerdatadumpdelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'job_entry' =&gt; 1 ]; $json_result = datadump::getlocal($customer_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue($result); } /** * * @depends testadmindatadumplisting */ public function testcustomerdatadumpdeletenotfound() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'job_entry' =&gt; 1337 ]; $this-&gt;expectexceptioncode(404); $this-&gt;expectexceptionmessage('data export job id #1337 could found'); datadump::getlocal($customer_userdata, $data)-&gt;delete(); } }</file><file name="tests/Bulk/DomainBulkTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\api\commands\domains; use froxlor\bulk\domainbulkaction; /** * * @covers \froxlor\bulk\bulkaction * @covers \froxlor\bulk\domainbulkaction */ class domainbulktest extends testcase { public function testnoimportfile() { global $admin_userdata; $this-&gt;expectexceptionmessage("no file given import"); $bulk = new domainbulkaction(null, $admin_userdata); $bulk-&gt;doimport(";", 0); } public function testimportfiledoesnotexist() { global $admin_userdata; $this-&gt;expectexceptionmessage("the file '/tmp/nonexisting.csv' could found"); $bulk = new domainbulkaction("/tmp/nonexisting.csv", $admin_userdata); $bulk-&gt;doimport(";", 0); } public function testimportdomains() { global $admin_userdata; $content = &lt;&lt;&lt;eoc domain;loginname; imported-a.com;test1; imported-b.com;test1; imported-c.com;test2; eoc; file_put_contents('/tmp/import-test.csv', $content); $bulk = new domainbulkaction("/tmp/import-test.csv", $admin_userdata); $result = $bulk-&gt;doimport(";", 0); $this-&gt;assertequals(3, $result['all']); $this-&gt;assertequals(2, $result['imported']); $this-&gt;assertequals("customer loginname 'test2' could found", $bulk-&gt;geterrors()[0]); // check whether domain really exists test1 user $data = [ 'domain' =&gt; 'imported-a.com' ]; $json_result = domains::getlocal($admin_userdata, $data)-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('imported-a.com', $result['domain']); $this-&gt;assertequals(1, $result['customerid']); } public function testimportdomainsmaxalloc() { global $admin_userdata; // fake allocation restriction $admin_userdata['domains'] = 1; $content = &lt;&lt;&lt;eoc domain;loginname; imported-a.com;test1; imported-b.com;test1; imported-c.com;test2; eoc; file_put_contents('/tmp/import-test.csv', $content); $bulk = new domainbulkaction("/tmp/import-test.csv", $admin_userdata); $result = $bulk-&gt;doimport(";", 0); $this-&gt;assertequals(3, $result['all']); $this-&gt;assertequals(0, $result['imported']); $this-&gt;assertequals("you reached maximum allocation domains (" . $admin_userdata['domains'] . ")", $result['notes']); } }</file><file name="tests/Global/ApiParameterTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\api\commands\froxlor; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\froxlor */ class apiparametertest extends testcase { public function testmissingrequiredparameter() { global $admin_userdata; $this-&gt;expectexceptioncode(404); $this-&gt;expectexceptionmessage('requested parameter "key" could found "froxlor:getsetting"'); froxlor::getlocal($admin_userdata)-&gt;getsetting(); } }</file><file name="tests/Global/FroxlorRpcTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\database\database; use froxlor\api\froxlorrpc; /** * * @covers \froxlor\api\froxlorrpc */ class froxlorrpctest extends testcase { public function testnocredentialsgiven() { $this-&gt;expectexceptioncode(401); $this-&gt;expectexceptionmessage("unauthenticated. please provide api user credentials."); froxlorrpc::validaterequest(""); } public function testvalidateauthinvalid() { $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("invalid authorization credentials"); $_server['php_auth_user'] = 'asd'; $_server['php_auth_pw'] = 'asd'; froxlorrpc::validaterequest(""); } public function testvalidateauthallowfrominvalid() { $_server['remote_addr'] = '127.0.0.1'; database::query("update `api_keys` set `allowed_from` = '123.123.123.123';"); $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("invalid authorization credentials"); $_server['php_auth_user'] = 'test'; $_server['php_auth_pw'] = 'test'; froxlorrpc::validaterequest(""); } public function testemptyrequestbody() { database::query("update `api_keys` set `allowed_from` = '';"); $this-&gt;expectexceptioncode(400); $this-&gt;expectexceptionmessage("empty request body."); $_server['php_auth_user'] = 'test'; $_server['php_auth_pw'] = 'test'; froxlorrpc::validaterequest(""); } public function testinvalidjson() { $this-&gt;expectexceptioncode(400); $this-&gt;expectexceptionmessage("invalid json format."); $_server['php_auth_user'] = 'test'; $_server['php_auth_pw'] = 'test'; froxlorrpc::validaterequest('asd'); } public function testnocommandgiven() { $this-&gt;expectexceptioncode(400); $this-&gt;expectexceptionmessage("please provide command."); $_server['php_auth_user'] = 'test'; $_server['php_auth_pw'] = 'test'; froxlorrpc::validaterequest(json_encode(['cmd' =&gt; 'test'])); } public function testinvalidcommandgiven() { $this-&gt;expectexceptioncode(400); $this-&gt;expectexceptionmessage("the given command invalid."); $_server['php_auth_user'] = 'test'; $_server['php_auth_pw'] = 'test'; froxlorrpc::validaterequest(json_encode(['command' =&gt; 'froxlor'])); } public function testunknowncommandgiven() { $this-&gt;expectexceptioncode(400); $this-&gt;expectexceptionmessage("unknown command"); $_server['php_auth_user'] = 'test'; $_server['php_auth_pw'] = 'test'; froxlorrpc::validaterequest(json_encode(['command' =&gt; 'somemodule.cmd'])); } public function testcommandok() { $_server['php_auth_user'] = 'test'; $_server['php_auth_pw'] = 'test'; $result = froxlorrpc::validaterequest(json_encode(['command' =&gt; 'froxlor.listfunctions'])); $this-&gt;assertequals('froxlor', $result['command']['class']); $this-&gt;assertequals('listfunctions', $result['command']['method']); $this-&gt;assertnull($result['params']); } public function testapiphpescaping() { $key = $this-&gt;generatekey(); $request = array( 'command' =&gt; 'froxlor.listfunctions', 'params' =&gt; $key ); $json_request = json_encode($request); $decoded_request = json_decode($json_request, true); $decoded_request = $this-&gt;stripcslashes_deep($decoded_request); $this-&gt;assertequals($key['key'], $decoded_request['params']['key']); $this-&gt;assertequals($key['cert'], $decoded_request['params']['cert']); } private function stripcslashes_deep($value) { return is_array($value) ? array_map([$this, 'stripcslashes_deep'], $value) : stripcslashes($value); } private function generatekey() { $dn = array( "countryname" =&gt; "de", "stateorprovincename" =&gt; "hessen", "localityname" =&gt; "frankfurt", "organizationname" =&gt; "froxlor", "organizationalunitname" =&gt; "testing", "commonname" =&gt; "test2.local", "emailaddress" =&gt; "team@froxlor.org" ); // generate key pair $privkey = openssl_pkey_new(array( "private_key_bits" =&gt; 2048, "private_key_type" =&gt; openssl_keytype_rsa )); // generate csr $csr = openssl_csr_new($dn, $privkey, array( 'digest_alg' =&gt; 'sha256' )); // generate self-signed certificate $sscert = openssl_csr_sign($csr, null, $privkey, 365, array( 'digest_alg' =&gt; 'sha256' )); // export openssl_x509_export($sscert, $certout); openssl_pkey_export($privkey, $pkeyout, null); return array( 'cert' =&gt; $certout, 'key' =&gt; $pkeyout ); } }</file><file name="tests/Certificates/CertificatesTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\certificates; use froxlor\api\commands\subdomains; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\certificates */ class certificatestest extends testcase { public function testadmincertificatesadd() { global $admin_userdata; $json_result = subdomains::getlocal($admin_userdata, array( 'domainname' =&gt; 'test2.local' ))-&gt;get(); $domain = json_decode($json_result, true)['data']; $domainid = $domain['id']; $certdata = $this-&gt;generatekey(); $json_result = certificates::getlocal($admin_userdata, array( 'domainname' =&gt; 'test2.local', 'ssl_cert_file' =&gt; $certdata['cert'], 'ssl_key_file' =&gt; $certdata['key'] ))-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($domainid, $result['domainid']); } public function testresellercertificatesaddagain() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $certdata = $this-&gt;generatekey(); $this-&gt;expectexceptioncode(406); $this-&gt;expectexceptionmessage("domain 'test2.local' already certificate. mean call update?"); $json_result = certificates::getlocal($reseller_userdata, array( 'domainname' =&gt; 'test2.local', 'ssl_cert_file' =&gt; $certdata['cert'], 'ssl_key_file' =&gt; $certdata['key'] ))-&gt;add(); } public function testcustomercertificatesadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = subdomains::getlocal($admin_userdata, array( 'domainname' =&gt; 'mysub2.test2.local' ))-&gt;get(); $domain = json_decode($json_result, true)['data']; $domainid = $domain['id']; $certdata = $this-&gt;generatekey(); $json_result = certificates::getlocal($customer_userdata, array( 'domainname' =&gt; 'mysub2.test2.local', 'ssl_cert_file' =&gt; $certdata['cert'], 'ssl_key_file' =&gt; $certdata['key'] ))-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($domainid, $result['domainid']); } public function testadmincertificateslist() { global $admin_userdata; $json_result = certificates::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['count']); $json_result = certificates::getlocal($admin_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result); } public function testresellercertificateslist() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $json_result = certificates::getlocal($reseller_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['count']); $json_result = certificates::getlocal($reseller_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result); } public function testcustomercertificateslist() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = certificates::getlocal($customer_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['count']); $json_result = certificates::getlocal($customer_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result); } public function testadmincertificatesupdate() { global $admin_userdata; $certdata = $this-&gt;generatekey(); $json_result = certificates::getlocal($admin_userdata, array( 'domainname' =&gt; 'test2.local', 'ssl_cert_file' =&gt; $certdata['cert'], 'ssl_key_file' =&gt; $certdata['key'] ))-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(str_replace("\n", "", $certdata['cert']), str_replace("\n", "", $result['ssl_cert_file'])); } public function testcustomercertificatesupdate() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $certdata = $this-&gt;generatekey(); $json_result = certificates::getlocal($customer_userdata, array( 'domainname' =&gt; 'mysub2.test2.local', 'ssl_cert_file' =&gt; $certdata['cert'], 'ssl_key_file' =&gt; $certdata['key'] ))-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(str_replace("\n", "", $certdata['cert']), str_replace("\n", "", $result['ssl_cert_file'])); } /** * * @depends testadmincertificatesupdate */ public function testcustomercertificatesdelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = certificates::getlocal($customer_userdata, array( 'id' =&gt; 1 ))-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;asserttrue(isset($result['domainid']) &amp;&amp; $result['domainid'] &gt; 0); } private function generatekey() { $dn = array( "countryname" =&gt; "de", "stateorprovincename" =&gt; "hessen", "localityname" =&gt; "frankfurt", "organizationname" =&gt; "froxlor", "organizationalunitname" =&gt; "testing", "commonname" =&gt; "test2.local", "emailaddress" =&gt; "team@froxlor.org" ); // generate key pair $privkey = openssl_pkey_new(array( "private_key_bits" =&gt; 2048, "private_key_type" =&gt; openssl_keytype_rsa )); // generate csr $csr = openssl_csr_new($dn, $privkey, array( 'digest_alg' =&gt; 'sha256' )); // generate self-signed certificate $sscert = openssl_csr_sign($csr, null, $privkey, 365, array( 'digest_alg' =&gt; 'sha256' )); // export openssl_x509_export($sscert, $certout); openssl_pkey_export($privkey, $pkeyout, null); return array( 'cert' =&gt; $certout, 'key' =&gt; $pkeyout ); } }</file><file name="tests/SubDomains/SubDomainsTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\subdomains; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\subdomains * @covers \froxlor\api\commands\domains * @covers \froxlor\api\commands\customers * @covers \froxlor\api\commands\admins */ class subdomainstest extends testcase { public function testcustomersubdomainsadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'subdomain' =&gt; 'mysub', 'domain' =&gt; 'test2.local' ]; $json_result = subdomains::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('mysub.test2.local', $result['domain']); } public function testresellersubdomainsadd() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $data = [ 'subdomain' =&gt; 'mysub2', 'domain' =&gt; 'test2.local', 'customerid' =&gt; 1 ]; $json_result = subdomains::getlocal($reseller_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('mysub2.test2.local', $result['domain']); } public function testcustomersubdomainsaddnopunycode() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'subdomain' =&gt; 'xn--asd', 'domain' =&gt; 'unknown.froxlor.org' ]; $this-&gt;expectexceptionmessage('you must specify punycode (idna). domain automatically converted'); subdomains::getlocal($customer_userdata, $data)-&gt;add(); } public function testcustomersubdomainsaddmaindomainunknown() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'subdomain' =&gt; 'wohoo', 'domain' =&gt; 'unknown.froxlor.org' ]; $this-&gt;expectexceptionmessage('the main-domain unknown.froxlor.org exist.'); subdomains::getlocal($customer_userdata, $data)-&gt;add(); } public function testcustomersubdomainsaddinvaliddomain() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'subdomain' =&gt; '#+?', 'domain' =&gt; 'unknown.froxlor.org' ]; $this-&gt;expectexceptionmessage("wrong input field 'domain'"); subdomains::getlocal($customer_userdata, $data)-&gt;add(); } /** * * @depends testcustomersubdomainsadd */ public function testadminsubdomainsget() { global $admin_userdata; $data = [ 'domainname' =&gt; 'mysub.test2.local' ]; $json_result = subdomains::getlocal($admin_userdata, $data)-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('mysub.test2.local', $result['domain']); $this-&gt;assertequals(1, $result['customerid']); } /** * * @depends testcustomersubdomainsadd */ public function testadminsubdomainsgetmaindomain() { global $admin_userdata; $data = [ 'domainname' =&gt; 'test2.local' ]; $json_result = subdomains::getlocal($admin_userdata, $data)-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test2.local', $result['domain']); $this-&gt;assertequals(1, $result['customerid']); } /** * * @depends testcustomersubdomainsadd */ public function testadminsubdomainsupdate() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'mysub.test2.local', 'path' =&gt; 'mysub.test2.local', 'isemaildomain' =&gt; 1, 'customerid' =&gt; $customer_userdata['customerid'] ]; $json_result = subdomains::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals($customer_userdata['documentroot'] . 'mysub.test2.local/', $result['documentroot']); } /** * * @depends testadminsubdomainsupdate */ public function testcustomersubdomainsupdate() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domainname' =&gt; 'mysub.test2.local', 'url' =&gt; 'https://www.froxlor.org/', 'isemaildomain' =&gt; 0 ]; $json_result = subdomains::getlocal($customer_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('https://www.froxlor.org/', $result['documentroot']); } public function testcustomersubdomainslist() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = subdomains::getlocal($customer_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(3, $result['count']); $json_result = subdomains::getlocal($customer_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(3, $result); } public function testresellersubdomainslist() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $json_result = subdomains::getlocal($reseller_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(3, $result['count']); $json_result = subdomains::getlocal($reseller_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(3, $result); } public function testadminsubdomainslistwithcustomer() { global $admin_userdata; $json_result = subdomains::getlocal($admin_userdata, [ 'loginname' =&gt; 'test1' ])-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(3, $result['count']); $json_result = subdomains::getlocal($admin_userdata, [ 'loginname' =&gt; 'test1' ])-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(3, $result); } /** * * @depends testcustomersubdomainslist */ public function testcustomersubdomainsdelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = subdomains::getlocal($customer_userdata, [ 'domainname' =&gt; 'mysub.test2.local' ])-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('mysub.test2.local', $result['domain']); $this-&gt;assertequals($customer_userdata['customerid'], $result['customerid']); } public function testcustomersubdomainsadddnsletsencryptfail() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); \froxlor\settings::set('system.le_domain_dnscheck', 1); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'subdomain' =&gt; 'nodns', 'domain' =&gt; 'test2.local', 'letsencrypt' =&gt; 1 ]; $this-&gt;expectexceptioncode(400); $this-&gt;expectexceptionmessage('the domains dns include chosen ip addresses. let\'s encrypt certificate generation possible.'); subdomains::getlocal($customer_userdata, $data)-&gt;add(); } }</file><file name="tests/Emails/EmailsTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\settings; use froxlor\database\database; use froxlor\api\commands\customers; use froxlor\api\commands\emails; use froxlor\api\commands\emailforwarders; use froxlor\api\commands\emailaccounts; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\emails * @covers \froxlor\api\commands\emailforwarders * @covers \froxlor\api\commands\emailaccounts * @covers \froxlor\api\commands\customers * @covers \froxlor\api\commands\admins */ class mailstest extends testcase { public function testcustomeremailsadd() { global $admin_userdata; // set domains hidden test whether internal flag works settings::set('panel.customer_hide_options', 'domains', true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'email_part' =&gt; 'info', 'domain' =&gt; 'test2.local', 'description' =&gt; 'awesome email' ]; $json_result = emails::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals("info@test2.local", $result['email_full']); $this-&gt;assertequals(0, $result['iscatchall']); $this-&gt;assertequals('awesome email', $result['description']); // reset setting settings::set('panel.customer_hide_options', '', true); } public function testadminemailsadd() { global $admin_userdata; $data = [ 'email_part' =&gt; 'catchall', 'domain' =&gt; 'test2.local', 'iscatchall' =&gt; 1, 'customerid' =&gt; 1 ]; $json_result = emails::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals("catchall@test2.local", $result['email_full']); $this-&gt;assertequals(1, $result['iscatchall']); } public function testadminemailsupdate() { global $admin_userdata; $data = [ 'emailaddr' =&gt; 'catchall@test2.local', 'iscatchall' =&gt; 0, 'customerid' =&gt; 1 ]; $json_result = emails::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(0, $result['iscatchall']); } public function testcustomeremailsupdate() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'emailaddr' =&gt; 'catchall@test2.local', 'iscatchall' =&gt; 1, 'description' =&gt; 'now catchall' ]; $json_result = emails::getlocal($customer_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['iscatchall']); $this-&gt;assertequals('now catchall', $result['description']); } public function testcustomeremailforwardersadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'emailaddr' =&gt; 'info@test2.local', 'destination' =&gt; 'other@domain.tld' ]; $json_result = emailforwarders::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('other@domain.tld', $result['destination']); } /** * * @depends testcustomeremailforwardersadd */ public function testcustomeremailforwardersaddnomoreresources() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $customer_userdata['email_forwarders_used'] = $customer_userdata['email_forwarders']; $this-&gt;expectexceptioncode(406); $this-&gt;expectexceptionmessage("no resources available"); emailforwarders::getlocal($customer_userdata)-&gt;add(); } /** * * @depends testcustomeremailforwardersaddnomoreresources */ public function testcustomeremailforwardersaddemailhidden() { global $admin_userdata; settings::set('panel.customer_hide_options', 'email', true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(405); $this-&gt;expectexceptionmessage("you cannot access resource"); emailforwarders::getlocal($customer_userdata)-&gt;add(); } /** * * @depends testcustomeremailforwardersaddemailhidden */ public function testcustomeremailforwardersdeleteemailhidden() { global $admin_userdata; settings::set('panel.customer_hide_options', 'email', true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(405); $this-&gt;expectexceptionmessage("you cannot access resource"); emailforwarders::getlocal($customer_userdata)-&gt;delete(); } /** * * @depends testcustomeremailforwardersdeleteemailhidden */ public function testcustomeremailforwardersaddanother() { global $admin_userdata; settings::set('panel.customer_hide_options', '', true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'emailaddr' =&gt; 'info@test2.local', 'destination' =&gt; 'other2@domain.tld' ]; $json_result = emailforwarders::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('other@domain.tld other2@domain.tld', $result['destination']); } /** * * @depends testcustomeremailforwardersaddanother */ public function testcustomeremailforwarderslisting() { global $admin_userdata; settings::set('panel.customer_hide_options', '', true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'emailaddr' =&gt; 'info@test2.local' ]; $json_result = emailforwarders::getlocal($customer_userdata, $data)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['count']); $this-&gt;assertequals(0, $result['list'][0]['id']); $this-&gt;assertequals('other@domain.tld', $result['list'][0]['address']); $this-&gt;assertequals(1, $result['list'][1]['id']); $this-&gt;assertequals('other2@domain.tld', $result['list'][1]['address']); $json_result = emailforwarders::getlocal($customer_userdata, $data)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result); } /** * * @depends testcustomeremailforwardersdeleteemailhidden */ public function testcustomeremailforwardersaddwithspaces() { global $admin_userdata; settings::set('panel.customer_hide_options', '', true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'emailaddr' =&gt; 'info@test2.local', 'destination' =&gt; 'other3@domain.tld ' ]; $json_result = emailforwarders::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('other@domain.tld other2@domain.tld other3@domain.tld', $result['destination']); } /** * * @depends testcustomeremailforwardersadd */ public function testcustomeremailforwardersaddexistingasmail() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'emailaddr' =&gt; 'info@test2.local', 'destination' =&gt; 'info@test2.local' ]; $this-&gt;expectexceptionmessage("the forwarder info@test2.local already exists active email-address."); emailforwarders::getlocal($customer_userdata, $data)-&gt;add(); } /** * * @depends testcustomeremailforwardersadd */ public function testcustomeremailforwardersaddexistingasdestination() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'emailaddr' =&gt; 'info@test2.local', 'destination' =&gt; 'other@domain.tld' ]; $this-&gt;expectexceptionmessage('you already defined forwarder "other@domain.tld"'); emailforwarders::getlocal($customer_userdata, $data)-&gt;add(); } public function testcustomeremailforwardersaddinvalid() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'emailaddr' =&gt; 'info@test2.local', 'destination' =&gt; '@domain.com' ]; $this-&gt;expectexceptionmessage("the forwarder domain.com contains invalid character(s) incomplete."); emailforwarders::getlocal($customer_userdata, $data)-&gt;add(); } public function testadminemailforwadersundefinedget() { global $admin_userdata; $this-&gt;expectexceptioncode(303); emailforwarders::getlocal($admin_userdata)-&gt;get(); } public function testadminemailforwadersundefinedupdate() { global $admin_userdata; $this-&gt;expectexceptioncode(303); emailforwarders::getlocal($admin_userdata)-&gt;update(); } /** * * @depends testcustomeremailforwardersaddanother */ public function testcustomeremailforwardersdelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'emailaddr' =&gt; 'info@test2.local', 'forwarderid' =&gt; 1 ]; $json_result = emailforwarders::getlocal($customer_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('other@domain.tld other3@domain.tld', $result['destination']); } /** * * @depends testcustomeremailforwardersaddanother */ public function testcustomeremailforwardersdeleteunknown() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'emailaddr' =&gt; 'info@test2.local', 'forwarderid' =&gt; 1337 ]; $this-&gt;expectexceptioncode(404); $this-&gt;expectexceptionmessage("unknown forwarder id"); emailforwarders::getlocal($customer_userdata, $data)-&gt;delete(); } public function testcustomeremailslisting() { global $admin_userdata; settings::set('panel.customer_hide_options', '', true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = emails::getlocal($customer_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['count']); $this-&gt;assertequals("info@test2.local", $result['list'][0]['email']); $this-&gt;assertequals("@test2.local", $result['list'][1]['email']); $json_result = emails::getlocal($customer_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result); } public function testcustomeremailaccountsadd() { global $admin_userdata; settings::set('panel.sendalternativemail', 1, true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'emailaddr' =&gt; 'info@test2.local', 'email_password' =&gt; \froxlor\system\crypt::generatepassword(), 'alternative_email' =&gt; 'noone@example.com', 'email_quota' =&gt; 1337, 'sendinfomail' =&gt; travis_ci == 1 ? 0 : 1 ]; $json_result = emailaccounts::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['popaccountid']); switch (settings::get('system.passwordcryptfunc')) { case 'argon2i': $cpprefix = '{argon2i}'; break; case 'argon2id': $cpprefix = '{argon2id}'; break; default: $cpprefix = '{blf-crypt}'; break; } // password returned api, query directly $sel_stmt = database::prepare("select `password_enc` `" . table_mail_users . "` `email` = :email"); $result2 = database::pexecute_first($sel_stmt, ['email' =&gt; $result['email']]); $this-&gt;assertequals($cpprefix, substr($result2['password_enc'], 0, strlen($cpprefix))); } public function testadminemailaccountsupdate() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'emailaddr' =&gt; 'info@test2.local', 'email_password' =&gt; \froxlor\system\crypt::generatepassword(), 'alternative_email' =&gt; 'noone@example.com', 'email_quota' =&gt; 1338 ]; $json_result = emailaccounts::getlocal($customer_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; // quota disabled $this-&gt;assertequals(0, $result['quota']); } public function testadminemailaccountsupdatedeactivated() { global $admin_userdata; // disable $data = [ 'emailaddr' =&gt; 'info@test2.local', 'loginname' =&gt; 'test1', 'deactivated' =&gt; 1 ]; $json_result = emailaccounts::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; // quota disabled $this-&gt;assertequals(0, $result['imap']); $this-&gt;assertequals(0, $result['pop3']); $this-&gt;assertequals('n', $result['postfix']); // re-enable $data = [ 'emailaddr' =&gt; 'info@test2.local', 'loginname' =&gt; 'test1', 'deactivated' =&gt; 0 ]; $json_result = emailaccounts::getlocal($admin_userdata, $data)-&gt;update(); $result = json_decode($json_result, true)['data']; // quota disabled $this-&gt;assertequals(1, $result['imap']); $this-&gt;assertequals(1, $result['pop3']); $this-&gt;assertequals('y', $result['postfix']); } public function testadminemailaccountsundefinedget() { global $admin_userdata; $this-&gt;expectexceptioncode(303); emailaccounts::getlocal($admin_userdata)-&gt;get(); } public function testadminemailaccountsundefinedlisting() { global $admin_userdata; $this-&gt;expectexceptioncode(303); emailaccounts::getlocal($admin_userdata)-&gt;listing(); } public function testcustomeremailaccountsdelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'emailaddr' =&gt; 'info@test2.local', 'delete_userfiles' =&gt; 1 ]; $json_result = emailaccounts::getlocal($customer_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(0, $result['popaccountid']); } public function testcustomeremailsdelete() { global $admin_userdata; // remove possible existing delete tasks database::query("truncate `" . table_panel_tasks . "`"); settings::set('panel.sendalternativemail', 0, true); // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; // add account $data = [ 'emailaddr' =&gt; 'info@test2.local', 'email_password' =&gt; \froxlor\system\crypt::generatepassword(), 'alternative_email' =&gt; 'noone@example.com', 'sendinfomail' =&gt; travis_ci == 1 ? 0 : 1 ]; $json_result = emailaccounts::getlocal($customer_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['popaccountid']); // delete whole address $data = [ 'emailaddr' =&gt; 'info@test2.local', 'delete_userfiles' =&gt; 1 ]; $json_result = emails::getlocal($customer_userdata, $data)-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals("info@test2.local", $result['email_full']); } }</file><file name="tests/Customers/HostingPlansTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\settings; use froxlor\database\database; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\hostingplans; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\hostingplans * @covers \froxlor\api\commands\customers */ class hostingplanstest extends testcase { public function testadminplanadd() { global $admin_userdata; $data = [ 'name' =&gt; 'test', 'description' =&gt; 'first test plan', 'diskspace' =&gt; 0, 'diskspace_ul' =&gt; 1, 'traffic' =&gt; - 1, 'subdomains' =&gt; 15, 'emails' =&gt; - 1, 'email_accounts' =&gt; 15, 'email_forwarders' =&gt; 15, 'email_imap' =&gt; 1, 'email_pop3' =&gt; 0, 'ftps' =&gt; 15, 'mysqls' =&gt; 15, 'phpenabled' =&gt; 1, 'dnsenabled' =&gt; 1, 'allowed_phpconfigs' =&gt; array( 1 ) ]; $json_result = hostingplans::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $result['value'] = json_decode($result['value'], true); foreach ($result['value'] $index =&gt; $value) { $result[$index] = $value; } $this-&gt;assertequals('test', $result['name']); $this-&gt;assertequals(- 1, $result['diskspace']); $this-&gt;assertequals(15, $result['email_accounts']); $this-&gt;assertequals([ 1 ], $result['allowed_phpconfigs']); } public function testadminplanaddemptyname() { global $admin_userdata; $data = [ 'description' =&gt; 'test plan' ]; $this-&gt;expectexceptionmessage('requested parameter "name" could found "hostingplans:add"'); hostingplans::getlocal($admin_userdata, $data)-&gt;add(); $data['name'] = null; $this-&gt;expectexceptionmessage('requested parameter "name" empty "hostingplans:add"'); hostingplans::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadminplanadd */ public function testadminplanlist() { global $admin_userdata; $json_result = hostingplans::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $json_result = hostingplans::getlocal($admin_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result); } /** * * @depends testadminplanadd */ public function testresellerplanlist() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $json_result = hostingplans::getlocal($reseller_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(0, $result['count']); $json_result = hostingplans::getlocal($reseller_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(0, $result); } /** * * @depends testadminplanadd */ public function testcustomerplanlist() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); $json_result = hostingplans::getlocal($customer_userdata)-&gt;listing(); $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); $json_result = hostingplans::getlocal($customer_userdata)-&gt;listingcount(); } public function testcustomerplanadd() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); $json_result = hostingplans::getlocal($customer_userdata)-&gt;add(); } public function testcustomerplanget() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); $json_result = hostingplans::getlocal($customer_userdata)-&gt;get(); } public function testcustomerplanupdate() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); $json_result = hostingplans::getlocal($customer_userdata)-&gt;update(); } public function testcustomerplandelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); $json_result = hostingplans::getlocal($customer_userdata)-&gt;delete(); } public function testadminplangetnotfound() { global $admin_userdata; $this-&gt;expectexceptioncode(404); $this-&gt;expectexceptionmessage("hosting-plan id #999 could found"); hostingplans::getlocal($admin_userdata, array( 'id' =&gt; 999 ))-&gt;get(); } /** * * @depends testadminplanadd */ public function testadminplanupdate() { global $admin_userdata; hostingplans::getlocal($admin_userdata, array( 'planname' =&gt; 'test', 'name' =&gt; '', 'ftps' =&gt; '20' ))-&gt;update(); $json_result = hostingplans::getlocal($admin_userdata, array( 'planname' =&gt; 'test' ))-&gt;get(); $result = json_decode($json_result, true)['data']; $result['value'] = json_decode($result['value'], true); foreach ($result['value'] $index =&gt; $value) { $result[$index] = $value; } $this-&gt;assertequals(20, $result['ftps']); $this-&gt;assertequals(- 1, $result['diskspace']); $this-&gt;assertequals(15, $result['email_accounts']); $this-&gt;assertequals([ 1 ], $result['allowed_phpconfigs']); } public function testresellerplandeletenotowned() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $this-&gt;expectexceptioncode(404); hostingplans::getlocal($reseller_userdata, array( 'planname' =&gt; 'test' ))-&gt;delete(); } /** * * @depends testadminplanadd */ public function testadminplandelete() { global $admin_userdata; // add new customer $data = [ 'name' =&gt; 'test2', 'description' =&gt; 'second test plan' ]; hostingplans::getlocal($admin_userdata, $data)-&gt;add(); $json_result = hostingplans::getlocal($admin_userdata, array( 'planname' =&gt; 'test2' ))-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test2', $result['name']); } /** * * @depends testadminplanadd */ public function testadmincustomersaddwithhostingplan() { global $admin_userdata; $json_result = hostingplans::getlocal($admin_userdata, array( 'planname' =&gt; 'test' ))-&gt;get(); $result = json_decode($json_result, true)['data']; $data = [ 'new_loginname' =&gt; 'test1hp', 'email' =&gt; 'team@froxlor.org', 'firstname' =&gt; 'test', 'name' =&gt; 'testman', 'customernumber' =&gt; 1337, 'createstdsubdomain' =&gt; 0, 'new_customer_password' =&gt; 'h0lymo1y', 'sendpassword' =&gt; travis_ci == 1 ? 0 : 1, 'store_defaultindex' =&gt; 1, 'custom_notes' =&gt; 'secret', 'custom_notes_show' =&gt; 0, 'gender' =&gt; 5, 'hosting_plan_id' =&gt; $result['id'] ]; $json_result = customers::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(- 1024, $result['diskspace']); $this-&gt;assertequals(15, $result['subdomains']); $this-&gt;assertequals(1, $result['phpenabled']); $this-&gt;assertjsonstringequalsjsonstring(json_encode([ 1 ]), $result['allowed_phpconfigs']); // remove customer customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1hp' ))-&gt;delete(); } }</file><file name="tests/Customers/CustomersTest.php">&lt;?php use phpunit\framework\testcase; use froxlor\settings; use froxlor\database\database; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\subdomains; use froxlor\api\commands\ftps; /** * * @covers \froxlor\api\apicommand * @covers \froxlor\api\apiparameter * @covers \froxlor\api\commands\customers * @covers \froxlor\api\commands\admins */ class customerstest extends testcase { public function testadmincustomersadd() { global $admin_userdata; $data = [ 'new_loginname' =&gt; 'test1', 'email' =&gt; 'team@froxlor.org', 'firstname' =&gt; 'test', 'name' =&gt; 'testman', 'customernumber' =&gt; 1337, 'diskspace' =&gt; 0, 'diskspace_ul' =&gt; 1, 'traffic' =&gt; - 1, 'subdomains' =&gt; 15, 'emails' =&gt; - 1, 'email_accounts' =&gt; 15, 'email_forwarders' =&gt; 15, 'email_imap' =&gt; 1, 'email_pop3' =&gt; 0, 'ftps' =&gt; 15, 'mysqls' =&gt; 15, 'createstdsubdomain' =&gt; 1, 'new_customer_password' =&gt; 'h0lymo1y', 'sendpassword' =&gt; travis_ci == 1 ? 0 : 1, 'phpenabled' =&gt; 1, 'dnsenabled' =&gt; 1, 'store_defaultindex' =&gt; 1, 'custom_notes' =&gt; 'secret', 'custom_notes_show' =&gt; 0, 'gender' =&gt; 5, 'allowed_phpconfigs' =&gt; array( 1 ) ]; $json_result = customers::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['customerid']); $this-&gt;assertequals('team@froxlor.org', $result['email']); $this-&gt;assertequals(1337, $result['customernumber']); $this-&gt;assertequals(15, $result['subdomains']); $this-&gt;assertequals('secret', $result['custom_notes']); $stdsubdomain = $result['standardsubdomain'] ?? false; (! $stdsubdomain) { $this-&gt;fail('no standardsubdomain one'); } else { // validate std-subdomain added $json_result = subdomains::getlocal($admin_userdata, array( 'id' =&gt; $result['standardsubdomain'] ))-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test1.dev.froxlor.org', $result['domain']); } } public function testadmincustomersaddemptymail() { global $admin_userdata; $data = [ 'new_loginname' =&gt; 'test2', 'email' =&gt; ' ', 'firstname' =&gt; 'test2', 'name' =&gt; 'testman2' ]; $this-&gt;expectexceptionmessage('requested parameter "email" empty "customers:add"'); customers::getlocal($admin_userdata, $data)-&gt;add(); } public function testadmincustomersaddinvalidmail() { global $admin_userdata; $data = [ 'new_loginname' =&gt; 'test2', 'email' =&gt; 'test.froxlor.org', 'firstname' =&gt; 'test2', 'name' =&gt; 'testman2' ]; $this-&gt;expectexceptionmessage("email-address test.froxlor.org contains invalid characters incomplete"); customers::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadmincustomersadd */ public function testadmincustomerslist() { global $admin_userdata; $json_result = customers::getlocal($admin_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;assertfalse(isset($result['list'][0]['webspace_used'])); $json_result = customers::getlocal($admin_userdata, [ 'show_usages' =&gt; true ])-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['count']); $this-&gt;asserttrue(isset($result['list'][0]['webspace_used'])); $json_result = customers::getlocal($admin_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result); } /** * * @depends testadmincustomersadd */ public function testresellercustomerslist() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $json_result = customers::getlocal($reseller_userdata)-&gt;listing(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(0, $result['count']); $json_result = customers::getlocal($reseller_userdata)-&gt;listingcount(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(0, $result); } /** * * @depends testadmincustomersadd */ public function testcustomercustomerslist() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); $json_result = customers::getlocal($customer_userdata)-&gt;listing(); $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); $json_result = customers::getlocal($customer_userdata)-&gt;listingcount(); } /** * * @depends testadmincustomersadd */ public function testcustomercustomersget() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $json_result = customers::getlocal($customer_userdata, array( 'id' =&gt; $customer_userdata['customerid'] ))-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['customerid']); $this-&gt;assertequals('team@froxlor.org', $result['email']); $this-&gt;assertequals(1337, $result['customernumber']); $this-&gt;assertequals(15, $result['subdomains']); $this-&gt;assertequals('froxlor', $result['theme']); $this-&gt;assertequals('', $result['custom_notes']); } public function testadmincustomersgetnotfound() { global $admin_userdata; $this-&gt;expectexceptioncode(404); $this-&gt;expectexceptionmessage("customer id #999 could found"); customers::getlocal($admin_userdata, array( 'id' =&gt; 999 ))-&gt;get(); } /** * * @depends testadmincustomersadd */ public function testcustomercustomersgetforeign() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexception(exception::class); $this-&gt;expectexceptioncode(401); customers::getlocal($customer_userdata, array( 'id' =&gt; 2 ))-&gt;get(); } /** * * @depends testadmincustomersadd */ public function testadmincustomerupdatedeactivate() { global $admin_userdata; // get customer customers::getlocal($admin_userdata, array( 'id' =&gt; 1, 'deactivated' =&gt; 1 ))-&gt;update(); // get customer check results $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(1, $result['customerid']); $this-&gt;assertequals(1, $result['deactivated']); // standard-subdomains removed deactivation $this-&gt;assertequals(0, $result['standardsubdomain']); } /** * * @depends testadmincustomerupdatedeactivate */ public function testcustomercustomersgetwhendeactivated() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexception(exception::class); $this-&gt;expectexceptioncode(406); $this-&gt;expectexceptionmessage("account suspended"); customers::getlocal($customer_userdata, array( 'id' =&gt; $customer_userdata['customerid'] ))-&gt;get(); } /** * * @depends testcustomercustomersgetwhendeactivated */ public function testcustomercustomersupdate() { global $admin_userdata; // reactivate customer // get customer customers::getlocal($admin_userdata, array( 'id' =&gt; 1, 'deactivated' =&gt; 0 ))-&gt;update(); // get customer $json_result = customers::getlocal($admin_userdata, array( 'id' =&gt; 1 ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; customers::getlocal($customer_userdata, array( 'id' =&gt; $customer_userdata['customerid'], 'def_language' =&gt; 'english', 'theme' =&gt; 'froxlor', 'new_customer_password' =&gt; 'h0lymo1y2' ))-&gt;update(); $json_result = customers::getlocal($customer_userdata, array( 'id' =&gt; $customer_userdata['customerid'] ))-&gt;get(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('froxlor', $result['theme']); $this-&gt;assertequals('english', $result['def_language']); } /** * * @depends testadmincustomersadd */ public function testresellercustomersaddallocatemore() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $this-&gt;expectexceptionmessage("you cannot allocate resources yourself."); // add new customer $data = [ 'new_loginname' =&gt; 'test2', 'email' =&gt; 'test2@froxlor.org', 'firstname' =&gt; 'test', 'name' =&gt; 'testman', 'customernumber' =&gt; 1338, 'subdomains' =&gt; - 1, 'new_customer_password' =&gt; 'h0lymo1y' ]; customers::getlocal($reseller_userdata, $data)-&gt;add(); } public function testcustomercustomersdelete() { global $admin_userdata; // get customer $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;get(); $customer_userdata = json_decode($json_result, true)['data']; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); customers::getlocal($customer_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;delete(); } public function testresellercustomersdeletenotowned() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; $this-&gt;expectexceptioncode(404); customers::getlocal($reseller_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;delete(); } public function testadmincustomersdelete() { global $admin_userdata; // add new customer $data = [ 'new_loginname' =&gt; 'test2', 'email' =&gt; 'test2@froxlor.org', 'firstname' =&gt; 'test', 'name' =&gt; 'testman', 'customernumber' =&gt; 1338, 'new_customer_password' =&gt; 'h0lymo1y' ]; customers::getlocal($admin_userdata, $data)-&gt;add(); $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test2' ))-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('test2', $result['loginname']); } public function testadmincustomersunlock() { global $admin_userdata; // update customer correct test-data database::query("update `" . table_panel_customers . "` set `loginfail_count` = '5' `loginname` = 'test1'"); $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;unlock(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(0, $result['loginfail_count']); } public function testadmincustomersunlocknotallowed() { global $admin_userdata; $testadmin_userdata = $admin_userdata; $testadmin_userdata['adminsession'] = 0; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); customers::getlocal($testadmin_userdata, array( 'loginname' =&gt; 'test1' ))-&gt;unlock(); } public function testadmincustomersmovenotallowed() { global $admin_userdata; $testadmin_userdata = $admin_userdata; $testadmin_userdata['change_serversettings'] = 0; $this-&gt;expectexceptioncode(403); $this-&gt;expectexceptionmessage("not allowed execute given command."); customers::getlocal($testadmin_userdata, array( 'loginname' =&gt; 'test1', 'adminid' =&gt; 1 ))-&gt;move(); } public function testadmincustomersmovetargetissource() { global $admin_userdata; $this-&gt;expectexceptioncode(406); $this-&gt;expectexceptionmessage("cannot move customer admin/reseller currently assigned to"); customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1', 'adminid' =&gt; 1 ))-&gt;move(); } public function testadmincustomersmove() { global $admin_userdata; $json_result = customers::getlocal($admin_userdata, array( 'loginname' =&gt; 'test1', 'adminid' =&gt; 2 ))-&gt;move(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals(2, $result['adminid']); } /** * * @depends testadmincustomersmove */ public function testadmincustomersaddloginnameissystemaccount() { global $admin_userdata; $data = [ 'new_loginname' =&gt; 'web1', 'email' =&gt; 'team@froxlor.org', 'firstname' =&gt; 'test', 'name' =&gt; 'testman', 'customernumber' =&gt; 1338, 'diskspace' =&gt; - 1, 'traffic' =&gt; - 1, 'subdomains' =&gt; 15, 'emails' =&gt; - 1, 'email_accounts' =&gt; 15, 'email_forwarders' =&gt; 15, 'email_imap' =&gt; 1, 'email_pop3' =&gt; 0, 'ftps' =&gt; 15, 'mysqls' =&gt; 15, 'createstdsubdomain' =&gt; 1, 'new_customer_password' =&gt; 'h0lymo1y', 'sendpassword' =&gt; travis_ci == 1 ? 0 : 1, 'phpenabled' =&gt; 1, 'store_defaultindex' =&gt; 1, 'custom_notes' =&gt; 'secret', 'custom_notes_show' =&gt; 0, 'gender' =&gt; 5, 'allowed_phpconfigs' =&gt; array( 1 ) ]; $this-&gt;expectexceptionmessage('you cannot create accounts begin "web", prefix set used automatic account-naming. please enter another account name.'); customers::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadmincustomersaddloginnameissystemaccount */ public function testadmincustomersaddautologinname() { global $admin_userdata; settings::set('system.lastaccountnumber', 0, true); $data = [ 'new_loginname' =&gt; '', 'email' =&gt; 'team@froxlor.org', 'firstname' =&gt; 'test2', 'name' =&gt; 'testman2', 'customernumber' =&gt; 1338, 'sendpassword' =&gt; 0, 'perlenabled' =&gt; 2, 'dnsenabled' =&gt; 4, 'createstdsubdomain' =&gt; 0 ]; $json_result = customers::getlocal($admin_userdata, $data)-&gt;add(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('web1', $result['loginname']); $this-&gt;assertequals(1338, $result['customernumber']); } /** * * @depends testadmincustomersaddautologinname */ public function testadmincustomersaddloginnameexists() { global $admin_userdata; $data = [ 'new_loginname' =&gt; 'test1', 'email' =&gt; 'team@froxlor.org', 'firstname' =&gt; 'test2', 'name' =&gt; 'testman2', 'customernumber' =&gt; 1339 ]; $this-&gt;expectexceptionmessage('loginname test1 already exists'); customers::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadmincustomersaddloginnameexists */ public function testadmincustomersaddloginnameinvalid() { global $admin_userdata; $data = [ 'new_loginname' =&gt; 'user-', 'email' =&gt; 'team@froxlor.org', 'firstname' =&gt; 'test2', 'name' =&gt; 'testman2', 'customernumber' =&gt; 1339 ]; $this-&gt;expectexceptionmessage('loginname "user-" contains illegal characters.'); customers::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadmincustomersaddloginnameexists */ public function testadmincustomersaddloginnameinvalid2() { global $admin_userdata; $loginname = str_repeat("x", \froxlor\database\database::getsqlusernamelength() + 1); $data = [ 'new_loginname' =&gt; $loginname, 'email' =&gt; 'team@froxlor.org', 'firstname' =&gt; 'test2', 'name' =&gt; 'testman2', 'customernumber' =&gt; 1339 ]; $this-&gt;expectexceptionmessage('loginname contains many characters. ' . (\froxlor\database\database::getsqlusernamelength() - strlen(settings::get('customer.mysqlprefix'))) . ' characters allowed.'); customers::getlocal($admin_userdata, $data)-&gt;add(); } /** * * @depends testadmincustomersaddautologinname */ public function testresellercustomersaddnoftpvalidatedefaultuserexists() { global $admin_userdata; // get reseller $json_result = admins::getlocal($admin_userdata, array( 'loginname' =&gt; 'reseller' ))-&gt;get(); $reseller_userdata = json_decode($json_result, true)['data']; $reseller_userdata['adminsession'] = 1; // set available ftp resources 0 validate customer // added default ftp user customer created regardless // available resource reseller/admin $reseller_userdata['ftps'] = 0; // add new customer $data = [ 'new_loginname' =&gt; 'testftpx', 'email' =&gt; 'testftp@froxlor.org', 'firstname' =&gt; 'test', 'name' =&gt; 'ftpman', 'customernumber' =&gt; 1339, 'new_customer_password' =&gt; 'h0lymo1y' ]; customers::getlocal($reseller_userdata, $data)-&gt;add(); // get ftp user $json_result = ftps::getlocal($reseller_userdata, [ 'username' =&gt; 'testftpx' ])-&gt;get(); $ftp_data = json_decode($json_result, true)['data']; $this-&gt;assertequals("testftpx", $ftp_data['username']); // get rid customer $json_result = customers::getlocal($reseller_userdata, array( 'loginname' =&gt; 'testftpx' ))-&gt;delete(); $result = json_decode($json_result, true)['data']; $this-&gt;assertequals('testftpx', $result['loginname']); } }</file><file name="lib/tables.inc.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ const table_ftp_groups = 'ftp_groups'; const table_ftp_users = 'ftp_users'; const table_ftp_quotalimits = 'ftp_quotalimits'; const table_ftp_quotatallies = 'ftp_quotatallies'; const table_mail_autoresponder = 'mail_autoresponder'; const table_mail_users = 'mail_users'; const table_mail_virtual = 'mail_virtual'; const table_panel_activation = 'panel_activation'; const table_panel_admins = 'panel_admins'; const table_panel_customers = 'panel_customers'; const table_panel_databases = 'panel_databases'; const table_panel_domains = 'panel_domains'; const table_panel_htaccess = 'panel_htaccess'; const table_panel_htpasswds = 'panel_htpasswds'; const table_panel_settings = 'panel_settings'; const table_panel_tasks = 'panel_tasks'; const table_panel_templates = 'panel_templates'; const table_panel_traffic = 'panel_traffic'; const table_panel_traffic_admins = 'panel_traffic_admins'; const table_panel_diskspace = 'panel_diskspace'; const table_panel_ipsandports = 'panel_ipsandports'; const table_panel_log = 'panel_syslog'; const table_panel_phpconfigs = 'panel_phpconfigs'; const table_panel_cronruns = 'cronjobs_run'; const table_panel_redirectcodes = 'redirect_codes'; const table_panel_domainredirects = 'domain_redirect_codes'; const table_panel_domain_ssl_settings = 'domain_ssl_settings'; const table_domaintoip = 'panel_domaintoip'; const table_domain_dns = 'domain_dns_entries'; const table_panel_fpmdaemons = 'panel_fpmdaemons'; const table_panel_plans = 'panel_plans'; const table_api_keys = 'api_keys'; const table_panel_usercolumns = 'panel_usercolumns'; const table_panel_loginlinks = 'panel_loginlinks'; const table_panel_2fa_tokens = 'panel_2fa_tokens';</file><file name="lib/ajax.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor; use exception; use froxlor\ajax\ajax; require_once dirname(__dir__) . '/vendor/autoload.php'; // load user settings (!file_exists('./userdata.inc.php')) { die(); } require_once dirname(__dir__) . '/lib/userdata.inc.php'; require_once dirname(__dir__) . '/lib/functions.php'; require_once dirname(__dir__) . '/lib/tables.inc.php'; // return response try { echo (new ajax)-&gt;handle(); } catch (exception $e) { header("content-type: application/json"); echo \froxlor\api\response::jsonerrorresponse($e-&gt;getmessage(), 500); }</file><file name="lib/config.example.inc.php">&lt;?php /** * change options either true false */ return [ /** * enable/disable possibility update froxlor within web-interface, * recommended value debian/ubuntu package users false rely apt version mixup. * also useful providers manage servers give admin access froxlor handle * updates way providers (e.g. automation, etc.) * * default: false */ 'enable_webupdate' =&gt; false, /** * settings major impact system values used executed high * privileges system require admin-user set enabled otp corresponding * account change values. * disable extra security validation, set value true * * default: false */ 'disable_otp_security_check' =&gt; false, /** * debugging/development purposes only. * enable display php related issue (notices, warnings, etc.; depending php.ini) froxlor * * default: false */ 'display_php_errors' =&gt; false, ];</file><file name="lib/init.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ // define default theme configurehint, etc. $_deftheme = 'froxlor'; require dirname(__dir__) . '/lib/functions.php'; // validate correct php version (version_compare("7.4.0", php_version, "&gt;=")) { die(view($_deftheme . '/misc/phprequirementfailed.html.twig', [ '{{ basehref }}' =&gt; '', '{{ froxlor_min_version }}' =&gt; '7.4.0', '{{ current_version }}' =&gt; php_version, '{{ current_year }}' =&gt; date('y', time()), ])); } // validate vendor autoloader (!file_exists(dirname(__dir__) . '/vendor/autoload.php')) { die(view($_deftheme . '/misc/vendormissinghint.html.twig', [ '{{ basehref }}' =&gt; '', '{{ froxlor_install_dir }}' =&gt; dirname(__dir__), '{{ current_year }}' =&gt; date('y', time()), ])); } require dirname(__dir__) . '/vendor/autoload.php'; use froxlor\currentuser; use froxlor\filedir; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\http\ratelimiter; use froxlor\idna\idnawrapper; use froxlor\install\update; use froxlor\language; use froxlor\phphelper; use froxlor\settings; use froxlor\system\mailer; use froxlor\ui\html; use froxlor\ui\linker; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\install\requirements; // include mysql-tabledefinitions require froxlor::getinstalldir() . '/lib/tables.inc.php'; ui::sendheaders(); ui::inittwig(); /** * register globals security fix */ request::cleanall(); unset($_); unset($key); $filename = htmlentities(basename($_server['script_name'])); // check whether userdata file exists (!file_exists(froxlor::getinstalldir() . '/lib/userdata.inc.php')) { ui::twig()-&gt;addglobal('install_mode', '1'); echo ui::twig()-&gt;render($_deftheme . '/misc/configurehint.html.twig'); die(); } // check whether read userdata file (!is_readable(froxlor::getinstalldir() . '/lib/userdata.inc.php')) { // get possible owner $posixusername = posix_getpwuid(posix_getuid()); $posixgroup = posix_getgrgid(posix_getgid()); ui::twig()-&gt;addglobal('install_mode', '1'); echo ui::twig()-&gt;render($_deftheme . '/misc/ownershiphint.html.twig', [ 'user' =&gt; $posixusername['name'], 'group' =&gt; $posixgroup['name'], 'installdir' =&gt; froxlor::getinstalldir() ]); die(); } // include mysql-username/passwort etc. require froxlor::getinstalldir() . '/lib/userdata.inc.php'; (!isset($sql) || !is_array($sql)) { ui::twig()-&gt;addglobal('install_mode', '1'); echo ui::twig()-&gt;render($_deftheme . '/misc/configurehint.html.twig'); die(); } /** * show nice note requested domain "unknown" froxlor thus lead vhost */ $req_host = ui::getcookiehost(); ($req_host != settings::get('system.hostname') &amp;&amp; settings::get('panel.is_configured') == 1 &amp;&amp; !filter_var($req_host, filter_validate_ip) &amp;&amp; ( empty(settings::get('system.froxloraliases')) || (!empty(settings::get('system.froxloraliases')) &amp;&amp; !in_array($req_host, array_map('trim', explode(',', settings::get('system.froxloraliases'))))) )) { // froxlor system-hostname, show info page domains configured froxlor $redirect_file = filedir::getunknowndomaintemplate($req_host ?? "non-detectable http-host"); header('location: '.$redirect_file); die(); } // validate php-extensions requirements $loadedextensions = get_loaded_extensions(); $missingextensions = []; foreach (requirements::required_extensions $requiredextension) { (in_array($requiredextension, $loadedextensions)) { continue; } $missingextensions[] = $requiredextension; } (!empty($missingextensions)) { ui::twig()-&gt;addglobal('install_mode', '1'); echo ui::twig()-&gt;render($_deftheme . '/misc/missingextensionhint.html.twig', [ 'phpversion' =&gt; phpversion(), 'missing_extensions' =&gt; implode(", ", $missingextensions), ]); die(); } // set error-handler @set_error_handler([ '\\froxlor\\phphelper', 'phperrhandler' ]); @set_exception_handler([ '\\froxlor\\phphelper', 'phpexceptionhandler' ]); // send ssl-related headers (later others need working database-connection installation) ui::sendsslheaders(); ratelimiter::run(); // create new idna converter $idna_convert = new idnawrapper(); // re-read user data logged (currentuser::hassession()) { currentuser::rereaduserdata(); } /** * language management */ // set default language anything else // ensure display messages language::setlanguage(settings::get('panel.standardlanguage')); // set language given user (currentuser::hassession()) { (!empty(currentuser::getfield('language')) &amp;&amp; isset(language::getlanguages()[currentuser::getfield('language')])) { language::setlanguage(currentuser::getfield('language')); } else { language::setlanguage(currentuser::getfield('def_language')); } } // initialize link - class $linker = new linker('index.php'); ui::setlinker($linker); /** * global theme-variable */ (update::versioninupdate(settings::get('panel.version'), '2.0.0-beta1')) { $theme = $_deftheme; } else { $theme = (settings::get('panel.default_theme') !== null) ? settings::get('panel.default_theme') : $_deftheme; // overwrite customer/admin theme defined (currentuser::hassession() &amp;&amp; currentuser::getfield('theme') != $theme) { $theme = currentuser::getfield('theme'); } } // check different variant theme used $themevariant = "default"; (preg_match("/([a-z0-9.\-]+)_([a-z0-9.\-]+)/i", $theme, $matches)) { $theme = $matches[1]; $themevariant = $matches[2]; } // check existence theme (@file_exists('templates/' . $theme . '/config.json')) { $_themeoptions = json_decode(file_get_contents('templates/' . $theme . '/config.json'), true); } else { $_themeoptions = null; } // check existence variant theme (is_array($_themeoptions) &amp;&amp; (!array_key_exists('variants', $_themeoptions) || !array_key_exists( $themevariant, $_themeoptions['variants'] ))) { $themevariant = "default"; } (array_key_exists('global', $_themeoptions)) { $_themeoptions['variants'][$themevariant] = phphelper::array_merge_recursive_distinct($_themeoptions['global'], $_themeoptions['variants'][$themevariant]); } // check custom header-graphic $hl_path = 'templates/' . $theme . '/assets/img'; // default theme-image $header_logo = $hl_path . '/' . ($_themeoptions['variants'][$themevariant]['img']['ui'] ?? 'logo_white.png'); $header_logo_login = $hl_path . '/' . ($_themeoptions['variants'][$themevariant]['img']['login'] ?? 'logo_white.png'); (settings::get('panel.logo_overridetheme') == 1 || settings::get('panel.logo_overridecustom') == 1) { // logo settings shall overwrite theme logo possible custom logo $header_logo = settings::get('panel.logo_image_header') ?: $header_logo; $header_logo_login = settings::get('panel.logo_image_login') ?: $header_logo_login; } (settings::get('panel.logo_overridecustom') == 0 &amp;&amp; file_exists($hl_path . '/logo_custom.png')) { // custom theme image (logo_custom.png) overwritten logo_image_* setting $header_logo = $hl_path . '/logo_custom.png'; $header_logo_login = $hl_path . '/logo_custom.png'; (file_exists($hl_path . '/logo_custom_login.png')) { $header_logo_login = $hl_path . '/logo_custom_login.png'; } } $color_scheme = $_themeoptions['variants'][$themevariant]['color-scheme'] ?? 'auto'; ui::twig()-&gt;addglobal('header_logo_login', $header_logo_login); ui::twig()-&gt;addglobal('header_logo', $header_logo); ui::twig()-&gt;addglobal('color_scheme', $color_scheme); /** * redirects index.php (login page) session exists */ (!currentuser::hassession() &amp;&amp; area != 'login') { unset($_session['userinfo']); currentuser::setdata(); $_session = [ "lastscript" =&gt; basename($_server["script_name"]), "lastqrystr" =&gt; $_server["query_string"] ]; response::redirectto('index.php'); exit(); } $userinfo = currentuser::getdata(); ui::twig()-&gt;addglobal('userinfo', $userinfo); ui::setcurrentuser($userinfo); // initialize logger (currentuser::hassession()) { // initialize logging $log = froxlorlogger::getinstanceof($userinfo); ((currentuser::isadmin() &amp;&amp; area != 'admin') || (!currentuser::isadmin() &amp;&amp; area != 'customer')) { // user tries access area meant -&gt; redirect corresponding index response::redirectto((currentuser::isadmin() ? 'admin' : 'customer') . '_index.php'); exit(); } } /** * fills variables navigation, header footer */ $navigation = []; (area == 'admin' || area == 'customer') { (froxlor::hasupdates() || froxlor::hasdbupdates()) { /* * froxlor-files updated * yet configured admin * show logout update-page */ $navigation_data = [ 'admin' =&gt; [ 'server' =&gt; [ 'label' =&gt; lng('admin.server'), 'required_resources' =&gt; 'change_serversettings', 'elements' =&gt; [ [ 'url' =&gt; 'admin_updates.php?page=overview', 'label' =&gt; lng('update.update'), 'required_resources' =&gt; 'change_serversettings' ] ] ] ] ]; $navigation = html::buildnavigation($navigation_data['admin'], currentuser::getdata()); } else { $navigation_data = phphelper::loadconfigarraydir('lib/navigation/'); $navigation = html::buildnavigation($navigation_data[area], currentuser::getdata()); } } ui::twig()-&gt;addglobal('nav_entries', $navigation); $theme_assets = []; foreach (['css', 'js'] $asset) { (is_array($_themeoptions) &amp;&amp; array_key_exists($asset, $_themeoptions['variants'][$themevariant])) { (is_array($_themeoptions['variants'][$themevariant][$asset])) { foreach ($_themeoptions['variants'][$themevariant][$asset] $assetfile) { (file_exists('templates/' . $theme . '/' . $assetfile)) { $theme_assets[] .= 'templates/' . $theme . '/' . $assetfile; } } } } } ui::twig()-&gt;addglobal('theme_assets', $theme_assets); unset($theme_assets); $action = request::any('action'); $page = request::any('page', 'overview'); $gsearchtext = request::any('searchtext'); // clear request data (!$action &amp;&amp; isset($_session)) { unset($_session['requestdata']); } ui::twig()-&gt;addglobal('action', $action); ui::twig()-&gt;addglobal('page', $page); ui::twig()-&gt;addglobal('area', area); ui::twig()-&gt;addglobal('gsearchtext', $gsearchtext); // initialize mailingsystem $mail = new mailer(true); // initialize csrf (currentuser::hassession()) { // create new csrf token set (!$csrf_token = currentuser::getfield('csrf_token')) { $csrf_token = froxlor::gensessionid(20); currentuser::setfield('csrf_token', $csrf_token); } // set csrf token twig ui::twig()-&gt;addglobal('csrf_token', $csrf_token); // check csrf token valid (in_array($_server['request_method'], ['post', 'put', 'patch', 'delete'])) { $current_token = request::post('csrf_token', $_server['http_x_csrf_token'] ?? null); ($current_token != currentuser::getfield('csrf_token')) { http_response_code(403); response::dynamicerror('csrf validation failed'); } } // update cookie lifetime $cookie_params = [ 'expires' =&gt; time() + min(settings::get('session.sessiontimeout'), 31536000), 'path' =&gt; '/', 'domain' =&gt; ui::getcookiehost(), 'secure' =&gt; ui::requestishttps(), 'httponly' =&gt; true, 'samesite' =&gt; 'lax' ]; setcookie(session_name(), $_cookie[session_name()], $cookie_params); } else { ui::twig()-&gt;addglobal('csrf_token', froxlor::gensessionid(20)); }</file><file name="lib/functions.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\language; use froxlor\ui\request; /** * render template given data. * mostly used template-engine (twig). * * @param $template * @param $attributes * @return array|false|string|string[] */ function view($template, $attributes) { $view = file_get_contents(dirname(__dir__) . '/templates/' . $template); return str_replace(array_keys($attributes), array_values($attributes), $view); } /** * get current translation given string. * * @param string $identifier * @param array $arguments * @return array|string */ function lng(string $identifier, array $arguments = []) { return language::gettranslation($identifier, $arguments); } /** * get value request variable. * * @param string $identifier * @param string|null $default * @param string|null $session * @return mixed|string|null */ function old(string $identifier, string $default = null, string $session = null) { ($session &amp;&amp; isset($_session[$session])) { return $_session[$session][$identifier] ?? $default; } return request::any($identifier, $default); } /** * loading mix manifest file given theme. * file contains hashed filenames assets. * must always placed theme assets folder. * * @deprecated since 2.1.x longer use * @param $filename * @return mixed|string */ function mix($filename) { (preg_match('/templates\/(.+)\/assets\/(.+)\/(.+)/', $filename, $matches)) { $mixmanifest = dirname(__dir__) . '/templates/' . $matches[1] . '/assets/mix-manifest.json'; (file_exists($mixmanifest)) { $manifest = json_decode(file_get_contents($mixmanifest), true); $key = '/' . $matches[2] . '/' . $matches[3]; ($manifest &amp;&amp; !empty($manifest[$key])) { $filename = 'templates/' . $matches[1] . '/assets' . $manifest[$key]; } } } return $filename; } /** * loading vite manifest file given theme. * file contains hashed filenames assets. * must always placed theme assets folder. * * @param string|null $basehref * @param array $filenames * @return string * @throws exception */ function vite($basehref, array $filenames): string { // get hashed filenames manifest file $links = []; foreach ($filenames $filename) { (preg_match("/templates\/([^\/]+)(.*)/", $filename, $matches)) { $assetdirectory = '/templates/' . $matches[1] . '/build/'; $vitemanifest = dirname(__dir__) . $assetdirectory . '/manifest.json'; $manifest = json_decode(file_get_contents($vitemanifest), true); (!empty($manifest[$filename]['file'])) { $links[] = $basehref . ltrim($assetdirectory, '/') . $manifest[$filename]['file']; } else { // additional asset config.json prebuilt release (e.g. custom.css) $links[] = $filename; } } else { $links[] = $filename; } } // update links correct html tags foreach ($links $key =&gt; $link) { switch (pathinfo($link, pathinfo_extension)) { case 'css': $links[$key] = '&lt;link rel="stylesheet" href="'. $link . '"&gt;'; break; case 'js': $links[$key] = '&lt;script src="' . $link . '" type="module"&gt;&lt;/script&gt;'; break; default: throw new exception('unknown file extension file '. $link .' manifest.json'); } } return implode("\n", $links); }</file><file name="lib/index.html" /><file name="lib/Froxlor/User.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor; use froxlor\database\database; use pdo; class user { /** * returns full style user details "name, firstname | company" * * @param array array keys firstname, name company * @return string full details * * @author florian lippert &lt;flo@syscp.org&gt; (2003-2009) */ public static function getcorrectfulluserdetails($userinfo, $html = false): string { $returnval = ''; (isset($userinfo['firstname']) &amp;&amp; isset($userinfo['name']) &amp;&amp; isset($userinfo['company'])) { ($userinfo['company'] == '') { $returnval = $userinfo['name'] . ', ' . $userinfo['firstname']; } else { ($userinfo['name'] != '' &amp;&amp; $userinfo['firstname'] != '') { ($html) { $returnval = $userinfo['name'] . ', ' . $userinfo['firstname'] . '&lt;br&gt;&lt;small&gt;' . $userinfo['company'] . '&lt;/small&gt;'; } else { $returnval = $userinfo['name'] . ', ' . $userinfo['firstname'] . ', ' . $userinfo['company']; } } else { $returnval = $userinfo['company']; } } } elseif (isset($userinfo['name'])) { $returnval = $userinfo['name']; } return $returnval; } /** * returns correct user salutation, either "firstname name" "company" * * @param array array keys firstname, name company * @return string correct salutation * * @author florian lippert &lt;flo@syscp.org&gt; (2003-2009) */ public static function getcorrectusersalutation($userinfo) { $returnval = ''; (isset($userinfo['firstname']) &amp;&amp; isset($userinfo['name']) &amp;&amp; isset($userinfo['company'])) { // always prefer firstname name ($userinfo['company'] != '' &amp;&amp; $userinfo['name'] == '' &amp;&amp; $userinfo['firstname'] == '') { $returnval = $userinfo['company']; } else { $returnval = $userinfo['firstname'] . ' ' . $userinfo['name']; } } return $returnval; } /** * function updates counters used resources panel_admins panel_customers * * @param bool $returndebuginfo set true get array debug information * @return array contains debug information parameter 'returndebuginfo' set true * * @author florian lippert &lt;flo@syscp.org&gt; (2003-2009) * @author froxlor team &lt;team@froxlor.org&gt; (2010-) */ public static function updatecounters($returndebuginfo = false) { $returnval = []; ($returndebuginfo === true) { $returnval = [ 'admins' =&gt; [], 'customers' =&gt; [] ]; } // customers $customers_stmt = database::prepare('select * `' . table_panel_customers . '` order `customerid`'); database::pexecute($customers_stmt); // array store currently used resources per admin $admin_resources = []; ($customer = $customers_stmt-&gt;fetch(pdo::fetch_assoc)) { // set current admin $cur_adm = $customer['adminid']; // initialize admin-resources array admin $customer['adminid'] (!isset($admin_resources[$cur_adm])) { $admin_resources[$cur_adm] = []; } // fill admin resource usage array customer data self::addresourcecountex($admin_resources[$cur_adm], $customer, 'diskspace_used', 'diskspace'); self::addresourcecountex($admin_resources[$cur_adm], $customer, 'traffic_used', 'traffic_used'); // !!! yes, used used foreach ([ 'mysqls', 'ftps', 'emails', 'email_accounts', 'email_forwarders', 'email_quota', 'subdomains' ] $field) { self::addresourcecount($admin_resources[$cur_adm], $customer, $field . '_used', $field); } // calculate real usage $customer_mysqls_stmt = database::prepare('select count(*) `number_mysqls` `' . table_panel_databases . '` `customerid` = :cid'); $customer_mysqls = database::pexecute_first($customer_mysqls_stmt, [ "cid" =&gt; $customer['customerid'] ]); $customer['mysqls_used_new'] = (int)$customer_mysqls['number_mysqls']; $customer_emails_stmt = database::prepare('select count(*) `number_emails` `' . table_mail_virtual . '` `customerid` = :cid'); $customer_emails = database::pexecute_first($customer_emails_stmt, [ "cid" =&gt; $customer['customerid'] ]); $customer['emails_used_new'] = (int)$customer_emails['number_emails']; $customer_emails_result_stmt = database::prepare('select `email`, `email_full`, `destination`, `popaccountid` `' . table_mail_virtual . '` `customerid` = :cid'); database::pexecute($customer_emails_result_stmt, [ "cid" =&gt; $customer['customerid'] ]); $customer_email_forwarders = 0; $customer_email_accounts = 0; ($customer_emails_row = $customer_emails_result_stmt-&gt;fetch(pdo::fetch_assoc)) { ($customer_emails_row['destination'] != '') { $customer_emails_row['destination'] = explode(' ', filedir::makecorrectdestination($customer_emails_row['destination'])); $customer_email_forwarders += count($customer_emails_row['destination']); (in_array($customer_emails_row['email_full'], $customer_emails_row['destination'])) { $customer_email_forwarders -= 1; $customer_email_accounts++; } } } $customer['email_accounts_used_new'] = $customer_email_accounts; $customer['email_forwarders_used_new'] = $customer_email_forwarders; $customer_ftps_stmt = database::prepare('select count(*) `number_ftps` `' . table_ftp_users . '` `customerid` = :cid'); $customer_ftps = database::pexecute_first($customer_ftps_stmt, [ "cid" =&gt; $customer['customerid'] ]); $customer['ftps_used_new'] = ((int)$customer_ftps['number_ftps'] - 1); $customer_subdomains_stmt = database::prepare('select count(*) `number_subdomains` `' . table_panel_domains . '` `customerid` = :cid `parentdomainid` &lt;&gt; "0"'); $customer_subdomains = database::pexecute_first($customer_subdomains_stmt, [ "cid" =&gt; $customer['customerid'] ]); $customer['subdomains_used_new'] = (int)$customer_subdomains['number_subdomains']; $customer_email_quota_stmt = database::prepare('select sum(`quota`) `email_quota` `' . table_mail_users . '` `customerid` = :cid'); $customer_email_quota = database::pexecute_first($customer_email_quota_stmt, [ "cid" =&gt; $customer['customerid'] ]); $customer['email_quota_used_new'] = (int)$customer_email_quota['email_quota']; // update database accordingly $stmt = database::prepare('update `' . table_panel_customers . '` set `mysqls_used` = :mysqls_used, `emails_used` = :emails_used, `email_accounts_used` = :email_accounts_used, `email_forwarders_used` = :email_forwarders_used, `email_quota_used` = :email_quota_used, `ftps_used` = :ftps_used, `subdomains_used` = :subdomains_used `customerid` = :cid'); $params = [ "mysqls_used" =&gt; $customer['mysqls_used_new'], "emails_used" =&gt; $customer['emails_used_new'], "email_accounts_used" =&gt; $customer['email_accounts_used_new'], "email_forwarders_used" =&gt; $customer['email_forwarders_used_new'], "email_quota_used" =&gt; $customer['email_quota_used_new'], "ftps_used" =&gt; $customer['ftps_used_new'], "subdomains_used" =&gt; $customer['subdomains_used_new'], "cid" =&gt; $customer['customerid'] ]; database::pexecute($stmt, $params); ($returndebuginfo === true) { $returnval['customers'][$customer['customerid']] = $customer; } } // admins $admins_stmt = database::prepare('select * `' . table_panel_admins . '` order `adminid`'); database::pexecute($admins_stmt, []); $resource_fields = [ 'diskspace_used', 'traffic_used', 'mysqls_used', 'ftps_used', 'emails_used', 'email_accounts_used', 'email_forwarders_used', 'email_quota_used', 'subdomains_used' ]; $admin_customers_stmt = database::prepare('select * `' . table_panel_customers . '` `adminid` = :aid'); ($admin = $admins_stmt-&gt;fetch(pdo::fetch_assoc)) { database::pexecute($admin_customers_stmt, [ "aid" =&gt; $admin['adminid'] ]); $admin_customers = $admin_customers_stmt-&gt;fetchall(pdo::fetch_assoc); $admin['customers_used_new'] = count($admin_customers); $admin_domains_stmt = database::prepare('select count(*) `number_domains` `' . table_panel_domains . '` `adminid` = :aid `parentdomainid` = "0"'); $admin_domains = database::pexecute_first($admin_domains_stmt, [ "aid" =&gt; $admin['adminid'] ]); // subtract amount domains std-subdomains later iterated customers know sure $admin['domains_used_new'] = $admin_domains['number_domains']; // set current admin $cur_adm = $admin['adminid']; // there's admin without customers might possible id yet known $admin_resources (!isset($admin_resources[$cur_adm])) { $admin_resources[$cur_adm] = []; } // sure fields set array foreach ($resource_fields $field) { self::initarrfield($field, $admin_resources[$cur_adm], 0); // initialize new values $admin[$field . '_new'] = 0; } // get customer resource usage re-calculated previously foreach ($admin_customers $acustomer) { foreach ($resource_fields $field) { ($field == 'diskspace_used') { // admin/reseller-usage == assign customer (($acustomer['diskspace'] / 1024) != -1) { $admin[$field . '_new'] += $acustomer['diskspace']; } } else ($field != 'traffic_used') { ($acustomer[str_replace("_used", "", $field)] != '-1') { $admin[$field . '_new'] += $acustomer[str_replace("_used", "", $field)]; } } else { // traffic always current usage, assigned value $admin[$field . '_new'] += $acustomer[$field]; } } // check std-subdomain ($acustomer['standardsubdomain'] &gt; 0) { // std-subdomain count assigned resource $admin['domains_used_new']--; } } // update database entry accordingly $stmt = database::prepare('update `' . table_panel_admins . '` set `customers_used` = :customers_used, `domains_used` = :domains_used, `diskspace_used` = :diskspace_used, `mysqls_used` = :mysqls_used, `emails_used` = :emails_used, `email_accounts_used` = :email_accounts_used, `email_forwarders_used` = :email_forwarders_used, `email_quota_used` = :email_quota_used, `ftps_used` = :ftps_used, `subdomains_used` = :subdomains_used, `traffic_used` = :traffic_used `adminid` = :aid'); $params = [ "customers_used" =&gt; $admin['customers_used_new'], "domains_used" =&gt; $admin['domains_used_new'], "diskspace_used" =&gt; $admin['diskspace_used_new'], "mysqls_used" =&gt; $admin['mysqls_used_new'], "emails_used" =&gt; $admin['emails_used_new'], "email_accounts_used" =&gt; $admin['email_accounts_used_new'], "email_forwarders_used" =&gt; $admin['email_forwarders_used_new'], "email_quota_used" =&gt; $admin['email_quota_used_new'], "ftps_used" =&gt; $admin['ftps_used_new'], "subdomains_used" =&gt; $admin['subdomains_used_new'], "traffic_used" =&gt; $admin['traffic_used_new'], "aid" =&gt; $admin['adminid'] ]; database::pexecute($stmt, $params); ($returndebuginfo === true) { $returnval['admins'][$admin['adminid']] = $admin; } } return $returnval; } /** * customer unlimited resources, add used resources * admin-resource-counter * special function wrapper diskspace traffic need * calculated otherwise get -1 unlimited * * @param array $arr reference * @param array $customer_arr * @param string $used_field * @param string $field * * @return void */ private static function addresourcecountex(&amp;$arr, $customer_arr, $used_field = null, $field = null) { self::initarrfield($used_field, $arr, 0); ($field == 'diskspace' &amp;&amp; ($customer_arr[$field] / 1024) != '-1') { $arr[$used_field] += intval($customer_arr[$field]); } elseif ($field == 'traffic_used') { // check -1 want assigned traffic admins/resellers // actually used (for stats reasons) $arr[$used_field] += intval($customer_arr[$field]); } } /** * initialize field-value array yet initialized * * @param string $field * @param array $arr reference * @param int $init_value * * @return void */ private static function initarrfield($field = null, &amp;$arr = [], $init_value = 0) { (!isset($arr[$field])) { $arr[$field] = $init_value; } } /** * customer unlimited resources, add used resources * admin-resource-counter * * @param array $arr reference * @param array $customer_arr * @param string $used_field * @param string $field * * @return void */ private static function addresourcecount(&amp;$arr, $customer_arr, $used_field = null, $field = null) { self::initarrfield($used_field, $arr, 0); ($customer_arr[$field] != '-1') { $arr[$used_field] += intval($customer_arr[$used_field]); } } }</file><file name="lib/Froxlor/Language.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor; use recursivearrayiterator; use recursiveiteratoriterator; class language { protected static ?array $lng = null; protected static string $defaultlanguage = 'en'; protected static ?string $requestedlanguage = null; /** * @return array */ public static function getlanguages(): array { $languages = []; $directory = dirname(__dir__, 2) . '/lng'; foreach (array_diff(scandir($directory), ['..', '.', 'index.html']) $language) { $iso = explode('.', $language)[0]; $languages[$iso] = self::gettranslation('languages.' . $iso); } return $languages; } public static function gettranslation(string $identifier, array $arguments = []) { // initialize (is_null(self::$lng)) { // load fallback language self::$lng = self::loadlanguage(self::$defaultlanguage); // load user requested language (self::$requestedlanguage) { self::$lng = array_merge(self::$lng, self::loadlanguage(self::$requestedlanguage)); } // load fallback browser nothing requested $iso = trim(substr(strtok(strtok(($_server['http_accept_language'] ?? 'en'), ','), ';'), 0, 5)); (!self::$requestedlanguage &amp;&amp; strlen($iso) == 2 &amp;&amp; $iso !== self::$defaultlanguage) { self::$lng = array_merge(self::$lng, self::loadlanguage($iso)); } } // shortcut identifier =&gt; [title, description] (!isset(self::$lng[$identifier]) &amp;&amp; isset(self::$lng[$identifier . '.title'])) { return [ 'title' =&gt; vsprintf(self::$lng[$identifier . '.title'] ?? $identifier, $arguments), 'description' =&gt; vsprintf(self::$lng[$identifier . '.description'] ?? $identifier, $arguments), ]; } // search identifier return vsprintf(self::$lng[$identifier] ?? $identifier, $arguments); } /** * @todo: possible iso: de, de-de, de-at (fallback de) * * @param $iso * @return array */ private static function loadlanguage($iso): array { $languagefile = dirname(__dir__, 2) . sprintf('/lng/%s.lng.php', $iso); (!file_exists($languagefile)) { return []; } // load default language $lng = require $languagefile; // multidimensional array dot notation keys $reitit = new recursiveiteratoriterator(new recursivearrayiterator($lng)); $result = []; foreach ($reitit $leafvalue) { $keys = []; foreach (range(0, $reitit-&gt;getdepth()) $depth) { $keys[] = $reitit-&gt;getsubiterator($depth)-&gt;key(); } $result[join('.', $keys)] = $leafvalue; } return $result; } public static function setdefaultlanguage(string $string) { self::$defaultlanguage = $string; } public static function setlanguage(string $string) { self::$requestedlanguage = $string; self::$lng = null; } }</file><file name="lib/Froxlor/SImExporter.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor; use exception; use froxlor\database\database; use froxlor\ui\form; use froxlor\validate\validate; use pdo; /** * class simexporter * * import/export settings json */ class simexporter { /** * settings exported * * @var array */ private static $no_export = [ 'panel.adminmail', 'admin.show_news_feed', 'system.lastaccountnumber', 'system.lastguid', 'system.ipaddress', 'system.last_traffic_run', 'system.hostname', 'system.mysql_access_host', 'system.lastcronrun', 'system.defaultip', 'system.defaultsslip', 'system.last_tasks_run', 'system.last_archive_run', 'system.leprivatekey', 'system.lepublickey', 'system.updatecheck_data', ]; public static function export() { $settings_definitions = []; foreach (phphelper::loadconfigarraydir(froxlor::getinstalldir() . '/actions/admin/settings/')['groups'] $group) { foreach ($group['fields'] $field) { $settings_definitions[$field['settinggroup']][$field['varname']] = $field; } } $result_stmt = database::query(" select * `" . table_panel_settings . "` order `settingid` asc "); $_data = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $index = $row['settinggroup'] . "." . $row['varname']; (!in_array($index, self::$no_export)) { $_data[$index] = $row['value']; } (array_key_exists($row['settinggroup'], $settings_definitions) &amp;&amp; array_key_exists($row['varname'], $settings_definitions[$row['settinggroup']])) { // export image file ($settings_definitions[$row['settinggroup']][$row['varname']]['type'] === "image") { ($row['value'] === "") { continue; } $_data[$index . '.image_data'] = base64_encode(file_get_contents(explode('?', $row['value'], 2)[0])); } } } // add checksum validation $_data['_sha'] = sha1(var_export($_data, true)); $_export = json_encode($_data, json_pretty_print | json_unescaped_slashes); (!$_export) { throw new exception("error exporting settings: " . json_last_error_msg()); } return $_export; } public static function import($json_str = null) { // decode data $_data = json_decode($json_str, true); ($_data) { // get validity check data $_sha = isset($_data['_sha']) ? $_data['_sha'] : false; $_version = isset($_data['panel.version']) ? $_data['panel.version'] : false; $_dbversion = isset($_data['panel.db_version']) ? $_data['panel.db_version'] : false; // check everything need (!$_sha || !$_version || !$_dbversion) { throw new exception("invalid froxlor settings data. unable import."); } // validate import file unset($_data['_sha']); // compare ($_sha != sha1(var_export($_data, true))) { throw new exception("sha check import data failed. unable import."); } // import version info - need possibly update settings // changes variable-name similar unset($_data['panel.version']); unset($_data['panel.db_version']); // validate got ssl enabled ips ssl enabled // otherwise deactivate ($_data['system.use_ssl'] == 1) { $result_ssl_ipsandports_stmt = database::prepare(" select count(*) count_ssl_ip `" . table_panel_ipsandports . "` `ssl`='1' "); $result = database::pexecute_first($result_ssl_ipsandports_stmt); ($result['count_ssl_ip'] &lt;= 0) { // ssl-ip -&gt; deactivate $_data['system.use_ssl'] = 0; // deactivate ssl-related settings $_data['system.leenabled'] = 0; $_data['system.le_froxlor_enabled'] = 0; $_data['system.le_froxlor_redirect'] = 0; } } $form_data = []; $image_data = []; // read current settings $current_settings = settings::getall(); foreach ($current_settings $setting_group =&gt; $setting) { foreach ($setting $varname =&gt; $value) { // set group/varname:values import file (!array_key_exists($setting_group . '.' . $varname, $_data)) { $_data[$setting_group . '.' . $varname] = $value; } } } // re-format array-key form::processform foreach ($_data $key =&gt; $value) { $index_split = explode('.', $key, 3); (!isset($current_settings[$index_split[0]][$index_split[1]])) { continue; } (isset($index_split[2]) &amp;&amp; $index_split[2] === 'image_data' &amp;&amp; !empty($_data[$index_split[0] . '.' . $index_split[1]])) { $image_data[$key] = $value; } else { $form_data[str_replace(".", "_", $key)] = $value; } } // store new data $settings_data = phphelper::loadconfigarraydir(froxlor::getinstalldir() . '/actions/admin/settings/'); settings::loadsettingsinto($settings_data); (form::processform($settings_data, $form_data, [], null, true)) { // save db settings::flush(); // process image_data save (count($image_data) &gt; 0) { foreach ($image_data $index =&gt; $value) { $index_split = explode('.', $index, 3); $path = froxlor::getinstalldir() . '/img/'; (!is_dir($path) &amp;&amp; !mkdir($path, 0775)) { throw new exception("img directory exist cannot created"); } // make sure write upload directory (!is_writable($path)) { (!chmod($path, 0775)) { throw new exception("cannot write img directory"); } } (validate::validatebase64image($value)) { $img_data = base64_decode($value); $img_filename = explode('?', $_data[$index_split[0] . '.' . $index_split[1]], 2)[0]; $spl = explode('.', $img_filename); $file_extension = strtolower(array_pop($spl)); unset($spl); (!in_array($file_extension, [ 'jpeg', 'jpg', 'png', 'gif' ])) { throw new exception("invalid file-extension, use one of: jpeg, jpg, png, gif"); } $img_filename = 'img/' . bin2hex(random_bytes(16)) . '.' . $file_extension; file_put_contents(froxlor::getinstalldir() . '/' . $img_filename, $img_data); $img_index = $index_split[0].'.'.$index_split[1]; settings::set($img_index, $img_filename . '?v=' . time()); } } } // good return true; } else { throw new exception("importing settings failed"); } } throw new exception("invalid json data: " . json_last_error_msg()); } }</file><file name="lib/Froxlor/PhpHelper.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor; use exception; use froxlor\ui\panel\ui; use net_dns2_exception; use net_dns2_resolver; use throwable; use voku\helper\antixss; class phphelper { /** * wrapper around htmlentities handle arrays, advantage * select fields handled htmlentities * * @param array|string $subject subject array * @param array|string $fields fields checked for, separated spaces * @param int $quote_style see php documentation * @param string $charset see php documentation * * @return array|string string array htmlentities converted strings * @author florian lippert &lt;flo@syscp.org&gt; (2003-2009) */ public static function htmlentitiesarray($subject, $fields = '', $quote_style = ent_quotes, $charset = 'utf-8') { (is_array($subject)) { (!is_array($fields)) { $fields = self::arraytrim(explode(' ', $fields)); } foreach ($subject $field =&gt; $value) { ((!is_array($fields) || empty($fields)) || (in_array($field, $fields))) { // call ourselve manage multi-dimensional arrays $subject[$field] = self::htmlentitiesarray($value, $fields, $quote_style, $charset); } } } else { $subject = empty($subject) ? "" : htmlentities($subject, $quote_style, $charset); } return $subject; } /** * returns array empty-values removed * * @param array $source array trim * @return array trim'med array */ public static function arraytrim(array $source): array { $source = array_map('trim', $source); return array_filter($source, function ($value) { return $value !== ''; }); } /** * froxlor php error handler * * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline * * @return void|boolean */ public static function phperrhandler($errno, $errstr, $errfile, $errline) { (!(error_reporting() &amp; $errno)) { // error code included error_reporting return; } (!isset($_server['shell']) || (isset($_server['shell']) &amp;&amp; $_server['shell'] == '')) { // prevent possible file-path-disclosure $errfile = str_replace(froxlor::getinstalldir(), "", $errfile); // build alert $type = 'danger'; ($errno == e_notice || $errno == e_deprecated || $errno == e_strict) { $type = 'info'; } elseif ($errno = e_warning) { $type = 'warning'; } $err_display = '&lt;div class="alert alert-' . $type . ' my-1" role="alert"&gt;'; $err_display .= '&lt;strong&gt;#' . $errno . ' ' . $errstr . '&lt;/strong&gt;&lt;br&gt;'; $err_display .= $errfile . ':' . $errline; // later depended whether show $err_display .= '&lt;br&gt;&lt;p&gt;&lt;pre&gt;'; $debug = debug_backtrace(debug_backtrace_ignore_args); foreach ($debug $dline) { $err_display .= $dline['function'] . '() called [' . str_replace(froxlor::getinstalldir(), '', ($dline['file'] ?? 'unknown')) . ':' . ($dline['line'] ?? 0) . ']&lt;br&gt;'; } $err_display .= '&lt;/pre&gt;&lt;/p&gt;'; // end later $err_display .= '&lt;/div&gt;'; // set errors session errorbag::adderror($err_display); // return true ignore php standard error-handler return true; } // shell, use php standard error-handler return false; } /** * @param throwable $exception * @return void */ public static function phpexceptionhandler(throwable $exception) { (!isset($_server['shell']) || $_server['shell'] == '') { // show ui::inittwig(true); ui::twig()-&gt;addglobal('install_mode', '1'); ui::view('misc/alert_nosession.html.twig', [ 'page_title' =&gt; 'uncaught exception', 'heading' =&gt; 'uncaught exception', 'type' =&gt; 'danger', 'alert_msg' =&gt; $exception-&gt;getcode() . ' ' . $exception-&gt;getmessage(), 'alert_info' =&gt; $exception-&gt;gettraceasstring() ]); die(); } } /** * @param ...$configdirs * @return array|null */ public static function loadconfigarraydir(...$configdirs) { (count($configdirs) &lt;= 0) { return null; } $data = []; $data_files = []; $has_data = false; foreach ($configdirs $data_dirname) { (is_dir($data_dirname)) { $data_dirhandle = opendir($data_dirname); (false !== ($data_filename = readdir($data_dirhandle))) { ($data_filename != '.' &amp;&amp; $data_filename != '..' &amp;&amp; $data_filename != '' &amp;&amp; substr($data_filename, -4) == '.php' ) { $data_files[] = $data_dirname . $data_filename; } } $has_data = true; } } ($has_data) { sort($data_files); foreach ($data_files $data_filename) { $data = array_merge_recursive($data, include $data_filename); } } return $data; } /** * ipv6 aware gethostbynamel function * * @param string $host * @param boolean $try_a default true * @param string|null $nameserver set additional resolver nameserver use (e.g. 1.1.1.1) * @return bool|array */ public static function gethostbynamel6(string $host, bool $try_a = true, string $nameserver = null) { $ips = []; try { // set default nameservers use, use system default none provided $resolver = new net_dns2_resolver($nameserver ? ['nameservers' =&gt; [$nameserver]] : []); // get ip addresses record normalize ($try_a) { try { $answer = $resolver-&gt;query($host, 'a')-&gt;answer; foreach ($answer $rr) { ($rr instanceof \net_dns2_rr_a) { $ips[] = inet_ntop(inet_pton($rr-&gt;address)); } } } catch (net_dns2_exception $e) { // can't anything here, continue } } // get ip addresses aaaa record normalize try { $answer = $resolver-&gt;query($host, 'aaaa')-&gt;answer; foreach ($answer $rr) { ($rr instanceof \net_dns2_rr_aaaa) { $ips[] = inet_ntop(inet_pton($rr-&gt;address)); } } } catch (net_dns2_exception $e) { // can't anything here, continue } } catch (net_dns2_exception $e) { // fallback php's dns_get_record net_dns2 resolver available, may cause // problems system's dns configured correctly; example, acme pre-check // fail providers put local ip /etc/hosts // get ip addresses record normalize ($try_a) { $answer = @dns_get_record($host, dns_a); foreach ($answer $rr) { $ips[] = inet_ntop(inet_pton($rr['ip'])); } } // get ip addresses aaaa record normalize $answer = @dns_get_record($host, dns_aaaa); foreach ($answer $rr) { $ips[] = inet_ntop(inet_pton($rr['ipv6'])); } } return count($ips) &gt; 0 ? $ips : false; } /** * function randomstr * * generate pseudo-random string bytes * * @param int $length * @return string * @throws exception */ public static function randomstr(int $length): string { (function_exists('openssl_random_pseudo_bytes')) { return openssl_random_pseudo_bytes($length); } return random_bytes($length); } /** * return human-readable sizes * * @param int $size size bytes * @param ?string $max maximum unit * @param string $system 'si' si, 'bi' binary prefixes * @param string $retstring string-format * * @return string */ public static function sizereadable( $size, ?string $max = '', string $system = 'si', string $retstring = '%01.2f %s' ): string { // pick units $systems = [ 'si' =&gt; [ 'prefix' =&gt; [ 'b', 'kb', 'mb', 'gb', 'tb', 'pb' ], 'size' =&gt; 1000 ], 'bi' =&gt; [ 'prefix' =&gt; [ 'b', 'kib', 'mib', 'gib', 'tib', 'pib' ], 'size' =&gt; 1024 ] ]; $sys = $systems[$system] ?? $systems['si']; // max unit display $depth = count($sys['prefix']) - 1; ($max &amp;&amp; false !== $d = array_search($max, $sys['prefix'])) { $depth = $d; } // loop $i = 0; ($size &gt;= $sys['size'] &amp;&amp; $i &lt; $depth) { $size /= $sys['size']; $i++; } return sprintf($retstring, $size, $sys['prefix'][$i]); } /** * replaces occurrences variables defined second argument * first argument values. * * @param string $text string searched variables * @param array $vars array containing variables values * * @return string submitted string variables replaced. */ public static function replacevariables(string $text, array $vars): string { $pattern = "/\{([a-za-z0-9\-_]+)\}/"; $matches = []; (count($vars) &gt; 0 &amp;&amp; preg_match_all($pattern, $text, $matches)) { ($i = 0; $i &lt; count($matches[1]); $i++) { $current = $matches[1][$i]; (isset($vars[$current])) { $var = $vars[$current]; $text = str_replace("{" . $current . "}", $var, $text); } } } return str_replace('\n', "\n", $text); } /** * @param string $needle * @param array $haystack * @param array $keys * @param string $currentkey * @return true */ public static function recursive_array_search( string $needle, array $haystack, array &amp;$keys = [], string $currentkey = '' ): bool { foreach ($haystack $key =&gt; $value) { (empty($value)) { continue; } $pathkey = empty($currentkey) ? $key : $currentkey . '.' . $key; (is_array($value)) { self::recursive_array_search($needle, $value, $keys, $pathkey); } else { (stripos($value, $needle) !== false) { $keys[] = $pathkey; } } } return true; } /** * function check super-global passed reference, * gets automatically updated * * @param array $global * @param antixss $antixss */ public static function cleanglobal(array &amp;$global, antixss &amp;$antixss) { $ignored_fields = [ 'system_default_vhostconf', 'system_default_sslvhostconf', 'system_apache_globaldiropt', 'specialsettings', 'ssl_specialsettings', 'default_vhostconf_domain', 'ssl_default_vhostconf_domain', 'filecontent', 'admin_password', 'password', 'new_customer_password', 'privileged_password', 'email_password', 'directory_password', 'ftp_password', 'mysql_password', 'mysql_root_pass', 'mysql_unprivileged_pass', 'admin_pass', 'admin_pass_confirm', 'panel_password_special_char', 'old_password', 'new_password', 'new_password_confirm', ]; (!empty($global)) { $tmp = $global; foreach ($tmp $index =&gt; $value) { (!in_array($index, $ignored_fields)) { $global[$index] = $antixss-&gt;xss_clean($value); } } } } /** * generate php file array. * * @param array $array * @param string|null $comment * @param bool $asreturn * @return string */ public static function parsearraytophpfile(array $array, string $comment = null, bool $asreturn = false): string { $str = sprintf("&lt;?php\n// %s\n\n", $comment ?? 'autogenerated froxlor file'); ($asreturn) { return $str . sprintf("return %s;\n", rtrim(self::parsearraytostring($array), "\n,")); } foreach ($array $var =&gt; $arr) { $str .= sprintf("\$%s = %s;\n", $var, rtrim(self::parsearraytostring($arr), "\n,")); } return $str; } /** * parse array array string. * * @param array $array * @param ?string $key * @param int $depth * @return string */ public static function parsearraytostring(array $array, string $key = null, int $depth = 1): string { $str = ''; (!is_null($key)) { $str .= self::tabprefix(($depth - 1), "'{$key}' =&gt; [\n"); } else { $str .= self::tabprefix(($depth - 1), "[\n"); } foreach ($array $key =&gt; $value) { (!is_array($value)) { (is_bool($value)) { $str .= self::tabprefix($depth, sprintf("'%s' =&gt; %s,\n", $key, $value ? 'true' : 'false')); } elseif (is_int($value)) { $str .= self::tabprefix($depth, "'{$key}' =&gt; $value,\n"); } else { ($key == 'password') { // special case passwords (nowdoc) $str .= self::tabprefix($depth, "'{$key}' =&gt; &lt;&lt;&lt;'eot'\n{$value}\neot,\n"); } else { $str .= self::tabprefix($depth, "'{$key}' =&gt; '{$value}',\n"); } } } else { $str .= self::parsearraytostring($value, $key, ($depth + 1)); } } $str .= self::tabprefix(($depth - 1), "],\n"); return $str; } /** * apply tabs given depth string. * * @param int $depth * @param string $str * @return string */ private static function tabprefix(int $depth, string $str = ''): string { $tab = ''; ($i = 1; $i &lt;= $depth; $i++) { $tab .= "\t"; } return $tab . $str; } public static function array_merge_recursive_distinct(array &amp;$array1, array &amp;$array2) { $merged = $array1; foreach ($array2 $key =&gt; &amp;$value) { (is_array($value) &amp;&amp; isset($merged[$key]) &amp;&amp; is_array($merged[$key])) { $merged[$key] = self::array_merge_recursive_distinct($merged[$key], $value); } else { $merged[$key] = $value; } } return $merged; } }</file><file name="lib/Froxlor/FileDir.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor; use exception; use froxlor\customer\customer; use froxlor\database\database; use pdo; use recursivecallbackfilteriterator; class filedir { /** * creates directory users homedir sets directories, * created correct owner/group * (copied cron_tasks.php:rev1189 we'll need often future) * * @param string $homedir homedir user * @param string $dirtocreate dir created * @param int $uid uid user * @param int $gid gid user * @param bool $placeindex place standard-index.html new folder * @param bool $allow_notwithinhomedir allow creating directory customers docroot * * @return bool true everything went okay, false something went wrong * @throws exception */ public static function mkdirwithcorrectownership( string $homedir, string $dirtocreate, int $uid, int $gid, bool $placeindex = false, bool $allow_notwithinhomedir = false ): bool { ($homedir != '' &amp;&amp; $dirtocreate != '') { $homedir = self::makecorrectdir($homedir); $dirtocreate = self::makecorrectdir($dirtocreate); (substr($dirtocreate, 0, strlen($homedir)) == $homedir) { $subdir = substr($dirtocreate, strlen($homedir) - 1); $within_homedir = true; } else { $subdir = $dirtocreate; $within_homedir = false; } $subdir = self::makecorrectdir($subdir); $subdirs = []; ($within_homedir || !$allow_notwithinhomedir) { $subdirlen = strlen($subdir); $offset = 0; ($offset &lt; $subdirlen) { $offset = strpos($subdir, '/', $offset); $subdirelem = substr($subdir, 0, $offset); $offset++; array_push($subdirs, self::makecorrectdir($homedir . $subdirelem)); } } else { array_push($subdirs, $dirtocreate); } $subdirs = array_unique($subdirs); sort($subdirs); foreach ($subdirs $sdir) { (!is_dir($sdir)) { $sdir = self::makecorrectdir($sdir); self::safe_exec('mkdir -p ' . escapeshellarg($sdir)); // place index ($placeindex) { $loginname = customer::getloginnamebyuid($uid); ($loginname !== false) { self::storedefaultindex($loginname, $sdir, null); } } self::safe_exec('chown -r ' . (int)$uid . ':' . (int)$gid . ' ' . escapeshellarg($sdir)); } } return true; } return false; } /** * returns correct/secure dirname, means add slashes beginning end * some. $fixes_homedir specified, * * * @param string $dir path correct * * @return string corrected path * @throws exception */ public static function makecorrectdir(string $dir, string $fixed_homedir = ""): string { (strlen($dir) &gt; 0) { $dir = trim($dir); (substr($dir, -1, 1) != '/') { $dir .= '/'; } (substr($dir, 0, 1) != '/') { $dir = '/' . $dir; } // given, check target path within $fixed_homedir // checking folder symlink whether targets // customers homedir points outside (!empty($fixed_homedir)) { $to_check = explode("/", substr($dir, strlen($fixed_homedir) + 1), -1); $check_dir = substr($fixed_homedir, 0, -1); // symlink check foreach ($to_check $sub_dir) { $check_dir .= '/' . $sub_dir; (is_link($check_dir)) { $original_target = $check_dir; $check_dir = readlink($check_dir); $link_dir = dirname($original_target); // check whether link relative absolute (substr($check_dir, 0, 1) != '/') { // relative directory, prepend link_dir $check_dir = $link_dir . '/' . $check_dir; } (substr($check_dir, 0, strlen($fixed_homedir)) != $fixed_homedir) { throw new exception("found symlink pointing outside customer home directory: " . substr($original_target, strlen($fixed_homedir))); } } } // check path within given homedir (substr($dir, 0, strlen($fixed_homedir)) != $fixed_homedir) { throw new exception("target path within required customer home directory"); } } return self::makesecurepath($dir); } throw new exception("cannot validate directory " . __function__ . " dangerous."); } /** * function returns secure path, means remove multiple dots slashes * * @param string $path path secure * * @return string corrected path */ public static function makesecurepath(string $path): string { // check bad characters, allowed escaping, // generally want directory-names, // thx aaronmueller snippet $badchars = [ ':', ';', '|', '&amp;', '&gt;', '&lt;', '`', '$', '~', '?', "\0", "\n", "\r", "\t", "\f" ]; foreach ($badchars $bc) { $path = str_replace($bc, "", $path); } $search = [ '#/+#', '#\.+#' ]; $replace = [ '/', '.' ]; $path = preg_replace($search, $replace, $path); // replace space escaped space // might escaped already $path = str_replace("\ ", " ", $path); $path = str_replace(" ", "\ ", $path); return $path; } /** * wrapper around exec command. * * @param string $exec_string command executed * @param mixed $return_value referenced variable output stored * @param ?array $allowedchars optional array allowed characters path/command * * @return array result exec() */ public static function safe_exec(string $exec_string, &amp;$return_value = false, $allowedchars = null) { $disallowed = [ ';', '|', '&amp;', '&gt;', '&lt;', '`', '$', '~', '?' ]; $acheck = false; ($allowedchars != null &amp;&amp; is_array($allowedchars) &amp;&amp; count($allowedchars) &gt; 0) { $acheck = true; } foreach ($disallowed $dc) { ($acheck &amp;&amp; in_array($dc, $allowedchars)) { continue; } // check bad signs execute command (stristr($exec_string, $dc)) { die("security check failed!\nthe execute string '" . $exec_string . "' possible security risk!\nplease check whole server security problems hand!\n"); } } // execute command return output $return = []; // ------------------------------------------------------------------------------- ($return_value == false) { exec($exec_string, $return); } else { exec($exec_string, $return, $return_value); } return $return; } /** * read unconfigured-domain template database exists fallback default * * @param string $servername * * @return string * @throws exception */ public static function getunknowndomaintemplate(string $servername = "") { $result_stmt = database::prepare(" select * `" . table_panel_templates . "` `templategroup` = 'files' `varname` = 'unconfigured_html' "); database::pexecute($result_stmt); (database::num_rows() &gt; 0) { $template = $result_stmt-&gt;fetch(pdo::fetch_assoc); $replace_arr = [ 'servername' =&gt; $servername, ]; $tpl_content = phphelper::replacevariables($template['value'], $replace_arr); $tpl_ext = $template['file_extension']; } else { $tpl_ext = 'html'; $unconfiguredpath = filedir::makecorrectfile(froxlor::getinstalldir() . '/templates/misc/unconfigured/index.html'); (file_exists($unconfiguredpath)) { $tpl_content = file_get_contents($unconfiguredpath); } else { $tpl_content = lng('admin.templates.unconfigured_content_fallback'); } } $redirect_file = filedir::makecorrectfile(froxlor::getinstalldir() . '/notice.' . $tpl_ext); file_put_contents($redirect_file, $tpl_content); return basename($redirect_file); } /** * store default index-file given destination folder * * @param string $loginname customers loginname * @param string $destination path create file * @param object $logger froxlorlogger object * @param bool $force force creation whatever settings say (needed task #2, create new user) * * @return void * @throws exception */ public static function storedefaultindex( string $loginname, string $destination, $logger = null, bool $force = false ) { ($force || (int)settings::get('system.store_index_file_subs') == 1) { $result_stmt = database::prepare(" select `t`.`value`, `t`.`file_extension`, `c`.`email` `customer_email`, `a`.`email` `admin_email`, `c`.`loginname` `customer_login`, `a`.`loginname` `admin_login` `" . table_panel_customers . "` `c` inner join `" . table_panel_admins . "` `a` `c`.`adminid` = `a`.`adminid` inner join `" . table_panel_templates . "` `t` `a`.`adminid` = `t`.`adminid` `varname` = 'index_html' `c`.`loginname` = :loginname"); database::pexecute($result_stmt, [ 'loginname' =&gt; $loginname ]); (database::num_rows() &gt; 0) { $template = $result_stmt-&gt;fetch(pdo::fetch_assoc); $replace_arr = [ 'servername' =&gt; settings::get('system.hostname'), 'customer' =&gt; $template['customer_login'], 'admin' =&gt; $template['admin_login'], 'customer_email' =&gt; $template['customer_email'], 'admin_email' =&gt; $template['admin_email'] ]; // replacevariables $htmlcontent = phphelper::replacevariables($template['value'], $replace_arr); $indexhtmlpath = self::makecorrectfile($destination . '/index.' . $template['file_extension']); $index_html_handler = fopen($indexhtmlpath, 'w'); fwrite($index_html_handler, $htmlcontent); fclose($index_html_handler); ($logger !== null) { $logger-&gt;logaction( froxlorlogger::cron_action, log_notice, 'creating \'index.' . $template['file_extension'] . '\' customer \'' . $template['customer_login'] . '\' based template directory ' . escapeshellarg($indexhtmlpath) ); } } else { $destination = self::makecorrectdir($destination); ($logger !== null) { $logger-&gt;logaction( froxlorlogger::cron_action, log_notice, 'running: cp -a ' . froxlor::getinstalldir() . '/templates/misc/standardcustomer/* ' . escapeshellarg($destination) ); } self::safe_exec('cp -a ' . froxlor::getinstalldir() . '/templates/misc/standardcustomer/* ' . escapeshellarg($destination)); } } } /** * function returns correct filename, means add slash beginning one * * @param string $filename filename * * @return string corrected filename */ public static function makecorrectfile(string $filename): string { (trim($filename) == '') { $error = 'given filename function ' . __function__ . ' empty.' . "\n"; $error .= 'this dangerous happen.' . "\n"; $error .= 'please inform froxlor team issue fix it.'; echo $error; // see happened debug_print_backtrace(); die(); } (substr($filename, 0, 1) != '/') { $filename = '/' . $filename; } return self::makesecurepath($filename); } /** * checks directory disallowed paths could * lead damaged system use * * @param string|null $path * * @return bool * @throws exception */ public static function checkdisallowedpaths(string $path): bool { /* * disallow base-directories / */ $disallowed_values = [ "/", "/bin/", "/boot/", "/dev/", "/etc/", "/home/", "/lib/", "/lib32/", "/lib64/", "/opt/", "/proc/", "/root/", "/run/", "/sbin/", "/sys/", "/tmp/", "/usr/", "/var/" ]; $path = self::makecorrectdir($path); // check disallowed path (in_array($path, $disallowed_values)) { return false; } return true; } /** * function returns correct destination postfix virtual table * * @param string $destination destinations * * @return string corrected destinations */ public static function makecorrectdestination(string $destination): string { $search = '/ +/'; $replace = ' '; $destination = preg_replace($search, $replace, $destination); (substr($destination, 0, 1) == ' ') { $destination = substr($destination, 1); } (substr($destination, -1, 1) == ' ') { $destination = substr($destination, 0, strlen($destination) - 1); } return $destination; } /** * returns valid html tag chosen $fieldtype paths * * @param string $path path start searching * @param int $uid uid must match found directories * @param int $gid gid must match found directories * @param string $value value input-field * @param bool $dom * * @return array * * @throws exception * @author manuel bernhardt &lt;manuel.bernhardt@syscp.de&gt; * @author martin burchert &lt;martin.burchert@syscp.de&gt; */ public static function makepathfield(string $path, int $uid, int $gid, string $value = '', bool $dom = false): array { $value = str_replace($path, '', $value); $field = []; // path given without starting slash // dirlist holds paths starting slash, // add one get correct // default path selected, #225 (substr($value, 0, 1) != '/' &amp;&amp; !$dom) { $value = '/' . $value; } $fieldtype = strtolower(settings::get('panel.pathedit')); ($fieldtype == 'manual') { $field = [ 'type' =&gt; 'text', 'value' =&gt; htmlspecialchars($value) ]; } elseif ($fieldtype == 'dropdown') { $dirlist = self::finddirs($path, $uid, $gid); natcasesort($dirlist); (sizeof($dirlist) &gt; 0) { $_field = []; foreach ($dirlist $dir) { (strpos($dir, $path) === 0) { $dir = substr($dir, strlen($path)); // docroot cut current directory == empty -&gt; directory docroot (empty($dir)) { $dir = '/'; } $dir = self::makecorrectdir($dir); } $_field[$dir] = $dir; } $field = [ 'type' =&gt; 'select', 'select_var' =&gt; $_field, 'selected' =&gt; $value, 'value' =&gt; $value ]; } else { $field = [ 'type' =&gt; 'hidden', 'value' =&gt; '/', 'note' =&gt; lng('panel.dirsmissing') ]; } } return $field; } /** * returns array found directories * * function checks every found directory match either $uid $gid, * found directory valid. uses recursive-iterators find subdirectories. * * @param string $path path start searching * @param int $uid uid must match found directories * @param int $gid gid must match found directories * * @return array array found valid paths * @throws exception */ private static function finddirs(string $path, int $uid, int $gid): array { $_filelist = []; $path = self::makecorrectdir($path); // valid directory? (is_dir($path)) { // exclude everything directories $exclude = [ 'awstats', 'webalizer', 'goaccess' ]; /** * * @param splfileinfo $file * @param mixed $key * @param recursivecallbackfilteriterator $iterator * @return bool true need recurse item acceptable */ $filter = function ($file, $key, $iterator) use ($exclude) { (in_array($file-&gt;getfilename(), $exclude)) { return false; } elseif (substr($file-&gt;getfilename(), 0, 1) == '.') { // also hide hidden folders return false; } return true; }; // create recursiveiteratoriterator $its = new \recursiveiteratoriterator( new \recursivecallbackfilteriterator( new \recursivedirectoryiterator($path, \recursivedirectoryiterator::skip_dots), $filter ), \recursiveiteratoriterator::self_first, \recursiveiteratoriterator::catch_get_child ); // limit recursion-depth, helpful // people start asking "why see 2 subdirectories, want use /a/b/c" // let's keep mind see whether useful $its-&gt;setmaxdepth(2); // check every file foreach ($its $fullfilename =&gt; $it) { ($it-&gt;isdir() &amp;&amp; (fileowner($fullfilename) == $uid || filegroup($fullfilename) == $gid)) { $_filelist[] = self::makecorrectdir($fullfilename); } } $_filelist[] = $path; } return array_unique($_filelist); } /** * set immutable flag file * * @param string $filename file set flag * * @return void */ public static function setimmutable(string $filename) { self::safe_exec(self::getimmutablefunction(false) . escapeshellarg($filename)); } /** * internal function check whether * use chattr (linux) chflags (freebsd) * * @param bool $remove whether use +i|schg (false) -i|noschg (true) * * @return string functionname + parameter (not file) */ private static function getimmutablefunction(bool $remove = false): string { (self::isfreebsd()) { // freebsd style return 'chflags ' . (($remove === true) ? 'noschg ' : 'schg '); } else { // linux style return 'chattr ' . (($remove === true) ? '-i ' : '+i '); } } /** * check system freebsd (if exact) * bsd-based (netbsd, openbsd, etc. * exact = false [default]) * * @param bool $exact whether check explicitly freebsd *bsd * * @return bool */ public static function isfreebsd(bool $exact = false): bool { (($exact &amp;&amp; php_os == 'freebsd') || (!$exact &amp;&amp; stristr(php_os, 'bsd'))) { return true; } return false; } /** * removes immutable flag file * * @param string $filename file set flag * * @return void */ public static function removeimmutable(string $filename) { filedir::safe_exec(self::getimmutablefunction(true) . escapeshellarg($filename)); } /** * * @return array|false */ public static function getfilesystemquota() { // enabled all? (settings::get('system.diskquota_enabled')) { // set linux defaults $repquota_params = "-np"; // $quota_line_regex = "/^#([0-9]+)\s*[+-]{2}\s*(\d+)\s*(\d+)\s*(\d+)\s*(\d+)\s*(\d+)\s*(\d+)\s*(\d+)\s*(\d+)/i"; $quota_line_regex = "/^#([0-9]+)\s+[+-]{2}\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/i"; // check freebsd - needs values (self::isfreebsd()) { $repquota_params = "-nu"; $quota_line_regex = "/^([0-9]+)\s+[+-]{2}\s+(\d+)\s+(\d+)\s+(\d+)\s+(\s+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\s+)/i"; } // fetch quota desired partition $repquota = []; exec( settings::get('system.diskquota_repquota_path') . " " . $repquota_params . " " . escapeshellarg(settings::get('system.diskquota_customer_partition')), $repquota ); $usedquota = []; foreach ($repquota $tmpquota) { $matches = null; // let's see line matches quota - line (preg_match($quota_line_regex, $tmpquota, $matches)) { // matches - put array userid key (for easy lookup later) $usedquota[$matches[1]] = [ 'block' =&gt; [ 'used' =&gt; $matches[2], 'soft' =&gt; $matches[3], 'hard' =&gt; $matches[4], 'grace' =&gt; (self::isfreebsd() ? '0' : $matches[5]) ], 'file' =&gt; [ 'used' =&gt; $matches[6], 'soft' =&gt; $matches[7], 'hard' =&gt; $matches[8], 'grace' =&gt; (self::isfreebsd() ? '0' : $matches[9]) ] ]; } } return $usedquota; } return false; } }</file><file name="lib/Froxlor/Settings.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor; use exception; use froxlor\database\database; use pdo; use pdostatement; /** * class settings * * interaction settings db */ class settings { /** * settings data * * @var array */ private static $data = null; /** * local config overrides * * @var array */ private static $conf = null; /** * changed unsaved settings data * * @var array */ private static $updatedata = null; /** * prepared statement updating * settings table * * @var pdostatement */ private static $updstmt = null; /** * tests setting-value comma separated list contains entry * * @param string $setting * group varname separated dot (group.varname) * @param string $entry * entry expected list * * @return boolean true, list contains $entry */ public static function isinlist($setting = null, $entry = null) { self::init(); $svalue = self::get($setting); ($svalue == null) { return false; } $slist = explode(",", $svalue); return in_array($entry, $slist); } /** * private constructor, reads settings */ private static function init() { (empty(self::$data)) { self::readsettings(); self::readconfig(); self::$updatedata = []; // prepare statement self::$updstmt = database::prepare(" update `" . table_panel_settings . "` set `value` = :value `settinggroup` = :group `varname` = :varname "); } } /** * read settings database * set internal $_data array */ private static function readsettings() { $result_stmt = database::query(" select `settingid`, `settinggroup`, `varname`, `value` `" . table_panel_settings . "` "); self::$data = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { self::$data[$row['settinggroup']][$row['varname']] = $row['value']; } return true; } /** * read config overrides * config/config.inc.php */ private static function readconfig() { // set defaults self::$conf = [ 'enable_webupdate' =&gt; false, 'disable_otp_security_check' =&gt; false, 'display_php_errors' =&gt; false, ]; $configfile = froxlor::getinstalldir() . '/lib/config.inc.php'; (@file_exists($configfile) &amp;&amp; is_readable($configfile)) { self::$conf = array_merge(self::$conf, include $configfile); } return true; } /** * return setting-value group varname * * @param string $setting * group varname separated dot (group.varname) * * @return mixed */ public static function get($setting = null) { self::init(); $sstr = explode(".", $setting); // separator - do'h (!isset($sstr[1])) { return null; } $result = null; (isset(self::$data[$sstr[0]][$sstr[1]])) { $result = self::$data[$sstr[0]][$sstr[1]]; } return $result; } /** * update setting / set new value * * @param string $setting * group varname separated dot (group.varname) * @param string $value * @param boolean $instant_save * * @return bool */ public static function set($setting = null, $value = null, $instant_save = true) { self::init(); // check whether setting exists (self::get($setting) !== null) { // set new value array $sstr = explode(".", $setting); (!isset($sstr[1])) { return false; } self::$data[$sstr[0]][$sstr[1]] = $value; // store db instantly? ($instant_save) { self::storesetting($sstr[0], $sstr[1], $value); } else { // set temporary data usage (!isset(self::$data[$sstr[0]]) || !is_array(self::$data[$sstr[0]])) { self::$data[$sstr[0]] = []; } self::$data[$sstr[0]][$sstr[1]] = $value; // set update-data invoking flush() (!isset(self::$updatedata[$sstr[0]]) || !is_array(self::$updatedata[$sstr[0]])) { self::$updatedata[$sstr[0]] = []; } self::$updatedata[$sstr[0]][$sstr[1]] = $value; } return true; } return false; } /** * update value database * * @param string $group * @param string $varname * @param string $value */ private static function storesetting($group = null, $varname = null, $value = null) { $upd_data = [ 'group' =&gt; $group, 'varname' =&gt; $varname, 'value' =&gt; $value ]; database::pexecute(self::$updstmt, $upd_data); } /** * add new setting database (mainly used updater) * * @param string $setting * group varname separated dot (group.varname) * @param string $value * * @return boolean */ public static function addnew($setting = null, $value = null) { self::init(); // first check exist (self::get($setting) === null) { // validate parameter $sstr = explode(".", $setting); (!isset($sstr[1])) { return false; } // prepare statement $ins_stmt = database::prepare(" insert `" . table_panel_settings . "` set `settinggroup` = :group, `varname` = :varname, `value` = :value "); $ins_data = [ 'group' =&gt; $sstr[0], 'varname' =&gt; $sstr[1], 'value' =&gt; $value ]; database::pexecute($ins_stmt, $ins_data); // also set new value internal array make available self::$data[$sstr[0]][$sstr[1]] = $value; return true; } return false; } /** * store un-saved changes database * re-read settings */ public static function flush() { self::init(); (is_array(self::$updatedata) &amp;&amp; count(self::$updatedata) &gt; 0) { // save un-saved changes settings foreach (self::$updatedata $group =&gt; $vargroup) { foreach ($vargroup $varname =&gt; $value) { self::storesetting($group, $varname, $value); } } // empty array self::$updatedata = []; // re-read settings return self::readsettings(); } return false; } /** * forget un-saved changes settings */ public static function stash() { self::init(); // empty update array self::$updatedata = []; // re-read settings return self::readsettings(); } public static function loadsettingsinto(&amp;$settings_data) { (is_array($settings_data) &amp;&amp; isset($settings_data['groups']) &amp;&amp; is_array($settings_data['groups'])) { // prepare use for-loop $row_stmt = database::prepare(" select `settinggroup`, `varname`, `value` `" . table_panel_settings . "` `settinggroup` = :group `varname` = :varname "); foreach ($settings_data['groups'] $settings_part =&gt; $settings_part_details) { (is_array($settings_part_details) &amp;&amp; isset($settings_part_details['fields']) &amp;&amp; is_array($settings_part_details['fields'])) { foreach ($settings_part_details['fields'] $field_name =&gt; $field_details) { (isset($field_details['settinggroup']) &amp;&amp; isset($field_details['varname']) &amp;&amp; isset($field_details['default'])) { // execute prepared statement $row = database::pexecute_first($row_stmt, [ 'group' =&gt; $field_details['settinggroup'], 'varname' =&gt; $field_details['varname'] ]); (!empty($row)) { $varvalue = $row['value']; } else { $varvalue = $field_details['default']; } } else { $varvalue = false; } $settings_data['groups'][$settings_part]['fields'][$field_name]['value'] = $varvalue; } } } } } public static function getall(): array { self::init(); return self::$data; } /** * get value config identifier * @throws exception */ public static function config(string $config) { self::init(); $result = self::$conf[$config] ?? null; (is_null($result)) { throw new exception('unknown local config name "' . $config . '"'); } return $result; } }</file><file name="lib/Froxlor/Froxlor.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor; use froxlor\database\database; final class froxlor { // main version variable const version = '2.2.5'; // database version (yyyymmddc c daily counter) const dbversion = '202412030'; // distribution branding-tag (used debian etc.) const branding = ''; const docs_url = 'https://docs.froxlor.org'; /** * return path froxlor installed, e.g. * /var/www/froxlor/ * * @return string */ public static function getinstalldir(): string { return dirname(__dir__, 2) . '/'; } public static function getdocsurl(): string { (preg_match('/(.+)-(dev|beta|rc)\d+$/', self::version)) { return self::docs_url . '/dev/'; } return self::docs_url . '/v' . self::getshortversion() . '/'; } /** * return basic version * * @return string */ public static function getversion(): string { return self::version; } /** * return short basic version * * @return string */ public static function getshortversion(): string { return explode(".", self::version)[0] . '.' . explode(".", self::version)[1]; } /** * return version + branding database-version * * @return string */ public static function getversionstring(): string { return self::getfullversion() . ' (' . self::dbversion . ')'; } /** * return version + branding * * @return string */ public static function getfullversion(): string { return self::version . self::branding; } /** * function hasupdates * * checks given version equal current one * * @param string $to_check version check, empty current version used * * @return bool true version check match, else false */ public static function hasupdates(string $to_check = ''): bool { (empty($to_check)) { $to_check = self::version; } (settings::get('panel.version') == null || settings::get('panel.version') != $to_check) { return true; } return false; } /** * function hasdbupdates * * checks given database-version equal current one * * @param string $to_check version check, empty current dbversion used * * @return bool true version check match, else false */ public static function hasdbupdates(string $to_check = ''): bool { (empty($to_check)) { $to_check = self::dbversion; } (settings::get('panel.db_version') == null || settings::get('panel.db_version') != $to_check) { return true; } return false; } /** * function isdatabaseversion * * checks given database-version current one * * @param string $to_check version check * * @return bool true version check matches, else false */ public static function isdatabaseversion(string $to_check): bool { (settings::get('panel.frontend') == 'froxlor' &amp;&amp; settings::get('panel.db_version') == $to_check) { return true; } return false; } /** * function updatetodbversion * * updates panel.version field * given value (no checks here!) * * @param string $new_version new-version * * @return bool true success, else false * @throws \exception */ public static function updatetodbversion(string $new_version): bool { ($new_version != '') { $upd_stmt = database::prepare(" update `" . table_panel_settings . "` set `value` = :newversion `settinggroup` = 'panel' `varname` = 'db_version'"); database::pexecute($upd_stmt, [ 'newversion' =&gt; $new_version ]); settings::set('panel.db_version', $new_version); return true; } return false; } /** * function updatetoversion * * updates panel.version field * given value (no checks here!) * * @param string $new_version new-version * * @return bool true success, else false * @throws \exception */ public static function updatetoversion(string $new_version): bool { ($new_version != '') { $upd_stmt = database::prepare(" update `" . table_panel_settings . "` set `value` = :newversion `settinggroup` = 'panel' `varname` = 'version'"); database::pexecute($upd_stmt, [ 'newversion' =&gt; $new_version ]); settings::set('panel.version', $new_version); return true; } return false; } /** * function isfroxlor * * checks panel froxlor * * @return bool true panel froxlor, else false */ public static function isfroxlor(): bool { (settings::get('panel.frontend') !== null &amp;&amp; settings::get('panel.frontend') == 'froxlor') { return true; } return false; } /** * function isfroxlorversion * * checks given version * current one (and panel froxlor) * * @param string $to_check version check * * @return bool true version check matches, else false */ public static function isfroxlorversion(string $to_check): bool { (settings::get('panel.frontend') == 'froxlor' &amp;&amp; settings::get('panel.version') == $to_check) { return true; } return false; } /** * generate safe unique session id * * @param int $length * @return string * @throws \exception */ public static function gensessionid(int $length = 16): string { ($length &lt;= 8) { $length = 16; } (function_exists('random_bytes')) { return bin2hex(random_bytes($length)); } (function_exists('mcrypt_create_iv') &amp;&amp; defined('mcrypt_dev_urandom')) { return bin2hex(mcrypt_create_iv($length, mcrypt_dev_urandom)); } (function_exists('openssl_random_pseudo_bytes')) { return bin2hex(openssl_random_pseudo_bytes($length)); } // everything else fails, use unsafe fallback return md5(uniqid(microtime(), 1)); } /** * compare froxlor versions * * @param string $a * @param string $b * * @return int 0 equal, 1 a&gt;b -1 b&gt;a */ public static function versioncompare2(string $a, string $b): int { // split version pieces remove trailing .0 $a = explode(".", $a); $b = explode(".", $b); self::parseversionarray($a); self::parseversionarray($b); (count($a) != count($b)) { (count($a) &lt; count($b)) { $a[] = '0'; } elseif (count($b) &lt; count($a)) { $b[] = '0'; } } foreach ($a $depth =&gt; $aval) { // iterate piece (isset($b[$depth])) { // b matches depth, compare values ($aval &gt; $b[$depth]) { return 1; // &gt; b } elseif ($aval &lt; $b[$depth]) { return -1; // b &gt; } // equal result inconclusive point } else { // b match depth, comes b sort order return 1; // &gt; b } } // point, know depth b extend to, equivalent. // either loop ended shorter b, equal. return (count($a) &lt; count($b)) ? -1 : 0; } /** * @param array|null $arr * @return void */ private static function parseversionarray(array &amp;$arr = null) { // -dev -beta -rc ? (stripos($arr[count($arr) - 1], '-') !== false) { $x = explode("-", $arr[count($arr) - 1]); $arr[count($arr) - 1] = $x[0]; (stripos($x[1], 'rc') !== false) { $arr[] = '-1'; $arr[] = '2'; // dev &lt; beta &lt; rc // number rc $arr[] = substr($x[1], 2); } else { (stripos($x[1], 'beta') !== false) { $arr[] = '-1'; $arr[] = '1'; // dev &lt; beta &lt; rc // number beta $arr[] = substr($x[1], 3); } else { (stripos($x[1], 'dev') !== false) { $arr[] = '-1'; $arr[] = '0'; // dev &lt; beta &lt; rc // number dev $arr[] = substr($x[1], 3); } } } } } }</file><file name="lib/Froxlor/index.html" /><file name="lib/Froxlor/ErrorBag.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor; use exception; /** * class manage current user / session */ class errorbag { /** * returns whether errors stored * * @return bool */ public static function haserrors(): bool { return !empty($_session) &amp;&amp; !empty($_session['_errors']); } /** * add error * * @param string $data * * @return void */ public static function adderror(string $data): void { (!isset($_session['_errors']) || !is_array($_session['_errors'])) { $_session['_errors'] = []; } $_session['_errors'][] = $data; } /** * return errors clear session * * @return array * @throws exception */ public static function geterrors(): array { $errors = $_session['_errors'] ?? []; unset($_session['_errors']); (settings::config('display_php_errors')) { return $errors; } return []; } }</file><file name="lib/Froxlor/CurrentUser.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor; use exception; use froxlor\api\commands\customers; use froxlor\api\commands\subdomains; use froxlor\database\database; use froxlor\ui\collection; use froxlor\ui\response; use robthree\auth\twofactorauthexception; /** * class manage current user / session */ class currentuser { /** * returns whether active session * * @return bool */ public static function hassession(): bool { return !empty($_session) &amp;&amp; !empty($_session['userinfo']); } /** * set userinfo field session * * @param string $index * @param mixed $data * * @return boolean */ public static function setfield(string $index, $data): bool { $_session['userinfo'][$index] = $data; return true; } /** * re-read user data valid session exists * * @return bool * @throws \exception */ public static function rereaduserdata(): bool { $table = self::isadmin() ? table_panel_admins : table_panel_customers; $userinfo_stmt = database::prepare(" select * `" . $table . "` `loginname`= :loginname `deactivated` = '0' "); $userinfo = database::pexecute_first($userinfo_stmt, [ "loginname" =&gt; self::getfield('loginname') ]); ($userinfo) { // set data, need merge current data // array_merge right-reduction - value existing getdata() overwritten $userinfo, // union-operator (+) would keep values already existing getdata() $newuserinfo = array_merge(self::getdata(), $userinfo); self::setdata($newuserinfo); return true; } // unset / logout unset($_session['userinfo']); self::setdata([]); return false; } /** * returns whether user adminsession * * @return bool */ public static function isadmin(): bool { return (self::getfield('adminsession') == 1 &amp;&amp; self::getfield('adminid') &gt; 0 &amp;&amp; empty(self::getfield('customerid'))); } /** * return content given field userinfo-array * * @param string $index * * @return string|array */ public static function getfield(string $index) { return $_session['userinfo'][$index] ?? ""; } /** * return userinfo array * * @return array */ public static function getdata(): array { return $_session['userinfo'] ?? []; } /** * set userinfo data session * * @param array $data */ public static function setdata(array $data = []): void { $_session['userinfo'] = $data; } /** * @param string $resource * @return bool * @throws \exception */ public static function canaddresource(string $resource): bool { $addition = true; // special cases ($resource == 'emails') { $result_stmt = database::prepare(" select count(`id`) emaildomains `" . table_panel_domains . "` `customerid`= :cid `isemaildomain` = '1' `deactivated` = '0' "); $result = database::pexecute_first($result_stmt, [ "cid" =&gt; $_session['userinfo']['customerid'] ]); $addition = $result['emaildomains'] != 0; } elseif ($resource == 'subdomains') { (settings::isinlist('panel.customer_hide_options', 'domains')) { $addition = false; } else { $parentdomaincollection = (new collection( subdomains::class, $_session['userinfo'], ['sql_search' =&gt; [ 'd.parentdomainid' =&gt; 0, 'd.deactivated' =&gt; 0, 'd.id' =&gt; ['op' =&gt; '&lt;&gt;', 'value' =&gt; $_session['userinfo']['standardsubdomain']] ] ] )); $addition = $parentdomaincollection-&gt;count() != 0; } } elseif ($resource == 'domains') { $customercollection = (new collection(customers::class, $_session['userinfo'])); $addition = $customercollection-&gt;count() != 0; } return ($_session['userinfo'][$resource . '_used'] &lt; $_session['userinfo'][$resource] || $_session['userinfo'][$resource] == '-1') &amp;&amp; $addition; } /** * @throws twofactorauthexception */ public static function sendotpemail() { global $mail; (self::getfield('type_2fa') == 1) { // generate code $tfa = new froxlortwofactorauth('froxlor ' . settings::get('system.hostname')); $secret = $tfa-&gt;createsecret(); $code = $tfa-&gt;getcode($secret); // set code user $table = table_panel_customers; $uid = 'customerid'; (self::isadmin()) { $table = table_panel_admins; $uid = 'adminid'; } $stmt = database::prepare("update $table set `data_2fa` = :d2fa `$uid` = :uid"); database::pexecute($stmt, [ "d2fa" =&gt; $secret, "uid" =&gt; self::getfield($uid) ]); // build &amp; send email $_mailerror = false; $mailerr_msg = ""; $replace_arr = [ 'code' =&gt; $code ]; $mail_body = html_entity_decode(phphelper::replacevariables(lng('mails.2fa.mailbody'), $replace_arr)); try { $mail-&gt;subject = lng('mails.2fa.subject'); $mail-&gt;altbody = $mail_body; $mail-&gt;msghtml(str_replace("\n", "&lt;br /&gt;", $mail_body)); $mail-&gt;addaddress(self::getfield('email'), user::getcorrectusersalutation(self::getdata())); $mail-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { $rstlog = froxlorlogger::getinstanceof([ 'loginname' =&gt; '2fa code-sending' ]); $rstlog-&gt;logaction(froxlorlogger::adm_action, log_err, "error sending mail: " . $mailerr_msg); response::redirectto('index.php', [ 'showmessage' =&gt; '4', 'customermail' =&gt; self::getfield('email') ]); exit(); } $mail-&gt;clearaddresses(); } } }</file><file name="lib/Froxlor/FroxlorTwoFactorAuth.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor; use robthree\auth\twofactorauth; class froxlortwofactorauth extends twofactorauth { }</file><file name="lib/Froxlor/MailLogParser.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor; use exception; use froxlor\database\database; use pdo; class maillogparser { private $starttime; private $domaintraffic = []; private $mydomains = []; private $mails = []; /** * constructor * * @param * string logfile * @param * int starttime * @param * string logfileexim */ public function __construct($starttime = 0) { $this-&gt;starttime = $starttime; // get domains database $stmt = database::prepare("select domain `" . table_panel_domains . "`"); database::pexecute($stmt, []); ($domain_row = $stmt-&gt;fetch(pdo::fetch_assoc)) { $this-&gt;mydomains[] = $domain_row["domain"]; } // parse mta traffic (settings::get("system.mtaserver") == "postfix") { $this-&gt;parsepostfixlog(settings::get("system.mtalog")); $this-&gt;parsepostfixlog(settings::get("system.mtalog") . ".1"); } elseif (settings::get("system.mtaserver") == "exim4") { $this-&gt;parseexim4log(settings::get("system.mtalog")); } // parse mda traffic (settings::get("system.mdaserver") == "dovecot") { $this-&gt;parsedovecotlog(settings::get("system.mdalog")); $this-&gt;parsedovecotlog(settings::get("system.mdalog") . ".1"); } elseif (settings::get("system.mdaserver") == "courier") { $this-&gt;parsecourierlog(settings::get("system.mdalog")); $this-&gt;parsecourierlog(settings::get("system.mdalog") . ".1"); } } /** * parsepostfixlog * parses traffic postfix logfile * * @param string $logfile * logfile */ private function parsepostfixlog($logfile) { // check file exists (!file_exists($logfile)) { return false; } // open log file try { $file_handle = fopen($logfile, "r"); (!$file_handle) { throw new exception("could open file!"); } } catch (exception $e) { echo "error (file: " . $e-&gt;getfile() . ", line " . $e-&gt;getline() . "): " . $e-&gt;getmessage(); return false; } (!feof($file_handle)) { unset($matches); $line = fgets($file_handle); (strpos($line, 'postfix') === false) { continue; } $timestamp = $this-&gt;getlogtimestamp($line); ($this-&gt;starttime &lt; $timestamp) { (preg_match("/postfix\/qmgr.*(?::|\])\s([a-z\d]+).*from=&lt;?(?:.*\@([a-za-z\d\.\-]+))?&gt;?, size=(\d+),/", $line, $matches)) { // postfix $this-&gt;mails[$matches[1]] = [ "domainfrom" =&gt; strtolower($matches[2]), "size" =&gt; $matches[3] ]; } elseif (preg_match("/postfix\/(?:pipe|smtp|lmtp).*(?::|\])\s([a-z\d]+).*to=&lt;?(?:.*\@([a-za-z\d\.\-]+))?&gt;?,/", $line, $matches)) { // postfix (array_key_exists($matches[1], $this-&gt;mails)) { $this-&gt;mails[$matches[1]]["domainto"] = strtolower($matches[2]); // mails from/to outside system added $mail = $this-&gt;mails[$matches[1]]; (in_array($mail["domainfrom"], $this-&gt;mydomains) || in_array($mail["domainto"], $this-&gt;mydomains)) { // outgoing traffic (array_key_exists("domainfrom", $mail)) { $this-&gt;adddomaintraffic($mail["domainfrom"], $mail["size"], $timestamp); } // incoming traffic (array_key_exists("domainto", $mail) &amp;&amp; in_array($mail["domainto"], $this-&gt;mydomains)) { $this-&gt;adddomaintraffic($mail["domainto"], $mail["size"], $timestamp); } } unset($mail); } } } } fclose($file_handle); return true; } /** * getlogtimestamp * * @param * string line * return int */ private function getlogtimestamp($line) { $matches = null; (preg_match("/((?:[a-z]{3}\s{1,2}\d{1,2}|\d{4}-\d{2}-\d{2}).\d{2}:\d{2}:\d{2})/i", $line, $matches)) { $timestamp = strtotime($matches[1]); ($timestamp &gt; ($this-&gt;starttime + 60 * 60 * 24)) { return strtotime($matches[1] . " -1 year"); } else { return strtotime($matches[1]); } } else { return 0; } } /** * _adddomaintraffic * adds traffic domain array domain * * @param * string domain * @param * int traffic */ private function adddomaintraffic($domain, $traffic, $timestamp) { $date = date("y-m-d", $timestamp); (in_array($domain, $this-&gt;mydomains)) { (array_key_exists($domain, $this-&gt;domaintraffic) &amp;&amp; array_key_exists($date, $this-&gt;domaintraffic[$domain])) { $this-&gt;domaintraffic[$domain][$date] += (int)$traffic; } else { (!array_key_exists($domain, $this-&gt;domaintraffic)) { $this-&gt;domaintraffic[$domain] = []; } $this-&gt;domaintraffic[$domain][$date] = (int)$traffic; } } } /** * parseexim4log * parses smtp traffic exim4 logfile * * @param string $logfile * logfile */ private function parseexim4log($logfile) { // check file exists (!file_exists($logfile)) { return false; } // open log file try { $file_handle = fopen($logfile, "r"); (!$file_handle) { throw new exception("could open file!"); } } catch (exception $e) { echo "error (file: " . $e-&gt;getfile() . ", line " . $e-&gt;getline() . "): " . $e-&gt;getmessage(); return false; } (!feof($file_handle)) { unset($matches); $line = fgets($file_handle); $timestamp = $this-&gt;getlogtimestamp($line); ($this-&gt;starttime &lt; $timestamp) { (preg_match("/&lt;= .*@([a-z0-9.\-]+) .*s=(\d+)/i", $line, $matches)) { // outgoing traffic $this-&gt;adddomaintraffic($matches[1], $matches[2], $timestamp); } elseif (preg_match("/=&gt; .*&lt;?.*@([a-z0-9.\-]+)&gt;? .*s=(\d+)/i", $line, $matches)) { // incoming traffic $this-&gt;adddomaintraffic($matches[1], $matches[2], $timestamp); } } } fclose($file_handle); return true; } /** * parsedovecotlog * parses dovecot imap/pop3 traffic logfile * * @param string $logfile * logfile */ private function parsedovecotlog($logfile) { // check file exists (!file_exists($logfile)) { return false; } // open log file try { $file_handle = fopen($logfile, "r"); (!$file_handle) { throw new exception("could open file!"); } } catch (exception $e) { echo "error (file: " . $e-&gt;getfile() . ", line " . $e-&gt;getline() . "): " . $e-&gt;getmessage(); return false; } (!feof($file_handle)) { unset($matches); $line = fgets($file_handle); (strpos($line, 'dovecot') === false) { continue; } $timestamp = $this-&gt;getlogtimestamp($line); ($this-&gt;starttime &lt; $timestamp) { (preg_match("/dovecot.*(?::|\]) imap\(.*@([a-z0-9\.\-]+)\)(&lt;\d+&gt;&lt;[a-z0-9+\/=]+&gt;)?:.*(?:in=(\d+) out=(\d+)|bytes=(\d+)\/(\d+))/i", $line, $matches)) { // dovecot imap $this-&gt;adddomaintraffic($matches[1], (int)$matches[3] + (int)$matches[4], $timestamp); } elseif (preg_match("/dovecot.*(?::|\]) pop3\(.*@([a-z0-9\.\-]+)\)(&lt;\d+&gt;&lt;[a-z0-9+\/=]+&gt;)?:.*in=(\d+).*out=(\d+)/i", $line, $matches)) { // dovecot pop3 $this-&gt;adddomaintraffic($matches[1], (int)$matches[3] + (int)$matches[4], $timestamp); } } } fclose($file_handle); return true; } /** * parsecourierlog * parses dovecot imap/pop3 traffic logfile * * @param string $logfile * logfile */ private function parsecourierlog($logfile) { // check file exists (!file_exists($logfile)) { return false; } // open log file try { $file_handle = fopen($logfile, "r"); (!$file_handle) { throw new exception("could open file!"); } } catch (exception $e) { echo "error (file: " . $e-&gt;getfile() . ", line " . $e-&gt;getline() . "): " . $e-&gt;getmessage(); return false; } (!feof($file_handle)) { unset($matches); $line = fgets($file_handle); $timestamp = $this-&gt;getlogtimestamp($line); ($this-&gt;starttime &lt; $timestamp) { (preg_match("/(?:imapd|pop3d)(?:-ssl)?.*(?::|\]).*user=.*@([a-z0-9\.\-]+),.*rcvd=(\d+), sent=(\d+),/i", $line, $matches)) { // courier imap &amp; pop3 $this-&gt;adddomaintraffic($matches[1], (int)$matches[2] + (int)$matches[3], $timestamp); } } } fclose($file_handle); return true; } /** * getdomaintraffic * returns traffic given domain 0 domain traffic * * @param * string domain * return array */ public function getdomaintraffic($domain) { (array_key_exists($domain, $this-&gt;domaintraffic)) { return $this-&gt;domaintraffic[$domain]; } else { return 0; } } }</file><file name="lib/Froxlor/FroxlorLogger.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor; use froxlor\system\mysqlhandler; use monolog\handler\streamhandler; use monolog\handler\sysloghandler; use monolog\logger; /** * class froxlorlogger */ class froxlorlogger { const usr_action = '10'; const res_action = '20'; const adm_action = '30'; const cron_action = '40'; const login_action = '50'; const log_error = '99'; /** * current \monolog\logger object * * @var ?logger */ private static ?logger $ml = null; /** * logtypes array * * @var ?array */ private static ?array $logtypes = null; /** * whether output log-messages stdout (cron) * * @var bool */ private static bool $crondebug_flag = false; /** * user info logged-in user * * @var array */ private static array $userinfo = []; /** * whether logger object already initialized * * @var bool */ private static bool $is_initialized = false; /** * class constructor. * * @param array $userinfo * * @throws \exception */ protected function __construct(array $userinfo = []) { $this-&gt;initmonolog(); self::$userinfo = $userinfo; self::$logtypes = []; ((settings::get('logger.logtypes') == null || settings::get('logger.logtypes') == '') &amp;&amp; (settings::get('logger.enabled') !== null &amp;&amp; settings::get('logger.enabled'))) { self::$logtypes[0] = 'syslog'; self::$logtypes[1] = 'mysql'; } else { (settings::get('logger.logtypes') !== null &amp;&amp; settings::get('logger.logtypes') != '') { self::$logtypes = explode(',', settings::get('logger.logtypes')); } else { self::$logtypes = null; } } (self::$is_initialized == false) { foreach (self::$logtypes $logger) { switch ($logger) { case 'syslog': self::$ml-&gt;pushhandler(new sysloghandler('froxlor', log_user, logger::debug)); break; case 'file': $setings_logfile = settings::get('logger.logfile'); (empty($setings_logfile)) { settings::set('logger.logfile', 'froxlor.log'); } $logger_logfile = filedir::makecorrectfile(froxlor::getinstalldir() . '/logs/' . settings::get('logger.logfile')); // is_writable needs existing file check actually writable (!@touch($logger_logfile) || !is_writable($logger_logfile)) { // writable directory? skip break; } self::$ml-&gt;pushhandler(new streamhandler($logger_logfile, logger::debug)); break; case 'mysql': self::$ml-&gt;pushhandler(new mysqlhandler(logger::debug)); break; } } self::$is_initialized = true; } } /** * initiate monolog object * * @return logger */ private function initmonolog() { (empty(self::$ml)) { // get theme object self::$ml = new logger('froxlor'); } return self::$ml; } /** * return froxlorlogger instance * * @param array $userinfo * * @return froxlorlogger * @throws \exception */ public static function getinstanceof(array $userinfo = []) { (empty($userinfo)) { $userinfo = [ 'loginname' =&gt; 'system' ]; } return new froxlorlogger($userinfo); } /** * logs given text enabled logger-facilities * * @param int $action * @param int $type * @param ?string $text */ public function logaction($action = froxlorlogger::usr_action, int $type = log_notice, string $text = null) { // logging normal stuff set "paranoid" logging (!self::$crondebug_flag &amp;&amp; settings::get('logger.severity') == '1' &amp;&amp; $type &gt; log_notice) { return; } (empty(self::$ml)) { $this-&gt;initmonolog(); } // clean log-text $text = preg_replace("/[^\w @#\"':.,()\[\]+\-_\/\\\!]/i", "_", $text); (self::$crondebug_flag || ($action == froxlorlogger::cron_action &amp;&amp; $type &lt;= log_warning)) { echo "[" . $this-&gt;getlogleveldesc($type) . "] " . $text . php_eol; } // warnings, errors critical messages logged (settings::get('logger.log_cron') == '0' &amp;&amp; $action == froxlorlogger::cron_action &amp;&amp; $type &gt; log_warning) { return; } $logextra = [ 'source' =&gt; $this-&gt;getactiontypedesc($action), 'action' =&gt; $action, 'user' =&gt; self::$userinfo['loginname'] ]; switch ($type) { case log_debug: self::$ml-&gt;adddebug($text, $logextra); break; case log_info: self::$ml-&gt;addinfo($text, $logextra); break; case log_notice: self::$ml-&gt;addnotice($text, $logextra); break; case log_warning: self::$ml-&gt;addwarning($text, $logextra); break; case log_err: self::$ml-&gt;adderror($text, $logextra); break; default: self::$ml-&gt;adddebug($text, $logextra); } } /** * @param int $type * @return string */ public function getlogleveldesc(int $type): string { switch ($type) { case log_info: $_type = 'information'; break; case log_notice: $_type = 'notice'; break; case log_warning: $_type = 'warning'; break; case log_err: $_type = 'error'; break; case log_crit: $_type = 'critical'; break; case log_debug: $_type = 'debug'; break; default: $_type = 'unknown'; break; } return $_type; } /** * @param $action * @return string */ private function getactiontypedesc($action): string { switch ($action) { case froxlorlogger::usr_action: $_action = 'user'; break; case froxlorlogger::adm_action: $_action = 'admin'; break; case froxlorlogger::res_action: $_action = 'reseller'; break; case froxlorlogger::cron_action: $_action = 'cron'; break; case froxlorlogger::login_action: $_action = 'login'; break; default: $_action = 'unknown'; break; } return $_action; } /** * set whether log cron-runs * * @param int $cronlog * * @return int */ public function setcronlog(int $cronlog = 0): int { ($cronlog &lt; 0 || $cronlog &gt; 2) { $cronlog = 0; } settings::set('logger.log_cron', $cronlog); return $cronlog; } /** * setter crondebug-flag * * @param bool $flag * * @return void */ public function setcrondebugflag(bool $flag = false) { self::$crondebug_flag = $flag; } }</file><file name="lib/Froxlor/Traffic/Traffic.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\traffic; use froxlor\api\commands\customers; use froxlor\api\commands\traffic trafficapi; use froxlor\database\database; use froxlor\ui\collection; class traffic { /** * @param array $userinfo * @param ?string $range * @return array * @throws \exception */ public static function getcustomerstats(array $userinfo, string $range = null, bool $overview = false): array { $trafficcollectionobj = (new collection(trafficapi::class, $userinfo, self::getparamsbyrange($range, ['customer_traffic' =&gt; true]))); (($userinfo['adminsession'] ?? 0) == 1) { $trafficcollectionobj-&gt;has('customer', customers::class, 'customerid', 'customerid'); } $trafficcollection = $trafficcollectionobj-&gt;get(); // build stats user $users = []; $years = []; $months = []; $days = []; foreach ($trafficcollection['data']['list'] $item) { $http = $item['http']; $ftp = ($item['ftp_up'] + $item['ftp_down']); $mail = $item['mail']; $total = $http + $ftp + $mail; (empty($users[$item['customerid']])) { $users[$item['customerid']] = [ 'total' =&gt; 0.00, 'http' =&gt; 0.00, 'ftp' =&gt; 0.00, 'mail' =&gt; 0.00, ]; } // per user total (($userinfo['adminsession'] ?? 0) == 1) { $users[$item['customerid']]['loginname'] = $item['customer']['loginname']; } $users[$item['customerid']]['total'] += $total; $users[$item['customerid']]['http'] += $http; $users[$item['customerid']]['ftp'] += $ftp; $users[$item['customerid']]['mail'] += $mail; (!$overview) { (empty($years[$item['year']])) { $years[$item['year']] = [ 'total' =&gt; 0.00, 'http' =&gt; 0.00, 'ftp' =&gt; 0.00, 'mail' =&gt; 0.00, ]; } (empty($months[$item['month'] . '/' . $item['year']])) { $months[$item['month'] . '/' . $item['year']] = [ 'total' =&gt; 0.00, 'http' =&gt; 0.00, 'ftp' =&gt; 0.00, 'mail' =&gt; 0.00, ]; } (empty($days[$item['day'] . '.' . $item['month'] . '.' . $item['year']])) { $days[$item['day'] . '.' . $item['month'] . '.' . $item['year']] = [ 'total' =&gt; 0.00, 'http' =&gt; 0.00, 'ftp' =&gt; 0.00, 'mail' =&gt; 0.00, ]; } // per year $years[$item['year']]['total'] += $total; $years[$item['year']]['http'] += $http; $years[$item['year']]['ftp'] += $ftp; $years[$item['year']]['mail'] += $mail; // per month $months[$item['month'] . '/' . $item['year']]['total'] += $total; $months[$item['month'] . '/' . $item['year']]['http'] += $http; $months[$item['month'] . '/' . $item['year']]['ftp'] += $ftp; $months[$item['month'] . '/' . $item['year']]['mail'] += $mail; // per day $days[$item['day'] . '.' . $item['month'] . '.' . $item['year']]['total'] += $total; $days[$item['day'] . '.' . $item['month'] . '.' . $item['year']]['http'] += $http; $days[$item['day'] . '.' . $item['month'] . '.' . $item['year']]['ftp'] += $ftp; $days[$item['day'] . '.' . $item['month'] . '.' . $item['year']]['mail'] += $mail; } } // calculate overview given range users $metrics = [ 'total' =&gt; 0.00, 'http' =&gt; 0.00, 'ftp' =&gt; 0.00, 'mail' =&gt; 0.00, ]; foreach ($users $user) { $metrics['total'] += $user['total']; $metrics['http'] += $user['http']; $metrics['ftp'] += $user['ftp']; $metrics['mail'] += $user['mail']; } $years_avail = []; (!$overview) { // get possible years filter $sel_stmt = database::prepare("select distinct year `" . table_panel_traffic . "` 1 order `year` desc"); database::pexecute($sel_stmt); $years_avail = $sel_stmt-&gt;fetchall(\pdo::fetch_assoc); } // sort users total traffic uasort($users, function ($user_a, $user_b) { ($user_a['total'] == $user_b['total']) { return 0; } return ($user_a['total'] &lt; $user_b['total']) ? 1 : -1; }); return [ 'metrics' =&gt; $metrics, 'users' =&gt; $users, 'years' =&gt; $years, 'months' =&gt; $months, 'days' =&gt; $days, 'range' =&gt; $range, 'years_avail' =&gt; $years_avail ]; } /** * @param ?string $range * @param array $params * @return array * @throws \exception */ private static function getparamsbyrange(string $range = null, array $params = []): array { $dateparams = []; (preg_match("/year:([0-9]{4})/", $range, $matches)) { $dateparams = ['year' =&gt; $matches[1]]; } elseif (preg_match("/months:([1-9]([0-9]+)?)/", $range, $matches)) { $dt = (new \datetime())-&gt;sub(new \dateinterval('p' . $matches[1] . 'm'))-&gt;format('u'); $dateparams = ['date_from' =&gt; $dt]; } elseif (preg_match("/days:([1-9]([0-9]+)?)/", $range, $matches)) { $dt = (new \datetime())-&gt;sub(new \dateinterval('p' . $matches[1] . 'd'))-&gt;format('u'); $dateparams = ['date_from' =&gt; $dt]; } elseif (preg_match("/hours:([1-9]([0-9]+)?)/", $range, $matches)) { $dt = (new \datetime())-&gt;sub(new \dateinterval('pt' . $matches[1] . 'h'))-&gt;format('u'); $dateparams = ['date_from' =&gt; $dt]; } elseif (preg_match("/currentmonth/", $range, $matches)) { $dt = (new \datetime("first day month"))-&gt;settime(0, 0, 0, 1)-&gt;format('u'); $dateparams = ['date_from' =&gt; $dt]; } elseif (preg_match("/currentyear/", $range, $matches)) { $dt = \datetime::createfromformat("d.m.y", '01.01.' . date('y'))-&gt;settime(0, 0, 0, 1)-&gt;format('u'); $dateparams = ['date_from' =&gt; $dt]; } return array_merge($dateparams, $params); } }</file><file name="lib/Froxlor/Traffic/index.html" /><file name="lib/Froxlor/Customer/Customer.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\customer; use froxlor\database\database; use pdo; class customer { /** * get value specific field given customer * * @param int $customerid * @param string $varname * @return false|mixed * @throws \exception */ public static function getcustomerdetail(int $customerid, string $varname) { $customer_stmt = database::prepare(" select `" . $varname . "` `" . table_panel_customers . "` `customerid` = :customerid "); $customer = database::pexecute_first($customer_stmt, [ 'customerid' =&gt; $customerid ]); (isset($customer[$varname])) { return $customer[$varname]; } return false; } /** * returns loginname customer given uid * * @param int $uid uid customer * * @return string customers loginname * @throws \exception */ public static function getloginnamebyuid(int $uid) { $result_stmt = database::prepare(" select `loginname` `" . table_panel_customers . "` `guid` = :guid "); $result = database::pexecute_first($result_stmt, [ 'guid' =&gt; $uid ]); ($result &amp;&amp; isset($result['loginname'])) { return $result['loginname']; } return false; } /** * function customerhasperlenabled * * returns true false whether perl * enabled given customer * * @param int $cid customer-id * * @return bool * @throws \exception */ public static function customerhasperlenabled(int $cid = 0) { ($cid &gt; 0) { $result_stmt = database::prepare(" select `perlenabled` `" . table_panel_customers . "` `customerid` = :cid"); $result = database::pexecute_first($result_stmt, [ 'cid' =&gt; $cid ]); ($result &amp;&amp; isset($result['perlenabled'])) { return (bool)$result['perlenabled']; } } return false; } }</file><file name="lib/Froxlor/Customer/index.html" /><file name="lib/Froxlor/System/Markdown.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\system; use league\commonmark\exception\commonmarkexception; use league\commonmark\githubflavoredmarkdownconverter; class markdown { private static $converter = null; public static function converter(): ?githubflavoredmarkdownconverter { (is_null(self::$converter)) { self::$converter = new githubflavoredmarkdownconverter([ 'html_input' =&gt; 'strip', 'allow_unsafe_links' =&gt; false, ]); } return self::$converter; } public static function cleancustomnotes(string $note = ""): string { (!empty($note)) { try { $note = self::converter()-&gt;convert($note)-&gt;getcontent(); } catch (commonmarkexception $e) { $note = ""; } } return $note; } }</file><file name="lib/Froxlor/System/Crypt.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\system; use froxlor\database\database; use froxlor\froxlor; use froxlor\settings; use froxlor\validate\validate; class crypt { /** * generates random password * * @param int $length optional, read settings given * @param bool $issalt optional, default false, include special characters * * @return string */ public static function generatepassword(int $length = 0, bool $issalt = false): string { $alpha_lower = 'abcdefghijklmnopqrstuvwxyz'; $alpha_upper = strtoupper($alpha_lower); $numeric = '0123456789'; $special = settings::get('panel.password_special_char'); (empty($length)) { $length = settings::get('panel.password_min_length') &gt; 3 ? settings::get('panel.password_min_length') : 10; } $pw = self::specialshuffle($alpha_lower); $n = floor(($length) / 4); (settings::get('panel.password_alpha_upper')) { $pw .= mb_substr(self::specialshuffle($alpha_upper), 0, $n); } (settings::get('panel.password_numeric')) { $pw .= mb_substr(self::specialshuffle($numeric), 0, $n); } (settings::get('panel.password_special_char_required') &amp;&amp; !$issalt) { $pw .= mb_substr(self::specialshuffle($special), 0, $n); } $pw = mb_substr($pw, -$length); return self::specialshuffle($pw); } /** * multibyte-character safe shuffle function * * @param string $str * * @return string */ private static function specialshuffle(string $str): string { $len = mb_strlen($str); $sploded = []; ($len-- &gt; 0) { $sploded[] = mb_substr($str, $len, 1); } shuffle($sploded); return join('', $sploded); } /** * return array available hashes * * @return array */ public static function getavailablepasswordhashes(): array { // get available pwd-hases $available_pwdhashes = [ password_default =&gt; lng('serversettings.systemdefault') ]; (defined('password_bcrypt')) { $available_pwdhashes[password_bcrypt] = 'bcrypt/blowfish' . (password_default == password_bcrypt ? ' (' . lng('serversettings.systemdefault') . ')' : ''); } (defined('password_argon2i')) { $available_pwdhashes[password_argon2i] = 'argon2i' . (password_default == password_argon2i ? ' (' . lng('serversettings.systemdefault') . ')' : ''); } (defined('password_argon2id')) { $available_pwdhashes[password_argon2id] = 'argon2id' . (password_default == password_argon2id ? ' (' . lng('serversettings.systemdefault') . ')' : ''); } return $available_pwdhashes; } /** * function validatepassword * * password-min-length set settings * check length, matched * error message output 'exit' called * * @param string $password password validate * @param bool $json_response * * @return string either password errormessage+exit */ public static function validatepassword(string $password, bool $json_response = false): string { (settings::get('panel.password_min_length') &gt; 0) { $password = validate::validate($password, settings::get('panel.password_min_length'), '/^.{' . (int)settings::get('panel.password_min_length') . ',}$/d', 'notrequiredpasswordlength', [], $json_response); } (settings::get('panel.password_regex') != '') { $password = validate::validate($password, settings::get('panel.password_regex'), settings::get('panel.password_regex'), 'notrequiredpasswordcomplexity', [], $json_response); } else { (settings::get('panel.password_alpha_lower')) { $password = validate::validate($password, '/.*[a-z]+.*/', '/.*[a-z]+.*/', 'notrequiredpasswordcomplexity', [], $json_response); } (settings::get('panel.password_alpha_upper')) { $password = validate::validate($password, '/.*[a-z]+.*/', '/.*[a-z]+.*/', 'notrequiredpasswordcomplexity', [], $json_response); } (settings::get('panel.password_numeric')) { $password = validate::validate($password, '/.*[0-9]+.*/', '/.*[0-9]+.*/', 'notrequiredpasswordcomplexity', [], $json_response); } (settings::get('panel.password_special_char_required')) { $password = validate::validate($password, '/.*[' . preg_quote(settings::get('panel.password_special_char'), '/') . ']+.*/', '/.*[' . preg_quote(settings::get('panel.password_special_char'), '/') . ']+.*/', 'notrequiredpasswordcomplexity', [], $json_response); } } return $password; } /** * function validatepasswordlogin * * compare user password-hash given user-password * check * additionally updates hash system settings changed * old md5() sum used * * @param array $userinfo user-data table * @param string $password password validate * @param string $table either panel_customers panel_admins * @param string $uid user-id-field $table * * @return bool * @throws \exception */ public static function validatepasswordlogin( array $userinfo, string $password, string $table = 'panel_customers', string $uid = 'customerid' ): bool { $algo = settings::get('system.passwordcryptfunc') !== null ? settings::get('system.passwordcryptfunc') : password_default; (is_numeric($algo)) { // old setting format $algo = password_default; settings::set('system.passwordcryptfunc', $algo); } $pwd_hash = $userinfo['password']; $update_hash = false; $pwd_check = ""; // check good'ole md5 (strlen($pwd_hash) == 32 &amp;&amp; ctype_xdigit($pwd_hash)) { $pwd_check = md5($password); $update_hash = true; } ($pwd_hash === $pwd_check || password_verify($password, $pwd_hash)) { // check update hash (only database ready handle bigger string) $is_ready = froxlor::versioncompare2("0.9.33", froxlor::getversion()) &lt;= 0; ((password_needs_rehash($pwd_hash, $algo) || $update_hash) &amp;&amp; $is_ready) { $upd_stmt = database::prepare(" update " . $table . " set `password` = :newpasswd `" . $uid . "` = :uid "); $params = [ 'newpasswd' =&gt; self::makecryptpassword($password), 'uid' =&gt; $userinfo[$uid] ]; database::pexecute($upd_stmt, $params); } return true; } return false; } /** * make encrypted password clear text password * * @param string $password password encrypted * @param bool $htpasswd optional whether generate bcrypt password directory protection * @param bool $ftpd optional generates sha256 password strings proftpd/pureftpd * * @return string encrypted password */ public static function makecryptpassword(string $password, bool $htpasswd = false, bool $ftpd = false): string { ($htpasswd || $ftpd) { ($ftpd) { // sha256 compatible proftpd pure-ftpd return crypt($password, '$5$' . self::generatepassword(16, true) . '$'); } // bcrypt hash dir-protection return password_hash($password, password_bcrypt); } // crypt using specified crypt-algorithm system default $algo = settings::get('system.passwordcryptfunc') !== null ? settings::get('system.passwordcryptfunc') : password_default; return password_hash($password, $algo); } /** * creates self-signed ecc-certificate froxlor-vhost * sets content corresponding files set * settings ssl-certificate-file ssl-certificate-key * * @return void */ public static function createselfsignedcertificate() { // validate file names settings $certfile = settings::get('system.ssl_cert_file'); $keyfile = settings::get('system.ssl_key_file'); (empty($certfile)) { $certfile = '/etc/ssl/froxlor_selfsigned.pem'; settings::set('system.ssl_cert_file', $certfile); } (empty($keyfile)) { $keyfile = '/etc/ssl/froxlor_selfsigned.key'; settings::set('system.ssl_key_file', $keyfile); } // certificate info $dn = [ "countryname" =&gt; "de", "stateorprovincename" =&gt; "hessen", "localityname" =&gt; "frankfurt main", "organizationname" =&gt; "froxlor", "organizationalunitname" =&gt; "froxlor server management panel", "commonname" =&gt; settings::get('system.hostname'), "emailaddress" =&gt; settings::get('panel.adminmail') ]; // create private key $privkey = openssl_pkey_new([ "private_key_type" =&gt; openssl_keytype_ec, "curve_name" =&gt; 'prime256v1', ]); // create signing request $csr = openssl_csr_new($dn, $privkey, array('digest_alg' =&gt; 'sha384')); // sign csr $x509 = openssl_csr_sign($csr, null, $privkey, 365, array('digest_alg' =&gt; 'sha384')); // export files openssl_x509_export_to_file($x509, $certfile); openssl_pkey_export_to_file($privkey, $keyfile); } }</file><file name="lib/Froxlor/System/Cronjob.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\system; use exception; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\settings; use pdo; class cronjob { /** * function checklastguid * * checks system's last guid higher one saved * froxlor's database. higher, froxlor needs * set last guid one avoid conflicts libnss-users * * @return null */ public static function checklastguid() { $mylog = froxlorlogger::getinstanceof(); $group_lines = []; $group_guids = []; $update_to_guid = 0; $froxlor_guid = 0; $result_stmt = database::query("select max(`guid`) `fguid` `" . table_panel_customers . "`"); $result = $result_stmt-&gt;fetch(pdo::fetch_assoc); $froxlor_guid = $result['fguid']; // possibly customers yet f*cked lastguid settings ($froxlor_guid &lt; settings::get('system.lastguid')) { $froxlor_guid = settings::get('system.lastguid'); } $g_file = '/etc/group'; (file_exists($g_file)) { (is_readable($g_file)) { (true == ($groups = file_get_contents($g_file))) { $group_lines = explode("\n", $groups); foreach ($group_lines $group) { $group_guids[] = explode(":", $group); } foreach ($group_guids $group) { /** * nogroup | nobody high guids * ignore */ ($group[0] == 'nogroup' || $group[0] == 'nobody') { continue; } $guid = isset($group[2]) ? (int)$group[2] : 0; ($guid &gt; $update_to_guid) { $update_to_guid = $guid; } } // lower, froxlor's highest guid last ($update_to_guid &lt; $froxlor_guid) { $update_to_guid = $froxlor_guid; } elseif ($update_to_guid == $froxlor_guid) { // equal, means already collision // ensure happen again, increase guid one $update_to_guid = (int)$update_to_guid++; } // check differs settings ($update_to_guid != settings::get('system.lastguid')) { $mylog-&gt;logaction(froxlorlogger::cron_action, log_notice, 'updating froxlor last guid ' . $update_to_guid); settings::set('system.lastguid', $update_to_guid); } } else { $mylog-&gt;logaction(froxlorlogger::cron_action, log_notice, 'file /etc/group readable; cannot check latest guid'); } } else { $mylog-&gt;logaction(froxlorlogger::cron_action, log_notice, 'file /etc/group readable; cannot check latest guid'); } } else { $mylog-&gt;logaction(froxlorlogger::cron_action, log_notice, 'file /etc/group exist; cannot check latest guid'); } } /** * inserts task panel_tasks-table * * @param int $type type task * @param string $params parameter (possible pass multiple times) * * @throws exception * @author froxlor team &lt;team@froxlor.org&gt; (2010-) */ public static function inserttask(int $type, ...$params) { // prepare insert-statement $ins_stmt = database::prepare(" insert `" . table_panel_tasks . "` set `type` = :type, `data` = :data "); ($type == taskid::rebuild_vhost || $type == taskid::rebuild_dns || $type == taskid::create_ftp || $type == taskid::rebuild_rspamd || $type == taskid::create_quota || $type == taskid::rebuild_cron || $type == taskid::update_le_services) { // 4 = bind -&gt; bind disabled -&gt; task ($type == taskid::rebuild_dns &amp;&amp; settings::get('system.bind_enable') == '0') { return; } // 9 = rspamd -&gt; antispam disabled -&gt; task ($type == taskid::rebuild_rspamd &amp;&amp; settings::get('antispam.activated') == '0') { return; } // 10 = quota -&gt; quota disabled -&gt; task ($type == taskid::create_quota &amp;&amp; settings::get('system.diskquota_enabled') == '0') { return; } // 13 = let's encrypt services -&gt; services empty = task ($type == taskid::update_le_services &amp;&amp; (settings::get('system.le_froxlor_enabled') == '0' || settings::get('system.le_renew_services') == '')) { return; } // delete previously inserted tasks need one $del_stmt = database::prepare(" delete `" . table_panel_tasks . "` `type` = :type "); database::pexecute($del_stmt, [ 'type' =&gt; $type ]); // insert new task database::pexecute($ins_stmt, [ 'type' =&gt; $type, 'data' =&gt; '' ]); } elseif ($type == taskid::create_home &amp;&amp; count($params) == 4 &amp;&amp; $params[0] != '' &amp;&amp; $params[1] != '' &amp;&amp; $params[2] != '' &amp;&amp; ($params[3] == 0 || $params[3] == 1)) { $data = []; $data['loginname'] = $params[0]; $data['uid'] = $params[1]; $data['gid'] = $params[2]; $data['store_defaultindex'] = $params[3]; $data = json_encode($data); database::pexecute($ins_stmt, [ 'type' =&gt; taskid::create_home, 'data' =&gt; $data ]); } elseif ($type == taskid::delete_customer_files &amp;&amp; isset($params[0]) &amp;&amp; $params[0] != '') { $data = []; $data['loginname'] = $params[0]; $data = json_encode($data); database::pexecute($ins_stmt, [ 'type' =&gt; taskid::delete_customer_files, 'data' =&gt; $data ]); } elseif ($type == taskid::delete_email_data &amp;&amp; count($params) == 2 &amp;&amp; $params[0] != '' &amp;&amp; $params[1] != '') { $data = []; $data['loginname'] = $params[0]; $data['emailpath'] = $params[1]; $data = json_encode($data); database::pexecute($ins_stmt, [ 'type' =&gt; taskid::delete_email_data, 'data' =&gt; $data ]); } elseif ($type == taskid::delete_ftp_data &amp;&amp; count($params) == 2 &amp;&amp; $params[0] != '' &amp;&amp; $params[1] != '') { $data = []; $data['loginname'] = $params[0]; $data['homedir'] = $params[1]; $data = json_encode($data); database::pexecute($ins_stmt, [ 'type' =&gt; taskid::delete_ftp_data, 'data' =&gt; $data ]); } elseif ($type == taskid::delete_domain_pdns &amp;&amp; isset($params[0]) &amp;&amp; $params[0] != '' &amp;&amp; settings::get('system.bind_enable') == '1' &amp;&amp; settings::get('system.dns_server') == 'powerdns') { // -&gt; bind disabled dns-server powerdns -&gt; task $data = []; $data['domain'] = $params[0]; $data = json_encode($data); database::pexecute($ins_stmt, [ 'type' =&gt; taskid::delete_domain_pdns, 'data' =&gt; $data ]); } elseif ($type == taskid::delete_domain_ssl &amp;&amp; isset($params[0]) &amp;&amp; $params[0] != '') { $data = []; $data['domain'] = $params[0]; $data = json_encode($data); database::pexecute($ins_stmt, [ 'type' =&gt; taskid::delete_domain_ssl, 'data' =&gt; $data ]); } elseif ($type == taskid::create_customer_datadump &amp;&amp; isset($params[0]) &amp;&amp; is_array($params[0])) { $data = json_encode($params[0]); database::pexecute($ins_stmt, [ 'type' =&gt; taskid::create_customer_datadump, 'data' =&gt; $data ]); } } /** * returns array cronjobs last executed * * @return array */ public static function getcronjobslastrun(): array { $query = "select `lastrun`, `desc_lng_key` `" . table_panel_cronruns . "` `isactive` = '1' order `cronfile` asc"; $result = database::query($query); $cronjobs_last_run = []; ($row = $result-&gt;fetch(pdo::fetch_assoc)) { $cronjobs_last_run[] = [ 'title' =&gt; lng('crondesc.' . $row['desc_lng_key']), 'lastrun' =&gt; $row['lastrun'] ]; } return $cronjobs_last_run; } /** * @param string $module * @param int $isactive * @return void * @throws exception */ public static function togglecronstatus(string $module, int $isactive = 0) { ($isactive != 1) { $isactive = 0; } $upd_stmt = database::prepare(" update `" . table_panel_cronruns . "` set `isactive` = :active `module` = :module "); database::pexecute($upd_stmt, [ 'active' =&gt; $isactive, 'module' =&gt; $module ]); } /** * returns array tasks queued run cronjob * * @return array */ public static function getoutstandingtasks(): array { $query = "select * `" . table_panel_tasks . "` order `type` asc"; $result = database::query($query); $tasks = []; ($row = $result-&gt;fetch(pdo::fetch_assoc)) { ($row['data'] != '') { $row['data'] = json_decode($row['data'], true); } $task_id = $row['type']; (taskid::isvalid($task_id)) { $task_constname = taskid::converttoconstant($task_id); $lngparams = []; (is_array($row['data'])) { // task includes loginname (isset($row['data']['loginname'])) { $lngparams = [$row['data']['loginname']]; } // task includes domain data (isset($row['data']['domain'])) { $lngparams = [$row['data']['domain']]; } } $task = [ 'desc' =&gt; lng('tasks.' . $task_constname, $lngparams) ]; } else { // unknown $task = ['desc' =&gt; "error: unknown task type '" . $row['type'] . "'"]; } $tasks[] = $task; } (empty($tasks)) { $tasks = [['desc' =&gt; lng('tasks.noneoutstanding')]]; } return $tasks; } /** * send notification system admin via email * * @param string $message * @param string $subject * * @return void */ public static function notifymailtoadmin(string $message, string $subject = "[froxlor] important notice") { $mail = new mailer(true); $mailerror = false; $mailerr_msg = ""; try { $mail-&gt;subject = $subject; $mail-&gt;altbody = $message; $mail-&gt;msghtml(nl2br($message)); $mail-&gt;addaddress(settings::get('panel.adminmail'), settings::get('panel.adminmail_defname')); $mail-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $mailerror = true; } $mail-&gt;clearaddresses(); ($mailerror) { echo 'error sending mail: ' . $mailerr_msg . "\n"; } } /** * @param string $cronname * @return void * @throws exception */ public static function updatelastrunofcron(string $cronname) { $upd_stmt = database::prepare(" update `" . table_panel_cronruns . "` set `lastrun` = unix_timestamp() `cronfile` = :cron; "); database::pexecute($upd_stmt, [ 'cron' =&gt; $cronname ]); } }</file><file name="lib/Froxlor/System/MysqlHandler.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\system; use froxlor\database\database; use monolog\handler\abstractprocessinghandler; use monolog\logger; class mysqlhandler extends abstractprocessinghandler { protected static array $froxlorlevels = [ logger::debug =&gt; log_debug, logger::info =&gt; log_info, logger::notice =&gt; log_notice, logger::warning =&gt; log_warning, logger::error =&gt; log_err, logger::critical =&gt; log_err, logger::alert =&gt; log_err, logger::emergency =&gt; log_err ]; protected $pdostatement = null; /** * constructor * * @param bool|int $level debug level handler store * @param bool $bubble */ public function __construct($level = logger::debug, bool $bubble = true) { parent::__construct($level, $bubble); } /** * writes record log * * @param array $record * @return void */ protected function write(array $record) { $this-&gt;insert([ ':message' =&gt; $record['message'], ':contextuser' =&gt; ($record['context']['user'] ?? 'unknown'), ':contextaction' =&gt; ($record['context']['action'] ?? '0'), ':level' =&gt; self::$froxlorlevels[$record['level']], ':datetime' =&gt; $record['datetime']-&gt;format('u') ]); } /** * insert data logger table * * @param array $data * @return bool */ protected function insert(array $data): bool { ($this-&gt;pdostatement === null) { $sql = "insert `panel_syslog` set `text` = :message, `user` = :contextuser, `action` = :contextaction, `type` = :level, `date` = :datetime"; $this-&gt;pdostatement = database::prepare($sql); } return $this-&gt;pdostatement-&gt;execute($data); } }</file><file name="lib/Froxlor/System/Mailer.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\system; use froxlor\settings; use phpmailer\phpmailer\exception; use phpmailer\phpmailer\phpmailer; class mailer extends phpmailer { /** * class constructor * * @param bool $exceptions whether throw exceptions * * @throws exception */ public function __construct(bool $exceptions = false) { parent::__construct($exceptions); $this-&gt;charset = "utf-8"; (settings::get('system.mail_use_smtp')) { $this-&gt;issmtp(); $this-&gt;host = settings::get('system.mail_smtp_host'); $this-&gt;smtpauth = settings::get('system.mail_smtp_auth') == '1'; $this-&gt;username = settings::get('system.mail_smtp_user'); $this-&gt;password = settings::get('system.mail_smtp_passwd'); (settings::get('system.mail_smtp_usetls')) { $this-&gt;smtpsecure = 'tls'; } else { $this-&gt;smtpautotls = false; } $this-&gt;port = settings::get('system.mail_smtp_port'); } /** * use froxlor's email-validation */ self::$validator = [ '\froxlor\\validate\\validate', 'validateemail' ]; (self::validateaddress(settings::get('panel.adminmail')) !== false) { // set return-to address custom sender-name, see #76 $this-&gt;setfrom(settings::get('panel.adminmail'), settings::get('panel.adminmail_defname')); (settings::get('panel.adminmail_return') != '') { $this-&gt;addreplyto(settings::get('panel.adminmail_return'), settings::get('panel.adminmail_defname')); } } } }</file><file name="lib/Froxlor/System/IPTools.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\system; class iptools { /** * converts cidr netmask address * * @thx https://stackoverflow.com/a/5711080/3020926 * @param string $cidr * * @return string */ public static function cidr2netmaskaddr(string $cidr): string { $ta = substr($cidr, strpos($cidr, '/') + 1) * 1; $netmask = str_split(str_pad(str_pad('', $ta, '1'), 32, '0'), 8); foreach ($netmask &amp;$element) { $element = bindec($element); } return implode('.', $netmask); } /** * checks whether given $ip range given ip/cidr range * * @param array $ip_cidr 0 =&gt; ip, 1 =&gt; netmask decimal, e.g. [0 =&gt; '123.123.123.123', 1 =&gt; 24] * @param string $ip ip-address check * * @return bool */ public static function ip_in_range(array $ip_cidr, string $ip): bool { $netip = $ip_cidr[0]; (self::is_ipv6($netip)) { return self::ipv6_in_range($ip_cidr, $ip); } $netmask = $ip_cidr[1]; $range_decimal = ip2long($netip); $ip_decimal = ip2long($ip); $wildcard_decimal = pow(2, (32 - $netmask)) - 1; $netmask_decimal = ~$wildcard_decimal; return (($ip_decimal &amp; $netmask_decimal) == ($range_decimal &amp; $netmask_decimal)); } /** * checks $address (ip) ipv6 * * @param string $address * * @return string|bool ip address success, false failure */ public static function is_ipv6(string $address) { return filter_var($address, filter_validate_ip, filter_flag_ipv6); } /** * checks whether given ipv6 $ip range given ip/cidr range * * @param array $ip_cidr 0 =&gt; ip, 1 =&gt; netmask decimal, e.g. [0 =&gt; '123:123::1', 1 =&gt; 64] * @param string $ip ip-address check * * @return bool */ private static function ipv6_in_range(array $ip_cidr, string $ip): bool { $in_range = false; $size = 128 - $ip_cidr[1]; ($size == 0) { return inet_ntop(inet_pton($ip_cidr[0])) == inet_ntop(inet_pton($ip)); } $addr = gmp_init('0x' . str_replace(':', '', self::inet6_expand($ip_cidr[0]))); $mask = gmp_init('0x' . str_replace(':', '', self::inet6_expand(self::inet6_prefix_to_mask($ip_cidr[1])))); $prefix = gmp_and($addr, $mask); $start = gmp_strval(gmp_add($prefix, '0x1'), 16); $end = '0b'; ($i = 0; $i &lt; $size; $i++) { $end .= '1'; } $end = gmp_strval(gmp_add($prefix, gmp_init($end)), 16); $start_result = ''; ($i = 0; $i &lt; 8; $i++) { $start_result .= substr($start, $i * 4, 4); ($i != 7) { $start_result .= ':'; } } $end_result = ''; ($i = 0; $i &lt; 8; $i++) { $end_result .= substr($end, $i * 4, 4); ($i != 7) { $end_result .= ':'; } } $first = self::ip2long6($start_result); $last = self::ip2long6($end_result); $ip = self::ip2long6($ip); $in_range = ($ip &gt;= $first &amp;&amp; $ip &lt;= $last); return $in_range; } /** * @param string $addr * @return false|string */ private static function inet6_expand(string $addr) { // check segments missing, insert necessary (strpos($addr, '::') !== false) { $part = explode('::', $addr); $part[0] = explode(':', $part[0]); $part[1] = explode(':', $part[1]); $missing = []; ($i = 0; $i &lt; (8 - (count($part[0]) + count($part[1]))); $i++) { $missing[] = '0000'; } $missing = array_merge($part[0], $missing); $part = array_merge($missing, $part[1]); } else { $part = explode(":", $addr); } // pad segment 4 digits foreach ($part &amp;$p) { (strlen($p) &lt; 4) { $p = '0' . $p; } } unset($p); // join segments $result = implode(':', $part); // quick check make sure length expected (strlen($result) == 39) { return $result; } else { return false; } } /** * @param int $prefix * @return false|string */ private static function inet6_prefix_to_mask(int $prefix) { /* make sure prefix number 1 127 (inclusive) */ ($prefix &lt; 0 || $prefix &gt; 128) { return false; } $mask = '0b'; $mask .= str_repeat('1', $prefix); ($i = strlen($mask) - 2; $i &lt; 128; $i++) { $mask .= '0'; } $mask = gmp_strval(gmp_init($mask), 16); $result = ''; ($i = 0; $i &lt; 8; $i++) { $result .= substr($mask, $i * 4, 4); ($i != 7) { $result .= ':'; } } // return inet_ntop(inet_pton($result)); } /** * @param string $ip * @return string */ private static function ip2long6(string $ip): string { $ip_n = inet_pton($ip); $bits = 15; // 16 x 8 bit = 128bit $ipv6long = ''; ($bits &gt;= 0) { $bin = sprintf("%08b", (ord($ip_n[$bits]))); $ipv6long = $bin . $ipv6long; $bits--; } return gmp_strval(gmp_init($ipv6long, 2), 10); } }</file><file name="lib/Froxlor/System/index.html" /><file name="lib/Froxlor/Cron/FroxlorCron.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron; abstract class froxlorcron { protected static $cronlog = null; protected static $lockfile = null; abstract public static function run(); public static function getlockfile() { return static::$lockfile; } public static function setlockfile($lockfile = null) { static::$lockfile = $lockfile; } public static function setcronlog($cronlog = null) { static::$cronlog = $cronlog; } }</file><file name="lib/Froxlor/Cron/CronConfig.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlor; use froxlor\settings; use pdo; class cronconfig { /** * 1st: check task generation * 2nd: task found, generate cron.d-file * 3rd: maybe restart cron? */ public static function checkcrondconfigurationfile() { // check task database::query(" select * `" . table_panel_tasks . "` `type` = '99' "); $num_results = database::num_rows(); // task re-generating cron.d-file? ($num_results &gt; 0) { // get crons intervals (filedir::isfreebsd()) { // freebsd need header writing directly crontab $cronfile = "\n"; } else { $cronfile = "# automatically generated cron-configuration froxlor\n"; $cronfile .= "# manually edit file re-generated periodically.\n"; $cronfile .= "path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin\n#\n"; } // get crons $result_stmt = database::query(" select * `" . table_panel_cronruns . "` `isactive` = '1' "); $binpath = settings::get("system.croncmdline"); // fallback important ($binpath === null) { $binpath = "/usr/bin/nice -n 5 /usr/bin/php -q"; } $hour_delay = 0; $day_delay = 5; $month_delay = 7; ($row_cronentry = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { // create cron.d-entry $matches = []; (preg_match("/(\d+) (minute|hour|day|week|month)/", $row_cronentry['interval'], $matches)) { ($matches[1] == 1) { $minvalue = "*"; } else { $minvalue = "*/" . $matches[1]; } switch ($matches[2]) { case "minute": $cronfile .= $minvalue . " * * * * "; break; case "hour": $cronfile .= $hour_delay . " " . $minvalue . " * * * "; $hour_delay += 3; break; case "day": ($row_cronentry['cronfile'] == 'traffic') { // traffic exactly 0:00 o'clock $cronfile .= "0 0 " . $minvalue . " * * "; } else { $cronfile .= $day_delay . " 0 " . $minvalue . " * * "; $day_delay += 5; } break; case "month": $cronfile .= $month_delay . " 0 1 " . $minvalue . " * "; $month_delay += 7; break; case "week": $cronfile .= $day_delay . " 0 " . ($matches[1] * 7) . " * * "; $day_delay += 5; break; } // create entry-line $cronfile .= "root " . $binpath . " " . filedir::makecorrectfile(froxlor::getinstalldir() . "/bin/froxlor-cli") . " froxlor:cron " . escapeshellarg($row_cronentry['cronfile']) . " -q 1&gt; /dev/null\n"; } } // php sessionclean enabled ((int)settings::get('phpfpm.enabled') == 1) { $cronfile .= "# look purge old sessions every 30 minutes" . php_eol; $cronfile .= "09,39 * * * * root " . $binpath . " " . filedir::makecorrectfile(froxlor::getinstalldir() . "/bin/froxlor-cli") . " froxlor:php-sessionclean 1&gt; /dev/null" . php_eol; } (filedir::isfreebsd()) { // freebsd handles cron-stuff another way. need directly // write crontab file cron.d/froxlor file // (settings system.cronconfig set correctly course) $crontab = file_get_contents(settings::get("system.cronconfig")); ($crontab === false) { die("oh snap, cannot read crontab file. happen.\nplease check path permissions, cron keep trying stop cron-service.\n\n"); } // parse / replace entries $crontablines = explode("\n", $crontab); $newcrontab = ""; foreach ($crontablines $ctl) { $ctl = trim($ctl); (!empty($ctl) &amp;&amp; !preg_match("/(.*)froxlor\:cron(.*)/", $ctl)) { $newcrontab .= $ctl . "\n"; } } // re-assemble old-content + new froxlor-content $newcrontab .= $cronfile; // continue writing file $cronfile = $newcrontab; } // write file (file_put_contents(settings::get("system.cronconfig"), $cronfile) === false) { // oh snap cannot create new crond-file die("oh snap, cannot create cron-file. happen.\nplease check path permissions, cron keep trying stop cron-service.\n\n"); } // correct permissions chmod(settings::get("system.cronconfig"), 0640); // remove re-generation tasks database::query("delete `" . table_panel_tasks . "` `type` = '99'"); // run reload command filedir::safe_exec(escapeshellcmd(settings::get('system.crondreload'))); } return true; } }</file><file name="lib/Froxlor/Cron/TaskId.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron; use reflectionclass; final class taskid { /** * type=1 means rebuild apache vhosts.conf */ const rebuild_vhost = 1; /** * type=2 means create new home chown */ const create_home = 2; /** * type=4 means something dns config changed. * rebuild froxlor_bind.conf bind enabled, update dkim keys */ const rebuild_dns = 4; /** * type=5 means new ftp-account created, create directory */ const create_ftp = 5; /** * type=6 means customer deleted remove files */ const delete_customer_files = 6; /** * type=7 customer deleted email account wants data deleted filesystem */ const delete_email_data = 7; /** * type=8 customer deleted ftp account wants homedir deleted filesystem * refs #293 */ const delete_ftp_data = 8; /** * type=9 means something antispam related changed. * rebuild froxlor_settings.conf antispam enabled */ const rebuild_rspamd = 9; /** * type=10 set filesystem - quota */ const create_quota = 10; /** * type=11 domain deleted, remove pdns database used */ const delete_domain_pdns = 11; /** * type=12 domain deleted, remove acme.sh/let's encrypt directory used */ const delete_domain_ssl = 12; /** * type=13 set configuration selected services regarding use let's encrypt certificate */ const update_le_services = 13; /** * type=20 custumer data dump */ const create_customer_datadump = 20; /** * type=99 regenerate cron */ const rebuild_cron = 99; /** * return cron task id valid * * @param int|string $id cron task id (legacy string support) * @return boolean */ public static function isvalid($id) { static $reflcontants; (!is_numeric($id)) { return false; } $numericid = (int)$id; (!is_array($reflcontants)) { $reflclass = new reflectionclass(get_called_class()); $reflcontants = $reflclass-&gt;getconstants(); } return in_array($numericid, $reflcontants, true); } /** * get constant name id * * @param int|string $id cron task id (legacy string support) * @return string|false constant name false found */ public static function converttoconstant($id) { static $reflcontants; (!is_numeric($id)) { return false; } $numericid = (int)$id; (!is_array($reflcontants)) { $reflclass = new reflectionclass(get_called_class()); $reflcontants = $reflclass-&gt;getconstants(); } return array_search($numericid, $reflcontants, true); } }</file><file name="lib/Froxlor/Cron/index.html" /><file name="lib/Froxlor/Cron/Forkable.php">&lt;?php namespace froxlor\cron; use froxlor\database\database; use froxlor\froxlorlogger; trait forkable { public static function runfork($closure, array $attributes = [], int $concurrentchildren = 3) { $childrenpids = []; // fork pcntl_fork available nofork flag set (function_exists('pcntl_fork') &amp;&amp; !defined('cron_nofork_flag')) { foreach ($attributes $closureattributes) { // close database - connection fork, share resources child database::needroot(false); // forces connection set null $pid = pcntl_fork(); ($pid == -1) { exit("error forking...\n"); } elseif ($pid == 0) { // re-create db database::needroot(false); $closure($closureattributes); exit(); } else { $childrenpids[] = $pid; (count($childrenpids) &gt;= $concurrentchildren) { foreach ($childrenpids $key =&gt; $pid) { $res = pcntl_waitpid($pid, $status, wnohang); // process already exited ($res == -1 || $res &gt; 0) { unset($childrenpids[$key]); } } sleep(1); } } } (pcntl_waitpid(0, $status) != -1); } else { (!defined('cron_nofork_flag')) { (extension_loaded('pcntl')) { $msg = "php compiled pcntl pcntl_fork function available."; } else { $msg = "php compiled without pcntl."; } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_warning, $msg . " forking " . self::class . ", may take long time!"); } foreach ($attributes $closureattributes) { $closure($closureattributes); } } } }</file><file name="lib/Froxlor/Cron/Traffic/index.html" /><file name="lib/Froxlor/Cron/Traffic/TrafficCron.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\traffic; /** * @author florian lippert &lt;flo@syscp.org&gt; (2003-2009) * @author froxlor team &lt;team@froxlor.org&gt; (2010-) */ use froxlor\cron\forkable; use froxlor\cron\froxlorcron; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\http\statistics; use froxlor\maillogparser; use froxlor\settings; use pdo; class trafficcron extends froxlorcron { use forkable; public static function run() { self::runfork([self::class, 'handle'], [true]); } public static function handle() { /** * traffic diskusage measure */ froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'traffic run started...'); $admin_traffic = []; $domainlist = []; $speciallogfile_domainlist = []; $result_domainlist_stmt = database::query(" select `id`, `domain`, `customerid`, `parentdomainid`, `speciallogfile` `" . table_panel_domains . "` `aliasdomain` null `email_only` &lt;&gt; '1'; "); ($row_domainlist = $result_domainlist_stmt-&gt;fetch(pdo::fetch_assoc)) { (!isset($domainlist[$row_domainlist['customerid']])) { $domainlist[$row_domainlist['customerid']] = []; } $domainlist[$row_domainlist['customerid']][$row_domainlist['id']] = $row_domainlist['domain']; ($row_domainlist['parentdomainid'] == '0' &amp;&amp; $row_domainlist['speciallogfile'] == '1') { (!isset($speciallogfile_domainlist[$row_domainlist['customerid']])) { $speciallogfile_domainlist[$row_domainlist['customerid']] = []; } $speciallogfile_domainlist[$row_domainlist['customerid']][$row_domainlist['id']] = $row_domainlist['domain']; } } $mysqlusage_all = []; $databases_stmt = database::query("select * " . table_panel_databases . " order `dbserver`"); $last_dbserver = 0; $databases_list = []; database::needroot(true); $databases_list_result_stmt = database::query("show databases"); ($databases_list_row = $databases_list_result_stmt-&gt;fetch(pdo::fetch_assoc)) { $databases_list[] = strtolower($databases_list_row['database']); } ($row_database = $databases_stmt-&gt;fetch(pdo::fetch_assoc)) { ($last_dbserver != $row_database['dbserver']) { database::needroot(true, $row_database['dbserver'], true); $last_dbserver = $row_database['dbserver']; $databases_list = []; $databases_list_result_stmt = database::query("show databases"); ($databases_list_row = $databases_list_result_stmt-&gt;fetch(pdo::fetch_assoc)) { $databases_list[] = strtolower($databases_list_row['database']); } } (in_array(strtolower($row_database['databasename']), $databases_list)) { // sum data_length index_length $mysql_usage_result_stmt = database::prepare(" select sum(data_length + index_length) customerusage information_schema.tables table_schema = :database group table_schema; "); // get result $mysql_usage_row = database::pexecute_first($mysql_usage_result_stmt, [ 'database' =&gt; $row_database['databasename'] ]); // initialize counter customer (!isset($mysqlusage_all[$row_database['customerid']])) { $mysqlusage_all[$row_database['customerid']] = 0; } // sum result ($mysql_usage_row) { $mysqlusage_all[$row_database['customerid']] += floatval($mysql_usage_row['customerusage']); } else { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, "cannot get usage database " . $row_database['databasename'] . "."); } } else { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_warning, "seems like database " . $row_database['databasename'] . " removed manually."); } } database::needroot(false); // using file-system quota, speed diskusage - collection (settings::get('system.diskquota_enabled')) { $usedquota = filedir::getfilesystemquota(); } /** * mail-traffic */ (settings::get("system.mailtraffic_enabled")) { $mailtrafficcalc = new maillogparser(settings::get("system.last_traffic_run")); } $result_stmt = database::query("select * `" . table_panel_customers . "` order `customerid` asc"); $currentdate = date("y-m-d"); $current_stamp = time(); $current_year = date('y', $current_stamp); $current_month = date('m', $current_stamp); // @todo locale? $current_month_short = date('m', $current_stamp); $current_day = date('d', $current_stamp); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { /** * http-traffic */ froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'http traffic ' . $row['loginname'] . ' started...'); $httptraffic = 0; (isset($domainlist[$row['customerid']]) &amp;&amp; is_array($domainlist[$row['customerid']]) &amp;&amp; count($domainlist[$row['customerid']]) != 0) { // examining caption use default webalizer stats... ($row['standardsubdomain'] != '0' &amp;&amp; isset($domainlist[$row['customerid']][$row['standardsubdomain']])) { // ... course we'd prefer use standardsubdomain ... $caption = $domainlist[$row['customerid']][$row['standardsubdomain']]; } else { // ... standardsubdomain, use loginname ... $caption = $row['loginname']; // ... results non-usable links files stats, let's look find domain speciallogfiledomain foreach ($domainlist[$row['customerid']] $domainid =&gt; $domain) { (!isset($speciallogfile_domainlist[$row['customerid']]) || !isset($speciallogfile_domainlist[$row['customerid']][$domainid])) { $caption = $domain; break; } } } $httptraffic = 0; reset($domainlist[$row['customerid']]); $statstool = settings::get('system.traffictool'); (isset($speciallogfile_domainlist[$row['customerid']]) &amp;&amp; is_array($speciallogfile_domainlist[$row['customerid']]) &amp;&amp; count($speciallogfile_domainlist[$row['customerid']]) != 0) { reset($speciallogfile_domainlist[$row['customerid']]); ($statstool != 'awstats') { foreach ($speciallogfile_domainlist[$row['customerid']] $domainid =&gt; $domain) { ($statstool == 'goaccess') { $httptraffic += floatval(self::callgoaccessgettraffic($row['customerid'], $row['loginname'] . '-' . $domain, $row['documentroot'] . '/goaccess/' . $domain . '/', $domain, ['month' =&gt; $current_month_short, 'year' =&gt; $current_year], $current_stamp)); } else { $httptraffic += floatval(self::callwebalizergettraffic($row['loginname'] . '-' . $domain, $row['documentroot'] . '/webalizer/' . $domain . '/', $domain, $domainlist[$row['customerid']])); } // kind keep-alive-call unsets link leads new connection database database::needroot(); } } } reset($domainlist[$row['customerid']]); // callawstatsgettraffic called // *not* also special-logfiles-loop, function // iterate customer-domains awstats-configs // know logfile-name, #246 ($statstool == 'awstats') { $httptraffic += floatval(self::callawstatsgettraffic($row['customerid'], $row['documentroot'] . '/awstats/', $domainlist[$row['customerid']], $current_stamp)); } elseif ($statstool == 'goaccess') { $httptraffic += floatval(self::callgoaccessgettraffic($row['customerid'], $row['loginname'], $row['documentroot'] . '/goaccess/', $caption, ['month' =&gt; $current_month_short, 'year' =&gt; $current_year], $current_stamp)); } else { $httptraffic += floatval(self::callwebalizergettraffic($row['loginname'], $row['documentroot'] . '/webalizer/', $caption, $domainlist[$row['customerid']])); } // kind keep-alive-call unsets link leads new connection database database::needroot(); // make stuff readable customer, #258 statistics::makechownwithnewstats($row); } /** * ftp-traffic */ froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'ftp traffic ' . $row['loginname'] . ' started...'); $ftptraffic_stmt = database::prepare(" select sum(`up_bytes`) `up_bytes_sum`, sum(`down_bytes`) `down_bytes_sum` `" . table_ftp_users . "` `customerid` = :customerid "); $ftptraffic = database::pexecute_first($ftptraffic_stmt, [ 'customerid' =&gt; $row['customerid'] ]); (!is_array($ftptraffic)) { $ftptraffic = [ 'up_bytes_sum' =&gt; 0, 'down_bytes_sum' =&gt; 0 ]; } $upd_stmt = database::prepare(" update `" . table_ftp_users . "` set `up_bytes` = '0', `down_bytes` = '0' `customerid` = :customerid "); database::pexecute($upd_stmt, [ 'customerid' =&gt; $row['customerid'] ]); /** * mail-traffic */ $mailtraffic = 0; (settings::get("system.mailtraffic_enabled")) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'mail traffic usage ' . $row['loginname'] . " started..."); $domains_stmt = database::prepare("select domain `" . table_panel_domains . "` `customerid` = :cid"); database::pexecute($domains_stmt, [ "cid" =&gt; $row['customerid'] ]); ($domainrow = $domains_stmt-&gt;fetch(pdo::fetch_assoc)) { $domainmailtraffic = $mailtrafficcalc-&gt;getdomaintraffic($domainrow["domain"]); (!is_array($domainmailtraffic)) { continue; } foreach ($domainmailtraffic $datetraffic =&gt; $daytraffic) { $daytraffic = floatval($daytraffic / 1024); [$year, $month, $day] = explode("-", $datetraffic); ($datetraffic == $currentdate) { $mailtraffic = $daytraffic; } else { // check entry given day exists $stmt = database::prepare("select * `" . table_panel_traffic . "` `customerid` = :cid `year` = :year `month` = :month `day` = :day "); $params = [ "cid" =&gt; $row['customerid'], "year" =&gt; $year, "month" =&gt; $month, "day" =&gt; $day ]; database::pexecute($stmt, $params); ($stmt-&gt;rowcount() &gt; 0) { $updrow = $stmt-&gt;fetch(pdo::fetch_assoc); $upd_stmt = database::prepare("update `" . table_panel_traffic . "` set `mail` = :mail `id` = :id "); database::pexecute($upd_stmt, [ "mail" =&gt; $updrow['mail'] + $daytraffic, "id" =&gt; $updrow['id'] ]); } } } } } /** * total traffic */ froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'total traffic ' . $row['loginname'] . ' started'); $current_traffic = []; $current_traffic['http'] = floatval($httptraffic); $current_traffic['ftp_up'] = floatval(($ftptraffic['up_bytes_sum'] / 1024)); $current_traffic['ftp_down'] = floatval(($ftptraffic['down_bytes_sum'] / 1024)); $current_traffic['mail'] = floatval($mailtraffic); $current_traffic['all'] = $current_traffic['http'] + $current_traffic['ftp_up'] + $current_traffic['ftp_down'] + $current_traffic['mail']; $ins_data = [ 'customerid' =&gt; $row['customerid'], 'year' =&gt; $current_year, 'month' =&gt; $current_month, 'day' =&gt; $current_day, 'stamp' =&gt; $current_stamp, 'http' =&gt; $current_traffic['http'], 'ftp_up' =&gt; $current_traffic['ftp_up'], 'ftp_down' =&gt; $current_traffic['ftp_down'], 'mail' =&gt; $current_traffic['mail'] ]; $ins_stmt = database::prepare(" insert `" . table_panel_traffic . "` set `customerid` = :customerid, `year` = :year, `month` = :month, `day` = :day, `stamp` = :stamp, `http` = :http, `ftp_up` = :ftp_up, `ftp_down` = :ftp_down, `mail` = :mail "); database::pexecute($ins_stmt, $ins_data); $sum_month_traffic_stmt = database::prepare(" select sum(`http`) `http`, sum(`ftp_up`) `ftp_up`, sum(`ftp_down`) `ftp_down`, sum(`mail`) `mail` `" . table_panel_traffic . "` `year` = :year `month` = :month `customerid` = :customerid "); $sum_month_traffic = database::pexecute_first($sum_month_traffic_stmt, [ 'year' =&gt; $current_year, 'month' =&gt; $current_month, 'customerid' =&gt; $row['customerid'] ]); $sum_month_traffic['all'] = $sum_month_traffic['http'] + $sum_month_traffic['ftp_up'] + $sum_month_traffic['ftp_down'] + $sum_month_traffic['mail']; (!isset($admin_traffic[$row['adminid']]) || !is_array($admin_traffic[$row['adminid']])) { $admin_traffic[$row['adminid']]['http'] = 0; $admin_traffic[$row['adminid']]['ftp_up'] = 0; $admin_traffic[$row['adminid']]['ftp_down'] = 0; $admin_traffic[$row['adminid']]['mail'] = 0; $admin_traffic[$row['adminid']]['all'] = 0; $admin_traffic[$row['adminid']]['sum_month'] = 0; } $admin_traffic[$row['adminid']]['http'] += $current_traffic['http']; $admin_traffic[$row['adminid']]['ftp_up'] += $current_traffic['ftp_up']; $admin_traffic[$row['adminid']]['ftp_down'] += $current_traffic['ftp_down']; $admin_traffic[$row['adminid']]['mail'] += $current_traffic['mail']; $admin_traffic[$row['adminid']]['all'] += $current_traffic['all']; $admin_traffic[$row['adminid']]['sum_month'] += $sum_month_traffic['all']; /** * webspace-usage */ froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'calculating webspace usage ' . $row['loginname']); $webspaceusage = 0; // using repquota, faster using tool using du traversing complete directory (settings::get('system.diskquota_enabled') &amp;&amp; isset($usedquota[$row['guid']]['block']['used']) &amp;&amp; $usedquota[$row['guid']]['block']['used'] &gt;= 1) { // may use array created earlier, used diskspace stored [&lt;guid&gt;][block][used] $webspaceusage = floatval($usedquota[$row['guid']]['block']['used']); } else { // use old fashioned way "du" (file_exists($row['documentroot']) &amp;&amp; is_dir($row['documentroot'])) { $back = filedir::safe_exec('du -sk ' . escapeshellarg($row['documentroot'])); foreach ($back $backrow) { $webspaceusage = explode(' ', $backrow); } $webspaceusage = floatval($webspaceusage['0']); unset($back); } else { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_warning, 'documentroot ' . $row['documentroot'] . ' exist'); } } /** * mailspace-usage */ froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'calculating mailspace usage ' . $row['loginname']); $emailusage = 0; $maildir = filedir::makecorrectdir(settings::get('system.vmail_homedir') . $row['loginname']); (file_exists($maildir) &amp;&amp; is_dir($maildir)) { $back = filedir::safe_exec('du -sk ' . escapeshellarg($maildir)); foreach ($back $backrow) { $emailusage = explode(' ', $backrow); } $emailusage = floatval($emailusage['0']); unset($back); } else { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_warning, 'maildir ' . $maildir . ' exist'); } /** * mysqlspace-usage */ froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'calculating mysqlspace usage ' . $row['loginname']); $mysqlusage = 0; (isset($mysqlusage_all[$row['customerid']])) { $mysqlusage = floatval($mysqlusage_all[$row['customerid']] / 1024); } $current_diskspace = []; $current_diskspace['webspace'] = floatval($webspaceusage); $current_diskspace['mail'] = floatval($emailusage); $current_diskspace['mysql'] = floatval($mysqlusage); $current_diskspace['all'] = $current_diskspace['webspace'] + $current_diskspace['mail'] + $current_diskspace['mysql']; $ins_data = [ 'customerid' =&gt; $row['customerid'], 'year' =&gt; $current_year, 'month' =&gt; $current_month, 'day' =&gt; $current_day, 'stamp' =&gt; $current_stamp, 'webspace' =&gt; $current_diskspace['webspace'], 'mail' =&gt; $current_diskspace['mail'], 'mysql' =&gt; $current_diskspace['mysql'] ]; $ins_stmt = database::prepare(" insert `" . table_panel_diskspace . "` set `customerid` = :customerid, `year` = :year, `month` = :month, `day` = :day, `stamp` = :stamp, `webspace` = :webspace, `mail` = :mail, `mysql` = :mysql "); database::pexecute($ins_stmt, $ins_data); (!isset($admin_diskspace[$row['adminid']]) || !is_array($admin_diskspace[$row['adminid']])) { $admin_diskspace[$row['adminid']] = []; $admin_diskspace[$row['adminid']]['webspace'] = 0; $admin_diskspace[$row['adminid']]['mail'] = 0; $admin_diskspace[$row['adminid']]['mysql'] = 0; $admin_diskspace[$row['adminid']]['all'] = 0; } $admin_diskspace[$row['adminid']]['webspace'] += $current_diskspace['webspace']; $admin_diskspace[$row['adminid']]['mail'] += $current_diskspace['mail']; $admin_diskspace[$row['adminid']]['mysql'] += $current_diskspace['mysql']; $admin_diskspace[$row['adminid']]['all'] += $current_diskspace['all']; /** * total usage */ $diskusage = floatval($webspaceusage + $emailusage + $mysqlusage); $upd_data = [ 'diskspace' =&gt; $current_diskspace['all'], 'traffic' =&gt; $sum_month_traffic['all'], 'customerid' =&gt; $row['customerid'] ]; $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `diskspace_used` = :diskspace, `traffic_used` = :traffic `customerid` = :customerid "); database::pexecute($upd_stmt, $upd_data); /** * proftpd quota */ $upd_data = [ 'biu' =&gt; ($current_diskspace['all'] * 1024), 'loginname' =&gt; $row['loginname'], 'loginnamelike' =&gt; $row['loginname'] . settings::get('customer.ftpprefix') . "%" ]; $upd_stmt = database::prepare(" update `" . table_ftp_quotatallies . "` set `bytes_in_used` = :biu `name` = :loginname `name` like :loginnamelike "); database::pexecute($upd_stmt, $upd_data); /** * pureftpd quota */ (settings::get('system.ftpserver') == "pureftpd") { $result_quota_stmt = database::prepare(" select homedir `" . table_ftp_users . "` customerid = :customerid "); database::pexecute($result_quota_stmt, [ 'customerid' =&gt; $row['customerid'] ]); // get correct user ((settings::get('system.mod_fcgid') == 1 || settings::get('phpfpm.enabled') == 1) &amp;&amp; $row['deactivated'] == '0') { $user = $row['loginname']; $group = $row['loginname']; } else { $user = $row['guid']; $group = $row['guid']; } ($row_quota = $result_quota_stmt-&gt;fetch(pdo::fetch_assoc)) { $quotafile = "" . $row_quota['homedir'] . ".ftpquota"; $fh = fopen($quotafile, 'w'); $stringdata = "0 " . $current_diskspace['all'] * 1024 . ""; fwrite($fh, $stringdata); fclose($fh); filedir::safe_exec('chown ' . $user . ':' . $group . ' ' . escapeshellarg($quotafile) . ''); } } } /** * admin usage */ $result_stmt = database::query("select `adminid` `" . table_panel_admins . "` order `adminid` asc"); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { (isset($admin_traffic[$row['adminid']])) { $ins_data = [ 'adminid' =&gt; $row['adminid'], 'year' =&gt; $current_year, 'month' =&gt; $current_month, 'day' =&gt; $current_day, 'stamp' =&gt; $current_stamp, 'http' =&gt; $admin_traffic[$row['adminid']]['http'], 'ftp_up' =&gt; $admin_traffic[$row['adminid']]['ftp_up'], 'ftp_down' =&gt; $admin_traffic[$row['adminid']]['ftp_down'], 'mail' =&gt; $admin_traffic[$row['adminid']]['mail'] ]; $ins_stmt = database::prepare(" insert `" . table_panel_traffic_admins . "` set `adminid` = :adminid, `year` = :year, `month` = :month, `day` = :day, `stamp` = :stamp, `http` = :http, `ftp_up` = :ftp_up, `ftp_down` = :ftp_down, `mail` = :mail "); database::pexecute($ins_stmt, $ins_data); $upd_data = [ 'traffic' =&gt; $admin_traffic[$row['adminid']]['sum_month'], 'adminid' =&gt; $row['adminid'] ]; $upd_stmt = database::prepare(" update `" . table_panel_admins . "` set `traffic_used` = :traffic `adminid` = :adminid "); database::pexecute($upd_stmt, $upd_data); } (isset($admin_diskspace[$row['adminid']])) { $upd_data = [ 'diskspace' =&gt; $admin_diskspace[$row['adminid']]['all'], 'adminid' =&gt; $row['adminid'] ]; $upd_stmt = database::prepare(" update `" . table_panel_admins . "` set `diskspace_used` = :diskspace `adminid` = :adminid "); database::pexecute($upd_stmt, $upd_data); } } database::query("update `" . table_panel_settings . "` set `value` = unix_timestamp() `settinggroup` = 'system' `varname` = 'last_traffic_run'"); } /** * run goaccess create statistics return used traffic since last run * * @param int $customerid * @param string $logfile name logfile * @param string $outputdir place stats build * @param string $caption caption webalizer output * @param array $monthyear_arr * @param int $current_stamp * * @return int used traffic */ private static function callgoaccessgettraffic($customerid, $logfile, $outputdir, $caption, array $monthyear_arr = [], int $current_stamp = 0) { $returnval = 0; $logfile = filedir::makecorrectfile(settings::get('system.logfiles_directory') . $logfile . '-access.log'); (file_exists($logfile)) { $outputdir = filedir::makecorrectdir($outputdir); (!file_exists($outputdir)) { filedir::safe_exec('mkdir -p ' . escapeshellarg($outputdir)); } (file_exists($outputdir . '.tmp.json')) { @unlink($outputdir . '.tmp.json'); } // goaccess &lt;1.4 $keep_params = '--keep-db-files --load-from-disk'; $res = filedir::safe_exec('goaccess --version'); $ver_str = array_shift($res); $cgover = substr($ver_str, strrpos($ver_str, " ") + 1, -1); (version_compare($cgover, '1.4', '&gt;=')) { // least 1.4 $keep_params = '--persist --restore'; } $format = settings::get('system.logfiles_type') == '2' ? 'vcombined' : 'combined'; $monthyear = $monthyear_arr['month'] . '/' . $monthyear_arr['year']; $return_value = false; filedir::safe_exec("grep '" . $monthyear . "' " . escapeshellarg($logfile) . " | goaccess " . $keep_params . " --db-path=" . escapeshellarg($outputdir) . " -o " . escapeshellarg($outputdir . '.tmp.json') . " -o " . escapeshellarg($outputdir . 'index.html') . " --html-report-title=" . escapeshellarg($caption) . " --log-format=" . $format . " --no-parsing-spinner --no-progress - ", $return_value, ['|']); (file_exists($outputdir . '.tmp.json')) { // need jq potentially large json files $returnval = filedir::safe_exec("jq -c '.general.bandwidth' " . escapeshellarg($outputdir . '.tmp.json')); $returnval = array_shift($returnval); // return kb others two $returnval = floatval($returnval / 1024); @unlink($outputdir . '.tmp.json'); } } ($returnval &gt; 0) { /** * now, traffic saved daily, * subtract values month's values return * sane value panel_traffic remain whole stats * (awstats overwrites customers .html stats-files) */ ($customerid !== false) { $result_stmt = database::prepare(" select sum(`http`) `trafficmonth` `" . table_panel_traffic . "` `customerid` = :customerid `year` = :year `month` = :month "); $result_data = [ 'customerid' =&gt; $customerid, 'year' =&gt; date('y', $current_stamp), 'month' =&gt; date('m', $current_stamp) ]; $result = database::pexecute_first($result_stmt, $result_data); (is_array($result) &amp;&amp; isset($result['trafficmonth'])) { $returnval = ($returnval - floatval($result['trafficmonth'])); } } } return $returnval; } /** * function make webalizer statistics returns used traffic since last run * * @param string $logfile name logfile * @param string $outputdir place stats build * @param string $caption caption webalizer output * @param array $usersdomainlist * * @return float used traffic */ private static function callwebalizergettraffic($logfile, $outputdir, $caption, array $usersdomainlist = []) { $returnval = 0; $logfile = filedir::makecorrectfile(settings::get('system.logfiles_directory') . $logfile . '-access.log'); (file_exists($logfile)) { $domainargs = ''; foreach ($usersdomainlist $domain) { // hide referer $domainargs .= ' -r ' . escapeshellarg($domain); } $outputdir = filedir::makecorrectdir($outputdir); (!file_exists($outputdir)) { filedir::safe_exec('mkdir -p ' . escapeshellarg($outputdir)); } (file_exists($outputdir . 'webalizer.hist.1')) { @unlink($outputdir . 'webalizer.hist.1'); } (file_exists($outputdir . 'webalizer.hist') &amp;&amp; !file_exists($outputdir . 'webalizer.hist.1')) { filedir::safe_exec('cp ' . escapeshellarg($outputdir . 'webalizer.hist') . ' ' . escapeshellarg($outputdir . 'webalizer.hist.1')); } $verbosity = ''; (settings::get('system.webalizer_quiet') == '1') { $verbosity = '-q'; } elseif (settings::get('system.webalizer_quiet') == '2') { $verbosity = '-q'; } $we = '/usr/bin/webalizer'; // freebsd uses paths, #140 (!file_exists($we)) { $we = '/usr/local/bin/webalizer'; } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "running webalizer domain '" . $caption . "'"); filedir::safe_exec($we . ' ' . $verbosity . ' -p -o ' . escapeshellarg($outputdir) . ' -n ' . escapeshellarg($caption) . $domainargs . ' ' . escapeshellarg($logfile)); /** * format webalizer.hist-files: * month: $webalizer_hist_row['0'] * year: $webalizer_hist_row['1'] * kb: $webalizer_hist_row['5'] */ $httptraffic = []; $webalizer_hist = @file_get_contents($outputdir . 'webalizer.hist'); froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "gathering traffic information '" . $webalizer_hist . "'"); $webalizer_hist_rows = explode("\n", $webalizer_hist); foreach ($webalizer_hist_rows $webalizer_hist_row) { ($webalizer_hist_row != '') { $webalizer_hist_row = explode(' ', $webalizer_hist_row); (isset($webalizer_hist_row['0']) &amp;&amp; isset($webalizer_hist_row['1']) &amp;&amp; isset($webalizer_hist_row['5'])) { $month = intval($webalizer_hist_row['0']); $year = intval($webalizer_hist_row['1']); $traffic = floatval($webalizer_hist_row['5']); (!isset($httptraffic[$year])) { $httptraffic[$year] = []; } $httptraffic[$year][$month] = $traffic; } } } reset($httptraffic); $httptrafficlast = []; $webalizer_lasthist = @file_get_contents($outputdir . 'webalizer.hist.1'); froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "gathering traffic information '" . $webalizer_lasthist . "'"); $webalizer_lasthist_rows = explode("\n", $webalizer_lasthist); foreach ($webalizer_lasthist_rows $webalizer_lasthist_row) { ($webalizer_lasthist_row != '') { $webalizer_lasthist_row = explode(' ', $webalizer_lasthist_row); (isset($webalizer_lasthist_row['0']) &amp;&amp; isset($webalizer_lasthist_row['1']) &amp;&amp; isset($webalizer_lasthist_row['5'])) { $month = intval($webalizer_lasthist_row['0']); $year = intval($webalizer_lasthist_row['1']); $traffic = floatval($webalizer_lasthist_row['5']); (!isset($httptrafficlast[$year])) { $httptrafficlast[$year] = []; } $httptrafficlast[$year][$month] = $traffic; } } } reset($httptrafficlast); foreach ($httptraffic $year =&gt; $months) { foreach ($months $month =&gt; $traffic) { (!isset($httptrafficlast[$year][$month])) { $returnval += $traffic; } elseif ($httptrafficlast[$year][$month] &lt; $traffic) { $returnval += ($traffic - $httptrafficlast[$year][$month]); } } } } return floatval($returnval); } private static function callawstatsgettraffic($customerid, $outputdir, $usersdomainlist, $current_stamp) { $returnval = 0; foreach ($usersdomainlist $singledomain) { // check config-model awstats parse // 'real' domains subdomains aliases // model-config-file. $returnval += self::awstatsdosingledomain($singledomain, $outputdir, $current_stamp); // kind keep-alive-call unsets link leads new connection database database::needroot(); } /** * #124, awstats traffic saved bytes instead * kilobytes (like webalizer does) */ $returnval = floatval($returnval / 1024); /** * now, traffic saved daily, * subtract values month's values return * sane value panel_traffic remain whole stats * (awstats overwrites customers .html stats-files) */ ($customerid !== false) { $result_stmt = database::prepare(" select sum(`http`) `trafficmonth` `" . table_panel_traffic . "` `customerid` = :customerid `year` = :year `month` = :month "); $result_data = [ 'customerid' =&gt; $customerid, 'year' =&gt; date('y', $current_stamp), 'month' =&gt; date('m', $current_stamp) ]; $result = database::pexecute_first($result_stmt, $result_data); (is_array($result) &amp;&amp; isset($result['trafficmonth'])) { $returnval = ($returnval - floatval($result['trafficmonth'])); } } return floatval($returnval); } private static function awstatsdosingledomain($domain, $outputdir, $current_stamp) { $returnval = 0; $domainconfig = filedir::makecorrectfile(settings::get('system.awstats_conf') . '/awstats.' . $domain . '.conf'); (file_exists($domainconfig)) { $outputdir = filedir::makecorrectdir($outputdir . '/' . $domain); $staticoutputdir = filedir::makecorrectdir($outputdir . '/' . date('y') . '-' . date('m')); (!is_dir($staticoutputdir)) { filedir::safe_exec('mkdir -p ' . escapeshellarg($staticoutputdir)); } // check correct path awstats_buildstaticpages.pl $awbsp = filedir::makecorrectfile(settings::get('system.awstats_path') . '/awstats_buildstaticpages.pl'); $awprog = filedir::makecorrectfile(settings::get('system.awstats_awstatspath') . '/awstats.pl'); (!file_exists($awbsp)) { echo "wanring: necessary awstats_buildstaticpages.pl script could found, traffic calculated stats generated. please check awstats-path setting"; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_warning, "necessary awstats_buildstaticpages.pl script could found, traffic calculated stats generated. please check awstats-path setting"); exit(); } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "running awstats_buildstaticpages.pl domain '" . $domain . "' (output: '" . $staticoutputdir . "')"); filedir::safe_exec($awbsp . ' -awstatsprog=' . escapeshellarg($awprog) . ' -update -month=' . date('m', $current_stamp) . ' -year=' . date('y', $current_stamp) . ' -config=' . $domain . ' -dir=' . escapeshellarg($staticoutputdir)); // update awstats index files self::awstatsgenerateindex($domain, $outputdir); // default selection 'current', // link latest dir $new_current = filedir::makecorrectfile($outputdir . '/current'); filedir::safe_exec('ln -fts ' . escapeshellarg($staticoutputdir) . ' ' . escapeshellarg($new_current)); // statistics file looks like: 'awstats[month][year].[domain].txt' $file = filedir::makecorrectfile($outputdir . '/awstats' . date('my', time()) . '.' . $domain . '.txt'); froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "gathering traffic information '" . $file . "'"); (file_exists($file)) { $content = @file_get_contents($file); ($content !== false) { $content_array = explode("\n", $content); $count_bdw = false; foreach ($content_array $line) { // skip empty lines comments (trim($line) == '' || substr(trim($line), 0, 1) == '#') { continue; } $parts = explode(' ', $line); (isset($parts[0]) &amp;&amp; strtoupper($parts[0]) == 'begin_domain') { $count_bdw = true; } ($count_bdw) { (isset($parts[0]) &amp;&amp; strtoupper($parts[0]) == 'end_domain') { $count_bdw = false; break; } elseif (isset($parts[3])) { $returnval += floatval($parts[3]); } } } } } } return $returnval; } private static function awstatsgenerateindex($domain, $outputdir) { // generation header $header = "&lt;!-- generated froxlor --&gt;\n"; // looking {year}-{month} directories $entries = []; foreach (scandir($outputdir) $a) { (is_dir(filedir::makecorrectdir($outputdir . '/' . $a)) &amp;&amp; preg_match('/^[0-9]{4}-[0-9]{2}$/', $a)) { array_push($entries, '&lt;option value="' . $a . '"&gt;' . $a . '&lt;/option&gt;'); } } // variables replace $regex = [ '/\{site_domain\}/', '/\{select_entries\}/' ]; $replace = [ $domain, implode($entries) ]; // file names $index_file = froxlor::getinstalldir() . '/templates/misc/awstats/index.html'; $index_file = filedir::makecorrectfile($index_file); $nav_file = froxlor::getinstalldir() . '/templates/misc/awstats/nav.html'; $nav_file = filedir::makecorrectfile($nav_file); // write index file // 'index.html' used symlink (ignore errors case first run index.html exists yet) @unlink(filedir::makecorrectfile($outputdir . '/' . 'index.html')); $awstats_index_file = fopen(filedir::makecorrectfile($outputdir . '/' . 'index.html'), 'w'); $awstats_index_tpl = fopen($index_file, 'r'); // write header fwrite($awstats_index_file, $header); // write configuration file (($line = fgets($awstats_index_tpl, 4096)) !== false) { (!preg_match('/^#/', $line) &amp;&amp; trim($line) != '') { fwrite($awstats_index_file, preg_replace($regex, $replace, $line)); } } fclose($awstats_index_file); fclose($awstats_index_tpl); // write nav file $awstats_nav_file = fopen(filedir::makecorrectfile($outputdir . '/' . 'nav.html'), 'w'); $awstats_nav_tpl = fopen($nav_file, 'r'); // write header fwrite($awstats_nav_file, $header); // write configuration file (($line = fgets($awstats_nav_tpl, 4096)) !== false) { (!preg_match('/^#/', $line) &amp;&amp; trim($line) != '') { fwrite($awstats_nav_file, preg_replace($regex, $replace, $line)); } } fclose($awstats_nav_file); fclose($awstats_nav_tpl); return; } }</file><file name="lib/Froxlor/Cron/Traffic/ReportsCron.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\traffic; /** * @author florian lippert &lt;flo@syscp.org&gt; (2003-2009) * @author froxlor team &lt;team@froxlor.org&gt; (2010-) */ use exception; use froxlor\cron\froxlorcron; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\settings; use froxlor\system\mailer; use froxlor\user; use froxlor\language; use pdo; class reportscron extends froxlorcron { public static function run() { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'web- traffic-usage reporting started...'); $yesterday = time() - (60 * 60 * 24); /** * initialize mailingsystem */ $mail = new mailer(true); // set default language anything else // ensure display messages language::setlanguage(settings::get('panel.standardlanguage')); ((int)settings::get('system.report_trafficmax') &gt; 0) { // warn customers xx% traffic-usage $result_stmt = database::prepare(" select `c`.`customerid`, `c`.`loginname`, `c`.`customernumber`, `c`.`adminid`, `c`.`name`, `c`.`firstname`, `c`.`company`, `c`.`traffic`, `c`.`email`, `c`.`def_language`, `a`.`name` `adminname`, `a`.`email` `adminmail`, (select sum(`t`.`http` + `t`.`ftp_up` + `t`.`ftp_down` + `t`.`mail`) `" . table_panel_traffic . "` `t` `t`.`customerid` = `c`.`customerid` `t`.`year` = :year `t`.`month` = :month ) `traffic_used` `" . table_panel_customers . "` `c` left join `" . table_panel_admins . "` `a` `a`.`adminid` = `c`.`adminid` `c`.`reportsent` &amp; 1 = 0 "); $result_data = [ 'year' =&gt; date("y", $yesterday), 'month' =&gt; date("m", $yesterday) ]; database::pexecute($result_stmt, $result_data); $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `reportsent` = `reportsent` + 1 `customerid` = :customerid "); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $row['traffic'] *= 1024; $row['traffic_used'] *= 1024; (isset($row['traffic']) &amp;&amp; $row['traffic'] &gt; 0 &amp;&amp; $row['traffic_used'] != null &amp;&amp; (($row['traffic_used'] * 100) / $row['traffic']) &gt;= (int)settings::get('system.report_trafficmax')) { $rep_userinfo = [ 'name' =&gt; $row['name'], 'firstname' =&gt; $row['firstname'], 'company' =&gt; $row['company'], 'loginname' =&gt; $row['loginname'], 'customernumber' =&gt; $row['customernumber'] ]; $replace_arr = [ 'salutation' =&gt; user::getcorrectusersalutation($rep_userinfo), 'name' =&gt; $rep_userinfo['name'], 'firstname' =&gt; $rep_userinfo['firstname'], 'company' =&gt; $rep_userinfo['company'], 'username' =&gt; $rep_userinfo['loginname'], 'customer_no' =&gt; $rep_userinfo['customernumber'], 'traffic' =&gt; phphelper::sizereadable((int)$row['traffic'], null, 'bi'), 'trafficused' =&gt; phphelper::sizereadable((int)$row['traffic_used'], null, 'bi'), 'usage_percent' =&gt; round(($row['traffic_used'] * 100) / $row['traffic'], 2), 'max_percent' =&gt; settings::get('system.report_trafficmax') ]; // set target user language language::setlanguage($row['def_language']); // get mail templates database; ones 'admin' fetched fallback $result2_stmt = database::prepare(" select `value` `" . table_panel_templates . "` `adminid` = :adminid `language` = :lang `templategroup` = 'mails' `varname` = :varname "); $result2_data = [ 'adminid' =&gt; $row['adminid'], 'lang' =&gt; $row['def_language'], 'varname' =&gt; 'trafficmaxpercent_subject' ]; $result2 = database::pexecute_first($result2_stmt, $result2_data); $mail_subject = html_entity_decode(phphelper::replacevariables((($result2 !== false &amp;&amp; $result2['value'] != '') ? $result2['value'] : language::gettranslation('mails.trafficmaxpercent.subject')), $replace_arr)); $result2_data['varname'] = 'trafficmaxpercent_mailbody'; $result2 = database::pexecute_first($result2_stmt, $result2_data); $mail_body = html_entity_decode(phphelper::replacevariables((($result2 !== false &amp;&amp; $result2['value'] != '') ? $result2['value'] : language::gettranslation('mails.trafficmaxpercent.mailbody')), $replace_arr)); $_mailerror = false; $mailerr_msg = ""; try { $mail-&gt;setfrom(settings::get('panel.adminmail'), $row['adminname']); $mail-&gt;clearreplytos(); $mail-&gt;addreplyto($row['adminmail'], $row['adminname']); $mail-&gt;subject = $mail_subject; $mail-&gt;altbody = $mail_body; $mail-&gt;msghtml(nl2br($mail_body)); $mail-&gt;addaddress($row['email'], $row['firstname'] . ' ' . $row['name']); $mail-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, 'error sending mail: ' . $mailerr_msg); echo 'error sending mail: ' . $mailerr_msg . "\n"; } $mail-&gt;clearaddresses(); database::pexecute($upd_stmt, [ 'customerid' =&gt; $row['customerid'] ]); } } // warn admins xx% traffic-usage $result_stmt = database::prepare(" select `a`.*, (select sum(`t`.`http` + `t`.`ftp_up` + `t`.`ftp_down` + `t`.`mail`) `" . table_panel_traffic_admins . "` `t` `t`.`adminid` = `a`.`adminid` `t`.`year` = :year `t`.`month` = :month ) `traffic_used_total` `" . table_panel_admins . "` `a` `a`.`reportsent` &amp; 1 = 0 "); $result_data = [ 'year' =&gt; date("y", $yesterday), 'month' =&gt; date("m", $yesterday) ]; database::pexecute($result_stmt, $result_data); $upd_stmt = database::prepare(" update `" . table_panel_admins . "` set `reportsent` = `reportsent` + 1 `adminid` = :adminid "); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $row['traffic'] *= 1024; $row['traffic_used_total'] *= 1024; (isset($row['traffic']) &amp;&amp; $row['traffic'] &gt; 0 &amp;&amp; (($row['traffic_used_total'] * 100) / ($row['traffic'])) &gt;= (int)settings::get('system.report_trafficmax')) { $replace_arr = [ 'name' =&gt; $row['name'], 'traffic' =&gt; phphelper::sizereadable((int)$row['traffic'], null, 'bi'), 'trafficused' =&gt; phphelper::sizereadable((int)$row['traffic_used_total'], null, 'bi'), 'usage_percent' =&gt; round(($row['traffic_used_total'] * 100) / $row['traffic'], 2), 'max_percent' =&gt; settings::get('system.report_trafficmax') ]; // set target user language language::setlanguage($row['def_language']); // get mail templates database; ones 'admin' fetched fallback $result2_stmt = database::prepare(" select `value` `" . table_panel_templates . "` `adminid` = :adminid `language` = :lang `templategroup` = 'mails' `varname` = :varname "); $result2_data = [ 'adminid' =&gt; $row['adminid'], 'lang' =&gt; $row['def_language'], 'varname' =&gt; 'trafficmaxpercent_subject' ]; $result2 = database::pexecute_first($result2_stmt, $result2_data); $mail_subject = html_entity_decode(phphelper::replacevariables((($result2 !== false &amp;&amp; $result2['value'] != '') ? $result2['value'] : language::gettranslation('mails.trafficmaxpercent.subject')), $replace_arr)); $result2_data['varname'] = 'trafficmaxpercent_mailbody'; $result2 = database::pexecute_first($result2_stmt, $result2_data); $mail_body = html_entity_decode(phphelper::replacevariables((($result2 !== false &amp;&amp; $result2['value'] != '') ? $result2['value'] : language::gettranslation('mails.trafficmaxpercent.mailbody')), $replace_arr)); $_mailerror = false; $mailerr_msg = ""; try { $mail-&gt;setfrom(settings::get('panel.adminmail'), settings::get('panel.adminmail_defname')); $mail-&gt;subject = $mail_subject; $mail-&gt;altbody = $mail_body; $mail-&gt;msghtml(nl2br($mail_body)); $mail-&gt;addaddress($row['email'], $row['name']); $mail-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, "error sending mail: " . $mailerr_msg); echo "error sending mail: " . $mailerr_msg . "\n"; } $mail-&gt;clearaddresses(); database::pexecute($upd_stmt, [ 'adminid' =&gt; $row['adminid'] ]); } // another month, let's build report (date('d') == '01') { $mail_subject = 'trafficreport ' . date("m/y", $yesterday) . ' ' . $row['name']; $mail_body = 'trafficreport ' . date("m/y", $yesterday) . ' ' . $row['name'] . "\n"; $mail_body .= '---------------------------------------------------------------' . "\n"; $mail_body .= 'loginname traffic used (percent) | traffic available' . "\n"; $customers_stmt = database::prepare(" select `c`.*, (select sum(`t`.`http` + `t`.`ftp_up` + `t`.`ftp_down` + `t`.`mail`) `" . table_panel_traffic . "` `t` `t`.`customerid` = `c`.`customerid` `t`.`year` = :year `t`.`month` = :month ) `traffic_used_total` `" . table_panel_customers . "` `c` `c`.`adminid` = :adminid "); $customers_data = [ 'year' =&gt; date("y", $yesterday), 'month' =&gt; date("m", $yesterday), 'adminid' =&gt; $row['adminid'] ]; database::pexecute($customers_stmt, $customers_data); ($customer = $customers_stmt-&gt;fetch(pdo::fetch_assoc)) { $customer['traffic'] *= 1024; $t = (int) $customer['traffic_used_total'] * 1024; ($customer['traffic'] &gt; 0) { $p = (($t * 100) / $customer['traffic']); $tg = (int) $customer['traffic']; $str = sprintf('%s ( %00.1f %% )', phphelper::sizereadable($t, null, 'bi'), $p); $mail_body .= sprintf('%-15s', $customer['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . sprintf('%s', phphelper::sizereadable($tg, null, 'bi')) . "\n"; } elseif ($customer['traffic'] == 0) { $str = sprintf('%s ( - )', phphelper::sizereadable($t, null, 'bi')); $mail_body .= sprintf('%-15s', $customer['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . '0' . "\n"; } else { $str = sprintf('%s ( - )', phphelper::sizereadable($t, null, 'bi')); $mail_body .= sprintf('%-15s', $customer['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . 'unlimited' . "\n"; } } $mail_body .= '---------------------------------------------------------------' . "\n"; $t = (int) $row['traffic_used_total']; ($row['traffic'] &gt; 0) { $p = (($t * 100) / $row['traffic']); $tg = (int) $row['traffic']; $str = sprintf('%s ( %00.1f %% )', phphelper::sizereadable($t, null, 'bi'), $p); $mail_body .= sprintf('%-15s', $row['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . sprintf('%s', phphelper::sizereadable($tg, null, 'bi')) . "\n"; } elseif ($row['traffic'] == 0) { $str = sprintf('%s ( - )', phphelper::sizereadable($t, null, 'bi')); $mail_body .= sprintf('%-15s', $row['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . '0' . "\n"; } else { $str = sprintf('%s ( - )', phphelper::sizereadable($t, null, 'bi')); $mail_body .= sprintf('%-15s', $row['loginname']) . ' ' . sprintf('%-25s', $str) . ' ' . 'unlimited' . "\n"; } $_mailerror = false; $mailerr_msg = ""; try { $mail-&gt;setfrom(settings::get('panel.adminmail'), settings::get('panel.adminmail_defname')); $mail-&gt;subject = $mail_subject; $mail-&gt;body = $mail_body; $mail-&gt;msghtml(nl2br($mail_body)); $mail-&gt;addaddress($row['email'], $row['name']); $mail-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, 'error sending mail: ' . $mailerr_msg); echo 'error sending mail: ' . $mailerr_msg . "\n"; } $mail-&gt;clearaddresses(); } } } // trafficmax &gt; 0 // include diskspace-usage report, #466 self::usagediskspace(); // another month, reset reportstatus (date('d') == '01') { database::query("update `" . table_panel_customers . "` set `reportsent` = '0';"); database::query("update `" . table_panel_admins . "` set `reportsent` = '0';"); } } private static function usagediskspace() { ((int)settings::get('system.report_webmax') &gt; 0) { /** * report diskusage customers */ $result_stmt = database::query(" select `c`.`customerid`, `c`.`loginname`, `c`.`customernumber`, `c`.`adminid`, `c`.`name`, `c`.`firstname`, `c`.`company`, `c`.`diskspace`, `c`.`diskspace_used`, `c`.`email`, `c`.`def_language`, `a`.`name` `adminname`, `a`.`email` `adminmail` `" . table_panel_customers . "` `c` left join `" . table_panel_admins . "` `a` `a`.`adminid` = `c`.`adminid` `c`.`diskspace` &gt; '0' `c`.`reportsent` &amp; 2 = 0 "); $mail = new mailer(true); $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `reportsent` = `reportsent` + 2 `customerid` = :customerid "); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $row['diskspace'] *= 1024; $row['diskspace_used'] *= 1024; (isset($row['diskspace']) &amp;&amp; $row['diskspace_used'] != null &amp;&amp; $row['diskspace_used'] &gt; 0 &amp;&amp; (($row['diskspace_used'] * 100) / $row['diskspace']) &gt;= (int)settings::get('system.report_webmax')) { $rep_userinfo = [ 'name' =&gt; $row['name'], 'firstname' =&gt; $row['firstname'], 'company' =&gt; $row['company'], 'loginname' =&gt; $row['loginname'], 'customernumber' =&gt; $row['customernumber'] ]; $replace_arr = [ 'salutation' =&gt; user::getcorrectusersalutation($rep_userinfo), 'name' =&gt; $rep_userinfo['name'], 'firstname' =&gt; $rep_userinfo['firstname'], 'company' =&gt; $rep_userinfo['company'], 'username' =&gt; $rep_userinfo['loginname'], 'customer_no' =&gt; $rep_userinfo['customernumber'], 'diskavailable' =&gt; phphelper::sizereadable((int)$row['diskspace'], null, 'bi'), 'diskused' =&gt; phphelper::sizereadable((int)$row['diskspace_used'], null, 'bi'), 'usage_percent' =&gt; round(($row['diskspace_used'] * 100) / $row['diskspace'], 2), 'max_percent' =&gt; settings::get('system.report_webmax') ]; // set target user language language::setlanguage($row['def_language']); // get mail templates database; ones 'admin' fetched fallback $result2_stmt = database::prepare(" select `value` `" . table_panel_templates . "` `adminid` = :adminid `language` = :lang `templategroup` = 'mails' `varname` = :varname "); $result2_data = [ 'adminid' =&gt; $row['adminid'], 'lang' =&gt; $row['def_language'], 'varname' =&gt; 'diskmaxpercent_subject' ]; $result2 = database::pexecute_first($result2_stmt, $result2_data); $mail_subject = html_entity_decode(phphelper::replacevariables((($result2 !== false &amp;&amp; $result2['value'] != '') ? $result2['value'] : language::gettranslation('mails.diskmaxpercent.subject')), $replace_arr)); $result2_data['varname'] = 'diskmaxpercent_mailbody'; $result2 = database::pexecute_first($result2_stmt, $result2_data); $mail_body = html_entity_decode(phphelper::replacevariables((($result2 !== false &amp;&amp; $result2['value'] != '') ? $result2['value'] : language::gettranslation('mails.diskmaxpercent.mailbody')), $replace_arr)); $_mailerror = false; $mailerr_msg = ""; try { $mail-&gt;setfrom(settings::get('panel.adminmail'), $row['adminname']); $mail-&gt;clearreplytos(); $mail-&gt;addreplyto($row['adminmail'], $row['adminname']); $mail-&gt;subject = $mail_subject; $mail-&gt;altbody = $mail_body; $mail-&gt;msghtml(nl2br($mail_body)); $mail-&gt;addaddress($row['email'], $row['name']); $mail-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, "error sending mail: " . $mailerr_msg); echo "error sending mail: " . $mailerr_msg . "\n"; } $mail-&gt;clearaddresses(); database::pexecute($upd_stmt, [ 'customerid' =&gt; $row['customerid'] ]); } } /** * report diskusage admins/reseller */ $result_stmt = database::query(" select `a`.* `" . table_panel_admins . "` `a` `a`.`reportsent` &amp; 2 = 0 "); $upd_stmt = database::prepare(" update `" . table_panel_admins . "` set `reportsent` = `reportsent` + 2 `adminid` = :adminid "); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $row['diskspace'] *= 1024; $row['diskspace_used'] *= 1024; (isset($row['diskspace']) &amp;&amp; $row['diskspace_used'] != null &amp;&amp; $row['diskspace_used'] &gt; 0 &amp;&amp; (($row['diskspace_used'] * 100) / $row['diskspace']) &gt;= (int)settings::get('system.report_webmax')) { $replace_arr = [ 'name' =&gt; $row['name'], 'diskavailable' =&gt; phphelper::sizereadable((int)$row['diskspace'], null, 'bi'), 'diskused' =&gt; phphelper::sizereadable((int)$row['diskspace_used'], null, 'bi'), 'usage_percent' =&gt; ($row['diskspace_used'] * 100) / $row['diskspace'], 'max_percent' =&gt; settings::get('system.report_webmax') ]; // set target user language language::setlanguage($row['def_language']); // get mail templates database; ones 'admin' fetched fallback $result2_stmt = database::prepare(" select `value` `" . table_panel_templates . "` `adminid` = :adminid `language` = :lang `templategroup` = 'mails' `varname` = :varname "); $result2_data = [ 'adminid' =&gt; $row['adminid'], 'lang' =&gt; $row['def_language'], 'varname' =&gt; 'diskmaxpercent_subject' ]; $result2 = database::pexecute_first($result2_stmt, $result2_data); $mail_subject = html_entity_decode(phphelper::replacevariables((($result2 !== false &amp;&amp; $result2['value'] != '') ? $result2['value'] : language::gettranslation('mails.diskmaxpercent.subject')), $replace_arr)); $result2_data['varname'] = 'diskmaxpercent_mailbody'; $result2 = database::pexecute_first($result2_stmt, $result2_data); $mail_body = html_entity_decode(phphelper::replacevariables((($result2 !== false &amp;&amp; $result2['value'] != '') ? $result2['value'] : language::gettranslation('mails.diskmaxpercent.mailbody')), $replace_arr)); $_mailerror = false; $mailerr_msg = ""; try { $mail-&gt;setfrom(settings::get('panel.adminmail'), settings::get('panel.adminmail_defname')); $mail-&gt;subject = $mail_subject; $mail-&gt;altbody = $mail_body; $mail-&gt;msghtml(nl2br($mail_body)); $mail-&gt;addaddress($row['email'], $row['name']); $mail-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, "error sending mail: " . $mailerr_msg); echo "error sending mail: " . $mailerr_msg . "\n"; } $mail-&gt;clearaddresses(); database::pexecute($upd_stmt, [ 'adminid' =&gt; $row['adminid'] ]); } } } // webmax &gt; 0 } }</file><file name="lib/Froxlor/Cron/System/MailboxsizeCron.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\system; use froxlor\cron\froxlorcron; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; use pdo; class mailboxsizecron extends froxlorcron { public static function run() { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'calculating mailspace usage'); $maildirs_stmt = database::query(" select `id`, concat(`homedir`, `maildir`) `maildirpath` `" . table_mail_users . "` order `id` "); $upd_stmt = database::prepare(" update `" . table_mail_users . "` set `mboxsize` = :size `id` = :id "); ($maildir = $maildirs_stmt-&gt;fetch(pdo::fetch_assoc)) { $_maildir = filedir::makecorrectdir($maildir['maildirpath']); (file_exists($_maildir) &amp;&amp; is_dir($_maildir)) { $maildirsize = filedir::makecorrectfile($_maildir . '/maildirsize'); // quota enabled maildirsize file exists, use calculate size (settings::get('system.mail_quota_enabled') == 1 &amp;&amp; file_exists($maildirsize)) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'found maildirsize file ' . $_maildir); $file = file($maildirsize, file_ignore_new_lines | file_skip_empty_lines); // remove header array_shift($file); $emailusage = 0; // sum changes (line 2 -&gt; end) foreach ($file $line) { $parts = explode(' ', $line); (!empty($parts[0])) { $emailusage += floatval($parts[0]); } } } else { // quota disabled maildirsize file exist, compute du // mail-address allows many special characters, see http://en.wikipedia.org/wiki/email_address#local_part $return = false; $back = filedir::safe_exec('du -sk ' . escapeshellarg($_maildir), $return, [ '|', '&amp;', '`', '$', '~', '?' ]); foreach ($back $backrow) { $emailusage = explode(' ', $backrow); } $emailusage = floatval($emailusage['0']); // freebsd -b flag 'du' gives // size bytes, use "-sk" calculate kib $emailusage *= 1024; unset($back); } database::pexecute($upd_stmt, [ 'size' =&gt; $emailusage, 'id' =&gt; $maildir['id'] ]); } else { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_warning, 'maildir ' . $_maildir . ' exist'); } } } }</file><file name="lib/Froxlor/Cron/System/TasksCron.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\system; use exception; use froxlor\cron\froxlorcron; use froxlor\cron\http\configio; use froxlor\cron\http\httpconfigbase; use froxlor\cron\http\letsencrypt\acmesh; use froxlor\cron\mail\rspamd; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\dns\powerdns; use froxlor\domain\domain; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; use pdo; class taskscron extends froxlorcron { /** * @throws exception */ public static function run() { /** * look tasks table see undone jobs */ self::$cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, "taskscron: searching tasks do"); // type 99 (regenerate cron.d-file) type 20 (customer data export) // order type descending re-create bind webserver end $result_tasks_stmt = database::query(" select `id`, `type`, `data` `" . table_panel_tasks . "` `type` &lt;&gt; '99' `type` &lt;&gt; '20' order `type` desc, `id` asc "); $num_results = database::num_rows(); $resultids = []; ($row = $result_tasks_stmt-&gt;fetch(pdo::fetch_assoc)) { $resultids[] = $row['id']; ($row['data'] != '') { $row['data'] = json_decode($row['data'], true); } ($row['type'] == taskid::rebuild_vhost) { /** * type=1 means rebuild apache vhosts.conf */ self::rebuildwebserverconfigs(); } elseif ($row['type'] == taskid::create_home) { /** * type=2 means create new home chown */ self::createnewhome($row); } elseif ($row['type'] == taskid::rebuild_dns &amp;&amp; (int)settings::get('system.bind_enable') != 0) { /** * type=4 means something bind config changed. * rebuild froxlor_bind.conf bind enabled */ self::rebuilddnsconfigs(); } elseif ($row['type'] == taskid::create_ftp) { /** * type=5 means new ftp-account created, create directory */ self::createnewftphome($row); } elseif ($row['type'] == taskid::delete_customer_files) { /** * type=6 means customer deleted remove files */ self::deletecustomerdata($row); } elseif ($row['type'] == taskid::delete_email_data) { /** * type=7 customer deleted email account wants data deleted filesystem */ self::deleteemaildata($row); } elseif ($row['type'] == taskid::delete_ftp_data) { /** * type=8 customer deleted ftp account wants homedir deleted filesystem * refs #293 */ self::deleteftpdata($row); } elseif ($row['type'] == taskid::rebuild_rspamd &amp;&amp; (int)settings::get('antispam.activated') != 0) { /** * type=9 rebuild antispam config */ self::rebuildantispamconfigs(); } elseif ($row['type'] == taskid::create_quota &amp;&amp; (int)settings::get('system.diskquota_enabled') != 0) { /** * type=10 set filesystem - quota */ self::setfilesystemquota(); } elseif ($row['type'] == taskid::delete_domain_pdns &amp;&amp; settings::get('system.dns_server') == 'powerdns') { /** * type=11 domain deleted, remove pdns database used */ froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, "removing powerdns entries domain " . $row['data']['domain']); powerdns::cleandomainzone($row['data']['domain']); } elseif ($row['type'] == taskid::delete_domain_ssl) { /** * type=12 domain deleted, remove acme.sh/let's encrypt directory used */ froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, "removing let's encrypt entries domain " . $row['data']['domain']); domain::doletsencryptcleanup($row['data']['domain']); } elseif ($row['type'] == taskid::update_le_services) { /** * type=13 set configuration selected services regarding use let's encrypt certificate */ froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, "updating let's encrypt configuration selected services"); acmesh::renewhookconfigs(froxlorlogger::getinstanceof()); } } ($num_results != 0) { $where = []; $where_data = []; foreach ($resultids $id) { $where[] = "`id` = :id_" . (int)$id; $where_data['id_' . $id] = $id; } $where = implode(' ', $where); $del_stmt = database::prepare("delete `" . table_panel_tasks . "` " . $where); database::pexecute($del_stmt, $where_data); unset($resultids); unset($where); } database::query("update `" . table_panel_settings . "` set `value` = unix_timestamp() `settinggroup` = 'system' `varname` = 'last_tasks_run';"); } private static function rebuildwebserverconfigs() { (settings::get('system.webserver') == "apache2") { $websrv = '\\froxlor\\cron\\http\\apache'; (settings::get('system.mod_fcgid') == 1 || settings::get('phpfpm.enabled') == 1) { $websrv .= 'fcgi'; } } elseif (settings::get('system.webserver') == "lighttpd") { $websrv = '\\froxlor\\cron\\http\\lighttpd'; (settings::get('system.mod_fcgid') == 1 || settings::get('phpfpm.enabled') == 1) { $websrv .= 'fcgi'; } } elseif (settings::get('system.webserver') == "nginx") { $websrv = '\\froxlor\\cron\\http\\nginx'; (settings::get('phpfpm.enabled') == 1) { $websrv .= 'fcgi'; } } // get configuration-i/o object $configio = new configio(); // get webserver object $webserver = new $websrv(); ($webserver instanceof httpconfigbase) { $webserver-&gt;init(); // clean old configs $configio-&gt;cleanup(); $webserver-&gt;createipport(); $webserver-&gt;createvirtualhosts(); $webserver-&gt;createfilediroptions(); $webserver-&gt;writeconfigs(); $webserver-&gt;createownvhoststarter(); $webserver-&gt;reload(); } else { echo "please check webserver settings\n"; } // use php-fpm local user froxlor, need // add webserver-user local-group order allow webserver // access fpm-socket (settings::get('phpfpm.enabled') == 1 &amp;&amp; function_exists("posix_getgrnam")) { // get group info local-user's group (e.g. froxlorlocal) $groupinfo = posix_getgrnam(settings::get('phpfpm.vhost_httpgroup')); // check group members (isset($groupinfo['members']) &amp;&amp; !in_array(settings::get('system.httpuser'), $groupinfo['members'])) { // webserver access, add (filedir::isfreebsd()) { filedir::safe_exec('pw usermod ' . escapeshellarg(settings::get('system.httpuser')) . ' -g ' . escapeshellarg(settings::get('phpfpm.vhost_httpgroup'))); } else { filedir::safe_exec('usermod -a -g ' . escapeshellarg(settings::get('phpfpm.vhost_httpgroup')) . ' ' . escapeshellarg(settings::get('system.httpuser'))); } } } // tell let's encrypt cron okay generate certificate enable redirect afterwards $upd_stmt = database::prepare("update `" . table_panel_domains . "` set `ssl_redirect` = '3' `ssl_redirect` = '2'"); database::pexecute($upd_stmt); } private static function createnewhome($row = null) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'taskscron: task2 started - create new home'); (is_array($row['data'])) { // define paths $userhomedir = filedir::makecorrectdir(settings::get('system.documentroot_prefix') . '/' . $row['data']['loginname'] . '/'); $usermaildir = filedir::makecorrectdir(settings::get('system.vmail_homedir') . '/' . $row['data']['loginname'] . '/'); // stats directory $statsdir = filedir::makecorrectdir($userhomedir . '/' . settings::get('system.traffictool')); froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'running: mkdir -p ' . escapeshellarg($statsdir)); filedir::safe_exec('mkdir -p ' . escapeshellarg($statsdir)); foreach (['webalizer', 'awstats', 'goaccess'] $statstools) { $statsdir = filedir::makecorrectdir($userhomedir . '/' . $statstools); // case changed stats -&gt; remove old (settings::get('system.traffictool') != $statstools &amp;&amp; file_exists($statsdir)) { // (yes know, stats lost - that's change time!) filedir::safe_exec('rm -rf ' . escapeshellarg($statsdir)); } } // maildir froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'running: mkdir -p ' . escapeshellarg($usermaildir)); filedir::safe_exec('mkdir -p ' . escapeshellarg($usermaildir)); // check admin customer added template new customer directories ((int)$row['data']['store_defaultindex'] == 1) { filedir::storedefaultindex($row['data']['loginname'], $userhomedir, froxlorlogger::getinstanceof(), true); } // strip last slash paths correct chown results $userhomedir = (substr($userhomedir, 0, -1) == '/') ? substr($userhomedir, 0, -1) : $userhomedir; $usermaildir = (substr($usermaildir, 0, -1) == '/') ? substr($usermaildir, 0, -1) : $usermaildir; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'running: chown -r ' . (int)$row['data']['uid'] . ':' . (int)$row['data']['gid'] . ' ' . escapeshellarg($userhomedir)); filedir::safe_exec('chown -r ' . (int)$row['data']['uid'] . ':' . (int)$row['data']['gid'] . ' ' . escapeshellarg($userhomedir)); // allow others access directory (webserver group via libnss-mysql) (settings::get('system.mod_fcgid') == 1 || settings::get('phpfpm.enabled') == 1) { // fcgid fpm filedir::safe_exec('chmod 0750 ' . escapeshellarg($userhomedir)); } else { // mod_php -&gt; libnss-mysql -&gt; webserver-user group filedir::safe_exec('chmod 0755 ' . escapeshellarg($userhomedir)); } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'running: chown -r ' . (int)settings::get('system.vmail_uid') . ':' . (int)settings::get('system.vmail_gid') . ' ' . escapeshellarg($usermaildir)); filedir::safe_exec('chown -r ' . (int)settings::get('system.vmail_uid') . ':' . (int)settings::get('system.vmail_gid') . ' ' . escapeshellarg($usermaildir)); (settings::get('system.nssextrausers') == 1) { // explicitly create files user created avoid unknown user issues apache/php-fpm task#1 runs $extrausers_log = froxlorlogger::getinstanceof(); extrausers::generatefiles($extrausers_log); } // clear nscd cache using fcgid fpm, #1570 - needed nss-extrausers ((settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1) &amp;&amp; settings::get('system.nssextrausers') == 0) { $false_val = false; filedir::safe_exec('nscd -i passwd 1&gt; /dev/null', $false_val, [ '&gt;' ]); filedir::safe_exec('nscd -i group 1&gt; /dev/null', $false_val, [ '&gt;' ]); } } } private static function rebuilddnsconfigs() { $dnssrv = '\\froxlor\\cron\\dns\\' . settings::get('system.dns_server'); $nameserver = new $dnssrv(froxlorlogger::getinstanceof()); $nameserver-&gt;writeconfigs(); } private static function createnewftphome($row = null) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'creating new ftp-home'); $result_directories_stmt = database::query(" select `f`.`homedir`, `f`.`uid`, `f`.`gid`, `c`.`documentroot` `customerroot` `" . table_ftp_users . "` `f` left join `" . table_panel_customers . "` `c` using (`customerid`) "); ($directory = $result_directories_stmt-&gt;fetch(pdo::fetch_assoc)) { filedir::mkdirwithcorrectownership($directory['customerroot'], $directory['homedir'], $directory['uid'], $directory['gid']); } } private static function deletecustomerdata($row = null) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'taskscron: task6 started - deleting customer data'); (is_array($row['data'])) { (isset($row['data']['loginname'])) { // remove homedir $homedir = filedir::makecorrectdir(settings::get('system.documentroot_prefix') . '/' . $row['data']['loginname']); (file_exists($homedir) &amp;&amp; $homedir != '/' &amp;&amp; $homedir != settings::get('system.documentroot_prefix') &amp;&amp; substr($homedir, 0, strlen(settings::get('system.documentroot_prefix'))) == settings::get('system.documentroot_prefix')) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'running: rm -rf ' . escapeshellarg($homedir)); filedir::safe_exec('rm -rf ' . escapeshellarg($homedir)); } // remove maildir $maildir = filedir::makecorrectdir(settings::get('system.vmail_homedir') . '/' . $row['data']['loginname']); (file_exists($maildir) &amp;&amp; $maildir != '/' &amp;&amp; $maildir != settings::get('system.vmail_homedir') &amp;&amp; substr($maildir, 0, strlen(settings::get('system.vmail_homedir'))) == settings::get('system.vmail_homedir') &amp;&amp; is_dir($maildir) &amp;&amp; fileowner($maildir) == settings::get('system.vmail_uid') &amp;&amp; filegroup($maildir) == settings::get('system.vmail_gid')) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'running: rm -rf ' . escapeshellarg($maildir)); // mail-address allows many special characters, see http://en.wikipedia.org/wiki/email_address#local_part $return = false; filedir::safe_exec('rm -rf ' . escapeshellarg($maildir), $return, [ '|', '&amp;', '`', '$', '?' ]); } // remove tmpdir exists $tmpdir = filedir::makecorrectdir(settings::get('system.mod_fcgid_tmpdir') . '/' . $row['data']['loginname'] . '/'); (file_exists($tmpdir) &amp;&amp; is_dir($tmpdir) &amp;&amp; $tmpdir != "/" &amp;&amp; $tmpdir != settings::get('system.mod_fcgid_tmpdir') &amp;&amp; substr($tmpdir, 0, strlen(settings::get('system.mod_fcgid_tmpdir'))) == settings::get('system.mod_fcgid_tmpdir')) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'running: rm -rf ' . escapeshellarg($tmpdir)); filedir::safe_exec('rm -rf ' . escapeshellarg($tmpdir)); } // webserver logs $logsdir = filedir::makecorrectfile(settings::get('system.logfiles_directory') . '/' . $row['data']['loginname']); (file_exists(dirname($logsdir)) &amp;&amp; $logsdir != '/' &amp;&amp; $logsdir != filedir::makecorrectdir(settings::get('system.logfiles_directory')) &amp;&amp; substr($logsdir, 0, strlen(settings::get('system.logfiles_directory'))) == settings::get('system.logfiles_directory')) { // build wildcard webx-{access,error}.log{*} $logsdir .= '-*.log'; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'running: rm -rf ' .filedir::makecorrectfile($logsdir)); filedir::safe_exec('rm -f ' . filedir::makecorrectfile($logsdir)); } } } } private static function deleteemaildata($row = null) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'taskscron: task7 started - deleting customer e-mail data'); (is_array($row['data'])) { (isset($row['data']['loginname']) &amp;&amp; isset($row['data']['emailpath'])) { // remove specific maildir $email_full = $row['data']['emailpath']; (empty($email_full)) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, 'fatal: task7 asks delete email account emailpath field empty!'); } $maildir = filedir::makecorrectdir($email_full); ($maildir != '/' &amp;&amp; !empty($maildir) &amp;&amp; $maildir != settings::get('system.vmail_homedir') &amp;&amp; substr($maildir, 0, strlen(settings::get('system.vmail_homedir'))) == settings::get('system.vmail_homedir') &amp;&amp; is_dir($maildir) &amp;&amp; fileowner($maildir) == settings::get('system.vmail_uid') &amp;&amp; filegroup($maildir) == settings::get('system.vmail_gid')) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'running: rm -rf ' . escapeshellarg($maildir)); // mail-address allows many special characters, see http://en.wikipedia.org/wiki/email_address#local_part $return = false; filedir::safe_exec('rm -rf ' . escapeshellarg($maildir), $return, [ '|', '&amp;', '`', '$', '~', '?' ]); } } } } private static function deleteftpdata($row = null) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'taskscron: task8 started - deleting customer ftp homedir'); (is_array($row['data'])) { (isset($row['data']['loginname']) &amp;&amp; isset($row['data']['homedir'])) { // remove specific homedir $ftphomedir = filedir::makecorrectdir($row['data']['homedir']); $customerdocroot = filedir::makecorrectdir(settings::get('system.documentroot_prefix') . '/' . $row['data']['loginname'] . '/'); (file_exists($ftphomedir) &amp;&amp; $ftphomedir != '/' &amp;&amp; $ftphomedir != settings::get('system.documentroot_prefix') &amp;&amp; $ftphomedir != $customerdocroot) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'running: rm -rf ' . escapeshellarg($ftphomedir)); filedir::safe_exec('rm -rf ' . escapeshellarg($ftphomedir)); } } } } private static function setfilesystemquota() { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'taskscron: task10 started - setting filesystem quota'); $usedquota = filedir::getfilesystemquota(); // check whether really entries check (is_array($usedquota) &amp;&amp; count($usedquota) &gt; 0) { // select customers froxlor knows $result_stmt = database::query("select `guid`, `loginname`, `diskspace` `" . table_panel_customers . "`;"); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { // want set quota root accident ($row['guid'] != 0) { $used_quota = isset($usedquota[$row['guid']]) ? $usedquota[$row['guid']]['block']['hard'] : 0; // user quota froxlor, filesystem (($row['diskspace'] == 0 || $row['diskspace'] == -1024) &amp;&amp; $used_quota != 0) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, "disabling quota " . $row['loginname']); (filedir::isfreebsd()) { filedir::safe_exec(settings::get('system.diskquota_quotatool_path') . " -e " . escapeshellarg(settings::get('system.diskquota_customer_partition')) . ":0:0 " . $row['guid']); } else { filedir::safe_exec(settings::get('system.diskquota_quotatool_path') . " -u " . $row['guid'] . " -bl 0 -q 0 " . escapeshellarg(settings::get('system.diskquota_customer_partition'))); } } elseif ($row['diskspace'] != $used_quota &amp;&amp; $row['diskspace'] != -1024) { // user quota froxlor different filesystem froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, "setting quota " . $row['loginname'] . " " . $used_quota . " " . $row['diskspace']); (filedir::isfreebsd()) { filedir::safe_exec(settings::get('system.diskquota_quotatool_path') . " -e " . escapeshellarg(settings::get('system.diskquota_customer_partition')) . ":" . $row['diskspace'] . ":" . $row['diskspace'] . " " . $row['guid']); } else { filedir::safe_exec(settings::get('system.diskquota_quotatool_path') . " -u " . $row['guid'] . " -bl " . $row['diskspace'] . " -q " . $row['diskspace'] . " " . escapeshellarg(settings::get('system.diskquota_customer_partition'))); } } } } } } /** * @throws exception */ private static function rebuildantispamconfigs() { $antispam = new rspamd(froxlorlogger::getinstanceof()); $antispam-&gt;writeconfigs(); } }</file><file name="lib/Froxlor/Cron/System/Extrausers.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\system; use froxlor\customer\customer; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\user; use pdo; class extrausers { public static function generatefiles(&amp;$cronlog) { // passwd $passwd = '/var/lib/extrausers/passwd'; $sql = "select customerid,username,'x' password,uid,gid,'froxlor user' comment,homedir,shell, login_enabled ftp_users order uid, length(username) asc"; $users_list = []; self::generatefile($passwd, $sql, $cronlog, $users_list); // group $group = '/var/lib/extrausers/group'; $sql = "select groupname,'x' password,gid,members ftp_groups order gid asc"; self::generatefile($group, $sql, $cronlog, $users_list); // shadow $shadow = '/var/lib/extrausers/shadow'; $sql = "select username,password ftp_users order gid asc"; self::generatefile($shadow, $sql, $cronlog); // set correct permissions @chmod('/var/lib/extrausers/', 0755); @chmod('/var/lib/extrausers/passwd', 0644); @chmod('/var/lib/extrausers/group', 0644); @chmod('/var/lib/extrausers/shadow', 0640); } private static function generatefile($file, $query, &amp;$cronlog, &amp;$result_list = null) { $type = basename($file); $cronlog-&gt;logaction(froxlorlogger::cron_action, log_notice, 'creating ' . $type . ' file'); (!file_exists($file)) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_notice, $type . ' file yet exist'); @mkdir(dirname($file), 0750, true); touch($file); } $data_sel_stmt = database::query($query); $data_content = ""; $cronlog-&gt;logaction(froxlorlogger::cron_action, log_notice, 'writing ' . $data_sel_stmt-&gt;rowcount() . ' entries ' . $type . ' file'); ($u = $data_sel_stmt-&gt;fetch(pdo::fetch_assoc)) { switch ($type) { case 'passwd': // get user real name $salutation_array = [ 'firstname' =&gt; customer::getcustomerdetail($u['customerid'], 'firstname'), 'name' =&gt; customer::getcustomerdetail($u['customerid'], 'name'), 'company' =&gt; customer::getcustomerdetail($u['customerid'], 'company') ]; $u['comment'] = self::cleanstring(user::getcorrectusersalutation($salutation_array)); ($u['login_enabled'] != 'y') { $u['password'] = '*'; $u['shell'] = '/bin/false'; $u['comment'] = 'locked froxlor user'; } $line = $u['username'] . ':' . $u['password'] . ':' . $u['uid'] . ':' . $u['gid'] . ':' . $u['comment'] . ':' . $u['homedir'] . ':' . $u['shell'] . php_eol; (is_array($result_list)) { $result_list[] = $u['username']; } break; case 'group': $line = $u['groupname'] . ':' . $u['password'] . ':' . $u['gid'] . ':' . $u['members'] . php_eol; break; case 'shadow': $line = $u['username'] . ':' . $u['password'] . ':' . floor(time() / 86400 - 1) . ':0:99999:7:::' . php_eol; break; } $data_content .= $line; } // check local group generate ($type == 'group' &amp;&amp; settings::get('system.froxlorusergroup') != '') { $guid = intval(settings::get('system.froxlorusergroup_gid')); (empty($guid)) { $guid = intval(settings::get('system.lastguid')) + 1; settings::set('system.lastguid', $guid, true); settings::set('system.froxlorusergroup_gid', $guid, true); } $line = settings::get('system.froxlorusergroup') . ':x:' . $guid . ':' . implode(',', $result_list) . php_eol; $data_content .= $line; } (file_put_contents($file, $data_content) !== false) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_notice, 'succesfully wrote ' . $type . ' file'); } else { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_notice, 'error writing ' . $type . ' file entries'); } } private static function cleanstring($string = null) { $allowed = "/[^a-z0-9\\.\\-\\_\\ ]/i"; return preg_replace($allowed, "", $string); } }</file><file name="lib/Froxlor/Cron/System/ExportCron.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\system; use exception; use froxlor\cron\forkable; use froxlor\cron\froxlorcron; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; class exportcron extends froxlorcron { use forkable; public static function run() { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'exportcron: started - creating customer data export'); $result_tasks_stmt = database::query(" select * `" . table_panel_tasks . "` `type` = '20' order `id` asc "); $all_jobs = $result_tasks_stmt-&gt;fetchall(); (!empty($all_jobs)) { self::runfork([self::class, 'handle'], $all_jobs); } } public static function handle(array $row) { $del_stmt = database::prepare("delete `" . table_panel_tasks . "` `id` = :id"); $cronlog = froxlorlogger::getinstanceof(); ($row['data'] != '') { $row['data'] = json_decode($row['data'], true); } (is_array($row['data'])) { (isset($row['data']['customerid']) &amp;&amp; isset($row['data']['loginname']) &amp;&amp; isset($row['data']['destdir'])) { $row['data']['destdir'] = filedir::makecorrectdir($row['data']['destdir']); $customerdocroot = filedir::makecorrectdir(settings::get('system.documentroot_prefix') . '/' . $row['data']['loginname'] . '/'); // create folder exists (!file_exists($row['data']['destdir']) &amp;&amp; $row['data']['destdir'] != '/' &amp;&amp; $row['data']['destdir'] != settings::get('system.documentroot_prefix') &amp;&amp; $row['data']['destdir'] != $customerdocroot) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, 'creating data export destination path customer: ' . escapeshellarg($row['data']['destdir'])); filedir::safe_exec('mkdir -p ' . escapeshellarg($row['data']['destdir'])); } self::createcustomerexport($row['data'], $customerdocroot, $cronlog); } } // remove entry database::pexecute($del_stmt, [ 'id' =&gt; $row['id'] ]); } /** * depending give choice, customers web-data, email-data databases exported * * @param array $data * * @return void * * @throws exception */ private static function createcustomerexport($data = null, $customerdocroot = null, &amp;$cronlog = null) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_notice, 'creating data export user "' . $data['loginname'] . '"'); // create tmp folder $tmpdir = filedir::makecorrectdir($data['destdir'] . '/.tmp/'); $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'creating tmp-folder "' . $tmpdir . '"'); $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'shell&gt; mkdir -p ' . escapeshellarg($tmpdir)); filedir::safe_exec('mkdir -p ' . escapeshellarg($tmpdir)); $create_export_tar_data = ""; // mysql databases ($data['dump_dbs'] == 1) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'creating mysql-folder "' . filedir::makecorrectdir($tmpdir . '/mysql') . '"'); $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'shell&gt; mkdir -p ' . escapeshellarg(filedir::makecorrectdir($tmpdir . '/mysql'))); filedir::safe_exec('mkdir -p ' . escapeshellarg(filedir::makecorrectdir($tmpdir . '/mysql'))); // get customer database-names $sel_stmt = database::prepare("select `databasename`, `dbserver` `" . table_panel_databases . "` `customerid` = :cid order `dbserver`"); database::pexecute($sel_stmt, [ 'cid' =&gt; $data['customerid'] ]); $has_dbs = false; $current_dbserver = -1; // look mysqldump $section = 'mysqldump'; (file_exists("/usr/bin/mysqldump")) { $mysql_dump = '/usr/bin/mysqldump'; } elseif (file_exists("/usr/local/bin/mysqldump")) { $mysql_dump = '/usr/local/bin/mysqldump'; } elseif (file_exists("/usr/bin/mariadb-dump")) { $mysql_dump = '/usr/bin/mariadb-dump'; $section = 'mariadb-dump'; } (!isset($mysql_dump)) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_err, 'mysqldump/mariadb-dump executable could found. please install mysql-client/mariadb-client package.'); } else { ($row = $sel_stmt-&gt;fetch()) { // get sql_root data specific database-server database resides ($current_dbserver != $row['dbserver']) { database::needroot(true, $row['dbserver']); database::needsqldata(); $sql_root = database::getsqldata(); database::needroot(false); // create temporary mysql-defaults file connection-credentials/details $mysqlcnf_file = tempnam("/tmp", "frx"); $mysqlcnf = "[".$section."]\npassword=" . $sql_root['passwd'] . "\nhost=" . $sql_root['host'] . "\n"; (!empty($sql_root['port'])) { $mysqlcnf .= "port=" . $sql_root['port'] . "\n"; } elseif (!empty($sql_root['socket'])) { $mysqlcnf .= "socket=" . $sql_root['socket'] . "\n"; } file_put_contents($mysqlcnf_file, $mysqlcnf); } $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'shell&gt; '.basename($mysql_dump) . ' -u ' . escapeshellarg($sql_root['user']) . ' -pxxxxx ' . $row['databasename'] . ' &gt; ' . filedir::makecorrectfile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('ymdhi', time()) . '.sql')); $bool_false = false; filedir::safe_exec($mysql_dump . ' --defaults-file=' . escapeshellarg($mysqlcnf_file) . ' -u ' . escapeshellarg($sql_root['user']) . ' ' . $row['databasename'] . ' &gt; ' . filedir::makecorrectfile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('ymdhi', time()) . '.sql'), $bool_false, [ '&gt;' ]); $has_dbs = true; $current_dbserver = $row['dbserver']; } } ($has_dbs) { $create_export_tar_data .= './mysql '; } (file_exists($mysqlcnf_file)) { unlink($mysqlcnf_file); } unset($sql_root); } // e-mail data ($data['dump_mail'] == 1) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'creating mail-folder "' . filedir::makecorrectdir($tmpdir . '/mail') . '"'); filedir::safe_exec('mkdir -p ' . escapeshellarg(filedir::makecorrectdir($tmpdir . '/mail'))); // get customer mail-accounts $sel_stmt = database::prepare("select `homedir`, `maildir` `" . table_mail_users . "` `customerid` = :cid"); database::pexecute($sel_stmt, [ 'cid' =&gt; $data['customerid'] ]); $tar_file_list = ""; $mail_homedir = ""; ($row = $sel_stmt-&gt;fetch()) { $tar_file_list .= escapeshellarg("./" . $row['maildir']) . " "; $mail_homedir = $row['homedir']; } (!empty($tar_file_list)) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'shell&gt; tar cfvz ' . escapeshellarg(filedir::makecorrectfile($tmpdir . '/mail/' . $data['loginname'] . '-mail.tar.gz')) . ' -c ' . escapeshellarg($mail_homedir) . ' ' . trim($tar_file_list)); filedir::safe_exec('tar cfz ' . escapeshellarg(filedir::makecorrectfile($tmpdir . '/mail/' . $data['loginname'] . '-mail.tar.gz')) . ' -c ' . escapeshellarg($mail_homedir) . ' ' . trim($tar_file_list)); $create_export_tar_data .= './mail '; } } // web data ($data['dump_web'] == 1) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'creating web-folder "' . filedir::makecorrectdir($tmpdir . '/web') . '"'); filedir::safe_exec('mkdir -p ' . escapeshellarg(filedir::makecorrectdir($tmpdir . '/web'))); $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'shell&gt; tar cfz ' . escapeshellarg(filedir::makecorrectfile($tmpdir . '/web/' . $data['loginname'] . '-web.tar.gz')) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", filedir::makecorrectfile($tmpdir . '/*'))) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", substr(filedir::makecorrectdir($tmpdir), 0, -1))) . ' -c ' . escapeshellarg($customerdocroot) . ' .'); filedir::safe_exec('tar cfz ' . escapeshellarg(filedir::makecorrectfile($tmpdir . '/web/' . $data['loginname'] . '-web.tar.gz')) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", filedir::makecorrectfile($tmpdir . '/*'))) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", substr(filedir::makecorrectfile($tmpdir), 0, -1))) . ' -c ' . escapeshellarg($customerdocroot) . ' .'); $create_export_tar_data .= './web '; } (!empty($create_export_tar_data)) { // set owner customer $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'shell&gt; chown -r ' . (int)$data['uid'] . ':' . (int)$data['gid'] . ' ' . escapeshellarg($tmpdir)); filedir::safe_exec('chown -r ' . (int)$data['uid'] . ':' . (int)$data['gid'] . ' ' . escapeshellarg($tmpdir)); // create tar-file $export_file = filedir::makecorrectfile($tmpdir . '/' . $data['loginname'] . '-export_' . date('ymdhi', time()) . '.tar.gz' . (!empty($data['pgp_public_key']) ? '.gpg' : '')); $cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, 'creating export-file "' . $export_file . '"'); (!empty($data['pgp_public_key'])) { // pack archives tmp-dir one archive encrypt gpg $recipient_file = filedir::makecorrectfile($tmpdir . '/' . $data['loginname'] . '-recipients.gpg'); $cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, 'creating recipient-file "' . $recipient_file . '"'); file_put_contents($recipient_file, $data['pgp_public_key']); $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'shell&gt; tar cfz - -c ' . escapeshellarg($tmpdir) . ' ' . trim($create_export_tar_data) . ' | gpg --encrypt --recipient-file ' . escapeshellarg($recipient_file) . ' --output ' . escapeshellarg($export_file) . ' --trust-model always --batch --yes'); filedir::safe_exec('tar cfz - -c ' . escapeshellarg($tmpdir) . ' ' . trim($create_export_tar_data) . ' | gpg --encrypt --recipient-file ' . escapeshellarg($recipient_file) . ' --output ' . escapeshellarg($export_file) . ' --trust-model always --batch --yes', $return_value, ['|']); } else { // pack archives tmp-dir one archive $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'shell&gt; tar cfz ' . escapeshellarg($export_file) . ' -c ' . escapeshellarg($tmpdir) . ' ' . trim($create_export_tar_data)); filedir::safe_exec('tar cfz ' . escapeshellarg($export_file) . ' -c ' . escapeshellarg($tmpdir) . ' ' . trim($create_export_tar_data)); } // move destination directory $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'shell&gt; mv ' . escapeshellarg($export_file) . ' ' . escapeshellarg($data['destdir'])); filedir::safe_exec('mv ' . escapeshellarg($export_file) . ' ' . escapeshellarg($data['destdir'])); // remove tmp-files $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'shell&gt; rm -rf ' . escapeshellarg($tmpdir)); filedir::safe_exec('rm -rf ' . escapeshellarg($tmpdir)); // set owner customer $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, 'shell&gt; chown -r ' . (int)$data['uid'] . ':' . (int)$data['gid'] . ' ' . escapeshellarg($data['destdir'])); filedir::safe_exec('chown -r ' . (int)$data['uid'] . ':' . (int)$data['gid'] . ' ' . escapeshellarg($data['destdir'])); } } }</file><file name="lib/Froxlor/Cron/System/index.html" /><file name="lib/Froxlor/Cron/Dns/PowerDNS.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\dns; use froxlor\dns\dns; use froxlor\dns\dnszone; use froxlor\froxlorlogger; use froxlor\settings; use pdo; class powerdns extends dnsbase { public function writeconfigs() { // tell world $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'task4 started - refreshing dns database'); $domains = $this-&gt;getdomainlist(); // clean $this-&gt;clearzonetables($domains); (empty($domains)) { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'no domains found nameserver-config, creating zones...'); } else { foreach ($domains $domain) { ($domain['is_child']) { // domains subdomains main domains handled recursion within walkdomainlist() continue; } $this-&gt;walkdomainlist($domain, $domains); } } $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'powerdns database updated'); $this-&gt;reloaddaemon(); $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'task4 finished'); } private function clearzonetables($domains = null) { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'cleaning dns zone entries database'); $pdns_domains_stmt = \froxlor\dns\powerdns::getdb()-&gt;prepare("select `id`, `name` `domains` `name` = :domain"); $del_rec_stmt = \froxlor\dns\powerdns::getdb()-&gt;prepare("delete `records` `domain_id` = :did"); $del_meta_stmt = \froxlor\dns\powerdns::getdb()-&gt;prepare("delete `domainmetadata` `domain_id` = :did"); $del_dom_stmt = \froxlor\dns\powerdns::getdb()-&gt;prepare("delete `domains` `id` = :did"); foreach ($domains $domain) { $pdns_domains_stmt-&gt;execute([ 'domain' =&gt; $domain['domain'] ]); $pdns_domain = $pdns_domains_stmt-&gt;fetch(pdo::fetch_assoc); ($pdns_domain &amp;&amp; !empty($pdns_domain['id'])) { $del_rec_stmt-&gt;execute([ 'did' =&gt; $pdns_domain['id'] ]); $del_meta_stmt-&gt;execute([ 'did' =&gt; $pdns_domain['id'] ]); $del_dom_stmt-&gt;execute([ 'did' =&gt; $pdns_domain['id'] ]); } } } private function walkdomainlist($domain, $domains) { $zonecontent = ''; $subzones = []; foreach ($domain['children'] $child_domain_id) { $subzones[] = $this-&gt;walkdomainlist($domains[$child_domain_id], $domains); } ($domain['zonefile'] == '') { // check system-hostname $isfroxlorhostname = false; (isset($domain['froxlorhost']) &amp;&amp; $domain['froxlorhost'] == 1) { $isfroxlorhostname = true; } (!$domain['is_child']) { $zonecontent = dns::createdomainzone(($domain['id'] == 'none') ? $domain : $domain['id'], $isfroxlorhostname); (count($subzones)) { foreach ($subzones $subzone) { $zonecontent-&gt;records[] = $subzone; } } $pdnsdomid = $this-&gt;insertzone($zonecontent-&gt;origin, $zonecontent-&gt;serial); $this-&gt;insertrecords($pdnsdomid, $zonecontent-&gt;records, $zonecontent-&gt;origin); $this-&gt;insertallowedtransfers($pdnsdomid); $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'db entries stored zone `' . $domain['domain'] . '`'); } else { return dns::createdomainzone(($domain['id'] == 'none') ? $domain : $domain['id'], $isfroxlorhostname, true); } } else { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_err, 'custom zonefiles supported powerdns selected dns daemon (triggered by: ' . $domain['domain'] . ')'); } } private function insertzone($domainname, $serial = 0) { $ins_stmt = \froxlor\dns\powerdns::getdb()-&gt;prepare(" insert domains set `name` = :domainname, `notified_serial` = :serial, `type` = :type "); $ins_stmt-&gt;execute([ 'domainname' =&gt; $domainname, 'serial' =&gt; $serial, 'type' =&gt; strtoupper(settings::get('system.powerdns_mode')) ]); $lastid = \froxlor\dns\powerdns::getdb()-&gt;lastinsertid(); return $lastid; } private function insertrecords($domainid = 0, $records = [], $origin = "") { $ins_stmt = \froxlor\dns\powerdns::getdb()-&gt;prepare(" insert records set `domain_id` = :did, `name` = :rec, `type` = :type, `content` = :content, `ttl` = :ttl, `prio` = :prio, `disabled` = '0' "); foreach ($records $record) { ($record instanceof dnszone) { $this-&gt;insertrecords($domainid, $record-&gt;records, $record-&gt;origin); continue; } ($record-&gt;record == '@') { $_record = $origin; } else { $_record = $record-&gt;record . "." . $origin; } $ins_data = [ 'did' =&gt; $domainid, 'rec' =&gt; $_record, 'type' =&gt; $record-&gt;type, 'content' =&gt; $record-&gt;content, 'ttl' =&gt; $record-&gt;ttl, 'prio' =&gt; $record-&gt;priority ]; $ins_stmt-&gt;execute($ins_data); } } private function insertallowedtransfers($domainid) { $ins_stmt = \froxlor\dns\powerdns::getdb()-&gt;prepare(" insert domainmetadata set `domain_id` = :did, `kind` = 'allow-axfr-from', `content` = :value "); $ins_data = [ 'did' =&gt; $domainid ]; (count($this-&gt;ns) &gt; 0 || count($this-&gt;axfr) &gt; 0) { // put nameservers allow-transfer (count($this-&gt;ns) &gt; 0) { foreach ($this-&gt;ns $ns) { foreach ($ns["ips"] $ip) { $ins_data['value'] = $ip; $ins_stmt-&gt;execute($ins_data); } } } // axfr server #100 (count($this-&gt;axfr) &gt; 0) { foreach ($this-&gt;axfr $axfrserver) { $ins_data['value'] = $axfrserver; $ins_stmt-&gt;execute($ins_data); } } } } }</file><file name="lib/Froxlor/Cron/Dns/DnsBase.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\dns; use froxlor\database\database; use froxlor\domain\domain; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\settings; use pdo; /** * class dnsbase * * base class dns server configs */ abstract class dnsbase { protected $logger = false; protected $ns = []; protected $mx = []; protected $axfr = []; public function __construct($logger) { $this-&gt;logger = $logger; $known_ns_ips = []; (settings::get('system.nameservers') != '') { $nameservers = explode(',', settings::get('system.nameservers')); foreach ($nameservers $nameserver) { $nameserver = trim($nameserver); // dns servers might multi homed; allow transfer ip // addresses dns server $nameserver_ips = phphelper::gethostbynamel6($nameserver); // append dot hostname (substr($nameserver, -1, 1) != '.') { $nameserver .= '.'; } // ignore invalid responses (!is_array($nameserver_ips)) { // act like \froxlor\phphelper::gethostbynamel6() return unmodified hostname error $nameserver_ips = [ $nameserver ]; } else { $known_ns_ips = array_merge($known_ns_ips, $nameserver_ips); } $this-&gt;ns[] = [ 'hostname' =&gt; $nameserver, 'ips' =&gt; $nameserver_ips ]; } } (settings::get('system.mxservers') != '') { $mxservers = explode(',', settings::get('system.mxservers')); foreach ($mxservers $mxserver) { (substr($mxserver, -1, 1) != '.') { $mxserver .= '.'; } $this-&gt;mx[] = $mxserver; } } // axfr server #100 (settings::get('system.axfrservers') != '') { $axfrservers = explode(',', settings::get('system.axfrservers')); foreach ($axfrservers $axfrserver) { (!in_array(trim($axfrserver), $known_ns_ips)) { $this-&gt;axfr[] = trim($axfrserver); } } } } abstract public function writeconfigs(); public function reloaddaemon() { // reload dns daemon $cmd = settings::get('system.bindreload_command'); $cmdstatus = 1; filedir::safe_exec(escapeshellcmd($cmd), $cmdstatus); ($cmdstatus === 0) { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, settings::get('system.dns_server') . ' daemon reloaded'); } else { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_err, 'error running `' . $cmd . '`: exit code (' . $cmdstatus . ') - please check system logs'); } } protected function getdomainlist() { $result_domains_stmt = database::query(" select `d`.`id`, `d`.`domain`, `d`.`isemaildomain`, `d`.`iswildcarddomain`, `d`.`wwwserveralias`, `d`.`customerid`, `d`.`zonefile`, `d`.`bindserial`, `d`.`dkim`, `d`.`dkim_id`, `d`.`dkim_pubkey`, `c`.`loginname`, `c`.`guid` `" . table_panel_domains . "` `d` left join `" . table_panel_customers . "` `c` using(`customerid`) `d`.`isbinddomain` = '1' order length(`d`.`domain`), `d`.`domain` asc "); $domains = []; // use fetchall() able set first column domain id use later set rows' // array direct children without search outer array ($domain = $result_domains_stmt-&gt;fetch(pdo::fetch_assoc)) { $domains[$domain["id"]] = $domain; } // frolxor-hostname (#1090) (settings::get('system.dns_createhostnameentry') == 1) { $hostname_arr = [ 'id' =&gt; 'none', 'domain' =&gt; settings::get('system.hostname'), 'isbinddomain' =&gt; '1', 'isemaildomain' =&gt; settings::get('system.dns_createmailentry'), 'customerid' =&gt; 'none', 'loginname' =&gt; 'froxlor.panel', 'bindserial' =&gt; date('ymd') . '00', 'dkim' =&gt; '0', 'iswildcarddomain' =&gt; '1', 'zonefile' =&gt; '', 'froxlorhost' =&gt; '1' ]; $domains[0] = $hostname_arr; } (empty($domains)) { return null; } // collect domain ids direct child domains arrays ['children'] column foreach (array_keys($domains) $key) { (!isset($domains[$key]['children'])) { $domains[$key]['children'] = []; } (!isset($domains[$key]['is_child'])) { $domains[$key]['is_child'] = false; } $children = domain::getmainsubdomainids($key); (count($children) &gt; 0) { foreach ($children $child) { (isset($domains[$child])) { $domains[$key]['children'][] = $domains[$child]['id']; $domains[$child]['is_child'] = true; } } } } $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_debug, str_pad('domid', 9, ' ') . str_pad('domain', 40, ' ') . "list child domain ids"); foreach ($domains $domain) { $logline = str_pad($domain['id'], 9, ' ') . str_pad($domain['domain'], 40, ' ') . join(', ', $domain['children']); $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_debug, $logline); } return $domains; } }</file><file name="lib/Froxlor/Cron/Dns/Bind.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\dns; use froxlor\dns\dns; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\validate\validate; use recursivedirectoryiterator; use recursiveiteratoriterator; class bind extends dnsbase { private $bindconf_file = ""; public function writeconfigs() { // tell world $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'task4 started - rebuilding froxlor_bind.conf'); // clean $this-&gt;cleanzonefiles(); // check subfolder bind-config-directory (!file_exists(filedir::makecorrectdir(settings::get('system.bindconf_directory') . '/domains/'))) { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_notice, 'mkdir ' . escapeshellarg(filedir::makecorrectdir(settings::get('system.bindconf_directory') . '/domains/'))); filedir::safe_exec('mkdir -p ' . escapeshellarg(filedir::makecorrectdir(settings::get('system.bindconf_directory') . '/domains/'))); } $domains = $this-&gt;getdomainlist(); (empty($domains)) { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'no domains found nameserver-config, creating zones...'); $this-&gt;bindconf_file = ''; } else { $this-&gt;bindconf_file = '# ' . settings::get('system.bindconf_directory') . 'froxlor_bind.conf' . "\n" . '# created ' . date('d.m.y h:i') . "\n" . '# manually edit file, changes deleted next domain change panel.' . "\n\n"; foreach ($domains $domain) { ($domain['is_child']) { // domains subdomains main domains handled recursion within walkdomainlist() continue; } $this-&gt;walkdomainlist($domain, $domains); } } $bindconf_file_handler = fopen(filedir::makecorrectfile(settings::get('system.bindconf_directory') . '/froxlor_bind.conf'), 'w'); fwrite($bindconf_file_handler, $this-&gt;bindconf_file); fclose($bindconf_file_handler); $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'froxlor_bind.conf written'); $this-&gt;reloaddaemon(); $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'task4 finished'); } private function cleanzonefiles() { $config_dir = filedir::makecorrectfile(settings::get('system.bindconf_directory') . '/domains/'); $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'cleaning dns zone files ' . $config_dir); // check directory (@is_dir($config_dir)) { // create directory iterator $its = new recursiveiteratoriterator(new recursivedirectoryiterator($config_dir)); // iterate subdirs, look zone files delete foreach ($its $it) { ($it-&gt;isfile()) { // remove file filedir::safe_exec('rm -f ' . escapeshellarg(filedir::makecorrectfile($its-&gt;getpathname()))); } } } } private function walkdomainlist($domain, $domains) { $zonecontent = ''; $subzones = ''; foreach ($domain['children'] $child_domain_id) { $subzones .= $this-&gt;walkdomainlist($domains[$child_domain_id], $domains); } ($domain['zonefile'] == '') { // check system-hostname $isfroxlorhostname = false; (isset($domain['froxlorhost']) &amp;&amp; $domain['froxlorhost'] == 1) { $isfroxlorhostname = true; } (!$domain['is_child']) { $zonecontent = (string)dns::createdomainzone(($domain['id'] == 'none') ? $domain : $domain['id'], $isfroxlorhostname); $domain['zonefile'] = 'domains/' . $domain['domain'] . '.zone'; $zonefile_name = filedir::makecorrectfile(settings::get('system.bindconf_directory') . '/' . $domain['zonefile']); $zonefile_handler = fopen($zonefile_name, 'w'); fwrite($zonefile_handler, $zonecontent . $subzones); fclose($zonefile_handler); $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, '`' . $zonefile_name . '` written'); $this-&gt;bindconf_file .= $this-&gt;generatedomainconfig($domain); } else { return (string)dns::createdomainzone(($domain['id'] == 'none') ? $domain : $domain['id'], $isfroxlorhostname, true); } } else { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'added zonefile ' . $domain['zonefile'] . ' domain ' . $domain['domain'] . ' - note also handle records subdomains.'); $this-&gt;bindconf_file .= $this-&gt;generatedomainconfig($domain); } } private function generatedomainconfig($domain = []) { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_debug, 'generating dns config ' . $domain['domain']); $bindconf_file = '# domain id: ' . $domain['id'] . ' - customerid: ' . $domain['customerid'] . ' - customerlogin: ' . $domain['loginname'] . "\n"; $bindconf_file .= 'zone "' . $domain['domain'] . '" {' . "\n"; $bindconf_file .= ' type master;' . "\n"; $bindconf_file .= ' file "' . filedir::makecorrectfile(settings::get('system.bindconf_directory') . '/' . $domain['zonefile']) . '";' . "\n"; $bindconf_file .= ' allow-query { any; };' . "\n"; (count($this-&gt;ns) &gt; 0 || count($this-&gt;axfr) &gt; 0) { // open allow-transfer $bindconf_file .= ' allow-transfer {' . "\n"; // put nameservers allow-transfer (count($this-&gt;ns) &gt; 0) { foreach ($this-&gt;ns $ns) { foreach ($ns["ips"] $ip) { $ip = validate::validate_ip2($ip, true, 'invalidip', true, true, true); ($ip) { $bindconf_file .= ' ' . $ip . ";\n"; } } } } // axfr server #100 (count($this-&gt;axfr) &gt; 0) { foreach ($this-&gt;axfr $axfrserver) { $bindconf_file .= ' ' . $axfrserver . ';' . "\n"; } } // close allow-transfer $bindconf_file .= ' };' . "\n"; } $bindconf_file .= '};' . "\n"; $bindconf_file .= "\n"; return $bindconf_file; } }</file><file name="lib/Froxlor/Cron/Dns/index.html" /><file name="lib/Froxlor/Cron/Http/DomainSSL.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; class domainssl { /** * read domain-related (or empty, parentdomain-related) ssl-certificates database * (if empty) set corresponding array-indices (ssl_cert_file, ssl_key_file, * ssl_ca_file ssl_cert_chainfile). * hence parameter reference. * * @param array $domain * domain-array reference set corresponding array-indices * * @return null * @throws \exception */ public function setdomainsslfilesarray(array &amp;$domain = null) { // check domain certificate defined $dom_certs_stmt = database::prepare(" select s.*, d.domain `" . table_panel_domain_ssl_settings . "` left join `" . table_panel_domains . "` d.id = s.domainid s.`domainid` = :domid "); $dom_certs = database::pexecute_first($dom_certs_stmt, [ 'domid' =&gt; $domain['id'] ]); $parent_certificate = false; (!is_array($dom_certs) || !isset($dom_certs['ssl_cert_file']) || $dom_certs['ssl_cert_file'] == '') { // maybe parent? (isset($domain['parentdomainid']) &amp;&amp; $domain['parentdomainid'] != 0) { $dom_certs = database::pexecute_first($dom_certs_stmt, [ 'domid' =&gt; $domain['parentdomainid'] ]); $parent_certificate = true; } } // check array important field set (is_array($dom_certs) &amp;&amp; isset($dom_certs['ssl_cert_file']) &amp;&amp; $dom_certs['ssl_cert_file'] != '') { // get destination path $sslcertpath = filedir::makecorrectdir(settings::get('system.customer_ssl_path')); // create path exist (!file_exists($sslcertpath)) { filedir::safe_exec('mkdir -p ' . escapeshellarg($sslcertpath)); } // make correct files certificates $ssl_files = [ 'ssl_cert_file' =&gt; filedir::makecorrectfile($sslcertpath . '/' . ($parent_certificate ? $dom_certs['domain'] : $domain['domain']) . '.crt'), 'ssl_key_file' =&gt; filedir::makecorrectfile($sslcertpath . '/' . ($parent_certificate ? $dom_certs['domain'] : $domain['domain']) . '.key') ]; (!$this-&gt;validatecertificate($dom_certs)) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, 'given ssl private key ' . $domain['domain'] . ' seem match certificate. cannot create ssl-directives'); return; } (settings::get('system.webserver') == 'lighttpd') { // put my.crt my.key together lighty. $dom_certs['ssl_cert_file'] = trim($dom_certs['ssl_cert_file']) . "\n" . trim($dom_certs['ssl_key_file']) . "\n"; $ssl_files['ssl_key_file'] = ''; } // initialize optional files $ssl_files['ssl_ca_file'] = ''; $ssl_files['ssl_cert_chainfile'] = ''; // set != empty ($dom_certs['ssl_ca_file'] != '') { $ssl_files['ssl_ca_file'] = filedir::makecorrectfile($sslcertpath . '/' . ($parent_certificate ? $dom_certs['domain'] : $domain['domain']) . '_ca.pem'); } ($dom_certs['ssl_cert_chainfile'] != '') { (settings::get('system.webserver') == 'nginx') { // put ca.crt my.crt, nginx support separate chain file. $dom_certs['ssl_cert_file'] = trim($dom_certs['ssl_cert_file']) . "\n" . trim($dom_certs['ssl_cert_chainfile']) . "\n"; } else { $ssl_files['ssl_cert_chainfile'] = filedir::makecorrectfile($sslcertpath . '/' . ($parent_certificate ? $dom_certs['domain'] : $domain['domain']) . '_chain.pem'); } } // generated used externally, froxlor need ($dom_certs['ssl_fullchain_file'] != '') { $ssl_files['ssl_fullchain_file'] = filedir::makecorrectfile($sslcertpath . '/' . ($parent_certificate ? $dom_certs['domain'] : $domain['domain']) . '_fullchain.pem'); } // create filesystem foreach ($ssl_files $type =&gt; $filename) { ($filename != '') { touch($filename); $_fh = fopen($filename, 'w'); fwrite($_fh, $dom_certs[$type]); fclose($_fh); ($type == 'ssl_key_file') { chmod($filename, 0600); } else { chmod($filename, 0644); } } } // override corresponding array values $domain['ssl_cert_file'] = $ssl_files['ssl_cert_file']; $domain['ssl_key_file'] = $ssl_files['ssl_key_file']; $domain['ssl_ca_file'] = $ssl_files['ssl_ca_file']; $domain['ssl_cert_chainfile'] = $ssl_files['ssl_cert_chainfile']; } return; } private function validatecertificate($dom_certs = []): bool { return openssl_x509_check_private_key($dom_certs['ssl_cert_file'], $dom_certs['ssl_key_file']); } }</file><file name="lib/Froxlor/Cron/Http/NginxFcgi.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http; use froxlor\cron\http\php\phpinterface; use froxlor\database\database; use froxlor\filedir; use froxlor\settings; class nginxfcgi extends nginx { public function createownvhoststarter() { (settings::get('phpfpm.enabled') == '1' &amp;&amp; settings::get('phpfpm.enabled_ownvhost') == '1') { $mypath = filedir::makecorrectdir(dirname(__file__, 3)); // /var/www/froxlor, needed chown $user = settings::get('phpfpm.vhost_httpuser'); $group = settings::get('phpfpm.vhost_httpgroup'); // get fpm config $fpm_sel_stmt = database::prepare(" select f.id `" . table_panel_fpmdaemons . "` f left join `" . table_panel_phpconfigs . "` p p.fpmsettingid = f.id p.id = :phpconfigid "); $fpm_config = database::pexecute_first($fpm_sel_stmt, [ 'phpconfigid' =&gt; settings::get('phpfpm.vhost_defaultini') ]); $domain = [ 'id' =&gt; 'none', 'domain' =&gt; settings::get('system.hostname'), 'adminid' =&gt; 1, /* first admin-user (superadmin) */ 'mod_fcgid_starter' =&gt; -1, 'mod_fcgid_maxrequests' =&gt; -1, 'guid' =&gt; $user, 'openbasedir' =&gt; 0, 'email' =&gt; settings::get('panel.adminmail'), 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath, 'fpm_config_id' =&gt; isset($fpm_config['id']) ? $fpm_config['id'] : 1 ]; // files folders belong local user // also use fcgid vhost filedir::safe_exec('chown -r ' . $user . ':' . $group . ' ' . escapeshellarg($mypath)); // get php.ini vhost $php = new phpinterface($domain); // get php-config (settings::get('phpfpm.enabled') == '1') { // fpm $phpconfig = $php-&gt;getphpconfig(settings::get('phpfpm.vhost_defaultini')); } else { // fcgid $phpconfig = $php-&gt;getphpconfig(settings::get('system.mod_fcgid_defaultini_ownvhost')); } // create starter-file | config-file $php-&gt;getinterface()-&gt;createconfig($phpconfig); // create php.ini (fpm nothing here, // defines ini-settings pool config) $php-&gt;getinterface()-&gt;createinifile($phpconfig); } } protected function composephpoptions(&amp;$domain, $ssl_vhost = false) { $php_options_text = ''; ($domain['phpenabled_customer'] == 1 &amp;&amp; $domain['phpenabled_vhost'] == '1') { $php = new phpinterface($domain); $phpconfig = $php-&gt;getphpconfig((int)$domain['phpsettingid']); $php_options_text = "\t" . 'location ~ ^(.+?\.php)(/.*)?$ {' . "\n"; ($domain['notryfiles'] != 1) { $php_options_text .= "\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n"; $php_options_text .= "\t" . '}' . "\n\n"; $php_options_text .= "\t" . 'location @php {' . "\n"; $php_options_text .= "\t\t" . 'try_files $1 =404;' . "\n\n"; } $php_options_text .= "\t\t" . 'include ' . settings::get('nginx.fastcgiparams') . ";\n"; $php_options_text .= "\t\t" . 'fastcgi_split_path_info ^(.+?\.php)(/.*)$;' . "\n"; $php_options_text .= "\t\t" . 'fastcgi_param script_filename $request_filename;' . "\n"; $php_options_text .= "\t\t" . 'fastcgi_param path_info $2;' . "\n"; ($domain['ssl'] == '1' &amp;&amp; $ssl_vhost) { $php_options_text .= "\t\t" . 'fastcgi_param https on;' . "\n"; } $domain['fpm_socket'] = $php-&gt;getinterface()-&gt;getsocketfile(); $php_options_text .= "\t\t" . 'fastcgi_pass unix:' . $domain['fpm_socket'] . ";\n"; $php_options_text .= "\t\t" . 'fastcgi_index index.php;' . "\n"; $php_options_text .= "\t}\n\n"; // create starter-file | config-file $php-&gt;getinterface()-&gt;createconfig($phpconfig); // create php.ini (fpm nothing here, // defines ini-settings pool config) $php-&gt;getinterface()-&gt;createinifile($phpconfig); } else { $php_options_text .= ' # php disabled vhost' . "\n"; } return $php_options_text; } }</file><file name="lib/Froxlor/Cron/Http/Lighttpd.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http; use froxlor\cron\http\php\phpinterface; use froxlor\customer\customer; use froxlor\database\database; use froxlor\domain\domain; use froxlor\froxlor; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\http\directory; use froxlor\http\statistics; use froxlor\settings; use froxlor\validate\validate; use froxlor\system\crypt; use froxlor\idna\idnawrapper; use pdo; class lighttpd extends httpconfigbase { // protected protected $lighttpd_data = []; protected $needed_htpasswds = []; protected $auth_backend_loaded = false; protected $htpasswd_files = []; protected $mod_accesslog_loaded = "0"; /** * indicator whether customer deactivated * yes, webroot generated * * @var bool */ private $deactivated = false; public function createipport() { $result_ipsandports_stmt = database::query("select * `" . table_panel_ipsandports . "` order `ip` asc, `port` asc"); ($row_ipsandports = $result_ipsandports_stmt-&gt;fetch(pdo::fetch_assoc)) { (filter_var($row_ipsandports['ip'], filter_validate_ip, filter_flag_ipv6)) { $ip = '[' . $row_ipsandports['ip'] . ']'; $port = $row_ipsandports['port']; $ipv6 = 'server.use-ipv6 = "enable"' . "\n"; } else { $ip = $row_ipsandports['ip']; $port = $row_ipsandports['port']; $ipv6 = ''; } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'lighttpd::createipport: creating ip/port settings ' . $ip . ":" . $port); $vhost_filename = filedir::makecorrectfile(settings::get('system.apacheconf_vhost') . '/10_froxlor_ipandport_' . trim(str_replace(':', '.', $row_ipsandports['ip']), '.') . '.' . $row_ipsandports['port'] . '.conf'); (!isset($this-&gt;lighttpd_data[$vhost_filename])) { $this-&gt;lighttpd_data[$vhost_filename] = ''; } $this-&gt;lighttpd_data[$vhost_filename] .= '$server["socket"] == "' . $ip . ':' . $port . '" {' . "\n"; ($row_ipsandports['listen_statement'] == '1') { $this-&gt;lighttpd_data[$vhost_filename] .= 'server.port = ' . $port . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= 'server.bind = "' . $ip . '"' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= $ipv6; } ($row_ipsandports['vhostcontainer'] == '1') { $myhost = str_replace('.', '\.', settings::get('system.hostname')); $this-&gt;lighttpd_data[$vhost_filename] .= '# froxlor default vhost' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= '$http["host"] =~ "^(?:www\.|)' . $myhost . '$" {' . "\n"; $mypath = $this-&gt;getmypath($row_ipsandports); $this-&gt;lighttpd_data[$vhost_filename] .= ' server.document-root = "' . $mypath . '"' . "\n"; $is_redirect = false; // check ssl redirect ($row_ipsandports['ssl'] == '0' &amp;&amp; settings::get('system.le_froxlor_redirect') == '1') { $is_redirect = true; // check whether froxlor uses let's encrypt cert generated yet // renew ongoing - disable redirect (settings::get('system.le_froxlor_enabled') &amp;&amp; ($this-&gt;froxlorvhosthasletsencryptcert() == false || $this-&gt;froxlorvhostletsencryptneedsrenew())) { $this-&gt;lighttpd_data[$vhost_filename] .= '# temp. disabled ssl-redirect due let\'s encrypt certificate generation.' . php_eol; $is_redirect = false; } else { $_sslport = $this-&gt;checkalternativesslport(); $mypath = 'https://' . settings::get('system.hostname') . $_sslport . '/'; $this-&gt;lighttpd_data[$vhost_filename] .= ' url.redirect = (' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= ' "^/(.*)$" =&gt; "' . $mypath . '$1"' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= ' )' . "\n"; } } (!$is_redirect) { (settings::get('system.froxlordirectlyviahostname')) { $relpath = "/"; } else { $relpath = "/".basename(froxlor::getinstalldir()); } // protect lib/userdata.inc.php $this-&gt;lighttpd_data[$vhost_filename] .= ' $http["url"] =~ "' . rtrim($relpath, "/") . '/lib" {' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= ' url.access-deny = ("userdata.inc.php")' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= ' }' . "\n"; // protect bin/ $this-&gt;lighttpd_data[$vhost_filename] .= ' $http["url"] =~ "^' . rtrim($relpath, "/") . '/(bin|cache|logs|tests|vendor)" {' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= ' url.access-deny = ("")' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= ' }' . "\n"; /** * dirprotection, see #72 * * @todo use better regex this, deferred 0.9.5 * * $this-&gt;lighttpd_data[$vhost_filename].= ' $http["url"] =~ "^/(.+)\/(.+)\.php" {' . "\n"; * $this-&gt;lighttpd_data[$vhost_filename].= ' url.access-deny = ("")' . "\n"; * $this-&gt;lighttpd_data[$vhost_filename].= ' }' . "\n"; */ /** * php-fpm vhost */ ((int)settings::get('phpfpm.enabled') == 1 &amp;&amp; (int)settings::get('phpfpm.enabled_ownvhost') == 1) { // get fpm config $fpm_sel_stmt = database::prepare(" select f.id `" . table_panel_fpmdaemons . "` f left join `" . table_panel_phpconfigs . "` p p.fpmsettingid = f.id p.id = :phpconfigid "); $fpm_config = database::pexecute_first($fpm_sel_stmt, [ 'phpconfigid' =&gt; settings::get('phpfpm.vhost_defaultini') ]); $domain = [ 'id' =&gt; 'none', 'domain' =&gt; settings::get('system.hostname'), 'adminid' =&gt; 1, /* first admin-user (superadmin) */ 'mod_fcgid_starter' =&gt; -1, 'mod_fcgid_maxrequests' =&gt; -1, 'guid' =&gt; settings::get('phpfpm.vhost_httpuser'), 'openbasedir' =&gt; 0, 'email' =&gt; settings::get('panel.adminmail'), 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath, 'fpm_config_id' =&gt; isset($fpm_config['id']) ? $fpm_config['id'] : 1 ]; $php = new phpinterface($domain); $this-&gt;lighttpd_data[$vhost_filename] .= ' fastcgi.server = ( ' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= "\t" . '".php" =&gt; (' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= "\t\t" . '"localhost" =&gt; (' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= "\t\t" . '"socket" =&gt; "' . $php-&gt;getinterface()-&gt;getsocketfile() . '",' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= "\t\t" . '"check-local" =&gt; "enable",' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= "\t\t" . '"disable-time" =&gt; 1' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= "\t" . ')' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= "\t" . ')' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= ' )' . "\n"; } else { $domain = [ 'id' =&gt; 'none', 'domain' =&gt; settings::get('system.hostname'), 'adminid' =&gt; 1, /* first admin-user (superadmin) */ 'guid' =&gt; settings::get('system.httpuser'), 'openbasedir' =&gt; 0, 'email' =&gt; settings::get('panel.adminmail'), 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath ]; } } else { // fallback froxlor domain-data processspecialconfigtemplate() $domain = [ 'domain' =&gt; settings::get('system.hostname'), 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath ]; } ($row_ipsandports['specialsettings'] != '' &amp;&amp; ($row_ipsandports['ssl'] == '0' || ($row_ipsandports['ssl'] == '1' &amp;&amp; settings::get('system.use_ssl') == '1' &amp;&amp; $row_ipsandports['include_specialsettings'] == '1'))) { $this-&gt;lighttpd_data[$vhost_filename] .= $this-&gt;processspecialconfigtemplate($row_ipsandports['specialsettings'], $domain, $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n"; } $this-&gt;lighttpd_data[$vhost_filename] .= '}' . "\n"; } ($row_ipsandports['ssl'] == '1') { ($row_ipsandports['ssl_specialsettings'] != '') { $this-&gt;lighttpd_data[$vhost_filename] .= $this-&gt;processspecialconfigtemplate($row_ipsandports['ssl_specialsettings'], $domain, $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n"; } // check required fallback (($row_ipsandports['ssl_cert_file'] == '' || !file_exists($row_ipsandports['ssl_cert_file'])) &amp;&amp; (settings::get('system.le_froxlor_enabled') == '0' || $this-&gt;froxlorvhosthasletsencryptcert() == false)) { $row_ipsandports['ssl_cert_file'] = settings::get('system.ssl_cert_file'); (!file_exists($row_ipsandports['ssl_cert_file'])) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, 'system certificate file "' . settings::get('system.ssl_cert_file') . '" seem exist. creating self-signed certificate...'); crypt::createselfsignedcertificate(); } } ($row_ipsandports['ssl_key_file'] == '') { $row_ipsandports['ssl_key_file'] = settings::get('system.ssl_key_file'); (!file_exists($row_ipsandports['ssl_key_file'])) { // explicitly disable ssl vhost $row_ipsandports['ssl_cert_file'] = ""; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, 'system certificate key-file "' . settings::get('system.ssl_key_file') . '" seem exist. disabling ssl-vhost "' . settings::get('system.hostname') . '"'); } } ($row_ipsandports['ssl_ca_file'] == '') { $row_ipsandports['ssl_ca_file'] = settings::get('system.ssl_ca_file'); } $domain = [ 'id' =&gt; 0, 'domain' =&gt; settings::get('system.hostname'), 'adminid' =&gt; 1, /* first admin-user (superadmin) */ 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath, 'parentdomainid' =&gt; 0 ]; // override corresponding array values $domain['ssl_cert_file'] = $row_ipsandports['ssl_cert_file']; $domain['ssl_key_file'] = $row_ipsandports['ssl_key_file']; $domain['ssl_ca_file'] = $row_ipsandports['ssl_ca_file']; $domain['ssl_cert_chainfile'] = $row_ipsandports['ssl_cert_chainfile']; // ssl stuff $dssl = new domainssl(); // sets ssl-related array-indices $domain array // domain customer-defined ssl-certificates $dssl-&gt;setdomainsslfilesarray($domain); ($domain['ssl_cert_file'] != '') { // check existence, #1485 (!file_exists($domain['ssl_cert_file'])) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, $ip . ':' . $port . ' :: certificate file "' . $domain['ssl_cert_file'] . '" exist! cannot create ssl-directives'); echo $ip . ':' . $port . ' :: certificate file "' . $domain['ssl_cert_file'] . '" exist! cannot create ssl-directives' . "\n"; } else { $this-&gt;lighttpd_data[$vhost_filename] .= 'ssl.engine = "enable"' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= 'ssl.use-compression = "disable"' . "\n"; (!empty(settings::get('system.dhparams_file'))) { $dhparams = filedir::makecorrectfile(settings::get('system.dhparams_file')); (!file_exists($dhparams)) { file_put_contents($dhparams, self::ffdhe4096); } $this-&gt;lighttpd_data[$vhost_filename] .= 'ssl.dh-file = "' . $dhparams . '"' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= 'ssl.ec-curve = "secp384r1"' . "\n"; } $this-&gt;lighttpd_data[$vhost_filename] .= 'ssl.use-sslv2 = "disable"' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= 'ssl.use-sslv3 = "disable"' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= 'ssl.cipher-list = "' . settings::get('system.ssl_cipher_list') . '"' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= 'ssl.honor-cipher-order = "enable"' . "\n"; $this-&gt;lighttpd_data[$vhost_filename] .= 'ssl.pemfile = "' . filedir::makecorrectfile($domain['ssl_cert_file']) . '"' . "\n"; ($domain['ssl_ca_file'] != '') { // check existence, #1485 (!file_exists($domain['ssl_ca_file'])) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, $ip . ':' . $port . ' :: certificate ca file "' . $domain['ssl_ca_file'] . '" exist! cannot create ssl-directives'); echo $ip . ':' . $port . ' :: certificate ca file "' . $domain['ssl_ca_file'] . '" exist! ssl-directives might working' . "\n"; } else { $this-&gt;lighttpd_data[$vhost_filename] .= 'ssl.ca-file = "' . filedir::makecorrectfile($domain['ssl_ca_file']) . '"' . "\n"; } } } } } /** * function create new file included * settings::get('system.apacheconf_vhost') folder * refs #70 */ $vhosts = $this-&gt;createlighttpdhosts($row_ipsandports['id'], $row_ipsandports['ssl'], $vhost_filename); ($vhosts !== null &amp;&amp; is_array($vhosts) &amp;&amp; isset($vhosts[0])) { // sort vhosts number (subdomains first!) sort($vhosts); foreach ($vhosts $vhost) { $this-&gt;lighttpd_data[$vhost_filename] .= ' include "' . $vhost . '"' . "\n"; } } $this-&gt;lighttpd_data[$vhost_filename] .= '}' . "\n"; } /** * bug #unknown-yet */ $this-&gt;createstandarderrorhandler(); } protected function createlighttpdhosts($ipid, $ssl, $vhost_filename) { $domains = webserverbase::getvhoststocreate(); $included_vhosts = []; foreach ($domains $domain) { (is_dir(settings::get('system.apacheconf_vhost'))) { filedir::safe_exec('mkdir -p ' . escapeshellarg(filedir::makecorrectdir(settings::get('system.apacheconf_vhost') . '/vhosts/'))); // determine correct include-path: // e.g. '/etc/lighttpd/conf-enabled/vhosts/ become' // 'conf-enabled/vhosts/' (damn debian, luckily works distros) $_tmp_path = substr(filedir::makecorrectdir(settings::get('system.apacheconf_vhost')), 0, -1); $_pos = strrpos($_tmp_path, '/'); $_inc_path = substr($_tmp_path, $_pos + 1); $filename = self::getvhostfilename($domain, ($ssl == '1'), true); $vhost_filename = filedir::makecorrectfile(settings::get('system.apacheconf_vhost') . '/vhosts/' . $filename); $included_vhosts[] = $_inc_path . '/vhosts/' . $filename; } (!isset($this-&gt;lighttpd_data[$vhost_filename])) { $this-&gt;lighttpd_data[$vhost_filename] = ''; } ((!empty($this-&gt;lighttpd_data[$vhost_filename]) &amp;&amp; !is_dir(settings::get('system.apacheconf_vhost'))) || is_dir(settings::get('system.apacheconf_vhost'))) { ($ssl == '1') { $ssl_vhost = true; } else { $ssl_vhost = false; } // fixme get duplicate entries vhost assigned one ip // checking lightt_data filename empty *might* correct ($this-&gt;lighttpd_data[$vhost_filename] == '') { $this-&gt;lighttpd_data[$vhost_filename] .= $this-&gt;getvhostcontent($domain, $ssl_vhost, $ipid); } } } return $included_vhosts; } protected function getvhostcontent($domain, $ssl_vhost = false, $ipid = 0) { ($ssl_vhost === true &amp;&amp; $domain['ssl'] != '1' &amp;&amp; $domain['ssl_enabled'] != '1' &amp;&amp; $domain['ssl_redirect'] != '1') { return ''; } $vhost_content = ''; $vhost_content .= $this-&gt;getservernames($domain) . " {\n"; // respect ssl_redirect settings, #542 ($ssl_vhost == false &amp;&amp; $domain['ssl'] == '1' &amp;&amp; $domain['ssl_redirect'] == '1') { // must check port differs port 443, // destination-port != 443 $_sslport = ''; // returns first port != 443 ssl enabled, // ordered ssl-certificate (if any) ip/port combo // certificate used $ssldestport_stmt = database::prepare("select `ip`.`port` " . table_panel_ipsandports . " `ip` left join `" . table_domaintoip . "` `dip` (`ip`.`id` = `dip`.`id_ipandports`) `dip`.`id_domain` = :domainid `ip`.`ssl` = '1' `ip`.`port` != 443 order `ip`.`ssl_cert_file` desc, `ip`.`port` limit 1;"); $ssldestport = database::pexecute_first($ssldestport_stmt, [ 'domainid' =&gt; $domain['id'] ]); ($ssldestport &amp;&amp; $ssldestport['port'] != '') { $_sslport = ":" . $ssldestport['port']; } $domain['documentroot'] = 'https://%1' . $_sslport . '/'; } // avoid using whitespaces $domain['documentroot'] = trim($domain['documentroot']); (preg_match('/^https?\:\/\//', $domain['documentroot'])) { $possible_deactivated_webroot = $this-&gt;getwebroot($domain); ($this-&gt;deactivated == false) { $uri = $domain['documentroot']; // get domain's redirect code $code = domain::getdomainredirectcode($domain['id']); $vhost_content .= $this-&gt;getlogfiles($domain); $vhost_content .= ' url.redirect-code = ' . $code . "\n"; $vhost_content .= ' url.redirect = (' . "\n"; $vhost_content .= ' "^/(.*)$" =&gt; "' . $uri . '$1"' . "\n"; $vhost_content .= ' )' . "\n"; } elseif (settings::get('system.deactivateddocroot') != '') { $vhost_content .= $possible_deactivated_webroot; } } else { filedir::mkdirwithcorrectownership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true, true); $only_webroot = false; ($ssl_vhost === false &amp;&amp; $domain['ssl_redirect'] == '1') { $only_webroot = true; } $vhost_content .= $this-&gt;getwebroot($domain, $ssl_vhost); (!$only_webroot) { ($this-&gt;deactivated == false) { $vhost_content .= $this-&gt;createhtaccess($domain); $vhost_content .= $this-&gt;createpathoptions($domain); $vhost_content .= $this-&gt;composephpoptions($domain); $vhost_content .= $this-&gt;getstats($domain); $ipandport_stmt = database::prepare(" select * `" . table_panel_ipsandports . "` `id` = :id "); $ipandport = database::pexecute_first($ipandport_stmt, [ 'id' =&gt; $ipid ]); $domain['ip'] = $ipandport['ip']; $domain['port'] = $ipandport['port']; $domain['ssl_cert_file'] = $ipandport['ssl_cert_file']; $domain['ssl_key_file'] = $ipandport['ssl_key_file']; $domain['ssl_ca_file'] = $ipandport['ssl_ca_file']; // #418 $domain['ssl_cert_chainfile'] = $ipandport['ssl_cert_chainfile']; // ssl stuff $dssl = new domainssl(); // sets ssl-related array-indices $domain array // domain customer-defined ssl-certificates $dssl-&gt;setdomainsslfilesarray($domain); $vhost_content .= $this-&gt;getsslsettings($domain, $ssl_vhost); ($domain['specialsettings'] != '' &amp;&amp; ($ssl_vhost == false || ($ssl_vhost == true &amp;&amp; $domain['include_specialsettings'] == 1))) { $vhost_content .= $this-&gt;processspecialconfigtemplate($domain['specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } ($domain['ssl_specialsettings'] != '' &amp;&amp; $ssl_vhost == true) { $vhost_content .= $this-&gt;processspecialconfigtemplate($domain['ssl_specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } ($ipandport['default_vhostconf_domain'] != '' &amp;&amp; ($ssl_vhost == false || ($ssl_vhost == true &amp;&amp; $ipandport['include_default_vhostconf_domain'] == '1'))) { $vhost_content .= $this-&gt;processspecialconfigtemplate($ipandport['default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } ($ipandport['ssl_default_vhostconf_domain'] != '' &amp;&amp; $ssl_vhost == true) { $vhost_content .= $this-&gt;processspecialconfigtemplate($ipandport['ssl_default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } (settings::get('system.default_vhostconf') != '' &amp;&amp; ($ssl_vhost == false || ($ssl_vhost == true &amp;&amp; settings::get('system.include_default_vhostconf') == 1))) { $vhost_content .= $this-&gt;processspecialconfigtemplate(settings::get('system.default_vhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } (settings::get('system.default_sslvhostconf') != '' &amp;&amp; $ssl_vhost == true) { $vhost_content .= $this-&gt;processspecialconfigtemplate(settings::get('system.default_sslvhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } } $vhost_content .= $this-&gt;getlogfiles($domain); } } $vhost_content .= '}' . "\n"; return $vhost_content; } protected function getservernames($domain) { $server_string = []; $domain_name = str_replace('.', '\.', $domain['domain']); ($domain['iswildcarddomain'] == '1') { $server_string[] = '(?:^|\.)' . $domain_name . '$'; } else { ($domain['wwwserveralias'] == '1') { $server_string[] = '^(?:www\.|)' . $domain_name . '$'; } else { $server_string[] = '^' . $domain_name . '$'; } } $alias_domains_stmt = database::prepare(" select `domain`, `iswildcarddomain`, `wwwserveralias` `" . table_panel_domains . "` `aliasdomain` = :domainid "); database::pexecute($alias_domains_stmt, [ 'domainid' =&gt; $domain['id'] ]); (($alias_domain = $alias_domains_stmt-&gt;fetch(pdo::fetch_assoc)) !== false) { $alias_domain_name = str_replace('.', '\.', $alias_domain['domain']); ($alias_domain['iswildcarddomain'] == '1') { $server_string[] = '(?:^|\.)' . $alias_domain_name . '$'; } else { ($alias_domain['wwwserveralias'] == '1') { $server_string[] = '^(?:www\.|)' . $alias_domain_name . '$'; } else { $server_string[] = '^' . $alias_domain_name . '$'; } } } $servernames_text = ''; ($i = 0; $i &lt; sizeof($server_string); $i++) { $data = $server_string[$i]; (sizeof($server_string) &gt; 1) { ($i == 0) { $servernames_text = '(' . $data . '|'; } elseif (sizeof($server_string) - 1 == $i) { $servernames_text .= $data . ')'; } else { $servernames_text .= $data . '|'; } } else { $servernames_text = $data; } } unset($data); ($servernames_text != '') { $servernames_text = '$http["host"] =~ "' . $servernames_text . '"'; } else { $servernames_text = '$http["host"] == "' . $domain['domain'] . '"'; } return $servernames_text; } protected function getwebroot($domain, bool $ssl = false) { $webroot_text = ''; (($domain['deactivated'] == '1' || $domain['customer_deactivated'] == '1') &amp;&amp; settings::get('system.deactivateddocroot') != '') { $webroot_text .= ' # using docroot deactivated users/domains...' . "\n"; $webroot_text .= ' server.document-root = "' . filedir::makecorrectdir(settings::get('system.deactivateddocroot')) . "\"\n"; $this-&gt;deactivated = true; } else { ($ssl === false &amp;&amp; $domain['ssl_redirect'] == '1') { $redirect_domain = (new idnawrapper)-&gt;encode('https://' . $domain['domain']); } elseif (preg_match("#^https?://#i", $domain['documentroot'])) { $redirect_domain = (new idnawrapper)-&gt;encode($domain['documentroot']); } else { $webroot_text .= ' server.document-root = "' . filedir::makecorrectdir($domain['documentroot']) . "\"\n"; $redirect_domain = ''; } (!empty($redirect_domain)) { $webroot_text .= ' url.redirect = (' . "\n"; $webroot_text .= "\t" . '"^/(.*)" =&gt; "' . $redirect_domain . '/$1",' . "\n"; $webroot_text .= "\t" . '"" =&gt; "' . $redirect_domain . '",' . "\n"; $webroot_text .= "\t" . '"/" =&gt; "' . $redirect_domain . '"' . "\n"; $webroot_text .= ' )' . "\n"; } $this-&gt;deactivated = false; } return $webroot_text; } protected function createhtaccess($domain) { $needed_htpasswds = []; $result_htpasswds_stmt = database::prepare(" select * " . table_panel_htpasswds . " `path` like :docroot "); database::pexecute($result_htpasswds_stmt, [ 'docroot' =&gt; $domain['documentroot'] . '%' ]); $htaccess_text = ''; ($row_htpasswds = $result_htpasswds_stmt-&gt;fetch(pdo::fetch_assoc)) { $row_htpasswds['path'] = filedir::makecorrectdir($row_htpasswds['path']); filedir::mkdirwithcorrectownership($domain['documentroot'], $row_htpasswds['path'], $domain['guid'], $domain['guid']); $filename = $row_htpasswds['customerid'] . '-' . md5($row_htpasswds['path']) . '.htpasswd'; (!in_array($row_htpasswds['path'], $needed_htpasswds)) { (!isset($this-&gt;needed_htpasswds[$filename])) { $this-&gt;needed_htpasswds[$filename] = ''; } (!strstr($this-&gt;needed_htpasswds[$filename], $row_htpasswds['username'] . ':' . $row_htpasswds['password'])) { $this-&gt;needed_htpasswds[$filename] .= $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n"; } $htaccess_path = substr($row_htpasswds['path'], strlen($domain['documentroot']) - 1); $htaccess_path = filedir::makecorrectdir($htaccess_path); $htaccess_text .= ' $http["url"] =~ "^' . $htaccess_path . '" {' . "\n"; $htaccess_text .= ' auth.backend = "htpasswd"' . "\n"; $htaccess_text .= ' auth.backend.htpasswd.userfile = "' . filedir::makecorrectfile(settings::get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n"; $htaccess_text .= ' auth.require = ( ' . "\n"; $htaccess_text .= ' "' . $htaccess_path . '" =&gt;' . "\n"; $htaccess_text .= ' (' . "\n"; $htaccess_text .= ' "method" =&gt; "basic",' . "\n"; $htaccess_text .= ' "realm" =&gt; "' . $row_htpasswds['authname'] . '",' . "\n"; $htaccess_text .= ' "require" =&gt; "valid-user"' . "\n"; $htaccess_text .= ' )' . "\n"; $htaccess_text .= ' )' . "\n"; $htaccess_text .= ' }' . "\n"; $needed_htpasswds[] = $row_htpasswds['path']; } } return $htaccess_text; } protected function createpathoptions($domain) { $result_stmt = database::prepare(" select * " . table_panel_htaccess . " `path` like :docroot "); database::pexecute($result_stmt, [ 'docroot' =&gt; $domain['documentroot'] . '%' ]); $path_options = ''; $error_string = ''; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { (!empty($row['error404path'])) { $defhandler = $row['error404path']; (!validate::validateurl($defhandler)) { $defhandler = filedir::makecorrectfile($domain['documentroot'] . '/' . $defhandler); } $error_string .= ' server.error-handler-404 = "' . $defhandler . '"' . "\n\n"; } ($row['options_indexes'] != '0') { (!empty($error_string)) { $path_options .= $error_string; // reset $error_string prevent duplicate entries $error_string = ''; } $path = filedir::makecorrectdir(substr($row['path'], strlen($domain['documentroot']) - 1)); filedir::mkdirwithcorrectownership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); // need remove last slash, otherwise regex work ($row['path'] != $domain['documentroot']) { $path = substr($path, 0, -1); } $path_options .= ' $http["url"] =~ "^' . $path . '($|/)" {' . "\n"; $path_options .= "\t" . 'dir-listing.activate = "enable"' . "\n"; $path_options .= ' }' . "\n\n"; } else { $path_options = $error_string; } (customer::customerhasperlenabled($domain['customerid']) &amp;&amp; $row['options_cgi'] != '0') { $path = filedir::makecorrectdir(substr($row['path'], strlen($domain['documentroot']) - 1)); filedir::mkdirwithcorrectownership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); // need remove last slash, otherwise regex work ($row['path'] != $domain['documentroot']) { $path = substr($path, 0, -1); } $path_options .= ' $http["url"] =~ "^' . $path . '($|/)" {' . "\n"; $path_options .= "\t" . 'cgi.assign = (' . "\n"; $path_options .= "\t\t" . '".pl" =&gt; "' . filedir::makecorrectfile(settings::get('system.perl_path')) . '",' . "\n"; $path_options .= "\t\t" . '".cgi" =&gt; "' . filedir::makecorrectfile(settings::get('system.perl_path')) . '"' . "\n"; $path_options .= "\t" . ')' . "\n"; $path_options .= ' }' . "\n\n"; } } return $path_options; } protected function composephpoptions(&amp;$domain) { return; } /** * lets set text part stats software */ protected function getstats($domain) { $stats_text = ''; $stattool = settings::get('system.traffictool'); $statdomain = ""; ($stattool == 'awstats') { // awstats generates domain regardless speciallogfile $statdomain = "/" . $domain['domain']; } ($domain['speciallogfile'] == '1') { $statdomain = "/" . (($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']); } $statdocroot = filedir::makecorrectfile($domain['customerroot'] . '/' . $stattool . $statdomain); $stats_text .= ' alias.url = ( "/'.$stattool.'/" =&gt; "' . $statdocroot . '" )' . "\n"; // awstats special requirement icons ($stattool == 'awstats') { $stats_text .= ' alias.url += ( "/awstats-icon" =&gt; "' . filedir::makecorrectdir(settings::get('system.awstats_icons')) . '" )' . "\n"; } return $stats_text; } protected function getsslsettings($domain, $ssl_vhost) { $ssl_settings = ''; ($ssl_vhost === true &amp;&amp; $domain['ssl'] == '1' &amp;&amp; (int)settings::get('system.use_ssl') == 1) { ($domain['ssl_cert_file'] == '' || !file_exists($domain['ssl_cert_file'])) { $domain['ssl_cert_file'] = settings::get('system.ssl_cert_file'); (!file_exists($domain['ssl_cert_file'])) { // explicitly disable ssl vhost $domain['ssl_cert_file'] = ""; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, 'system certificate file "' . settings::get('system.ssl_cert_file') . '" seem exist. disabling ssl-vhost "' . $domain['domain'] . '"'); } } ($domain['ssl_ca_file'] == '') { $domain['ssl_ca_file'] = settings::get('system.ssl_ca_file'); } ($domain['ssl_cert_file'] != '') { $ssl_cipher_list = ($domain['override_tls'] == '1' &amp;&amp; !empty($domain['ssl_cipher_list'])) ? $domain['ssl_cipher_list'] : settings::get('system.ssl_cipher_list'); // ssl.engine necessary ip/port vhost (server['socket'] condition) // $ssl_settings .= 'ssl.engine = "enable"' . "\n"; $ssl_settings .= 'ssl.use-compression = "disable"' . "\n"; (!empty(settings::get('system.dhparams_file'))) { $dhparams = filedir::makecorrectfile(settings::get('system.dhparams_file')); (!file_exists($dhparams)) { file_put_contents($dhparams, self::ffdhe4096); } $ssl_settings .= 'ssl.dh-file = "' . $dhparams . '"' . "\n"; $ssl_settings .= 'ssl.ec-curve = "secp384r1"' . "\n"; } $ssl_settings .= 'ssl.use-sslv2 = "disable"' . "\n"; $ssl_settings .= 'ssl.use-sslv3 = "disable"' . "\n"; $ssl_settings .= 'ssl.cipher-list = "' . $ssl_cipher_list . '"' . "\n"; $ssl_settings .= 'ssl.honor-cipher-order = ' . ($domain['ssl_honorcipherorder'] == '1' ? '"enable"' : '"disable"') . "\n"; $ssl_settings .= 'ssl.pemfile = "' . filedir::makecorrectfile($domain['ssl_cert_file']) . '"' . "\n"; ($domain['ssl_ca_file'] != '') { $ssl_settings .= 'ssl.ca-file = "' . filedir::makecorrectfile($domain['ssl_ca_file']) . '"' . "\n"; } ($domain['hsts'] &gt;= 0) { $ssl_settings .= '$http["scheme"] == "https" { setenv.add-response-header = ( "strict-transport-security" =&gt; "max-age=' . $domain['hsts']; ($domain['hsts_sub'] == 1) { $ssl_settings .= '; includesubdomains'; } ($domain['hsts_preload'] == 1) { $ssl_settings .= '; preload'; } $ssl_settings .= '") }' . "\n"; } } } return $ssl_settings; } protected function getlogfiles($domain) { $logfiles_text = ''; $speciallogfile = ''; ($domain['speciallogfile'] == '1') { ($domain['parentdomainid'] == '0') { $speciallogfile = '-' . $domain['domain']; } else { $speciallogfile = '-' . $domain['parentdomain']; } } // normal access/error - logging enabled // error log cannot set conditionally see // https://redmine.lighttpd.net/issues/665 ($domain['writeaccesslog']) { $access_log = filedir::makecorrectfile(settings::get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log'); // create logfile exist (fixes #46) touch($access_log); chown($access_log, settings::get('system.httpuser')); chgrp($access_log, settings::get('system.httpgroup')); $logfiles_text .= ' accesslog.filename = "' . $access_log . '"' . "\n"; } (settings::get('system.traffictool') == 'awstats') { ((int)$domain['parentdomainid'] == 0) { // prepare aliases subdomains stats config files $server_alias = ''; $alias_domains_stmt = database::prepare(" select `domain`, `iswildcarddomain`, `wwwserveralias` `" . table_panel_domains . "` `aliasdomain` = :domainid `parentdomainid` = :domainid "); database::pexecute($alias_domains_stmt, [ 'domainid' =&gt; $domain['id'] ]); (($alias_domain = $alias_domains_stmt-&gt;fetch(pdo::fetch_assoc)) !== false) { $server_alias .= ' ' . $alias_domain['domain'] . ' '; ($alias_domain['iswildcarddomain'] == '1') { $server_alias .= '*.' . $domain['domain']; } else { ($alias_domain['wwwserveralias'] == '1') { $server_alias .= 'www.' . $alias_domain['domain']; } else { $server_alias .= ''; } } } ($domain['iswildcarddomain'] == '1') { $alias = '*.' . $domain['domain']; } else { ($domain['wwwserveralias'] == '1') { $alias = 'www.' . $domain['domain']; } else { $alias = ''; } } // inserting awstats information, // sure build awstats conf file well // chown using $awstats_params, #258 // bug 960 + bug 970 : use full $domain instead custom $awstats_params following classes depend information statistics::createawstatsconf(settings::get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log', $domain['domain'], $alias . $server_alias, $domain['customerroot'], $domain); } } return $logfiles_text; } /** * define default server.error-handler-404-statement, bug #unknown-yet */ private function createstandarderrorhandler() { (settings::get('defaultwebsrverrhandler.enabled') == '1' &amp;&amp; settings::get('defaultwebsrverrhandler.err404') != '') { $vhost_filename = filedir::makecorrectfile(settings::get('system.apacheconf_vhost') . '/05_froxlor_default_errorhandler.conf'); (!isset($this-&gt;lighttpd_data[$vhost_filename])) { $this-&gt;lighttpd_data[$vhost_filename] = ''; } $defhandler = settings::get('defaultwebsrverrhandler.err404'); (!validate::validateurl($defhandler)) { $defhandler = filedir::makecorrectfile($defhandler); } $this-&gt;lighttpd_data[$vhost_filename] = 'server.error-handler-404 = "' . $defhandler . '"'; } } public function createvirtualhosts() { return; } public function createfilediroptions() { return; } public function createownvhoststarter() { return; } public function writeconfigs() { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "lighttpd::writeconfigs: rebuilding " . settings::get('system.apacheconf_vhost')); $vhostdir = new directory(settings::get('system.apacheconf_vhost')); (!$vhostdir-&gt;isconfigdir()) { // save one big file $vhosts_file = ''; // sort filename order is: // 1. main-domains // 2. subdomains main-domains // 3. subdomains // (former #437) - #833 (the numbering done createlighttpdhosts()) ksort($this-&gt;lighttpd_data); foreach ($this-&gt;lighttpd_data $vhosts_filename =&gt; $vhost_content) { $vhosts_file .= $vhost_content . "\n\n"; } $vhosts_filename = settings::get('system.apacheconf_vhost'); // apply header $vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# created ' . date('d.m.y h:i') . "\n" . '# manually edit file, changes deleted next domain change panel.' . "\n" . "\n" . $vhosts_file; $vhosts_file_handler = fopen($vhosts_filename, 'w'); fwrite($vhosts_file_handler, $vhosts_file); fclose($vhosts_file_handler); } else { (!file_exists(settings::get('system.apacheconf_vhost'))) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'lighttpd::writeconfigs: mkdir ' . escapeshellarg(filedir::makecorrectdir(settings::get('system.apacheconf_vhost')))); filedir::safe_exec('mkdir ' . escapeshellarg(filedir::makecorrectdir(settings::get('system.apacheconf_vhost')))); } // write single file every vhost foreach ($this-&gt;lighttpd_data $vhosts_filename =&gt; $vhosts_file) { // apply header $vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# created ' . date('d.m.y h:i') . "\n" . '# manually edit file, changes deleted next domain change panel.' . "\n" . "\n" . $vhosts_file; (!empty($vhosts_filename)) { $vhosts_file_handler = fopen($vhosts_filename, 'w'); fwrite($vhosts_file_handler, $vhosts_file); fclose($vhosts_file_handler); } } } // write diroptions $htpasswddir = new directory(settings::get('system.apacheconf_htpasswddir')); ($htpasswddir-&gt;isconfigdir()) { foreach ($this-&gt;needed_htpasswds $key =&gt; $data) { (!is_dir(settings::get('system.apacheconf_htpasswddir'))) { mkdir(filedir::makecorrectdir(settings::get('system.apacheconf_htpasswddir'))); } $filename = filedir::makecorrectfile(settings::get('system.apacheconf_htpasswddir') . '/' . $key); $htpasswd_handler = fopen($filename, 'w'); fwrite($htpasswd_handler, $data); fclose($htpasswd_handler); } } } protected function getdiroptions($domain) { $result_stmt = database::prepare(" select * " . table_panel_htpasswds . " `customerid` = :customerid "); database::pexecute($result_stmt, [ 'customerid' =&gt; $domain['customerid'] ]); $diroption_text = ''; ($row_htpasswds = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { ($this-&gt;auth_backend_loaded[$domain['ipandport']] != 'yes' &amp;&amp; $this-&gt;auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') { $filename = $domain['customerid'] . '.htpasswd'; ($this-&gt;auth_backend_loaded[$domain['ipandport']] != 'yes') { $this-&gt;auth_backend_loaded[$domain['ipandport']] = 'yes'; $diroption_text .= 'auth.backend = "htpasswd"' . "\n"; $diroption_text .= 'auth.backend.htpasswd.userfile = "' . filedir::makecorrectfile(settings::get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n"; $this-&gt;needed_htpasswds[$filename] = $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n"; $diroption_text .= 'auth.require = ( ' . "\n"; } elseif ($this-&gt;auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') { $this-&gt;auth_backend_loaded[$domain['ssl_ipandport']] = 'yes'; $diroption_text .= 'auth.backend= "htpasswd"' . "\n"; $diroption_text .= 'auth.backend.htpasswd.userfile = "' . filedir::makecorrectfile(settings::get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n"; $this-&gt;needed_htpasswds[$filename] = $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n"; $diroption_text .= 'auth.require = ( ' . "\n"; } } $diroption_text .= '"' . filedir::makecorrectdir($row_htpasswds['path']) . '" =&gt;' . "\n"; $diroption_text .= '(' . "\n"; $diroption_text .= ' "method" =&gt; "basic",' . "\n"; $diroption_text .= ' "realm" =&gt; "' . $row_htpasswds['authname'] . '",' . "\n"; $diroption_text .= ' "require" =&gt; "valid-user"' . "\n"; $diroption_text .= ')' . "\n"; ($this-&gt;auth_backend_loaded[$domain['ssl_ipandport']] == 'yes') { $this-&gt;needed_htpasswds[$domain['ssl_ipandport']] .= $diroption_text; } ($this-&gt;auth_backend_loaded[$domain['ipandport']] != 'yes') { $this-&gt;needed_htpasswds[$domain['ipandport']] .= $diroption_text; } } return ' auth.backend.htpasswd.userfile = "' . filedir::makecorrectfile(settings::get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n"; } }</file><file name="lib/Froxlor/Cron/Http/ApacheFcgi.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http; use froxlor\cron\http\php\phpinterface; use froxlor\customer\customer; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlor; use froxlor\http\directory; use froxlor\settings; /** * @author florian lippert &lt;flo@syscp.org&gt; (2003-2009) * @author froxlor team &lt;team@froxlor.org&gt; (2010-) */ class apachefcgi extends apache { public function createownvhoststarter() { (settings::get('system.mod_fcgid_ownvhost') == '1' || (settings::get('phpfpm.enabled') == '1' &amp;&amp; settings::get('phpfpm.enabled_ownvhost') == '1')) { $mypath = froxlor::getinstalldir(); (settings::get('system.mod_fcgid_ownvhost') == '1') { $user = settings::get('system.mod_fcgid_httpuser'); $group = settings::get('system.mod_fcgid_httpgroup'); } elseif (settings::get('phpfpm.enabled') == '1' &amp;&amp; settings::get('phpfpm.enabled_ownvhost') == '1') { $user = settings::get('phpfpm.vhost_httpuser'); $group = settings::get('phpfpm.vhost_httpgroup'); // get fpm config $fpm_sel_stmt = database::prepare(" select f.id `" . table_panel_fpmdaemons . "` f left join `" . table_panel_phpconfigs . "` p p.fpmsettingid = f.id p.id = :phpconfigid "); $fpm_config = database::pexecute_first($fpm_sel_stmt, [ 'phpconfigid' =&gt; settings::get('phpfpm.vhost_defaultini') ]); } $domain = [ 'id' =&gt; 'none', 'domain' =&gt; settings::get('system.hostname'), 'adminid' =&gt; 1, /* first admin-user (superadmin) */ 'mod_fcgid_starter' =&gt; -1, 'mod_fcgid_maxrequests' =&gt; -1, 'guid' =&gt; $user, 'openbasedir' =&gt; 0, 'email' =&gt; settings::get('panel.adminmail'), 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath, 'fpm_config_id' =&gt; isset($fpm_config['id']) ? $fpm_config['id'] : 1 ]; // files folders belong local user // also use fcgid vhost filedir::safe_exec('chown -r ' . $user . ':' . $group . ' ' . escapeshellarg($mypath)); // get php.ini vhost $php = new phpinterface($domain); // get php-config (settings::get('phpfpm.enabled') == '1') { // fpm $phpconfig = $php-&gt;getphpconfig(settings::get('phpfpm.vhost_defaultini')); } else { // fcgid $phpconfig = $php-&gt;getphpconfig(settings::get('system.mod_fcgid_defaultini_ownvhost')); } // create starter-file | config-file $php-&gt;getinterface()-&gt;createconfig($phpconfig); // create php.ini (fpm nothing here, // defines ini-settings pool config) $php-&gt;getinterface()-&gt;createinifile($phpconfig); } } protected function composephpoptions(&amp;$domain, $ssl_vhost = false) { $php_options_text = ''; ($domain['phpenabled_customer'] == 1 &amp;&amp; $domain['phpenabled_vhost'] == '1') { $php = new phpinterface($domain); $phpconfig = $php-&gt;getphpconfig((int)$domain['phpsettingid']); ((int)settings::get('phpfpm.enabled') == 1) { $srvname = 'fpm.external'; ($domain['ssl'] == 1 &amp;&amp; $ssl_vhost) { $srvname = 'ssl-fpm.external'; } // #1317 - perl executed via apache therefore, using fpm, know user // perl supposed run as, hence need suexec need (customer::customerhasperlenabled($domain['customerid'])) { $php_options_text .= ' suexecusergroup "' . $domain['loginname'] . '" "' . $domain['loginname'] . '"' . "\n"; } $domain['fpm_socket'] = $php-&gt;getinterface()-&gt;getsocketfile(); // mod_proxy stuff apache-2.4 (settings::get('system.apache24') == '1' &amp;&amp; settings::get('phpfpm.use_mod_proxy') == '1') { $php_options_text .= ' &lt;directory "' . filedir::makecorrectdir($domain['documentroot']) . '"&gt;' . "\n"; $filesmatch = $phpconfig['fpm_settings']['limit_extensions']; $extensions = explode(" ", $filesmatch); $filesmatch = ""; foreach ($extensions $ext) { $filesmatch .= substr($ext, 1) . '|'; } // start block, cut last pipe close block $filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, -1)) . ')'; $php_options_text .= ' &lt;filesmatch \.' . $filesmatch . '$&gt;' . "\n"; $php_options_text .= ' &lt;if "-f %{script_filename}"&gt;' . "\n"; $php_options_text .= ' sethandler proxy:unix:' . $domain['fpm_socket'] . '|fcgi://localhost' . "\n"; $php_options_text .= ' &lt;/if&gt;' . "\n"; $php_options_text .= ' &lt;/filesmatch&gt;' . "\n"; $mypath_dir = new directory($domain['documentroot']); // create "require granted" directive active directory-protection // path, would first require therefore grant access ($mypath_dir-&gt;isuserprotected() == false) { ($phpconfig['pass_authorizationheader'] == '1') { $php_options_text .= ' cgipassauth on' . "\n"; } $php_options_text .= ' require granted' . "\n"; $php_options_text .= ' allowoverride all' . "\n"; } elseif ($phpconfig['pass_authorizationheader'] == '1') { // allow pass authorization header $php_options_text .= ' cgipassauth on' . "\n"; } $php_options_text .= ' &lt;/directory&gt;' . "\n"; } else { $addheader = ""; ($phpconfig['pass_authorizationheader'] == '1') { $addheader = " -pass-header authorization"; } $php_options_text .= ' fastcgiexternalserver ' . $php-&gt;getinterface()-&gt;getaliasconfigdir() . $srvname . ' -socket ' . $domain['fpm_socket'] . ' -idle-timeout ' . $phpconfig['fpm_settings']['idle_timeout'] . $addheader . "\n"; $php_options_text .= ' &lt;directory "' . filedir::makecorrectdir($domain['documentroot']) . '"&gt;' . "\n"; $filesmatch = $phpconfig['fpm_settings']['limit_extensions']; $extensions = explode(" ", $filesmatch); $filesmatch = ""; foreach ($extensions $ext) { $filesmatch .= substr($ext, 1) . '|'; } // start block, cut last pipe close block $filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, -1)) . ')'; $php_options_text .= ' &lt;filesmatch \.' . $filesmatch . '$&gt;' . "\n"; $php_options_text .= ' sethandler php-fastcgi' . "\n"; $php_options_text .= ' action php-fastcgi /fastcgiphp' . "\n"; $php_options_text .= ' options +execcgi' . "\n"; $php_options_text .= ' &lt;/filesmatch&gt;' . "\n"; // &gt;=apache-2.4 enabled? (settings::get('system.apache24') == '1') { $mypath_dir = new directory($domain['documentroot']); // create require granted active directory-protection // path, would first require therefore grant access ($mypath_dir-&gt;isuserprotected() == false) { $php_options_text .= ' require granted' . "\n"; $php_options_text .= ' allowoverride all' . "\n"; } } else { $php_options_text .= ' order allow,deny' . "\n"; $php_options_text .= ' allow all' . "\n"; } $php_options_text .= ' &lt;/directory&gt;' . "\n"; $php_options_text .= ' alias /fastcgiphp ' . $php-&gt;getinterface()-&gt;getaliasconfigdir() . $srvname . "\n"; } } else { $php_options_text .= ' fcgididletimeout ' . settings::get('system.mod_fcgid_idle_timeout') . "\n"; ($phpconfig['pass_authorizationheader'] == '1') { $php_options_text .= ' fcgidpassheader authorization' . "\n"; } ((int)settings::get('system.mod_fcgid_wrapper') == 0) { $php_options_text .= ' suexecusergroup "' . $domain['loginname'] . '" "' . $domain['loginname'] . '"' . "\n"; $php_options_text .= ' scriptalias /php/ ' . $php-&gt;getinterface()-&gt;getconfigdir() . "\n"; } else { $php_options_text .= ' suexecusergroup "' . $domain['loginname'] . '" "' . $domain['loginname'] . '"' . "\n"; $php_options_text .= ' &lt;directory "' . filedir::makecorrectdir($domain['documentroot']) . '"&gt;' . "\n"; $file_extensions = explode(' ', $phpconfig['file_extensions']); $php_options_text .= ' &lt;filesmatch "\.(' . implode('|', $file_extensions) . ')$"&gt;' . "\n"; $php_options_text .= ' sethandler fcgid-script' . "\n"; foreach ($file_extensions $file_extension) { $php_options_text .= ' fcgidwrapper ' . $php-&gt;getinterface()-&gt;getstarterfile() . ' .' . $file_extension . "\n"; } $php_options_text .= ' options +execcgi' . "\n"; $php_options_text .= ' &lt;/filesmatch&gt;' . "\n"; // &gt;=apache-2.4 enabled? (settings::get('system.apache24') == '1') { $mypath_dir = new directory($domain['documentroot']); // create require granted active directory-protection // path, would first require therefore grant access ($mypath_dir-&gt;isuserprotected() == false) { $php_options_text .= ' require granted' . "\n"; $php_options_text .= ' allowoverride all' . "\n"; } } else { $php_options_text .= ' order allow,deny' . "\n"; $php_options_text .= ' allow all' . "\n"; } $php_options_text .= ' &lt;/directory&gt;' . "\n"; } } // create starter-file | config-file $php-&gt;getinterface()-&gt;createconfig($phpconfig); // create php.ini (fpm nothing here, // defines ini-settings pool config) $php-&gt;getinterface()-&gt;createinifile($phpconfig); } else { $php_options_text .= ' # php disabled vhost' . "\n"; } return $php_options_text; } }</file><file name="lib/Froxlor/Cron/Http/WebserverBase.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http; use froxlor\database\database; use froxlor\domain\domain; use froxlor\settings; use pdo; class webserverbase { /** * returns array entries required * webserver-vhost-configs * * @return array */ public static function getvhoststocreate() { $query = "select `d`.*, `pd`.`domain` `parentdomain`, `c`.`loginname`, `d`.`phpsettingid`, `c`.`adminid`, `c`.`guid`, `c`.`email`, `c`.`documentroot` `customerroot`, `c`.`deactivated` `customer_deactivated`, `c`.`phpenabled` `phpenabled_customer`, `d`.`phpenabled` `phpenabled_vhost` `" . table_panel_domains . "` `d` left join `" . table_panel_customers . "` `c` using(`customerid`) left join `" . table_panel_domains . "` `pd` (`pd`.`id` = `d`.`parentdomainid`) `d`.`aliasdomain` null `d`.`email_only` &lt;&gt; '1' order `d`.`parentdomainid` desc, `d`.`iswildcarddomain`, `d`.`domain` asc; "; $result_domains_stmt = database::query($query); // prepare ip statement $ip_stmt = database::prepare(" select `di`.`id_domain` , `p`.`ssl`, `p`.`ssl_cert_file`, `p`.`ssl_key_file`, `p`.`ssl_ca_file`, `p`.`ssl_cert_chainfile` `" . table_domaintoip . "` `di`, `" . table_panel_ipsandports . "` `p` `p`.`id` = `di`.`id_ipandports` `di`.`id_domain` = :domainid `p`.`ssl` = '1' "); // prepare fpm-config select query $fpm_sel_stmt = database::prepare(" select f.id `" . table_panel_fpmdaemons . "` f left join `" . table_panel_phpconfigs . "` p p.fpmsettingid = f.id p.id = :phpconfigid "); $domains = []; ($domain = $result_domains_stmt-&gt;fetch(pdo::fetch_assoc)) { // set whole domain $domains[$domain['domain']] = $domain; // set empty-defaults non-ssl $domains[$domain['domain']]['ssl'] = ''; $domains[$domain['domain']]['ssl_cert_file'] = ''; $domains[$domain['domain']]['ssl_key_file'] = ''; $domains[$domain['domain']]['ssl_ca_file'] = ''; $domains[$domain['domain']]['ssl_cert_chainfile'] = ''; // now, domain ssl ip/port assigned, get // corresponding information db (domain::domainhassslipport($domain['id'])) { $ssl_ip = database::pexecute_first($ip_stmt, [ 'domainid' =&gt; $domain['id'] ]); // set ssl info domain $domains[$domain['domain']]['ssl'] = '1'; $domains[$domain['domain']]['ssl_cert_file'] = $ssl_ip['ssl_cert_file']; $domains[$domain['domain']]['ssl_key_file'] = $ssl_ip['ssl_key_file']; $domains[$domain['domain']]['ssl_ca_file'] = $ssl_ip['ssl_ca_file']; $domains[$domain['domain']]['ssl_cert_chainfile'] = $ssl_ip['ssl_cert_chainfile']; } // read fpm-config-id using fpm ((int)settings::get('phpfpm.enabled') == 1) { $fpm_config = database::pexecute_first($fpm_sel_stmt, [ 'phpconfigid' =&gt; $domain['phpsettingid'] ]); ($fpm_config) { $domains[$domain['domain']]['fpm_config_id'] = $fpm_config['id']; } else { // fallback $domains[$domain['domain']]['fpm_config_id'] = 1; } } } return $domains; } }</file><file name="lib/Froxlor/Cron/Http/HttpConfigBase.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http; use froxlor\cron\http\letsencrypt\acmesh; use froxlor\cron\http\php\fpm; use froxlor\database\database; use froxlor\domain\domain; use froxlor\filedir; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\settings; use froxlor\system\cronjob; use pdo; /** * class httpconfigbase * * base class http server configs */ class httpconfigbase { /** * pre-defined dhe groups use fallback dhparams_file * given, non-existent, see also https://github.com/froxlor/froxlor/issues/1270 */ const ffdhe4096 = &lt;&lt;&lt;eoc -----begin dh parameters----- miiccakcagea//////////+t+fryortkmq/cvianptzx2lnfg84tnpwp4tzbfgqz +8ytnc4kmz75fs/jy2mmddj2gbicrsrhetpfhtxv/wvhjdp1h18gbtcfy2vvpe0a 87vxe15/v8k1me8mcodmi3fipona8+/och3xwke2rec1mkzkt0g6exq8crgcsyt7 ydeiquuyyop7uwrat2dx9ggdt0kj3jln9k5w7edjcrszcwenyo4kbxceavzhzffi 7ma0bm0onc9hkxl+nomfg/+otxiy7vkbg8p+oxtmb61zo7x8vc7ciaxfjvgdfrad ssbzsibbsu/6igtcogefz9zenvs7zrkdw7w09n75nai4ybrvydbmyqd62r0mkff3 7lmmsprbhtkcrv4tcyutknc0ewytven5rpt9rfli103tzplihnh1s/9crokrnj32 nuhtk8uinjonq8uhl5sn6todv5pc1critgq80gv6u93vpbsg7j/vnxwl5b0rzp4e 8w5vusmwtft7etdp5owiv7asfv9c1p9tghdjzx1va0aeh/vbpx4xzhpxncig77qx iu1qhgetnmgyqqdgcpgbmmrtx3j5ca0aoakpmamzy4t6gh25pxfaadwqts6p+y0k zaqckc3oyx3pjsm1wn+ipgtntahr9egc4cakah5ezv9q//////////8caqi= -----end dh parameters----- eoc; public function init() { // let's encrypt activated, run regeneration webserver configfiles (settings::get('system.leenabled') == 1) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'running let\'s encrypt cronjob prior regenerating webserver config files'); acmesh::$no_inserttask = true; acmesh::run(true); // set last run timestamp cronjob cronjob::updatelastrunofcron('letsencrypt'); } } public function reload() { $called_class = get_called_class(); ((int)settings::get('phpfpm.enabled') == 1) { // get start/stop commands $startstop_sel = database::prepare("select reload_cmd, config_dir `" . table_panel_fpmdaemons . "`"); database::pexecute($startstop_sel); $restart_cmds = $startstop_sel-&gt;fetchall(pdo::fetch_assoc); // restart php-fpm instances foreach ($restart_cmds $restart_cmd) { // check whether config dir empty (no domains uses daemon) // need create dummy $_conffiles = glob(filedir::makecorrectfile($restart_cmd['config_dir'] . "/*.conf")); ($_conffiles === false || empty($_conffiles)) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, $called_class . '::reload: fpm config directory "' . $restart_cmd['config_dir'] . '" empty. creating dummy.'); fpm::createdummypool($restart_cmd['config_dir']); } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, $called_class . '::reload: running ' . $restart_cmd['reload_cmd']); filedir::safe_exec(escapeshellcmd($restart_cmd['reload_cmd'])); } } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, $called_class . '::reload: reloading ' . $called_class); filedir::safe_exec(escapeshellcmd(settings::get('system.apachereload_command'))); /** * nginx auto-spawn fcgi-processes */ (settings::get('system.webserver') == "nginx" &amp;&amp; settings::get('system.phpreload_command') != '' &amp;&amp; (int)settings::get('phpfpm.enabled') == 0) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, $called_class . '::reload: restarting php processes'); filedir::safe_exec(settings::get('system.phpreload_command')); } } /** * process special config template, substituting {variable} * respective value. * * following variables known moment: * * {domain} - domain name * {ip} - ip domain * {port} - port domain * {customer} - customer name * {is_ssl} - evaluates 'ssl' domain/ip ssl, otherwise empty string * {docroot} - document root domain * * @param * $template * @return string */ protected function processspecialconfigtemplate($template, $domain, $ip, $port, $is_ssl_vhost) { $templatevars = [ 'domain' =&gt; $domain['domain'], 'customer' =&gt; $domain['loginname'], 'ip' =&gt; $ip, 'port' =&gt; $port, 'scheme' =&gt; ($is_ssl_vhost) ? 'https' : 'http', 'docroot' =&gt; $domain['documentroot'], 'fpmsocket' =&gt; '' ]; ((int)settings::get('phpfpm.enabled') == 1 &amp;&amp; isset($domain['fpm_socket']) &amp;&amp; !empty($domain['fpm_socket'])) { $templatevars['fpmsocket'] = $domain['fpm_socket']; } return phphelper::replacevariables($template, $templatevars); } protected function getmypath($ip_port = null) { (!empty($ip_port) &amp;&amp; $ip_port['docroot'] == '') { (settings::get('system.froxlordirectlyviahostname')) { $mypath = filedir::makecorrectdir(froxlor::getinstalldir()); } else { $mypath = filedir::makecorrectdir(dirname(froxlor::getinstalldir())); } } else { // user-defined docroot, #417 $mypath = filedir::makecorrectdir($ip_port['docroot']); } return $mypath; } protected function checkalternativesslport() { // must check port differs port 443, // destination-port != 443 $_sslport = ''; // returns first port != 443 ssl enabled, // ordered ssl-certificate (if any) ip/port combo // certificate used $ssldestport_stmt = database::prepare(" select `ip`.`port` " . table_panel_ipsandports . " `ip` `ip`.`ssl` = '1' `ip`.`port` != 443 order `ip`.`ssl_cert_file` desc, `ip`.`port` limit 1; "); $ssldestport = database::pexecute_first($ssldestport_stmt); ($ssldestport &amp;&amp; $ssldestport['port'] != '') { $_sslport = ":" . $ssldestport['port']; } return $_sslport; } protected function froxlorvhosthasletsencryptcert() { // check whether entry valid certificates need // updating yet, need skip $froxlor_ssl_settings_stmt = database::prepare(" select * `" . table_panel_domain_ssl_settings . "` `domainid` = '0' "); $froxlor_ssl = database::pexecute_first($froxlor_ssl_settings_stmt); ($froxlor_ssl &amp;&amp; !empty($froxlor_ssl['ssl_cert_file'])) { return true; } return false; } protected function froxlorvhostletsencryptneedsrenew() { $froxlor_ssl_settings_stmt = database::prepare(" select * `" . table_panel_domain_ssl_settings . "` `domainid` = '0' (`validtodate` &lt; date_add(now(), interval 30 day) `validtodate` null) "); $froxlor_ssl = database::pexecute_first($froxlor_ssl_settings_stmt); ($froxlor_ssl &amp;&amp; !empty($froxlor_ssl['ssl_cert_file'])) { return true; } return false; } /** * get filename virtualhost */ protected function getvhostfilename(array $domain, bool $ssl_vhost = false, bool $filename_only = false) { // number dots domain specifies position (and depth subdomain) starting 35 going downwards higher depth $vhost_no = (string)(35 - substr_count($domain['domain'], ".") + 1); $filename = $vhost_no . '_froxlor_' . ($ssl_vhost ? 'ssl' : 'normal') . '_vhost_' . $domain['domain'] . '.conf'; ($filename_only) { return $filename; } return filedir::makecorrectfile(settings::get('system.apacheconf_vhost') . '/' . $filename); } protected function getcustomvhostfilename(string $name) { $vhosts_folder = filedir::makecorrectdir(dirname(settings::get('system.apacheconf_vhost'))); (is_dir(settings::get('system.apacheconf_vhost'))) { $vhosts_folder = filedir::makecorrectdir(settings::get('system.apacheconf_vhost')); } return filedir::makecorrectfile($vhosts_folder . '/' . $name); } }</file><file name="lib/Froxlor/Cron/Http/ConfigIO.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlor; use froxlor\settings; use pdo; use recursivedirectoryiterator; use recursiveiteratoriterator; class configio { /** * clean former created configs, including (if enabled) * awstats, fcgid, php-fpm course automatically created * webserver vhost diroption files * * @return null */ public function cleanup() { // old error logs $this-&gt;cleanerrlogs(); // awstats files $this-&gt;cleanawstatsfiles(); // fcgid files $this-&gt;cleanfcgidfiles(); // php-fpm files $this-&gt;cleanfpmfiles(); // clean webserver-configs $this-&gt;cleanwebserverconfigs(); // old htpasswd files $this-&gt;cleanhtpasswdfiles(); // customer-specified ssl-certificates $this-&gt;cleancustomersslcerts(); } private function cleanerrlogs() { $err_dir = filedir::makecorrectdir(froxlor::getinstalldir() . "/logs/"); (@is_dir($err_dir)) { // get rid old stuff // (but append /*.log delete directory) $err_dir .= '/*.log'; filedir::safe_exec('rm -f ' . filedir::makecorrectfile($err_dir)); } } /** * remove awstats related configuration files regeneration * * @return null */ private function cleanawstatsfiles() { (settings::get('system.traffictool') != 'awstats') { return; } // dhr: cleanout froxlor-generated awstats configs prior re-creation $awstatsclean = []; $awstatsclean['header'] = "## generated froxlor\n"; $awstatsclean['headerold'] = "## generated syscp\n"; $awstatsclean['path'] = $this-&gt;getfile('system', 'awstats_conf'); /** * anything directory exist * (e.g. * awstats installed yet whatever) * fixes #45 */ ($awstatsclean['path'] !== false &amp;&amp; is_dir($awstatsclean['path'])) { $awstatsclean['dir'] = dir($awstatsclean['path']); ($awstatsclean['entry'] = $awstatsclean['dir']-&gt;read()) { $awstatsclean['fullentry'] = filedir::makecorrectfile($awstatsclean['path'] . '/' . $awstatsclean['entry']); /** * anything file exist */ (@file_exists($awstatsclean['fullentry']) &amp;&amp; $awstatsclean['entry'] != '.' &amp;&amp; $awstatsclean['entry'] != '..') { $awstatsclean['fh'] = fopen($awstatsclean['fullentry'], 'r'); $awstatsclean['headerread'] = fgets($awstatsclean['fh'], strlen($awstatsclean['header']) + 1); fclose($awstatsclean['fh']); ($awstatsclean['headerread'] == $awstatsclean['header'] || $awstatsclean['headerread'] == $awstatsclean['headerold']) { $awstats_conf_file = filedir::makecorrectfile($awstatsclean['fullentry']); @unlink($awstats_conf_file); } } } } unset($awstatsclean); // end dhr } /** * returns file/directory settings checks whether exists * * @param string $group * settings-group * @param string $varname * var-name * @param boolean $check_exists * check file exists * * @return string|boolean complete path including filename false error */ private function getfile($group, $varname, $check_exists = true) { // read settings $file = settings::get($group . '.' . $varname); // check whether exists ($check_exists &amp;&amp; @file_exists($file) == false) { return false; } return $file; } /** * remove fcgid related configuration files regeneration * * @return null */ private function cleanfcgidfiles() { (settings::get('system.mod_fcgid') == '0') { return; } // get correct directory $configdir = $this-&gt;getfile('system', 'mod_fcgid_configdir'); ($configdir !== false) { $configdir = filedir::makecorrectdir($configdir); (@is_dir($configdir)) { // create directory iterator $its = new recursiveiteratoriterator(new recursivedirectoryiterator($configdir)); // iterate subdirs, // look php-fcgi-starter files // take immutable-flag away // delete :) foreach ($its $it) { ($it-&gt;isfile() &amp;&amp; $it-&gt;getfilename() == 'php-fcgi-starter') { // set chattr -i filedir::removeimmutable($its-&gt;getpathname()); } } // get rid old stuff // (but append /* delete directory) $configdir .= '/*'; filedir::safe_exec('rm -rf ' . filedir::makecorrectfile($configdir)); } } } /** * remove php-fpm related configuration files regeneration * * @return null */ private function cleanfpmfiles() { (settings::get('phpfpm.enabled') == '0') { return; } // get fpm config paths $fpmconf_sel = database::prepare("select config_dir `" . table_panel_fpmdaemons . "`"); database::pexecute($fpmconf_sel); $fpmconf_paths = $fpmconf_sel-&gt;fetchall(pdo::fetch_assoc); // clean php-fpm config-dirs foreach ($fpmconf_paths $configdir) { $configdir = filedir::makecorrectdir($configdir['config_dir']); (@is_dir($configdir)) { // get rid old stuff // (but append /*.conf delete directory) $configdir .= '/*.conf'; filedir::safe_exec('rm -f ' . filedir::makecorrectfile($configdir)); } else { filedir::safe_exec('mkdir -p ' . $configdir); } } // also remove aliasconfigdir #1273 $aliasconfigdir = $this-&gt;getfile('phpfpm', 'aliasconfigdir'); ($aliasconfigdir !== false) { $aliasconfigdir = filedir::makecorrectdir($aliasconfigdir); (@is_dir($aliasconfigdir)) { $aliasconfigdir .= '/*'; filedir::safe_exec('rm -rf ' . filedir::makecorrectfile($aliasconfigdir)); } } } /** * remove webserver related configuration files regeneration * * @return null */ private function cleanwebserverconfigs() { // get directories $configdirs = []; $dir = $this-&gt;getfile('system', 'apacheconf_vhost'); ($dir !== false) { $configdirs[] = filedir::makecorrectdir($dir); } $dir = $this-&gt;getfile('system', 'apacheconf_diroptions'); ($dir !== false) { $configdirs[] = filedir::makecorrectdir($dir); } // file pattern $pattern = "/^([0-9]){2}_(froxlor|syscp)_(.+)\.conf$/"; // check folders foreach ($configdirs $config_dir) { // check directory (@is_dir($config_dir)) { // create directory iterator $its = new recursiveiteratoriterator(new recursivedirectoryiterator($config_dir)); // iterate subdirs, // look vhost/diroption files // delete foreach ($its $it) { ($it-&gt;isfile() &amp;&amp; preg_match($pattern, $it-&gt;getfilename())) { // remove file filedir::safe_exec('rm -f ' . escapeshellarg(filedir::makecorrectfile($its-&gt;getpathname()))); } } } } } /** * remove htpasswd files regeneration * * @return null */ private function cleanhtpasswdfiles() { // get correct directory $configdir = $this-&gt;getfile('system', 'apacheconf_htpasswddir'); ($configdir !== false) { $configdir = filedir::makecorrectdir($configdir); (@is_dir($configdir)) { // get rid old stuff // (but append /* delete directory) $configdir .= '/*'; filedir::safe_exec('rm -f ' . filedir::makecorrectfile($configdir)); } } } /** * remove customer-specified auto-generated ssl-certificates * (they regenerated) * * @return null */ private function cleancustomersslcerts() { /* * clean we're actually using ssl */ (settings::get('system.use_ssl') == '1') { // get correct directory $configdir = $this-&gt;getfile('system', 'customer_ssl_path'); ($configdir !== false) { $configdir = filedir::makecorrectdir($configdir); (@is_dir($configdir)) { // get rid old stuff // (but append /* delete directory) $configdir .= '/*'; filedir::safe_exec('rm -f ' . filedir::makecorrectfile($configdir)); } } } } }</file><file name="lib/Froxlor/Cron/Http/LighttpdFcgi.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http; use froxlor\cron\http\php\phpinterface; use froxlor\database\database; use froxlor\filedir; use froxlor\settings; class lighttpdfcgi extends lighttpd { public function createownvhoststarter() { (settings::get('phpfpm.enabled') == '1' &amp;&amp; settings::get('phpfpm.enabled_ownvhost') == '1') { $mypath = filedir::makecorrectdir(dirname(__file__, 3)); // /var/www/froxlor, needed chown $user = settings::get('phpfpm.vhost_httpuser'); $group = settings::get('phpfpm.vhost_httpgroup'); // get fpm config $fpm_sel_stmt = database::prepare(" select f.id `" . table_panel_fpmdaemons . "` f left join `" . table_panel_phpconfigs . "` p p.fpmsettingid = f.id p.id = :phpconfigid "); $fpm_config = database::pexecute_first($fpm_sel_stmt, [ 'phpconfigid' =&gt; settings::get('phpfpm.vhost_defaultini') ]); $domain = [ 'id' =&gt; 'none', 'domain' =&gt; settings::get('system.hostname'), 'adminid' =&gt; 1, /* first admin-user (superadmin) */ 'mod_fcgid_starter' =&gt; -1, 'mod_fcgid_maxrequests' =&gt; -1, 'guid' =&gt; $user, 'openbasedir' =&gt; 0, 'email' =&gt; settings::get('panel.adminmail'), 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath, 'fpm_config_id' =&gt; isset($fpm_config['id']) ? $fpm_config['id'] : 1 ]; // files folders belong local user // also use fcgid vhost filedir::safe_exec('chown -r ' . $user . ':' . $group . ' ' . escapeshellarg($mypath)); // get php.ini vhost $php = new phpinterface($domain); // get php-config (settings::get('phpfpm.enabled') == '1') { // fpm $phpconfig = $php-&gt;getphpconfig(settings::get('phpfpm.vhost_defaultini')); } else { // fcgid $phpconfig = $php-&gt;getphpconfig(settings::get('system.mod_fcgid_defaultini_ownvhost')); } // create starter-file | config-file $php-&gt;getinterface()-&gt;createconfig($phpconfig); // create php.ini (fpm nothing here, // defines ini-settings pool config) $php-&gt;getinterface()-&gt;createinifile($phpconfig); } } protected function composephpoptions(&amp;$domain) { $php_options_text = ''; ($domain['phpenabled_customer'] == 1 &amp;&amp; $domain['phpenabled_vhost'] == '1') { $php = new phpinterface($domain); $phpconfig = $php-&gt;getphpconfig((int)$domain['phpsettingid']); // vhost data php-fpm ((int)settings::get('phpfpm.enabled') == 1) { $domain['fpm_socket'] = $php-&gt;getinterface()-&gt;getsocketfile(); $php_options_text = ' fastcgi.server = ( ' . "\n"; $php_options_text .= "\t" . '".php" =&gt; (' . "\n"; $php_options_text .= "\t\t" . '"localhost" =&gt; (' . "\n"; $php_options_text .= "\t\t" . '"socket" =&gt; "' . $domain['fpm_socket'] . '",' . "\n"; $php_options_text .= "\t\t" . '"check-local" =&gt; "enable",' . "\n"; $php_options_text .= "\t\t" . '"disable-time" =&gt; 1' . "\n"; $php_options_text .= "\t" . ')' . "\n"; $php_options_text .= "\t" . ')' . "\n"; $php_options_text .= ' )' . "\n"; } elseif ((int)settings::get('system.mod_fcgid') == 1) { // vhost data fcgid $php_options_text = ' fastcgi.server = ( ' . "\n"; $file_extensions = explode(' ', $phpconfig['file_extensions']); foreach ($file_extensions $f_extension) { $php_options_text .= "\t" . '".' . $f_extension . '" =&gt; (' . "\n"; $php_options_text .= "\t\t" . '"localhost" =&gt; (' . "\n"; $php_options_text .= "\t\t" . '"socket" =&gt; "/var/run/lighttpd/' . $domain['loginname'] . '-' . $domain['domain'] . '-php.socket",' . "\n"; $php_options_text .= "\t\t" . '"bin-path" =&gt; "' . $phpconfig['binary'] . ' -c ' . $php-&gt;getinterface()-&gt;getinifile() . '",' . "\n"; $php_options_text .= "\t\t" . '"bin-environment" =&gt; (' . "\n"; ((int)$domain['mod_fcgid_starter'] != -1) { $php_options_text .= "\t\t\t" . '"php_fcgi_children" =&gt; "' . (int)$domain['mod_fcgid_starter'] . '",' . "\n"; } else { ((int)$phpconfig['mod_fcgid_starter'] != -1) { $php_options_text .= "\t\t\t" . '"php_fcgi_children" =&gt; "' . (int)$phpconfig['mod_fcgid_starter'] . '",' . "\n"; } else { $php_options_text .= "\t\t\t" . '"php_fcgi_children" =&gt; "' . (int)settings::get('system.mod_fcgid_starter') . '",' . "\n"; } } ((int)$domain['mod_fcgid_maxrequests'] != -1) { $php_options_text .= "\t\t\t" . '"php_fcgi_max_requests" =&gt; "' . (int)$domain['mod_fcgid_maxrequests'] . '"' . "\n"; } else { ((int)$phpconfig['mod_fcgid_maxrequests'] != -1) { $php_options_text .= "\t\t\t" . '"php_fcgi_max_requests" =&gt; "' . (int)$phpconfig['mod_fcgid_maxrequests'] . '"' . "\n"; } else { $php_options_text .= "\t\t\t" . '"php_fcgi_max_requests" =&gt; "' . (int)settings::get('system.mod_fcgid_maxrequests') . '"' . "\n"; } } $php_options_text .= "\t\t" . ')' . "\n"; $php_options_text .= "\t" . ')' . "\n"; $php_options_text .= "\t" . ')' . "\n"; } // foreach extension $php_options_text .= ' )' . "\n"; } // create starter-file | config-file $php-&gt;getinterface()-&gt;createconfig($phpconfig); // create php.ini (fpm nothing here, // defines ini-settings pool config) $php-&gt;getinterface()-&gt;createinifile($phpconfig); } else { $php_options_text .= ' # php disabled vhost' . "\n"; } return $php_options_text; } }</file><file name="lib/Froxlor/Cron/Http/Apache.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http; use froxlor\cron\http\php\phpinterface; use froxlor\cron\taskid; use froxlor\customer\customer; use froxlor\database\database; use froxlor\domain\domain; use froxlor\filedir; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\http\directory; use froxlor\http\statistics; use froxlor\phphelper; use froxlor\settings; use froxlor\system\cronjob; use froxlor\system\crypt; use froxlor\validate\validate; use pdo; class apache extends httpconfigbase { // protected protected $known_diroptionsfilenames = []; protected $known_htpasswdsfilenames = []; protected $virtualhosts_data = []; protected $diroptions_data = []; protected $htpasswds_data = []; /** * indicator whether customer deactivated * yes, webroot generated * * @var bool */ private $deactivated = false; public function createipport() { $result_ipsandports_stmt = database::query("select * `" . table_panel_ipsandports . "` order `ip` asc, `port` asc"); ($row_ipsandports = $result_ipsandports_stmt-&gt;fetch(pdo::fetch_assoc)) { (filter_var($row_ipsandports['ip'], filter_validate_ip, filter_flag_ipv6)) { $ipport = '[' . $row_ipsandports['ip'] . ']:' . $row_ipsandports['port']; } else { $ipport = $row_ipsandports['ip'] . ':' . $row_ipsandports['port']; } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'apache::createipport: creating ip/port settings ' . $ipport); $vhosts_filename = filedir::makecorrectfile(settings::get('system.apacheconf_vhost') . '/10_froxlor_ipandport_' . trim(str_replace(':', '.', $row_ipsandports['ip']), '.') . '.' . $row_ipsandports['port'] . '.conf'); (!isset($this-&gt;virtualhosts_data[$vhosts_filename])) { $this-&gt;virtualhosts_data[$vhosts_filename] = ''; } ($row_ipsandports['listen_statement'] == '1') { $this-&gt;virtualhosts_data[$vhosts_filename] .= 'listen ' . $ipport . "\n"; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, $ipport . ' :: inserted listen-statement'); } ($row_ipsandports['namevirtualhost_statement'] == '1') { // &gt;=apache-2.4 enabled? (settings::get('system.apache24') == '1') { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, $ipport . ' :: namevirtualhost-statement longer needed apache-2.4'); } else { $this-&gt;virtualhosts_data[$vhosts_filename] .= 'namevirtualhost ' . $ipport . "\n"; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, $ipport . ' :: inserted namevirtualhost-statement'); } } ($row_ipsandports['vhostcontainer'] == '1') { $without_vhost = $this-&gt;virtualhosts_data[$vhosts_filename]; $close_vhost = true; $this-&gt;virtualhosts_data[$vhosts_filename] .= '&lt;virtualhost ' . $ipport . '&gt;' . "\n"; $mypath = $this-&gt;getmypath($row_ipsandports); $this-&gt;virtualhosts_data[$vhosts_filename] .= 'documentroot "' . rtrim($mypath, "/") . '"' . "\n"; ($row_ipsandports['vhostcontainer_servername_statement'] == '1') { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' servername ' . settings::get('system.hostname') . "\n"; $froxlor_aliases = settings::get('system.froxloraliases'); (!empty($froxlor_aliases)) { $froxlor_aliases = explode(",", $froxlor_aliases); $aliases = ""; foreach ($froxlor_aliases $falias) { (validate::validatedomain(trim($falias))) { $aliases .= trim($falias) . " "; } } $aliases = trim($aliases); (!empty($aliases)) { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' serveralias ' . $aliases . "\n"; } } } $is_redirect = false; // check ssl redirect ($row_ipsandports['ssl'] == '0' &amp;&amp; settings::get('system.le_froxlor_redirect') == '1') { $is_redirect = true; // check whether froxlor uses let's encrypt cert generated yet // renewal ongoing - disable redirect (settings::get('system.le_froxlor_enabled') &amp;&amp; ($this-&gt;froxlorvhosthasletsencryptcert() == false || $this-&gt;froxlorvhostletsencryptneedsrenew())) { $this-&gt;virtualhosts_data[$vhosts_filename] .= '# temp. disabled ssl-redirect due let\'s encrypt certificate generation.' . php_eol; $is_redirect = false; cronjob::inserttask(taskid::rebuild_vhost); } else { $_sslport = $this-&gt;checkalternativesslport(); $mypath = 'https://' . settings::get('system.hostname') . $_sslport . '/'; $code = '301'; $modrew_red = ' [r=' . $code . ';l,ne]'; // redirect everything, root-directory, #541 $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;ifmodule mod_rewrite.c&gt;' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' rewriteengine on' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' rewritecond %{https} off' . "\n"; (settings::get('system.le_froxlor_enabled') == '1') { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' rewritecond %{request_uri} !^/\.well-known/acme-challenge' . "\n"; } $this-&gt;virtualhosts_data[$vhosts_filename] .= ' rewriterule ^/(.*) ' . $mypath . '$1' . $modrew_red . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;/ifmodule&gt;' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;ifmodule !mod_rewrite.c&gt;' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' redirect ' . $code . ' / ' . $mypath . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;/ifmodule&gt;' . "\n"; } } (!$is_redirect) { (settings::get('system.froxlordirectlyviahostname')) { $relpath = "/"; } else { $relpath = "/" . basename(froxlor::getinstalldir()); } // protect lib/userdata.inc.php $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;directory "' . rtrim($relpath, "/") . '/lib/"&gt;' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;files "userdata.inc.php"&gt;' . "\n"; (settings::get('system.apache24') == '1') { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' require denied' . "\n"; } else { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' order deny,allow' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' deny all' . "\n"; } $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;/files&gt;' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;/directory&gt;' . "\n"; // protect bin/ $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;directorymatch "^' . rtrim($relpath, "/") . '/(bin|cache|logs|tests|vendor)/"&gt;' . "\n"; (settings::get('system.apache24') == '1') { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' require denied' . "\n"; } else { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' order deny,allow' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' deny all' . "\n"; } $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;/directorymatch&gt;' . "\n"; // create fcgid &lt;directory&gt;-part (starter created apache_fcgid) (settings::get('system.mod_fcgid_ownvhost') == '1' &amp;&amp; settings::get('system.mod_fcgid') == '1') { $configdir = filedir::makecorrectdir(settings::get('system.mod_fcgid_configdir') . '/froxlor.panel/' . settings::get('system.hostname')); $this-&gt;virtualhosts_data[$vhosts_filename] .= ' fcgididletimeout ' . settings::get('system.mod_fcgid_idle_timeout') . "\n"; ((int)settings::get('system.mod_fcgid_wrapper') == 0) { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' suexecusergroup "' . settings::get('system.mod_fcgid_httpuser') . '" "' . settings::get('system.mod_fcgid_httpgroup') . '"' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' scriptalias /php/ ' . $configdir . "\n"; } else { $domain = [ 'id' =&gt; 'none', 'domain' =&gt; settings::get('system.hostname'), 'adminid' =&gt; 1, /* first admin-user (superadmin) */ 'mod_fcgid_starter' =&gt; -1, 'mod_fcgid_maxrequests' =&gt; -1, 'guid' =&gt; settings::get('system.mod_fcgid_httpuser'), 'openbasedir' =&gt; 0, 'email' =&gt; settings::get('panel.adminmail'), 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath ]; $php = new phpinterface($domain); $phpconfig = $php-&gt;getphpconfig(settings::get('system.mod_fcgid_defaultini_ownvhost')); ($phpconfig['pass_authorizationheader'] == '1') { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' fcgidpassheader authorization' . "\n"; } $starter_filename = filedir::makecorrectfile($configdir . '/php-fcgi-starter'); $this-&gt;virtualhosts_data[$vhosts_filename] .= ' suexecusergroup "' . settings::get('system.mod_fcgid_httpuser') . '" "' . settings::get('system.mod_fcgid_httpgroup') . '"' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;directory "' . $mypath . '"&gt;' . "\n"; $file_extensions = explode(' ', $phpconfig['file_extensions']); $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;filesmatch "\.(' . implode('|', $file_extensions) . ')$"&gt;' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sethandler fcgid-script' . "\n"; foreach ($file_extensions $file_extension) { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' fcgidwrapper ' . $starter_filename . ' .' . $file_extension . "\n"; } $this-&gt;virtualhosts_data[$vhosts_filename] .= ' options +execcgi' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;/filesmatch&gt;' . "\n"; // &gt;=apache-2.4 enabled? (settings::get('system.apache24') == '1') { $mypath_dir = new directory($mypath); // create require granted active directory-protection // path, would first require therefore grant access ($mypath_dir-&gt;isuserprotected() == false) { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' require granted' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' allowoverride all' . "\n"; } } else { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' order allow,deny' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' allow all' . "\n"; } $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;/directory&gt;' . "\n"; } } elseif (settings::get('phpfpm.enabled') == '1' &amp;&amp; (int)settings::get('phpfpm.enabled_ownvhost') == 1) { // get fpm config $fpm_sel_stmt = database::prepare(" select f.id `" . table_panel_fpmdaemons . "` f left join `" . table_panel_phpconfigs . "` p p.fpmsettingid = f.id p.id = :phpconfigid "); $fpm_config = database::pexecute_first($fpm_sel_stmt, [ 'phpconfigid' =&gt; settings::get('phpfpm.vhost_defaultini') ]); // create php-fpm &lt;directory&gt;-part (config created apache_fcgid) $domain = [ 'id' =&gt; 'none', 'domain' =&gt; settings::get('system.hostname'), 'adminid' =&gt; 1, /* first admin-user (superadmin) */ 'mod_fcgid_starter' =&gt; -1, 'mod_fcgid_maxrequests' =&gt; -1, 'guid' =&gt; settings::get('phpfpm.vhost_httpuser'), 'openbasedir' =&gt; 0, 'email' =&gt; settings::get('panel.adminmail'), 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath, 'fpm_config_id' =&gt; isset($fpm_config['id']) ? $fpm_config['id'] : 1 ]; $php = new phpinterface($domain); $phpconfig = $php-&gt;getphpconfig(settings::get('phpfpm.vhost_defaultini')); $srvname = substr(md5($ipport), 0, 4) . '.fpm.external'; ($row_ipsandports['ssl']) { $srvname = substr(md5($ipport), 0, 4) . '.ssl-fpm.external'; } // mod_proxy stuff apache-2.4 (settings::get('system.apache24') == '1' &amp;&amp; settings::get('phpfpm.use_mod_proxy') == '1') { $filesmatch = $phpconfig['fpm_settings']['limit_extensions']; $extensions = explode(" ", $filesmatch); $filesmatch = ""; foreach ($extensions $ext) { $filesmatch .= substr($ext, 1) . '|'; } // start block, cut last pipe close block $filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, -1)) . ')'; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;filesmatch \.' . $filesmatch . '$&gt;' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;if "-f %{script_filename}"&gt;' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sethandler proxy:unix:' . $php-&gt;getinterface()-&gt;getsocketfile() . '|fcgi://localhost' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;/if&gt;' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;/filesmatch&gt;' . "\n"; ($phpconfig['pass_authorizationheader'] == '1') { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;directory "' . $mypath . '"&gt;' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' cgipassauth on' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;/directory&gt;' . "\n"; } } else { $addheader = ""; ($phpconfig['pass_authorizationheader'] == '1') { $addheader = " -pass-header authorization"; } $this-&gt;virtualhosts_data[$vhosts_filename] .= ' fastcgiexternalserver ' . $php-&gt;getinterface()-&gt;getaliasconfigdir() . $srvname . ' -socket ' . $php-&gt;getinterface()-&gt;getsocketfile() . ' -idle-timeout ' . $phpconfig['fpm_settings']['idle_timeout'] . $addheader . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;directory "' . $mypath . '"&gt;' . "\n"; $filesmatch = $phpconfig['fpm_settings']['limit_extensions']; $extensions = explode(" ", $filesmatch); $filesmatch = ""; foreach ($extensions $ext) { $filesmatch .= substr($ext, 1) . '|'; } // start block, cut last pipe close block $filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, -1)) . ')'; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;filesmatch \.' . $filesmatch . '$&gt;' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' addhandler php-fastcgi .php' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' action php-fastcgi /fastcgiphp' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' options +execcgi' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;/filesmatch&gt;' . "\n"; // &gt;=apache-2.4 enabled? (settings::get('system.apache24') == '1') { $mypath_dir = new directory($mypath); // create require granted active directory-protection // path, would first require therefore grant access ($mypath_dir-&gt;isuserprotected() == false) { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' require granted' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' allowoverride all' . "\n"; } } else { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' order allow,deny' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' allow all' . "\n"; } $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;/directory&gt;' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' alias /fastcgiphp ' . $php-&gt;getinterface()-&gt;getaliasconfigdir() . $srvname . "\n"; } } else { // mod_php $domain = [ 'id' =&gt; 'none', 'domain' =&gt; settings::get('system.hostname'), 'adminid' =&gt; 1, /* first admin-user (superadmin) */ 'guid' =&gt; settings::get('system.httpuser'), 'openbasedir' =&gt; 0, 'email' =&gt; settings::get('panel.adminmail'), 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath ]; } // end ssl-redirect check } else { // fallback froxlor domain-data processspecialconfigtemplate() $domain = [ 'domain' =&gt; settings::get('system.hostname'), 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath ]; } /** * dirprotection, see #72 * * @todo deferred 0.9.5, needs testing * $this-&gt;virtualhosts_data[$vhosts_filename] .= "\t&lt;directory \"'.$mypath.'(images|packages|templates)\"&gt;\n"; * $this-&gt;virtualhosts_data[$vhosts_filename] .= "\t\tallow all\n"; * $this-&gt;virtualhosts_data[$vhosts_filename] .= "\t\toptions -indexes\n"; * $this-&gt;virtualhosts_data[$vhosts_filename] .= "\t&lt;/directory&gt;\n"; * * $this-&gt;virtualhosts_data[$vhosts_filename] .= "\t&lt;directory \"'.$mypath.'*\"&gt;\n"; * $this-&gt;virtualhosts_data[$vhosts_filename] .= "\t\torder deny,allow\n"; * $this-&gt;virtualhosts_data[$vhosts_filename] .= "\t\tdeny all\n"; * $this-&gt;virtualhosts_data[$vhosts_filename] .= "\t&lt;/directory&gt;\n"; * end dirprotection */ ($row_ipsandports['specialsettings'] != '' &amp;&amp; ($row_ipsandports['ssl'] == '0' || ($row_ipsandports['ssl'] == '1' &amp;&amp; settings::get('system.use_ssl') == '1' &amp;&amp; $row_ipsandports['include_specialsettings'] == '1'))) { $this-&gt;virtualhosts_data[$vhosts_filename] .= $this-&gt;processspecialconfigtemplate($row_ipsandports['specialsettings'], $domain, $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n"; } ($row_ipsandports['ssl'] == '1' &amp;&amp; settings::get('system.use_ssl') == '1') { ($row_ipsandports['ssl_specialsettings'] != '') { $this-&gt;virtualhosts_data[$vhosts_filename] .= $this-&gt;processspecialconfigtemplate($row_ipsandports['ssl_specialsettings'], $domain, $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n"; } // check required fallback (($row_ipsandports['ssl_cert_file'] == '' || !file_exists($row_ipsandports['ssl_cert_file'])) &amp;&amp; (settings::get('system.le_froxlor_enabled') == '0' || $this-&gt;froxlorvhosthasletsencryptcert() == false)) { $row_ipsandports['ssl_cert_file'] = settings::get('system.ssl_cert_file'); (!file_exists($row_ipsandports['ssl_cert_file'])) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, 'system certificate file "' . settings::get('system.ssl_cert_file') . '" seem exist. creating self-signed certificate...'); crypt::createselfsignedcertificate(); } } ($row_ipsandports['ssl_key_file'] == '') { $row_ipsandports['ssl_key_file'] = settings::get('system.ssl_key_file'); (!file_exists($row_ipsandports['ssl_key_file'])) { // explicitly disable ssl vhost $row_ipsandports['ssl_cert_file'] = ""; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, 'system certificate key-file "' . settings::get('system.ssl_key_file') . '" seem exist. disabling ssl-vhost "' . settings::get('system.hostname') . '"'); } } ($row_ipsandports['ssl_ca_file'] == '') { $row_ipsandports['ssl_ca_file'] = settings::get('system.ssl_ca_file'); } // #418 ($row_ipsandports['ssl_cert_chainfile'] == '') { $row_ipsandports['ssl_cert_chainfile'] = settings::get('system.ssl_cert_chainfile'); } $domain = [ 'id' =&gt; 0, 'domain' =&gt; settings::get('system.hostname'), 'adminid' =&gt; 1, /* first admin-user (superadmin) */ 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath, 'parentdomainid' =&gt; 0, 'ssl_honorcipherorder' =&gt; settings::get('system.honorcipherorder'), 'ssl_sessiontickets' =&gt; settings::get('system.sessiontickets') ]; // override corresponding array values $domain['ssl_cert_file'] = $row_ipsandports['ssl_cert_file']; $domain['ssl_key_file'] = $row_ipsandports['ssl_key_file']; $domain['ssl_ca_file'] = $row_ipsandports['ssl_ca_file']; $domain['ssl_cert_chainfile'] = $row_ipsandports['ssl_cert_chainfile']; // ssl stuff $dssl = new domainssl(); // sets ssl-related array-indices $domain array // domain customer-defined ssl-certificates $dssl-&gt;setdomainsslfilesarray($domain); ($domain['ssl_cert_file'] != '') { // check existence, #1485 (!file_exists($domain['ssl_cert_file'])) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, $ipport . ' :: certificate file "' . $domain['ssl_cert_file'] . '" exist! cannot create ssl-directives'); } else { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sslengine on' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sslprotocol -all +' . str_replace(",", " +", settings::get('system.ssl_protocols')) . "\n"; (settings::get('system.apache24') == '1') { (settings::get('system.http2_support') == '1') { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' protocols h2 http/1.1' . "\n"; } (!empty(settings::get('system.dhparams_file'))) { $dhparams = filedir::makecorrectfile(settings::get('system.dhparams_file')); (!file_exists($dhparams)) { file_put_contents($dhparams, self::ffdhe4096); } $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sslopensslconfcmd dhparameters "' . $dhparams . '"' . "\n"; } $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sslcompression off' . "\n"; (settings::get('system.sessionticketsenabled') == '1') { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sslsessiontickets ' . ($domain['ssl_sessiontickets'] == '1' ? 'on' : 'off') . "\n"; } } $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sslhonorcipherorder ' . ($domain['ssl_honorcipherorder'] == '1' ? 'on' : 'off') . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sslciphersuite ' . settings::get('system.ssl_cipher_list') . "\n"; $protocols = array_map('trim', explode(",", settings::get('system.ssl_protocols'))); (in_array("tlsv1.3", $protocols) &amp;&amp; !empty(settings::get('system.tlsv13_cipher_list')) &amp;&amp; settings::get('system.apache24') == 1) { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sslciphersuite tlsv1.3 ' . settings::get('system.tlsv13_cipher_list') . "\n"; } $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sslverifydepth 10' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sslcertificatefile ' . filedir::makecorrectfile($domain['ssl_cert_file']) . "\n"; ($domain['ssl_key_file'] != '') { // check existence, #1485 (!file_exists($domain['ssl_key_file'])) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, $ipport . ' :: certificate key file "' . $domain['ssl_key_file'] . '" exist! cannot create ssl-directives'); } else { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sslcertificatekeyfile ' . filedir::makecorrectfile($domain['ssl_key_file']) . "\n"; } } ($domain['ssl_ca_file'] != '') { // check existence, #1485 (!file_exists($domain['ssl_ca_file'])) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, $ipport . ' :: certificate ca file "' . $domain['ssl_ca_file'] . '" exist! cannot create ssl-directives'); } else { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sslcacertificatefile ' . filedir::makecorrectfile($domain['ssl_ca_file']) . "\n"; } } // #418 ($domain['ssl_cert_chainfile'] != '') { // check existence, #1485 (!file_exists($domain['ssl_cert_chainfile'])) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, $ipport . ' :: certificate chain file "' . $domain['ssl_cert_chainfile'] . '" exist! cannot create ssl-directives'); } else { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' sslcertificatechainfile ' . filedir::makecorrectfile($domain['ssl_cert_chainfile']) . "\n"; } } } } else { // cert-file specified generating ssl-vhost, // return empty string vhost would suck dick, ref #1583 froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, $domain['domain'] . ' :: empty certificate file! cannot create ssl-directives'); $this-&gt;virtualhosts_data[$vhosts_filename] = $without_vhost; $this-&gt;virtualhosts_data[$vhosts_filename] .= '# ssl-certificate specified domain, therefore explicit vhost-container generated'; $close_vhost = false; } } ($close_vhost) { $this-&gt;virtualhosts_data[$vhosts_filename] .= '&lt;/virtualhost&gt;' . "\n"; } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, $ipport . ' :: inserted vhostcontainer'); } unset($vhosts_filename); } /** * bug #32 */ $this-&gt;createstandarddirectoryentry(); /** * bug #unknown-yet */ $this-&gt;createstandarderrorhandler(); } /** * define standard &lt;directory&gt;-statement, bug #32 */ private function createstandarddirectoryentry() { $vhosts_filename = $this-&gt;getcustomvhostfilename('05_froxlor_dirfix_nofcgid.conf'); (!isset($this-&gt;virtualhosts_data[$vhosts_filename])) { $this-&gt;virtualhosts_data[$vhosts_filename] = ''; } $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;directory "' . filedir::makecorrectdir(settings::get('system.documentroot_prefix')) . '"&gt;' . "\n"; // check custom values, see #1638 $custom_opts = settings::get('system.apacheglobaldiropt'); (!empty($custom_opts)) { $this-&gt;virtualhosts_data[$vhosts_filename] .= $custom_opts . "\n"; } else { // &gt;=apache-2.4 enabled? (settings::get('system.apache24') == '1') { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' require granted' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' allowoverride all' . "\n"; } else { $this-&gt;virtualhosts_data[$vhosts_filename] .= ' order allow,deny' . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename] .= ' allow all' . "\n"; } } $this-&gt;virtualhosts_data[$vhosts_filename] .= ' &lt;/directory&gt;' . "\n"; $ocsp_cache_filename = $this-&gt;getcustomvhostfilename('03_froxlor_ocsp_cache.conf'); (settings::get('system.use_ssl') == '1' &amp;&amp; settings::get('system.apache24') == 1) { $this-&gt;virtualhosts_data[$ocsp_cache_filename] = 'sslstaplingcache ' . settings::get('system.apache24_ocsp_cache_path') . "\n"; } else { (file_exists($ocsp_cache_filename)) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'apache::_createstandarddirectoryentry: unlinking ' . basename($ocsp_cache_filename)); unlink(filedir::makecorrectfile($ocsp_cache_filename)); } } } /** * define default errordocument-statement, bug #unknown-yet */ private function createstandarderrorhandler() { (settings::get('defaultwebsrverrhandler.enabled') == '1' &amp;&amp; (settings::get('defaultwebsrverrhandler.err401') != '' || settings::get('defaultwebsrverrhandler.err403') != '' || settings::get('defaultwebsrverrhandler.err404') != '' || settings::get('defaultwebsrverrhandler.err500') != '')) { $vhosts_filename = $this-&gt;getcustomvhostfilename('05_froxlor_default_errorhandler.conf'); (!isset($this-&gt;virtualhosts_data[$vhosts_filename])) { $this-&gt;virtualhosts_data[$vhosts_filename] = ''; } $statuscodes = [ '401', '403', '404', '500' ]; foreach ($statuscodes $statuscode) { (settings::get('defaultwebsrverrhandler.err' . $statuscode) != '') { $defhandler = settings::get('defaultwebsrverrhandler.err' . $statuscode); (!validate::validateurl($defhandler)) { (substr($defhandler, 0, 1) != '"' &amp;&amp; substr($defhandler, -1, 1) != '"') { $defhandler = '"' . filedir::makecorrectfile($defhandler) . '"'; } } $this-&gt;virtualhosts_data[$vhosts_filename] .= 'errordocument ' . $statuscode . ' ' . $defhandler . "\n"; } } } } public function createownvhoststarter() { return; } /** * compose virtualhost entries domains */ public function createvirtualhosts() { $domains = webserverbase::getvhoststocreate(); foreach ($domains $domain) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'apache::createvirtualhosts: creating vhost container domain ' . $domain['id'] . ', customer ' . $domain['loginname']); $vhosts_filename = $this-&gt;getvhostfilename($domain); // apply header $this-&gt;virtualhosts_data[$vhosts_filename] = '# domain id: ' . $domain['id'] . ' - customerid: ' . $domain['customerid'] . ' - customerlogin: ' . $domain['loginname'] . "\n"; $ddr = settings::get('system.deactivateddocroot'); (($domain['deactivated'] == '1' || $domain['customer_deactivated'] == '1') &amp;&amp; empty($ddr)) { $this-&gt;virtualhosts_data[$vhosts_filename] .= '# customer/domain deactivated docroot deactivated users hasn\'t set.' . "\n"; } else { // create vhost without ssl $this-&gt;virtualhosts_data[$vhosts_filename] .= $this-&gt;getvhostcontent($domain, false); ($domain['ssl_enabled'] == '1' &amp;&amp; ($domain['ssl'] == '1' || $domain['ssl_redirect'] == '1')) { // adding ssl stuff enabled $vhosts_filename_ssl = $this-&gt;getvhostfilename($domain, true); $this-&gt;virtualhosts_data[$vhosts_filename_ssl] = '# domain id: ' . $domain['id'] . ' (ssl) - customerid: ' . $domain['customerid'] . ' - customerlogin: ' . $domain['loginname'] . "\n"; $this-&gt;virtualhosts_data[$vhosts_filename_ssl] .= $this-&gt;getvhostcontent($domain, true); } } } } /** * compose virtualhost entry one domain */ protected function getvhostcontent($domain, $ssl_vhost = false) { ($ssl_vhost === true &amp;&amp; ($domain['ssl_redirect'] != '1' &amp;&amp; $domain['ssl'] != '1')) { return ''; } $query = "select * `" . table_panel_ipsandports . "` `i`, `" . table_domaintoip . "` `dip` dip.id_domain = :domainid i.id = dip.id_ipandports "; ($ssl_vhost === true &amp;&amp; ($domain['ssl'] == '1' || $domain['ssl_redirect'] == '1')) { // ordering cert-file row filled ssl-fields shown last, thus enough fill 1 set ssl-fields $query .= "and i.ssl = '1' order i.ssl_cert_file asc;"; } else { $query .= "and i.ssl = '0';"; } $vhost_content = ''; $result_stmt = database::prepare($query); database::pexecute($result_stmt, [ 'domainid' =&gt; $domain['id'] ]); $ipportlist = ''; $_vhost_content = ''; ($ipandport = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $ipport = ''; $domain['ip'] = $ipandport['ip']; $domain['port'] = $ipandport['port']; ($domain['ssl'] == '1') { $domain['ssl_cert_file'] = $ipandport['ssl_cert_file']; $domain['ssl_key_file'] = $ipandport['ssl_key_file']; $domain['ssl_ca_file'] = $ipandport['ssl_ca_file']; $domain['ssl_cert_chainfile'] = $ipandport['ssl_cert_chainfile']; // ssl stuff $dssl = new domainssl(); // sets ssl-related array-indices $domain array // domain customer-defined ssl-certificates $dssl-&gt;setdomainsslfilesarray($domain); } (filter_var($domain['ip'], filter_validate_ip, filter_flag_ipv6)) { $ipport = '[' . $domain['ip'] . ']:' . $domain['port'] . ' '; } else { $ipport = $domain['ip'] . ':' . $domain['port'] . ' '; } ($ipandport['default_vhostconf_domain'] != '' &amp;&amp; ($ssl_vhost == false || ($ssl_vhost == true &amp;&amp; $ipandport['include_default_vhostconf_domain'] == '1'))) { $_vhost_content .= $this-&gt;processspecialconfigtemplate($ipandport['default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } ($ipandport['ssl_default_vhostconf_domain'] != '' &amp;&amp; $ssl_vhost == true) { $_vhost_content .= $this-&gt;processspecialconfigtemplate($ipandport['ssl_default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } $ipportlist .= $ipport; } $vhost_content .= '&lt;virtualhost ' . trim($ipportlist) . '&gt;' . "\n"; $vhost_content .= $this-&gt;getservernames($domain); $domain['documentroot_norewrite'] = $domain['documentroot']; (($ssl_vhost == false &amp;&amp; $domain['ssl'] == '1' &amp;&amp; $domain['ssl_redirect'] == '1')) { // must check port differs port 443, // destination-port != 443 $_sslport = ''; // returns first port != 443 ssl enabled, // ordered ssl-certificate (if any) ip/port combo // certificate used $ssldestport_stmt = database::prepare(" select `ip`.`port` " . table_panel_ipsandports . " `ip` left join `" . table_domaintoip . "` `dip` (`ip`.`id` = `dip`.`id_ipandports`) `dip`.`id_domain` = :domainid `ip`.`ssl` = '1' `ip`.`port` != 443 order `ip`.`ssl_cert_file` desc, `ip`.`port` limit 1; "); $ssldestport = database::pexecute_first($ssldestport_stmt, [ 'domainid' =&gt; $domain['id'] ]); ($ssldestport &amp;&amp; $ssldestport['port'] != '') { $_sslport = ":" . $ssldestport['port']; } $domain['documentroot'] = 'https://%{http_host}' . $_sslport . '/'; $domain['documentroot_norewrite'] = 'https://' . $domain['domain'] . $_sslport . '/'; } ($ssl_vhost === true &amp;&amp; $domain['ssl'] == '1' &amp;&amp; settings::get('system.use_ssl') == '1') { ($domain['ssl_cert_file'] == '' || !file_exists($domain['ssl_cert_file'])) { $domain['ssl_cert_file'] = settings::get('system.ssl_cert_file'); (!file_exists($domain['ssl_cert_file'])) { // explicitly disable ssl vhost $domain['ssl_cert_file'] = ""; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, 'system certificate file "' . settings::get('system.ssl_cert_file') . '" seem exist. disabling ssl-vhost "' . $domain['domain'] . '"'); } } ($domain['ssl_key_file'] == '' || !file_exists($domain['ssl_key_file'])) { $domain['ssl_key_file'] = settings::get('system.ssl_key_file'); (!file_exists($domain['ssl_key_file'])) { // explicitly disable ssl vhost $domain['ssl_cert_file'] = ""; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, 'system certificate key-file "' . settings::get('system.ssl_key_file') . '" seem exist. disabling ssl-vhost "' . $domain['domain'] . '"'); } } ($domain['ssl_ca_file'] == '') { $domain['ssl_ca_file'] = settings::get('system.ssl_ca_file'); } ($domain['ssl_cert_chainfile'] == '') { $domain['ssl_cert_chainfile'] = settings::get('system.ssl_cert_chainfile'); } ($domain['ssl_cert_file'] != '') { $ssl_protocols = ($domain['override_tls'] == '1' &amp;&amp; !empty($domain['ssl_protocols'])) ? $domain['ssl_protocols'] : settings::get('system.ssl_protocols'); $ssl_cipher_list = ($domain['override_tls'] == '1' &amp;&amp; !empty($domain['ssl_cipher_list'])) ? $domain['ssl_cipher_list'] : settings::get('system.ssl_cipher_list'); $tlsv13_cipher_list = ($domain['override_tls'] == '1' &amp;&amp; !empty($domain['tlsv13_cipher_list'])) ? $domain['tlsv13_cipher_list'] : settings::get('system.tlsv13_cipher_list'); $vhost_content .= ' sslengine on' . "\n"; $vhost_content .= ' sslprotocol -all +' . str_replace(",", " +", $ssl_protocols) . "\n"; (settings::get('system.apache24') == '1') { (isset($domain['http2']) &amp;&amp; $domain['http2'] == '1' &amp;&amp; settings::get('system.http2_support') == '1') { $vhost_content .= ' protocols h2 http/1.1' . "\n"; } (!empty(settings::get('system.dhparams_file'))) { $dhparams = filedir::makecorrectfile(settings::get('system.dhparams_file')); (!file_exists($dhparams)) { file_put_contents($dhparams, self::ffdhe4096); } $vhost_content .= ' sslopensslconfcmd dhparameters "' . $dhparams . '"' . "\n"; } $vhost_content .= ' sslcompression off' . "\n"; (settings::get('system.sessionticketsenabled') == '1') { $vhost_content .= ' sslsessiontickets ' . ($domain['ssl_sessiontickets'] == '1' ? 'on' : 'off') . "\n"; } } $vhost_content .= ' sslhonorcipherorder ' . ($domain['ssl_honorcipherorder'] == '1' ? 'on' : 'off') . "\n"; $vhost_content .= ' sslciphersuite ' . $ssl_cipher_list . "\n"; $protocols = array_map('trim', explode(",", $ssl_protocols)); (in_array("tlsv1.3", $protocols) &amp;&amp; !empty($tlsv13_cipher_list) &amp;&amp; settings::get('system.apache24') == 1) { $vhost_content .= ' sslciphersuite tlsv1.3 ' . $tlsv13_cipher_list . "\n"; } $vhost_content .= ' sslverifydepth 10' . "\n"; $vhost_content .= ' sslcertificatefile ' . filedir::makecorrectfile($domain['ssl_cert_file']) . "\n"; ($domain['ssl_key_file'] != '') { $vhost_content .= ' sslcertificatekeyfile ' . filedir::makecorrectfile($domain['ssl_key_file']) . "\n"; } ($domain['ssl_ca_file'] != '') { $vhost_content .= ' sslcacertificatefile ' . filedir::makecorrectfile($domain['ssl_ca_file']) . "\n"; } ($domain['ssl_cert_chainfile'] != '') { $vhost_content .= ' sslcertificatechainfile ' . filedir::makecorrectfile($domain['ssl_cert_chainfile']) . "\n"; } (settings::get('system.apache24') == '1' &amp;&amp; isset($domain['ocsp_stapling']) &amp;&amp; $domain['ocsp_stapling'] == '1') { $vhost_content .= ' sslusestapling on' . php_eol; } ($domain['hsts'] &gt;= 0) { $vhost_content .= ' &lt;ifmodule mod_headers.c&gt;' . "\n"; $vhost_content .= ' header always set strict-transport-security "max-age=' . $domain['hsts']; ($domain['hsts_sub'] == 1) { $vhost_content .= '; includesubdomains'; } ($domain['hsts_preload'] == 1) { $vhost_content .= '; preload'; } $vhost_content .= '"' . "\n"; $vhost_content .= ' &lt;/ifmodule&gt;' . "\n"; } } else { // cert-file specified generating ssl-vhost, // return empty string vhost would suck dick, ref #1583 froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, $domain['domain'] . ' :: empty certificate file! cannot create ssl-directives'); return '# ssl-certificate specified domain, therefore explicit vhost generated'; } } // avoid using whitespaces $domain['documentroot'] = trim($domain['documentroot']); (preg_match('/^https?\:\/\//', $domain['documentroot'])) { $possible_deactivated_webroot = $this-&gt;getwebroot($domain); ($this-&gt;deactivated == false) { $corrected_docroot = $domain['documentroot']; // get domain's redirect code $code = domain::getdomainredirectcode($domain['id']); $modrew_red = ''; ($code != '') { $modrew_red = ' [r=' . $code . ';l,ne]'; } $vhost_content .= $this-&gt;getlogfiles($domain); // redirect everything, root-directory, #541 $vhost_content .= ' &lt;ifmodule mod_rewrite.c&gt;' . "\n"; $vhost_content .= ' rewriteengine on' . "\n"; (!$ssl_vhost) { $vhost_content .= ' rewritecond %{https} off' . "\n"; } ($domain['letsencrypt'] == '1') { $vhost_content .= ' rewritecond %{request_uri} !^/\.well-known/acme-challenge' . "\n"; } $vhost_content .= ' rewriterule ^/(.*) ' . $corrected_docroot . '$1' . $modrew_red . "\n"; $vhost_content .= ' &lt;/ifmodule&gt;' . "\n"; $vhost_content .= ' &lt;ifmodule !mod_rewrite.c&gt;' . "\n"; $vhost_content .= ' redirect ' . $code . ' / ' . $domain['documentroot_norewrite'] . "\n"; $vhost_content .= ' &lt;/ifmodule&gt;' . "\n"; } elseif (settings::get('system.deactivateddocroot') != '') { $vhost_content .= $possible_deactivated_webroot; } } else { filedir::mkdirwithcorrectownership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true, true); $vhost_content .= $this-&gt;getwebroot($domain); ($this-&gt;deactivated == false) { $vhost_content .= $this-&gt;composephpoptions($domain, $ssl_vhost); $vhost_content .= $this-&gt;getstats($domain); } $vhost_content .= $this-&gt;getlogfiles($domain); ($this-&gt;deactivated == false) { ($domain['specialsettings'] != '' &amp;&amp; ($ssl_vhost == false || ($ssl_vhost == true &amp;&amp; $domain['include_specialsettings'] == 1))) { $vhost_content .= $this-&gt;processspecialconfigtemplate($domain['specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } ($domain['ssl_specialsettings'] != '' &amp;&amp; $ssl_vhost == true) { $vhost_content .= $this-&gt;processspecialconfigtemplate($domain['ssl_specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } ($_vhost_content != '') { $vhost_content .= $_vhost_content; } (settings::get('system.default_vhostconf') != '' &amp;&amp; ($ssl_vhost == false || ($ssl_vhost == true &amp;&amp; settings::get('system.include_default_vhostconf') == 1))) { $vhost_content .= $this-&gt;processspecialconfigtemplate(settings::get('system.default_vhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } (settings::get('system.default_sslvhostconf') != '' &amp;&amp; $ssl_vhost == true) { $vhost_content .= $this-&gt;processspecialconfigtemplate(settings::get('system.default_sslvhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } } } $vhost_content .= '&lt;/virtualhost&gt;' . "\n"; return $vhost_content; } /** * collect servernames aliases */ protected function getservernames($domain) { $servernames_text = ' servername ' . $domain['domain'] . "\n"; $server_alias = ''; ($domain['iswildcarddomain'] == '1') { $server_alias = '*.' . $domain['domain']; } elseif ($domain['wwwserveralias'] == '1') { $server_alias = 'www.' . $domain['domain']; } (trim($server_alias) != '') { $servernames_text .= ' serveralias ' . $server_alias . "\n"; } $alias_domains_stmt = database::prepare(" select `domain`, `iswildcarddomain`, `wwwserveralias` `" . table_panel_domains . "` `aliasdomain`= :domainid "); database::pexecute($alias_domains_stmt, [ 'domainid' =&gt; $domain['id'] ]); (($alias_domain = $alias_domains_stmt-&gt;fetch(pdo::fetch_assoc)) !== false) { $server_alias = ' serveralias ' . $alias_domain['domain']; ($alias_domain['iswildcarddomain'] == '1') { $server_alias .= ' *.' . $alias_domain['domain']; } else { ($alias_domain['wwwserveralias'] == '1') { $server_alias .= ' www.' . $alias_domain['domain']; } } $servernames_text .= $server_alias . "\n"; } $servernames_text .= ' serveradmin ' . $domain['email'] . "\n"; return $servernames_text; } /** * let's get webroot */ protected function getwebroot($domain) { $webroot_text = ''; $domain['customerroot'] = filedir::makecorrectdir($domain['customerroot']); $domain['documentroot'] = filedir::makecorrectdir($domain['documentroot']); (($domain['deactivated'] == '1' || $domain['customer_deactivated'] == '1') &amp;&amp; settings::get('system.deactivateddocroot') != '') { $webroot_text .= ' # using docroot deactivated users/domains...' . "\n"; $webroot_text .= ' documentroot "' . rtrim(filedir::makecorrectdir(settings::get('system.deactivateddocroot')), "/") . "\"\n"; $webroot_text .= ' &lt;directory "' . filedir::makecorrectdir(settings::get('system.deactivateddocroot')) . '"&gt;' . "\n"; // &gt;=apache-2.4 enabled? (settings::get('system.apache24') == '1') { $webroot_text .= ' require granted' . "\n"; $webroot_text .= ' allowoverride all' . "\n"; } else { $webroot_text .= ' order allow,deny' . "\n"; $webroot_text .= ' allow all' . "\n"; } $webroot_text .= ' &lt;/directory&gt;' . "\n"; $this-&gt;deactivated = true; } else { $webroot_text .= ' documentroot "' . rtrim($domain['documentroot'], "/") . "\"\n"; $this-&gt;deactivated = false; } return $webroot_text; } /** * put together needed php options virtualhost entries * * @param array $domain * @param bool $ssl_vhost * * @return string */ protected function composephpoptions(&amp;$domain, $ssl_vhost = false) { $php_options_text = ''; ($domain['phpenabled_customer'] == 1 &amp;&amp; $domain['phpenabled_vhost'] == '1') { // vhost php enabled using regular mod_php $cmail = customer::getcustomerdetail($domain['customerid'], 'email'); $php_options_text .= ' php_admin_value sendmail_path "/usr/sbin/sendmail -t -f ' . $cmail . '"' . php_eol; ($domain['openbasedir'] == '1') { ($domain['openbasedir_path'] == '1' || strstr($domain['documentroot'], ":") !== false) { $_phpappendopenbasedir = domain::appendopenbasedirpath($domain['customerroot'], true); } else ($domain['openbasedir_path'] == '2' &amp;&amp; strpos(dirname($domain['documentroot']) . '/', $domain['customerroot']) !== false) { $_phpappendopenbasedir = domain::appendopenbasedirpath(dirname($domain['documentroot']) . '/', true); } else { $_phpappendopenbasedir = domain::appendopenbasedirpath($domain['documentroot'], true); } $_custom_openbasedir = explode(':', settings::get('system.phpappendopenbasedir')); foreach ($_custom_openbasedir $cobd) { $_phpappendopenbasedir .= domain::appendopenbasedirpath($cobd); } $php_options_text .= ' php_admin_value open_basedir "' . $_phpappendopenbasedir . '"' . "\n"; } } else { $php_options_text .= ' # php disabled vhost' . "\n"; $php_options_text .= ' php_flag engine off' . "\n"; } /** * check apache-itk-support, #1400 * here? works mod_php */ (settings::get('system.apacheitksupport') == 1) { $php_options_text .= ' &lt;ifmodule mpm_itk_module&gt;' . "\n"; $php_options_text .= ' assignuserid ' . $domain['loginname'] . ' ' . $domain['loginname'] . "\n"; $php_options_text .= ' &lt;/ifmodule&gt;' . "\n"; } return $php_options_text; } /** * lets set text part stats software */ protected function getstats($domain) { $stats_text = ''; $stattool = settings::get('system.traffictool'); $statdomain = ""; ($stattool == 'awstats') { // awstats generates domain regardless speciallogfile $statdomain = "/" . $domain['domain']; } ($domain['speciallogfile'] == '1') { $statdomain = "/" . (($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']); } $statdocroot = filedir::makecorrectfile($domain['customerroot'] . '/' . $stattool . $statdomain); $stats_text .= ' alias /' . $stattool . ' "' . $statdocroot . '"' . "\n"; // awstats special requirement icons ($stattool == 'awstats') { $stats_text .= ' alias /awstats-icon "' . filedir::makecorrectdir(settings::get('system.awstats_icons')) . '"' . "\n"; } return $stats_text; } /** * lets set logfiles */ protected function getlogfiles($domain) { $logfiles_text = ''; ($domain['speciallogfile'] == '1') { ($domain['parentdomainid'] == '0') { $speciallogfile = '-' . $domain['domain']; } else { $speciallogfile = '-' . $domain['parentdomain']; } } else { $speciallogfile = ''; } ($domain['writeerrorlog']) { // normal access/error - logging enabled $error_log = filedir::makecorrectfile(settings::get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-error.log'); // create logfile exist (fixes #46) touch($error_log); chown($error_log, settings::get('system.httpuser')); chgrp($error_log, settings::get('system.httpgroup')); // set error log log-level $logfiles_text .= ' loglevel ' . settings::get('system.errorlog_level') . "\n"; } else { $error_log = '/dev/null'; } ($domain['writeaccesslog']) { $access_log = filedir::makecorrectfile(settings::get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log'); // create logfile exist (fixes #46) touch($access_log); chown($access_log, settings::get('system.httpuser')); chgrp($access_log, settings::get('system.httpgroup')); } else { $access_log = '/dev/null'; } $logtype = 'combined'; (settings::get('system.logfiles_format') != '') { $logtype = 'frx_custom'; $logfiles_text .= ' logformat ' . settings::get('system.logfiles_format') . ' ' . $logtype . "\n"; } (settings::get('system.logfiles_type') == '2' &amp;&amp; settings::get('system.logfiles_format') == '') { $logtype = 'vhost_combined'; } (settings::get('system.logfiles_piped') == '1' &amp;&amp; settings::get('system.logfiles_script') != '') { ($domain['writeerrorlog']) { // replace error_log $command = phphelper::replacevariables(settings::get('system.logfiles_script'), [ 'logfile' =&gt; $error_log, 'domain' =&gt; $domain['domain'], 'customer' =&gt; $domain['loginname'] ]); $logfiles_text .= ' errorlog "|' . $command . "\"\n"; } else { $logfiles_text .= ' errorlog "' . $error_log . '"' . "\n"; } ($domain['writeaccesslog']) { // replace access_log $command = phphelper::replacevariables(settings::get('system.logfiles_script'), [ 'logfile' =&gt; $access_log, 'domain' =&gt; $domain['domain'], 'customer' =&gt; $domain['loginname'] ]); $logfiles_text .= ' customlog "|' . $command . '" ' . $logtype . "\n"; } else { $logfiles_text .= ' customlog "' . $access_log . '" ' . $logtype . "\n"; } } else { $logfiles_text .= ' errorlog "' . $error_log . '"' . "\n"; $logfiles_text .= ' customlog "' . $access_log . '" ' . $logtype . "\n"; } (settings::get('system.traffictool') == 'awstats') { ((int)$domain['parentdomainid'] == 0) { // prepare aliases subdomains stats config files $server_alias = ''; $alias_domains_stmt = database::prepare(" select `domain`, `iswildcarddomain`, `wwwserveralias` `" . table_panel_domains . "` `aliasdomain` = :domainid `parentdomainid` = :domainid "); database::pexecute($alias_domains_stmt, [ 'domainid' =&gt; $domain['id'] ]); (($alias_domain = $alias_domains_stmt-&gt;fetch(pdo::fetch_assoc)) !== false) { $server_alias .= ' ' . $alias_domain['domain'] . ' '; ($alias_domain['iswildcarddomain'] == '1') { $server_alias .= '*.' . $alias_domain['domain']; } elseif ($alias_domain['wwwserveralias'] == '1') { $server_alias .= 'www.' . $alias_domain['domain']; } } $alias = ''; ($domain['iswildcarddomain'] == '1') { $alias = '*.' . $domain['domain']; } elseif ($domain['wwwserveralias'] == '1') { $alias = 'www.' . $domain['domain']; } // inserting awstats information, // sure build awstats conf file well // chown using $awstats_params, #258 // bug 960 + bug 970 : use full $domain instead custom $awstats_params following classes depend information statistics::createawstatsconf(settings::get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log', $domain['domain'], $alias . $server_alias, $domain['customerroot'], $domain); } } return $logfiles_text; } /** * compose diroption entries paths */ public function createfilediroptions() { $result_stmt = database::query(" select `htac`.*, `c`.`guid`, `c`.`documentroot` `customerroot` `" . table_panel_htaccess . "` `htac` left join `" . table_panel_customers . "` `c` using (`customerid`) order `htac`.`path` "); $diroptions = []; ($row_diroptions = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { ($row_diroptions['customerid'] != 0 &amp;&amp; isset($row_diroptions['customerroot']) &amp;&amp; $row_diroptions['customerroot'] != '') { $diroptions[$row_diroptions['path']] = $row_diroptions; $diroptions[$row_diroptions['path']]['htpasswds'] = []; } } $result_stmt = database::query(" select `htpw`.*, `c`.`guid`, `c`.`documentroot` `customerroot` `" . table_panel_htpasswds . "` `htpw` left join `" . table_panel_customers . "` `c` using (`customerid`) order `htpw`.`path`, `htpw`.`username` "); ($row_htpasswds = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { ($row_htpasswds['customerid'] != 0 &amp;&amp; isset($row_htpasswds['customerroot']) &amp;&amp; $row_htpasswds['customerroot'] != '') { (!isset($diroptions[$row_htpasswds['path']]) || !is_array($diroptions[$row_htpasswds['path']])) { $diroptions[$row_htpasswds['path']] = []; } $diroptions[$row_htpasswds['path']]['path'] = $row_htpasswds['path']; $diroptions[$row_htpasswds['path']]['guid'] = $row_htpasswds['guid']; $diroptions[$row_htpasswds['path']]['customerroot'] = $row_htpasswds['customerroot']; $diroptions[$row_htpasswds['path']]['customerid'] = $row_htpasswds['customerid']; $diroptions[$row_htpasswds['path']]['htpasswds'][] = $row_htpasswds; } } foreach ($diroptions $row_diroptions) { $row_diroptions['path'] = filedir::makecorrectdir($row_diroptions['path']); filedir::mkdirwithcorrectownership($row_diroptions['customerroot'], $row_diroptions['path'], $row_diroptions['guid'], $row_diroptions['guid']); $diroptions_filename = filedir::makecorrectfile(settings::get('system.apacheconf_diroptions') . '/40_froxlor_diroption_' . md5($row_diroptions['path']) . '.conf'); (!isset($this-&gt;diroptions_data[$diroptions_filename])) { $this-&gt;diroptions_data[$diroptions_filename] = ''; } (is_dir($row_diroptions['path'])) { $cperlenabled = customer::customerhasperlenabled($row_diroptions['customerid']); $this-&gt;diroptions_data[$diroptions_filename] .= '&lt;directory "' . $row_diroptions['path'] . '"&gt;' . "\n"; (isset($row_diroptions['options_indexes']) &amp;&amp; $row_diroptions['options_indexes'] == '1') { $this-&gt;diroptions_data[$diroptions_filename] .= ' options +indexes'; // add perl options enabled ($cperlenabled &amp;&amp; isset($row_diroptions['options_cgi']) &amp;&amp; $row_diroptions['options_cgi'] == '1') { $this-&gt;diroptions_data[$diroptions_filename] .= ' +execcgi -multiviews +symlinksifownermatch +followsymlinks' . "\n"; } else { $this-&gt;diroptions_data[$diroptions_filename] .= "\n"; } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'setting options +indexes ' . $row_diroptions['path']); } (isset($row_diroptions['options_indexes']) &amp;&amp; $row_diroptions['options_indexes'] == '0') { $this-&gt;diroptions_data[$diroptions_filename] .= ' options -indexes'; // add perl options enabled ($cperlenabled &amp;&amp; isset($row_diroptions['options_cgi']) &amp;&amp; $row_diroptions['options_cgi'] == '1') { $this-&gt;diroptions_data[$diroptions_filename] .= ' +execcgi -multiviews +symlinksifownermatch +followsymlinks' . "\n"; } else { $this-&gt;diroptions_data[$diroptions_filename] .= "\n"; } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'setting options -indexes ' . $row_diroptions['path']); } $statuscodes = [ '404', '403', '500' ]; foreach ($statuscodes $statuscode) { (isset($row_diroptions['error' . $statuscode . 'path']) &amp;&amp; $row_diroptions['error' . $statuscode . 'path'] != '') { $defhandler = $row_diroptions['error' . $statuscode . 'path']; (!validate::validateurl($defhandler)) { (substr($defhandler, 0, 1) != '"' &amp;&amp; substr($defhandler, -1, 1) != '"') { $defhandler = '"' . filedir::makecorrectfile($defhandler) . '"'; } } $this-&gt;diroptions_data[$diroptions_filename] .= ' errordocument ' . $statuscode . ' ' . $defhandler . "\n"; } } ($cperlenabled &amp;&amp; isset($row_diroptions['options_cgi']) &amp;&amp; $row_diroptions['options_cgi'] == '1') { $this-&gt;diroptions_data[$diroptions_filename] .= ' allowoverride none' . "\n"; $this-&gt;diroptions_data[$diroptions_filename] .= ' addhandler cgi-script .cgi .pl' . "\n"; // &gt;=apache-2.4 enabled? (settings::get('system.apache24') == '1') { $mypath_dir = new directory($row_diroptions['path']); // create the' require granted' active directory-protection // path, would first require therefore grant access ($mypath_dir-&gt;isuserprotected() == false) { $this-&gt;diroptions_data[$diroptions_filename] .= ' require granted' . "\n"; // $this-&gt;diroptions_data[$diroptions_filename] .= ' allowoverride all' . "\n"; } } else { $this-&gt;diroptions_data[$diroptions_filename] .= ' order allow,deny' . "\n"; $this-&gt;diroptions_data[$diroptions_filename] .= ' allow all' . "\n"; } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'enabling perl execution ' . $row_diroptions['path']); // check suexec-workaround, #319 ((int)settings::get('perl.suexecworkaround') == 1) { // symlink directory suexec-safe-path $loginname = customer::getcustomerdetail($row_diroptions['customerid'], 'loginname'); $suexecpath = filedir::makecorrectdir(settings::get('perl.suexecpath') . '/' . $loginname . '/' . md5($row_diroptions['path']) . '/'); (!file_exists($suexecpath)) { filedir::safe_exec('mkdir -p ' . escapeshellarg($suexecpath)); filedir::safe_exec('chown -r ' . escapeshellarg($row_diroptions['guid']) . ':' . escapeshellarg($row_diroptions['guid']) . ' ' . escapeshellarg($suexecpath)); } // symlink {$givenpath}/cgi-bin // note: symlinks files, append / $perlsymlink = filedir::makecorrectfile($row_diroptions['path'] . '/cgi-bin'); (!file_exists($perlsymlink)) { filedir::safe_exec('ln -s ' . escapeshellarg($suexecpath) . ' ' . escapeshellarg($perlsymlink)); } filedir::safe_exec('chown -h ' . escapeshellarg($row_diroptions['guid']) . ':' . escapeshellarg($row_diroptions['guid']) . ' ' . escapeshellarg($perlsymlink)); } } else { // perl-execution enabled workaround is, // remove symlink folder suexecpath ((int)settings::get('perl.suexecworkaround') == 1) { $loginname = customer::getcustomerdetail($row_diroptions['customerid'], 'loginname'); $suexecpath = filedir::makecorrectdir(settings::get('perl.suexecpath') . '/' . $loginname . '/' . md5($row_diroptions['path']) . '/'); $perlsymlink = filedir::makecorrectfile($row_diroptions['path'] . '/cgi-bin'); // remove symlink (file_exists($perlsymlink)) { filedir::safe_exec('rm -f ' . escapeshellarg($perlsymlink)); } // remove folder suexec-path (file_exists($suexecpath)) { filedir::safe_exec('rm -rf ' . escapeshellarg($suexecpath)); } } } (count($row_diroptions['htpasswds']) &gt; 0) { $htpasswd_filename = filedir::makecorrectfile(settings::get('system.apacheconf_htpasswddir') . '/' . $row_diroptions['customerid'] . '-' . md5($row_diroptions['path']) . '.htpasswd'); (!isset($this-&gt;htpasswds_data[$htpasswd_filename])) { $this-&gt;htpasswds_data[$htpasswd_filename] = ''; } foreach ($row_diroptions['htpasswds'] $row_htpasswd) { $this-&gt;htpasswds_data[$htpasswd_filename] .= $row_htpasswd['username'] . ':' . $row_htpasswd['password'] . "\n"; } $this-&gt;diroptions_data[$diroptions_filename] .= ' authtype basic' . "\n"; $this-&gt;diroptions_data[$diroptions_filename] .= ' authname "' . $row_htpasswd['authname'] . '"' . "\n"; $this-&gt;diroptions_data[$diroptions_filename] .= ' authuserfile ' . $htpasswd_filename . "\n"; $this-&gt;diroptions_data[$diroptions_filename] .= ' require valid-user' . "\n"; } $this-&gt;diroptions_data[$diroptions_filename] .= '&lt;/directory&gt;' . "\n"; } } } /** * write configs */ public function writeconfigs() { // write diroptions froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "apache::writeconfigs: rebuilding " . settings::get('system.apacheconf_diroptions')); (count($this-&gt;diroptions_data) &gt; 0) { $optsdir = new directory(settings::get('system.apacheconf_diroptions')); (!$optsdir-&gt;isconfigdir()) { // save one big file $diroptions_file = ''; foreach ($this-&gt;diroptions_data $diroptions_filename =&gt; $diroptions_content) { $diroptions_file .= $diroptions_content . "\n\n"; } $diroptions_filename = settings::get('system.apacheconf_diroptions'); // apply header $diroptions_file = '# ' . basename($diroptions_filename) . "\n" . '# created ' . date('d.m.y h:i') . "\n" . '# manually edit file, changes deleted next domain change panel.' . "\n" . "\n" . $diroptions_file; $diroptions_file_handler = fopen($diroptions_filename, 'w'); fwrite($diroptions_file_handler, $diroptions_file); fclose($diroptions_file_handler); } else { (!file_exists(settings::get('system.apacheconf_diroptions'))) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'apache::writeconfigs: mkdir ' . escapeshellarg(filedir::makecorrectdir(settings::get('system.apacheconf_diroptions')))); filedir::safe_exec('mkdir ' . escapeshellarg(filedir::makecorrectdir(settings::get('system.apacheconf_diroptions')))); } // write single file every diroption foreach ($this-&gt;diroptions_data $diroptions_filename =&gt; $diroptions_file) { $this-&gt;known_diroptionsfilenames[] = basename($diroptions_filename); // apply header $diroptions_file = '# ' . basename($diroptions_filename) . "\n" . '# created ' . date('d.m.y h:i') . "\n" . '# manually edit file, changes deleted next domain change panel.' . "\n" . "\n" . $diroptions_file; $diroptions_file_handler = fopen($diroptions_filename, 'w'); fwrite($diroptions_file_handler, $diroptions_file); fclose($diroptions_file_handler); } } } // write htpasswds froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "apache::writeconfigs: rebuilding " . settings::get('system.apacheconf_htpasswddir')); (count($this-&gt;htpasswds_data) &gt; 0) { (!file_exists(settings::get('system.apacheconf_htpasswddir'))) { $umask = umask(); umask(0000); mkdir(settings::get('system.apacheconf_htpasswddir'), 0751); umask($umask); } $htpasswddir = new directory(settings::get('system.apacheconf_htpasswddir')); ($htpasswddir-&gt;isconfigdir(true)) { foreach ($this-&gt;htpasswds_data $htpasswd_filename =&gt; $htpasswd_file) { $this-&gt;known_htpasswdsfilenames[] = basename($htpasswd_filename); $htpasswd_file_handler = fopen($htpasswd_filename, 'w'); fwrite($htpasswd_file_handler, $htpasswd_file); fclose($htpasswd_file_handler); } } else { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_warning, 'warning!!! ' . settings::get('system.apacheconf_htpasswddir') . ' directory. htpasswd directory protection disabled!!!'); } } // write virtualhosts froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "apache::writeconfigs: rebuilding " . settings::get('system.apacheconf_vhost')); (count($this-&gt;virtualhosts_data) &gt; 0) { $vhostdir = new directory(settings::get('system.apacheconf_vhost')); (!$vhostdir-&gt;isconfigdir()) { // save one big file $vhosts_file = ''; // sort filename order is: // 1. subdomains x-29 // 2. subdomains main-domains 30 // 3. main-domains 35 // #437 ksort($this-&gt;virtualhosts_data); foreach ($this-&gt;virtualhosts_data $vhosts_filename =&gt; $vhost_content) { $vhosts_file .= $vhost_content . "\n\n"; } // include diroptions file case exists (file_exists(settings::get('system.apacheconf_diroptions'))) { $vhosts_file .= "\n" . 'include ' . settings::get('system.apacheconf_diroptions') . "\n\n"; } $vhosts_filename = settings::get('system.apacheconf_vhost'); // apply header $vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# created ' . date('d.m.y h:i') . "\n" . '# manually edit file, changes deleted next domain change panel.' . "\n" . "\n" . $vhosts_file; $vhosts_file_handler = fopen($vhosts_filename, 'w'); fwrite($vhosts_file_handler, $vhosts_file); fclose($vhosts_file_handler); } else { (!file_exists(settings::get('system.apacheconf_vhost'))) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'apache::writeconfigs: mkdir ' . escapeshellarg(filedir::makecorrectdir(settings::get('system.apacheconf_vhost')))); filedir::safe_exec('mkdir ' . escapeshellarg(filedir::makecorrectdir(settings::get('system.apacheconf_vhost')))); } // write single file every vhost foreach ($this-&gt;virtualhosts_data $vhosts_filename =&gt; $vhosts_file) { // apply header $vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# created ' . date('d.m.y h:i') . "\n" . '# manually edit file, changes deleted next domain change panel.' . "\n" . "\n" . $vhosts_file; $vhosts_file_handler = fopen($vhosts_filename, 'w'); fwrite($vhosts_file_handler, $vhosts_file); fclose($vhosts_file_handler); } } } } }</file><file name="lib/Froxlor/Cron/Http/index.html" /><file name="lib/Froxlor/Cron/Http/Nginx.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http; use froxlor\cron\http\php\phpinterface; use froxlor\customer\customer; use froxlor\database\database; use froxlor\domain\domain; use froxlor\froxlor; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\http\directory; use froxlor\http\statistics; use froxlor\settings; use froxlor\validate\validate; use froxlor\system\crypt; use pdo; class nginx extends httpconfigbase { protected $nginx_data = []; // protected protected $needed_htpasswds = []; protected $http2_on_directive = false; protected $htpasswds_data = []; protected $known_htpasswdsfilenames = []; protected $vhost_root_autoindex = false; /** * indicator whether customer deactivated * yes, webroot generated * * @var bool */ private $deactivated = false; public function __construct() { $nores = false; $res = filedir::safe_exec('nginx -v 2&gt;&amp;1', $nores, ['&gt;', '&amp;']); $ver_str = array_shift($res); $cnginxver = substr($ver_str, strrpos($ver_str, "/") + 1); (version_compare($cnginxver, '1.25.1', '&gt;=')) { // least 1.25.1 $this-&gt;http2_on_directive = true; } } public function createvirtualhosts() { return; } public function createfilediroptions() { return; } public function createipport() { $this-&gt;createlogformatentry(); $result_ipsandports_stmt = database::query(" select * `" . table_panel_ipsandports . "` order `ip` asc, `port` asc "); ($row_ipsandports = $result_ipsandports_stmt-&gt;fetch(pdo::fetch_assoc)) { (filter_var($row_ipsandports['ip'], filter_validate_ip, filter_flag_ipv6)) { $ip = '[' . $row_ipsandports['ip'] . ']'; } else { $ip = $row_ipsandports['ip']; } $port = $row_ipsandports['port']; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, 'nginx::createipport: creating ip/port settings ' . $ip . ":" . $port); $vhost_filename = filedir::makecorrectfile(settings::get('system.apacheconf_vhost') . '/10_froxlor_ipandport_' . trim(str_replace(':', '.', $row_ipsandports['ip']), '.') . '.' . $row_ipsandports['port'] . '.conf'); (!isset($this-&gt;nginx_data[$vhost_filename])) { $this-&gt;nginx_data[$vhost_filename] = ''; } ($row_ipsandports['vhostcontainer'] == '1') { $this-&gt;nginx_data[$vhost_filename] .= 'server { ' . "\n"; $mypath = $this-&gt;getmypath($row_ipsandports); // check ssl anything else // know whether ssl vhost $ssl_vhost = false; ($row_ipsandports['ssl'] == '1') { // check required fallback (($row_ipsandports['ssl_cert_file'] == '' || !file_exists($row_ipsandports['ssl_cert_file'])) &amp;&amp; (settings::get('system.le_froxlor_enabled') == '0' || $this-&gt;froxlorvhosthasletsencryptcert() == false)) { $row_ipsandports['ssl_cert_file'] = settings::get('system.ssl_cert_file'); (!file_exists($row_ipsandports['ssl_cert_file'])) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, 'system certificate file "' . settings::get('system.ssl_cert_file') . '" seem exist. creating self-signed certificate...'); crypt::createselfsignedcertificate(); } } ($row_ipsandports['ssl_key_file'] == '') { $row_ipsandports['ssl_key_file'] = settings::get('system.ssl_key_file'); (!file_exists($row_ipsandports['ssl_key_file'])) { // explicitly disable ssl vhost $row_ipsandports['ssl_cert_file'] = ""; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, 'system certificate key-file "' . settings::get('system.ssl_key_file') . '" seem exist. disabling ssl-vhost "' . settings::get('system.hostname') . '"'); } } ($row_ipsandports['ssl_ca_file'] == '') { $row_ipsandports['ssl_ca_file'] = settings::get('system.ssl_ca_file'); } ($row_ipsandports['ssl_cert_file'] != '' &amp;&amp; file_exists($row_ipsandports['ssl_cert_file'])) { $ssl_vhost = true; } $domain = [ 'id' =&gt; 0, 'domain' =&gt; settings::get('system.hostname'), 'adminid' =&gt; 1, /* first admin-user (superadmin) */ 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath, 'parentdomainid' =&gt; 0 ]; // override corresponding array values $domain['ssl_cert_file'] = $row_ipsandports['ssl_cert_file']; $domain['ssl_key_file'] = $row_ipsandports['ssl_key_file']; $domain['ssl_ca_file'] = $row_ipsandports['ssl_ca_file']; $domain['ssl_cert_chainfile'] = $row_ipsandports['ssl_cert_chainfile']; // ssl stuff $dssl = new domainssl(); // sets ssl-related array-indices $domain array // domain customer-defined ssl-certificates $dssl-&gt;setdomainsslfilesarray($domain); ($domain['ssl_cert_file'] != '' &amp;&amp; file_exists($domain['ssl_cert_file'])) { // override corresponding array values $row_ipsandports['ssl_cert_file'] = $domain['ssl_cert_file']; $row_ipsandports['ssl_key_file'] = $domain['ssl_key_file']; $row_ipsandports['ssl_ca_file'] = $domain['ssl_ca_file']; $row_ipsandports['ssl_cert_chainfile'] = $domain['ssl_cert_chainfile']; $ssl_vhost = true; } } $http2 = $ssl_vhost == true &amp;&amp; settings::get('system.http2_support') == '1'; /** * set default host nginx else vhost work */ $this-&gt;nginx_data[$vhost_filename] .= "\t" . 'listen ' . $ip . ':' . $port . ' default_server' . ($ssl_vhost == true ? ' ssl' : '') . ($http2 &amp;&amp; !$this-&gt;http2_on_directive ? ' http2' : '') . ';' . "\n"; ($http2 &amp;&amp; $this-&gt;http2_on_directive) { $this-&gt;nginx_data[$vhost_filename] .= "\t" . 'http2 on;' . "\n"; } $this-&gt;nginx_data[$vhost_filename] .= "\t" . '# froxlor default vhost' . "\n"; $aliases = ""; $froxlor_aliases = settings::get('system.froxloraliases'); (!empty($froxlor_aliases)) { $froxlor_aliases = explode(",", $froxlor_aliases); foreach ($froxlor_aliases $falias) { (validate::validatedomain(trim($falias))) { $aliases .= trim($falias) . " "; } } $aliases = " " . trim($aliases); } $this-&gt;nginx_data[$vhost_filename] .= "\t" . 'server_name ' . settings::get('system.hostname') . $aliases . ';' . "\n"; $logtype = 'combined'; (settings::get('system.logfiles_format') != '') { $logtype = 'frx_custom'; } $this-&gt;nginx_data[$vhost_filename] .= "\t" . 'access_log /var/log/nginx/access.log ' . $logtype . ';' . "\n"; (settings::get('system.use_ssl') == '1' &amp;&amp; settings::get('system.leenabled') == '1' &amp;&amp; settings::get('system.le_froxlor_enabled') == '1') { $acmeconffilename = settings::get('system.letsencryptacmeconf'); $this-&gt;nginx_data[$vhost_filename] .= "\t" . 'include ' . $acmeconffilename . ';' . "\n"; } $is_redirect = false; // check ssl redirect ($row_ipsandports['ssl'] == '0' &amp;&amp; settings::get('system.le_froxlor_redirect') == '1') { $is_redirect = true; // check whether froxlor uses let's encrypt cert generated yet // renew ongoing - disable redirect (settings::get('system.le_froxlor_enabled') &amp;&amp; ($this-&gt;froxlorvhosthasletsencryptcert() == false || $this-&gt;froxlorvhostletsencryptneedsrenew())) { $this-&gt;nginx_data[$vhost_filename] .= '# temp. disabled ssl-redirect due let\'s encrypt certificate generation.' . php_eol; $is_redirect = false; } else { $_sslport = $this-&gt;checkalternativesslport(); $mypath = 'https://' . settings::get('system.hostname') . $_sslport; $this-&gt;nginx_data[$vhost_filename] .= "\t" . 'location / {' . "\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t\t" . 'return 301 ' . $mypath . '$request_uri;' . "\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t" . '}' . "\n"; } } (!$is_redirect) { $this-&gt;nginx_data[$vhost_filename] .= "\t" . 'root ' . $mypath . ';' . "\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t" . 'index index.php index.html index.htm;' . "\n\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t" . 'location / {' . "\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t" . '}' . "\n"; (settings::get('system.froxlordirectlyviahostname')) { $relpath = "/"; } else { $relpath = "/".basename(froxlor::getinstalldir()); } // protect lib/userdata.inc.php $this-&gt;nginx_data[$vhost_filename] .= "\t" . 'location = ' . rtrim($relpath, "/") . '/lib/userdata.inc.php {' . "\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t" . ' deny all;' . "\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t" . '}' . "\n"; // protect bin/ $this-&gt;nginx_data[$vhost_filename] .= "\t" . 'location ~ ^' . rtrim($relpath, "/") . '/(bin|cache|logs|tests|vendor) {' . "\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t" . ' deny all;' . "\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t" . '}' . "\n"; } ($row_ipsandports['specialsettings'] != '' &amp;&amp; ($row_ipsandports['ssl'] == '0' || ($row_ipsandports['ssl'] == '1' &amp;&amp; settings::get('system.use_ssl') == '1' &amp;&amp; $row_ipsandports['include_specialsettings'] == '1'))) { $this-&gt;nginx_data[$vhost_filename] .= $this-&gt;processspecialconfigtemplate($row_ipsandports['specialsettings'], [ 'domain' =&gt; settings::get('system.hostname'), 'loginname' =&gt; settings::get('phpfpm.vhost_httpuser'), 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath ], $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n"; } /** * ssl config options */ ($row_ipsandports['ssl'] == '1') { $row_ipsandports['domain'] = settings::get('system.hostname'); $row_ipsandports['ssl_honorcipherorder'] = settings::get('system.honorcipherorder'); $row_ipsandports['ssl_sessiontickets'] = settings::get('system.sessiontickets'); $this-&gt;nginx_data[$vhost_filename] .= $this-&gt;composesslsettings($row_ipsandports); ($row_ipsandports['ssl_specialsettings'] != '') { $this-&gt;nginx_data[$vhost_filename] .= $this-&gt;processspecialconfigtemplate($row_ipsandports['ssl_specialsettings'], [ 'domain' =&gt; settings::get('system.hostname'), 'loginname' =&gt; settings::get('phpfpm.vhost_httpuser'), 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath ], $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n"; } } (!$is_redirect) { $this-&gt;nginx_data[$vhost_filename] .= "\tlocation ~ \.php {\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t\tfastcgi_split_path_info ^(.+?\.php)(/.*)$;\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t\tinclude " . settings::get('nginx.fastcgiparams') . ";\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t\tfastcgi_param script_filename \$request_filename;\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t\tfastcgi_param path_info \$fastcgi_path_info;\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t\ttry_files \$fastcgi_script_name =404;\n"; ($row_ipsandports['ssl'] == '1') { $this-&gt;nginx_data[$vhost_filename] .= "\t\tfastcgi_param https on;\n"; } ((int)settings::get('phpfpm.enabled') == 1 &amp;&amp; (int)settings::get('phpfpm.enabled_ownvhost') == 1) { // get fpm config $fpm_sel_stmt = database::prepare(" select f.id `" . table_panel_fpmdaemons . "` f left join `" . table_panel_phpconfigs . "` p p.fpmsettingid = f.id p.id = :phpconfigid "); $fpm_config = database::pexecute_first($fpm_sel_stmt, [ 'phpconfigid' =&gt; settings::get('phpfpm.vhost_defaultini') ]); $domain = [ 'id' =&gt; 'none', 'domain' =&gt; settings::get('system.hostname'), 'adminid' =&gt; 1, /* first admin-user (superadmin) */ 'mod_fcgid_starter' =&gt; -1, 'mod_fcgid_maxrequests' =&gt; -1, 'guid' =&gt; settings::get('phpfpm.vhost_httpuser'), 'openbasedir' =&gt; 0, 'email' =&gt; settings::get('panel.adminmail'), 'loginname' =&gt; 'froxlor.panel', 'documentroot' =&gt; $mypath, 'customerroot' =&gt; $mypath, 'fpm_config_id' =&gt; isset($fpm_config['id']) ? $fpm_config['id'] : 1 ]; $php = new phpinterface($domain); $this-&gt;nginx_data[$vhost_filename] .= "\t\tfastcgi_pass unix:" . $php-&gt;getinterface()-&gt;getsocketfile() . ";\n"; } else { $this-&gt;nginx_data[$vhost_filename] .= "\t\tfastcgi_pass " . settings::get('system.nginx_php_backend') . ";\n"; } $this-&gt;nginx_data[$vhost_filename] .= "\t\tfastcgi_index index.php;\n"; $this-&gt;nginx_data[$vhost_filename] .= "\t}\n"; } $this-&gt;nginx_data[$vhost_filename] .= "}\n\n"; // end froxlor server{}-part } } $this-&gt;createnginxhosts(); /** * standard error pages */ $this-&gt;createstandarderrorhandler(); } private function createlogformatentry() { (settings::get('system.logfiles_format') != '') { $vhosts_folder = ''; (is_dir(settings::get('system.apacheconf_vhost'))) { $vhosts_folder = filedir::makecorrectdir(settings::get('system.apacheconf_vhost')); } else { $vhosts_folder = filedir::makecorrectdir(dirname(settings::get('system.apacheconf_vhost'))); } $vhosts_filename = filedir::makecorrectfile($vhosts_folder . '/02_froxlor_logfiles_format.conf'); (!isset($this-&gt;nginx_data[$vhosts_filename])) { $this-&gt;nginx_data[$vhosts_filename] = ''; } $logtype = 'frx_custom'; $this-&gt;nginx_data[$vhosts_filename] = 'log_format ' . $logtype . ' ' . settings::get('system.logfiles_format') . ';' . "\n"; } } protected function composesslsettings($domain_or_ip) { $sslsettings = ''; ($domain_or_ip['ssl_cert_file'] == '' || !file_exists($domain_or_ip['ssl_cert_file'])) { $domain_or_ip['ssl_cert_file'] = settings::get('system.ssl_cert_file'); (!file_exists($domain_or_ip['ssl_cert_file'])) { // explicitly disable ssl vhost $domain_or_ip['ssl_cert_file'] = ""; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, 'system certificate file "' . settings::get('system.ssl_cert_file') . '" seem exist. disabling ssl-vhost "' . $domain_or_ip['domain'] . '"'); } } ($domain_or_ip['ssl_key_file'] == '' || !file_exists($domain_or_ip['ssl_key_file'])) { // use fallback $domain_or_ip['ssl_key_file'] = settings::get('system.ssl_key_file'); // check whether exists (!file_exists($domain_or_ip['ssl_key_file'])) { // explicitly disable ssl vhost $domain_or_ip['ssl_cert_file'] = ""; froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_debug, 'system certificate key-file "' . settings::get('system.ssl_key_file') . '" seem exist. disabling ssl-vhost "' . $domain_or_ip['domain'] . '"'); } } ($domain_or_ip['ssl_ca_file'] == '') { $domain_or_ip['ssl_ca_file'] = settings::get('system.ssl_ca_file'); } // #418 ($domain_or_ip['ssl_cert_chainfile'] == '') { $domain_or_ip['ssl_cert_chainfile'] = settings::get('system.ssl_cert_chainfile'); } ($domain_or_ip['ssl_cert_file'] != '') { // check existence, #1485 (!file_exists($domain_or_ip['ssl_cert_file'])) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, $domain_or_ip['domain'] . ' :: certificate file "' . $domain_or_ip['ssl_cert_file'] . '" exist! cannot create ssl-directives'); } else { $ssl_protocols = (isset($domain_or_ip['override_tls']) &amp;&amp; $domain_or_ip['override_tls'] == '1' &amp;&amp; !empty($domain_or_ip['ssl_protocols'])) ? $domain_or_ip['ssl_protocols'] : settings::get('system.ssl_protocols'); $ssl_cipher_list = (isset($domain_or_ip['override_tls']) &amp;&amp; $domain_or_ip['override_tls'] == '1' &amp;&amp; !empty($domain_or_ip['ssl_cipher_list'])) ? $domain_or_ip['ssl_cipher_list'] : settings::get('system.ssl_cipher_list'); // obsolete: ssl belongs listen block 'ssl' end // $sslsettings .= "\t" . 'ssl on;' . "\n"; $sslsettings .= "\t" . 'ssl_protocols ' . str_replace(",", " ", $ssl_protocols) . ';' . "\n"; $sslsettings .= "\t" . 'ssl_ciphers ' . $ssl_cipher_list . ';' . "\n"; (!empty(settings::get('system.dhparams_file'))) { $dhparams = filedir::makecorrectfile(settings::get('system.dhparams_file')); (!file_exists($dhparams)) { file_put_contents($dhparams, self::ffdhe4096); } $sslsettings .= "\t" . 'ssl_dhparam ' . $dhparams . ';' . "\n"; } // &lt;1.11.0: defaults prime256v1, similar first curve recommendation mozilla. // (when specifyng one, there's fallback specific curve supported client.) // &gt;1.11.0: defaults auto, using recommended curves provided openssl. // see https://github.com/froxlor/froxlor/issues/652 // $sslsettings .= "\t" . 'ssl_ecdh_curve secp384r1;' . "\n"; $sslsettings .= "\t" . 'ssl_prefer_server_ciphers ' . (isset($domain_or_ip['ssl_honorcipherorder']) &amp;&amp; $domain_or_ip['ssl_honorcipherorder'] == '1' ? 'on' : 'off') . ';' . "\n"; (settings::get('system.sessionticketsenabled') == '1') { $sslsettings .= "\t" . 'ssl_session_tickets ' . (isset($domain_or_ip['ssl_sessiontickets']) &amp;&amp; $domain_or_ip['ssl_sessiontickets'] == '1' ? 'on' : 'off') . ';' . "\n"; } $sslsettings .= "\t" . 'ssl_session_cache shared:ssl:10m;' . "\n"; $sslsettings .= "\t" . 'ssl_certificate ' . filedir::makecorrectfile($domain_or_ip['ssl_cert_file']) . ';' . "\n"; ($domain_or_ip['ssl_key_file'] != '') { // check existence, #1485 (!file_exists($domain_or_ip['ssl_key_file'])) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, $domain_or_ip['domain'] . ' :: certificate key file "' . $domain_or_ip['ssl_key_file'] . '" exist! cannot create ssl-directives'); } else { $sslsettings .= "\t" . 'ssl_certificate_key ' . filedir::makecorrectfile($domain_or_ip['ssl_key_file']) . ';' . "\n"; } } (isset($domain_or_ip['hsts']) &amp;&amp; $domain_or_ip['hsts'] &gt;= 0) { $sslsettings .= 'add_header strict-transport-security "max-age=' . $domain_or_ip['hsts']; ($domain_or_ip['hsts_sub'] == 1) { $sslsettings .= '; includesubdomains'; } ($domain_or_ip['hsts_preload'] == 1) { $sslsettings .= '; preload'; } $sslsettings .= '";' . "\n"; } ((isset($domain_or_ip['ocsp_stapling']) &amp;&amp; $domain_or_ip['ocsp_stapling'] == "1") || (isset($domain_or_ip['letsencrypt']) &amp;&amp; $domain_or_ip['letsencrypt'] == "1")) { $sslsettings .= "\t" . 'ssl_stapling on;' . "\n"; $sslsettings .= "\t" . 'ssl_stapling_verify on;' . "\n"; $sslsettings .= "\t" . 'ssl_trusted_certificate ' . filedir::makecorrectfile($domain_or_ip['ssl_cert_file']) . ';' . "\n"; } } } return $sslsettings; } /** * create vhosts */ protected function createnginxhosts() { $domains = webserverbase::getvhoststocreate(); foreach ($domains $domain) { (is_dir(settings::get('system.apacheconf_vhost'))) { filedir::safe_exec('mkdir -p ' . escapeshellarg(filedir::makecorrectdir(settings::get('system.apacheconf_vhost')))); } $vhost_filename = $this-&gt;getvhostfilename($domain); (!isset($this-&gt;nginx_data[$vhost_filename])) { $this-&gt;nginx_data[$vhost_filename] = ''; } ((empty($this-&gt;nginx_data[$vhost_filename]) &amp;&amp; !is_dir(settings::get('system.apacheconf_vhost'))) || is_dir(settings::get('system.apacheconf_vhost'))) { $domain['nonexistinguri'] = '/' . md5(uniqid(microtime(), 1)) . '.htm'; // create non-ssl host $this-&gt;nginx_data[$vhost_filename] .= $this-&gt;getvhostcontent($domain, false); ($domain['ssl'] == '1' || $domain['ssl_redirect'] == '1') { $vhost_filename_ssl = $this-&gt;getvhostfilename($domain, true); (!isset($this-&gt;nginx_data[$vhost_filename_ssl])) { $this-&gt;nginx_data[$vhost_filename_ssl] = ''; } // enable ssl stuff $this-&gt;nginx_data[$vhost_filename_ssl] .= $this-&gt;getvhostcontent($domain, true); } } } } protected function getvhostcontent($domain, $ssl_vhost = false) { ($ssl_vhost === true &amp;&amp; $domain['ssl'] != '1' &amp;&amp; $domain['ssl_redirect'] != '1') { return ''; } // check whether customer/domain deactivated docroot deactivated users set# $ddr = settings::get('system.deactivateddocroot'); (($domain['deactivated'] == '1' || $domain['customer_deactivated'] == '1') &amp;&amp; empty($ddr)) { return '# customer deactivated docroot deactivated users/domains hasn\'t set.' . "\n"; } $vhost_content = ''; $_vhost_content = ''; $has_http2_on = false; $query = "select * `" . table_panel_ipsandports . "` `i`, `" . table_domaintoip . "` `dip` dip.id_domain = :domainid i.id = dip.id_ipandports "; ($ssl_vhost === true &amp;&amp; ($domain['ssl'] == '1' || $domain['ssl_redirect'] == '1')) { // ordering cert-file row filled ssl-fields shown last, // thus enough fill 1 set ssl-fields $query .= "and i.ssl = 1 order i.ssl_cert_file asc;"; } else { $query .= "and i.ssl = '0';"; } // start vhost $vhost_content .= 'server { ' . "\n"; $result_stmt = database::prepare($query); database::pexecute($result_stmt, [ 'domainid' =&gt; $domain['id'] ]); ($ipandport = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $domain['ip'] = $ipandport['ip']; $domain['port'] = $ipandport['port']; ($domain['ssl'] == '1') { $domain['ssl_cert_file'] = $ipandport['ssl_cert_file']; $domain['ssl_key_file'] = $ipandport['ssl_key_file']; $domain['ssl_ca_file'] = $ipandport['ssl_ca_file']; $domain['ssl_cert_chainfile'] = $ipandport['ssl_cert_chainfile']; // ssl stuff $dssl = new domainssl(); // sets ssl-related array-indices $domain array // domain customer-defined ssl-certificates $dssl-&gt;setdomainsslfilesarray($domain); } (filter_var($domain['ip'], filter_validate_ip, filter_flag_ipv6)) { $ipport = '[' . $domain['ip'] . ']:' . $domain['port']; } else { $ipport = $domain['ip'] . ':' . $domain['port']; } ($ipandport['default_vhostconf_domain'] != '' &amp;&amp; ($ssl_vhost == false || ($ssl_vhost == true &amp;&amp; $ipandport['include_default_vhostconf_domain'] == '1'))) { $_vhost_content .= $this-&gt;processspecialconfigtemplate($ipandport['default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } ($ipandport['ssl_default_vhostconf_domain'] != '' &amp;&amp; $ssl_vhost == true) { $_vhost_content .= $this-&gt;processspecialconfigtemplate($ipandport['ssl_default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } $http2 = $ssl_vhost == true &amp;&amp; (isset($domain['http2']) &amp;&amp; $domain['http2'] == '1' &amp;&amp; settings::get('system.http2_support') == '1'); $vhost_content .= "\t" . 'listen ' . $ipport . ($ssl_vhost == true ? ' ssl' : '') . ($http2 &amp;&amp; !$this-&gt;http2_on_directive ? ' http2' : '') . ';' . "\n"; ($http2 &amp;&amp; $this-&gt;http2_on_directive &amp;&amp; !$has_http2_on) { $vhost_content .= "\t" . 'http2 on;' . "\n"; $has_http2_on = true; } } // get server-names $vhost_content .= $this-&gt;getservernames($domain); // respect ssl_redirect settings, #542 ($ssl_vhost == false &amp;&amp; $domain['ssl'] == '1' &amp;&amp; $domain['ssl_redirect'] == '1') { // must check port differs port 443, // destination-port != 443 $_sslport = ''; // returns first port != 443 ssl enabled, // ordered ssl-certificate (if any) ip/port combo // certificate used $ssldestport_stmt = database::prepare("select `ip`.`port` " . table_panel_ipsandports . " `ip` left join `" . table_domaintoip . "` `dip` (`ip`.`id` = `dip`.`id_ipandports`) `dip`.`id_domain` = :domainid `ip`.`ssl` = '1' `ip`.`port` != 443 order `ip`.`ssl_cert_file` desc, `ip`.`port` limit 1;"); $ssldestport = database::pexecute_first($ssldestport_stmt, [ 'domainid' =&gt; $domain['id'] ]); ($ssldestport &amp;&amp; $ssldestport['port'] != '') { $_sslport = ":" . $ssldestport['port']; } $domain['documentroot'] = 'https://$host' . $_sslport . '/'; } // avoid using whitespaces $domain['documentroot'] = trim($domain['documentroot']); // create ssl settings first since required normal redirect vhosts ($ssl_vhost === true &amp;&amp; $domain['ssl'] == '1' &amp;&amp; settings::get('system.use_ssl') == '1') { $vhost_content .= "\n" . $this-&gt;composesslsettings($domain) . "\n"; } (settings::get('system.use_ssl') == '1' &amp;&amp; settings::get('system.leenabled') == '1') { $acmeconffilename = settings::get('system.letsencryptacmeconf'); $vhost_content .= "\t" . 'include ' . $acmeconffilename . ';' . "\n"; } // documentroot url redirect (preg_match('/^https?\:\/\//', $domain['documentroot'])) { $possible_deactivated_webroot = $this-&gt;getwebroot($domain); ($this-&gt;deactivated == false) { $uri = $domain['documentroot']; (substr($uri, -1) == '/') { $uri = substr($uri, 0, -1); } // get domain's redirect code $code = domain::getdomainredirectcode($domain['id']); $vhost_content .= $this-&gt;getlogfiles($domain); $vhost_content .= "\t" . 'location / {' . "\n"; $vhost_content .= "\t\t" . 'return ' . $code . ' ' . $uri . '$request_uri;' . "\n"; $vhost_content .= "\t" . '}' . "\n"; } elseif (settings::get('system.deactivateddocroot') != '') { $vhost_content .= $possible_deactivated_webroot; } } else { filedir::mkdirwithcorrectownership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true); $vhost_content .= $this-&gt;getlogfiles($domain); $vhost_content .= $this-&gt;getwebroot($domain); ($this-&gt;deactivated == false) { $vhost_content = $this-&gt;mergevhostcustom($vhost_content, $this-&gt;createpathoptions($domain)) . "\n"; $vhost_content .= $this-&gt;composephpoptions($domain, $ssl_vhost); $vhost_content .= isset($this-&gt;needed_htpasswds[$domain['id']]) ? $this-&gt;needed_htpasswds[$domain['id']] . "\n" : ''; ($domain['specialsettings'] != '' &amp;&amp; ($ssl_vhost == false || ($ssl_vhost == true &amp;&amp; $domain['include_specialsettings'] == 1))) { $vhost_content = $this-&gt;mergevhostcustom($vhost_content, $this-&gt;processspecialconfigtemplate($domain['specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost)); } ($domain['ssl_specialsettings'] != '' &amp;&amp; $ssl_vhost == true) { $vhost_content = $this-&gt;mergevhostcustom($vhost_content, $this-&gt;processspecialconfigtemplate($domain['ssl_specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost)); } ($_vhost_content != '') { $vhost_content = $this-&gt;mergevhostcustom($vhost_content, $_vhost_content); } (settings::get('system.default_vhostconf') != '' &amp;&amp; ($ssl_vhost == false || ($ssl_vhost == true &amp;&amp; settings::get('system.include_default_vhostconf') == 1))) { $vhost_content = $this-&gt;mergevhostcustom($vhost_content, $this-&gt;processspecialconfigtemplate(settings::get('system.default_vhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"); } (settings::get('system.default_sslvhostconf') != '' &amp;&amp; $ssl_vhost == true) { $vhost_content = $this-&gt;mergevhostcustom($vhost_content, $this-&gt;processspecialconfigtemplate(settings::get('system.default_sslvhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"); } } } $vhost_content .= "\n}\n\n"; return $vhost_content; } protected function getservernames($domain) { $server_alias = ''; ($domain['iswildcarddomain'] == '1') { $server_alias = '*.' . $domain['domain']; } elseif ($domain['wwwserveralias'] == '1') { $server_alias = 'www.' . $domain['domain']; } $alias_domains_stmt = database::prepare(" select `domain`, `iswildcarddomain`, `wwwserveralias` `" . table_panel_domains . "` `aliasdomain` = :domainid "); database::pexecute($alias_domains_stmt, [ 'domainid' =&gt; $domain['id'] ]); (($alias_domain = $alias_domains_stmt-&gt;fetch(pdo::fetch_assoc)) !== false) { $server_alias .= ' ' . $alias_domain['domain']; ($alias_domain['iswildcarddomain'] == '1') { $server_alias .= ' *.' . $alias_domain['domain']; } elseif ($alias_domain['wwwserveralias'] == '1') { $server_alias .= ' www.' . $alias_domain['domain']; } } $servernames_text = "\t" . 'server_name ' . $domain['domain']; (trim($server_alias) != '') { $servernames_text .= ' ' . $server_alias; } $servernames_text .= ';' . "\n"; return $servernames_text; } protected function getlogfiles($domain) { $logfiles_text = ''; $speciallogfile = ''; ($domain['speciallogfile'] == '1') { ($domain['parentdomainid'] == '0') { $speciallogfile = '-' . $domain['domain']; } else { $speciallogfile = '-' . $domain['parentdomain']; } } ($domain['writeerrorlog']) { // normal access/error - logging enabled $error_log = filedir::makecorrectfile(settings::get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-error.log'); // create logfile exist (fixes #46) touch($error_log); chown($error_log, settings::get('system.httpuser')); chgrp($error_log, settings::get('system.httpgroup')); } else { $error_log = '/dev/null'; } ($domain['writeaccesslog']) { $access_log = filedir::makecorrectfile(settings::get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log'); // create logfile exist (fixes #46) touch($access_log); chown($access_log, settings::get('system.httpuser')); chgrp($access_log, settings::get('system.httpgroup')); } else { $access_log = '/dev/null'; } $logtype = 'combined'; (settings::get('system.logfiles_format') != '') { $logtype = 'frx_custom'; } $logfiles_text .= "\t" . 'access_log ' . $access_log . ' ' . $logtype . ';' . "\n"; $logfiles_text .= "\t" . 'error_log ' . $error_log . ' ' . settings::get('system.errorlog_level') . ';' . "\n"; (settings::get('system.traffictool') == 'awstats') { ((int)$domain['parentdomainid'] == 0) { // prepare aliases subdomains stats config files $server_alias = ''; $alias_domains_stmt = database::prepare(" select `domain`, `iswildcarddomain`, `wwwserveralias` `" . table_panel_domains . "` `aliasdomain` = :domainid `parentdomainid` = :domainid "); database::pexecute($alias_domains_stmt, [ 'domainid' =&gt; $domain['id'] ]); (($alias_domain = $alias_domains_stmt-&gt;fetch(pdo::fetch_assoc)) !== false) { $server_alias .= ' ' . $alias_domain['domain'] . ' '; ($alias_domain['iswildcarddomain'] == '1') { $server_alias .= '*.' . $domain['domain']; } else { ($alias_domain['wwwserveralias'] == '1') { $server_alias .= 'www.' . $alias_domain['domain']; } else { $server_alias .= ''; } } } $alias = ''; ($domain['iswildcarddomain'] == '1') { $alias = '*.' . $domain['domain']; } elseif ($domain['wwwserveralias'] == '1') { $alias = 'www.' . $domain['domain']; } // inserting awstats information, // sure build awstats conf file well // chown using $awstats_params, #258 // bug 960 + bug 970 : use full $domain instead custom $awstats_params following classes depend information statistics::createawstatsconf(settings::get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log', $domain['domain'], $alias . $server_alias, $domain['customerroot'], $domain); } } return $logfiles_text; } protected function getwebroot($domain) { $webroot_text = ''; (($domain['deactivated'] == '1' || $domain['customer_deactivated'] == '1' ) &amp;&amp; settings::get('system.deactivateddocroot') != '') { $webroot_text .= "\t" . '# using docroot deactivated users/domains...' . "\n"; $webroot_text .= "\t" . 'root ' . filedir::makecorrectdir(settings::get('system.deactivateddocroot')) . ';' . "\n"; $this-&gt;deactivated = true; } else { $webroot_text .= "\t" . 'root ' . filedir::makecorrectdir($domain['documentroot']) . ';' . "\n"; $this-&gt;deactivated = false; } $webroot_text .= "\n\t" . 'location / {' . "\n"; ($domain['phpenabled_customer'] == 1 &amp;&amp; $domain['phpenabled_vhost'] == '1') { $webroot_text .= "\t" . 'index index.php index.html index.htm;' . "\n"; ($domain['notryfiles'] != 1) { $webroot_text .= "\t\t" . 'try_files $uri $uri/ @rewrites;' . "\n"; } } else { $webroot_text .= "\t" . 'index index.html index.htm;' . "\n"; } ($this-&gt;vhost_root_autoindex) { $webroot_text .= "\t\t" . 'autoindex on;' . "\n"; $this-&gt;vhost_root_autoindex = false; } $webroot_text .= "\t" . '}' . "\n\n"; ($domain['phpenabled_customer'] == 1 &amp;&amp; $domain['phpenabled_vhost'] == '1' &amp;&amp; $domain['notryfiles'] != 1) { $webroot_text .= "\tlocation @rewrites {\n"; $webroot_text .= "\t\trewrite ^ /index.php last;\n"; $webroot_text .= "\t}\n\n"; } return $webroot_text; } protected function mergevhostcustom($vhost_frx, $vhost_usr) { // clean froxlor defined settings $vhost_frx = $this-&gt;cleanvhoststruct($vhost_frx); // clean user defined settings $vhost_usr = $this-&gt;cleanvhoststruct($vhost_usr); // cycle user defined settings $currentblock = []; $blocklevel = 0; foreach ($vhost_usr $line) { $line = trim($line); $currentblock[] = $line; (strpos($line, "{") !== false) { $blocklevel++; } (strpos($line, "}") !== false &amp;&amp; $blocklevel &gt; 0) { $blocklevel--; } ($line == "}" &amp;&amp; $blocklevel == 0) { (in_array($currentblock[0], $vhost_frx)) { // add existing block $pos = array_search($currentblock[0], $vhost_frx); { $pos++; } ($vhost_frx[$pos] != "}"); ($i = 1; $i &lt; count($currentblock) - 1; $i++) { array_splice($vhost_frx, $pos + $i - 1, 0, $currentblock[$i]); } } else { // add end array_splice($vhost_frx, count($vhost_frx), 0, $currentblock); } $currentblock = []; } elseif ($blocklevel == 0) { array_splice($vhost_frx, count($vhost_frx), 0, $currentblock); $currentblock = []; } } $nextlevel = 0; ($i = 0; $i &lt; count($vhost_frx); $i++) { (substr_count($vhost_frx[$i], "}") != 0 &amp;&amp; substr_count($vhost_frx[$i], "{") == 0) { $nextlevel -= 1; $vhost_frx[$i] .= "\n"; } ($nextlevel &gt; 0) { ($j = 0; $j &lt; $nextlevel; $j++) { $vhost_frx[$i] = " " . $vhost_frx[$i]; } } (substr_count($vhost_frx[$i], "{") != 0 &amp;&amp; substr_count($vhost_frx[$i], "}") == 0) { $nextlevel += 1; } } return implode("\n", $vhost_frx); } private function cleanvhoststruct($vhost = null) { // remove windows linebreaks $vhost = str_replace("\r", "\n", $vhost); // remove comments $vhost = implode("\n", preg_replace('/^(\s+)?#(.*)$/', '', explode("\n", $vhost))); // break blocks lines $vhost = preg_replace("/^(\s+)?location(.+)\{(.+)\}$/misu", "location $2 {\n $3 \n}", $vhost); // break array items $vhost = explode("\n", preg_replace('/[ \t]+/', ' ', trim(preg_replace('/\t+/', '', $vhost)))); // remove empty lines $vhost = array_filter($vhost, function ($a) { return preg_match("#\s#", $a); }); // remove unnecessary whitespaces $vhost = array_map("trim", $vhost); // re-number array keys $vhost = array_values($vhost); return $vhost; } protected function createpathoptions($domain) { $result_stmt = database::prepare(" select * " . table_panel_htaccess . " `path` like :docroot "); database::pexecute($result_stmt, [ 'docroot' =&gt; $domain['documentroot'] . '%' ]); $path_options = ''; $htpasswds = $this-&gt;gethtpasswds($domain); // entry htaccess table ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { (!empty($row['error404path'])) { $defhandler = $row['error404path']; (!validate::validateurl($defhandler)) { $defhandler = filedir::makecorrectfile($defhandler); } $path_options .= "\t" . 'error_page 404 ' . $defhandler . ';' . "\n"; } (!empty($row['error403path'])) { $defhandler = $row['error403path']; (!validate::validateurl($defhandler)) { $defhandler = filedir::makecorrectfile($defhandler); } $path_options .= "\t" . 'error_page 403 ' . $defhandler . ';' . "\n"; } (!empty($row['error500path'])) { $defhandler = $row['error500path']; (!validate::validateurl($defhandler)) { $defhandler = filedir::makecorrectfile($defhandler); } $path_options .= "\t" . 'error_page 500 502 503 504 ' . $defhandler . ';' . "\n"; } // ($row['options_indexes'] != '0') { $path = filedir::makecorrectdir(substr($row['path'], strlen($domain['documentroot']) - 1)); filedir::mkdirwithcorrectownership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); $path_options .= "\t" . '# ' . $path . "\n"; ($path == '/') { ($row['options_indexes'] != '0') { $this-&gt;vhost_root_autoindex = true; } $path_options .= "\t" . 'location ' . filedir::makecorrectdir($path) . ' {' . "\n"; ($this-&gt;vhost_root_autoindex) { $path_options .= "\t\t" . 'autoindex on;' . "\n"; $this-&gt;vhost_root_autoindex = false; } // check htpasswd path // (damn nginx like one // 'location'-part path) (count($htpasswds) &gt; 0) { foreach ($htpasswds $idx =&gt; $single) { switch ($single['path']) { case '/awstats/': case '/webalizer/': case '/goaccess/': // stats-alias "location /"-context break; default: ($single['path'] == '/') { $path_options .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; $path_options .= "\t\t" . 'auth_basic_user_file ' . filedir::makecorrectfile($single['usrf']) . ';' . "\n"; ($domain['phpenabled_customer'] == 1 &amp;&amp; $domain['phpenabled_vhost'] == '1') { $path_options .= "\t\t" . 'index index.php index.html index.htm;' . "\n"; } else { $path_options .= "\t\t" . 'index index.html index.htm;' . "\n"; } // remove already used entries doubles unset($htpasswds[$idx]); } } } } $path_options .= "\t" . '}' . "\n"; $this-&gt;vhost_root_autoindex = false; } else { $path_options .= "\t" . 'location ^~ ' . filedir::makecorrectfile($path) . ' {' . "\n"; ($this-&gt;vhost_root_autoindex || $row['options_indexes'] != '0') { $path_options .= "\t\t" . 'autoindex on;' . "\n"; $this-&gt;vhost_root_autoindex = false; } $path_options .= "\t" . '} ' . "\n"; } // } /** * perl support * required fastcgi wrapper running receive cgi requests. */ (customer::customerhasperlenabled($domain['customerid']) &amp;&amp; $row['options_cgi'] != '0') { $path = filedir::makecorrectdir(substr($row['path'], strlen($domain['documentroot']) - 1)); filedir::mkdirwithcorrectownership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); // need remove last slash, otherwise regex work ($row['path'] != $domain['documentroot']) { $path = substr($path, 0, -1); } $path_options .= "\t" . 'location ~ \(.pl|.cgi)$ {' . "\n"; $path_options .= "\t\t" . 'gzip off; #gzip makes scripts feel slower since complete getting gzipped' . "\n"; $path_options .= "\t\t" . 'fastcgi_pass ' . settings::get('system.perl_server') . ';' . "\n"; $path_options .= "\t\t" . 'fastcgi_index index.cgi;' . "\n"; $path_options .= "\t\t" . 'include ' . settings::get('nginx.fastcgiparams') . ';' . "\n"; $path_options .= "\t" . '}' . "\n"; } } // rest htpasswds (count($htpasswds) &gt; 0) { foreach ($htpasswds $idx =&gt; $single) { // ($single['path'] != '/') { switch ($single['path']) { case '/awstats/': case '/webalizer/': case '/goaccess/': $path_options .= $this-&gt;getstats($domain, $single); unset($htpasswds[$idx]); break; default: ($single['path'] == '/') { $path_options .= "\t" . 'location ' . filedir::makecorrectdir($single['path']) . ' {' . "\n"; } else { $path_options .= "\t" . 'location ^~ ' . filedir::makecorrectfile($single['path']) . ' {' . "\n"; } $path_options .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; $path_options .= "\t\t" . 'auth_basic_user_file ' . filedir::makecorrectfile($single['usrf']) . ';' . "\n"; ($domain['phpenabled_customer'] == 1 &amp;&amp; $domain['phpenabled_vhost'] == '1') { $path_options .= "\t\t" . 'index index.php index.html index.htm;' . "\n"; ($domain['notryfiles'] != 1) { $path_options .= "\t\t" . 'location ~ ^(.+?\.php)(/.*)?$ {' . "\n"; $path_options .= "\t\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n"; $path_options .= "\t\t" . '}' . "\n\n"; } } else { $path_options .= "\t\t" . 'index index.html index.htm;' . "\n"; } $path_options .= "\t" . '}' . "\n"; } // } unset($htpasswds[$idx]); } } return $path_options; } protected function gethtpasswds($domain) { $result_stmt = database::prepare(" select a.* `" . table_panel_htpasswds . "` join `" . table_panel_domains . "` b using (`customerid`) left join `" . table_panel_customers . "` c c.customerid = b.customerid b.customerid = :customerid b.domain = :domain (a.path = concat(c.documentroot, :ttool, '/') instr(a.path, b.documentroot)); "); database::pexecute($result_stmt, [ 'customerid' =&gt; $domain['customerid'], 'domain' =&gt; $domain['domain'], 'ttool' =&gt; settings::get('system.traffictool') ]); $returnval = []; $x = 0; ($row_htpasswds = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { (count($row_htpasswds) &gt; 0) { $htpasswd_filename = filedir::makecorrectfile(settings::get('system.apacheconf_htpasswddir') . '/' . $row_htpasswds['customerid'] . '-' . md5($row_htpasswds['path']) . '.htpasswd'); // ensure write array index $htpasswd_filename (!isset($this-&gt;htpasswds_data[$htpasswd_filename])) { $this-&gt;htpasswds_data[$htpasswd_filename] = ''; } $this-&gt;htpasswds_data[$htpasswd_filename] .= $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n"; // domains web contents located subdirectory // nginx user, evaluate right path protect (stripos($row_htpasswds['path'], $domain['documentroot']) !== false) { // website contents located user directory $path = filedir::makecorrectdir(substr($row_htpasswds['path'], strlen($domain['documentroot']) - 1)); } else { // website contents located subdirectory user $matches = []; preg_match('/^([\/[:print:]]*\/)([[:print:]\/]+){1}$/i', $row_htpasswds['path'], $matches); $path = filedir::makecorrectdir(substr($row_htpasswds['path'], strlen($matches[1]) - 1)); } $returnval[$x]['path'] = $path; $returnval[$x]['root'] = filedir::makecorrectdir($domain['documentroot']); // ensure one auth name per password block, otherwise // directives inserted multiple times -&gt; invalid config $authname = $row_htpasswds['authname']; ($i = 0; $i &lt; $x; $i++) { ($returnval[$i]['usrf'] == $htpasswd_filename) { $authname = $returnval[$i]['authname']; break; } } $returnval[$x]['authname'] = $authname; $returnval[$x]['usrf'] = $htpasswd_filename; $x++; } } // remove duplicate entries $returnval = array_map("unserialize", array_unique(array_map("serialize", $returnval))); return $returnval; } protected function getstats($domain, $single) { $stats_text = ''; $stattool = settings::get('system.traffictool'); $statdomain = ""; ($stattool == 'awstats') { // awstats generates domain regardless speciallogfile $statdomain = "/" . $domain['domain']; } ($domain['speciallogfile'] == '1') { $statdomain = "/" . (($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']); } $statdocroot = filedir::makecorrectfile($domain['customerroot'] . '/' . $stattool . $statdomain); $stats_text .= "\t" . 'location ^~ /'.$stattool.' {' . "\n"; $stats_text .= "\t\t" . 'alias ' . $statdocroot . '/;' . "\n"; $stats_text .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; $stats_text .= "\t\t" . 'auth_basic_user_file ' . filedir::makecorrectfile($single['usrf']) . ';' . "\n"; $stats_text .= "\t" . '}' . "\n\n"; // awstats special requirement icons ($stattool == 'awstats') { $stats_text .= "\t" . 'location ~ ^/awstats-icon/(.*)$ {' . "\n"; $stats_text .= "\t\t" . 'alias ' . filedir::makecorrectdir(settings::get('system.awstats_icons')) . '$1;' . "\n"; $stats_text .= "\t" . '}' . "\n\n"; } return $stats_text; } protected function composephpoptions(&amp;$domain, $ssl_vhost = false) { $phpopts = ''; ($domain['phpenabled_customer'] == 1 &amp;&amp; $domain['phpenabled_vhost'] == '1') { $phpopts = "\t" . 'location ~ ^(.+?\.php)(/.*)?$ {' . "\n"; ($domain['notryfiles'] != 1) { $phpopts .= "\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n"; $phpopts .= "\t" . '}' . "\n\n"; $phpopts .= "\tlocation @php {\n"; $phpopts .= "\t\t" . 'try_files $1 =404;' . "\n\n"; } $phpopts .= "\t\tfastcgi_split_path_info ^(.+?\.php)(/.*)$;\n"; $phpopts .= "\t\tinclude " . settings::get('nginx.fastcgiparams') . ";\n"; $phpopts .= "\t\tfastcgi_param script_filename \$request_filename;\n"; $phpopts .= "\t\tfastcgi_param path_info \$fastcgi_path_info;\n"; $phpopts .= "\t\tfastcgi_pass " . settings::get('system.nginx_php_backend') . ";\n"; $phpopts .= "\t\tfastcgi_index index.php;\n"; ($domain['ssl'] == '1' &amp;&amp; $ssl_vhost) { $phpopts .= "\t\tfastcgi_param https on;\n"; } $phpopts .= "\t}\n\n"; } return $phpopts; } /** * define default errordocument-statement, bug #unknown-yet */ private function createstandarderrorhandler() { (settings::get('defaultwebsrverrhandler.enabled') == '1' &amp;&amp; (settings::get('defaultwebsrverrhandler.err401') != '' || settings::get('defaultwebsrverrhandler.err403') != '' || settings::get('defaultwebsrverrhandler.err404') != '' || settings::get('defaultwebsrverrhandler.err500') != '')) { $vhosts_filename = $this-&gt;getcustomvhostfilename('05_froxlor_default_errorhandler.conf'); (!isset($this-&gt;nginx_data[$vhosts_filename])) { $this-&gt;nginx_data[$vhosts_filename] = ''; } $statuscodes = [ '401', '403', '404', '500' ]; foreach ($statuscodes $statuscode) { (settings::get('defaultwebsrverrhandler.err' . $statuscode) != '') { $defhandler = settings::get('defaultwebsrverrhandler.err' . $statuscode); (!validate::validateurl($defhandler)) { $defhandler = filedir::makecorrectfile($defhandler); } $this-&gt;nginx_data[$vhosts_filename] .= 'error_page ' . $statuscode . ' ' . $defhandler . ';' . "\n"; } } } } public function createownvhoststarter() { return; } public function writeconfigs() { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "nginx::writeconfigs: rebuilding " . settings::get('system.apacheconf_vhost')); $vhostdir = new directory(settings::get('system.apacheconf_vhost')); (!$vhostdir-&gt;isconfigdir()) { // save one big file $vhosts_file = ''; // sort filename order is: // 1. subdomains // 2. subdomains main-domains // 3. main-domains ksort($this-&gt;nginx_data); foreach ($this-&gt;nginx_data $vhosts_filename =&gt; $vhost_content) { $vhosts_file .= $vhost_content . "\n\n"; } $vhosts_filename = settings::get('system.apacheconf_vhost'); // apply header $vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# created ' . date('d.m.y h:i') . "\n" . '# manually edit file, changes deleted next domain change panel.' . "\n" . "\n" . $vhosts_file; $vhosts_file_handler = fopen($vhosts_filename, 'w'); fwrite($vhosts_file_handler, $vhosts_file); fclose($vhosts_file_handler); } else { (!file_exists(settings::get('system.apacheconf_vhost'))) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_notice, 'nginx::writeconfigs: mkdir ' . escapeshellarg(filedir::makecorrectdir(settings::get('system.apacheconf_vhost')))); filedir::safe_exec('mkdir -p ' . escapeshellarg(filedir::makecorrectdir(settings::get('system.apacheconf_vhost')))); } // write single file every vhost foreach ($this-&gt;nginx_data $vhosts_filename =&gt; $vhosts_file) { // apply header $vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# created ' . date('d.m.y h:i') . "\n" . '# manually edit file, changes deleted next domain change panel.' . "\n" . "\n" . $vhosts_file; (!empty($vhosts_filename)) { $vhosts_file_handler = fopen($vhosts_filename, 'w'); fwrite($vhosts_file_handler, $vhosts_file); fclose($vhosts_file_handler); } } } // htaccess stuff (count($this-&gt;htpasswds_data) &gt; 0) { (!file_exists(settings::get('system.apacheconf_htpasswddir'))) { $umask = umask(); umask(0000); mkdir(settings::get('system.apacheconf_htpasswddir'), 0751); umask($umask); } elseif (!is_dir(settings::get('system.apacheconf_htpasswddir'))) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_warning, 'warning!!! ' . settings::get('system.apacheconf_htpasswddir') . ' directory. htpasswd directory protection disabled!!!'); } (is_dir(settings::get('system.apacheconf_htpasswddir'))) { foreach ($this-&gt;htpasswds_data $htpasswd_filename =&gt; $htpasswd_file) { $this-&gt;known_htpasswdsfilenames[] = basename($htpasswd_filename); $htpasswd_file_handler = fopen($htpasswd_filename, 'w'); // filter duplicate pairs username password $htpasswd_file = implode("\n", array_unique(explode("\n", $htpasswd_file))); fwrite($htpasswd_file_handler, $htpasswd_file); fclose($htpasswd_file_handler); } } } } }</file><file name="lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http\letsencrypt; use froxlor\cron\froxlorcron; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\domain\domain; use froxlor\filedir; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\settings; use froxlor\system\cronjob; use froxlor\validate\validate; use pdo; use pdostatement; class acmesh extends froxlorcron { const acme_provider = [ 'letsencrypt' =&gt; "https://acme-v02.api.letsencrypt.org/directory", 'letsencrypt_test' =&gt; "https://acme-staging-v02.api.letsencrypt.org/directory", 'buypass' =&gt; "https://api.buypass.com/acme/directory", 'buypass_test' =&gt; "https://api.test4.buypass.no/acme/directory", 'zerossl' =&gt; "https://acme.zerossl.com/v2/dv90", 'google' =&gt; "https://dv.acme-v02.api.pki.goog/directory", 'google_test' =&gt; "https://dv.acme-v02.test-api.pki.goog/directory", ]; public static $no_inserttask = false; private static $apiserver = ""; private static $acmesh = "/root/.acme.sh/acme.sh"; /** * * @var pdostatement */ private static $updcert_stmt = null; /** * * @var pdostatement */ private static $upddom_stmt = null; /** * run task * * @param bool $internal * @return int * @throws \exception */ public static function run(bool $internal = false) { // usually, action called within tasks-jobs (!defined('cron_is_forced') &amp;&amp; !defined('cron_debug_flag') &amp;&amp; $internal == false) { // let's encrypt cronjob combined regeneration webserver configuration files. // debugging purposes use --debug switch --force switch run cron manually. // check whether might need run although task regenerate config-files $issue_froxlor = self::issuefroxlorvhost(); $issue_domains = self::issuedomains(); $renew_froxlor = self::renewfroxlorvhost(); $renew_domains = self::renewdomains(true); ($issue_froxlor || !empty($issue_domains) || !empty($renew_froxlor) || $renew_domains) { // insert task generate certificates vhost-configs cronjob::inserttask(taskid::rebuild_vhost); ($renew_froxlor) { cronjob::inserttask(taskid::update_le_services); } } return 0; } // set server according settings self::$apiserver = self::acme_provider[settings::get('system.letsencryptca')]; // validate acme.sh installation (!self::checkinstall()) { return -1; } self::checkupgrade(); // flag re-generation vhost files $changedetected = 0; // prepare update sql self::$updcert_stmt = database::prepare(" replace `" . table_panel_domain_ssl_settings . "` set `id` = :id, `domainid` = :domainid, `ssl_cert_file` = :crt, `ssl_key_file` = :key, `ssl_ca_file` = :ca, `ssl_cert_chainfile` = :chain, `ssl_csr_file` = :csr, `ssl_fullchain_file` = :fullchain, `validfromdate` = :validfromdate, `validtodate` = :validtodate, `issuer` = :issuer "); // prepare domain update sql self::$upddom_stmt = database::prepare("update `" . table_panel_domains . "` set `ssl_redirect` = '1' `id` = :domainid"); // check whether certificates issue $issue_froxlor = self::issuefroxlorvhost(); $issue_domains = self::issuedomains(); // first - generate le system-vhost enabled ($issue_froxlor) { // build row $certrow = [ 'loginname' =&gt; 'froxlor.panel', 'domain' =&gt; settings::get('system.hostname'), 'domainid' =&gt; 0, 'documentroot' =&gt; froxlor::getinstalldir(), 'leprivatekey' =&gt; settings::get('system.leprivatekey'), 'lepublickey' =&gt; settings::get('system.lepublickey'), 'leregistered' =&gt; settings::get('system.leregistered'), 'ssl_redirect' =&gt; settings::get('system.le_froxlor_redirect'), 'validfromdate' =&gt; null, 'validtodate' =&gt; null, 'issuer' =&gt; "", 'ssl_cert_file' =&gt; null, 'ssl_key_file' =&gt; null, 'ssl_ca_file' =&gt; null, 'ssl_csr_file' =&gt; null, 'id' =&gt; null, 'wwwserveralias' =&gt; 0 ]; // add queue $issue_domains[] = $certrow; } (count($issue_domains)) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "requesting " . count($issue_domains) . " new let's encrypt certificates"); self::runissuefor($issue_domains); $changedetected = 1; } // compare file-system certificates ones database // update needed $renew_froxlor = self::renewfroxlorvhost(); $renew_domains = self::renewdomains(); ($renew_froxlor) { // build row $certrow = [ 'loginname' =&gt; 'froxlor.panel', 'domain' =&gt; settings::get('system.hostname'), 'domainid' =&gt; 0, 'documentroot' =&gt; froxlor::getinstalldir(), 'leprivatekey' =&gt; settings::get('system.leprivatekey'), 'lepublickey' =&gt; settings::get('system.lepublickey'), 'leregistered' =&gt; settings::get('system.leregistered'), 'ssl_redirect' =&gt; settings::get('system.le_froxlor_redirect'), 'validfromdate' =&gt; is_array($renew_froxlor) ? $renew_froxlor['validfromdate'] : date('y-m-d h:i:s', 0), 'validtodate' =&gt; is_array($renew_froxlor) ? $renew_froxlor['validtodate'] : date('y-m-d h:i:s', 0), 'issuer' =&gt; is_array($renew_froxlor) ? $renew_froxlor['issuer'] : "", 'ssl_cert_file' =&gt; is_array($renew_froxlor) ? $renew_froxlor['ssl_cert_file'] : null, 'ssl_key_file' =&gt; is_array($renew_froxlor) ? $renew_froxlor['ssl_key_file'] : null, 'ssl_ca_file' =&gt; is_array($renew_froxlor) ? $renew_froxlor['ssl_ca_file'] : null, 'ssl_csr_file' =&gt; is_array($renew_froxlor) ? $renew_froxlor['ssl_csr_file'] : null, 'id' =&gt; is_array($renew_froxlor) ? $renew_froxlor['id'] : null, 'wwwserveralias' =&gt; 0 ]; $renew_domains[] = $certrow; } foreach ($renew_domains $domain) { $cronlog = froxlorlogger::getinstanceof([ 'loginname' =&gt; $domain['loginname'], 'adminsession' =&gt; 0 ]); (defined('cron_is_forced') || self::checkfsfilesarenewer($domain['domain'], $domain['validtodate'])) { self::certtodb($domain, $cronlog, []); $changedetected = 1; } } // change certificate, need update webserver - configs // easiest done creating new task ;) ($changedetected) { (self::$no_inserttask == false) { cronjob::inserttask(taskid::rebuild_vhost); } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "let's encrypt certificates updated"); } else { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "no new certificates certificate updates found"); } return 0; } /** * check whether need issue new certificate froxlor * * @return boolean * @throws \exception */ private static function issuefroxlorvhost() { (settings::get('system.le_froxlor_enabled') == '1') { // let's encrypt enabled, check whether certificate $froxlor_ssl_settings_stmt = database::prepare(" select * `" . table_panel_domain_ssl_settings . "` `domainid` = '0' "); $froxlor_ssl = database::pexecute_first($froxlor_ssl_settings_stmt); // also check possible existing certificate (($froxlor_ssl &amp;&amp; empty($froxlor_ssl['validtodate'])) || (!$froxlor_ssl &amp;&amp; !self::checkfsfilesarenewer(settings::get('system.hostname'), date('y-m-d h:i:s'))) ) { return true; } } return false; } private static function checkfsfilesarenewer($domain, $cert_date = 0): bool { $certificate_folder = self::getcertificatefolder(strtolower($domain)); (empty($certificate_folder)) { return false; } $ssl_file = filedir::makecorrectfile($certificate_folder . '/' . strtolower($domain) . '.cer'); (is_dir($certificate_folder) &amp;&amp; file_exists($ssl_file) &amp;&amp; is_readable($ssl_file)) { $cert_data = openssl_x509_parse(file_get_contents($ssl_file)); ($cert_data &amp;&amp; $cert_data['validto_time_t'] &gt; strtotime($cert_date)) { return true; } } return false; } public static function getworkingdirfromenv($domain = "", $forced_ecc = false): string { // first try without _ecc either enabled currently // might point chance certificates // without _ecc - method getcertificatefolder() check // possibilities ($forced_ecc) { $domain .= "_ecc"; } $env_file = filedir::makecorrectfile(dirname(self::getacmesh()) . '/acme.sh.env'); (file_exists($env_file)) { $output = []; $cut = &lt;&lt;&lt;eoc cut -d'"' -f2 eoc; exec('grep "le_working_dir" ' . escapeshellarg($env_file) . ' | ' . $cut, $output); (is_array($output) &amp;&amp; !empty($output) &amp;&amp; !empty($output[0])) { return filedir::makecorrectdir($output[0] . "/" . $domain); } } return filedir::makecorrectdir(dirname(self::getacmesh()) . "/" . $domain); } public static function getacmesh() { $from_settings = settings::get('system.acmeshpath'); (file_exists($from_settings)) { return $from_settings; } return self::$acmesh; } /** * get list domains require new certificate (issue) */ private static function issuedomains() { $certificates_stmt = database::query(" select domssl.`id`, domssl.`domainid`, domssl.`validfromdate`, domssl.`validtodate`, domssl.`issuer`, domssl.`ssl_cert_file`, domssl.`ssl_key_file`, domssl.`ssl_ca_file`, domssl.`ssl_csr_file`, dom.`domain`, dom.`wwwserveralias`, dom.`documentroot`, dom.`id` 'domainid', dom.`ssl_redirect`, cust.`leprivatekey`, cust.`lepublickey`, cust.`leregistered`, cust.`customerid`, cust.`loginname` `" . table_panel_customers . "` cust, `" . table_panel_domains . "` dom left join `" . table_panel_domain_ssl_settings . "` domssl dom.`id` = domssl.`domainid` dom.`customerid` = cust.`customerid` cust.deactivated = 0 dom.deactivated = 0 dom.`ssl_enabled` = 1 dom.`letsencrypt` = 1 dom.`aliasdomain` null dom.`iswildcarddomain` = 0 dom.`email_only` = 0 domssl.`validtodate` null "); $customer_ssl = $certificates_stmt-&gt;fetchall(pdo::fetch_assoc); ($customer_ssl) { return $customer_ssl; } return []; } /** * check whether need renew-check certificate froxlor * * @return boolean * @throws \exception */ private static function renewfroxlorvhost() { (settings::get('system.le_froxlor_enabled') == '1') { // let's encrypt enabled, check whether certificate $froxlor_ssl_settings_stmt = database::prepare(" select * `" . table_panel_domain_ssl_settings . "` `domainid` = '0' "); $froxlor_ssl = database::pexecute_first($froxlor_ssl_settings_stmt); // also check possible existing certificate ($froxlor_ssl &amp;&amp; self::checkfsfilesarenewer(settings::get('system.hostname'), $froxlor_ssl['validtodate'])) { return $froxlor_ssl; } } return false; } /** * get list domains lets encrypt certificate (possible renew) */ private static function renewdomains($check = false) { $certificates_stmt = database::query(" select domssl.`id`, domssl.`domainid`, domssl.`validfromdate`, domssl.`validtodate`, domssl.`issuer`, domssl.`ssl_cert_file`, domssl.`ssl_key_file`, dom.`domain`, dom.`id` 'domainid', dom.`ssl_redirect`, cust.`loginname` `" . table_panel_customers . "` cust, `" . table_panel_domains . "` dom left join `" . table_panel_domain_ssl_settings . "` domssl dom.`id` = domssl.`domainid` dom.`customerid` = cust.`customerid` cust.deactivated = 0 dom.deactivated = 0 dom.`ssl_enabled` = 1 dom.`letsencrypt` = 1 dom.`aliasdomain` null dom.`iswildcarddomain` = 0 dom.`email_only` = 0 "); $renew_certs = $certificates_stmt-&gt;fetchall(pdo::fetch_assoc); ($renew_certs) { ($check) { foreach ($renew_certs $cert) { (self::checkfsfilesarenewer($cert['domain'], $cert['validtodate'])) { return true; } } return false; } return $renew_certs; } return []; } /** * install acme.sh found yet */ private static function checkinstall($tries = 0) { (!file_exists(self::getacmesh()) &amp;&amp; $tries &gt; 0) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, "download/installation acme.sh seems failed. re-run cronjob try install manually '" . self::getacmesh() . "'"); echo php_eol . "download/installation acme.sh seems failed. re-run cronjob try install manually '" . self::getacmesh() . "'" . php_eol; return false; } else { (!file_exists(self::getacmesh())) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "could find acme.sh - installing /root/.acme.sh/"); $return = false; filedir::safe_exec("wget -o - https://get.acme.sh | sh -s email=" . settings::get('panel.adminmail'), $return, [ '|' ]); $set_path = self::getacmesh(); // this, regardless user specified, acme.sh installation /root/.acme.sh ($set_path != '/root/.acme.sh/acme.sh') { settings::set('system.acmeshpath', '/root/.acme.sh/acme.sh', true); // let user know froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_warning, "acme.sh could found '" . $set_path . "' froxlor installed default location, '/root/.acme.sh/'"); echo php_eol . "acme.sh could found '" . $set_path . "' froxlor installed default location, '/root/.acme.sh/'" . php_eol; } // check whether installation worked return self::checkinstall(++$tries); } } return true; } /** * run upgrade */ private static function checkupgrade() { $acmesh_result = filedir::safe_exec(self::getacmesh() . " --upgrade --auto-upgrade 0"); // check activated cron $acmesh_result2 = filedir::safe_exec(self::getacmesh() . " --install-cronjob"); // set default ca $acmesh_result3 = filedir::safe_exec(self::getacmesh() . " --set-default-ca --server " . self::$apiserver); // log messages froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_info, "checking letsencrypt client upgrades renewing certificates:\n" . implode("\n", $acmesh_result) . "\n" . implode("\n", $acmesh_result2) . "\n" . implode("\n", $acmesh_result3)); } /** * issue certificates list domains */ private static function runissuefor($certrows = []) { // prepare aliasdomain-check $aliasdomains_stmt = database::prepare(" select dom.`id` domainid, dom.`domain`, dom.`wwwserveralias` `" . table_panel_domains . "` dom dom.`aliasdomain` = :id dom.`letsencrypt` = 1 dom.`iswildcarddomain` = 0 "); // iterate domains foreach ($certrows $certrow) { // set logger corresponding loginname log appear users system-log $cronlog = froxlorlogger::getinstanceof([ 'loginname' =&gt; $certrow['loginname'], 'adminsession' =&gt; 0 ]); // issue let's encrypt certificate broken ssl_redirect enabled ($certrow['ssl_redirect'] != 2) { $do_force = false; (!empty($certrow['ssl_cert_file']) &amp;&amp; empty($certrow['validtodate'])) { // domain changed (san similar) $do_force = true; $cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, "re-creating certificate " . $certrow['domain']); } else { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, "creating certificate " . $certrow['domain']); } $cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, "adding common-name: " . $certrow['domain']); $domains = [ strtolower($certrow['domain']) ]; // add www.&lt;domain&gt; san list ($certrow['wwwserveralias'] == 1) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, "adding san entry: www." . $certrow['domain']); $domains[] = strtolower('www.' . $certrow['domain']); } ($certrow['domainid'] == 0) { $froxlor_aliases = settings::get('system.froxloraliases'); (!empty($froxlor_aliases)) { $froxlor_aliases = explode(",", $froxlor_aliases); foreach ($froxlor_aliases $falias) { (validate::validatedomain(trim($falias))) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, "adding san entry: " . strtolower(trim($falias))); $domains[] = strtolower(trim($falias)); } } } } else { // add alias domains (and possibly www.&lt;aliasdomain&gt;) san list database::pexecute($aliasdomains_stmt, [ 'id' =&gt; $certrow['domainid'] ]); $aliasdomains = $aliasdomains_stmt-&gt;fetchall(pdo::fetch_assoc); foreach ($aliasdomains $aliasdomain) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, "adding san entry: " . $aliasdomain['domain']); $domains[] = strtolower($aliasdomain['domain']); ($aliasdomain['wwwserveralias'] == 1) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, "adding san entry: www." . $aliasdomain['domain']); $domains[] = strtolower('www.' . $aliasdomain['domain']); } } } self::validatedns($domains, $certrow['domainid'], $cronlog); self::runacmesh($certrow, $domains, $cronlog, $do_force, $certrow['domainid'] == 0); } else { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_warning, "skipping let's encrypt generation " . $certrow['domain'] . " due enabled ssl_redirect"); // need another reconfigure order get certificate cronjob::inserttask(taskid::rebuild_vhost); } } } /** * validate dns (a / aaaa record) domain known system ips * * @param array $domains * @param int $domain_id * @param froxlorlogger $cronlog * @throws \exception */ private static function validatedns(array &amp;$domains, $domain_id, &amp;$cronlog) { (settings::get('system.le_domain_dnscheck') == '1' &amp;&amp; !empty($domains)) { $loop_domains = $domains; // ips according system $our_ips = domain::getipsofdomain($domain_id); foreach ($loop_domains $idx =&gt; $domain) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, "validating dns " . $domain); // ips according ns $domain_ips = phphelper::gethostbynamel6($domain, true, settings::get('system.le_domain_dnscheck_resolver')); ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) &lt;= 0) { // common ips... $cronlog-&gt;logaction(froxlorlogger::cron_action, log_warning, "skipping let's encrypt generation " . $domain . " due system known ip address via dns check"); unset($domains[$idx]); // order avoid cron-loop tries get certificate every 5 minutes, disable let's encrypt domain ($domain_id &gt; 0) { $upd_stmt = database::prepare("update `" . table_panel_domains . "` set `letsencrypt` = '0' `id` = :did"); database::pexecute($upd_stmt, [ 'did' =&gt; $domain_id ]); } else { // froxlor's hostname settings::set('system.le_froxlor_enabled', 0); } $cronlog-&gt;logaction(froxlorlogger::cron_action, log_warning, "let's encrypt deactivated domain " . $domain); (!defined('cron_is_forced') &amp;&amp; !defined('cron_debug_flag')) { // email info admin lets encrypt disabled domain cronjob::notifymailtoadmin("let's encrypt deactivated domain '" . $domain . "' due failed dns validation (wrong ip address)"); } } } } } private static function runacmesh(array $certrow, array $domains, &amp;$cronlog = null, bool $force = false, bool $renew_hook = false) { (!empty($domains)) { $acmesh_cmd = self::getacmesh() . " --server " . self::$apiserver . " --issue -d " . implode(" -d ", $domains); // challenge path $acmesh_cmd .= " -w " . settings::get('system.letsencryptchallengepath'); (settings::get('system.leecc') &gt; 0) { // ecc certificate $acmesh_cmd .= " --keylength ec-" . settings::get('system.leecc'); } else { $acmesh_cmd .= " --keylength " . settings::get('system.letsencryptkeysize'); } (settings::get('system.letsencryptreuseold') != '1') { $acmesh_cmd .= " --always-force-new-domain-key"; } (substr(settings::get('system.letsencryptca'), -5) == '_test') { $acmesh_cmd .= " --staging"; } ($force) { $acmesh_cmd .= " --force"; } ($renew_hook &amp;&amp; !empty(trim(settings::get('system.le_renew_services') ?? "")) &amp;&amp; !empty(trim(settings::get('system.le_renew_hook') ?? "")) ) { $acmesh_cmd .= " --renew-hook '" . settings::get('system.le_renew_hook') . "'"; } (defined('cron_debug_flag')) { $acmesh_cmd .= " --debug"; } $exit_code = null; $acme_result = filedir::safe_exec($acmesh_cmd, $exit_code); // debug output acme.sh run $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, implode("\n", $acme_result)); ($exit_code != 0) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, "non-successful exit-code returned :("); (!defined('cron_is_forced') &amp;&amp; !defined('cron_debug_flag')) { cronjob::notifymailtoadmin("let's encrypt certificate could obtained for: " . implode(", ", $domains) . "\n\n" . implode("\n", $acme_result)); } } else { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, "successful exit-code returned - storing certificate"); $cert_stored = self::certtodb($certrow, $cronlog, $acme_result); ($cert_stored &amp;&amp; $renew_hook) { self::renewhookconfigs($cronlog); } } } } public static function renewhookconfigs($cronlog) { (!empty(trim(settings::get('system.le_renew_services') ?? "")) &amp;&amp; !empty(trim(settings::get('system.le_renew_hook') ?? "")) ) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_debug, "renew-hook enabled - adjusting configurations"); $certificate_folder = self::getcertificatefolder(strtolower(settings::get('system.hostname'))); (empty($certificate_folder)) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, "no certificate folder '" . settings::get('system.hostname') . "' found"); return; } $fullchain = filedir::makecorrectfile($certificate_folder . '/fullchain.cer'); $keyfile = filedir::makecorrectfile($certificate_folder . '/' . strtolower(settings::get('system.hostname')) . '.key'); $ca_file = filedir::makecorrectfile($certificate_folder . '/ca.cer'); (!file_exists($fullchain) || !file_exists($keyfile) || !file_exists($ca_file)) { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, "at least one required certificate files '" . settings::get('system.hostname') . "' could found"); return; } $dovecot_conf = '/etc/dovecot/conf.d/99-froxlor.ssl.conf'; // @fixme setting? (settings::isinlist('system.le_renew_services', 'postfix')) { // "postconf -e" postfix filedir::safe_exec('postconf -e smtpd_tls_cert_file=' . escapeshellarg($fullchain)); filedir::safe_exec('postconf -e smtpd_tls_key_file=' . escapeshellarg($keyfile)); } (settings::isinlist('system.le_renew_services', 'dovecot')) { // custom config dovecot $ssl_content = &lt;&lt;&lt;eossl # autogenerated configuration froxlor. # manually edit file overwritten. ssl = yes ssl_cert = &lt;{$fullchain} ssl_key = &lt;{$keyfile} eossl; file_put_contents($dovecot_conf, $ssl_content); } elseif (file_exists($dovecot_conf)) { // safely remove autogenerated config file unlink($dovecot_conf); } (settings::isinlist('system.le_renew_services', 'proftpd')) { $proftpd_conf = '/etc/proftpd/tls.conf'; // @fixme setting? $rval = false; // ecc certificate not? (strpos($certificate_folder, '_ecc') === false) { // comment ecc related settings filedir::safe_exec("sed -i.bak 's|^tlseccertificatefile|# tlseccertificatefile|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']); filedir::safe_exec("sed -i.bak 's|^tlseccertificatekeyfile|# tlseccertificatekeyfile|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']); // add rsa directives filedir::safe_exec("sed -i.bak 's|^#\?\s\?tlsrsacertificatefile.*|tlsrsacertificatefile " . $fullchain . "|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']); filedir::safe_exec("sed -i.bak 's|^#\?\s\?tlsrsacertificatekeyfile.*|tlsrsacertificatekeyfile " . $keyfile . "|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']); } else { // comment rsa related settings filedir::safe_exec("sed -i.bak 's|^tlsrsacertificatefile|# tlsrsacertificatefile|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']); filedir::safe_exec("sed -i.bak 's|^tlsrsacertificatekeyfile|# tlsrsacertificatekeyfile|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']); // add ecc directives filedir::safe_exec("sed -i.bak 's|^#\?\s\?tlseccertificatefile.*|tlseccertificatefile " . $fullchain . "|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']); filedir::safe_exec("sed -i.bak 's|^#\?\s\?tlseccertificatekeyfile.*|tlseccertificatekeyfile " . $keyfile . "|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']); } filedir::safe_exec("sed -i.bak 's|^#\?\s\?tlscacertificatefile.*|tlscacertificatefile " . $ca_file . "|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']); } // reload services filedir::safe_exec(settings::get('system.le_renew_hook')); } } private static function certtodb($certrow, &amp;$cronlog, $acme_result): bool { $return = []; self::readcertificatetovar(strtolower($certrow['domain']), $return, $cronlog); (!empty($return['crt'])) { $newcert = openssl_x509_parse($return['crt']); ($newcert) { // store new data database::pexecute(self::$updcert_stmt, [ 'id' =&gt; $certrow['id'], 'domainid' =&gt; $certrow['domainid'], 'crt' =&gt; $return['crt'], 'key' =&gt; $return['key'], 'ca' =&gt; $return['chain'], 'chain' =&gt; $return['chain'], 'csr' =&gt; $return['csr'], 'fullchain' =&gt; $return['fullchain'], 'validfromdate' =&gt; date('y-m-d h:i:s', $newcert['validfrom_time_t']), 'validtodate' =&gt; date('y-m-d h:i:s', $newcert['validto_time_t']), 'issuer' =&gt; $newcert['issuer']['o'] ?? "" ]); ($certrow['ssl_redirect'] == 3) { database::pexecute(self::$upddom_stmt, [ 'domainid' =&gt; $certrow['domainid'] ]); } $cronlog-&gt;logaction(froxlorlogger::cron_action, log_info, "updated let's encrypt certificate " . $certrow['domain']); return true; } else { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_err, "got non-successful let's encrypt response " . $certrow['domain'] . ":\n" . implode("\n", $acme_result)); } } else { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_err, "could get let's encrypt certificate " . $certrow['domain'] . ":\n" . implode("\n", $acme_result)); } return false; } /** * get certificate files filesystem store $return array * * @param string $domain * @param array $return * @param object $cronlog */ private static function readcertificatetovar($domain, &amp;$return, &amp;$cronlog) { $certificate_folder = self::getcertificatefolder($domain); (!empty($certificate_folder)) { $certificate_files = [ 'crt' =&gt; $domain . '.cer', 'key' =&gt; $domain . '.key', 'chain' =&gt; 'ca.cer', 'fullchain' =&gt; 'fullchain.cer', 'csr' =&gt; $domain . '.csr' ]; foreach ($certificate_files $index =&gt; $sslfile) { $ssl_file = filedir::makecorrectfile($certificate_folder . '/' . $sslfile); (file_exists($ssl_file)) { $return[$index] = file_get_contents($ssl_file); } else { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_err, "could find file '" . $sslfile . "' '" . $certificate_folder . "'"); $return[$index] = null; } } } else { $cronlog-&gt;logaction(froxlorlogger::cron_action, log_err, "could find certificate-folder '" . $certificate_folder . "'"); } } private static function getcertificatefolder(string $domain): string { $certificate_folder = self::getworkingdirfromenv(strtolower($domain)); (file_exists($certificate_folder)) { return $certificate_folder; } $certificate_folder_ecc = self::getworkingdirfromenv($domain, true); (file_exists($certificate_folder_ecc)) { return $certificate_folder_ecc; } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::cron_action, log_err, "could find certificate-folder domain '" . $domain . "'"); return ""; } }</file><file name="lib/Froxlor/Cron/Http/LetsEncrypt/index.html" /><file name="lib/Froxlor/Cron/Http/Php/Fcgid.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http\php; use froxlor\database\database; use froxlor\domain\domain; use froxlor\filedir; use froxlor\phphelper; use froxlor\settings; class fcgid { /** * domain-data array * * @var array */ private $domain = []; /** * admin-date cache array * * @var array */ private $admin_cache = []; /** * main constructor */ public function __construct($domain) { $this-&gt;domain = $domain; } /** * create fcgid-starter-file * * @param array $phpconfig */ public function createconfig($phpconfig) { // create starter $starter_file = "#!/bin/sh\n\n"; $starter_file .= "#\n"; $starter_file .= "# starter created/changed " . date("y.m.d h:i:s") . " domain '" . $this-&gt;domain['domain'] . "' id #" . $this-&gt;domain['id'] . " php template '" . $phpconfig['description'] . "' id #" . $phpconfig['id'] . "\n"; $starter_file .= "# change anything file, overwritten froxlor cronjob!\n"; $starter_file .= "#\n\n"; $starter_file .= "umask " . $phpconfig['mod_fcgid_umask'] . "\n"; $starter_file .= "phprc=" . escapeshellarg($this-&gt;getconfigdir()) . "\n"; $starter_file .= "export phprc\n"; // set number processes one domain ((int)$this-&gt;domain['mod_fcgid_starter'] != -1) { $starter_file .= "php_fcgi_children=" . (int)$this-&gt;domain['mod_fcgid_starter'] . "\n"; } else { ((int)$phpconfig['mod_fcgid_starter'] != -1) { $starter_file .= "php_fcgi_children=" . (int)$phpconfig['mod_fcgid_starter'] . "\n"; } else { $starter_file .= "php_fcgi_children=" . (int)settings::get('system.mod_fcgid_starter') . "\n"; } } $starter_file .= "export php_fcgi_children\n"; // set number maximum requests one domain ((int)$this-&gt;domain['mod_fcgid_maxrequests'] != -1) { $starter_file .= "php_fcgi_max_requests=" . (int)$this-&gt;domain['mod_fcgid_maxrequests'] . "\n"; } else { ((int)$phpconfig['mod_fcgid_maxrequests'] != -1) { $starter_file .= "php_fcgi_max_requests=" . (int)$phpconfig['mod_fcgid_maxrequests'] . "\n"; } else { $starter_file .= "php_fcgi_max_requests=" . (int)settings::get('system.mod_fcgid_maxrequests') . "\n"; } } $starter_file .= "export php_fcgi_max_requests\n"; // set binary $starter_file .= "exec " . $phpconfig['binary'] . " -c " . escapeshellarg($this-&gt;getconfigdir()) . "\n"; // remove +i attribute, starter overwritten (file_exists($this-&gt;getstarterfile())) { filedir::removeimmutable($this-&gt;getstarterfile()); } $starter_file_handler = fopen($this-&gt;getstarterfile(), 'w'); fwrite($starter_file_handler, $starter_file); fclose($starter_file_handler); filedir::safe_exec('chmod 750 ' . escapeshellarg($this-&gt;getstarterfile())); filedir::safe_exec('chown ' . $this-&gt;domain['guid'] . ':' . $this-&gt;domain['guid'] . ' ' . escapeshellarg($this-&gt;getstarterfile())); filedir::setimmutable($this-&gt;getstarterfile()); } /** * fcgid-config directory * * @param boolean $createifnotexists * create directory exist * * @return string directory */ public function getconfigdir($createifnotexists = true) { $configdir = filedir::makecorrectdir(settings::get('system.mod_fcgid_configdir') . '/' . $this-&gt;domain['loginname'] . '/' . $this-&gt;domain['domain'] . '/'); (!is_dir($configdir) &amp;&amp; $createifnotexists) { filedir::safe_exec('mkdir -p ' . escapeshellarg($configdir)); filedir::safe_exec('chown ' . $this-&gt;domain['guid'] . ':' . $this-&gt;domain['guid'] . ' ' . escapeshellarg($configdir)); } return $configdir; } /** * return path php-starter file * * @return string directory */ public function getstarterfile() { $starter_filename = filedir::makecorrectfile($this-&gt;getconfigdir() . '/php-fcgi-starter'); return $starter_filename; } /** * create customized php.ini * * @param array $phpconfig */ public function createinifile($phpconfig) { $openbasedir = ''; $openbasedirc = ';'; ($this-&gt;domain['openbasedir'] == '1') { $openbasedirc = ''; $_phpappendopenbasedir = ''; $_custom_openbasedir = explode(':', settings::get('system.mod_fcgid_peardir')); foreach ($_custom_openbasedir $cobd) { $_phpappendopenbasedir .= domain::appendopenbasedirpath($cobd); } $_custom_openbasedir = explode(':', settings::get('system.phpappendopenbasedir')); foreach ($_custom_openbasedir $cobd) { $_phpappendopenbasedir .= domain::appendopenbasedirpath($cobd); } ($this-&gt;domain['openbasedir_path'] == '0' &amp;&amp; strstr($this-&gt;domain['documentroot'], ":") === false) { $openbasedir = domain::appendopenbasedirpath($this-&gt;domain['documentroot'], true); } else ($this-&gt;domain['openbasedir_path'] == '2' &amp;&amp; strpos(dirname($this-&gt;domain['documentroot']).'/', $this-&gt;domain['customerroot']) !== false) { $openbasedir = domain::appendopenbasedirpath(dirname($this-&gt;domain['documentroot']).'/', true); } else { $openbasedir = domain::appendopenbasedirpath($this-&gt;domain['customerroot'], true); } $openbasedir .= domain::appendopenbasedirpath($this-&gt;gettempdir()); $openbasedir .= $_phpappendopenbasedir; } else { $openbasedir = 'none'; $openbasedirc = ';'; } $admin = $this-&gt;getadmindata($this-&gt;domain['adminid']); $php_ini_variables = [ 'safe_mode' =&gt; 'off', // keep compatibility, case 'pear_dir' =&gt; settings::get('system.mod_fcgid_peardir'), 'tmp_dir' =&gt; $this-&gt;gettempdir(), 'customer_email' =&gt; $this-&gt;domain['email'], 'admin_email' =&gt; $admin['email'], 'domain' =&gt; $this-&gt;domain['domain'], 'customer' =&gt; $this-&gt;domain['loginname'], 'admin' =&gt; $admin['loginname'], 'open_basedir' =&gt; $openbasedir, 'open_basedir_c' =&gt; $openbasedirc, 'open_basedir_global' =&gt; settings::get('system.phpappendopenbasedir'), 'document_root' =&gt; filedir::makecorrectdir($this-&gt;domain['documentroot']), 'customer_homedir' =&gt; filedir::makecorrectdir($this-&gt;domain['customerroot']) ]; // insert small header file $phpini_file = ";\n"; $phpini_file .= "; php.ini created/changed " . date("y.m.d h:i:s") . " domain '" . $this-&gt;domain['domain'] . "' id #" . $this-&gt;domain['id'] . " php template '" . $phpconfig['description'] . "' id #" . $phpconfig['id'] . "\n"; $phpini_file .= "; change anything file, overwritten froxlor cronjob!\n"; $phpini_file .= ";\n\n"; $phpini_file .= phphelper::replacevariables($phpconfig['phpsettings'], $php_ini_variables); $phpini_file = str_replace('"none"', 'none', $phpini_file); // $phpini_file = preg_replace('/\"+/', '"', $phpini_file); $phpini_file_handler = fopen($this-&gt;getinifile(), 'w'); fwrite($phpini_file_handler, $phpini_file); fclose($phpini_file_handler); filedir::safe_exec('chown root:0 ' . escapeshellarg($this-&gt;getinifile())); filedir::safe_exec('chmod 0644 ' . escapeshellarg($this-&gt;getinifile())); } /** * fcgid-temp directory * * @param boolean $createifnotexists * create directory exist * * @return string directory */ public function gettempdir($createifnotexists = true) { $tmpdir = filedir::makecorrectdir(settings::get('system.mod_fcgid_tmpdir') . '/' . $this-&gt;domain['loginname'] . '/'); (!is_dir($tmpdir) &amp;&amp; $createifnotexists) { filedir::safe_exec('mkdir -p ' . escapeshellarg($tmpdir)); filedir::safe_exec('chown -r ' . $this-&gt;domain['guid'] . ':' . $this-&gt;domain['guid'] . ' ' . escapeshellarg($tmpdir)); filedir::safe_exec('chmod 0750 ' . escapeshellarg($tmpdir)); } return $tmpdir; } /** * return admin-data specific admin * * @param int $adminid * id admin-user * * @return array */ private function getadmindata($adminid) { $adminid = intval($adminid); (!isset($this-&gt;admin_cache[$adminid])) { $stmt = database::prepare(" select `email`, `loginname` `" . table_panel_admins . "` `adminid` = :id"); $this-&gt;admin_cache[$adminid] = database::pexecute_first($stmt, [ 'id' =&gt; $adminid ]); } return $this-&gt;admin_cache[$adminid]; } /** * return path php.ini file * * @return string full path file-name */ public function getinifile() { $phpini_filename = filedir::makecorrectfile($this-&gt;getconfigdir() . '/php.ini'); return $phpini_filename; } }</file><file name="lib/Froxlor/Cron/Http/Php/Fpm.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http\php; use froxlor\database\database; use froxlor\domain\domain; use froxlor\filedir; use froxlor\phphelper; use froxlor\settings; class fpm { /** * domain-data array * * @var array */ private $domain = []; /** * fpm config * * @var array */ private $fpm_cfg = []; /** * admin-date cache array * * @var array */ private $admin_cache = []; /** * defines used pool-config php.ini * mostly taken http://php.net/manual/en/ini.list.php * * @var array */ private $ini = []; /** * main constructor */ public function __construct($domain) { (!isset($domain['fpm_config_id']) || empty($domain['fpm_config_id'])) { $domain['fpm_config_id'] = 1; } $this-&gt;domain = $domain; $this-&gt;readfpmconfig($domain['fpm_config_id']); $this-&gt;buildinimapping(); } private function readfpmconfig($fpm_config_id) { $stmt = database::prepare("select * `" . table_panel_fpmdaemons . "` `id` = :id"); $this-&gt;fpm_cfg = database::pexecute_first($stmt, [ 'id' =&gt; $fpm_config_id ]); } private function buildinimapping() { $this-&gt;ini = [ 'php_flag' =&gt; array_map('trim', explode("\n", settings::get('phpfpm.ini_flags'))), 'php_value' =&gt; array_map('trim', explode("\n", settings::get('phpfpm.ini_values'))), 'php_admin_flag' =&gt; array_map('trim', explode("\n", settings::get('phpfpm.ini_admin_flags'))), 'php_admin_value' =&gt; array_map('trim', explode("\n", settings::get('phpfpm.ini_admin_values'))) ]; } /** * create dummy fpm pool config minimal configuration * (this used whenever config directory empty needs least one pool startup/restart) * * @param string $configdir */ public static function createdummypool($configdir) { (!is_dir($configdir)) { filedir::safe_exec('mkdir -p ' . escapeshellarg($configdir)); } $config = filedir::makecorrectfile($configdir . '/dummy.conf'); $dummy = "[dummy] user = " . settings::get('system.httpuser') . " listen = /run/" . md5($configdir) . "-fpm.sock pm = static pm.max_children = 1 "; file_put_contents($config, $dummy); } /** * create fpm-pool config * * @param array $phpconfig */ public function createconfig($phpconfig) { $fh = @fopen($this-&gt;getconfigfile(), 'w'); ($fh) { ($phpconfig['override_fpmconfig'] == 1) { $this-&gt;fpm_cfg['pm'] = $phpconfig['pm']; $this-&gt;fpm_cfg['max_children'] = $phpconfig['max_children']; $this-&gt;fpm_cfg['start_servers'] = $phpconfig['start_servers']; $this-&gt;fpm_cfg['min_spare_servers'] = $phpconfig['min_spare_servers']; $this-&gt;fpm_cfg['max_spare_servers'] = $phpconfig['max_spare_servers']; $this-&gt;fpm_cfg['max_requests'] = $phpconfig['max_requests']; $this-&gt;fpm_cfg['idle_timeout'] = $phpconfig['idle_timeout']; $this-&gt;fpm_cfg['limit_extensions'] = $phpconfig['limit_extensions']; } $fpm_pm = $this-&gt;fpm_cfg['pm']; $fpm_children = (int)$this-&gt;fpm_cfg['max_children']; $fpm_start_servers = (int)$this-&gt;fpm_cfg['start_servers']; $fpm_min_spare_servers = (int)$this-&gt;fpm_cfg['min_spare_servers']; $fpm_max_spare_servers = (int)$this-&gt;fpm_cfg['max_spare_servers']; $fpm_requests = (int)$this-&gt;fpm_cfg['max_requests']; $fpm_process_idle_timeout = (int)$this-&gt;fpm_cfg['idle_timeout']; $fpm_limit_extensions = $this-&gt;fpm_cfg['limit_extensions']; $fpm_custom_config = $this-&gt;fpm_cfg['custom_config']; ($fpm_children == 0) { $fpm_children = 1; } $fpm_config = ';php-fpm configuration "' . $this-&gt;domain['domain'] . '" created ' . date("y.m.d h:i:s") . "\n"; $fpm_config .= '[' . $this-&gt;domain['domain'] . ']' . "\n"; $fpm_config .= 'listen = ' . $this-&gt;getsocketfile() . "\n"; ($this-&gt;domain['loginname'] == 'froxlor.panel') { $fpm_config .= 'listen.owner = ' . $this-&gt;domain['guid'] . "\n"; $fpm_config .= 'listen.group = ' . $this-&gt;domain['guid'] . "\n"; } else { $fpm_config .= 'listen.owner = ' . $this-&gt;domain['loginname'] . "\n"; $fpm_config .= 'listen.group = ' . $this-&gt;domain['loginname'] . "\n"; } // see #1418 0660 $fpm_config .= 'listen.mode = 0660' . "\n"; ($this-&gt;domain['loginname'] == 'froxlor.panel') { $fpm_config .= 'user = ' . $this-&gt;domain['guid'] . "\n"; $fpm_config .= 'group = ' . $this-&gt;domain['guid'] . "\n"; } else { $fpm_config .= 'user = ' . $this-&gt;domain['loginname'] . "\n"; $fpm_config .= 'group = ' . $this-&gt;domain['loginname'] . "\n"; } $fpm_config .= 'pm = ' . $fpm_pm . "\n"; $fpm_config .= 'pm.max_children = ' . $fpm_children . "\n"; ($fpm_pm == 'dynamic') { // honor max_children ($fpm_children &lt; $fpm_min_spare_servers) { $fpm_min_spare_servers = $fpm_children; } ($fpm_children &lt; $fpm_max_spare_servers) { $fpm_max_spare_servers = $fpm_children; } // failsafe, refs #955 ($fpm_start_servers &lt; $fpm_min_spare_servers) { $fpm_start_servers = $fpm_min_spare_servers; } ($fpm_start_servers &gt; $fpm_max_spare_servers) { $fpm_start_servers = $fpm_max_spare_servers; } $fpm_config .= 'pm.start_servers = ' . $fpm_start_servers . "\n"; $fpm_config .= 'pm.min_spare_servers = ' . $fpm_min_spare_servers . "\n"; $fpm_config .= 'pm.max_spare_servers = ' . $fpm_max_spare_servers . "\n"; } elseif ($fpm_pm == 'ondemand') { $fpm_config .= 'pm.process_idle_timeout = ' . $fpm_process_idle_timeout . "\n"; } $fpm_config .= 'pm.max_requests = ' . $fpm_requests . "\n"; // possible slowlog configs ($phpconfig['fpm_slowlog'] == '1') { $fpm_config .= 'request_terminate_timeout = ' . $phpconfig['fpm_reqterm'] . "\n"; $fpm_config .= 'request_slowlog_timeout = ' . $phpconfig['fpm_reqslow'] . "\n"; $slowlog = filedir::makecorrectfile(settings::get('system.logfiles_directory') . '/' . $this-&gt;domain['loginname'] . '-php-slow.log'); $fpm_config .= 'slowlog = ' . $slowlog . "\n"; $fpm_config .= 'catch_workers_output = yes' . "\n"; } $fpm_config .= ';chroot = ' . filedir::makecorrectdir($this-&gt;domain['documentroot']) . "\n"; $fpm_config .= 'security.limit_extensions = ' . $fpm_limit_extensions . "\n"; $tmpdir = filedir::makecorrectdir(settings::get('phpfpm.tmpdir') . '/' . $this-&gt;domain['loginname'] . '/'); (!is_dir($tmpdir)) { $this-&gt;gettempdir(); } $env_path = settings::get('phpfpm.envpath'); (!empty($env_path)) { $fpm_config .= 'env[path] = ' . $env_path . "\n"; } $fpm_config .= 'env[tmp] = ' . $tmpdir . "\n"; $fpm_config .= 'env[tmpdir] = ' . $tmpdir . "\n"; $fpm_config .= 'env[temp] = ' . $tmpdir . "\n"; $openbasedir = ''; ($this-&gt;domain['loginname'] != 'froxlor.panel') { ($this-&gt;domain['openbasedir'] == '1') { $_phpappendopenbasedir = ''; $_custom_openbasedir = explode(':', settings::get('phpfpm.peardir')); foreach ($_custom_openbasedir $cobd) { $_phpappendopenbasedir .= domain::appendopenbasedirpath($cobd); } $_custom_openbasedir = explode(':', settings::get('system.phpappendopenbasedir')); foreach ($_custom_openbasedir $cobd) { $_phpappendopenbasedir .= domain::appendopenbasedirpath($cobd); } ($this-&gt;domain['openbasedir_path'] == '0' &amp;&amp; strstr($this-&gt;domain['documentroot'], ":") === false) { $openbasedir = domain::appendopenbasedirpath($this-&gt;domain['documentroot'], true); } else ($this-&gt;domain['openbasedir_path'] == '2' &amp;&amp; strpos(dirname($this-&gt;domain['documentroot']).'/', $this-&gt;domain['customerroot']) !== false) { $openbasedir = domain::appendopenbasedirpath(dirname($this-&gt;domain['documentroot']).'/', true); } else { $openbasedir = domain::appendopenbasedirpath($this-&gt;domain['customerroot'], true); } $openbasedir .= domain::appendopenbasedirpath($this-&gt;gettempdir()); $openbasedir .= $_phpappendopenbasedir; } } $fpm_config .= 'php_admin_value[upload_tmp_dir] = ' . filedir::makecorrectdir(settings::get('phpfpm.tmpdir') . '/' . $this-&gt;domain['loginname'] . '/') . "\n"; $admin = $this-&gt;getadmindata($this-&gt;domain['adminid']); $php_ini_variables = [ 'safe_mode' =&gt; 'off', // keep compatibility, case 'pear_dir' =&gt; settings::get('phpfpm.peardir'), 'tmp_dir' =&gt; $this-&gt;gettempdir(), 'customer_email' =&gt; $this-&gt;domain['email'], 'admin_email' =&gt; $admin['email'], 'domain' =&gt; $this-&gt;domain['domain'], 'customer' =&gt; $this-&gt;domain['loginname'], 'admin' =&gt; $admin['loginname'], 'open_basedir' =&gt; $openbasedir, 'open_basedir_c' =&gt; '', 'open_basedir_global' =&gt; settings::get('system.phpappendopenbasedir'), 'document_root' =&gt; filedir::makecorrectdir($this-&gt;domain['documentroot']), 'customer_homedir' =&gt; filedir::makecorrectdir($this-&gt;domain['customerroot']) ]; $phpini = phphelper::replacevariables($phpconfig['phpsettings'], $php_ini_variables); $phpini_array = explode("\n", $phpini); $fpm_config .= "\n\n"; foreach ($phpini_array $inisection) { $is = explode("=", trim($inisection)); (count($is) !== 2 || empty($is[0])) { continue; } foreach ($this-&gt;ini $sec =&gt; $possibles) { (in_array(trim($is[0]), $possibles)) { // check explicitly open_basedir (trim($is[0]) == 'open_basedir' &amp;&amp; $openbasedir == '') { continue; } $fpm_config .= $sec . '[' . trim($is[0]) . '] = ' . trim($is[1] ?? '') . "\n"; } } } // check 'sendmail_path' set custom-php.ini // use fallback-default usual (strpos($fpm_config, 'php_admin_value[sendmail_path]') === false) { $fpm_config .= 'php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f ' . $this-&gt;domain['email'] . "\n"; } // check session.save_path, whether specified user, not, set default (strpos($fpm_config, 'php_value[session.save_path]') === false &amp;&amp; strpos($fpm_config, 'php_admin_value[session.save_path]') === false) { $fpm_config .= 'php_admin_value[session.save_path] = ' . $this-&gt;gettempdir() . "\n"; } // append custom phpfpm configuration (!empty($fpm_custom_config)) { $fpm_config .= "\n; custom configuration\n"; $fpm_config .= phphelper::replacevariables($fpm_custom_config, $php_ini_variables); } fwrite($fh, $fpm_config, strlen($fpm_config)); fclose($fh); } } /** * fpm-config file * * @param boolean $createifnotexists * create directory exist * * @return string full path file */ public function getconfigfile($createifnotexists = true) { $configdir = $this-&gt;fpm_cfg['config_dir']; $config = filedir::makecorrectfile($configdir . '/' . $this-&gt;domain['domain'] . '.conf'); (!is_dir($configdir) &amp;&amp; $createifnotexists) { filedir::safe_exec('mkdir -p ' . escapeshellarg($configdir)); } return $config; } /** * return path fpm-socket file * * @param boolean $createifnotexists * create directory exist * * @return string full path socket */ public function getsocketfile($createifnotexists = true) { $socketdir = filedir::makecorrectdir(settings::get('phpfpm.fastcgi_ipcdir')); // add fpm-config-id filename, unique fpm-daemon interfere running configs reuilding $socket_filename = $socketdir . '/' . $this-&gt;domain['fpm_config_id'] . '-' . $this-&gt;domain['loginname'] . '-' . $this-&gt;domain['domain'] . '-php-fpm.socket'; (strlen($socket_filename) &gt; 100) { // respect unix socket-length limitation $socket_filename = $socketdir . '/' . $this-&gt;domain['fpm_config_id'] . '-' . $this-&gt;domain['loginname'] . '-' . $this-&gt;domain['id'] . '-php-fpm.socket'; (strlen($socket_filename) &gt; 100) { // even long loginname seems $socket_filename = $socketdir . '/' . $this-&gt;domain['fpm_config_id'] . '-' . $this-&gt;domain['guid'] . '-' . $this-&gt;domain['id'] . '-php-fpm.socket'; } } $socket = strtolower(filedir::makecorrectfile($socket_filename)); (!is_dir($socketdir) &amp;&amp; $createifnotexists) { filedir::safe_exec('mkdir -p ' . escapeshellarg($socketdir)); filedir::safe_exec('chown -r ' . settings::get('system.httpuser') . ':' . settings::get('system.httpgroup') . ' ' . escapeshellarg($socketdir)); } return $socket; } /** * fpm-temp directory * * @param boolean $createifnotexists * create directory exist * * @return string directory */ public function gettempdir($createifnotexists = true) { $tmpdir = filedir::makecorrectdir(settings::get('phpfpm.tmpdir') . '/' . $this-&gt;domain['loginname'] . '/'); (!is_dir($tmpdir) &amp;&amp; $createifnotexists) { filedir::safe_exec('mkdir -p ' . escapeshellarg($tmpdir)); filedir::safe_exec('chown -r ' . $this-&gt;domain['guid'] . ':' . $this-&gt;domain['guid'] . ' ' . escapeshellarg($tmpdir)); filedir::safe_exec('chmod 0750 ' . escapeshellarg($tmpdir)); } return $tmpdir; } /** * return admin-data specific admin * * @param int $adminid * id admin-user * * @return array */ private function getadmindata($adminid) { $adminid = intval($adminid); (!isset($this-&gt;admin_cache[$adminid])) { $stmt = database::prepare(" select `email`, `loginname` `" . table_panel_admins . "` `adminid` = :id"); $this-&gt;admin_cache[$adminid] = database::pexecute_first($stmt, [ 'id' =&gt; $adminid ]); } return $this-&gt;admin_cache[$adminid]; } /** * done via createconfig php-fpm defines * ini-values/flags pool-config * * @param string $phpconfig */ public function createinifile($phpconfig) { return; } /** * fastcgi-fakedirectory directory * * @param boolean $createifnotexists * create directory exist * * @return string directory */ public function getaliasconfigdir($createifnotexists = true) { // ensure default... (settings::get('phpfpm.aliasconfigdir') == null) { settings::set('phpfpm.aliasconfigdir', '/var/www/php-fpm'); } $configdir = filedir::makecorrectdir(settings::get('phpfpm.aliasconfigdir') . '/' . $this-&gt;domain['loginname'] . '/' . $this-&gt;domain['domain'] . '/'); (!is_dir($configdir) &amp;&amp; $createifnotexists) { filedir::safe_exec('mkdir -p ' . escapeshellarg($configdir)); filedir::safe_exec('chown ' . $this-&gt;domain['guid'] . ':' . $this-&gt;domain['guid'] . ' ' . escapeshellarg($configdir)); } return $configdir; } }</file><file name="lib/Froxlor/Cron/Http/Php/index.html" /><file name="lib/Froxlor/Cron/Http/Php/PhpInterface.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\http\php; use froxlor\database\database; use froxlor\settings; class phpinterface { /** * domain-data array * * @var array */ private $domain = []; /** * interface object * * @var object */ private $interface = null; /** * php-config data array * * @var array */ private $php_configs_cache = []; /** * main constructor */ public function __construct($domain) { $this-&gt;domain = $domain; $this-&gt;setinterface(); } /** * set interface-object type * php-interface: fcgid php-fpm * sets private $_interface variable */ private function setinterface() { // php-fpm ((int)settings::get('phpfpm.enabled') == 1) { $this-&gt;interface = new fpm($this-&gt;domain); } elseif ((int)settings::get('system.mod_fcgid') == 1) { $this-&gt;interface = new fcgid($this-&gt;domain); } } /** * returns interface-object * control */ public function getinterface() { return $this-&gt;interface; } /** * return php-configuration database * * @param int $php_config_id * id php-configuration * * @return array */ public function getphpconfig(int $php_config_id) { // domain config, use default one. ($php_config_id == 0) { $php_config_id = 1; } (!isset($this-&gt;php_configs_cache[$php_config_id])) { $stmt = database::prepare(" select * `" . table_panel_phpconfigs . "` `id` = :id "); $this-&gt;php_configs_cache[$php_config_id] = database::pexecute_first($stmt, [ 'id' =&gt; $php_config_id ]); ((int)settings::get('phpfpm.enabled') == 1) { $stmt = database::prepare(" select * `" . table_panel_fpmdaemons . "` `id` = :id "); $this-&gt;php_configs_cache[$php_config_id]['fpm_settings'] = database::pexecute_first($stmt, [ 'id' =&gt; $this-&gt;php_configs_cache[$php_config_id]['fpmsettingid'] ]); // override fpm daemon settings set php-config ($this-&gt;php_configs_cache[$php_config_id]['override_fpmconfig'] == 1) { $this-&gt;php_configs_cache[$php_config_id]['fpm_settings']['limit_extensions'] = $this-&gt;php_configs_cache[$php_config_id]['limit_extensions']; $this-&gt;php_configs_cache[$php_config_id]['fpm_settings']['idle_timeout'] = $this-&gt;php_configs_cache[$php_config_id]['idle_timeout']; } } } return $this-&gt;php_configs_cache[$php_config_id]; } }</file><file name="lib/Froxlor/Cron/Mail/Rspamd.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cron\mail; use exception; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; class rspamd { const default_mark_lvl = 7.0; const default_reject_lvl = 14.0; private string $frx_settings_file = ""; protected froxlorlogger $logger; public function __construct(froxlorlogger $logger) { $this-&gt;logger = $logger; } /** * @throws exception */ public function writeconfigs() { // tell world $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'task9 started - rebuilding antispam configuration'); // get email addresses $antispam_stmt = database::prepare(" select email, spam_tag_level, rewrite_subject, spam_kill_level, bypass_spam, policy_greylist, iscatchall `" . table_mail_virtual . "` order email "); database::pexecute($antispam_stmt); $this-&gt;frx_settings_file = "#\n# automatically generated file froxlor. edit manually overwritten!\n# generated: " . date('d.m.y h:i') . "\n#\n\n"; ($email = $antispam_stmt-&gt;fetch(\pdo::fetch_assoc)) { $this-&gt;generateemailaddrconfig($email); } $antispam_cfg_file = filedir::makecorrectfile(settings::get('antispam.config_file')); file_put_contents($antispam_cfg_file, $this-&gt;frx_settings_file); $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, $antispam_cfg_file . ' written'); $this-&gt;writedkimconfigs(); $this-&gt;reloaddaemon(); $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'task9 finished'); } /** * # local.d/dkim_signing.conf * try_fallback = true; * path = "/var/lib/rspamd/dkim/$domain.$selector.key"; * selector_map = "/etc/rspamd/dkim_selectors.map"; * * @return void * @throws exception */ public function writedkimconfigs() { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'writing dkim key-pairs'); $dkim_selector_map = ""; $result_domains_stmt = database::query(" select `id`, `domain`, `dkim`, `dkim_id`, `dkim_pubkey`, `dkim_privkey` `" . table_panel_domains . "` `dkim` = '1' order `id` asc "); ($domain = $result_domains_stmt-&gt;fetch(\pdo::fetch_assoc)) { ($domain['dkim_privkey'] == '' || $domain['dkim_pubkey'] == '') { $max_dkim_id_stmt = database::query("select max(`dkim_id`) `max_dkim_id` `" . table_panel_domains . "`"); $max_dkim_id = $max_dkim_id_stmt-&gt;fetch(\pdo::fetch_assoc); $domain['dkim_id'] = (int)$max_dkim_id['max_dkim_id'] + 1; $privkey_filename = filedir::makecorrectfile('/var/lib/rspamd/dkim/' . $domain['domain'] . '.dkim' . $domain['dkim_id'] . '.key'); $pubkey_filename = filedir::makecorrectfile('/var/lib/rspamd/dkim/' . $domain['domain'] . '.dkim' . $domain['dkim_id'] . '.txt'); $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'generating dkim keys "' . $domain['domain'] . '"'); $rsret = []; filedir::safe_exec( 'rspamadm dkim_keygen -d ' . escapeshellarg($domain['domain']) . ' -k ' . $privkey_filename . ' -s dkim' . $domain['dkim_id'] . ' -b ' . settings::get('antispam.dkim_keylength') . ' -o plain &gt; ' . escapeshellarg($pubkey_filename), $rsret, ['&gt;'] ); (!file_exists($privkey_filename) || !file_exists($pubkey_filename)) { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_err, 'dkim keypair domain "' . $domain['domain'] . '" generated successfully.'); continue; } $domain['dkim_privkey'] = file_get_contents($privkey_filename); filedir::safe_exec("chmod 0640 " . escapeshellarg($privkey_filename)); filedir::safe_exec("chown _rspamd:_rspamd " . escapeshellarg($privkey_filename)); $domain['dkim_pubkey'] = file_get_contents($pubkey_filename); filedir::safe_exec("chmod 0664 " . escapeshellarg($pubkey_filename)); filedir::safe_exec("chown _rspamd:_rspamd " . escapeshellarg($pubkey_filename)); $upd_stmt = database::prepare(" update `" . table_panel_domains . "` set `dkim_id` = :dkimid, `dkim_privkey` = :privkey, `dkim_pubkey` = :pubkey `id` = :id "); $upd_data = [ 'dkimid' =&gt; $domain['dkim_id'], 'privkey' =&gt; $domain['dkim_privkey'], 'pubkey' =&gt; $domain['dkim_pubkey'], 'id' =&gt; $domain['id'] ]; database::pexecute($upd_stmt, $upd_data); } else { $privkey_filename = filedir::makecorrectfile('/var/lib/rspamd/dkim/' . $domain['domain'] . '.dkim' . $domain['dkim_id'] . '.key'); $pubkey_filename = filedir::makecorrectfile('/var/lib/rspamd/dkim/' . $domain['domain'] . '.dkim' . $domain['dkim_id'] . '.txt'); } (!file_exists($privkey_filename) &amp;&amp; $domain['dkim_privkey'] != '') { file_put_contents($privkey_filename, $domain['dkim_privkey']); filedir::safe_exec("chmod 0640 " . escapeshellarg($privkey_filename)); filedir::safe_exec("chown _rspamd:_rspamd " . escapeshellarg($privkey_filename)); } (!file_exists($pubkey_filename) &amp;&amp; $domain['dkim_pubkey'] != '') { file_put_contents($pubkey_filename, $domain['dkim_pubkey']); filedir::safe_exec("chmod 0644 " . escapeshellarg($pubkey_filename)); filedir::safe_exec("chown _rspamd:_rspamd " . escapeshellarg($pubkey_filename)); } $dkim_selector_map .= $domain['domain'] . " dkim" . $domain['dkim_id'] . "\n"; } $dkim_selector_file = filedir::makecorrectfile('/etc/rspamd/dkim_selectors.map'); file_put_contents($dkim_selector_file, $dkim_selector_map); } private function generateemailaddrconfig(array $email): void { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_debug, 'generating antispam config ' . $email['email']); $email['spam_tag_level'] = floatval($email['spam_tag_level']); $email['spam_kill_level'] = $email['spam_kill_level'] == -1 ? "null" : floatval($email['spam_kill_level']); $email_id = md5($email['email']); $this-&gt;frx_settings_file .= '# email: ' . $email['email'] . "\n"; foreach (['rcpt', 'from'] $type) { $this-&gt;frx_settings_file .= 'frx_' . $email_id . '_' . $type . ' {' . "\n"; $this-&gt;frx_settings_file .= ' id = "frx_' . $email_id . '_' . $type . '";' . "\n"; ($email['iscatchall']) { $this-&gt;frx_settings_file .= ' priority = low;' . "\n"; $this-&gt;frx_settings_file .= ' ' . $type . ' = "' . substr($email['email'], strpos($email['email'], '@')) . '";' . "\n"; } else { $this-&gt;frx_settings_file .= ' priority = medium;' . "\n"; $this-&gt;frx_settings_file .= ' ' . $type . ' = "' . $email['email'] . '";' . "\n"; } ((int)$email['bypass_spam'] == 1) { $this-&gt;frx_settings_file .= ' want_spam = yes;' . "\n"; } else { $this-&gt;frx_settings_file .= ' apply {' . "\n"; $this-&gt;frx_settings_file .= ' actions {' . "\n"; $this-&gt;frx_settings_file .= ' "add header" = ' . $email['spam_tag_level'] . ';' . "\n"; ((int)$email['rewrite_subject'] == 1) { $this-&gt;frx_settings_file .= ' rewrite_subject = ' . ($email['spam_tag_level'] + 0.01) . ';' . "\n"; } $this-&gt;frx_settings_file .= ' reject = ' . $email['spam_kill_level'] . ';' . "\n"; ($type == 'rcpt' &amp;&amp; (int)$email['policy_greylist'] == 0) { $this-&gt;frx_settings_file .= ' greylist = null;' . "\n"; } $this-&gt;frx_settings_file .= ' }' . "\n"; $this-&gt;frx_settings_file .= ' }' . "\n"; ($type == 'rcpt' &amp;&amp; (int)$email['policy_greylist'] == 0) { $this-&gt;frx_settings_file .= ' symbols [ "dont_greylist" ]' . "\n"; } } $this-&gt;frx_settings_file .= '}' . "\n"; } $this-&gt;frx_settings_file .= "\n"; } public function reloaddaemon() { // reload dns daemon $cmd = settings::get('antispam.reload_command'); $cmdstatus = 1; filedir::safe_exec(escapeshellcmd($cmd), $cmdstatus); ($cmdstatus === 0) { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_info, 'antispam daemon reloaded'); } else { $this-&gt;logger-&gt;logaction(froxlorlogger::cron_action, log_err, 'error running `' . $cmd . '`: exit code (' . $cmdstatus . ') - please check system logs'); } } }</file><file name="lib/Froxlor/Install/Install.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\install; use exception; use froxlor\config\configparser; use froxlor\froxlor; use froxlor\install\install\core; use froxlor\system\iptools; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\validate\validate; use pdo; class install { public $currentstep; public $extendedview; public $maxsteps; public $phpversion; public $formfield; public array $suggestions = []; public array $criticals = []; public array $loadedextensions; public array $supportedos = []; public array $webserverbackend = [ 'php-fpm' =&gt; 'php-fpm', 'fcgid' =&gt; 'fcgid (apache2 only)', 'mod_php' =&gt; 'mod_php (not recommended)', ]; public function __construct(array $clidata = []) { // set actual php version extensions $this-&gt;phpversion = phpversion(); $this-&gt;loadedextensions = get_loaded_extensions(); // get supported os // show list available distro's $distros = glob(dirname(__dir__, 3) . '/lib/configfiles/*.xml'); $distributions_select[''] = '-'; (in_array('xml', $this-&gt;loadedextensions)) { // read distros foreach ($distros $distribution) { // get configparser object $dist = new configparser($distribution); // store tmp array $this-&gt;supportedos[str_replace(".xml", "", strtolower(basename($distribution)))] = $dist-&gt;getcompletedistroname(); } // sort distribution name asort($this-&gt;supportedos); } // guess distribution webserver preselect formfield $webserverbackend = $this-&gt;webserverbackend; $supportedos = $this-&gt;supportedos; $guesseddistribution = $this-&gt;guessdistribution(); $guessedwebserver = $this-&gt;guesswebserver(); // set formfield, get fields steps etc. $this-&gt;formfield = require dirname(__dir__, 3) . '/lib/formfields/install/formfield.install.php'; // set actual step $this-&gt;currentstep = $clidata['step'] ?? request::any('step', 0); $this-&gt;extendedview = $clidata['extended'] ?? request::any('extended', 0); $this-&gt;maxsteps = count($this-&gt;formfield['install']['sections']); (empty($clidata)) { // set global variables ui::twig()-&gt;addglobal('install_mode', true); ui::twig()-&gt;addglobal('basehref', '../'); // unset session user goes back step 0 (isset($_session['installation']) &amp;&amp; $this-&gt;currentstep == 0) { unset($_session['installation']); } // check url manipulation wrong step ((isset($_session['installation']['stepcompleted']) &amp;&amp; $this-&gt;currentstep &gt; $_session['installation']['stepcompleted']) || (!isset($_session['installation']['stepcompleted']) &amp;&amp; $this-&gt;currentstep &gt; 0) ) { $this-&gt;currentstep = isset($_session['installation']['stepcompleted']) ? $_session['installation']['stepcompleted'] + 1 : 1; } } } /** * @return void * @throws exception */ public function handle(): void { // handle form data (!is_null(request::any('submit')) &amp;&amp; $this-&gt;currentstep) { try { $this-&gt;handleformdata($this-&gt;formfield['install']); } catch (exception $e) { $error = $e-&gt;getmessage(); } } // load template ui::twigbuffer('/install/index.html.twig', [ 'setup' =&gt; [ 'step' =&gt; $this-&gt;currentstep, 'max_steps' =&gt; $this-&gt;maxsteps, ], 'preflight' =&gt; $this-&gt;checkrequirements(), 'page' =&gt; [ 'title' =&gt; 'database', 'description' =&gt; 'test', ], 'section' =&gt; $this-&gt;formfield['install']['sections']['step' . $this-&gt;currentstep] ?? [], 'error' =&gt; $error ?? null, 'extended' =&gt; $this-&gt;extendedview, 'csrf_token' =&gt; froxlor::gensessionid(20), ]); // output view ui::twigoutputbuffer(); } /** * @throws exception */ private function handleformdata(array $formfield): void { // handle current step ($this-&gt;currentstep &lt;= $this-&gt;maxsteps) { // validate user data $validateddata = $this-&gt;validaterequest($formfield['sections']['step' . $this-&gt;currentstep]['fields']); ($this-&gt;currentstep == 1) { // check database connection $this-&gt;checkdatabase($validateddata); } elseif ($this-&gt;currentstep == 2) { // check validity admin user data $this-&gt;checkadminuser($validateddata); } elseif ($this-&gt;currentstep == 3) { // check validity system data $this-&gt;checksystem($validateddata); } $validateddata['stepcompleted'] = ($this-&gt;currentstep &lt; $this-&gt;maxsteps) ? $this-&gt;currentstep : ($this-&gt;maxsteps - 1); // store validated data later use $_session['installation'] = array_merge($_session['installation'] ?? [], $validateddata); } // also handle completion installation step last step ($this-&gt;currentstep == ($this-&gt;maxsteps - 1)) { $core = new core($_session['installation']); $core-&gt;doinstall(); } // redirect user home installation done ($this-&gt;currentstep == $this-&gt;maxsteps) { // check setting "panel.is_configured" whether user // run config-services script (or checked manual mode) ($this-&gt;checkinstallstatefinished()) { header('location: ../'); return; } throw new exception(lng('install.errors.notyetconfigured')); } // redirect next step header('location: ?step=' . ($this-&gt;currentstep + 1)); } private function checkinstallstatefinished(): bool { $core = new core($_session['installation']); (isset($_session['installation']['manual_config']) &amp;&amp; (int)$_session['installation']['manual_config'] == 1) { $core-&gt;createuserdataconf(); return true; } $pdo = $core-&gt;getunprivilegedpdo(); $stmt = $pdo-&gt;prepare("select `value` `panel_settings` `settinggroup` = 'panel' `varname` = 'is_configured'"); $stmt-&gt;execute(); $result = $stmt-&gt;fetch(pdo::fetch_assoc); ($result &amp;&amp; (int)$result['value'] == 1) { $core-&gt;createuserdataconf(); return true; } return false; } /** * @return array */ public function checkrequirements(): array { // check whether read userdata file (!@touch(dirname(__dir__, 2) . '/.~writecheck')) { // get possible owner $posixusername = posix_getpwuid(posix_getuid())['name']; $posixgroup = posix_getgrgid(posix_getgid())['name']; $this-&gt;criticals['wrong_ownership'] = ['user' =&gt; $posixusername, 'group' =&gt; $posixgroup]; } else { @unlink(dirname(__dir__, 2) . '/.~writecheck'); } // check required extensions foreach (requirements::required_extensions $requiredextension) { (in_array($requiredextension, $this-&gt;loadedextensions)) { continue; } $this-&gt;criticals['missing_extensions'][] = $requiredextension; } // check suggested extensions foreach (requirements::suggested_extensions $suggestedextension) { (in_array($suggestedextension, $this-&gt;loadedextensions)) { continue; } $this-&gt;suggestions['missing_extensions'][] = $suggestedextension; } return [ 'text' =&gt; $this-&gt;getinformationtext(), 'suggestions' =&gt; $this-&gt;suggestions, 'criticals' =&gt; $this-&gt;criticals, ]; } /** * @return string */ private function getinformationtext(): string { (version_compare(requirements::required_version, php_version, "&lt;")) { $text = lng('install.phpinfosuccess', [$this-&gt;phpversion]); } else { $text = lng('install.phpinfowarn', [requirements::required_version]); $this-&gt;criticals[] = lng('install.phpinfoupdate', [$this-&gt;phpversion, requirements::required_version]); } return $text; } /** * @throws exception */ private function validaterequest(array $fields): array { $attributes = []; foreach ($fields $name =&gt; $field) { $attributes[$name] = $this-&gt;validateattribute(request::any($name), $field); (isset($field['next_to'])) { $attributes = array_merge($attributes, $this-&gt;validaterequest($field['next_to'])); } } return $attributes; } /** * @return mixed * @throws exception */ private function validateattribute($attribute, array $field) { // todo: validations (isset($field['mandatory']) &amp;&amp; $field['mandatory'] &amp;&amp; empty($attribute)) { throw new exception(lng('install.errors.mandatory_field_not_set', [$field['label']])); } return $attribute; } /** * @throws exception */ public function checksystem(array $validateddata): void { $serveripv4 = $validateddata['serveripv4'] ?? ''; $serveripv6 = $validateddata['serveripv6'] ?? ''; $servername = $validateddata['servername'] ?? ''; $httpuser = $validateddata['httpuser'] ?? 'www-data'; $httpgroup = $validateddata['httpgroup'] ?? 'www-data'; (empty($serveripv4) &amp;&amp; empty($serveripv6)) { throw new exception(lng('install.errors.nov4andnov6ip')); } elseif (!empty($serveripv4) &amp;&amp; (!validate::validate_ip2($serveripv4, true, '', false, true) || iptools::is_ipv6($serveripv4))) { throw new exception(lng('error.invalidip', [$serveripv4])); } elseif (!empty($serveripv6) &amp;&amp; (!validate::validate_ip2($serveripv6, true, '', false, true) || !iptools::is_ipv6($serveripv6))) { throw new exception(lng('error.invalidip', [$serveripv6])); } elseif (!validate::validatedomain($servername)) { throw new exception(lng('install.errors.servernameneedstobevalid')); } elseif (posix_getpwnam($httpuser) === false) { throw new exception(lng('install.errors.websrvuserdoesnotexist')); } elseif (posix_getgrnam($httpgroup) === false) { throw new exception(lng('install.errors.websrvgrpdoesnotexist')); } } /** * @throws exception */ public function checkadminuser(array $validateddata): void { $name = $validateddata['admin_name'] ?? 'administrator'; $loginname = $validateddata['admin_user'] ?? ''; $email = $validateddata['admin_email'] ?? ''; $password = $validateddata['admin_pass'] ?? ''; $password_confirm = $validateddata['admin_pass_confirm'] ?? ''; $useadminmailassender = $validateddata['use_admin_email_as_sender'] ?? '1'; $senderemail = $validateddata['sender_email'] ?? ''; (!preg_match('/^[^\r\n\t\f\0]*$/d', $name)) { throw new exception(lng('error.stringformaterror', ['admin_name'])); } elseif (empty(trim($loginname)) || !preg_match('/^[a-z][a-z0-9]+$/di', $loginname)) { throw new exception(lng('error.loginnameiswrong', [$loginname])); } elseif (empty(trim($email)) || !validate::validateemail($email)) { throw new exception(lng('error.emailiswrong', [$email])); } elseif ((int)$useadminmailassender == 0 &amp;&amp; !empty(trim($senderemail)) &amp;&amp; !validate::validateemail($senderemail)) { throw new exception(lng('error.emailiswrong', [$senderemail])); } elseif (empty($password) || $password != $password_confirm) { throw new exception(lng('error.newpasswordconfirmerror')); } elseif ($password == $loginname) { throw new exception(lng('error.passwordshouldnotbeusername')); } } /** * @throws exception */ public function checkdatabase(array $validateddata): void { $dsn = sprintf('mysql:host=%s;charset=utf8', $validateddata['mysql_host']); $pdo = new \pdo($dsn, $validateddata['mysql_root_user'], $validateddata['mysql_root_pass']); // check database already exist $stmt = $pdo-&gt;prepare('show databases like ?'); $stmt-&gt;execute([ $validateddata['mysql_database'] ]); $hasdatabase = $stmt-&gt;fetch(); ($hasdatabase &amp;&amp; !$validateddata['mysql_force_create']) { throw new exception(lng('install.errors.databaseexists')); } // check create new database $testdatabase = uniqid('froxlor_tmp_'); ($pdo-&gt;exec('create database exists ' . $testdatabase . ';') === false) { throw new exception(lng('install.errors.unabletocreatedb')); } ($pdo-&gt;exec('drop database exists ' . $testdatabase . ';') === false) { throw new exception(lng('install.errors.unabletodropdb')); } // check user already exist $stmt = $pdo-&gt;prepare("select `user` `mysql`.`user` `user` = ?"); $stmt-&gt;execute([$validateddata['mysql_unprivileged_user']]); ($stmt-&gt;rowcount() &amp;&amp; !$validateddata['mysql_force_create']) { throw new exception(lng('install.errors.mysqlusernameexists')); } // check create new user $testuser = uniqid('froxlor_tmp_'); $stmt = $pdo-&gt;prepare('create user ?@? identified ?'); ($stmt-&gt;execute([$testuser, $validateddata['mysql_host'], uniqid()]) === false) { throw new exception(lng('install.errors.unabletocreateuser')); } $stmt = $pdo-&gt;prepare('drop user ?@?'); ($stmt-&gt;execute([$testuser, $validateddata['mysql_host']]) === false) { throw new exception(lng('install.errors.unabletodropuser')); } ($pdo-&gt;prepare('flush privileges')-&gt;execute() === false) { throw new exception(lng('install.errors.unabletoflushprivs')); } } private function guesswebserver(): ?string { (strtoupper(@php_sapi_name()) == "apache2handler" || stristr($_server['server_software'], "apache")) { return 'apache24'; } elseif (substr(strtoupper(@php_sapi_name()), 0, 8) == "lighttpd" || stristr($_server['server_software'], "lighttpd")) { return 'lighttpd'; } elseif (substr(strtoupper(@php_sapi_name()), 0, 8) == "nginx" || stristr($_server['server_software'], "nginx")) { return 'nginx'; } return null; } private function guessdistribution(): ?string { // set default os. $default = 'bullseye'; // read os-release (@file_exists('/etc/os-release') &amp;&amp; is_readable('/etc/os-release')) { (function_exists('parse_ini_file')) { $os_dist = parse_ini_file('/etc/os-release', false); } else { $osrf = explode("\n", file_get_contents('/etc/os-release')); foreach ($osrf $line) { $osrfline = explode("=", $line); ($osrfline[0] == 'version_codename') { $os_dist['version_codename'] = $osrfline[1]; } else ($osrfline[0] == 'id') { $os_dist['id'] = $osrfline[1]; } } } return strtolower($os_dist['version_codename'] ?? ($os_dist['id'] ?? $default)); } return $default; } }</file><file name="lib/Froxlor/Install/Requirements.php">&lt;?php namespace froxlor\install; class requirements { const required_version = '7.4.0'; const required_extensions = ['session', 'ctype', 'xml', 'filter', 'posix', 'mbstring', 'pdo_mysql', 'curl', 'gmp', 'json', 'gd']; const suggested_extensions = ['bcmath', 'zip', 'gnupg']; }</file><file name="lib/Froxlor/Install/Update.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\install; use froxlor\filedir; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\settings; class update { private static $update_tasks = []; private static $task_counter = 0; /** * function showupdatestep * * stores logs current update progress * * @param string $task * @param bool $needs_status (if false, linebreak added) * * @return void */ public static function showupdatestep(string $task, bool $needs_status = true) { set_time_limit(30); // output self::$update_tasks[self::$task_counter] = ['title' =&gt; $task, 'result' =&gt; 0]; (!$needs_status) { self::$task_counter++; } froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::adm_action, \log_warning, $task); } /** * function laststepstatus * * outputs status last update-step * * @param int $status (0 = success, 1 = warning, 2 = failure) * @param string $message * @param string $additional_info * * @return void */ public static function laststepstatus(int $status = -1, string $message = 'ok', string $additional_info = '') { self::$update_tasks[self::$task_counter]['result_txt'] = $message; self::$update_tasks[self::$task_counter]['result_desc'] = $additional_info; switch ($status) { case 0: break; case 1: self::$update_tasks[self::$task_counter]['result'] = 2; break; case 2: self::$update_tasks[self::$task_counter]['result'] = 1; break; default: self::$update_tasks[self::$task_counter]['result'] = -1; break; } self::$task_counter++; ($status == -1 || $status == 2) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::adm_action, \log_warning, 'attention - last update task failed!!!'); } elseif ($status == 0 || $status == 1) { froxlorlogger::getinstanceof()-&gt;logaction(froxlorlogger::adm_action, \log_warning, 'success'); } } public static function versioninupdate($current_version, $version_to_check) { (!froxlor::isfroxlor()) { return true; } return froxlor::versioncompare2($current_version, $version_to_check) == -1; } public static function storeupdatecheckdata(array $response) { $data = [ 'ts' =&gt; time(), 'channel' =&gt; settings::get('system.update_channel'), 'data' =&gt; $response ]; settings::set('system.updatecheck_data', json_encode($data)); } public static function getupdatecheckdata() { $uc_data = settings::get('system.updatecheck_data'); (!empty($uc_data)) { $data = json_decode($uc_data, true); return $data; } return null; } public static function getupdatetasks(): array { return self::$update_tasks; } public static function gettaskcounter(): int { return self::$task_counter; } public static function cleanoldfiles(array $to_clean) { self::showupdatestep("cleaning old files"); $disabled = explode(',', ini_get('disable_functions')); $exec_allowed = !in_array('exec', $disabled); $del_list = ""; foreach ($to_clean $filedir) { $complete_filedir = froxlor::getinstalldir() . $filedir; (file_exists($complete_filedir)) { ($exec_allowed) { filedir::safe_exec("rm -rf " . escapeshellarg($complete_filedir)); } else { $del_list .= "rm -rf " . escapeshellarg($complete_filedir) . php_eol; } } } ($exec_allowed) { self::laststepstatus(0); } else { (empty($del_list)) { // none files existed self::laststepstatus(0); } else { self::laststepstatus( 1, 'manual commands needed', 'please run following commands manually:&lt;br&gt;&lt;pre&gt;' . $del_list . '&lt;/pre&gt;' ); } } } }</file><file name="lib/Froxlor/Install/AutoUpdate.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\install; use exception; use ziparchive; use froxlor\froxlor; use froxlor\settings; use froxlor\http\httpclient; class autoupdate { // define update-uri const update_uri = "https://version.froxlor.org/froxlor/api/v2/"; const release_uri = "https://autoupdate.froxlor.org/froxlor-{version}.zip"; const checksum_uri = "https://autoupdate.froxlor.org/froxlor-{version}.zip.sha256"; const err_nozipext = 2; const err_couldnotstore = 4; const err_zipnotfound = 7; const err_couldnotextract = 8; const err_chksum_mismatch = 9; const err_minphp = 10; private static $latestversion = ""; private static $lasterror = ""; /** * returns status whether newer version * * 0 = new version available * 1 = new version available * -1 = remote error message * &gt;1 = local error message * * @return int */ public static function checkversion(): int { $result = self::checkprerequisites(); ($result == 0) { try { $channel = ''; (settings::get('system.update_channel') == 'testing') { $channel = '/testing'; } elseif (settings::get('system.update_channel') == 'nightly') { (empty(froxlor::branding) || substr(froxlor::branding, 0, 1) == '-') { $channel = '/nightly.0000000'; } else { $channel = '/' . substr(froxlor::branding, 1); } } $latestversion = httpclient::urlget(self::update_uri . froxlor::version . $channel, true, 3); } catch (exception $e) { self::$lasterror = "version-check currently unavailable, please try later"; return -1; } self::$latestversion = json_decode($latestversion, true); (self::$latestversion) { (!empty(self::$latestversion['error']) &amp;&amp; self::$latestversion['error']) { $result = -1; self::$lasterror = self::$latestversion['message']; } elseif (isset(self::$latestversion['has_latest']) &amp;&amp; self::$latestversion['has_latest'] == false) { $result = 1; } } } return $result; } public static function downloadzip(string $newversion) { // define files get $toload = str_replace('{version}', $newversion, self::release_uri); $tocheck = str_replace('{version}', $newversion, self::checksum_uri); // check local destination folder (!is_dir(froxlor::getinstalldir() . '/updates/')) { mkdir(froxlor::getinstalldir() . '/updates/'); } // name archive $localarchive = froxlor::getinstalldir() . '/updates/' . basename($toload); // remove old archive (file_exists($localarchive)) { @unlink($localarchive); } // get archive data try { httpclient::fileget($toload, $localarchive); } catch (exception $e) { return self::err_couldnotstore; } // validate integrity downloaded file $_shouldsum = httpclient::urlget($tocheck); (!empty($_shouldsum)) { $_t = explode(" ", $_shouldsum); $shouldsum = $_t[0]; } else { $shouldsum = null; } $filesum = hash_file('sha256', $localarchive); ($filesum != $shouldsum) { return self::err_chksum_mismatch; } return basename($localarchive); } public static function extractzip(string $localarchive): int { (!file_exists($localarchive)) { return self::err_zipnotfound; } // decompress zip $zip = new ziparchive(); $res = $zip-&gt;open($localarchive); ($res === true) { $zip-&gt;extractto(froxlor::getinstalldir()); $zip-&gt;close(); // success - remove unused archive @unlink($localarchive); // reset cached version check settings::set('system.updatecheck_data', ''); // wait bit redirect sure sleep(3); return 0; } return self::err_couldnotextract; } private static function checkprerequisites(): int { (!extension_loaded('zip')) { return self::err_nozipext; } (version_compare("7.4.0", php_version, "&gt;=")) { return self::err_minphp; } return 0; } public static function getlasterror(): string { return self::$lasterror ?? ""; } public static function getfromresult(string $index) { return self::$latestversion[$index] ?? ""; } }</file><file name="lib/Froxlor/Install/Preconfig.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\install; use froxlor\froxlor; use froxlor\settings; class preconfig { private $preconfig_data = []; /** * returns whether preconfig items update * * @return bool */ public function haspreconfig(): bool { return count($this-&gt;preconfig_data) &gt; 0; } /** * return collected preconfig data * * @return array */ public function getdata(): array { return $this-&gt;preconfig_data; } /** * adds preconfig result-array preconfig-data * * @param array $array * * @return void */ public function addtopreconfig(array $array) { (isset($array['title']) &amp;&amp; isset($array['fields']) &amp;&amp; count($array['fields']) &gt; 0) { $this-&gt;preconfig_data[] = $array; } } /** * read preconfig files build data-array admin_updates */ public function __construct() { $preconfigs = glob(froxlor::getinstalldir() . '/install/updates/preconfig/*.php'); (!empty($preconfigs)) { $current_version = settings::get('panel.version'); $current_db_version = settings::get('panel.db_version'); (empty($current_db_version)) { $current_db_version = "0"; } foreach (array_reverse($preconfigs) $preconfig_file) { $pconf = include $preconfig_file; $this-&gt;addtopreconfig($pconf); } } } /** * function getpreconfig * * outputs various form-field-arrays update process * continued (asks agreement whatever asked) * * @param bool $no_check * @return array */ public static function getpreconfig(bool $no_check = false): array { $preconfig = new self(); ($preconfig-&gt;haspreconfig()) { (!$no_check) { $agree = [ 'title' =&gt; 'check', 'fields' =&gt; [ 'update_changesagreed' =&gt; ['mandatory' =&gt; true, 'type' =&gt; 'checkrequired', 'value' =&gt; 1, 'label' =&gt; '&lt;strong&gt;i read update notifications aware changes made system.&lt;/strong&gt;'], 'update_preconfig' =&gt; ['type' =&gt; 'hidden', 'value' =&gt; 1] ] ]; $preconfig-&gt;addtopreconfig($agree); } return $preconfig-&gt;getdata(); } return []; } }</file><file name="lib/Froxlor/Install/Install/Core.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\install\install; use exception; use froxlor\config\configparser; use froxlor\filedir; use froxlor\froxlor; use froxlor\phphelper; use pdo; use pdoexception; use pdostatement; /** * installation froxlor core database set settings. */ class core { protected array $validateddata; public function __construct(array $validateddata) { $this-&gt;validateddata = $validateddata; } /** * missing fields data -&gt; perform actual install * * @return void * @throws exception */ public function doinstall(bool $create_ud_str = true) { $options = [ 'pdo::mysql_attr_init_command' =&gt; 'set names utf8' ]; (!empty($this-&gt;validateddata['mysql_ssl_ca_file'])) { $options[pdo::mysql_attr_ssl_ca] = $this-&gt;validateddata['mysql_ssl_ca_file']; $options[pdo::mysql_attr_ssl_verify_server_cert] = (bool)$this-&gt;validateddata['mysql_ssl_verify_server_certificate']; } $dsn = "mysql:host=" . $this-&gt;validateddata['mysql_host'] . ";"; try { $db_root = new pdo($dsn, $this-&gt;validateddata['mysql_root_user'], $this-&gt;validateddata['mysql_root_pass'], $options); } catch (pdoexception $e) { // login failed; try log without passwd try { $db_root = new pdo($dsn, $this-&gt;validateddata['mysql_root_user'], '', $options); // set given password $passwd_stmt = $db_root-&gt;prepare(" set password = password(:passwd) "); $passwd_stmt-&gt;execute([ 'passwd' =&gt; $this-&gt;validateddata['mysql_root_pass'] ]); } catch (pdoexception $e) { // login failed; without password throw new exception(lng('install.errors.privileged_sql_connection_failed'), 0, $e); } } $version_server = $db_root-&gt;getattribute(pdo::attr_server_version); $sql_mode = 'no_engine_substitution'; (version_compare($version_server, '8.0.11', '&lt;')) { $sql_mode .= ',no_auto_create_user'; } $db_root-&gt;exec('set sql_mode = "' . $sql_mode . '"'); // ok, here, database connection running // check existing pdo create backup $this-&gt;backupexistingdatabase($db_root); // create unprivileged user database $this-&gt;createdatabaseanduser($db_root); // importing data new database $this-&gt;importdatabasedata(); // create db object new database $options = [ 'pdo::mysql_attr_init_command' =&gt; 'set names utf8' ]; (!empty($this-&gt;validateddata['mysql_ssl_ca_file']) &amp;&amp; isset($this-&gt;validateddata['mysql_ssl_verify_server_certificate'])) { $options[pdo::mysql_attr_ssl_ca] = $this-&gt;validateddata['mysql_ssl_ca_file']; $options[pdo::mysql_attr_ssl_verify_server_cert] = (bool)$this-&gt;validateddata['mysql_ssl_verify_server_certificate']; } $pdo = $this-&gt;getunprivilegedpdo(); // change settings accordingly $this-&gt;dosettings($pdo); // create entries $this-&gt;dodataentries($pdo); // create json array config-services $this-&gt;createjsonarray($pdo); ($create_ud_str) { $this-&gt;createuserdataparamstr(); } } /** * @throws exception */ public function getunprivilegedpdo(): pdo { $options = [ 'pdo::mysql_attr_init_command' =&gt; 'set names utf8' ]; (!empty($this-&gt;validateddata['mysql_ssl_ca_file'])) { $options[pdo::mysql_attr_ssl_ca] = $this-&gt;validateddata['mysql_ssl_ca_file']; $options[pdo::mysql_attr_ssl_verify_server_cert] = (bool)$this-&gt;validateddata['mysql_ssl_verify_server_certificate']; } $dsn = "mysql:host=" . $this-&gt;validateddata['mysql_host'] . ";dbname=" . $this-&gt;validateddata['mysql_database'] . ";"; try { $pdo = new pdo($dsn, $this-&gt;validateddata['mysql_unprivileged_user'], $this-&gt;validateddata['mysql_unprivileged_pass'], $options); $version_server = $pdo-&gt;getattribute(pdo::attr_server_version); $sql_mode = 'no_engine_substitution'; (version_compare($version_server, '8.0.11', '&lt;')) { $sql_mode .= ',no_auto_create_user'; } $pdo-&gt;exec('set sql_mode = "' . $sql_mode . '"'); return $pdo; } catch (pdoexception $e) { throw new exception(lng('install.errors.unexpected_database_error', [$e-&gt;getmessage()]), 0, $e); } } /** * check old database exists back necessary * * @param object $db_root * @return void * @throws exception */ private function backupexistingdatabase(object &amp;$db_root) { // check existing former database $stmt = $db_root-&gt;prepare("select schema_name information_schema.schemata schema_name = :database"); $stmt-&gt;execute([ 'database' =&gt; $this-&gt;validateddata['mysql_database'] ]); $rows = $db_root-&gt;query("select found_rows()")-&gt;fetchcolumn(); // backup tables exist ($rows &gt; 0) { (!$this-&gt;validateddata['mysql_force_create']) { throw new exception(lng('install.errors.database_already_exiting')); } // create temporary backup-filename $filename = "/tmp/froxlor_backup_" . date('ymdhi') . ".sql"; // look mysqldump $section = 'mysqldump'; (file_exists("/usr/bin/mysqldump")) { $mysql_dump = '/usr/bin/mysqldump'; } elseif (file_exists("/usr/local/bin/mysqldump")) { $mysql_dump = '/usr/local/bin/mysqldump'; } elseif (file_exists("/usr/bin/mariadb-dump")) { $mysql_dump = '/usr/bin/mariadb-dump'; $section = 'mariadb-dump'; } // create temporary .cnf file $cnffilename = "/tmp/froxlor_dump.cnf"; $dumpcnf = "[".$section."]" . php_eol . "password=\"" . $this-&gt;validateddata['mysql_root_pass'] . "\"" . php_eol; file_put_contents($cnffilename, $dumpcnf); // make backup (isset($mysql_dump)) { $command = $mysql_dump . " --defaults-extra-file=" . $cnffilename . " " . escapeshellarg($this-&gt;validateddata['mysql_database']) . " -u " . escapeshellarg($this-&gt;validateddata['mysql_root_user']) . " --result-file=" . $filename; $output = []; exec($command, $output); @unlink($cnffilename); (stristr(implode(" ", $output), "error")) { throw new exception(lng('install.errors.mysqldump_backup_failed')); } elseif (!file_exists($filename)) { throw new exception(lng('install.errors.sql_backup_file_missing')); } } else { throw new exception(lng('install.errors.backup_binary_missing')); } } } /** * create database database-user * * @param object $db_root * @return void * @throws exception */ private function createdatabaseanduser(object &amp;$db_root) { $this-&gt;validateddata['mysql_access_host'] = $this-&gt;validateddata['mysql_host']; // first delete database // user given unpriv-user exit $del_stmt = $db_root-&gt;prepare("delete `mysql`.`user` `user` = :user `host` = :accesshost"); $del_stmt-&gt;execute([ 'user' =&gt; $this-&gt;validateddata['mysql_unprivileged_user'], 'accesshost' =&gt; $this-&gt;validateddata['mysql_access_host'] ]); $del_stmt = $db_root-&gt;prepare("delete `mysql`.`db` `user` = :user `host` = :accesshost"); $del_stmt-&gt;execute([ 'user' =&gt; $this-&gt;validateddata['mysql_unprivileged_user'], 'accesshost' =&gt; $this-&gt;validateddata['mysql_access_host'] ]); $del_stmt = $db_root-&gt;prepare("delete `mysql`.`tables_priv` `user` = :user `host` =:accesshost"); $del_stmt-&gt;execute([ 'user' =&gt; $this-&gt;validateddata['mysql_unprivileged_user'], 'accesshost' =&gt; $this-&gt;validateddata['mysql_access_host'] ]); $del_stmt = $db_root-&gt;prepare("delete `mysql`.`columns_priv` `user` = :user `host` = :accesshost"); $del_stmt-&gt;execute([ 'user' =&gt; $this-&gt;validateddata['mysql_unprivileged_user'], 'accesshost' =&gt; $this-&gt;validateddata['mysql_access_host'] ]); $del_stmt = $db_root-&gt;prepare("drop database exists `" . str_replace('`', '', $this-&gt;validateddata['mysql_database']) . "`;"); $del_stmt-&gt;execute(); $db_root-&gt;query("flush privileges;"); // create new user database froxlor unprivileged mysql access $ins_stmt = $db_root-&gt;prepare("create database `" . str_replace('`', '', $this-&gt;validateddata['mysql_database']) . "` character set=utf8 collate=utf8_general_ci"); $ins_stmt-&gt;execute(); $mysql_access_host_array = array_map('trim', explode(',', $this-&gt;validateddata['mysql_access_host'])); (in_array('127.0.0.1', $mysql_access_host_array) &amp;&amp; !in_array('localhost', $mysql_access_host_array)) { $mysql_access_host_array[] = 'localhost'; } (!in_array('127.0.0.1', $mysql_access_host_array) &amp;&amp; in_array('localhost', $mysql_access_host_array)) { $mysql_access_host_array[] = '127.0.0.1'; } (!empty($this-&gt;validateddata['serveripv4']) &amp;&amp; !in_array($this-&gt;validateddata['serveripv4'], $mysql_access_host_array)) { $mysql_access_host_array[] = $this-&gt;validateddata['serveripv4']; } (!empty($this-&gt;validateddata['serveripv6']) &amp;&amp; !in_array($this-&gt;validateddata['serveripv6'], $mysql_access_host_array)) { $mysql_access_host_array[] = $this-&gt;validateddata['serveripv6']; } $mysql_access_host_array = array_unique($mysql_access_host_array); foreach ($mysql_access_host_array $mysql_access_host) { $this-&gt;grantdbprivilegesto($db_root, $this-&gt;validateddata['mysql_database'], $this-&gt;validateddata['mysql_unprivileged_user'], $this-&gt;validateddata['mysql_unprivileged_pass'], $mysql_access_host); } $db_root-&gt;query("flush privileges;"); $this-&gt;validateddata['mysql_access_host'] = implode(',', $mysql_access_host_array); } /** * grant privileges given user. * * @param $db_root * @param $database * @param $username * @param $password * @param $access_host * @return void * @throws exception */ private function grantdbprivilegesto(&amp;$db_root, $database, $username, $password, $access_host) { ($this-&gt;validateddata['mysql_force_create']) { try { // try drop user, ignore exceptions mysql-access-hosts might // changed would try drop non-existing user $drop_stmt = $db_root-&gt;prepare("drop user :username@:host"); $drop_stmt-&gt;execute([ "username" =&gt; $username, "host" =&gt; $access_host ]); } catch (pdoexception $e) { /* continue */ } } (version_compare($db_root-&gt;getattribute(pdo::attr_server_version), '8.0.11', '&gt;=')) { // mariadb &amp; mysql8 // create user $stmt = $db_root-&gt;prepare("create user '" . $username . "'@'" . $access_host . "' identified :password"); $stmt-&gt;execute([ "password" =&gt; $password ]); // grant privileges $stmt = $db_root-&gt;prepare("grant `" . $database . "`.* :username@:host"); $stmt-&gt;execute([ "username" =&gt; $username, "host" =&gt; $access_host ]); } else { // grant privileges $stmt = $db_root-&gt;prepare("grant privileges `" . $database . "`.* :username@:host identified :password"); $stmt-&gt;execute([ "username" =&gt; $username, "host" =&gt; $access_host, "password" =&gt; $password ]); } } /** * import froxlor.sql database * * @return void * @throws exception */ private function importdatabasedata() { try { $pdo = $this-&gt;getunprivilegedpdo(); } catch (pdoexception $e) { throw new exception(lng('install.errors.unprivileged_sql_connection_failed')); } // actually import data try { $froxlorsql = include dirname(__file__, 5) . '/install/froxlor.sql.php'; $pdo-&gt;query($froxlorsql); } catch (pdoexception $e) { throw new exception(lng('install.errors.sql_import_failed', [$e-&gt;getmessage()]), 0, $e); } } /** * change settings according users input * * @param object $db_user * @return void * @throws exception */ private function dosettings(object &amp;$db_user) { $upd_stmt = $db_user-&gt;prepare(" update `" . table_panel_settings . "` set `value` = :value `settinggroup` = :group `varname` = :varname "); $mainip = !empty($this-&gt;validateddata['serveripv6']) ? $this-&gt;validateddata['serveripv6'] : $this-&gt;validateddata['serveripv4']; ($this-&gt;validateddata['use_admin_email_as_sender'] == '1') { $adminmail_value = $this-&gt;validateddata['admin_email']; } elseif ($this-&gt;validateddata['use_admin_email_as_sender'] == '0' &amp;&amp; !empty($this-&gt;validateddata['sender_email'])) { $adminmail_value = $this-&gt;validateddata['sender_email']; } else { $adminmail_value = 'admin@' . $this-&gt;validateddata['servername']; } $this-&gt;updatesetting($upd_stmt, $adminmail_value, 'panel', 'adminmail'); $this-&gt;updatesetting($upd_stmt, $mainip, 'system', 'ipaddress'); ($this-&gt;validateddata['use_ssl']) { $this-&gt;updatesetting($upd_stmt, 1, 'system', 'use_ssl'); $this-&gt;updatesetting($upd_stmt, 1, 'system', 'leenabled'); $this-&gt;updatesetting($upd_stmt, 1, 'system', 'le_froxlor_enabled'); } $this-&gt;updatesetting($upd_stmt, strtolower($this-&gt;validateddata['servername']), 'system', 'hostname'); $this-&gt;updatesetting($upd_stmt, 'en', 'panel', 'standardlanguage'); // todo: set language $this-&gt;updatesetting($upd_stmt, $this-&gt;validateddata['mysql_access_host'], 'system', 'mysql_access_host'); $this-&gt;updatesetting($upd_stmt, $this-&gt;validateddata['webserver'], 'system', 'webserver'); $this-&gt;updatesetting($upd_stmt, $this-&gt;validateddata['httpuser'], 'system', 'httpuser'); $this-&gt;updatesetting($upd_stmt, $this-&gt;validateddata['httpgroup'], 'system', 'httpgroup'); $this-&gt;updatesetting($upd_stmt, $this-&gt;validateddata['distribution'], 'system', 'distribution'); // necessary changes webservers != apache2 ($this-&gt;validateddata['webserver'] == "apache24") { $this-&gt;updatesetting($upd_stmt, 'apache2', 'system', 'webserver'); $this-&gt;updatesetting($upd_stmt, '1', 'system', 'apache24'); } elseif ($this-&gt;validateddata['webserver'] == "lighttpd") { $this-&gt;updatesetting($upd_stmt, '/var/run/lighttpd/', 'phpfpm', 'fastcgi_ipcdir'); } elseif ($this-&gt;validateddata['webserver'] == "nginx") { $this-&gt;updatesetting($upd_stmt, '/var/run/', 'phpfpm', 'fastcgi_ipcdir'); $this-&gt;updatesetting($upd_stmt, 'error', 'system', 'errorlog_level'); } $distros = glob(filedir::makecorrectdir(froxlor::getinstalldir() . '/lib/configfiles/') . '*.xml'); foreach ($distros $_distribution) { ($this-&gt;validateddata['distribution'] == str_replace(".xml", "", strtolower(basename($_distribution)))) { $dist = new configparser($_distribution); $defaults = $dist-&gt;getdefaults(); (!empty($defaults)) { foreach ($defaults $property) { (!isset($property-&gt;attributes()-&gt;for) || (isset($property-&gt;attributes()-&gt;for) &amp;&amp; $property-&gt;attributes()-&gt;for == $this-&gt;validateddata['webserver'])) { $this-&gt;updatesetting($upd_stmt, $property-&gt;attributes()-&gt;value, $property-&gt;attributes()-&gt;settinggroup, $property-&gt;attributes()-&gt;varname); } } } } } $this-&gt;updatesetting($upd_stmt, $this-&gt;validateddata['activate_newsfeed'], 'admin', 'show_news_feed'); $this-&gt;updatesetting($upd_stmt, dirname(__file__, 5), 'system', 'letsencryptchallengepath'); $this-&gt;updatesetting($upd_stmt, dirname(__file__, 5) . '/templates/misc/deactivated/', 'system', 'deactivateddocroot'); // insert lastcronrun installation date $this-&gt;updatesetting($upd_stmt, time(), 'system', 'lastcronrun'); // set settings according selected php-backend ($this-&gt;validateddata['webserver_backend'] == 'php-fpm') { $this-&gt;updatesetting($upd_stmt, '1', 'phpfpm', 'enabled'); $this-&gt;updatesetting($upd_stmt, '1', 'phpfpm', 'enabled_ownvhost'); } elseif ($this-&gt;validateddata['webserver_backend'] == 'fcgid') { $this-&gt;updatesetting($upd_stmt, '1', 'system', 'mod_fcgid'); $this-&gt;updatesetting($upd_stmt, '1', 'system', 'mod_fcgid_ownvhost'); } // check currently used php version set values fpm/fcgid accordingly (defined('php_major_version') &amp;&amp; defined('php_minor_version')) { // php-fpm $reload = "service php" . php_major_version . "." . php_minor_version . "-fpm restart"; $config_dir = "/etc/php/" . php_major_version . "." . php_minor_version . "/fpm/pool.d/"; // fcgid ($this-&gt;validateddata['distribution'] == 'bookworm') { $binary = "/usr/bin/php-cgi" . php_major_version . "." . php_minor_version; } else { $binary = "/usr/bin/php" . php_major_version . "." . php_minor_version . "-cgi"; } $db_user-&gt;query("update `" . table_panel_fpmdaemons . "` set `reload_cmd` = '" . $reload . "', `config_dir` = '" . $config_dir . "' `id` ='1';"); $db_user-&gt;query("update `" . table_panel_phpconfigs . "` set `binary` = '" . $binary . "';"); } ($this-&gt;validateddata['use_ssl']) { // enable let's encrypt cron $db_user-&gt;query("update `" . table_panel_cronruns . "` set `isactive` = '1' `module` = 'froxlor/letsencrypt';"); } // set specific times crons (traffic night, etc.) $timestamp = mktime(0, 0, 0, date('m', time()), date('d', time()), date('y', time())); $db_user-&gt;query("update `" . table_panel_cronruns . "` set `lastrun` = '" . $timestamp . "' `cronfile` ='cron_traffic';"); // insert task 99 generate correct cron.d-file automatically $db_user-&gt;query("insert `" . table_panel_tasks . "` set `type` = '99';"); } /** * execute prepared statement update settings * * @param pdostatement|null $stmt * @param string|null $group * @param string|null $varname * @param string|null $value */ private function updatesetting(pdostatement &amp;$stmt = null, string $value = null, string $group = null, string $varname = null) { $stmt-&gt;execute([ 'group' =&gt; $group, 'varname' =&gt; $varname, 'value' =&gt; $value ]); } /** * create corresponding entries froxlor database * * @param $db_user * @return void */ private function dodataentries(&amp;$db_user) { // lets insert default ip port $stmt = $db_user-&gt;prepare(" insert `" . table_panel_ipsandports . "` set `ip`= :serverip, `port` = :serverport, `namevirtualhost_statement` = :nvh, `vhostcontainer` = '1', `vhostcontainer_servername_statement` = '1', `ssl` = :ssl "); $nvh = $this-&gt;validateddata['webserver'] == 'apache2' ? '1' : '0'; $defaultip = false; (!empty($this-&gt;validateddata['serveripv6'])) { $stmt-&gt;execute([ 'nvh' =&gt; $nvh, 'serverip' =&gt; $this-&gt;validateddata['serveripv6'], 'serverport' =&gt; 80, 'ssl' =&gt; 0 ]); $defaultip = $db_user-&gt;lastinsertid(); } (!empty($this-&gt;validateddata['serveripv4'])) { $stmt-&gt;execute([ 'nvh' =&gt; $nvh, 'serverip' =&gt; $this-&gt;validateddata['serveripv4'], 'serverport' =&gt; 80, 'ssl' =&gt; 0 ]); $lastinsert = $db_user-&gt;lastinsertid(); $defaultip = $defaultip != false ? $defaultip . ',' . $lastinsert : $lastinsert; } $defaultsslip = false; ($this-&gt;validateddata['use_ssl']) { (!empty($this-&gt;validateddata['serveripv6'])) { $stmt-&gt;execute([ 'nvh' =&gt; $this-&gt;validateddata['webserver'] == 'apache2' ? '1' : '0', 'serverip' =&gt; $this-&gt;validateddata['serveripv6'], 'serverport' =&gt; 443, 'ssl' =&gt; 1 ]); $defaultsslip = $db_user-&gt;lastinsertid(); } (!empty($this-&gt;validateddata['serveripv4'])) { $stmt-&gt;execute([ 'nvh' =&gt; $this-&gt;validateddata['webserver'] == 'apache2' ? '1' : '0', 'serverip' =&gt; $this-&gt;validateddata['serveripv4'], 'serverport' =&gt; 443, 'ssl' =&gt; 1 ]); $lastinsert = $db_user-&gt;lastinsertid(); $defaultsslip = $defaultsslip != false ? $defaultsslip . ',' . $lastinsert : $lastinsert; } } // insert defaultip $upd_stmt = $db_user-&gt;prepare(" update `" . table_panel_settings . "` set `value` = :defaultip `settinggroup` = 'system' `varname` = :defipfld "); $upd_stmt-&gt;execute([ 'defaultip' =&gt; $defaultip, 'defipfld' =&gt; 'defaultip' ]); ($defaultsslip) { $upd_stmt-&gt;execute([ 'defaultip' =&gt; $defaultsslip, 'defipfld' =&gt; 'defaultsslip' ]); } // last least create main admin $ins_data = [ 'loginname' =&gt; $this-&gt;validateddata['admin_user'], 'password' =&gt; password_hash($this-&gt;validateddata['admin_pass'], password_default), 'adminname' =&gt; $this-&gt;validateddata['admin_name'], 'email' =&gt; $this-&gt;validateddata['admin_email'], 'deflang' =&gt; 'en' // todo: set language ]; $ins_stmt = $db_user-&gt;prepare(" insert `" . table_panel_admins . "` set `loginname` = :loginname, `password` = :password, `name` = :adminname, `email` = :email, `def_language` = :deflang, `api_allowed` = 1, `customers` = -1, `customers_see_all` = 1, `caneditphpsettings` = 1, `domains` = -1, `change_serversettings` = 1, `diskspace` = -1024, `mysqls` = -1, `emails` = -1, `email_accounts` = -1, `email_forwarders` = -1, `email_quota` = -1, `ftps` = -1, `subdomains` = -1, `traffic` = -1048576 "); $ins_stmt-&gt;execute($ins_data); } /** * create userdata.inc.php file * * @return void * @throws exception */ public function createuserdataconf() { $userdata = [ 'sql' =&gt; [ 'debug' =&gt; false, 'host' =&gt; $this-&gt;validateddata['mysql_host'], 'user' =&gt; $this-&gt;validateddata['mysql_unprivileged_user'], 'password' =&gt; $this-&gt;validateddata['mysql_unprivileged_pass'], 'db' =&gt; $this-&gt;validateddata['mysql_database'], ], 'sql_root' =&gt; [ '0' =&gt; [ 'caption' =&gt; 'default', 'host' =&gt; $this-&gt;validateddata['mysql_host'], 'user' =&gt; $this-&gt;validateddata['mysql_root_user'], 'password' =&gt; $this-&gt;validateddata['mysql_root_pass'], ] ] ]; // enable sql ssl userdata unprivileged root db user (!empty($this-&gt;validateddata['mysql_ssl_ca_file']) &amp;&amp; isset($this-&gt;validateddata['mysql_ssl_verify_server_certificate'])) { $userdata['sql']['ssl'] = [ 'cafile' =&gt; $this-&gt;validateddata['mysql_ssl_ca_file'], 'verifyservercertificate' =&gt; (bool)$this-&gt;validateddata['mysql_ssl_verify_server_certificate'], ]; $userdata['sql_root']['0']['ssl'] = [ 'cafile' =&gt; $this-&gt;validateddata['mysql_ssl_ca_file'], 'verifyservercertificate' =&gt; (bool)$this-&gt;validateddata['mysql_ssl_verify_server_certificate'], ]; } // test store userdata.inc.php ../lib $umask = @umask(077); $userdata = phphelper::parsearraytophpfile($userdata); $userdata_file = dirname(__file__, 5) . '/lib/userdata.inc.php'; (@touch($userdata_file) &amp;&amp; @is_writable($userdata_file)) { $fp = @fopen($userdata_file, 'w'); @fputs($fp, $userdata, strlen($userdata)); @fclose($fp); } else { @unlink($userdata_file); // try creating temporary file $temp_file = @tempnam(sys_get_temp_dir(), 'fx'); ($temp_file) { $fp = @fopen($temp_file, 'w'); @fputs($fp, $userdata, strlen($userdata)); @fclose($fp); } else { throw new exception(lng('install.errors.creating_configfile_failed')); } } @umask($umask); } private function createjsonarray(&amp;$db_user) { // use traffic analyzer ftpserver settings could define defaults lib/configfiles/*.xml templates // useful third-party package-maintainer (e.g. distros) control // installation defaults (less hardcoded values) $custom_dependency = $db_user-&gt;query(" select `varname`, `value` `" . table_panel_settings . "` `settinggroup` = 'system' (`varname` = 'traffictool' `varname` = 'ftpserver') "); $cd_result = $custom_dependency-&gt;fetchall(\pdo::fetch_key_pair); $system_params = ["cron", "libnssextrausers", "logrotate"]; (isset($cd_result['traffictool'])) { $system_params[] = $cd_result['traffictool']; } ($this-&gt;validateddata['webserver_backend'] == 'php-fpm') { $system_params[] = 'php-fpm'; } elseif ($this-&gt;validateddata['webserver_backend'] == 'fcgid') { $system_params[] = 'fcgid'; } $json_params = [ 'distro' =&gt; $this-&gt;validateddata['distribution'], 'dns' =&gt; 'x', 'http' =&gt; $this-&gt;validateddata['webserver'], 'smtp' =&gt; 'postfix_dovecot', 'mail' =&gt; 'dovecot_postfix2', 'antispam' =&gt; 'rspamd', 'ftp' =&gt; $cd_result['ftpserver'] ?? 'x', 'system' =&gt; $system_params ]; $_session['installation']['json_params'] = json_encode($json_params); } private function createuserdataparamstr() { $req_fields = [ 'mysql_host', 'mysql_unprivileged_user', 'mysql_unprivileged_pass', 'mysql_database', 'mysql_root_user', 'mysql_root_pass', 'mysql_ssl_ca_file', 'mysql_ssl_verify_server_certificate' ]; $json_params = []; foreach ($req_fields $field) { $json_params[$field] = $this-&gt;validateddata[$field] ?? ""; } $_session['installation']['ud_str'] = base64_encode(json_encode($json_params)); } }</file><file name="lib/Froxlor/Settings/FroxlorVhostSettings.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\settings; use froxlor\database\database; class froxlorvhostsettings { /** * @param bool $need_ssl * * @return bool * @throws \exception */ public static function hasvhostcontainerenabled(bool $need_ssl = false): bool { $sel_stmt = database::prepare("select count(*) vcentries `" . table_panel_ipsandports . "` `vhostcontainer`= '1'" . ($need_ssl ? " `ssl` = '1'" : "")); $result = database::pexecute_first($sel_stmt); ($result) { return $result['vcentries'] &gt; 0; } return false; } }</file><file name="lib/Froxlor/Settings/Store.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\settings; use exception; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\database\dbmanager; use froxlor\filedir; use froxlor\froxlor; use froxlor\idna\idnawrapper; use froxlor\phphelper; use froxlor\settings; use froxlor\system\cronjob; use froxlor\system\iptools; use froxlor\ui\request; use froxlor\validate\validate; use pdo; class store { public static function storesettingclearcertificates($fieldname, $fielddata, $newfieldvalue) { $returnvalue = self::storesettingfield($fieldname, $fielddata, $newfieldvalue); ($returnvalue !== false &amp;&amp; is_array($fielddata) &amp;&amp; isset($fielddata['settinggroup']) &amp;&amp; $fielddata['settinggroup'] == 'system' &amp;&amp; isset($fielddata['varname']) ) { ($fielddata['varname'] == 'le_froxlor_enabled' &amp;&amp; $newfieldvalue == '0') { database::query(" delete `" . table_panel_domain_ssl_settings . "` `domainid` = '0' "); } elseif ($fielddata['varname'] == 'froxloraliases' &amp;&amp; $newfieldvalue != $fielddata['value']) { database::query(" update `" . table_panel_domain_ssl_settings . "` set `validtodate`= null `domainid` = '0' "); } } return $returnvalue; } public static function storesettingfield($fieldname, $fielddata, $newfieldvalue) { (is_array($fielddata) &amp;&amp; isset($fielddata['settinggroup']) &amp;&amp; $fielddata['settinggroup'] != '' &amp;&amp; isset($fielddata['varname']) &amp;&amp; $fielddata['varname'] != '') { (settings::set($fielddata['settinggroup'] . '.' . $fielddata['varname'], $newfieldvalue) !== false) { /* * fielddata[cronmodule] set, means enable/disable cronjob */ (isset($fielddata['cronmodule']) &amp;&amp; $fielddata['cronmodule'] != '') { cronjob::togglecronstatus($fielddata['cronmodule'], $newfieldvalue); } /* * satisfy dependencies */ (isset($fielddata['dependency']) &amp;&amp; is_array($fielddata['dependency'])) { ((int)$fielddata['dependency']['onlyif'] == (int)$newfieldvalue) { self::storesettingfield($fielddata['dependency']['fieldname'], $fielddata['dependency']['fielddata'], $newfieldvalue); } } return [ $fielddata['settinggroup'] . '.' . $fielddata['varname'] =&gt; $newfieldvalue ]; } else { return false; } } else { return false; } } public static function storesettingdefaultip($fieldname, $fielddata, $newfieldvalue) { $defaultips_old = settings::get('system.defaultip'); $returnvalue = self::storesettingfield($fieldname, $fielddata, $newfieldvalue); ($returnvalue !== false &amp;&amp; is_array($fielddata) &amp;&amp; isset($fielddata['settinggroup']) &amp;&amp; $fielddata['settinggroup'] == 'system' &amp;&amp; isset($fielddata['varname']) &amp;&amp; $fielddata['varname'] == 'defaultip') { self::updatestdsubdomaindefaultip($newfieldvalue, $defaultips_old); } return $returnvalue; } private static function updatestdsubdomaindefaultip($newfieldvalue, $defaultips_old) { // update standard-subdomain customer exists $customerstddomains_result_stmt = database::prepare(" select `standardsubdomain` `" . table_panel_customers . "` `standardsubdomain` &lt;&gt; '0' "); database::pexecute($customerstddomains_result_stmt); $ids = []; ($customerstddomains_row = $customerstddomains_result_stmt-&gt;fetch(pdo::fetch_assoc)) { $ids[] = (int)$customerstddomains_row['standardsubdomain']; } (count($ids) &gt; 0) { (!empty($defaultips_old)) { // delete existing mappings linking default ips $del_stmt = database::prepare(" delete `" . table_domaintoip . "` `id_domain` (" . implode(', ', $ids) . ") `id_ipandports` (" . $defaultips_old . ") "); database::pexecute($del_stmt); } $defaultips_new = !empty($newfieldvalue) ? explode(",", $newfieldvalue) : []; (count($defaultips_new) &gt; 0) { // insert new mappings $ins_stmt = database::prepare(" insert `" . table_domaintoip . "` set `id_domain` = :domainid, `id_ipandports` = :ipandportid "); foreach ($ids $id) { foreach ($defaultips_new $defaultip_new) { database::pexecute($ins_stmt, [ 'domainid' =&gt; $id, 'ipandportid' =&gt; $defaultip_new ]); } } } } } public static function storesettingdefaultsslip($fieldname, $fielddata, $newfieldvalue) { $defaultips_old = settings::get('system.defaultsslip'); self::cleanipselection($defaultips_old); self::cleanipselection($newfieldvalue); $returnvalue = self::storesettingfield($fieldname, $fielddata, $newfieldvalue); ($returnvalue !== false &amp;&amp; is_array($fielddata) &amp;&amp; isset($fielddata['settinggroup']) &amp;&amp; $fielddata['settinggroup'] == 'system' &amp;&amp; isset($fielddata['varname']) &amp;&amp; $fielddata['varname'] == 'defaultsslip') { self::updatestdsubdomaindefaultip($newfieldvalue, $defaultips_old); } return $returnvalue; } private static function cleanipselection(&amp;$selection) { $selection_arr = array_filter(explode(',', $selection), function ($value) { return !empty($value); }); $selection = implode(",", $selection_arr); } /** * updates setting default panel-theme * also user themes (customers admins) * changing themes disallowed * * @param string $fieldname * @param array $fielddata * @param mixed $newfieldvalue * * @return boolean|array */ public static function storesettingdefaulttheme($fieldname, $fielddata, $newfieldvalue) { // first save setting $returnvalue = self::storesettingfield($fieldname, $fielddata, $newfieldvalue); ($returnvalue !== false &amp;&amp; is_array($fielddata) &amp;&amp; isset($fielddata['settinggroup']) &amp;&amp; $fielddata['settinggroup'] == 'panel' &amp;&amp; isset($fielddata['varname']) &amp;&amp; $fielddata['varname'] == 'default_theme') { // now, changing themes disabled manually set // new theme (customers admin, depending settings) (settings::get('panel.allow_theme_change_customer') == '0') { $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `theme` = :theme "); database::pexecute($upd_stmt, [ 'theme' =&gt; $newfieldvalue ]); } (settings::get('panel.allow_theme_change_admin') == '0') { $upd_stmt = database::prepare(" update `" . table_panel_admins . "` set `theme` = :theme "); database::pexecute($upd_stmt, [ 'theme' =&gt; $newfieldvalue ]); } } return $returnvalue; } public static function storesettingfieldinsertbindtask($fieldname, $fielddata, $newfieldvalue) { // first save setting $returnvalue = self::storesettingfield($fieldname, $fielddata, $newfieldvalue); ($returnvalue !== false) { cronjob::inserttask(taskid::rebuild_dns); } return $returnvalue; } public static function storesettingfieldinsertantispamtask($fieldname, $fielddata, $newfieldvalue) { // first save setting $returnvalue = self::storesettingfield($fieldname, $fielddata, $newfieldvalue); ($returnvalue !== false) { cronjob::inserttask(taskid::rebuild_rspamd); } return $returnvalue; } public static function storesettingfieldinsertupdateservicestask($fieldname, $fielddata, $newfieldvalue) { // first save setting $returnvalue = self::storesettingfield($fieldname, $fielddata, $newfieldvalue); ($returnvalue !== false) { cronjob::inserttask(taskid::update_le_services); } return $returnvalue; } public static function storesettinghostname($fieldname, $fielddata, $newfieldvalue) { $returnvalue = self::storesettingfield($fieldname, $fielddata, $newfieldvalue); ($returnvalue !== false &amp;&amp; is_array($fielddata) &amp;&amp; isset($fielddata['settinggroup']) &amp;&amp; $fielddata['settinggroup'] == 'system' &amp;&amp; isset($fielddata['varname']) &amp;&amp; ($fielddata['varname'] == 'hostname' || $fielddata['varname'] == 'stdsubdomain')) { $idna_convert = new idnawrapper(); $newfieldvalue = $idna_convert-&gt;encode($newfieldvalue); (($fielddata['varname'] == 'hostname' &amp;&amp; settings::get('system.stdsubdomain') == '') || $fielddata['varname'] == 'stdsubdomain') { ($fielddata['varname'] == 'stdsubdomain' &amp;&amp; $newfieldvalue == '') { // clear field, reset stdsubdomain system-hostname $oldhost = $idna_convert-&gt;encode(settings::get('system.stdsubdomain')); $newhost = $idna_convert-&gt;encode(settings::get('system.hostname')); } elseif ($fielddata['varname'] == 'stdsubdomain' &amp;&amp; settings::get('system.stdsubdomain') == '') { // former std-subdomain system-hostname $oldhost = $idna_convert-&gt;encode(settings::get('system.hostname')); $newhost = $newfieldvalue; } elseif ($fielddata['varname'] == 'stdsubdomain') { // std-subdomain changed $oldhost = $idna_convert-&gt;encode(settings::get('system.stdsubdomain')); $newhost = $newfieldvalue; } elseif ($fielddata['varname'] == 'hostname' &amp;&amp; settings::get('system.stdsubdomain') == '') { // system-hostname changed system-stdsubdomain set $oldhost = $idna_convert-&gt;encode(settings::get('system.hostname')); $newhost = $newfieldvalue; } $customerstddomains_result_stmt = database::prepare(" select `standardsubdomain` `" . table_panel_customers . "` `standardsubdomain` &lt;&gt; '0' "); database::pexecute($customerstddomains_result_stmt); $ids = []; ($customerstddomains_row = $customerstddomains_result_stmt-&gt;fetch(pdo::fetch_assoc)) { $ids[] = (int)$customerstddomains_row['standardsubdomain']; } (count($ids) &gt; 0) { $upd_stmt = database::prepare(" update `" . table_panel_domains . "` set `domain` = replace(`domain`, :host, :newval) `id` ('" . implode(', ', $ids) . "') "); database::pexecute($upd_stmt, [ 'host' =&gt; $oldhost, 'newval' =&gt; $newhost ]); } } } return $returnvalue; } public static function storesettingipaddress($fieldname, $fielddata, $newfieldvalue) { $returnvalue = self::storesettingfield($fieldname, $fielddata, $newfieldvalue); ($returnvalue !== false &amp;&amp; is_array($fielddata) &amp;&amp; isset($fielddata['settinggroup']) &amp;&amp; $fielddata['settinggroup'] == 'system' &amp;&amp; isset($fielddata['varname']) &amp;&amp; $fielddata['varname'] == 'ipaddress') { $mysql_access_host_array = array_map('trim', explode(',', settings::get('system.mysql_access_host'))); $mysql_access_host_array[] = $newfieldvalue; $mysql_access_host_array = array_unique(phphelper::arraytrim($mysql_access_host_array)); dbmanager::correctmysqlusers($mysql_access_host_array); $mysql_access_host = implode(',', $mysql_access_host_array); settings::set('system.mysql_access_host', $mysql_access_host); } return $returnvalue; } public static function storesettingmysqlaccesshost($fieldname, $fielddata, $newfieldvalue) { $ips = $newfieldvalue; // convert cidr netmask mysql, needed (strpos($ips, ',') !== false) { $ips = explode(',', $ips); } (is_array($ips) &amp;&amp; count($ips) &gt; 0) { $newfieldvalue = []; foreach ($ips $ip) { $org_ip = $ip; $ip_cidr = explode("/", $ip); (count($ip_cidr) === 2) { $ip = $ip_cidr[0]; (strlen($ip_cidr[1]) &lt;= 2) { $ip_cidr[1] = iptools::cidr2netmaskaddr($org_ip); } $newfieldvalue[] = $ip . '/' . $ip_cidr[1]; } else { $newfieldvalue[] = $org_ip; } } $newfieldvalue = implode(',', $newfieldvalue); } $returnvalue = self::storesettingfield($fieldname, $fielddata, $newfieldvalue); ($returnvalue !== false &amp;&amp; is_array($fielddata) &amp;&amp; isset($fielddata['settinggroup']) &amp;&amp; $fielddata['settinggroup'] == 'system' &amp;&amp; isset($fielddata['varname']) &amp;&amp; $fielddata['varname'] == 'mysql_access_host') { $mysql_access_host_array = array_map('trim', explode(',', $newfieldvalue)); (in_array('127.0.0.1', $mysql_access_host_array) &amp;&amp; !in_array('localhost', $mysql_access_host_array)) { $mysql_access_host_array[] = 'localhost'; } (!in_array('127.0.0.1', $mysql_access_host_array) &amp;&amp; in_array('localhost', $mysql_access_host_array)) { $mysql_access_host_array[] = '127.0.0.1'; } // aware ipv6 addresses enclosed [ ] passed $mysql_access_host_array = array_map([ '\\froxlor\\settings\\store', 'cleanmysqlaccesshost' ], $mysql_access_host_array); $mysql_access_host_array = array_unique(phphelper::arraytrim($mysql_access_host_array)); $newfieldvalue = implode(',', $mysql_access_host_array); dbmanager::correctmysqlusers($mysql_access_host_array); $mysql_access_host = implode(',', $mysql_access_host_array); settings::set('system.mysql_access_host', $mysql_access_host); } return $returnvalue; } public static function storesettingresetcatchall($fieldname, $fielddata, $newfieldvalue) { $returnvalue = self::storesettingfield($fieldname, $fielddata, $newfieldvalue); ($returnvalue !== false &amp;&amp; is_array($fielddata) &amp;&amp; isset($fielddata['settinggroup']) &amp;&amp; $fielddata['settinggroup'] == 'catchall' &amp;&amp; isset($fielddata['varname']) &amp;&amp; $fielddata['varname'] == 'catchall_enabled' &amp;&amp; $newfieldvalue == '0') { database::query(" update `" . table_mail_virtual . "` set `iscatchall` = '0' `iscatchall` = '1' "); } return $returnvalue; } /** * whenever webserver- / fcgid- fpm-user gets updated * need update ftp_groups accordingly */ public static function storesettingwebserverfcgidfpmuser($fieldname, $fielddata, $newfieldvalue) { (is_array($fielddata) &amp;&amp; isset($fielddata['settinggroup']) &amp;&amp; isset($fielddata['varname'])) { $update_user = null; // webserver ($fielddata['settinggroup'] == 'system' &amp;&amp; $fielddata['varname'] == 'httpuser') { $update_user = settings::get('system.httpuser'); } // fcgid ($fielddata['settinggroup'] == 'system' &amp;&amp; $fielddata['varname'] == 'mod_fcgid_httpuser') { $update_user = settings::get('system.mod_fcgid_httpuser'); } // webserver ($fielddata['settinggroup'] == 'phpfpm' &amp;&amp; $fielddata['varname'] == 'vhost_httpuser') { $update_user = settings::get('phpfpm.vhost_httpuser'); } $returnvalue = self::storesettingfield($fieldname, $fielddata, $newfieldvalue); ($returnvalue !== false) { /** * update anything changed */ ($update_user != null &amp;&amp; $newfieldvalue != $update_user) { $upd_stmt = database::prepare("update `" . table_ftp_groups . "` set `members` = replace(`members`, :olduser, :newuser)"); database::pexecute($upd_stmt, [ 'olduser' =&gt; $update_user, 'newuser' =&gt; $newfieldvalue ]); } } } return $returnvalue; } public static function storesettingimage($fieldname, $fielddata) { (isset($fielddata['settinggroup'], $fielddata['varname']) &amp;&amp; is_array($fielddata) &amp;&amp; $fielddata['settinggroup'] !== '' &amp;&amp; $fielddata['varname'] !== '') { $save_to = null; $path = froxlor::getinstalldir() . '/img/'; $path = filedir::makecorrectdir($path); // new file? (isset($_files[$fieldname]) &amp;&amp; $_files[$fieldname]['tmp_name']) { // make sure upload directory exists (!is_dir($path) &amp;&amp; !mkdir($path, 0775)) { throw new exception("img directory exist cannot created"); } // make sure write upload directory (!is_writable($path)) { (!chmod($path, 0775)) { throw new exception("cannot write img directory"); } } // make sure mime-type matches image $image_content = file_get_contents($_files[$fieldname]['tmp_name']); $value = base64_encode($image_content); (validate::validatebase64image($value)) { $img_filename = $_files[$fieldname]['name']; $spl = explode('.', $img_filename); $file_extension = strtolower(array_pop($spl)); unset($spl); (!in_array($file_extension, [ 'jpeg', 'jpg', 'png', 'gif' ])) { throw new exception("invalid file-extension, use one of: jpeg, jpg, png, gif"); } $filename = bin2hex(random_bytes(16)) . '.' . $file_extension; // move file (!move_uploaded_file($_files[$fieldname]['tmp_name'], $path . $filename)) { throw new exception("unable save image img folder"); } $save_to = 'img/' . $filename . '?v=' . time(); } } // delete file? ($fielddata['value'] !== "" &amp;&amp; array_key_exists($fieldname . '_delete', $_post) &amp;&amp; request::post($fieldname . '_delete')) { @unlink(froxlor::getinstalldir() . '/' . explode('?', $fielddata['value'], 2)[0]); $save_to = ''; } // nothing changed ($save_to === null) { return [ $fielddata['settinggroup'] . '.' . $fielddata['varname'] =&gt; $fielddata['value'] ]; } (settings::set($fielddata['settinggroup'] . '.' . $fielddata['varname'], $save_to) === false) { return false; } return [ $fielddata['settinggroup'] . '.' . $fielddata['varname'] =&gt; $save_to ]; } return false; } private static function cleanmysqlaccesshost($value) { (substr($value, 0, 1) == '[' &amp;&amp; substr($value, -1) == ']') { return substr($value, 1, -1); } return $value; } public static function storesettingupdatetraffictool($fieldname, $fielddata, $newfieldvalue) { $returnvalue = self::storesettingfield($fieldname, $fielddata, $newfieldvalue); ($returnvalue !== false &amp;&amp; is_array($fielddata) &amp;&amp; isset($fielddata['settinggroup']) &amp;&amp; $fielddata['settinggroup'] == 'system' &amp;&amp; isset($fielddata['varname']) &amp;&amp; $fielddata['varname'] == 'traffictool' &amp;&amp; $newfieldvalue != $fielddata['value']) { $oldpath = '/' . $fielddata['value'] . '/'; $newpath = '/' . $newfieldvalue . '/'; $sel_stmt = database::prepare("select * `" . table_panel_htpasswds . "` `path` like :oldpath"); $upd_stmt = database::prepare(" update `" . table_panel_htpasswds . "` set `path` = :newpath `id` = :id "); database::pexecute($sel_stmt, [ 'oldpath' =&gt; '%' . $oldpath ]); ($entry = $sel_stmt-&gt;fetch(\pdo::fetch_assoc)) { $full_path = str_replace($oldpath, $newpath, $entry['path']); $eid = (int)$entry['id']; database::pexecute($upd_stmt, [ 'newpath' =&gt; $full_path, 'id' =&gt; $eid ]); } } return $returnvalue; } }</file><file name="lib/Froxlor/Settings/index.html" /><file name="lib/Froxlor/Domain/IpAddr.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\domain; use froxlor\database\database; use pdo; class ipaddr { /** * @return array */ public static function getipaddresses(): array { $result_stmt = database::query(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` order `ip` asc, `port` asc "); $system_ipaddress_array = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { (!isset($system_ipaddress_array[$row['ip']]) &amp;&amp; !in_array($row['ip'], $system_ipaddress_array)) { $system_ipaddress_array[$row['ip']] = $row['ip']; } } return $system_ipaddress_array; } /** * @return array * @throws \exception */ public static function getsslipportcombinations(): array { return [ '' =&gt; lng('panel.none_value') ] + self::getipportcombinations(true); } /** * @param bool $ssl * @return array * @throws \exception */ public static function getipportcombinations(bool $ssl = false): array { global $userinfo; $additional_conditions_params = []; $additional_conditions_array = []; (!empty($userinfo) &amp;&amp; $userinfo['ip'] != '-1') { $admin_ip_stmt = database::prepare(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `id` = (:ipid) "); $myips = implode(",", json_decode($userinfo['ip'], true)); database::pexecute($admin_ip_stmt, [ 'ipid' =&gt; $myips ]); $additional_conditions_array[] = "`ip` (:adminips)"; $additional_conditions_params['adminips'] = $myips; } ($ssl !== null) { $additional_conditions_array[] = "`ssl` = :ssl"; $additional_conditions_params['ssl'] = ($ssl === true ? '1' : '0'); } $additional_conditions = ''; (count($additional_conditions_array) &gt; 0) { $additional_conditions = " " . implode(" ", $additional_conditions_array) . " "; } $result_stmt = database::prepare(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` " . $additional_conditions . " order `ip` asc, `port` asc "); database::pexecute($result_stmt, $additional_conditions_params); $system_ipaddress_array = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { (filter_var($row['ip'], filter_validate_ip, filter_flag_ipv6)) { $row['ip'] = '[' . $row['ip'] . ']'; } $system_ipaddress_array[$row['id']] = $row['ip'] . ':' . $row['port']; } return $system_ipaddress_array; } }</file><file name="lib/Froxlor/Domain/Domain.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\domain; use froxlor\cron\http\letsencrypt\acmesh; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; use pdo; class domain { /** * return ip addresses associated given domain, * returns ips domain-id = 0 (froxlor.vhost) * * @param int $domain_id * @return array * @throws \exception */ public static function getipsofdomain(int $domain_id = 0): array { ($domain_id &gt; 0) { $sel_stmt = database::prepare(" select i.ip `" . table_panel_ipsandports . "` `i` left join `" . table_domaintoip . "` `dip` dip.id_ipandports = i.id dip.id_domain = :domainid group i.ip "); $sel_param = [ 'domainid' =&gt; $domain_id ]; } else { // assuming froxlor.vhost (id = 0) $sel_stmt = database::prepare(" select ip `" . table_panel_ipsandports . "` group ip "); $sel_param = []; } database::pexecute($sel_stmt, $sel_param); $result = []; ($ip = $sel_stmt-&gt;fetch(pdo::fetch_assoc)) { $result[] = $ip['ip']; } return $result; } /** * return array enabled redirect-codes * * @return array array enabled redirect-codes */ public static function getredirectcodesarray(): array { $sql = "select * `" . table_panel_redirectcodes . "` `enabled` = '1' order `id` asc"; $result_stmt = database::query($sql); $codes = []; ($rc = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $codes[] = $rc; } return $codes; } /** * returns redirect-code given * domain-id * * @param int $domainid id domain * * @return string redirect-code * @throws \exception */ public static function getdomainredirectcode(int $domainid = 0): string { // get system default $default = '301'; (settings::get('customredirect.enabled') == '1') { $all_codes = self::getredirectcodes(false); $_default = $all_codes[settings::get('customredirect.default')]; $default = ($_default == '---') ? $default : $_default; } $code = $default; ($domainid &gt; 0) { $result_stmt = database::prepare(" select `r`.`code` `redirect` `" . table_panel_redirectcodes . "` `r`, `" . table_panel_domainredirects . "` `rc` `r`.`id` = `rc`.`rid` `rc`.`did` = :domainid "); $result = database::pexecute_first($result_stmt, [ 'domainid' =&gt; $domainid ]); (is_array($result) &amp;&amp; isset($result['redirect'])) { $code = ($result['redirect'] == '---') ? $default : $result['redirect']; } } return $code; } /** * return array enabled redirect-codes * settings form * * @param bool $add_desc optional, default true, add code-description * * @return array array enabled redirect-codes */ public static function getredirectcodes(bool $add_desc = true): array { $sql = "select * `" . table_panel_redirectcodes . "` `enabled` = '1' order `id` asc"; $result_stmt = database::query($sql); $codes = []; ($rc = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $codes[$rc['id']] = $rc['code']; ($add_desc) { $codes[$rc['id']] .= ' (' . lng('redirect_desc.' . $rc['desc']) . ')'; } } return $codes; } /** * returns redirect-id given * domain-id * * @param int $domainid id domain * * @return int redirect-code-id * @throws \exception */ public static function getdomainredirectid(int $domainid = 0): int { $code = 1; ($domainid &gt; 0) { $result_stmt = database::prepare(" select `r`.`id` `redirect` `" . table_panel_redirectcodes . "` `r`, `" . table_panel_domainredirects . "` `rc` `r`.`id` = `rc`.`rid` `rc`.`did` = :domainid "); $result = database::pexecute_first($result_stmt, [ 'domainid' =&gt; $domainid ]); ($result &amp;&amp; isset($result['redirect'])) { $code = (int)$result['redirect']; } } return $code; } /** * adds redirect-code domain * * @param int $domainid id domain add code * @param int $redirect selected redirect-id * * @return null * @throws \exception */ public static function addredirecttodomain(int $domainid = 0, int $redirect = 1) { ($domainid &gt; 0) { $ins_stmt = database::prepare(" insert `" . table_panel_domainredirects . "` set `rid` = :rid, `did` = :did "); database::pexecute($ins_stmt, [ 'rid' =&gt; $redirect, 'did' =&gt; $domainid ]); } } /** * updates redirect-code domain * redirect-code false, nothing happens * * @param int $domainid id domain update * @param int $redirect selected redirect-id * * @return null * @throws \exception */ public static function updateredirectofdomain(int $domainid = 0, int $redirect = 0) { (!$redirect) { return; } ($domainid &gt; 0) { $del_stmt = database::prepare(" delete `" . table_panel_domainredirects . "` `did` = :domainid "); database::pexecute($del_stmt, [ 'domainid' =&gt; $domainid ]); $ins_stmt = database::prepare(" insert `" . table_panel_domainredirects . "` set `rid` = :rid, `did` = :did "); database::pexecute($ins_stmt, [ 'rid' =&gt; $redirect, 'did' =&gt; $domainid ]); } } /** * get ids domains main domains subdomain another main domain (for dns) * * @param int $id main-domain check * * @return array * @throws \exception */ public static function getmainsubdomainids(int $id): array { $result_stmt = database::prepare(" select id `" . table_panel_domains . "` isbinddomain = 1 domain like concat('%.', ( select d.domain `" . table_panel_domains . "` d.id = :id )) "); database::pexecute($result_stmt, [ 'id' =&gt; $id ]); $result = []; ($entry = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $result[] = $entry['id']; } return $result; } /** * check whether given domain ssl-ip/port assigned * * @param int $domainid * * @return bool * @throws \exception */ public static function domainhassslipport(int $domainid): bool { $result_stmt = database::prepare(" select `dt`.* `" . table_domaintoip . "` `dt`, `" . table_panel_ipsandports . "` `iap` `dt`.`id_ipandports` = `iap`.`id` `iap`.`ssl` = '1' `dt`.`id_domain` = :domainid;"); database::pexecute($result_stmt, [ 'domainid' =&gt; $domainid ]); $result = $result_stmt-&gt;fetch(pdo::fetch_assoc); ($result &amp;&amp; isset($result['id_ipandports'])) { return true; } return false; } /** * returns true false whether given domain id * std-subdomain customer * * @param int $did domain-id * * @return bool * @throws \exception */ public static function iscustomerstdsubdomain(int $did): bool { ($did &gt; 0) { $result_stmt = database::prepare(" select `customerid` `" . table_panel_customers . "` `standardsubdomain` = :did "); $result = database::pexecute_first($result_stmt, [ 'did' =&gt; $did ]); ($result &amp;&amp; isset($result['customerid'])) { return $result['customerid'] &gt; 0; } } return false; } /** * @param int $aliasdestinationdomainid * @param froxlorlogger $log * * @return void * @throws \exception */ public static function triggerletsencryptcsrforaliasdestinationdomain( int $aliasdestinationdomainid, froxlorlogger $log ) { ($aliasdestinationdomainid &gt; 0) { $log-&gt;logaction( froxlorlogger::adm_action, log_info, "letsencrypt csr triggered domain id " . $aliasdestinationdomainid ); $upd_stmt = database::prepare("update `" . table_panel_domain_ssl_settings . "` set `validtodate` = null domainid = :domainid "); database::pexecute($upd_stmt, [ 'domainid' =&gt; $aliasdestinationdomainid ]); } } /** * @param string $domainname * @return true */ public static function doletsencryptcleanup(string $domainname): bool { // @ see \froxlor\cron\http\letsencrypt\acmesh.php $acmesh = acmesh::getacmesh(); (file_exists($acmesh)) { $certificate_folder = acmesh::getworkingdirfromenv($domainname); $certificate_ecc_folder = acmesh::getworkingdirfromenv($domainname, true); (file_exists($certificate_folder) || file_exists($certificate_ecc_folder)) { $params = " --remove -d " . $domainname; (file_exists($certificate_ecc_folder)) { $params .= " --ecc"; } // run remove command filedir::safe_exec($acmesh . $params); // remove certificates directory (file_exists($certificate_folder)) { filedir::safe_exec('rm -rf ' . $certificate_folder); } elseif (file_exists($certificate_ecc_folder)) { filedir::safe_exec('rm -rf ' . $certificate_ecc_folder); } } } return true; } /** * checks give path security issues * returns string appended * line open_basedir directive * * @param string $path path check append * @param bool $first true, ':' prefixed path * * @return string * @throws \exception */ public static function appendopenbasedirpath(string $path = '', bool $first = false): string { ($path != '' &amp;&amp; $path != '/' &amp;&amp; (!preg_match("#^/dev#i", $path) || preg_match("#^/dev/urandom#i", $path)) &amp;&amp; !preg_match("#^/proc#i", $path) &amp;&amp; !preg_match("#^/etc#i", $path) &amp;&amp; !preg_match("#^/sys#i", $path) &amp;&amp; !preg_match("#:#", $path)) { (preg_match("#^/dev/urandom#i", $path)) { $path = filedir::makecorrectfile($path); } else { $path = filedir::makecorrectdir($path); } // check php-version requires trailing // slash removed allow usage // sub-folders within given folder, fixes #797 ((php_minor_version == 2 &amp;&amp; php_version_id &gt;= 50216) || php_version_id &gt;= 50304) { // check trailing slash (substr($path, -1, 1) == '/') { // remove $path = substr($path, 0, -1); } } ($first) { return $path; } return ':' . $path; } return ''; } }</file><file name="lib/Froxlor/Domain/index.html" /><file name="lib/Froxlor/Dns/PowerDNS.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\dns; use froxlor\filedir; use froxlor\settings; use pdo; use pdoexception; class powerdns { private static $pdns_db = null; /** * remove records entries given domain * * @param string|null $domain */ public static function cleandomainzone(string $domain = null) { (!empty($domain)) { $pdns_domains_stmt = self::getdb()-&gt;prepare("select `id`, `name` `domains` `name` = :domain"); $del_rec_stmt = self::getdb()-&gt;prepare("delete `records` `domain_id` = :did"); $del_meta_stmt = self::getdb()-&gt;prepare("delete `domainmetadata` `domain_id` = :did"); $del_dom_stmt = self::getdb()-&gt;prepare("delete `domains` `id` = :did"); $pdns_domains_stmt-&gt;execute([ 'domain' =&gt; $domain ]); $pdns_domain = $pdns_domains_stmt-&gt;fetch(pdo::fetch_assoc); $del_rec_stmt-&gt;execute([ 'did' =&gt; $pdns_domain['id'] ]); $del_meta_stmt-&gt;execute([ 'did' =&gt; $pdns_domain['id'] ]); $del_dom_stmt-&gt;execute([ 'did' =&gt; $pdns_domain['id'] ]); } } /** * get pdo database connection powerdns database * * @return \pdo */ public static function getdb(): \pdo { (!isset(self::$pdns_db) || !(self::$pdns_db instanceof pdo)) { self::connecttopdnsdb(); } return self::$pdns_db; } /** * @return void */ private static function connecttopdnsdb() { // get froxlor pdns config $cf = settings::get('system.bindconf_directory') . '/froxlor/pdns_froxlor.conf'; $config = filedir::makecorrectfile($cf); (!file_exists($config)) { die('powerdns configuration file (' . $config . ') found. go configuration templates?' . php_eol); } $lines = file($config); $mysql_data = []; foreach ($lines $line) { $line = trim($line); (strtolower(substr($line, 0, 6)) == 'gmysql') { $namevalue = explode("=", $line); $mysql_data[$namevalue[0]] = $namevalue[1]; } } // build connection string $driver = 'mysql'; $dsn = $driver . ":"; $options = [ 'pdo::mysql_attr_init_command' =&gt; 'set names utf8' ]; $attributes = [ 'attr_errmode' =&gt; 'errmode_exception' ]; $dbconf = []; $dbconf["dsn"] = [ 'dbname' =&gt; $mysql_data["gmysql-dbname"], 'charset' =&gt; 'utf8' ]; (isset($mysql_data['gmysql-socket']) &amp;&amp; !empty($mysql_data['gmysql-socket'])) { $dbconf["dsn"]['unix_socket'] = filedir::makecorrectfile($mysql_data['gmysql-socket']); } else { $dbconf["dsn"]['host'] = $mysql_data['gmysql-host']; $dbconf["dsn"]['port'] = $mysql_data['gmysql-port']; (!empty($mysql_data['gmysql-ssl-ca-file'])) { $options[pdo::mysql_attr_ssl_ca] = $mysql_data['gmysql-ssl-ca-file']; $options[pdo::mysql_attr_ssl_verify_server_cert] = (bool)$mysql_data['gmysql-ssl-verify-server-certificate']; } } // add options dsn-string foreach ($dbconf["dsn"] $k =&gt; $v) { $dsn .= $k . "=" . $v . ";"; } // clean unset($dbconf); // try connect try { self::$pdns_db = new pdo($dsn, $mysql_data['gmysql-user'], $mysql_data['gmysql-password'], $options); } catch (pdoexception $e) { die($e-&gt;getmessage()); } // set attributes foreach ($attributes $k =&gt; $v) { self::$pdns_db-&gt;setattribute(constant("pdo::" . $k), constant("pdo::" . $v)); } $version_server = self::$pdns_db-&gt;getattribute(pdo::attr_server_version); $sql_mode = 'no_engine_substitution'; (version_compare($version_server, '8.0.11', '&lt;')) { $sql_mode .= ',no_auto_create_user'; } self::$pdns_db-&gt;exec('set sql_mode = "' . $sql_mode . '"'); } }</file><file name="lib/Froxlor/Dns/DnsZone.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\dns; use froxlor\settings; class dnszone { public int $ttl; public string $origin; public string $serial; public ?array $records; /** * @param int $ttl * @param string $origin * @param string $serial * @param array|null $records */ public function __construct(int $ttl = 0, string $origin = '', string $serial = '', array $records = null) { $this-&gt;ttl = ($ttl &lt;= 0 ? settings::get('system.defaultttl') : $ttl); $this-&gt;origin = $origin; $this-&gt;serial = $serial; $this-&gt;records = $records; } public function __tostring() { $zone_file = "\$ttl " . $this-&gt;ttl . php_eol; $zone_file .= "\$origin " . $this-&gt;origin . "." . php_eol; (!empty($this-&gt;records)) { foreach ($this-&gt;records $record) { $zone_file .= (string)$record; } } return $zone_file; } }</file><file name="lib/Froxlor/Dns/DnsEntry.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\dns; use froxlor\settings; class dnsentry { public string $record; public int $ttl; public string $class = 'in'; public string $type; public int $priority; public ?string $content; /** * @param string $record * @param string $type * @param string|null $content * @param int $prio * @param int $ttl * @param string $class */ public function __construct(string $record = '', string $type = 'a', string $content = null, int $prio = 0, int $ttl = 0, string $class = 'in') { $this-&gt;record = $record; $this-&gt;type = $type; $this-&gt;content = $content; $this-&gt;priority = $prio; $this-&gt;ttl = ($ttl &lt;= 0 ? settings::get('system.defaultttl') : $ttl); $this-&gt;class = $class; } public function __tostring() { $_content = $this-&gt;content; // check content length txt records bind9 (multiline) (settings::get('system.dns_server') != 'pdns' &amp;&amp; $this-&gt;type == 'txt' &amp;&amp; strlen($_content) &gt;= 255) { // split string $_contentlines = str_split($_content, 254); // first line $_l = array_shift($_contentlines); // check starting quote (substr($_l, 0, 1) == '"') { $_l = substr($_l, 1); } $_content = '("' . $_l . '"' . php_eol; $_l = array_pop($_contentlines); // check ending quote (substr($_l, -1) == '"') { $_l = substr($_l, 0, -1); } foreach ($_contentlines $_cl) { // lines $_content .= "\t\t\t\t" . '"' . $_cl . '"' . php_eol; } // last line $_content .= "\t\t\t\t" . '"' . $_l . '")'; } return $this-&gt;record . "\t" . $this-&gt;ttl . "\t" . $this-&gt;class . "\t" . $this-&gt;type . "\t" . (($this-&gt;priority &gt;= 0 &amp;&amp; ($this-&gt;type == 'mx' || $this-&gt;type == 'srv')) ? $this-&gt;priority . "\t" : "") . $_content . php_eol; } }</file><file name="lib/Froxlor/Dns/Dns.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\dns; use froxlor\database\database; use froxlor\idna\idnawrapper; use froxlor\settings; use froxlor\ui\response; use pdo; class dns { /** * @param int $domain_id * @param string $area * @param array $userinfo * * @return string|void * @throws \exception */ public static function getalloweddomainentry(int $domain_id, string $area = 'customer', array $userinfo = []) { $dom_data = [ 'did' =&gt; $domain_id ]; $where_clause = ''; ($area == 'admin') { ((int)$userinfo['customers_see_all'] == 0) { $where_clause = '`adminid` = :uid '; $dom_data['uid'] = $userinfo['userid']; } } else { $where_clause = '`customerid` = :uid `email_only` = "0" '; $dom_data['uid'] = $userinfo['userid']; } $dom_stmt = database::prepare(" select domain, isbinddomain `" . table_panel_domains . "` " . $where_clause . " id = :did "); $domain = database::pexecute_first($dom_stmt, $dom_data); ($domain) { ($domain['isbinddomain'] != '1') { response::standarderror('dns_domain_nodns'); } $idna_convert = new idnawrapper(); return $idna_convert-&gt;decode($domain['domain']); } response::standarderror('dns_notfoundorallowed'); } /** * @param int|array $domain_id id domain case froxlorhostname, domain-array needed data * @param bool $froxlorhostname * @param bool $ismainbutsubto * * @return dnszone|void * @throws \exception */ public static function createdomainzone($domain_id, bool $froxlorhostname = false, bool $ismainbutsubto = false) { (!$froxlorhostname) { // get domain-name $dom_stmt = database::prepare("select * `" . table_panel_domains . "` id = :did"); $domain = database::pexecute_first($dom_stmt, [ 'did' =&gt; $domain_id ]); } else { $domain = $domain_id; } (!isset($domain['isbinddomain']) || $domain['isbinddomain'] != '1') { return; } $dom_entries = []; (!$froxlorhostname) { // select entries $sel_stmt = database::prepare("select * `" . table_domain_dns . "` domain_id = :did order id asc"); database::pexecute($sel_stmt, [ 'did' =&gt; $domain_id ]); $dom_entries = $sel_stmt-&gt;fetchall(pdo::fetch_assoc); } // check required records $required_entries = []; self::addrequiredentry('@', 'a', $required_entries); self::addrequiredentry('@', 'aaaa', $required_entries); (!$ismainbutsubto) { self::addrequiredentry('@', 'ns', $required_entries); } ($domain['isemaildomain'] == '1') { self::addrequiredentry('@', 'mx', $required_entries); (settings::get('system.dns_createmailentry')) { foreach (['imap', 'pop3', 'mail', 'smtp' ] $record ) { foreach (['aaaa', 'a' ] $type ) { self::addrequiredentry($record, $type, $required_entries); } } } } // additional required records setting ($domain['iswildcarddomain'] == '1') { self::addrequiredentry('*', 'a', $required_entries); self::addrequiredentry('*', 'aaaa', $required_entries); } elseif ($domain['wwwserveralias'] == '1') { self::addrequiredentry('www', 'a', $required_entries); self::addrequiredentry('www', 'aaaa', $required_entries); } (!$froxlorhostname) { // additional required records subdomains $subdomains_stmt = database::prepare(" select `domain`, `iswildcarddomain`, `wwwserveralias`, `isemaildomain` `" . table_panel_domains . "` `parentdomainid` = :domainid "); database::pexecute($subdomains_stmt, [ 'domainid' =&gt; $domain_id ]); ($subdomain = $subdomains_stmt-&gt;fetch(pdo::fetch_assoc)) { $sub_record = str_replace('.' . $domain['domain'], '', $subdomain['domain']); // listing domains enough currently support choosing // different ips subdomain =&gt; use ips toplevel self::addrequiredentry($sub_record, 'a', $required_entries); self::addrequiredentry($sub_record, 'aaaa', $required_entries); // check whether add www.-prefix ($subdomain['iswildcarddomain'] == '1') { self::addrequiredentry('*.' . $sub_record, 'a', $required_entries); self::addrequiredentry('*.' . $sub_record, 'aaaa', $required_entries); } elseif ($subdomain['wwwserveralias'] == '1') { self::addrequiredentry('www.' . $sub_record, 'a', $required_entries); self::addrequiredentry('www.' . $sub_record, 'aaaa', $required_entries); } // check email ability ($subdomain['isemaildomain'] == '1') { (settings::get('spf.use_spf') == '1') { // check spf content later self::addrequiredentry('@spf@.' . $sub_record, 'txt', $required_entries); } (settings::get('dmarc.use_dmarc') == '1') { // check dmarc content later self::addrequiredentry('@dmarc@.' . $sub_record, 'txt', $required_entries); } (settings::get('antispam.activated') == '1' &amp;&amp; $domain['dkim'] == '1') { // check dkim content later self::addrequiredentry('dkim' . $domain['dkim_id'] . '._domainkey.' . $sub_record, 'txt', $required_entries); } } } } // additional required records caa activated (settings::get('system.dns_createcaaentry') &amp;&amp; settings::get('system.use_ssl') == "1") { $result_stmt = database::prepare(" select i.`ip`, i.`port`, i.`ssl` " . table_panel_ipsandports . " left join " . table_domaintoip . " dip dip.id_ipandports = i.id i.ssl = 1 dip.id_domain = :domainid "); database::pexecute($result_stmt, [ 'domainid' =&gt; $domain['id'] ]); $ssl_ipandports = []; ($ssl_ipandport = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $ssl_ipandports[] = $ssl_ipandport; } (!empty($ssl_ipandports)) { // check caa content later self::addrequiredentry('@caa@', 'caa', $required_entries); } } // additional required records spf dkim activated ($domain['isemaildomain'] == '1') { (settings::get('spf.use_spf') == '1') { // check spf content later self::addrequiredentry('@spf@', 'txt', $required_entries); } (settings::get('dmarc.use_dmarc') == '1') { // check dmarc content later self::addrequiredentry('@dmarc@', 'txt', $required_entries); } (settings::get('antispam.activated') == '1' &amp;&amp; $domain['dkim'] == '1') { // check dkim content later self::addrequiredentry('dkim' . $domain['dkim_id'] . '._domainkey', 'txt', $required_entries); } } $primary_ns = null; $zonerecords = []; // generate records unset required entries foreach ($dom_entries $entry) { (array_key_exists($entry['type'], $required_entries) &amp;&amp; array_key_exists( md5($entry['record']), $required_entries[$entry['type']]) ) { unset($required_entries[$entry['type']][md5($entry['record'])]); } (settings::get('system.dns_createcaaentry') == '1' &amp;&amp; $entry['type'] == 'caa' &amp;&amp; strtolower(substr($entry['content'], 0, 7 )) == '"v=caa1' ) { // unset special caa required-entry unset($required_entries[$entry['type']][md5("@caa@")]); } (settings::get('spf.use_spf') == '1' &amp;&amp; $entry['type'] == 'txt' &amp;&amp; (strtolower(substr($entry['content'], 0, 7)) == '"v=spf1' || strtolower(substr($entry['content'], 0, 6)) == 'v=spf1') ) { // unset special spf required-entry ($entry['record'] == '@') { unset($required_entries[$entry['type']][md5("@spf@")]); } else { // subdomain unset($required_entries[$entry['type']][md5("@spf@." . $entry['record'])]); } } (settings::get('dmarc.use_dmarc') == '1' &amp;&amp; $entry['type'] == 'txt' &amp;&amp; ($entry['record'] == '_dmarc' || substr($entry['record'], 0, 7) == '_dmarc.') &amp;&amp; (strtolower(substr($entry['content'], 0, 9)) == '"v=dmarc1' || strtolower(substr($entry['content'], 0, 8)) == 'v=dmarc1') ) { // unset special dmarc required-entry ($entry['record'] == '_dmarc') { unset($required_entries[$entry['type']][md5("@dmarc@")]); } else { // subdomain unset($required_entries[$entry['type']][md5("@dmarc@" . substr($entry['record'], 6))]); } } (empty($primary_ns) &amp;&amp; $entry['record'] == '@' &amp;&amp; $entry['type'] == 'ns') { // use first ns entry pertaining current domain primary ns $primary_ns = $entry['content']; } // check cname @, www- wildcard-alias remove a/aaaa record accordingly foreach (['@', 'www', '*'] $crecord) { ($entry['type'] == 'cname' &amp;&amp; $entry['record'] == '@' &amp;&amp; (array_key_exists(md5($crecord), $required_entries['a']) || array_key_exists(md5($crecord), $required_entries['aaaa'])) ) { unset($required_entries['a'][md5($crecord)]); unset($required_entries['aaaa'][md5($crecord)]); } } // also allow overriding auto-generated values (imap,pop3,mail,smtp) enabled settings (settings::get('system.dns_createmailentry')) { foreach (['imap', 'pop3', 'mail', 'smtp'] $crecord) { ($entry['type'] == 'cname' &amp;&amp; $entry['record'] == $crecord &amp;&amp; (array_key_exists(md5($crecord), $required_entries['a']) || array_key_exists(md5($crecord), $required_entries['aaaa'])) ) { unset($required_entries['a'][md5($crecord)]); unset($required_entries['aaaa'][md5($crecord)]); } } } $zonerecords[] = new dnsentry($entry['record'], $entry['type'], $entry['content'], $entry['prio'] ?? 0, $entry['ttl']); } // add missing required entries (!empty($required_entries)) { // / aaaa records (array_key_exists("a", $required_entries) || array_key_exists("aaaa", $required_entries)) { ($froxlorhostname) { // use available ip's froxlor-hostname $result_ip_stmt = database::prepare(" select `ip` `" . table_panel_ipsandports . "` group `ip` "); database::pexecute($result_ip_stmt); } else { $result_ip_stmt = database::prepare(" select `p`.`ip` `ip` `" . table_panel_ipsandports . "` `p`, `" . table_domaintoip . "` `di` `di`.`id_domain` = :domainid `p`.`id` = `di`.`id_ipandports` group `p`.`ip`; "); database::pexecute($result_ip_stmt, [ 'domainid' =&gt; $domain_id ]); } $all_ips = $result_ip_stmt-&gt;fetchall(pdo::fetch_assoc); foreach ($all_ips $ip) { foreach ($required_entries $type =&gt; $records) { foreach ($records $record) { ($type == 'a' &amp;&amp; filter_var($ip['ip'], filter_validate_ip, filter_flag_ipv4) !== false) { $zonerecords[] = new dnsentry($record, 'a', $ip['ip']); } elseif ($type == 'aaaa' &amp;&amp; filter_var($ip['ip'], filter_validate_ip, filter_flag_ipv6 ) !== false) { $zonerecords[] = new dnsentry($record, 'aaaa', $ip['ip']); } } } } unset($required_entries['a']); unset($required_entries['aaaa']); } // ns records (array_key_exists("ns", $required_entries)) { (settings::get('system.nameservers') != '') { $nameservers = explode(',', settings::get('system.nameservers')); foreach ($nameservers $nameserver) { $nameserver = trim($nameserver); // append dot hostname (substr($nameserver, -1, 1) != '.') { $nameserver .= '.'; } foreach ($required_entries $type =&gt; $records) { ($type == 'ns') { foreach ($records $record) { (empty($primary_ns)) { // use first ns entry primary ns $primary_ns = $nameserver; } $zonerecords[] = new dnsentry($record, 'ns', $nameserver); } } } } unset($required_entries['ns']); } } // mx records (array_key_exists("mx", $required_entries)) { (settings::get('system.mxservers') != '') { $mxservers = explode(',', settings::get('system.mxservers')); foreach ($mxservers $mxserver) { $mxserver = trim($mxserver); (substr($mxserver, -1, 1) != '.') { $mxserver .= '.'; } // split prio server $mx_details = explode(" ", $mxserver); (count($mx_details) == 1) { $mx_details[1] = $mx_details[0]; $mx_details[0] = 10; } foreach ($required_entries $type =&gt; $records) { ($type == 'mx') { foreach ($records $record) { $zonerecords[] = new dnsentry($record, 'mx', $mx_details[1], $mx_details[0]); } } } } unset($required_entries['mx']); } } // txt (spf dkim) (array_key_exists("txt", $required_entries)) { $dkim_entries = self::generatedkimentries($domain); foreach ($required_entries $type =&gt; $records) { ($type == 'txt') { foreach ($records $record) { ($record == '@spf@') { // spf main-domain $txt_content = settings::get('spf.spf_entry'); $zonerecords[] = new dnsentry('@', 'txt', self::enclosetxtcontent($txt_content)); } elseif (strlen($record) &gt; 6 &amp;&amp; substr($record, 0, 6) == '@spf@.') { // spf subdomain $txt_content = settings::get('spf.spf_entry'); $sub_record = substr($record, 6); $zonerecords[] = new dnsentry($sub_record, 'txt', self::enclosetxtcontent($txt_content)); } elseif ($record == '@dmarc@') { // dmarc main-domain $txt_content = settings::get('dmarc.dmarc_entry'); $zonerecords[] = new dnsentry('_dmarc', 'txt', self::enclosetxtcontent($txt_content)); } elseif (strlen($record) &gt; 8 &amp;&amp; substr($record, 0, 8) == '@dmarc@.') { // dmarc subdomain $txt_content = settings::get('dmarc.dmarc_entry'); $sub_record = substr($record, 8); $zonerecords[] = new dnsentry('_dmarc.' . $sub_record, 'txt', self::enclosetxtcontent($txt_content)); } elseif (!empty($dkim_entries)) { // dkim entries $dkim_record = 'dkim' . $domain['dkim_id'] . '._domainkey'; ($record == $dkim_record) { // dkim main-domain // check multiline entry $multiline = false; (substr($dkim_entries[0], 0, 1) == '(') { $multiline = true; } $zonerecords[] = new dnsentry($record, 'txt', self::enclosetxtcontent($dkim_entries[0], $multiline)); } elseif (strlen($record) &gt; strlen($dkim_record) &amp;&amp; substr($record, 0, strlen($dkim_record) + 1) == $dkim_record . '.') { // dkim subdomain-domain // check multiline entry $multiline = false; (substr($dkim_entries[0], 0, 1) == '(') { $multiline = true; } $zonerecords[] = new dnsentry($record, 'txt', self::enclosetxtcontent($dkim_entries[0], $multiline)); } } } } } } // caa (array_key_exists("caa", $required_entries)) { foreach ($required_entries $type =&gt; $records) { ($type == 'caa') { foreach ($records $record) { ($record == '@caa@') { $caa_entries = explode(php_eol, settings::get('caa.caa_entry')); $caa_domain = "letsencrypt.org"; (settings::get('system.letsencryptca') == 'buypass' || settings::get('system.letsencryptca') == 'buypass_test') { $caa_domain = "buypass.com"; } ($domain['letsencrypt'] == 1) { (settings::get('system.letsencryptca') == 'zerossl') { $caa_domains = [ "sectigo.com", "trust-provider.com", "usertrust.com", "comodoca.com", "comodo.com" ]; foreach ($caa_domains $caa_domain) { $le_entry = $domain['iswildcarddomain'] == '1' ? '0 issuewild "' . $caa_domain . '"' : '0 issue "' . $caa_domain . '"'; array_push($caa_entries, $le_entry); } } else { $le_entry = $domain['iswildcarddomain'] == '1' ? '0 issuewild "' . $caa_domain . '"' : '0 issue "' . $caa_domain . '"'; array_push($caa_entries, $le_entry); } } foreach ($caa_entries $entry) { (empty($entry)) { continue; } $zonerecords[] = new dnsentry('@', 'caa', $entry); // additional required records subdomain setting ($domain['wwwserveralias'] == '1') { $zonerecords[] = new dnsentry('www', 'caa', $entry); } } } } } } } } (empty($primary_ns)) { // todo log error: ns given, use system-hostname $primary_ns = settings::get('system.hostname'); } (!$ismainbutsubto) { $date = date('ymd'); $domain['bindserial'] = (preg_match('/^' . $date . '/', $domain['bindserial']) ? $domain['bindserial'] + 1 : $date . '00'); (!$froxlorhostname) { $upd_stmt = database::prepare(" update `" . table_panel_domains . "` set `bindserial` = :serial `id` = :id "); database::pexecute($upd_stmt, [ 'serial' =&gt; $domain['bindserial'], 'id' =&gt; $domain['id'] ]); } // powerdns like multi-line-format $soa_email = settings::get('system.soaemail'); ($soa_email == "") { $soa_email = settings::get('panel.adminmail'); } $soa_content = $primary_ns . " " . self::escapesoaadminmail($soa_email) . " "; $soa_content .= $domain['bindserial'] . " "; // todo now, dummy time-periods $soa_content .= "3600 900 1209600 1200"; $soa_record = new dnsentry('@', 'soa', $soa_content); array_unshift($zonerecords, $soa_record); } $zone = new dnszone( (int)settings::get('system.defaultttl'), $domain['domain'], $domain['bindserial'], $zonerecords ); return $zone; } /** * @param string $record * @param string $type * @param array $required * @return void */ private static function addrequiredentry(string $record = '@', string $type = 'a', array &amp;$required = []) { (!isset($required[$type])) { $required[$type] = []; } $required[$type][md5($record)] = $record; } /** * @param array $domain * @return array */ private static function generatedkimentries(array $domain): array { $zone_dkim = []; (settings::get('antispam.activated') == '1' &amp;&amp; $domain['dkim'] == '1' &amp;&amp; $domain['dkim_pubkey'] != '') { // start $dkim_txt = 'v=dkim1;'; // key $dkim_txt .= 'k=rsa;p=' . trim($domain['dkim_pubkey']) . ';'; // dkim-entry $zone_dkim[] = $dkim_txt; } return $zone_dkim; } /** * @param string $txt_content * @param bool $ismultiline * @return string */ public static function enclosetxtcontent(string $txt_content, bool $ismultiline = false): string { // check txt content enclosed " " (!$ismultiline &amp;&amp; settings::get('system.dns_server') != 'powerdns') { (substr($txt_content, 0, 1) != '"') { $txt_content = '"' . $txt_content; } (substr($txt_content, -1) != '"') { $txt_content .= '"'; } } (settings::get('system.dns_server') == 'powerdns') { // quotation powerdns (substr($txt_content, 0, 1) == '"') { $txt_content = substr($txt_content, 1); } (substr($txt_content, -1) == '"') { $txt_content = substr($txt_content, 0, -1); } } return $txt_content; } /** * @param string $email * @return string */ private static function escapesoaadminmail(string $email): string { $mail_parts = explode("@", $email); return str_replace(".", "\.", $mail_parts[0]) . "." . $mail_parts[1] . "."; } }</file><file name="lib/Froxlor/Dns/index.html" /><file name="lib/Froxlor/Idna/IdnaWrapper.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\idna; use algo26\idnaconvert\idnaconvert; use invalidargumentexception; /** * class wrapping specific idna conversion class offering standard interface * * @author michael duergner &lt;michael@duergner.com&gt; (2003-2009) */ class idnawrapper { /** * idna converter use * * @var object */ private $idna_converter; /** * class constructor. * creates new idna converter */ public function __construct() { // instantiate $this-&gt;idna_converter = new idnaconvert(); } /** * encode domain name, email address list one both. * * @param string $to_encode may either single domain name, e single email address list one * separated either ',', ';' ' '. * * @return string returns either single domain name, single email address list one * separated string input. */ public function encode(string $to_encode): string { $to_encode = $this-&gt;isutf8($to_encode) ? $to_encode : mb_convert_encoding($to_encode, 'utf-8'); try { return $this-&gt;idna_converter-&gt;encode($to_encode); } catch (invalidargumentexception $iae) { ($iae-&gt;getcode() == 100) { return $to_encode; } throw $iae; } } /** * check whether string utf-8 encoded * * @param string $string * * @return boolean */ private function isutf8(string $string) { (function_exists("mb_detect_encoding")) { (mb_detect_encoding($string, 'utf-8, iso-8859-1') === 'utf-8') { return true; } return false; } $strlen = strlen($string); ($i = 0; $i &lt; $strlen; $i++) { $ord = ord($string[$i]); ($ord &lt; 0x80) { continue; // 0bbbbbbb } elseif (($ord &amp; 0xe0) === 0xc0 &amp;&amp; $ord &gt; 0xc1) { $n = 1; // 110bbbbb (exkl c0-c1) } elseif (($ord &amp; 0xf0) === 0xe0) { $n = 2; // 1110bbbb } elseif (($ord &amp; 0xf8) === 0xf0 &amp;&amp; $ord &lt; 0xf5) { $n = 3; // 11110bbb (exkl f5-ff) } else { // ungltiges utf-8-zeichen return false; } // $n folgebytes? // 10bbbbbb ($c = 0; $c &lt; $n; $c++) { (++$i === $strlen || (ord($string[$i]) &amp; 0xc0) !== 0x80) { // ungltiges utf-8-zeichen return false; } } } // kein ungltiges utf-8-zeichen gefunden return true; } /** * decode domain name, email address list one both. * * @param string $to_decode may either single domain name, e single email address list one * separated either ',', ';' ' '. * * @return string returns either single domain name, single email address list one * separated string input. */ public function decode(string $to_decode): string { return $this-&gt;idna_converter-&gt;decode($to_decode); } }</file><file name="lib/Froxlor/Idna/index.html" /><file name="lib/Froxlor/Validate/Validate.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\validate; use exception; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\idna\idnawrapper; use froxlor\system\iptools; use froxlor\ui\response; class validate { const regex_dir = '/^|(\/[\w-]+)+$/'; const regex_port = '/^(([1-9])|([1-9][0-9])|([1-9][0-9][0-9])|([1-9][0-9][0-9][0-9])|([1-5][0-9][0-9][0-9][0-9])|(6[0-4][0-9][0-9][0-9])|(65[0-4][0-9][0-9])|(655[0-2][0-9])|(6553[0-5]))$/di'; const regex_conf_text = '/^[^\0]*$/'; const regex_desc_text = '/^[^\0\r\n&lt;&gt;]*$/'; const regex_yyyy_mm_dd = '/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/'; /** * validates given string matching pattern, prints error failure exits. * default pattern used string match, try replace 'bad' values log action. * * @param string $str string tested (user input) * @param string $fieldname used error messages * @param string $pattern regular expression used testing * @param string|array $lng id error * @param string|array $emptydefault fallback value * @param bool $throw_exception whether display error throw exception, default false * * @return string|void clean string error * @throws exception */ public static function validate( string $str, string $fieldname, string $pattern = '', $lng = '', $emptydefault = [], bool $throw_exception = false ) { (!is_array($emptydefault)) { $emptydefault_array = [ $emptydefault ]; unset($emptydefault); $emptydefault = $emptydefault_array; unset($emptydefault_array); } // check $str one values represent default 'empty' value (is_array($emptydefault) &amp;&amp; !empty($emptydefault) &amp;&amp; in_array($str, $emptydefault)) { return $str; } ($pattern == '') { $pattern = '/^[^\r\n\t\f\0]*$/d'; (!preg_match($pattern, $str)) { // allows letters a-z, digits, space (\\040), hyphen (\\-), underscore (\\_) backslash (\\\\), // everything else removed string. $allowed = "/[^a-z0-9\\040\\.\\-\\_\\\\]/i"; $str = preg_replace($allowed, "", $str); $log = froxlorlogger::getinstanceof(); $log-&gt;logaction(froxlorlogger::usr_action, log_warning, "cleaned bad formatted string (" . $str . ")"); } } (preg_match($pattern, $str)) { return $str; } ($lng == '') { $lng = 'stringformaterror'; } response::standarderror($lng, $fieldname, $throw_exception); } /** * checks whether valid ip * * @param string $ip ip-address check * @param bool $return_bool whether return bool call \froxlor\ui\response::standard_error() * @param string $lng index error-message (if $return_bool false) * @param bool $allow_localhost whether allow 127.0.0.1 * @param bool $allow_priv whether allow private network addresses * @param bool $allow_cidr whether allow cidr values e.g. 10.10.10.10/16 * @param bool $cidr_as_netmask whether format cidr notation netmask notation * @param bool $throw_exception whether throw exception failure * * @return string|bool|void ip address success, false failure (or nothing error displayed) * @throws exception */ public static function validate_ip2( string $ip, bool $return_bool = false, string $lng = 'invalidip', bool $allow_localhost = false, bool $allow_priv = false, bool $allow_cidr = false, bool $cidr_as_netmask = false, bool $throw_exception = false ) { $cidr = ""; ($allow_cidr) { $org_ip = $ip; $ip_cidr = explode("/", $ip); (count($ip_cidr) === 2) { $cidr_range_max = 32; (iptools::is_ipv6($ip_cidr[0])) { $cidr_range_max = 128; } (strlen($ip_cidr[1]) &lt;= 3 &amp;&amp; in_array((int)$ip_cidr[1], array_values(range(1, $cidr_range_max)), true) === false) { ($return_bool) { return false; } response::standarderror($lng, $ip, $throw_exception); } ($cidr_as_netmask &amp;&amp; iptools::is_ipv6($ip_cidr[0])) { // mysql handle cidr ipv6 addresses, return error ($return_bool) { return false; } response::standarderror($lng, $ip, $throw_exception); } $ip = $ip_cidr[0]; ($cidr_as_netmask &amp;&amp; strlen($ip_cidr[1]) &lt;= 3) { $ip_cidr[1] = iptools::cidr2netmaskaddr($org_ip); } $cidr = "/" . $ip_cidr[1]; } else { $ip = $org_ip; } } elseif (strpos($ip, "/") !== false) { ($return_bool) { return false; } response::standarderror($lng, $ip, $throw_exception); } $filter_lan = $allow_priv ? filter_flag_no_res_range : (filter_flag_no_res_range | filter_flag_no_priv_range); ((filter_var($ip, filter_validate_ip, filter_flag_ipv6) || filter_var($ip, filter_validate_ip, filter_flag_ipv4)) &amp;&amp; filter_var($ip, filter_validate_ip, $filter_lan)) { return $ip . $cidr; } // special case localhost ip allowed (mysql-access-hosts example) ($allow_localhost &amp;&amp; ($ip == '127.0.0.1' || $ip == '::1')) { return $ip . $cidr; } ($return_bool) { return false; } response::standarderror($lng, $ip, $throw_exception); } /** * returns whether url correct format * * @param string $url url tested * @param bool $allow_private_ip optional, default false * * @return bool */ public static function validateurl(string $url, bool $allow_private_ip = false): bool { (strtolower(substr($url, 0, 7)) != "http://" &amp;&amp; strtolower(substr($url, 0, 8)) != "https://") { $url = 'http://' . $url; } // needs converting try { $idna_convert = new idnawrapper(); $url = $idna_convert-&gt;encode($url); } catch (exception $e) { return false; } ($allow_private_ip) { $pattern = '%^(?:(?:https?):\/\/)(?:\s+(?::\s*)?@)?(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$%ius'; } else { $pattern = '%^(?:(?:https?):\/\/)(?:\s+(?::\s*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$%ius'; } (preg_match($pattern, $url)) { return true; } return false; } /** * check submitted string valid domainname * * @param string $domainname domainname checked. * @param bool $allow_underscore optional true, allows underscore character domain label (dkim etc.) * * @return string|boolean domain-name domain valid, false otherwise */ public static function validatedomain(string $domainname, bool $allow_underscore = false) { $char_validation = '([a-z\d](-*[a-z\d])*)(\.?([a-z\d](-*[a-z\d])*))*\.(xn\-\-)?([a-z\d])+'; ($allow_underscore) { $char_validation = '([a-z\d\_](-*[a-z\d\_])*)(\.([a-z\d\_](-*[a-z\d])*))*(\.?([a-z\d](-*[a-z\d])*))+\.(xn\-\-)?([a-z\d])+'; } // valid chars check &amp;&amp; overall length check &amp;&amp; length label (preg_match("/^" . $char_validation . "$/i", $domainname) &amp;&amp; preg_match("/^.{1,253}$/", $domainname) &amp;&amp; preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domainname)) { return $domainname; } return false; } /** * validate local-hostname regex * * @param string $hostname * * @return string|boolean hostname success, else false */ public static function validatelocalhostname(string $hostname) { $pattern = '/^[a-z0-9][a-z0-9\-]{0,62}$/i'; (preg_match($pattern, $hostname)) { return $hostname; } return false; } /** * returns email-address correct format * * @param string $email email address check * * @return mixed */ public static function validateemail(string $email) { $email = strtolower($email); // php-7.1 (defined('filter_flag_email_unicode')) { return filter_var($email, filter_validate_email, filter_flag_email_unicode); } return filter_var($email, filter_validate_email); } /** * returns username correct format not. * * @param string $username username check * @param bool $unix_names optional, default true, checks whether must unix compatible * @param int $mysql_max optional, number max mysql username characters, default empty * * @return bool */ public static function validateusername(string $username, bool $unix_names = true, int $mysql_max = 0): bool { (empty($mysql_max) || $mysql_max &lt;= 0) { $mysql_max = database::getsqlusernamelength() - 1; } else { $mysql_max--; } (!$unix_names) { (strpos($username, '--') === false) { return (preg_match('/^[a-z][a-z0-9\-_]{0,' . $mysql_max . '}[a-z0-9]{1}$/di', $username) != false); } return false; } return (preg_match('/^[a-z][a-z0-9]{0,' . $mysql_max . '}$/di', $username) != false); } /** * validate sql interval string * * @param string $interval * * @return bool */ public static function validatesqlinterval(string $interval = ''): bool { (!empty($interval) &amp;&amp; strstr($interval, ' ') !== false) { /* * [0] = ([0-9]+) * [1] = valid sql-interval expression */ $valid_expr = [ 'second', 'minute', 'hour', 'day', 'week', 'month', 'year' ]; $interval_parts = explode(' ', $interval); (count($interval_parts) == 2 &amp;&amp; preg_match('/[0-9]+/', $interval_parts[0]) &amp;&amp; in_array(strtoupper($interval_parts[1]), $valid_expr)) { return true; } } return false; } /** * validates whether given base64 string decodes image * * @param string $base64string * @return bool * @throws exception */ public static function validatebase64image(string $base64string) { (!extension_loaded('gd')) { response::standarderror('phpgdextensionnotavailable', null, true); } // decode base64 string $data = base64_decode($base64string); // create image decoded data $image = @imagecreatefromstring($data); // check image created successfully (!$image) { return false; } // get mime type image $mime = image_type_to_mime_type(getimagesizefromstring($data)[2]); // check mime type valid image mime type (strpos($mime, 'image/') !== 0) { return false; } // everything okay, return true return true; } }</file><file name="lib/Froxlor/Validate/Form.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\validate; class form { /** * @param array $form * @return bool */ public static function validateformdefinition(array $form): bool { (!empty($form) &amp;&amp; isset($form['groups']) &amp;&amp; is_array($form['groups']) &amp;&amp; !empty($form['groups'])) { return true; } return false; } /** * @param array $field * @return bool */ public static function validatefielddefinition(array $field): bool { (!empty($field) &amp;&amp; isset($field['fields']) &amp;&amp; is_array($field['fields']) &amp;&amp; !empty($field['fields'])) { return true; } return false; } /** * @param $fieldname * @param array $fielddata * @param $newfieldvalue * @return mixed|string */ public static function validateformfield($fieldname, array $fielddata, $newfieldvalue) { $returnvalue = ''; (isset($fielddata['type']) &amp;&amp; $fielddata['type'] != '' &amp;&amp; method_exists('\\froxlor\\validate\\form\\data', 'validateformfield' . ucfirst($fielddata['type']))) { $returnvalue = call_user_func([ '\\froxlor\\validate\\form\\data', 'validateformfield' . ucfirst($fielddata['type']) ], $fieldname, $fielddata, $newfieldvalue); } else { $returnvalue = 'validation method found'; } return $returnvalue; } }</file><file name="lib/Froxlor/Validate/Check.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\validate; use froxlor\database\database; use froxlor\filedir; use froxlor\settings; use froxlor\ui\request; class check { const formfields_plausibility_check_ok = 0; const formfields_plausibility_check_error = 1; const formfields_plausibility_check_question = 2; /** * @param $fieldname * @param $fielddata * @param $newfieldvalue * @param $allnewfieldvalues * @return array|int[] */ public static function checkfcgidphpfpm($fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues) { $returnvalue = [ self::formfields_plausibility_check_ok ]; $check_array = [ 'system_mod_fcgid' =&gt; [ 'other_post_field' =&gt; 'phpfpm_enabled', 'other_enabled' =&gt; 'phpfpm.enabled', 'other_enabled_lng' =&gt; 'phpfpmstillenabled', 'deactivate' =&gt; [ 'phpfpm.enabled_ownvhost' =&gt; 0 ] ], 'phpfpm_enabled' =&gt; [ 'other_post_field' =&gt; 'system_mod_fcgid', 'other_enabled' =&gt; 'system.mod_fcgid', 'other_enabled_lng' =&gt; 'fcgidstillenabled', 'deactivate' =&gt; [ 'system.mod_fcgid_ownvhost' =&gt; 0 ] ] ]; // interface enabled ((int)$newfieldvalue == 1) { // check post value field == 1 (active) ((int)request::post($check_array[$fieldname]['other_post_field'], 0) == 1) { // interface activated already stays activated ((int)settings::get($check_array[$fieldname]['other_enabled']) == 1) { $returnvalue = [ self::formfields_plausibility_check_error, $check_array[$fieldname]['other_enabled_lng'] ]; } else { // fcgid validated fpm -&gt; "ask" fpm state ($fieldname == 'system_mod_fcgid_enabled') { $returnvalue = self::checkfcgidphpfpm( 'system_phpfpm_enabled', null, $check_array[$fieldname]['other_post_field'], null ); } else { // not, bot nogo $returnvalue = $returnvalue = [ self::formfields_plausibility_check_error, 'fcgidandphpfpmnogoodtogether' ]; } } } elseif ((int)settings::get($check_array[$fieldname]['other_enabled']) == 1) { // post still need check whether one's enabled $returnvalue = [ self::formfields_plausibility_check_error, $check_array[$fieldname]['other_enabled_lng'] ]; } (in_array(self::formfields_plausibility_check_ok, $returnvalue)) { // sure deactivate one froxlor-vhost // avoid settings-deadlock foreach ($check_array[$fieldname]['deactivate'] $setting =&gt; $value) { settings::set($setting, $value, true); } } } return $returnvalue; } public static function checkmysqlaccesshost($fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues) { $mysql_access_host_array = array_unique(array_map('trim', explode(',', $newfieldvalue))); foreach ($mysql_access_host_array $host_entry) { (validate::validate_ip2( $host_entry, true, 'invalidip', true, true, true, true, false ) == false &amp;&amp; validate::validatedomain($host_entry) == false &amp;&amp; validate::validatelocalhostname($host_entry) == false &amp;&amp; $host_entry != '%') { return [ self::formfields_plausibility_check_error, 'invalidmysqlhost', $host_entry ]; } } return [ self::formfields_plausibility_check_ok ]; } /** * @param $fieldname * @param $fielddata * @param $newfieldvalue * @param $allnewfieldvalues * @return array|int[] */ public static function checkhostname($fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues) { (0 == strlen(trim($newfieldvalue)) || validate::validatedomain($newfieldvalue) === false) { return [ self::formfields_plausibility_check_error, 'invalidhostname' ]; } else { return [ self::formfields_plausibility_check_ok ]; } } /** * check whether email account deleted * reference: #1519 * * @param string $email_addr * * @return bool true domain deleted, false otherwise * @throws \exception */ public static function checkmailaccdeletionstate(string $email_addr): bool { // example data task 7: a:2:{s:9:"loginname";s:4:"webx";s:5:"email";s:20:"deleteme@example.tld";} // check task $result_tasks_stmt = database::prepare(" select * `" . table_panel_tasks . "` `type` = '7' `data` like :emailaddr "); database::pexecute($result_tasks_stmt, [ 'emailaddr' =&gt; "%" . $email_addr . "%" ]); $num_results = database::num_rows(); // task deleting email account? ($num_results &gt; 0) { return true; } return false; } /** * @param $fieldname * @param $fielddata * @param $newfieldvalue * @param $allnewfieldvalues * @return array|int[] * @throws \exception */ public static function checkpathconflicts($fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues) { ((int)settings::get('system.mod_fcgid') == 1) { // fcgid-configdir changed -&gt; check customer-doc-prefix ($fieldname == "system_mod_fcgid_configdir") { $newdir = filedir::makecorrectdir($newfieldvalue); $cdir = filedir::makecorrectdir(settings::get('system.documentroot_prefix')); } elseif ($fieldname == "system_documentroot_prefix") { // customer-doc-prefix changed -&gt; check fcgid-configdir $newdir = filedir::makecorrectdir($newfieldvalue); $cdir = filedir::makecorrectdir(settings::get('system.mod_fcgid_configdir')); } // neither dir within equal (substr($newdir, 0, strlen($cdir)) == $cdir || substr( $cdir, 0, strlen($newdir) ) == $newdir || $newdir == $cdir) { $returnvalue = [ self::formfields_plausibility_check_error, 'fcgidpathcannotbeincustomerdoc' ]; } else { $returnvalue = [ self::formfields_plausibility_check_ok ]; } } else { $returnvalue = [ self::formfields_plausibility_check_ok ]; } return $returnvalue; } /** * @param $fieldname * @param $fielddata * @param $newfieldvalue * @param $allnewfieldvalues * @return array|int[] */ public static function checkphpinterfacesetting($fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues) { $returnvalue = [ self::formfields_plausibility_check_ok ]; ((int)settings::get('system.mod_fcgid') == 1) { // fcgid works apache lighttpd (strtolower($newfieldvalue) != 'apache2' &amp;&amp; strtolower($newfieldvalue) != 'lighttpd') { $returnvalue = [ self::formfields_plausibility_check_error, 'fcgidstillenableddeadlock' ]; } } return $returnvalue; } /** * @param $fieldname * @param $fielddata * @param $newfieldvalue * @param $allnewfieldvalues * @return array|int[] */ public static function checkusername($fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues) { (!isset($allnewfieldvalues['customer_mysqlprefix'])) { $allnewfieldvalues['customer_mysqlprefix'] = settings::get('customer.mysqlprefix'); } $returnvalue = []; (validate::validateusername( $newfieldvalue, settings::get('panel.unix_names'), database::getsqlusernamelength() - strlen($allnewfieldvalues['customer_mysqlprefix']) ) === true) { $returnvalue = [ self::formfields_plausibility_check_ok ]; } else { $errmsg = 'accountprefixiswrong'; ($fieldname == 'customer_mysqlprefix') { $errmsg = 'mysqlprefixiswrong'; } $returnvalue = [ self::formfields_plausibility_check_error, $errmsg ]; } return $returnvalue; } /** * @param $fieldname * @param $fielddata * @param $newfieldvalue * @param $allnewfieldvalues * @return array|int[] */ public static function checklocalgroup($fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues) { (empty($newfieldvalue) || $fielddata['value'] == $newfieldvalue) { $returnvalue = [ self::formfields_plausibility_check_ok ]; } elseif (function_exists('posix_getgrnam') &amp;&amp; posix_getgrnam($newfieldvalue) == false) { (validate::validateusername($newfieldvalue, settings::get('panel.unix_names'), 32)) { $returnvalue = [ self::formfields_plausibility_check_ok ]; } else { $returnvalue = [ self::formfields_plausibility_check_error, 'local_group_invalid' ]; } } else { $returnvalue = [ self::formfields_plausibility_check_error, 'local_group_exists' ]; } return $returnvalue; } public static function checkpgppublickeysetting($fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues) { // field empty, need check anything ($newfieldvalue === '') { return [self::formfields_plausibility_check_ok]; } // check gnupg extension loaded (!extension_loaded('gnupg')) { return [ self::formfields_plausibility_check_error, 'gnupgextensionnotavailable' ]; } // check pgp public key valid key putenv('gnupghome=' . sys_get_temp_dir()); (gnupg_import(gnupg_init(), $newfieldvalue) === false) { return [ self::formfields_plausibility_check_error, 'invalidpgppublickey' ]; } return [self::formfields_plausibility_check_ok]; } }</file><file name="lib/Froxlor/Validate/index.html" /><file name="lib/Froxlor/Validate/Form/Data.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\validate\form; use froxlor\filedir; use froxlor\validate\validate; class data { public static function validateformfieldtext($fieldname, $fielddata, $newfieldvalue) { return self::validateformfieldstring($fieldname, $fielddata, $newfieldvalue); } public static function validateformfieldpassword($fieldname, $fielddata, $newfieldvalue) { return self::validateformfieldstring($fieldname, $fielddata, $newfieldvalue); } public static function validateformfieldstring($fieldname, $fielddata, $newfieldvalue) { (isset($fielddata['string_delimiter']) &amp;&amp; $fielddata['string_delimiter'] != '') { $newfieldvalues = array_map('trim', explode($fielddata['string_delimiter'], $newfieldvalue)); unset($fielddata['string_delimiter']); $returnvalue = true; foreach ($newfieldvalues $single_newfieldvalue) { /** * use tabs value-fields, #81 */ $single_newfieldvalue = str_replace("\t", " ", $single_newfieldvalue); $single_returnvalue = self::validateformfieldstring($fieldname, $fielddata, $single_newfieldvalue); ($single_returnvalue !== true) { $returnvalue = $single_returnvalue; break; } } } else { $returnvalue = false; /** * use tabs value-fields, #81 */ $newfieldvalue = str_replace("\t", " ", $newfieldvalue); (isset($fielddata['string_type']) &amp;&amp; $fielddata['string_type'] == 'mail') { $returnvalue = validate::validateemail($newfieldvalue); } elseif (isset($fielddata['string_type']) &amp;&amp; $fielddata['string_type'] == 'url') { $returnvalue = validate::validateurl($newfieldvalue); } elseif (isset($fielddata['string_type']) &amp;&amp; $fielddata['string_type'] == 'dir') { // check empty value (it might allowed) (trim($newfieldvalue) == '') { $newfieldvalue = ''; $returnvalue = 'stringmustntbeempty'; } else { // add trailing slash validate path needed // refs #331 (substr($newfieldvalue, -1) != '/') { $newfieldvalue .= '/'; } $returnvalue = ($newfieldvalue == filedir::makecorrectdir($newfieldvalue)); } } elseif (isset($fielddata['string_type']) &amp;&amp; $fielddata['string_type'] == 'confdir') { // check empty value (it might allowed) (trim($newfieldvalue) == '') { $newfieldvalue = ''; $returnvalue = 'stringmustntbeempty'; } else { // add trailing slash validate path needed // refs #331 (substr($newfieldvalue, -1) != '/') { $newfieldvalue .= '/'; } // configuration directory, check stupidity admins :p (filedir::checkdisallowedpaths($newfieldvalue) !== true) { $newfieldvalue = ''; $returnvalue = 'givendirnotallowed'; } else { $returnvalue = ($newfieldvalue == filedir::makecorrectdir($newfieldvalue)); } } } elseif (isset($fielddata['string_type']) &amp;&amp; $fielddata['string_type'] == 'file') { // check empty value (it might allowed) (trim($newfieldvalue) == '') { $newfieldvalue = ''; $returnvalue = 'stringmustntbeempty'; } else { $returnvalue = ($newfieldvalue == filedir::makecorrectfile($newfieldvalue)); } } elseif (isset($fielddata['string_type']) &amp;&amp; $fielddata['string_type'] == 'filedir') { // check empty value (it might allowed) (trim($newfieldvalue) == '') { $newfieldvalue = ''; $returnvalue = 'stringmustntbeempty'; } else { $returnvalue = (($newfieldvalue == filedir::makecorrectdir($newfieldvalue)) || ($newfieldvalue == filedir::makecorrectfile($newfieldvalue))); } } elseif (isset($fielddata['string_type']) &amp;&amp; $fielddata['string_type'] == 'validate_ip') { // check empty value (it might allowed) (trim($newfieldvalue) == '') { $newfieldvalue = ''; $returnvalue = 'stringmustntbeempty'; } else { $newfieldvalue = validate::validate_ip2($newfieldvalue, true); $returnvalue = ($newfieldvalue !== false ? true : 'invalidip'); } } elseif (isset($fielddata['string_type']) &amp;&amp; $fielddata['string_type'] == 'validate_ip_incl_private') { // check empty value (it might allowed) (trim($newfieldvalue) == '') { $newfieldvalue = ''; $returnvalue = 'stringmustntbeempty'; } else { $newfieldvalue = validate::validate_ip2($newfieldvalue, true, 'invalidip', true, true, true); $returnvalue = ($newfieldvalue !== false ? true : 'invalidip'); } } elseif (preg_match('/^[^\r\n\t\f\0]*$/d', $newfieldvalue)) { $returnvalue = true; } (isset($fielddata['string_regexp']) &amp;&amp; $fielddata['string_regexp'] != '') { (preg_match($fielddata['string_regexp'], $newfieldvalue)) { $returnvalue = true; } else { $returnvalue = false; } } (isset($fielddata['string_emptyallowed']) &amp;&amp; $fielddata['string_emptyallowed'] === true &amp;&amp; $newfieldvalue === '') { $returnvalue = true; } elseif (isset($fielddata['string_emptyallowed']) &amp;&amp; $fielddata['string_emptyallowed'] === false &amp;&amp; $newfieldvalue === '') { $returnvalue = 'stringmustntbeempty'; } } ($returnvalue === true) { return true; } elseif ($returnvalue === false) { return 'stringformaterror'; } else { return $returnvalue; } } public static function validateformfieldemail($fieldname, $fielddata, $newfieldvalue) { $fielddata['string_type'] == 'mail'; return self::validateformfieldstring($fieldname, $fielddata, $newfieldvalue); } public static function validateformfieldurl($fieldname, $fielddata, $newfieldvalue) { $fielddata['string_type'] == 'url'; return self::validateformfieldstring($fieldname, $fielddata, $newfieldvalue); } public static function validateformfieldcheckbox($fieldname, $fielddata, $newfieldvalue) { ($newfieldvalue === '1' || $newfieldvalue === 1 || $newfieldvalue === true || strtolower($newfieldvalue) === 'yes' || strtolower($newfieldvalue) === 'ja' || $newfieldvalue === '0' || $newfieldvalue === 0 || $newfieldvalue === false || strtolower($newfieldvalue) === 'no' || strtolower($newfieldvalue) === 'nein' || strtolower($newfieldvalue) === '') { return true; } else { return 'noboolean'; } } public static function validateformfielddate($fieldname, $fielddata, $newfieldvalue) { ($newfieldvalue == '0000-00-00' || preg_match('/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', $newfieldvalue)) { $returnvalue = true; } else { $returnvalue = false; } return $returnvalue; } public static function validateformfieldfile($fieldname, $fielddata, $newfieldvalue) { return true; } public static function validateformfieldhidden($fieldname, $fielddata, $newfieldvalue) { /** * show error cronjob-timestamps changing * might possible cronjob ran * settings edited (bug #52) */ ($newfieldvalue === $fielddata['value'] || $fieldname == 'system_last_tasks_run' || $fieldname == 'system_last_traffic_run' || $fieldname == 'system_lastcronrun') { return true; } else { return 'hiddenfieldvaluechanged'; } } public static function validateformfieldnumber($fieldname, $fielddata, $newfieldvalue) { (isset($fielddata['min']) &amp;&amp; (int)$newfieldvalue &lt; (int)$fielddata['min']) { return ('intvaluetoolow'); } (isset($fielddata['max']) &amp;&amp; (int)$newfieldvalue &gt; (int)$fielddata['max']) { return ('intvaluetoohigh'); } return true; } public static function validateformfieldselect($fieldname, $fielddata, $newfieldvalue) { $returnvalue = true; (isset($fielddata['select_mode']) &amp;&amp; $fielddata['select_mode'] == 'multiple') { $options = explode(',', $newfieldvalue); foreach ($options $option) { $returnvalue = ($returnvalue &amp;&amp; isset($fielddata['select_var'][$option])); } } else { $returnvalue = isset($fielddata['select_var'][$newfieldvalue]); } ($returnvalue === true || (isset($fielddata['visible']) &amp;&amp; $fielddata['visible'] == false)) { return true; } else { (isset($fielddata['option_emptyallowed']) &amp;&amp; $fielddata['option_emptyallowed']) { return true; } return 'not option (field: ' . $fieldname . ')'; } } public static function validateformfieldtextarea($fieldname, $fielddata, $newfieldvalue) { $returnvalue = 'stringformaterror'; (isset($fielddata['string_regexp']) &amp;&amp; $fielddata['string_regexp'] != '') { (preg_match($fielddata['string_regexp'], $newfieldvalue)) { $returnvalue = true; } } elseif (preg_match('/^[^\0]*$/', $newfieldvalue)) { $returnvalue = true; } return $returnvalue; } public static function validateformfieldimage($fieldname, $fielddata, $newfieldvalue) { // validation handled \froxlor\settings\store::storesettingimage() return true; } }</file><file name="lib/Froxlor/Validate/Form/index.html" /><file name="lib/Froxlor/Config/ConfigParser.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\config; use exception; use simplexmlelement; /** * class configparser * * parses distributions xml - file gives access configuration */ class configparser { /** * name distribution configuration * * @var string */ public $distributionname = ''; /** * codename distribution configuration * * @var string */ public $distributioncodename = ''; /** * version distribution configuration * * @var string */ public $distributionversion = ''; /** * recommended editor * * @var string */ public $distributioneditor = '/bin/nano'; /** * show configuration deprecated * * @var bool */ public $deprecated = false; /** * holding available services xml * * @var array */ private $services = []; /** * holding available defaults xml * * @var array */ private $defaults = []; /** * store parsed simplexmlelement usage * * @var simplexmlelement */ private $xml; /** * memorize already parsed xml * * @var bool */ private $isparsed = false; /** * constructor * * initialize xml - configparser * * @param string $filename * filename froxlor - configurationfile * @return void */ public function __construct($filename) { (!is_readable($filename)) { throw new exception('file readable'); } $this-&gt;xml = simplexml_load_file($filename); ($this-&gt;xml === false) { $error = ''; foreach (libxml_get_errors() $error) { $error .= "\t" . $error-&gt;message; } throw new exception($error); } // let's see find &lt;distribution&gt; block xml $distribution = $this-&gt;xml-&gt;xpath('//distribution'); // distribution found - can't use file (!is_array($distribution)) { throw new exception('invalid xml, distribution found'); } // search attributes understand foreach ($distribution[0]-&gt;attributes() $key =&gt; $value) { switch ((string)$key) { case "name": $this-&gt;distributionname = (string)$value; break; case "version": $this-&gt;distributionversion = (string)$value; break; case "codename": $this-&gt;distributioncodename = (string)$value; break; case "defaulteditor": $this-&gt;distributioneditor = (string)$value; break; case "deprecated": (string)$value == 'true' ? $this-&gt;deprecated = true : $this-&gt;deprecated = false; break; } } } /** * return services defined xml * * array hold configservice - objects handling * * @return array */ public function getservices() { // let's parse shit(!) $this-&gt;parseservices(); // return carefully searched services return $this-&gt;services; } /** * parse xml populate $this-&gt;services * * @return bool */ private function parseservices() { // want parse stuff one time ($this-&gt;isparsed == true) { return true; } // get services $services = $this-&gt;xml-&gt;xpath('//services/service'); foreach ($services $service) { // want comments ($service-&gt;getname() == 'comment') { continue; } // search attributes "type" foreach ($service-&gt;attributes() $key =&gt; $value) { ($key == 'type') { $this-&gt;services[(string)$value] = new configservice($this-&gt;xml, '//services/service[@type="' . (string)$value . '"]'); } } } // switch flag indicate parsed data $this-&gt;isparsed = true; return true; } /** * return defaults defined xml * * array hold configdefaults - objects handling * * @return array */ public function getdefaults() { // let's parse shit(!) $this-&gt;parsedefaults(); // return carefully searched defaults return $this-&gt;defaults; } /** * parse xml populate $this-&gt;services * * @return bool */ private function parsedefaults() { // want parse stuff one time ($this-&gt;isparsed == true) { return true; } // get defaults $defaults = $this-&gt;xml-&gt;xpath('//defaults/default'); foreach ($defaults $default) { $this-&gt;defaults[] = $default; } // switch flag indicate parsed data $this-&gt;isparsed = true; return true; } /** * return complete distribution string "name [codename] [ (version)] [deprecated] * * @return string */ public function getcompletedistroname(): string { // get distro-info $dist_display = $this-&gt;distributionname; ($this-&gt;distributioncodename != '') { $dist_display .= " " . $this-&gt;distributioncodename; } ($this-&gt;distributionversion != '') { $dist_display .= " (" . $this-&gt;distributionversion . ")"; } ($this-&gt;deprecated) { $dist_display .= " [deprecated]"; } return $dist_display; } }</file><file name="lib/Froxlor/Config/ConfigDisplay.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\config; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlor; use froxlor\phphelper; use froxlor\settings; use froxlor\ui\panel\ui; class configdisplay { /** * @var array */ private static $replace_arr; /** * @var string */ private static $editor; /** * @var string */ private static $theme; /** * @param array $confarr * @param string $editor * @param string $theme */ public static function fromconfigarr(array $confarr, string $editor, string $theme) { self::$editor = $editor; self::$theme = $theme; $customer_tmpdir = '/tmp/'; (settings::get('system.mod_fcgid') == '1' &amp;&amp; settings::get('system.mod_fcgid_tmpdir') != '') { $customer_tmpdir = settings::get('system.mod_fcgid_tmpdir'); } elseif (settings::get('phpfpm.enabled') == '1' &amp;&amp; settings::get('phpfpm.tmpdir') != '') { $customer_tmpdir = settings::get('phpfpm.tmpdir'); } // try convert namserver hosts ip's $ns_ips = ""; $known_ns_ips = []; (settings::get('system.nameservers') != '') { $nameservers = explode(',', settings::get('system.nameservers')); foreach ($nameservers $nameserver) { $nameserver = trim($nameserver); // dns servers might multi homed; allow transfer ip // addresses dns server $nameserver_ips = phphelper::gethostbynamel6($nameserver); // append dot hostname (substr($nameserver, -1, 1) != '.') { $nameserver .= '.'; } // ignore invalid responses (!is_array($nameserver_ips)) { // act like \froxlor\phphelper::gethostbynamel6() return unmodified hostname error $nameserver_ips = [ $nameserver ]; } else { $known_ns_ips = array_merge($known_ns_ips, $nameserver_ips); } (!empty($ns_ips)) { $ns_ips .= ','; } $ns_ips .= implode(",", $nameserver_ips); } } // axfr server (settings::get('system.axfrservers') != '') { $axfrservers = explode(',', settings::get('system.axfrservers')); foreach ($axfrservers $axfrserver) { (!in_array(trim($axfrserver), $known_ns_ips)) { (!empty($ns_ips)) { $ns_ips .= ','; } $ns_ips .= trim($axfrserver); } } } database::needsqldata(); $sql = database::getsqldata(); self::$replace_arr = [ '&lt;sql_unprivileged_user&gt;' =&gt; $sql['user'], '&lt;sql_unprivileged_password&gt;' =&gt; 'froxlor_mysql_password', '&lt;sql_db&gt;' =&gt; $sql['db'], '&lt;sql_host&gt;' =&gt; $sql['host'], '&lt;sql_socket&gt;' =&gt; $sql['socket'] ?? null, '&lt;servername&gt;' =&gt; settings::get('system.hostname'), '&lt;serverip&gt;' =&gt; settings::get('system.ipaddress'), '&lt;nameservers&gt;' =&gt; settings::get('system.nameservers'), '&lt;nameservers_ip&gt;' =&gt; $ns_ips, '&lt;virtual_mailbox_base&gt;' =&gt; settings::get('system.vmail_homedir'), '&lt;virtual_uid_maps&gt;' =&gt; settings::get('system.vmail_uid'), '&lt;virtual_gid_maps&gt;' =&gt; settings::get('system.vmail_gid'), '&lt;sslprotocols&gt;' =&gt; (settings::get('system.use_ssl') == '1') ? 'imaps pop3s' : '', '&lt;customer_tmp&gt;' =&gt; filedir::makecorrectdir($customer_tmpdir), '&lt;base_path&gt;' =&gt; froxlor::getinstalldir(), '&lt;bind_config_path&gt;' =&gt; filedir::makecorrectdir(settings::get('system.bindconf_directory')), '&lt;webserver_reload_cmd&gt;' =&gt; settings::get('system.apachereload_command'), '&lt;customer_logs&gt;' =&gt; filedir::makecorrectdir(settings::get('system.logfiles_directory')), '&lt;fpm_ipcdir&gt;' =&gt; filedir::makecorrectdir(settings::get('phpfpm.fastcgi_ipcdir')), '&lt;webserver_group&gt;' =&gt; settings::get('system.httpgroup'), '&lt;ssl_cert_file&gt;' =&gt; settings::get('system.ssl_cert_file'), '&lt;ssl_key_file&gt;' =&gt; settings::get('system.ssl_key_file'), '&lt;admin_mail&gt;' =&gt; settings::get('panel.adminmail'), ]; $commands_pre = ""; $commands_file = ""; $commands_post = ""; $lasttype = ''; $commands = ''; $configpage = ""; foreach ($confarr $_action) { ($lasttype != '' &amp;&amp; $lasttype != $_action['type']) { $commands = trim($commands); $numbrows = count(explode("\n", $commands)); $configpage .= ui::twig()-&gt;render(ui::validatethemetemplate('/settings/conf/command.html.twig', self::$theme), [ 'commands' =&gt; $commands, 'numbrows' =&gt; $numbrows ]); $lasttype = ''; $commands = ''; } switch ($_action['type']) { case "install": $commands .= strtr($_action['content'], self::$replace_arr) . "\n"; $lasttype = "install"; break; case "command": $commands .= strtr($_action['content'], self::$replace_arr) . "\n"; $lasttype = "command"; break; case "file": (array_key_exists('content', $_action)) { $commands_file = self::getfilecontentcontainer($_action['content'], $_action['name']); } elseif (array_key_exists('subcommands', $_action)) { foreach ($_action['subcommands'] $fileaction) { (array_key_exists('execute', $fileaction) &amp;&amp; $fileaction['execute'] == "pre") { $commands_pre .= $fileaction['content'] . "\n"; } elseif (array_key_exists('execute', $fileaction) &amp;&amp; $fileaction['execute'] == "post") { $commands_post .= $fileaction['content'] . "\n"; } elseif ($fileaction['type'] == 'file') { $commands_file = self::getfilecontentcontainer($fileaction['content'], $_action['name']); } } } $realname = $_action['name']; $commands = trim($commands_pre); ($commands != "") { $numbrows = count(explode("\n", $commands)); $commands_pre = ui::twig()-&gt;render(ui::validatethemetemplate('/settings/conf/command.html.twig', self::$theme), [ 'commands' =&gt; $commands, 'numbrows' =&gt; $numbrows ]); } $commands = trim($commands_post); ($commands != "") { $numbrows = count(explode("\n", $commands)); $commands_post = ui::twig()-&gt;render(ui::validatethemetemplate('/settings/conf/command.html.twig', self::$theme), [ 'commands' =&gt; $commands, 'numbrows' =&gt; $numbrows ]); } $configpage .= ui::twig()-&gt;render(ui::validatethemetemplate('/settings/conf/fileblock.html.twig', self::$theme), [ 'realname' =&gt; $realname, 'commands_pre' =&gt; $commands_pre, 'commands_file' =&gt; $commands_file, 'commands_post' =&gt; $commands_post ]); $commands = ''; $commands_pre = ''; $commands_post = ''; break; } } $commands = trim($commands); ($commands != '') { $numbrows = count(explode("\n", $commands)); $configpage .= ui::twig()-&gt;render(ui::validatethemetemplate('/settings/conf/command.html.twig', self::$theme), [ 'commands' =&gt; $commands, 'numbrows' =&gt; $numbrows ]); } return $configpage; } /** * @param string $file_content * @param string $realname * * @return string */ private static function getfilecontentcontainer(string $file_content, string $realname): string { $files = ""; $file_content = trim($file_content); ($file_content != '') { $file_content = strtr($file_content, self::$replace_arr); $file_content = htmlspecialchars($file_content); $numbrows = count(explode("\n", $file_content)); //eval("\$files=\"" . \froxlor\ui\template::gettemplate("configfiles/configfiles_file") . "\";"); $files = ui::twig()-&gt;render(ui::validatethemetemplate('/settings/conf/file.html.twig', self::$theme), [ 'distro_editor' =&gt; self::$editor, 'realname' =&gt; $realname, 'numbrows' =&gt; $numbrows, 'file_content' =&gt; $file_content ]); } return $files; } }</file><file name="lib/Froxlor/Config/ConfigService.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\config; use exception; use froxlor\settings; use simplexmlelement; /** * class configservice * * parses distributions xml - file gives access services within * used directly */ class configservice { /** * human - readable title service * * @var string */ public $title; /** * holding available daemons service * * @var array */ private $daemons = []; /** * store parsed simplexmlelement usage * * @var simplexmlelement */ private $fullxml; /** * memorize already parsed xml * * @var bool */ private $isparsed = false; /** * xpath leading service full xml * * @var string */ private $xpath; public function __construct($xml, $xpath) { $this-&gt;fullxml = $xml; $this-&gt;xpath = $xpath; $service = $this-&gt;fullxml-&gt;xpath($this-&gt;xpath); $attributes = $service[0]-&gt;attributes(); ($attributes['title'] != '') { $this-&gt;title = $this-&gt;parsecontent((string)$attributes['title']); } } /** * replace placeholders content * * @param string $content * @return string $content w/o placeholder */ private function parsecontent($content) { $content = preg_replace_callback('/\{\{(.*)\}\}/ui', function ($matches) { $match = null; (preg_match('/^settings\.(.*)$/', $matches[1], $match)) { return settings::get($match[1]); } elseif (preg_match('/^lng\.(.*)(?:\.(.*)(?:\.(.*)))$/u', $matches[1], $match)) { (isset($match[1]) &amp;&amp; $match[1] != '' &amp;&amp; isset($match[2]) &amp;&amp; $match[2] != '' &amp;&amp; isset($match[3]) &amp;&amp; $match[3] != '') { return lng($match[1] . '.' . $match[2] . '.' . $match[3]); } elseif (isset($match[1]) &amp;&amp; $match[1] != '' &amp;&amp; isset($match[2]) &amp;&amp; $match[2] != '') { return lng($match[1] . '.' . $match[2]); } elseif (isset($match[1]) &amp;&amp; $match[1] != '') { return lng($match[1]); } return ''; } }, $content); return $content; } public function getdaemons() { $this-&gt;parse(); return $this-&gt;daemons; } /** * parse xml populate $this-&gt;daemons * * @return bool */ private function parse() { // want parse stuff one time ($this-&gt;isparsed == true) { return true; } $daemons = $this-&gt;fullxml-&gt;xpath($this-&gt;xpath . '/daemon'); foreach ($daemons $daemon) { ($daemon-&gt;getname() == 'comment') { continue; } $name = ''; $nametag = ''; $versiontag = ''; foreach ($daemon-&gt;attributes() $key =&gt; $value) { ($key == 'name' &amp;&amp; $name == '') { $name = (string)$value; $nametag = "[@name='" . $value . "']"; } elseif ($key == 'name' &amp;&amp; $name != '') { $name = (string)$value . '_' . $name; $nametag = "[@name='" . $value . "']"; } elseif ($key == 'version' &amp;&amp; $name == '') { $name = str_replace('.', '', $value); $versiontag = "[@version='" . $value . "']"; } elseif ($key == 'version' &amp;&amp; $name != '') { $name .= str_replace('.', '', $value); $versiontag = "[@version='" . $value . "']"; } } ($name == '') { throw new exception('no name attribute daemon'); } $this-&gt;daemons[$name] = new configdaemon($this-&gt;fullxml, $this-&gt;xpath . "/daemon" . $nametag . $versiontag); } // switch flag indicate parsed data $this-&gt;isparsed = true; return true; } }</file><file name="lib/Froxlor/Config/ConfigDaemon.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\config; use exception; use froxlor\froxlor; use froxlor\settings; use simplexmlelement; /** * class configdaemon * * parses distributions xml - file gives access configuration * used directly */ class configdaemon { /** * human - readable title service * * @var string */ public $title; /** * whether default daemon service-category * * @var boolean */ public $default; /** * holding commands daemon * * @var array */ private $orders = []; /** * store parsed simplexmlelement usage * * @var simplexmlelement */ private $fullxml; /** * memorize already parsed xml * * @var bool */ private $isparsed = false; /** * sub - area full - xml holding daemon - data interested * * @var simplexmlelement */ private $daemon; /** * xpath leading daemon full xml * * @var string */ private $xpath; /** * cache sql-data used */ private $sqldata_cache = null; public function __construct($xml, $xpath) { $this-&gt;fullxml = $xml; $this-&gt;xpath = $xpath; $this-&gt;daemon = $this-&gt;fullxml-&gt;xpath($this-&gt;xpath); (count($this-&gt;daemon) !== 1) { throw new exception('xpath "' . $this-&gt;xpath . '" didn\'t return exactly one element'); } $attributes = $this-&gt;daemon[0]-&gt;attributes(); ($attributes['title'] != '') { $this-&gt;title = $this-&gt;parsecontent((string)$attributes['title']); } (isset($attributes['default'])) { $this-&gt;default = ($attributes['default'] == true); } } /** * replace placeholders content * * @param string $content * @return string $content w/o placeholder */ private function parsecontent($content) { $content = preg_replace_callback('/\{\{(.*)\}\}/ui', function ($matches) { $match = null; (preg_match('/^settings\.(.*)$/', $matches[1], $match)) { return settings::get($match[1]); } elseif (preg_match('/^lng\.(.*)(?:\.(.*)(?:\.(.*)))$/u', $matches[1], $match)) { (isset($match[1]) &amp;&amp; $match[1] != '' &amp;&amp; isset($match[2]) &amp;&amp; $match[2] != '' &amp;&amp; isset($match[3]) &amp;&amp; $match[3] != '') { return lng($match[1] . '.' . $match[2] . '.' . $match[3]); } elseif (isset($match[1]) &amp;&amp; $match[1] != '' &amp;&amp; isset($match[2]) &amp;&amp; $match[2] != '') { return lng($match[1] . '.' . $match[2]); } elseif (isset($match[1]) &amp;&amp; $match[1] != '') { return lng($match[1]); } return ''; } elseif (preg_match('/^const\.(.*)$/', $matches[1], $match)) { return $this-&gt;returndynamic($match[1]); } elseif (preg_match('/^sql\.(.*)$/', $matches[1], $match)) { (is_null($this-&gt;sqldata_cache)) { // read sql-data (if exists) (file_exists(froxlor::getinstalldir() . "/lib/userdata.inc.php")) { $sql = []; $sql_root = []; require froxlor::getinstalldir() . "/lib/userdata.inc.php"; unset($sql_root); $this-&gt;sqldata_cache = $sql; } } return isset($this-&gt;sqldata_cache[$match[1]]) ? $this-&gt;sqldata_cache[$match[1]] : ''; } }, $content); return $content; } private function returndynamic($key = null) { $dynamics = [ 'install_dir' =&gt; froxlor::getinstalldir() ]; return $dynamics[$key] ?? ''; } /** * get config daemon * * returned array array array, sub-array looking like this: * array('type' =&gt; 'install|file|command', 'content' =&gt; '&lt;text&gt;') * type "file", additional "name" - element added array * configure daemon, steps array must followed order * * @return array */ public function getconfig() { $this-&gt;parse(); return $this-&gt;orders; } /** * parse xml populate $this-&gt;orders * * @return bool */ private function parse() { // want parse stuff one time ($this-&gt;isparsed == true) { return true; } $preparsed = []; // first: let's push everything array expand includes foreach ($this-&gt;daemon[0]-&gt;children() $order) { switch ((string)$order-&gt;getname()) { case "install": case "file": case "command": // normal stuff, add preparsed - array $preparsed[] = $order; break; case "include": // includes, get part want via xpath $includes = $this-&gt;fullxml-&gt;xpath((string)$order); foreach ($includes[0] $include) { // "include" also child, skip it, would make mess later ((string)$include-&gt;getname() == 'include') { continue; } $preparsed[] = $include; } break; // next 3 groupings, &lt;visibility&gt; must come first work properly case "commands": case "files": case "installs": // hold results $visibility = 1; foreach ($order-&gt;children() $child) { switch ((string)$child-&gt;getname()) { case "visibility": $visibility += $this-&gt;checkvisibility($child); break; case "install": case "file": case "command": ($visibility &gt; 0) { $preparsed[] = $child; } break; case "include": // includes, get part want via xpath $includes = $this-&gt;fullxml-&gt;xpath((string)$child); foreach ($includes[0] $include) { // "include" also child, skip it, would make mess later ((string)$include-&gt;getname() == 'include') { continue; } $preparsed[] = $include; } break; } } break; } } // go every preparsed order evaluate happen foreach ($preparsed $order) { $parsedorder = $this-&gt;parseorder($order); // got array (= valid order) array already type -&gt; add stack (is_array($parsedorder) &amp;&amp; array_key_exists('type', $parsedorder)) { $this-&gt;orders[] = $parsedorder; // got array, type, means got multiple orders back, stack one time } elseif (is_array($parsedorder)) { foreach ($parsedorder $neworder) { $this-&gt;orders[] = $neworder; } } } // switch flag indicate parsed data $this-&gt;isparsed = true; return true; } /** * check visibility changed * * @param simplexmlelement $order * @return int 0|-1 */ private function checkvisibility($order) { $attributes = []; foreach ($order-&gt;attributes() $key =&gt; $value) { $attributes[(string)$key] = $this-&gt;parsecontent(trim((string)$value)); } $order = $this-&gt;parsecontent(trim((string)$order)); (!array_key_exists('mode', $attributes)) { throw new exception('"&lt;visibility&gt;' . $order . '&lt;/visibility&gt;" missing mode'); } $return = 0; switch ($attributes['mode']) { case "isfile": (!is_file($order)) { $return = -1; } break; case "notisfile": (is_file($order)) { $return = -1; } break; case "isdir": (!is_dir($order)) { $return = -1; } break; case "notisdir": (is_dir($order)) { $return = -1; } break; case "false": ($order == true) { $return = -1; } break; case "true": ($order == false) { $return = -1; } break; case "notempty": ($order == "") { $return = -1; } break; case "userexists": (posix_getpwuid($order) === false) { $return = -1; } break; case "groupexists": (posix_getgrgid($order) === false) { $return = -1; } break; case "usernotexists": (is_array(posix_getpwuid($order))) { $return = -1; } break; case "groupnotexists": (is_array(posix_getgrgid($order))) { $return = -1; } break; case "usernamenotexists": (is_array(posix_getpwnam($order))) { $return = -1; } break; case "equals": $return = (isset($attributes['value']) &amp;&amp; $attributes['value'] == $order ? 0 : -1); break; } return $return; } /** * parse single order return format easier usage * * @param * simplexmlelement object holding single order distribution - xml * @return array|string */ private function parseorder($order) { $attributes = []; foreach ($order-&gt;attributes() $key =&gt; $value) { $attributes[(string)$key] = (string)$value; } $parsedorder = ''; switch ((string)$order-&gt;getname()) { case "file": $parsedorder = $this-&gt;parsefile($order, $attributes); break; case "command": $parsedorder = $this-&gt;parsecommand($order, $attributes); break; case "install": $parsedorder = $this-&gt;parseinstall($order, $attributes); break; default: throw new exception('invalid order: ' . (string)$order-&gt;getname()); } return $parsedorder; } /** * parse file - order return format easier usage * * @param * simplexmlelement object holding single file distribution - xml * @return array|string */ private function parsefile($order, $attributes) { $visibility = 1; // sub - elements, content returned directly ($order-&gt;count() == 0) { $content = (string)$order; } else { // hold results foreach ($order-&gt;children() $child) { switch ((string)$child-&gt;getname()) { case "visibility": $visibility += $this-&gt;checkvisibility($child); break; case "content": $content = (string)$child; break; } } } $return = []; // check original file backupped // @todo: maybe backup - location somewhere central? // @todo: use io - class (array_key_exists('backup', $attributes)) { (array_key_exists('mode', $attributes) &amp;&amp; $attributes['mode'] == 'append') { $cmd = 'cp'; } else { $cmd = 'mv'; } $return[] = [ 'type' =&gt; 'command', 'content' =&gt; '[ -f ' . $this-&gt;parsecontent($attributes['name']) . ' ] &amp;&amp; ' . $cmd . ' "' . $this-&gt;parsecontent($attributes['name']) . '" "' . $this-&gt;parsecontent($attributes['name']) . '.frx.bak"', 'execute' =&gt; "pre" ]; } // content file written (isset($attributes['mode'])) { $return[] = [ 'type' =&gt; 'file', 'content' =&gt; $this-&gt;parsecontent($content), 'name' =&gt; $this-&gt;parsecontent($attributes['name']), 'mode' =&gt; $this-&gt;parsecontent($attributes['mode']) ]; } else { $return[] = [ 'type' =&gt; 'file', 'content' =&gt; $this-&gt;parsecontent($content), 'name' =&gt; $this-&gt;parsecontent($attributes['name']) ]; } // let's check mode file changed (array_key_exists('chmod', $attributes)) { $return[] = [ 'type' =&gt; 'command', 'content' =&gt; 'chmod ' . $attributes['chmod'] . ' "' . $this-&gt;parsecontent($attributes['name']) . '"', 'execute' =&gt; "post" ]; } // let's check owner file changed (array_key_exists('chown', $attributes)) { $return[] = [ 'type' =&gt; 'command', 'content' =&gt; 'chown ' . $attributes['chown'] . ' "' . $this-&gt;parsecontent($attributes['name']) . '"', 'execute' =&gt; "post" ]; } // 1 element, want group stuff easier processing later (count($return) &gt; 1) { $return = [ 'type' =&gt; 'file', 'subcommands' =&gt; $return, 'name' =&gt; $this-&gt;parsecontent($attributes['name']) ]; } ($visibility &gt; 0) { return $return; } else { return ''; } } /** * parse command - order return format easier usage * * @param * simplexmlelement object holding single command distribution - xml * @return array|string */ private function parsecommand($order, $attributes) { // sub - elements, content returned directly ($order-&gt;count() == 0) { return [ 'type' =&gt; 'command', 'content' =&gt; $this-&gt;parsecontent(trim((string)$order)) ]; } // hold results $visibility = 1; $content = ''; foreach ($order-&gt;children() $child) { switch ((string)$child-&gt;getname()) { case "visibility": $visibility += $this-&gt;checkvisibility($child); break; case "content": $content = trim((string)$child); break; } } ($visibility &gt; 0) { return [ 'type' =&gt; 'command', 'content' =&gt; $this-&gt;parsecontent($content) ]; } else { return ''; } } /** * parse install - order return format easier usage * * @param * simplexmlelement object holding single install distribution - xml * @return array|string */ private function parseinstall($order, $attributes) { // sub - elements, content returned directly ($order-&gt;count() == 0) { return [ 'type' =&gt; 'install', 'content' =&gt; $this-&gt;parsecontent(trim((string)$order)) ]; } // hold results $visibility = 1; $content = ''; foreach ($order-&gt;children() $child) { switch ((string)$child-&gt;getname()) { case "visibility": $visibility += $this-&gt;checkvisibility($child); break; case "content": $content = trim((string)$child); break; } } ($visibility &gt; 0) { return [ 'type' =&gt; 'install', 'content' =&gt; $this-&gt;parsecontent($content) ]; } else { return ''; } } }</file><file name="lib/Froxlor/Config/index.html" /><file name="lib/Froxlor/Bulk/DomainBulkAction.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\bulk; use exception; /** * class domainbulkaction mass-import domains given customer */ class domainbulkaction extends bulkaction { /** * @param string $import_file * @param array $userinfo * * @return domainbulkaction */ public function __construct(string $import_file = null, array $userinfo = []) { parent::__construct($import_file, $userinfo); $this-&gt;setapicall('domains.add'); } /** * import parsed import file data optional separator semicolon * offset (maybe header-line csv similar) * * @param string $separator * @param int $offset * * @return array 'all' =&gt; amount records processed, 'imported' =&gt; number imported records */ public function doimport(string $separator = ";", int $offset = 0) { ($this-&gt;userinfo['domains'] == "-1") { $dom_unlimited = true; } else { $dom_unlimited = false; } $domains_used = (int)$this-&gt;userinfo['domains_used']; $domains_avail = (int)$this-&gt;userinfo['domains']; (!is_int($offset) || $offset &lt; 0) { throw new exception("invalid offset specified"); } try { $domain_array = $this-&gt;parseimportfile($separator); } catch (exception $e) { throw $e; } (count($domain_array) &lt;= 0) { throw new exception("no domains read file."); } $global_counter = 0; $import_counter = 0; $note = ''; foreach ($domain_array $idx =&gt; $dom) { ($idx &gt;= $offset) { ($dom_unlimited || (!$dom_unlimited &amp;&amp; $domains_used &lt; $domains_avail)) { $result = $this-&gt;importentity($dom); ($result) { $import_counter++; $domains_used++; } } else { $note .= 'you reached maximum allocation domains (' . $domains_avail . ').'; break; } } $global_counter++; } return [ 'all' =&gt; $global_counter, 'imported' =&gt; $import_counter, 'notice' =&gt; $note ]; } }</file><file name="lib/Froxlor/Bulk/index.html" /><file name="lib/Froxlor/Bulk/BulkAction.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\bulk; use exception; use froxlor\filedir; /** * abstract class bulkaction mass-import entities * * @author michael kaufmann (d00p) &lt;d00p@froxlor.org&gt; * */ abstract class bulkaction { /** * logged user * * @var array */ protected $userinfo = []; /** * complete path including filename file imported * * @var string */ private $impfile = null; /** * api-function call addingg entity * * @var string */ private $api_call = null; /** * api-function parameter names, read import-file (first line) * * @var array */ private $api_params = null; /** * errors importing * * @var array */ private $errors = []; /** * class constructor, optionally sets file customer-id * * @param string $import_file * @param array $userinfo * * @return object bulkaction instance */ protected function __construct(string $import_file = null, array $userinfo = []) { (!empty($import_file)) { $this-&gt;impfile = filedir::makecorrectfile($import_file); } $this-&gt;userinfo = $userinfo; } /** * import parsed import file data optional separator semicolon * offset (maybe header-line csv similar) * * @param string $separator * @param int $offset * * @return array 'all' =&gt; amount records processed, 'imported' =&gt; number imported records */ abstract public function doimport(string $separator = ";", int $offset = 0); /** * setter import-file * * @param string $import_file * * @return void */ public function setimportfile($import_file = null) { $this-&gt;impfile = filedir::makecorrectfile($import_file); } /** * return list errors * * @return array */ public function geterrors() { return $this-&gt;errors; } /** * setter api_call * * @param string $api_call * * @return void */ protected function setapicall($api_call = "") { $this-&gt;api_call = $api_call; } protected function importentity($data_array = null) { (empty($data_array)) { return null; } $module = '\\froxlor\\api\\commands\\' . substr($this-&gt;api_call, 0, strpos($this-&gt;api_call, ".")); $function = substr($this-&gt;api_call, strpos($this-&gt;api_call, ".") + 1); $new_data = []; foreach ($this-&gt;api_params $idx =&gt; $param) { (isset($data_array[$idx])) { $new_data[$param] = $data_array[$idx]; } } $result = null; try { $json_result = $module::getlocal($this-&gt;userinfo, $new_data)-&gt;$function(); $result = json_decode($json_result, true)['data']; } catch (exception $e) { $this-&gt;errors[] = $e-&gt;getmessage(); } return !empty($result); } /** * reads csv import file returns array * entities imported * * @param string $separator * * @return array */ protected function parseimportfile($separator = ";") { (empty($this-&gt;impfile)) { throw new exception("no file given import"); } (!file_exists($this-&gt;impfile)) { throw new exception("the file '" . $this-&gt;impfile . "' could found"); } (!is_readable($this-&gt;impfile)) { throw new exception("unable read file '" . $this-&gt;impfile . "'"); } (empty($separator) || strlen($separator) != 1) { throw new exception("invalid separator specified: '" . $separator . "'"); } $file_data = []; $is_params_line = true; $fh = @fopen($this-&gt;impfile, "r"); ($fh) { (($line = fgets($fh)) !== false) { $tmp_arr = explode($separator, $line); $data_arr = []; foreach ($tmp_arr $idx =&gt; $data) { ($is_params_line) { $this-&gt;api_params[$idx] = $data; } else { $data_arr[$idx] = $data; } } ($is_params_line) { $is_params_line = false; continue; } $file_data[] = array_map("trim", $data_arr); } $this-&gt;api_params = array_map("trim", $this-&gt;api_params); } else { throw new exception("unable open file '" . $this-&gt;impfile . "'"); } fclose($fh); return $file_data; } }</file><file name="lib/Froxlor/Http/PhpConfig.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\http; use froxlor\database\database; use pdo; class phpconfig { /** * returns array existing php-configurations * database settings-array * * @return array */ public static function getphpconfigs(): array { $configs_array = []; // check table exists used preconfig // tables possibly exist yet $results = database::query("show tables like '" . table_panel_phpconfigs . "'"); (!$results) { $configs_array[1] = 'default php.ini'; } else { // get configs $result_stmt = database::query("select * `" . table_panel_phpconfigs . "`"); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { (!isset($configs_array[$row['id']]) &amp;&amp; !in_array($row['id'], $configs_array)) { $configs_array[$row['id']] = html_entity_decode($row['description']); } } } return $configs_array; } }</file><file name="lib/Froxlor/Http/RateLimiter.php">&lt;?php namespace froxlor\http; use froxlor\froxlor; use froxlor\settings; use froxlor\ui\panel\ui; class ratelimiter { private static int $limit_per_interval = 60; private static int $reset_time = 0; public static function run(bool $install_mode = false) { // default interval = 60 sec self::$reset_time = time() + 60; (!$install_mode) { self::$limit_per_interval = settings::get('system.req_limit_per_interval') ?? 60; self::$reset_time = time() + settings::get('system.req_limit_interval') ?? 60; } // get remaining requests reset time headers $remaining = isset($_session['http_x_ratelimit_remaining']) ? (int)$_session['http_x_ratelimit_remaining'] : self::$limit_per_interval; $reset = isset($_session['http_x_ratelimit_reset']) ? (int)$_session['http_x_ratelimit_reset'] : self::$reset_time; // check reset time due (time() &gt; $reset) { $remaining = self::$limit_per_interval; $reset = self::$reset_time; } // we've hit limit, return error ($remaining &lt;= 0) { header('http/1.1 429 many requests'); header("retry-after: $reset"); ui::twig()-&gt;addglobal('install_mode', '1'); echo ui::twig()-&gt;render('froxlor/misc/ratelimithint.html.twig', [ 'retry' =&gt; $reset, 'installdir' =&gt; froxlor::getinstalldir() ]); die(); } // decrement remaining requests update headers $remaining--; $_session['http_x_ratelimit_remaining'] = $remaining; $_session['http_x_ratelimit_reset'] = $reset; header("x-ratelimit-limit: " . self::$limit_per_interval); header("x-ratelimit-remaining: " . $remaining); header("x-ratelimit-reset: " . $reset); } }</file><file name="lib/Froxlor/Http/Directory.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\http; use froxlor\database\database; use froxlor\filedir; /** * class frxdirectory handles directory actions gives information * given directory connections usage froxlor */ class directory { /** * directory string * * @var string */ private $dir = null; /** * class constructor, optionally set directory * * @param string $dir */ public function __construct(string $dir = null) { $this-&gt;dir = $dir; } /** * check whether directory options set panel_htaccess * * @return bool */ public function hasuseroptions(): bool { $uo_stmt = database::prepare(" select count(`id`) `usropts` `" . table_panel_htaccess . "` `path` = :dir "); $uo_res = database::pexecute_first($uo_stmt, [ 'dir' =&gt; filedir::makecorrectdir($this-&gt;dir) ]); ($uo_res &amp;&amp; isset($uo_res['usropts'])) { return $uo_res['usropts'] &gt; 0; } return false; } /** * check whether directory protected using panel_htpasswd * * @return bool */ public function isuserprotected(): bool { $up_stmt = database::prepare(" select count(`id`) `usrprot` `" . table_panel_htpasswds . "` `path` = :dir "); $up_res = database::pexecute_first($up_stmt, [ 'dir' =&gt; filedir::makecorrectdir($this-&gt;dir) ]); ($up_res &amp;&amp; isset($up_res['usrprot'])) { return $up_res['usrprot'] &gt; 0; } return false; } /** * checks given directory valid multiple configurations * rather used single file * * @param bool $ifexists also check whether file/dir exists * * @return bool true usable dir, false otherwise */ public function isconfigdir(bool $ifexists = false): bool { (is_null($this-&gt;dir)) { trigger_error(__class__ . '::' . __function__ . ' called null value', e_user_warning); return false; } (file_exists($this-&gt;dir)) { (is_dir($this-&gt;dir)) { $returnval = true; } else { $returnval = false; } } else { (!$ifexists) { (substr($this-&gt;dir, -1) == '/') { $returnval = true; } else { $returnval = false; } } else { $returnval = false; } } return $returnval; } }</file><file name="lib/Froxlor/Http/HttpClient.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\http; use exception; use froxlor\froxlor; class httpclient { /** * executes simple get request * * @param string $url * @param bool $follow_location * @param int $timeout * * @return bool|string * @throws exception */ public static function urlget(string $url, bool $follow_location = true, int $timeout = 10) { $ch = curl_init(); curl_setopt($ch, curlopt_url, $url); curl_setopt($ch, curlopt_useragent, 'froxlor/' . froxlor::getversion()); ($follow_location) { curl_setopt($ch, curlopt_followlocation, true); } curl_setopt($ch, curlopt_timeout, (int)$timeout); curl_setopt($ch, curlopt_returntransfer, 1); $output = curl_exec($ch); ($output === false) { $e = curl_error($ch); curl_close($ch); throw new exception("curl error: " . $e); } curl_close($ch); return $output; } /** * downloads stores file url * * @param string $url * @param string $target * * @return bool|string * @throws exception */ public static function fileget(string $url, string $target) { $fh = fopen($target, 'w'); $ch = curl_init(); curl_setopt($ch, curlopt_url, $url); curl_setopt($ch, curlopt_useragent, 'froxlor/' . froxlor::getversion()); curl_setopt($ch, curlopt_followlocation, true); curl_setopt($ch, curlopt_timeout, 50); // give curl file pointer write curl_setopt($ch, curlopt_returntransfer, 1); curl_setopt($ch, curlopt_file, $fh); $output = curl_exec($ch); ($output === false) { $e = curl_error($ch); curl_close($ch); throw new exception("curl error: " . $e); } curl_close($ch); return $output; } }</file><file name="lib/Froxlor/Http/Statistics.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\http; use froxlor\filedir; use froxlor\froxlor; use froxlor\settings; class statistics { /** * create modify awstats configuration file given domain. * modified berend dekens allow custom configurations. * * @param string $logfile * @param string $sitedomain * @param string $hostaliases * @param string $customerdocroot * @param array $domain_data * * @return null * @throws \exception */ public static function createawstatsconf( string $logfile, string $sitedomain, string $hostaliases, string $customerdocroot, array $domain_data = [] ) { // generation header $header = "## generated froxlor\n"; $header2 = "## remove line above! tells froxlor update configuration\n## wish manually change configuration file, remove first line make sure froxlor rebuild file\n## generated domain {site_domain} " . date('l ds \of f h:i:s a') . "\n"; $awstats_dir = filedir::makecorrectdir($customerdocroot . '/awstats/' . $sitedomain . '/'); (!is_dir($awstats_dir)) { filedir::safe_exec('mkdir -p ' . escapeshellarg($awstats_dir)); } // chown created folder, #258 self::makechownwithnewstats($domain_data); // weird could happen... (!is_dir(settings::get('system.awstats_conf'))) { filedir::safe_exec('mkdir -p ' . escapeshellarg(settings::get('system.awstats_conf'))); } $logformat = settings::get('system.awstats_logformat'); (!is_numeric($logformat)) { // logformat numeric (e.g. 1,2,3,4), quote it. // 1-4 pre-defined formats awstats must quoted work properly. // integer, something customized simply quote it. // escaping double-quote fine, put whole string double-quote. $logformat = '"' . str_replace('"', '\"', settings::get('system.awstats_logformat')) . '"'; } // variables replace $regex = [ '/\{log_file\}/', '/\{site_domain\}/', '/\{host_aliases\}/', '/\{customer_docroot\}/', '/\{awstats_conf\}/', '/\{awstats_logformat\}/' ]; $replace = [ filedir::makecorrectfile($logfile), $sitedomain, $hostaliases, $awstats_dir, filedir::makecorrectdir(settings::get('system.awstats_conf')), $logformat ]; // file names $domain_file = filedir::makecorrectfile(settings::get('system.awstats_conf') . '/awstats.' . $sitedomain . '.conf'); $model_file = froxlor::getinstalldir() . '/templates/misc/awstats/awstats.froxlor.model.conf'; $model_file = filedir::makecorrectfile($model_file); // test file exists (file_exists($domain_file)) { // check generated header - manual modification update $awstats_domain_conf = fopen($domain_file, 'r'); (fgets($awstats_domain_conf, strlen($header)) != $header) { fclose($awstats_domain_conf); return; } // close file fclose($awstats_domain_conf); } $awstats_domain_conf = fopen($domain_file, 'w'); $awstats_model_conf = fopen($model_file, 'r'); // write header fwrite($awstats_domain_conf, $header); fwrite($awstats_domain_conf, preg_replace($regex, $replace, $header2)); // write configuration file (($line = fgets($awstats_model_conf, 4096)) !== false) { (!preg_match('/^#/', $line) &amp;&amp; trim($line) != '') { fwrite($awstats_domain_conf, preg_replace($regex, $replace, $line)); } } fclose($awstats_domain_conf); fclose($awstats_model_conf); } /** * chowns stats-tools folder, either webserver-user * fcgid/php-fpm used, customers name, #258 * * @param array $row array panel_customers * * @return void * @throws \exception */ public static function makechownwithnewstats(array $row) { // get correct user ((settings::get('system.mod_fcgid') == '1' || settings::get('phpfpm.enabled') == '1') &amp;&amp; isset($row['deactivated']) &amp;&amp; $row['deactivated'] == '0') { $user = $row['loginname']; $group = $row['loginname']; } else { $user = $row['guid']; $group = $row['guid']; } // get correct directory $dir = $row['documentroot'] . '/' . settings::get('system.traffictool') . '/'; // run chown directory exists (file_exists($dir)) { // run chown filedir::safe_exec('chown -r ' . escapeshellarg($user) . ':' . escapeshellarg($group) . ' ' . escapeshellarg(filedir::makecorrectdir($dir))); } } }</file><file name="lib/Froxlor/Http/index.html" /><file name="lib/Froxlor/Cli/ConfigServices.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cli; use exception; use froxlor\config\configparser; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlor; use froxlor\phphelper; use froxlor\settings; use froxlor\simexporter; use froxlor\system\crypt; use symfony\component\console\input\inputinterface; use symfony\component\console\input\inputoption; use symfony\component\console\output\outputinterface; use symfony\component\console\style\symfonystyle; final class configservices extends clicommand { private $yes_to_all_supported = [ 'bookworm', 'bullseye', 'focal', 'jammy', 'noble', ]; protected function configure() { $this-&gt;setname('froxlor:config-services'); $this-&gt;setdescription('configure system services'); $this-&gt;addoption('create', 'c', inputoption::value_none, 'create services list configuration --apply option.') -&gt;addoption('apply', 'a', inputoption::value_required, 'configure services given configuration file/string. create one run command --create option.') -&gt;addoption('list', 'l', inputoption::value_none, 'output services going configured using given config file (--apply option). services configured.') -&gt;addoption('daemon', 'd', inputoption::value_required | inputoption::value_is_array, 'when used --apply specify one multiple daemons. services get configured.') -&gt;addoption('import-settings', 'i', inputoption::value_required, 'import settings another froxlor installation. done standalone addition --apply.') -&gt;addoption('yes-to-all', 'a', inputoption::value_none, 'install packages without asking questions (debian/ubuntu currently)'); } protected function execute(inputinterface $input, outputinterface $output): int { $result = $this-&gt;validaterequirements($output); require froxlor::getinstalldir() . '/lib/functions.php'; ($result == self::success &amp;&amp; $input-&gt;getoption('import-settings') == false &amp;&amp; $input-&gt;getoption('create') == false &amp;&amp; $input-&gt;getoption('apply') == false) { $output-&gt;writeln('&lt;error&gt;no option given something, exiting.&lt;/&gt;'); return self::invalid; } // import settings given ($result == self::success &amp;&amp; $input-&gt;getoption('import-settings')) { $result = $this-&gt;importsettings($input, $output); } ($result == self::success &amp;&amp; $input-&gt;getoption('yes-to-all')) { (in_array(settings::get('system.distribution'), $this-&gt;yes_to_all_supported)) { putenv("debian_frontend=noninteractive"); exec("echo 'apt::get::assume-yes \"true\";' &gt; /tmp/_tmp_apt.conf"); putenv("apt_config=/tmp/_tmp_apt.conf"); } else { $output-&gt;writeln('&lt;comment&gt;--yes-to-all ignored, configured supported distribution&lt;/&gt;'); } } ($result == self::success) { $io = new symfonystyle($input, $output); ($input-&gt;getoption('create')) { $result = $this-&gt;createconfig($output, $io); } elseif ($input-&gt;getoption('apply')) { $result = $this-&gt;applyconfig($input, $output, $io); } elseif ($input-&gt;getoption('list') || $input-&gt;getoption('daemon')) { $output-&gt;writeln('&lt;error&gt;options --list --daemon work together --apply.&lt;/&gt;'); $result = self::invalid; } } ($input-&gt;getoption('yes-to-all') &amp;&amp; in_array(settings::get('system.distribution'), $this-&gt;yes_to_all_supported)) { putenv("debian_frontend"); unlink("/tmp/_tmp_apt.conf"); putenv("apt_config"); } return $result; } private function importsettings(inputinterface $input, outputinterface $output) { $importfile = $input-&gt;getoption('import-settings'); (strtoupper(substr($importfile, 0, 4)) == 'http') { $output-&gt;writeln("settings file seems url, trying download"); $target = "/tmp/froxlor-import-settings-" . time() . ".json"; (@file_exists($target)) { @unlink($target); } $this-&gt;downloadfile($importfile, $target); $importfile = $target; } (!is_file($importfile)) { $output-&gt;writeln('&lt;error&gt;given settings file file&lt;/&gt;'); return self::invalid; } elseif (!file_exists($importfile)) { $output-&gt;writeln('&lt;error&gt;given settings file cannot found (' . $importfile . ')&lt;/&gt;'); return self::invalid; } elseif (!is_readable($importfile)) { $output-&gt;writeln('&lt;error&gt;given settings file cannot read (' . $importfile . ')&lt;/&gt;'); return self::invalid; } $imp_content = file_get_contents($importfile); simexporter::import($imp_content); $output-&gt;writeln("&lt;info&gt;successfully imported settings '" . $input-&gt;getoption('import-settings') . "'&lt;/info&gt;"); return self::success; } private function downloadfile($src, $dest) { set_time_limit(0); // file save information $fp = fopen($dest, 'w+'); // file downloading, replace spaces %20 $ch = curl_init(str_replace(" ", "%20", $src)); curl_setopt($ch, curlopt_timeout, 50); curl_setopt($ch, curlopt_ssl_verifypeer, false); // write curl response file curl_setopt($ch, curlopt_file, $fp); curl_setopt($ch, curlopt_followlocation, true); // get curl response curl_exec($ch); curl_close($ch); fclose($fp); } /** * @throws exception */ private function createconfig(outputinterface $output, symfonystyle $io): int { $_daemons_config = [ 'distro' =&gt; "" ]; $config_dir = froxlor::getinstalldir() . '/lib/configfiles/'; // show list available distro's $distros = glob($config_dir . '*.xml'); // tmp array $distributions_select_data = []; //set default os. $os_dist = ['id' =&gt; 'bookworm']; $os_version = ['0' =&gt; '12']; $os_default = $os_dist['id']; //read os-release (file_exists('/etc/os-release')) { $os_dist = parse_ini_file('/etc/os-release', false); (is_array($os_dist) &amp;&amp; array_key_exists('id', $os_dist) &amp;&amp; array_key_exists('version_id', $os_dist)) { $os_version = explode('.', $os_dist['version_id'])[0]; } } // read distros foreach ($distros $_distribution) { // get configparser object $dist = new configparser($_distribution); // get distro-info $dist_display = $dist-&gt;getcompletedistroname(); // store tmp array $distributions_select_data[$dist_display] = str_replace(".xml", "", strtolower(basename($_distribution))); //guess current distro. $ver = explode('.', $dist-&gt;distributionversion)[0]; (strtolower($os_dist['id']) == strtolower($dist-&gt;distributionname) &amp;&amp; $os_version == $ver) { $os_default = str_replace(".xml", "", strtolower(basename($_distribution))); } } // sort distribution name ksort($distributions_select_data); // list distributions $table_rows = []; $valid_dists = []; foreach ($distributions_select_data $name =&gt; $filename) { $table_rows[] = [$filename, $name]; $valid_dists[] = $filename; } $io-&gt;table( ['id', 'distribution'], $table_rows ); $_daemons_config['distro'] = $io-&gt;choice('choose distribution', $valid_dists, $os_default); // go services let user check whether include (empty($_daemons_config['distro']) || !file_exists($config_dir . '/' . $_daemons_config['distro']. ".xml")) { $output-&gt;writeln('&lt;error&gt;empty non-existing distribution given.&lt;/&gt;'); return self::invalid; } $configfiles = new configparser($config_dir . '/' . $_daemons_config['distro'] . ".xml"); $services = $configfiles-&gt;getservices(); foreach ($services $si =&gt; $service) { $output-&gt;writeln("--- " . strtoupper($si) . " ---"); $_daemons_config[$si] = ""; $daemons = $service-&gt;getdaemons(); $default_daemon = ""; $table_rows = []; $valid_options = []; ($si != 'system') { $table_rows[] = ['x', 'no']; $valid_options[] = 'x'; } foreach ($daemons $di =&gt; $dd) { $title = $dd-&gt;title; ($dd-&gt;default) { $default_daemon = $di; $title .= " (default)"; } $table_rows[] = [$di, $title]; $valid_options[] = $di; } $io-&gt;table( ['value', 'name'], $table_rows ); $daemons['x'] = 'x'; ($si == 'system') { $_daemons_config[$si] = []; // system/other services need multiple choice possibility $output-&gt;writeln("&lt;comment&gt;select every service need. enter empty value done&lt;/&gt;"); $sysservice = ""; { $sysservice = $io-&gt;ask('choose service'); (!empty($sysservice)) { $_daemons_config[$si][] = $sysservice; } } (!empty($sysservice)); // add 'cron' fixed part (doesn't hurt exists) (!in_array('cron', $_daemons_config[$si])) { $_daemons_config[$si][] = 'cron'; } } else { // others -&gt; one value $_daemons_config[$si] = $io-&gt;choice('choose service', $valid_options, $default_daemon); } } $daemons_config = json_encode($_daemons_config); $output_file = $io-&gt;ask("choose output-filename", "/tmp/froxlor-config-" . date('ymd') . ".json"); file_put_contents($output_file, $daemons_config); $output-&gt;writeln("&lt;info&gt;successfully generated service-configfile '" . $output_file . "'&lt;/&gt;"); $output-&gt;writeln([ "", "&lt;info&gt;you apply config running:&lt;/&gt;", "php " . froxlor::getinstalldir() . "bin/froxlor-cli froxlor:config-services --apply=" . $output_file, "" ]); $proceed = $io-&gt;confirm("do want apply config now?", false); ($proceed) { passthru("php " . froxlor::getinstalldir() . "bin/froxlor-cli froxlor:config-services --apply=" . $output_file); } return self::success; } /** * @throws exception */ private function applyconfig(inputinterface $input, outputinterface $output, symfonystyle $io): int { $applyfile = $input-&gt;getoption('apply'); // check plain json $decoded_config = json_decode($applyfile, true); $skipfilecheck = false; (json_last_error() == json_error_none) { $skipfilecheck = true; } (!$skipfilecheck) { (strtoupper(substr($applyfile, 0, 4)) == 'http') { $output-&gt;writeln("config file seems url, trying download"); $target = "/tmp/froxlor-config-" . time() . ".json"; (@file_exists($target)) { @unlink($target); } $this-&gt;downloadfile($applyfile, $target); $applyfile = $target; } (!is_file($applyfile)) { $output-&gt;writeln('&lt;error&gt;given config file file&lt;/&gt;'); return self::invalid; } elseif (!file_exists($applyfile)) { $output-&gt;writeln('&lt;error&gt;given config file cannot found (' . $applyfile . ')&lt;/&gt;'); return self::invalid; } elseif (!is_readable($applyfile)) { $output-&gt;writeln('&lt;error&gt;given config file cannot read (' . $applyfile . ')&lt;/&gt;'); return self::invalid; } $config = file_get_contents($applyfile); $decoded_config = json_decode($config, true); } ($input-&gt;getoption('list') != false) { $table_rows = []; foreach ($decoded_config $service =&gt; $daemon) { (is_array($daemon) &amp;&amp; count($daemon) &gt; 0) { foreach ($daemon $sysdaemon) { $table_rows[] = [$service, $sysdaemon]; } } else { ($daemon == 'x') { $daemon = '--- skipped ---'; } $table_rows[] = [$service, $daemon]; } } $io-&gt;table( ['service', 'selected daemon'], $table_rows ); return self::success; } $only_daemon = []; ($input-&gt;getoption('daemon') != false) { $only_daemon = $input-&gt;getoption('daemon'); } (!empty($decoded_config)) { $config_dir = froxlor::getinstalldir() . 'lib/configfiles/'; (empty($decoded_config['distro']) || !file_exists($config_dir . '/' . $decoded_config['distro']. ".xml")) { $output-&gt;writeln('&lt;error&gt;empty non-existing distribution given. please login admin, go "system -&gt; configuration" select correct distribution top-right corner specify valid distribution name "distro" parameter.&lt;/&gt;'); return self::invalid; } $configfiles = new configparser($config_dir . '/' . $decoded_config['distro']. ".xml"); $services = $configfiles-&gt;getservices(); $replace_arr = $this-&gt;getreplacerarray(); // sure fallback certificate specified settings exists $certfile = settings::get('system.ssl_cert_file'); $keyfile = settings::get('system.ssl_key_file'); (empty($certfile) || empty($keyfile) || !file_exists($certfile) || !file_exists($keyfile)) { $output-&gt;writeln('&lt;comment&gt;creating missing certificate ' . $certfile . '&lt;/&gt;'); crypt::createselfsignedcertificate(); } foreach ($services $si =&gt; $service) { $output-&gt;writeln("--- configuring: " . strtoupper($si) . " ---"); (!isset($decoded_config[$si]) || $decoded_config[$si] == 'x') { $output-&gt;writeln('&lt;comment&gt;skipping ' . strtoupper($si) . ' configuration desired&lt;/&gt;'); continue; } $daemons = $service-&gt;getdaemons(); foreach ($daemons $di =&gt; $dd) { // check desired service (($si != 'system' &amp;&amp; $decoded_config[$si] != $di) || (is_array($decoded_config[$si]) &amp;&amp; !in_array($di, $decoded_config[$si]))) { continue; } $output-&gt;writeln("configuring '" . $di . "'"); (!empty($only_daemon) &amp;&amp; !in_array($di, $only_daemon)) { $output-&gt;writeln('&lt;comment&gt;skipping ' . $di . ' configuration desired&lt;/&gt;'); continue; } // run cmds $confarr = $dd-&gt;getconfig(); foreach ($confarr $action) { switch ($action['type']) { case "install": $output-&gt;writeln("installing required packages"); $result = null; passthru(strtr($action['content'], $replace_arr), $result); (strlen($result) &gt; 1) { echo $result; } break; case "command": exec(strtr($action['content'], $replace_arr)); break; case "file": (array_key_exists('content', $action)) { $output-&gt;writeln('&lt;comment&gt;creating file "' . $action['name'] . '"&lt;/&gt;'); file_put_contents($action['name'], trim(strtr($action['content'], $replace_arr)) . php_eol); } elseif (array_key_exists('subcommands', $action)) { foreach ($action['subcommands'] $fileaction) { (array_key_exists('execute', $fileaction) &amp;&amp; $fileaction['execute'] == "pre") { exec(strtr($fileaction['content'], $replace_arr)); } elseif (array_key_exists('execute', $fileaction) &amp;&amp; $fileaction['execute'] == "post") { exec(strtr($fileaction['content'], $replace_arr)); } elseif ($fileaction['type'] == 'file') { $output-&gt;writeln('&lt;comment&gt;creating file "' . $fileaction['name'] . '"&lt;/&gt;'); file_put_contents($fileaction['name'], trim(strtr($fileaction['content'], $replace_arr)) . php_eol); } } } break; } } } } // set is_configured flag settings::set('panel.is_configured', '1', true); // run cronjob end ensure configs date exec('php ' . froxlor::getinstalldir() . 'bin/froxlor-cli froxlor:cron --force'); // done $output-&gt;writeln('&lt;info&gt;all services configured&lt;/&gt;'); return self::success; } else { $output-&gt;writeln('&lt;error&gt;unable decode given json file&lt;/&gt;'); return self::invalid; } } /** * @throws exception */ private function getreplacerarray(): array { $customer_tmpdir = '/tmp/'; (settings::get('system.mod_fcgid') == '1' &amp;&amp; settings::get('system.mod_fcgid_tmpdir') != '') { $customer_tmpdir = settings::get('system.mod_fcgid_tmpdir'); } elseif (settings::get('phpfpm.enabled') == '1' &amp;&amp; settings::get('phpfpm.tmpdir') != '') { $customer_tmpdir = settings::get('phpfpm.tmpdir'); } // try convert nameserver hosts ip's $ns_ips = ""; $known_ns_ips = []; (settings::get('system.nameservers') != '') { $nameservers = explode(',', settings::get('system.nameservers')); foreach ($nameservers $nameserver) { $nameserver = trim($nameserver); // dns servers might multi homed; allow transfer ip // addresses dns server $nameserver_ips = phphelper::gethostbynamel6($nameserver); // append dot hostname (substr($nameserver, -1, 1) != '.') { $nameserver .= '.'; } // ignore invalid responses (!is_array($nameserver_ips)) { // act like phphelper::gethostbynamel6() return unmodified hostname error $nameserver_ips = [ $nameserver ]; } else { $known_ns_ips = array_merge($known_ns_ips, $nameserver_ips); } (!empty($ns_ips)) { $ns_ips .= ','; } $ns_ips .= implode(",", $nameserver_ips); } } // axfr server (settings::get('system.axfrservers') != '') { $axfrservers = explode(',', settings::get('system.axfrservers')); foreach ($axfrservers $axfrserver) { (!in_array(trim($axfrserver), $known_ns_ips)) { (!empty($ns_ips)) { $ns_ips .= ','; } $ns_ips .= trim($axfrserver); } } } database::needsqldata(); $sql = database::getsqldata(); return [ '&lt;sql_unprivileged_user&gt;' =&gt; $sql['user'], '&lt;sql_unprivileged_password&gt;' =&gt; $sql['passwd'], '&lt;sql_db&gt;' =&gt; $sql['db'], '&lt;sql_host&gt;' =&gt; $sql['host'], '&lt;sql_socket&gt;' =&gt; $sql['socket'] ?? null, '&lt;servername&gt;' =&gt; settings::get('system.hostname'), '&lt;serverip&gt;' =&gt; settings::get('system.ipaddress'), '&lt;nameservers&gt;' =&gt; settings::get('system.nameservers'), '&lt;nameservers_ip&gt;' =&gt; $ns_ips, '&lt;virtual_mailbox_base&gt;' =&gt; settings::get('system.vmail_homedir'), '&lt;virtual_uid_maps&gt;' =&gt; settings::get('system.vmail_uid'), '&lt;virtual_gid_maps&gt;' =&gt; settings::get('system.vmail_gid'), '&lt;sslprotocols&gt;' =&gt; (settings::get('system.use_ssl') == '1') ? 'imaps pop3s' : '', '&lt;customer_tmp&gt;' =&gt; filedir::makecorrectdir($customer_tmpdir), '&lt;base_path&gt;' =&gt; froxlor::getinstalldir(), '&lt;bind_config_path&gt;' =&gt; filedir::makecorrectdir(settings::get('system.bindconf_directory')), '&lt;webserver_reload_cmd&gt;' =&gt; settings::get('system.apachereload_command'), '&lt;customer_logs&gt;' =&gt; filedir::makecorrectdir(settings::get('system.logfiles_directory')), '&lt;fpm_ipcdir&gt;' =&gt; filedir::makecorrectdir(settings::get('phpfpm.fastcgi_ipcdir')), '&lt;webserver_group&gt;' =&gt; settings::get('system.httpgroup'), '&lt;ssl_cert_file&gt;' =&gt; settings::get('system.ssl_cert_file'), '&lt;ssl_key_file&gt;' =&gt; settings::get('system.ssl_key_file'), '&lt;admin_mail&gt;' =&gt; settings::get('panel.adminmail'), ]; } }</file><file name="lib/Froxlor/Cli/SwitchServerIp.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cli; use froxlor\database\database; use pdo; use symfony\component\console\input\inputinterface; use symfony\component\console\input\inputoption; use symfony\component\console\output\outputinterface; use symfony\component\console\style\symfonystyle; final class switchserverip extends clicommand { protected function configure() { $this-&gt;setname('froxlor:switch-server-ip'); $this-&gt;setdescription('easily switch ip addresses e.g. server migration'); $this-&gt;addoption('switch', 's', inputoption::value_required | inputoption::value_is_array, 'switch ip-address pair. pair separated comma. example: --switch=a,b') -&gt;addoption('list', 'l', inputoption::value_none, 'list ip addresses currently added server froxlor'); } protected function execute(inputinterface $input, outputinterface $output): int { $result = $this-&gt;validaterequirements($output); ($result == self::success &amp;&amp; $input-&gt;getoption('list') == false &amp;&amp; $input-&gt;getoption('switch') == false) { $output-&gt;writeln('&lt;error&gt;either --list --switch option must provided. nothing do, exiting.&lt;/&gt;'); $result = self::invalid; } $io = new symfonystyle($input, $output); ($result == self::success &amp;&amp; $input-&gt;getoption('list')) { $sel_stmt = database::prepare("select * panel_ipsandports order ip asc, port asc"); database::pexecute($sel_stmt); $ips = $sel_stmt-&gt;fetchall(pdo::fetch_assoc); $table_rows = []; foreach ($ips $ipdata) { $table_rows[] = [$ipdata['id'], $ipdata['ip'], $ipdata['port']]; } $io-&gt;table( ['#', 'ip address', 'port'], $table_rows ); } ($result == self::success &amp;&amp; $input-&gt;getoption('switch')) { $result = $this-&gt;switchips($input, $output); } return $result; } private function switchips(inputinterface $input, outputinterface $output): int { $ip_list = $input-&gt;getoption('switch'); $has_error = false; $ips_to_switch = []; foreach ($ip_list $ips_combo) { $ip_pair = explode(",", $ips_combo); (count($ip_pair) != 2) { $output-&gt;writeln('&lt;error&gt;invalid option parameter, valid ip address pair.&lt;/&gt;'); $has_error = true; } else { (filter_var($ip_pair[0], filter_validate_ip) == false) { $output-&gt;writeln('&lt;error&gt;invalid source ip address: ' . $ip_pair[0] . '&lt;/&gt;'); $has_error = true; } (filter_var($ip_pair[1], filter_validate_ip) == false) { $output-&gt;writeln('&lt;error&gt;invalid target ip address: ' . $ip_pair[1] . '&lt;/&gt;'); $has_error = true; } ($ip_pair[0] == $ip_pair[1] &amp;&amp; !$has_error) { $output-&gt;writeln('&lt;error&gt;source target ip address equal&lt;/&gt;'); $has_error = true; } } $ips_to_switch[] = $ip_pair; } ($has_error) { return self::failure; } (count($ips_to_switch) &gt; 0) { $check_stmt = database::prepare("select `id` panel_ipsandports `ip` = :newip"); $upd_stmt = database::prepare("update panel_ipsandports set `ip` = :newip `ip` = :oldip"); // system.ipaddress $check_sysip_stmt = database::prepare("select `value` `panel_settings` `settinggroup` = 'system' `varname` = 'ipaddress'"); $check_sysip = database::pexecute_first($check_sysip_stmt); // system.mysql_access_host $check_mysqlip_stmt = database::prepare("select `value` `panel_settings` `settinggroup` = 'system' `varname` = 'mysql_access_host'"); $check_mysqlip = database::pexecute_first($check_mysqlip_stmt); // system.axfrservers $check_axfrip_stmt = database::prepare("select `value` `panel_settings` `settinggroup` = 'system' `varname` = 'axfrservers'"); $check_axfrip = database::pexecute_first($check_axfrip_stmt); foreach ($ips_to_switch $ip_pair) { $output-&gt;writeln('switching ip &lt;comment&gt;' . $ip_pair[0] . '&lt;/&gt; ip &lt;comment&gt;' . $ip_pair[1] . '&lt;/&gt;'); $ip_check = database::pexecute_first($check_stmt, [ 'newip' =&gt; $ip_pair[1] ]); ($ip_check) { $output-&gt;writeln('&lt;error&gt;note: ' . $ip_pair[0] . ' updated ' . $ip_pair[1] . ' - ip already exists froxlor\'s database&lt;/&gt;'); continue; } database::pexecute($upd_stmt, [ 'newip' =&gt; $ip_pair[1], 'oldip' =&gt; $ip_pair[0] ]); $rows_updated = $upd_stmt-&gt;rowcount(); ($rows_updated == 0) { $output-&gt;writeln('&lt;error&gt;note: ' . $ip_pair[0] . ' updated ' . $ip_pair[1] . ' (possibly entry found froxlor database. use --list see ip addresses added froxlor'); continue; } // check whether system.ipaddress needs updating ($check_sysip['value'] == $ip_pair[0]) { $upd2_stmt = database::prepare("update `panel_settings` set `value` = :newip `settinggroup` = 'system' `varname` = 'ipaddress'"); database::pexecute($upd2_stmt, [ 'newip' =&gt; $ip_pair[1] ]); $output-&gt;writeln('&lt;info&gt;updated system-ipaddress &lt;comment&gt;' . $ip_pair[0] . '&lt;/comment&gt; &lt;comment&gt;' . $ip_pair[1] . '&lt;/comment&gt;&lt;/info&gt;'); } // check whether system.mysql_access_host needs updating (strstr($check_mysqlip['value'], $ip_pair[0]) !== false) { $new_mysqlip = str_replace($ip_pair[0], $ip_pair[1], $check_mysqlip['value']); $upd2_stmt = database::prepare("update `panel_settings` set `value` = :newmysql `settinggroup` = 'system' `varname` = 'mysql_access_host'"); database::pexecute($upd2_stmt, [ 'newmysql' =&gt; $new_mysqlip ]); $output-&gt;writeln('&lt;info&gt;updated mysql_access_host &lt;comment&gt;' . $check_mysqlip['value'] . '&lt;/comment&gt; &lt;comment&gt;' . $new_mysqlip . '&lt;/comment&gt;&lt;/info&gt;'); } // check whether system.axfrservers needs updating (strstr($check_axfrip['value'], $ip_pair[0]) !== false) { $new_axfrip = str_replace($ip_pair[0], $ip_pair[1], $check_axfrip['value']); $upd2_stmt = database::prepare("update `panel_settings` set `value` = :newaxfr `settinggroup` = 'system' `varname` = 'axfrservers'"); database::pexecute($upd2_stmt, [ 'newaxfr' =&gt; $new_axfrip ]); $output-&gt;writeln('&lt;info&gt;updated axfr-servers &lt;comment&gt;' . $check_axfrip['value'] . '&lt;/comment&gt; &lt;comment&gt;' . $new_axfrip . '&lt;/comment&gt;&lt;/info&gt;'); } } } $output-&gt;writeln(""); $output-&gt;writeln("&lt;comment&gt;*** attention *** remember replace ip addresses configuration files used anywhere.&lt;/&gt;"); $output-&gt;writeln("&lt;info&gt;ip addresses updated&lt;/&gt;"); return self::success; } }</file><file name="lib/Froxlor/Cli/UserCommand.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cli; use exception; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\froxlor; use froxlor\system\crypt; use symfony\component\console\input\inputargument; use symfony\component\console\input\inputinterface; use symfony\component\console\input\inputoption; use symfony\component\console\output\outputinterface; use symfony\component\console\style\symfonystyle; final class usercommand extends clicommand { protected function configure() { $this-&gt;setname('froxlor:user'); $this-&gt;setdescription('various user actions'); $this-&gt;addargument('user', inputargument::required, 'loginname target user') -&gt;addargument('admin', inputargument::optional, 'loginname executing admin/reseller user', 'admin'); $this-&gt;addoption('unlock', 'u', inputoption::value_none, 'unlock user many failed login attempts') -&gt;addoption('change-passwd', 'p', inputoption::value_none, 'set new password given user') -&gt;addoption('show-info', 's', inputoption::value_none, 'output information details given user'); } protected function execute(inputinterface $input, outputinterface $output): int { $result = self::success; $result = $this-&gt;validaterequirements($output); require froxlor::getinstalldir() . '/lib/functions.php'; // set error-handler @set_error_handler([ '\\froxlor\\api\\api', 'phperrhandler' ]); ($result == self::success) { try { $adminname = $input-&gt;getargument('admin'); $admininfo = $this-&gt;getuserbyname($adminname); $loginname = $input-&gt;getargument('user'); $userinfo = $this-&gt;getuserbyname($loginname, false); $do_unlock = $input-&gt;getoption('unlock'); $do_passwd = $input-&gt;getoption('change-passwd'); $do_show = $input-&gt;getoption('show-info'); ($do_unlock === false &amp;&amp; $do_passwd === false &amp;&amp; $do_show === false) { $output-&gt;writeln('&lt;error&gt;no option given, nothing do.&lt;/&gt;'); $result = self::invalid; } ($do_unlock !== false) { // unlock given user ((int)$userinfo['adminsession'] == 1) { admins::getlocal($admininfo, ['loginname' =&gt; $loginname])-&gt;unlock(); } else { customers::getlocal($admininfo, ['loginname' =&gt; $loginname])-&gt;unlock(); } $output-&gt;writeln('&lt;info&gt;user ' . $loginname . ' unlocked successfully&lt;/&gt;'); $result = self::success; } ($result == self::success &amp;&amp; $do_passwd !== false) { $io = new symfonystyle($input, $output); $passwd = $io-&gt;askhidden("enter new password", function ($value) { (empty($value)) { throw new \runtimeexception('you must enter value.'); } $value = crypt::validatepassword($value, 'new password'); return $value; }); $passwd2 = $io-&gt;askhidden("confirm new password", function ($value) use ($passwd) { (empty($value)) { throw new \runtimeexception('you must enter value.'); } elseif ($value != $passwd) { throw new \runtimeexception('passwords match'); } return $value; }); ((int)$userinfo['adminsession'] == 1) { admins::getlocal($admininfo, ['id' =&gt; $userinfo['adminid'], 'admin_password' =&gt; $passwd])-&gt;update(); } else { customers::getlocal($admininfo, ['id' =&gt; $userinfo['customerid'], 'new_customer_password' =&gt; $passwd])-&gt;update(); } $output-&gt;writeln('&lt;info&gt;changed password ' . $loginname . '&lt;/&gt;'); $result = self::success; } ($result == self::success &amp;&amp; $do_show !== false) { $userinfo['password'] = '[hidden]'; $userinfo['data_2fa'] = '[hidden]'; $io = new symfonystyle($input, $output); $io-&gt;horizontaltable( array_keys($userinfo), [array_values($userinfo)] ); } } catch (exception $e) { $output-&gt;writeln('&lt;error&gt;' . $e-&gt;getmessage() . '&lt;/&gt;'); $result = self::failure; } } return $result; } }</file><file name="lib/Froxlor/Cli/PhpSessionclean.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cli; use froxlor\database\database; use froxlor\filedir; use froxlor\settings; use pdo; use symfony\component\console\input\inputargument; use symfony\component\console\input\inputinterface; use symfony\component\console\output\outputinterface; final class phpsessionclean extends clicommand { protected function configure() { $this-&gt;setname('froxlor:php-sessionclean'); $this-&gt;setdescription('cleans old php-session files tmp folder'); $this-&gt;addargument('max-lifetime', inputargument::optional, 'the number seconds data seen "garbage" potentially cleaned up. defaults "1440"'); } protected function execute(inputinterface $input, outputinterface $output): int { $result = $this-&gt;validaterequirements($output); ($result == self::success) { ((int)settings::get('phpfpm.enabled') == 1) { ($input-&gt;hasargument('max-lifetime') &amp;&amp; is_numeric($input-&gt;getargument('max-lifetime')) &amp;&amp; $input-&gt;getargument('max-lifetime') &gt; 0) { $this-&gt;cleansessionfiles((int)$input-&gt;getargument('max-lifetime')); } else { // use default max-lifetime value $this-&gt;cleansessionfiles(); } $result = self::success; } else { // php-fpm enabled $output-&gt;writeln('&lt;comment&gt;php-fpm enabled installation.&lt;/comment&gt;'); $result = self::invalid; } } return $result; } private function cleansessionfiles(int $maxlifetime = 1440) { // store paths clean $paths_to_clean = []; // get pool-config directories configured $sel_stmt = database::prepare("select distinct `config_dir` `" . table_panel_fpmdaemons . "`"); database::pexecute($sel_stmt); ($fpmd = $sel_stmt-&gt;fetch(pdo::fetch_assoc)) { $poolfiles = glob(filedir::makecorrectfile($fpmd['config_dir'] . '/*.conf')); foreach ($poolfiles $cf) { $contents = file_get_contents($cf); $pattern = preg_quote('session.save_path', '/'); $pattern = "/" . $pattern . ".+?\=(.*)/"; (preg_match_all($pattern, $contents, $matches)) { $paths_to_clean[] = filedir::makecorrectdir(trim($matches[1][0])); } } } // every path needed $paths_to_clean = array_unique($paths_to_clean); (count($paths_to_clean) &gt; 0) { foreach ($paths_to_clean $ptc) { // find files older maxlifetime delete filedir::safe_exec("find -o3 \"" . $ptc . "\" -ignore_readdir_race -depth -mindepth 1 -name 'sess_*' -type f -cmin \"+" . $maxlifetime . "\" -delete"); } } } }</file><file name="lib/Froxlor/Cli/MasterCron.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cli; use exception; use froxlor\cron\cronconfig; use froxlor\cron\system\extrausers; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\system\cronjob; use pdo; use symfony\component\console\input\inputargument; use symfony\component\console\input\inputinterface; use symfony\component\console\input\inputoption; use symfony\component\console\output\outputinterface; final class mastercron extends clicommand { private $lockfile = null; private $cronlog = null; protected function configure() { $this-&gt;setname('froxlor:cron'); $this-&gt;setdescription('regulary perform tasks created froxlor'); $this-&gt;addargument('job', inputargument::is_array, 'job(s) run'); $this-&gt;addoption('run-task', 'r', inputoption::value_required | inputoption::value_is_array, 'run specific task [1 = re-generate configs, 4 = re-generate dns zones, 9 = re-generate rspamd configs, 10 = re-set quotas, 99 = re-create cron.d-file]') -&gt;addoption('force', 'f', inputoption::value_none, 'forces given job or, none given, forces re-generating config-files (webserver, nameserver, etc.)') -&gt;addoption('debug', 'd', inputoption::value_none, 'output debug information going stdout.') -&gt;addoption('no-fork', 'n', inputoption::value_none, 'do fork background (traffic cron only).'); } /** * @throws exception */ protected function execute(inputinterface $input, outputinterface $output): int { $result = $this-&gt;validaterequirements($output); ($result != self::success) { // requirements failed, exit return $result; } $jobs = $input-&gt;getargument('job'); // handle force option ($input-&gt;getoption('force')) { (empty($jobs) || in_array('tasks', $jobs)) { cronjob::inserttask(taskid::rebuild_vhost); cronjob::inserttask(taskid::rebuild_dns); cronjob::inserttask(taskid::rebuild_rspamd); cronjob::inserttask(taskid::create_quota); cronjob::inserttask(taskid::rebuild_cron); cronjob::inserttask(taskid::update_le_services); $jobs[] = 'tasks'; } define('cron_is_forced', 1); } // handle debug option ($input-&gt;getoption('debug')) { define('cron_debug_flag', 1); } // handle no-fork option ($input-&gt;getoption('no-fork')) { define('cron_nofork_flag', 1); } // handle run-task option ($input-&gt;getoption('run-task')) { $tasks_to_run = $input-&gt;getoption('run-task'); foreach ($tasks_to_run $ttr) { (in_array($ttr, [taskid::rebuild_vhost, taskid::rebuild_dns, taskid::rebuild_rspamd, taskid::create_quota, taskid::rebuild_cron])) { cronjob::inserttask($ttr); $jobs[] = 'tasks'; } else { $output-&gt;writeln('&lt;comment&gt;unknown task number "' . $ttr . '"&lt;/&gt;'); } } } // unique job-array $jobs = array_unique($jobs); // check given job(s) execute return empty (empty($jobs)) { $output-&gt;writeln('&lt;error&gt;no job given. nothing do.&lt;/&gt;'); return self::invalid; } $this-&gt;validateownership($output); $this-&gt;cronlog = froxlorlogger::getinstanceof([ 'loginname' =&gt; 'cronjob' ]); $this-&gt;cronlog-&gt;setcrondebugflag(defined('cron_debug_flag')); // check whether actual tasks perform 'tasks'-cron, // regenerate files unnecessarily $tasks_cnt_stmt = database::query("select count(*) jobcnt `panel_tasks`"); $tasks_cnt = $tasks_cnt_stmt-&gt;fetch(pdo::fetch_assoc); // iterate needed jobs foreach ($jobs $job) { // lock job ($this-&gt;lockjob($job, $output)) { // get fqdn cron-class $cronfile = $this-&gt;getcronmodule($job, $output); // validate ($cronfile &amp;&amp; class_exists($cronfile)) { // info $output-&gt;writeln('&lt;info&gt;running "' . $job . '" job' . (defined('cron_is_forced') ? ' (forced)' : '') . (defined('cron_debug_flag') ? ' (debug)' : '') . (defined('cron_nofork_flag') ? ' (not forking)' : '') . '&lt;/&gt;'); // update time last run cronjob::updatelastrunofcron($job); // set logger $cronfile::setcronlog($this-&gt;cronlog); // run job $cronfile::run(); } // free lockfile $this-&gt;unlockjob(); } } // regenerate nss-extrausers files / invalidate nscd cache (if used) $this-&gt;refreshusers((int)$tasks_cnt['jobcnt']); // check system's last guid every cron run // case admin installed new software added new user //so users database conflict system users $this-&gt;cronlog-&gt;logaction(froxlorlogger::cron_action, log_notice, 'checking system\'s last guid'); cronjob::checklastguid(); // check cron.d-generation task create necessary cronconfig::checkcrondconfigurationfile(); // check old/compatibility cronjob file (file_exists(froxlor::getinstalldir() . '/scripts/froxlor_master_cronjob.php')) { @unlink(froxlor::getinstalldir() . '/scripts/froxlor_master_cronjob.php'); @rmdir(froxlor::getinstalldir() . '/scripts'); } // reset cronlog-flag set "once" ((int)settings::get('logger.log_cron') == 1) { froxlorlogger::getinstanceof()-&gt;setcronlog(0); } // clean possible old login-links 2fa tokens database::query("delete `" . table_panel_loginlinks . "` `valid_until` &lt; unix_timestamp()"); database::query("delete `" . table_panel_2fa_tokens . "` `valid_until` &lt; unix_timestamp()"); return $result; } /** * @throws exception */ private function validateownership(outputinterface $output) { // using fcgid fpm froxlor-vhost itself, check // whether permission files still correct $output-&gt;write('checking froxlor file permissions...'); $_mypath = filedir::makecorrectdir(froxlor::getinstalldir()); (((int)settings::get('system.mod_fcgid') == 1 &amp;&amp; (int)settings::get('system.mod_fcgid_ownvhost') == 1) || ((int)settings::get('phpfpm.enabled') == 1 &amp;&amp; (int)settings::get('phpfpm.enabled_ownvhost') == 1)) { $user = settings::get('system.mod_fcgid_httpuser'); $group = settings::get('system.mod_fcgid_httpgroup'); (settings::get('phpfpm.enabled') == 1) { $user = settings::get('phpfpm.vhost_httpuser'); $group = settings::get('phpfpm.vhost_httpgroup'); } // files folders belong local user filedir::safe_exec('chown -r ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath)); } else { // back webserver permission $user = settings::get('system.httpuser'); $group = settings::get('system.httpgroup'); filedir::safe_exec('chown -r ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath)); } $output-&gt;writeln('ok'); } private function lockjob(string $job, outputinterface $output): bool { $this-&gt;lockfile = '/run/lock/froxlor_' . $job . '.lock'; (file_exists($this-&gt;lockfile)) { $jobinfo = json_decode(file_get_contents($this-&gt;lockfile), true); $check_pid_return = null; // get status process system("kill -chld " . (int)$jobinfo['pid'] . " 1&gt; /dev/null 2&gt; /dev/null", $check_pid_return); ($check_pid_return == 1) { // process seem run, likely died $this-&gt;unlockjob(); } else { // cronjob still running, output info stop $output-&gt;writeln([ '&lt;comment&gt;job "' . $jobinfo['job'] . '" currently running.', 'started: ' . date('d.m.y h:i', (int)$jobinfo['startts']), 'pid: ' . $jobinfo['pid'] . '&lt;/&gt;' ]); return false; } } $jobinfo = [ 'job' =&gt; $job, 'startts' =&gt; time(), 'pid' =&gt; getmypid() ]; file_put_contents($this-&gt;lockfile, json_encode($jobinfo)); return true; } private function unlockjob(): bool { return @unlink($this-&gt;lockfile); } private function getcronmodule(string $cronname, outputinterface $output) { $upd_stmt = database::prepare(" select `cronclass` `" . table_panel_cronruns . "` `cronfile` = :cron; "); $cron = database::pexecute_first($upd_stmt, [ 'cron' =&gt; $cronname ]); ($cron) { return $cron['cronclass']; } $output-&gt;writeln("&lt;error&gt;requested cronjob '" . $cronname . "' could found.&lt;/&gt;"); return false; } private function refreshusers(int $jobcount = 0) { ($jobcount &gt; 0) { (settings::get('system.nssextrausers') == 1) { extrausers::generatefiles($this-&gt;cronlog); // reload crond shell users might use crontab user known crond reloaded filedir::safe_exec(escapeshellcmd(settings::get('system.crondreload'))); return; } // clear nscd cache using fcgid fpm, #1570 - needed nss-extrausers ((settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1) &amp;&amp; settings::get('system.nssextrausers') == 0) { $false_val = false; filedir::safe_exec('nscd -i passwd 1&gt; /dev/null', $false_val, [ '&gt;' ]); filedir::safe_exec('nscd -i group 1&gt; /dev/null', $false_val, [ '&gt;' ]); // reload crond shell users might use crontab user known crond reloaded filedir::safe_exec(escapeshellcmd(settings::get('system.crondreload'))); } } } }</file><file name="lib/Froxlor/Cli/RunApiCommand.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cli; use exception; use froxlor\froxlor; use symfony\component\console\input\inputargument; use symfony\component\console\input\inputinterface; use symfony\component\console\input\inputoption; use symfony\component\console\output\outputinterface; use symfony\component\console\style\symfonystyle; final class runapicommand extends clicommand { protected function configure() { $this-&gt;setname('froxlor:api-call'); $this-&gt;setdescription('run api command given user'); $this-&gt;addargument('user', inputargument::required, 'loginname user want run command as') -&gt;addargument('api-command', inputargument::required, 'the command execute form "module.function"') -&gt;addargument('parameters', inputargument::optional, 'paramaters pass command json array'); $this-&gt;addoption('show-params', 's', inputoption::value_none, 'show possible parameters given api-command (given command *not* called)'); } protected function execute(inputinterface $input, outputinterface $output): int { $result = $this-&gt;validaterequirements($output); require froxlor::getinstalldir() . '/lib/functions.php'; // set error-handler @set_error_handler([ '\\froxlor\\api\\api', 'phperrhandler' ]); ($result == self::success) { try { $loginname = $input-&gt;getargument('user'); $userinfo = $this-&gt;getuserbyname($loginname); $command = $input-&gt;getargument('api-command'); $apicmd = $this-&gt;validatecommand($command); $module = "\\froxlor\\api\\commands\\" . $apicmd['class']; $function = $apicmd['function']; ($input-&gt;getoption('show-params') !== false) { $json_result = \froxlor\api\commands\froxlor::getlocal($userinfo, ['module' =&gt; $apicmd['class'], 'function' =&gt; $function])-&gt;listfunctions(); $io = new symfonystyle($input, $output); $result = $this-&gt;outputparamslist($json_result, $io); } else { $params_json = $input-&gt;getargument('parameters'); $params = json_decode($params_json ?? '', true); $json_result = $module::getlocal($userinfo, $params)-&gt;{$function}(); $output-&gt;write($json_result); $result = self::success; } } catch (exception $e) { $output-&gt;writeln('&lt;error&gt;' . $e-&gt;getmessage() . '&lt;/&gt;'); $result = self::failure; } } return $result; } private function outputparamslist(string $json, symfonystyle $io): int { $docs = json_decode($json, true); $docs = array_shift($docs['data']); (!isset($docs['params'])) { $io-&gt;warning(($docs['head'] ?? "unknown return")); return self::invalid; } (empty($docs['params'])) { $io-&gt;success("no parameters required"); } else { $rows = []; foreach ($docs['params'] $param) { $rows[] = [$param['type'], '&lt;options=bold&gt;' . $param['parameter'] . '&lt;/&gt;', $param['desc'] ?? ""]; } $io-&gt;table(['type', 'name', 'description'], $rows); } return self::success; } /** * @throws exception */ private function validatecommand(string $command): array { $command = explode(".", $command); (count($command) != 2) { throw new exception("the given command invalid."); } // simply check file-existance, want use autoloader way // recognize non-api classes+methods valid commands $apiclass = '\\froxlor\\api\\commands\\' . $command[0]; (!class_exists($apiclass) || !@method_exists($apiclass, $command[1])) { throw new exception("unknown command"); } return ['class' =&gt; $command[0], 'function' =&gt; $command[1]]; } }</file><file name="lib/Froxlor/Cli/install.functions.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\language; function lng(string $identifier, array $arguments = []) { return language::gettranslation($identifier, $arguments); } function old(string $identifier, string $default = null, string $session = null) { return $default; }</file><file name="lib/Froxlor/Cli/InstallCommand.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cli; use exception; use froxlor\config\configparser; use froxlor\database\database; use froxlor\froxlor; use froxlor\install\install; use froxlor\install\install\core; use froxlor\settings; use symfony\component\console\command\command; use symfony\component\console\helper\table; use symfony\component\console\input\inputargument; use symfony\component\console\input\inputinterface; use symfony\component\console\input\inputoption; use symfony\component\console\output\outputinterface; use symfony\component\console\style\symfonystyle; final class installcommand extends command { private $io = null; private $formfielddata = []; protected function configure() { $this-&gt;setname('froxlor:install'); $this-&gt;setdescription('installation process use instead web-ui'); $this-&gt;addargument('input-file', inputargument::optional, 'optional json array file use unattended installations'); $this-&gt;addoption('print-example-file', 'p', inputoption::value_none, 'outputs example json content used input file parameter') -&gt;addoption('create-userdata-from-str', 'c', inputoption::value_required, 'creates lib/userdata.inc.php file string created web-install process') -&gt;addoption('show-sysinfo', 's', inputoption::value_none, 'outputs system information froxlor installation'); } /** * @throws exception */ protected function execute(inputinterface $input, outputinterface $output): int { $result = self::success; ($input-&gt;getoption('create-userdata-from-str') !== null) { $ud_str = $input-&gt;getoption('create-userdata-from-str'); $ud_dec = @json_decode(@base64_decode($ud_str), true); (is_array($ud_dec) &amp;&amp; !empty($ud_dec) &amp;&amp; count($ud_dec) == 8) { $core = new core($ud_dec); $core-&gt;createuserdataconf(); return $result; } $output-&gt;writeln("&lt;error&gt;invalid parameter value.&lt;/&gt;"); return self::invalid; } ($input-&gt;getoption('show-sysinfo') !== false) { (!file_exists(froxlor::getinstalldir() . '/lib/userdata.inc.php')) { $output-&gt;writeln("&lt;error&gt;could find froxlor's userdata.inc.php file. use parameter installed froxlor system.&lt;/&gt;"); return self::invalid; } $this-&gt;printsysinfo($output); return self::success; } session_start(); require __dir__ . '/install.functions.php'; // set defaults cli cannot know $_server['server_software'] = 'apache'; $host = []; exec('hostname -f', $host); $_server['server_name'] = $host[0] ?? ''; $ips = []; exec('hostname -i', $ips); $ips = explode(" ", $ips[0] ?? ""); // ipv4 address? $_server['server_addr'] = filter_var($ips[0] ?? "", filter_validate_ip, filter_flag_ipv4) ? ($ips[0] ?? '') : ''; (empty($_server['server_addr'])) { // possible ipv6 address? $_server['server_addr'] = filter_var($ips[0] ?? "", filter_validate_ip, filter_flag_ipv6) ? ($ips[0] ?? '') : ''; } ($input-&gt;getoption('print-example-file') !== false) { $this-&gt;printexamplefile($output); return self::success; } (file_exists(froxlor::getinstalldir() . '/lib/userdata.inc.php')) { $output-&gt;writeln("&lt;error&gt;froxlor seems installed already.&lt;/&gt;"); return self::invalid; } $this-&gt;io = new symfonystyle($input, $output); $this-&gt;io-&gt;title('froxlor installation'); ($input-&gt;getargument('input-file')) { $inputfile = $input-&gt;getargument('input-file'); (strtoupper(substr($inputfile, 0, 4)) == 'http') { $output-&gt;writeln("input file seems url, trying download"); $target = "/tmp/froxlor-install-" . time() . ".json"; (@file_exists($target)) { @unlink($target); } $this-&gt;downloadfile($inputfile, $target); $inputfile = $target; } (!is_file($inputfile)) { $output-&gt;writeln('&lt;error&gt;given input file file&lt;/&gt;'); return self::invalid; } elseif (!file_exists($inputfile)) { $output-&gt;writeln('&lt;error&gt;given input file cannot found (' . $inputfile . ')&lt;/&gt;'); return self::invalid; } elseif (!is_readable($inputfile)) { $output-&gt;writeln('&lt;error&gt;given input file cannot read (' . $inputfile . ')&lt;/&gt;'); return self::invalid; } $inputcontent = file_get_contents($inputfile); $decoded_input = json_decode($inputcontent, true) ?? []; $extended = true; (empty($decoded_input)) { $output-&gt;writeln('&lt;error&gt;given input file seems invalid json&lt;/&gt;'); return self::invalid; } $this-&gt;io-&gt;info('running unattended installation'); } else { $extended = $this-&gt;io-&gt;confirm('use advanced installation mode?', false); $decoded_input = []; } return $this-&gt;showstep(0, $extended, $decoded_input); } /** * @throws exception */ private function showstep(int $step = 0, bool $extended = false, array $decoded_input = []): int { $result = self::success; $inst = new install(['step' =&gt; $step, 'extended' =&gt; $extended]); switch ($step) { case 0: $this-&gt;io-&gt;section(lng('install.preflight')); $crresult = $inst-&gt;checkrequirements(); $this-&gt;io-&gt;info($crresult['text']); (!empty($crresult['criticals'])) { foreach ($crresult['criticals'] $ctype =&gt; $critical) { (!empty($ctype) &amp;&amp; $ctype == 'wrong_ownership') { $this-&gt;io-&gt;error(lng('install.errors.' . $ctype, [$critical['user'], $critical['group']])); } elseif (!empty($ctype) &amp;&amp; $ctype == 'missing_extensions') { $this-&gt;io-&gt;error([ lng('install.errors.' . $ctype), implode("\n", $critical) ]); } else { $this-&gt;io-&gt;error($critical); } } $result = self::failure; } (!empty($crresult['suggestions'])) { foreach ($crresult['suggestions'] $ctype =&gt; $suggestion) { ($ctype == 'missing_extensions') { $this-&gt;io-&gt;warning([ lng('install.errors.suggestedextensions'), implode("\n", $suggestion) ]); } else { $this-&gt;io-&gt;warning($suggestion); } } } ($result == self::success) { return $this-&gt;showstep(++$step, $extended, $decoded_input); } break; case 1: case 2: case 3: $section = $inst-&gt;formfield['install']['sections']['step' . $step] ?? []; $this-&gt;io-&gt;section($section['title']); (empty($decoded_input)) { $this-&gt;io-&gt;note($section['description']); } foreach ($section['fields'] $fieldname =&gt; $fielddata) { ($extended == false &amp;&amp; isset($fielddata['advanced']) &amp;&amp; $fielddata['advanced'] == true) { ($fieldname == 'httpuser' || $fieldname == 'httpgroup') { // overwrite posix_getgrgid(posix_getgid())['name'] would result 'root' $this-&gt;formfielddata[$fieldname] = 'www-data'; } else { $this-&gt;formfielddata[$fieldname] = $fielddata['value']; } continue; } $ask_field = true; // preset input-file (!empty($decoded_input) &amp;&amp; isset($decoded_input[$fieldname])) { $this-&gt;formfielddata[$fieldname] = $decoded_input[$fieldname]; $ask_field = false; } $fielddata['value'] = $this-&gt;formfielddata[$fieldname] ?? ($fielddata['value'] ?? null); $fielddata['label'] = $this-&gt;clitextformat($fielddata['label'], " "); ($ask_field) { ($fielddata['type'] == 'password') { $this-&gt;formfielddata[$fieldname] = $this-&gt;io-&gt;askhidden($fielddata['label'], function ($value) use ($fielddata) { (isset($fielddata['mandatory']) &amp;&amp; $fielddata['mandatory'] &amp;&amp; empty($value)) { throw new \runtimeexception('you must enter value.'); } return $value; }); } elseif ($fielddata['type'] == 'checkbox') { $this-&gt;formfielddata[$fieldname] = $this-&gt;io-&gt;confirm($fielddata['label'], $fielddata['value'] ?? false); } elseif ($fielddata['type'] == 'select') { $this-&gt;formfielddata[$fieldname] = $this-&gt;io-&gt;choice($fielddata['label'], $fielddata['select_var'], $fielddata['selected'] ?? ''); } else { $this-&gt;formfielddata[$fieldname] = $this-&gt;io-&gt;ask($fielddata['label'], $fielddata['value'] ?? '', function ($value) use ($fielddata) { (isset($fielddata['mandatory']) &amp;&amp; $fielddata['mandatory'] &amp;&amp; empty($value)) { throw new \runtimeexception('you must enter value.'); } return $value; }); } } else { $this-&gt;io-&gt;text("setting field '" . $fieldname . "' value '" . ($fielddata['type'] == 'password' ? '*hidden*' : $fielddata['value']) . "'"); (isset($fielddata['mandatory']) &amp;&amp; $fielddata['mandatory'] &amp;&amp; empty($fielddata['value'])) { $this-&gt;io-&gt;error("mandatory field '" . $fieldname . "' specified/empty value input file"); return self::failure; } } } try { ($step == 1) { $inst-&gt;checkdatabase($this-&gt;formfielddata); } elseif ($step == 2) { $inst-&gt;checkadminuser($this-&gt;formfielddata); } elseif ($step == 3) { $inst-&gt;checksystem($this-&gt;formfielddata); } } catch (exception $e) { $this-&gt;io-&gt;error($e-&gt;getmessage()); ($this-&gt;io-&gt;confirm('retry?', empty($decoded_input))) { return $this-&gt;showstep($step, $extended, $decoded_input); } return self::failure; } ($step == 3) { // actual install data $this-&gt;formfielddata $core = new core($this-&gt;formfielddata); $core-&gt;doinstall(false); $core-&gt;createuserdataconf(); } return $this-&gt;showstep(++$step, $extended, $decoded_input); break; case 4: $section = $inst-&gt;formfield['install']['sections']['step' . $step] ?? []; $this-&gt;io-&gt;section($section['title']); $this-&gt;io-&gt;note($this-&gt;clitextformat($section['description'])); $cmdfield = $section['fields']['system']; $this-&gt;io-&gt;success([ $cmdfield['label'], $cmdfield['value'] ]); (!isset($decoded_input['manual_config']) || (bool)$decoded_input['manual_config'] === false) { (!empty($decoded_input) || $this-&gt;io-&gt;confirm('execute command now?', false)) { passthru($cmdfield['value']); } } break; } return $result; } private function printexamplefile(outputinterface $output) { // show list available distro's $distros = glob(dirname(__dir__, 3) . '/lib/configfiles/*.xml'); // read distros foreach ($distros $distribution) { // get configparser object $dist = new configparser($distribution); // store tmp array $supportedos[str_replace(".xml", "", strtolower(basename($distribution)))] = $dist-&gt;getcompletedistroname(); } // sort distribution name asort($supportedos); $webserverbackend = [ 'php-fpm' =&gt; 'php-fpm', 'fcgid' =&gt; 'fcgid', 'mod_php' =&gt; 'mod_php (not recommended)', ]; $guesseddistribution = ""; $guessedwebserver = ""; $fields = include dirname(dirname(__dir__)) . '/formfields/install/formfield.install.php'; $json_output = []; foreach ($fields['install']['sections'] $section =&gt; $section_fields) { foreach ($section_fields['fields'] $name =&gt; $field) { ($name == 'system' || $name == 'target_servername') { continue; } ($field['type'] == 'text' || $field['type'] == 'email') { ($name == 'httpuser' || $name == 'httpgroup') { $fieldval = 'www-data'; } else { $fieldval = $field['value'] ?? ""; } } elseif ($field['type'] == 'password') { $fieldval = '******'; } elseif ($field['type'] == 'select') { $fieldval = implode("|", array_keys($field['select_var'])); } elseif ($field['type'] == 'checkbox') { $fieldval = "1|0"; } else { $fieldval = "?"; } $json_output[$name] = $fieldval; } } $output-&gt;writeln(json_encode($json_output, json_pretty_print)); } private function downloadfile($src, $dest) { set_time_limit(0); // file save information $fp = fopen($dest, 'w+'); // file downloading, replace spaces %20 $ch = curl_init(str_replace(" ", "%20", $src)); curl_setopt($ch, curlopt_timeout, 50); curl_setopt($ch, curlopt_ssl_verifypeer, false); // write curl response file curl_setopt($ch, curlopt_file, $fp); curl_setopt($ch, curlopt_followlocation, true); // get curl response curl_exec($ch); curl_close($ch); fclose($fp); } private function printsysinfo(outputinterface $output) { $php_sapi = 'mod_php'; $php_version = phpversion(); (settings::get('system.mod_fcgid') == '1') { $php_sapi = 'fcgid'; (settings::get('system.mod_fcgid_ownvhost') == '1') { $php_sapi .= ' (+ froxlor)'; } } elseif (settings::get('phpfpm.enabled') == '1') { $php_sapi = 'php-fpm'; (settings::get('phpfpm.enabled_ownvhost') == '1') { $php_sapi .= ' (+ froxlor)'; } } $kernel = 'unknown'; (function_exists('posix_uname')) { $kernel_nfo = posix_uname(); $kernel = $kernel_nfo['release'] . ' (' . $kernel_nfo['machine'] . ')'; } $ips = []; $ips_stmt = database::query("select concat(`ip`, ' (', `port`, ')') ipaddr `" . table_panel_ipsandports . "` order `id`"); ($ip = $ips_stmt-&gt;fetch(\pdo::fetch_assoc)) { $ips[] = $ip['ipaddr']; } $table = new table($output); $table -&gt;setheaders([ 'key', 'value' ]) -&gt;setrows([ ['froxlor', froxlor::getversionstring()], ['update-channel', settings::get('system.update_channel')], ['hostname', settings::get('system.hostname')], ['install-dir', froxlor::getinstalldir()], ['php cli', $php_version], ['php sapi', $php_sapi], ['webserver', settings::get('system.webserver')], ['kernel', $kernel], ['database', database::getattribute(\pdo::attr_server_version)], ['distro config', settings::get('system.distribution')], ['ip addresses', implode("\n", $ips)], ]); $table-&gt;setstyle('box'); $table-&gt;render(); } private function clitextformat(string $text, string $nl_char = "\n"): string { $text = str_replace(['&lt;br&gt;', '&lt;br/&gt;', '&lt;br /&gt;'], [$nl_char, $nl_char, $nl_char], $text); return strip_tags($text); } }</file><file name="lib/Froxlor/Cli/ValidateAcmeWebroot.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cli; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlor; use froxlor\settings; use froxlor\system\cronjob; use pdo; use symfony\component\console\input\inputinterface; use symfony\component\console\input\inputoption; use symfony\component\console\output\outputinterface; use symfony\component\console\question\confirmationquestion; use symfony\component\console\style\symfonystyle; final class validateacmewebroot extends clicommand { protected function configure() { $this-&gt;setname('froxlor:validate-acme-webroot'); $this-&gt;setdescription('validates le_webroot value correct froxlor managed domains let\'s encrypt certificate.'); $this-&gt;addoption('yes-to-all', 'a', inputoption::value_none, 'do ask confirmation, update files necessary'); } /** * @throws \exception */ protected function execute(inputinterface $input, outputinterface $output): int { $result = $this-&gt;validaterequirements($output, true); $io = new symfonystyle($input, $output); ((int)settings::get('system.leenabled') == 0) { $io-&gt;info("let's encrypt activated froxlor settings."); $result = self::invalid; } ($result == self::success) { $yestoall = $input-&gt;getoption('yes-to-all') !== false; $helper = $this-&gt;gethelper('question'); $count_changes = 0; // get let's encrypt enabled domains $sel_stmt = database::prepare("select id, domain panel_domains `letsencrypt` = '1' aliasdomain null order id asc"); database::pexecute($sel_stmt); $domains = $sel_stmt-&gt;fetchall(pdo::fetch_assoc); // check froxlor-vhost (settings::get('system.le_froxlor_enabled') == '1') { $domains[] = [ 'id' =&gt; 0, 'domain' =&gt; settings::get('system.hostname') ]; } $upd_stmt = database::prepare("update domain_ssl_settings set `validtodate`=null `domainid` = :did"); $acmesh_dir = dirname(settings::get('system.acmeshpath')); $acmesh_challenge_dir = rtrim(filedir::makecorrectdir(settings::get('system.letsencryptchallengepath')), "/"); $recommended = rtrim(filedir::makecorrectdir(froxlor::getinstalldir()), "/"); ($acmesh_challenge_dir != $recommended) { $io-&gt;warning([ "acme challenge docroot settings differs current installation directory.", "settings: '" . $acmesh_challenge_dir . "'", "default/recommended value: '" . $recommended . "'", ]); $question = new confirmationquestion('fix acme challenge docroot setting? [yes] ', true, '/^(y|j)/i'); ($yestoall || $helper-&gt;ask($input, $output, $question)) { settings::set('system.letsencryptchallengepath', $recommended); $former_value = $acmesh_challenge_dir; $acmesh_challenge_dir = $recommended; // need update corresponding acme-alias config-file $acme_alias_file = settings::get('system.letsencryptacmeconf'); $sed_params = "s@" . $former_value . "@" . $acmesh_challenge_dir . "@"; filedir::safe_exec('sed -i -e "' . $sed_params . '" ' . escapeshellarg($acme_alias_file)); $count_changes++; } } foreach ($domains $domain_arr) { $domain = $domain_arr['domain']; $acme_domain_conf = filedir::makecorrectfile($acmesh_dir . '/' . $domain . '/' . $domain . '.conf'); (file_exists($acme_domain_conf)) { $io-&gt;text("getting info " . $acme_domain_conf); $conf_content = file_get_contents($acme_domain_conf); } else { $acme_domain_conf = filedir::makecorrectfile($acmesh_dir . '/' . $domain . '_ecc/' . $domain . '.conf'); (file_exists($acme_domain_conf)) { $io-&gt;text("getting info " . $acme_domain_conf); $conf_content = file_get_contents($acme_domain_conf); } else { $io-&gt;info("no domain configuration file found '" . $acmesh_dir . "'"); continue; } } (!empty($conf_content)) { $lines = explode("\n", $conf_content); foreach ($lines $line) { $val_key = explode("=", $line); ($val_key[0] == 'le_webroot') { $domain_webroot = trim(trim($val_key[1], "'"), '"'); ($domain_webroot != $acmesh_challenge_dir) { $io-&gt;warning("domain '" . $domain . "' old/wrong le_webroot setting: '" . $domain_webroot . ' &lt;&gt; ' . $acmesh_challenge_dir . "'"); $question = new confirmationquestion('fix le_webroot? [yes] ', true, '/^(y|j)/i'); ($yestoall || $helper-&gt;ask($input, $output, $question)) { $sed_params = "s@le_webroot=.*@le_webroot='" . $acmesh_challenge_dir . "'@"; filedir::safe_exec('sed -i -e "' . $sed_params . '" ' . escapeshellarg($acme_domain_conf)); database::pexecute($upd_stmt, ['did' =&gt; $domain_arr['id']]); $io-&gt;success("correction le_webroot successful"); $count_changes++; } else { continue; } } else { $io-&gt;info("domain '" . $domain . "' le_webroot value correct"); } break; } } } } ($count_changes &gt; 0) { (froxlor::hasupdates() || froxlor::hasdbupdates()) { $io-&gt;info("changes detected froxlor updated. inserting task rebuild vhosts update."); cronjob::inserttask(taskid::rebuild_vhost); } else { $question = new confirmationquestion('changes detected. force cronjob refresh certificates? [yes] ', true, '/^(y|j)/i'); ($yestoall || $helper-&gt;ask($input, $output, $question)) { passthru(filedir::makecorrectfile(froxlor::getinstalldir() . '/bin/froxlor-cli') . ' froxlor:cron -f -d'); } } } else { $io-&gt;success("no changes necessary."); } } return $result; } }</file><file name="lib/Froxlor/Cli/index.html" /><file name="lib/Froxlor/Cli/UpdateCommand.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cli; use exception; use froxlor\froxlor; use froxlor\install\autoupdate; use froxlor\install\preconfig; use froxlor\install\update; use froxlor\settings; use froxlor\system\mailer; use symfony\component\console\input\inputinterface; use symfony\component\console\input\inputoption; use symfony\component\console\output\outputinterface; use symfony\component\console\question\choicequestion; use symfony\component\console\question\confirmationquestion; use symfony\component\console\question\question; use symfony\component\console\style\symfonystyle; final class updatecommand extends clicommand { protected function configure() { $this-&gt;setname('froxlor:update'); $this-&gt;setdescription('check newer version update froxlor'); $this-&gt;addoption('check-only', 'c', inputoption::value_none, 'only check newer version exit') -&gt;addoption('show-update-options', 'o', inputoption::value_none, 'show possible update option parameter update any. usable combination "check-only".') -&gt;addoption('update-options', 'o', inputoption::value_is_array | inputoption::value_required, 'parameter list update options.') -&gt;addoption('database', 'd', inputoption::value_none, 'only run database updates case updates done via apt manually.') -&gt;addoption('mail-notify', 'm', inputoption::value_none, 'additionally inform administrator via email newer version found') -&gt;addoption('yes-to-all', 'a', inputoption::value_none, 'do ask download, extract database-update, (if --check-only set)') -&gt;addoption('integer-return', 'i', inputoption::value_none, 'return integer whether new version available (implies --check-only). useful programmatic use.'); } protected function execute(inputinterface $input, outputinterface $output) { $result = self::success; // database update ($input-&gt;getoption('database')) { $result = $this-&gt;validaterequirements($output, true); ($result == self::success) { require froxlor::getinstalldir() . '/lib/functions.php'; (froxlor::hasupdates() || froxlor::hasdbupdates()) { $output-&gt;writeln('&lt;info&gt;' . lng('update.dbupdate_required') . '&lt;/&gt;'); ($input-&gt;getoption('check-only')) { $output-&gt;writeln('&lt;comment&gt;doing nothing "check-only" flag.&lt;/&gt;'); $this-&gt;askupdateoptions($input, $output, null, false); } else { $yestoall = $input-&gt;getoption('yes-to-all') !== false; $helper = $this-&gt;gethelper('question'); $this-&gt;askupdateoptions($input, $output, $helper, $yestoall); $question = new confirmationquestion('update database? [no] ', false, '/^(y|j)/i'); ($yestoall || $helper-&gt;ask($input, $output, $question)) { $result = $this-&gt;runupdate($output, true); } } return $result; } $output-&gt;writeln('&lt;info&gt;' . lng('update.noupdatesavail', (settings::get('system.update_channel') == 'testing' ? lng('serversettings.uc_testing') . ' ' : '')) . '&lt;/&gt;'); } return $result; } $result = $this-&gt;validaterequirements($output); ($result != self::success) { // requirements failed, exit return $result; } require froxlor::getinstalldir() . '/lib/functions.php'; // version check $newversionavail = false; ($result == self::success) { try { $aucheck = autoupdate::checkversion(); ($aucheck == 1) { $this-&gt;mailnotify($input, $output); ($input-&gt;getoption('integer-return')) { $output-&gt;write(1); return self::success; } // new version ($input-&gt;getoption('check-only')) { $text = lng('update.uc_newinfo', [(settings::get('system.update_channel') != 'stable' ? settings::get('system.update_channel') . ' ' : ''), autoupdate::getfromresult('version'), froxlor::version]); } else { $text = lng('admin.newerversionavailable') . ' ' . lng('admin.newerversiondetails', [autoupdate::getfromresult('version'), froxlor::version]); } $text = str_replace("&lt;br/&gt;", " ", $text); $text = str_replace("&lt;b&gt;", "&lt;info&gt;", $text); $text = str_replace("&lt;/b&gt;", "&lt;/info&gt;", $text); $newversionavail = true; $output-&gt;writeln('&lt;comment&gt;' . $text . '&lt;/&gt;'); $result = self::success; } elseif ($aucheck &lt; 0 || $aucheck &gt; 1) { ($input-&gt;getoption('integer-return')) { $output-&gt;write(-1); return self::invalid; } // errors ($aucheck &lt; 0) { $output-&gt;writeln('&lt;error&gt;' . autoupdate::getlasterror() . '&lt;/&gt;'); } else { $errmsg = 'error.autoupdate_' . $aucheck; ($aucheck == 3) { $errmsg = 'error.customized_version'; } $output-&gt;writeln('&lt;error&gt;' . lng($errmsg) . '&lt;/&gt;'); } $result = self::invalid; } else { ($input-&gt;getoption('integer-return')) { $output-&gt;write(0); return self::success; } // new version $output-&gt;writeln('&lt;info&gt;' . autoupdate::getfromresult('info') . '&lt;/&gt;'); $result = self::success; } } catch (exception $e) { ($input-&gt;getoption('integer-return')) { $output-&gt;write(-1); return self::failure; } $output-&gt;writeln('&lt;error&gt;' . $e-&gt;getmessage() . '&lt;/&gt;'); $result = self::failure; } } // there's newer version, proceed ($result == self::success &amp;&amp; $newversionavail) { // check whether wanted check ($input-&gt;getoption('check-only')) { //$output-&gt;writeln('&lt;comment&gt;not proceeding "check-only" specified&lt;/&gt;'); $this-&gt;askupdateoptions($input, $output, null, false); return $result; } else { $yestoall = $input-&gt;getoption('yes-to-all') !== false; $helper = $this-&gt;gethelper('question'); // ask download $question = new confirmationquestion('download newer version? [no] ', false, '/^(y|j)/i'); ($yestoall || $helper-&gt;ask($input, $output, $question)) { // download $output-&gt;writeln('downloading...'); $audl = autoupdate::downloadzip(autoupdate::getfromresult('version')); (!is_numeric($audl)) { // ask extract $question = new confirmationquestion('extract downloaded archive? [no] ', false, '/^(y|j)/i'); ($yestoall || $helper-&gt;ask($input, $output, $question)) { // extract $output-&gt;writeln('extracting...'); $auex = autoupdate::extractzip(froxlor::getinstalldir() . '/updates/' . $audl); ($auex == 0) { $output-&gt;writeln("&lt;info&gt;froxlor files updated successfully.&lt;/&gt;"); $result = self::success; $this-&gt;askupdateoptions($input, $output, $helper, $yestoall); $question = new confirmationquestion('update database? [no] ', false, '/^(y|j)/i'); ($yestoall || $helper-&gt;ask($input, $output, $question)) { $result = $this-&gt;runupdate($output, true); } } else { $errmsg = 'error.autoupdate_' . $auex; $output-&gt;writeln('&lt;error&gt;' . lng($errmsg) . '&lt;/&gt;'); $result = self::failure; } } } else { $errmsg = 'error.autoupdate_' . $audl; $output-&gt;writeln('&lt;error&gt;' . lng($errmsg) . '&lt;/&gt;'); $result = self::failure; } } } } return $result; } /** * @param inputinterface $input * @param outputinterface $output * @param $helper * @param bool $yestoall * @return void */ private function askupdateoptions(inputinterface $input, outputinterface $output, $helper, bool $yestoall = false) { // check preconfigs $preconfig = preconfig::getpreconfig(true); $show_options_only = $input-&gt;getoption('show-update-options') !== false; (!is_null($helper) &amp;&amp; $show_options_only) { $output-&gt;writeln('&lt;comment&gt;unsetting "show-update-options" due called "check-only".&lt;/&gt;'); $show_options_only = false; } $update_options = []; // set parameters $uoptions = $input-&gt;getoption('update-options'); (!empty($uoptions)) { $options_value = []; foreach ($uoptions $givenoption) { $optval = explode("=", $givenoption); (count($optval) == 2) { $options_value[$optval[0]] = $optval[1]; } } } (!empty($preconfig)) { krsort($preconfig); foreach ($preconfig $section) { (!$show_options_only) { $output-&gt;writeln("&lt;info&gt;updater questions " . $section['title'] . "&lt;/&gt;"); } foreach ($section['fields'] $update_field =&gt; $metainfo) { (isset($options_value[$update_field])) { $output-&gt;writeln('setting given parameter "' . $update_field . '" "' . $options_value[$update_field] . '"'); $_post[$update_field] = $options_value[$update_field]; continue; } $default = null; $question_text = html_entity_decode(strip_tags($metainfo['label']), ent_quotes | ent_ignore, "utf-8"); ($metainfo['type'] == 'checkbox') { $default = (int)$metainfo['checked']; ($show_options_only) { $update_options[] = [ 'name' =&gt; $update_field, 'question' =&gt; $question_text, 'default' =&gt; $default, 'choices' =&gt; '0: no' . php_eol . '1: yes' . php_eol ]; } else { $question = new confirmationquestion($question_text . ' [' . ($metainfo['checked'] ? 'yes' : 'no') . '] ', (bool)$metainfo['checked'], '/^(y|j)/i'); } } elseif ($metainfo['type'] == 'select') { $default = $metainfo['selected']; $choices = ""; foreach (array_values($metainfo['select_var'] ?? []) $index =&gt; $choice) { $choices .= $index . ': ' . $choice . php_eol; } ($show_options_only) { $update_options[] = [ 'name' =&gt; $update_field, 'question' =&gt; $question_text, 'default' =&gt; !empty($default) ? $default : '-', 'choices' =&gt; $choices ]; } else { $question = new choicequestion( $question_text, array_values($metainfo['select_var'] ?? []), $metainfo['selected'] ); $question-&gt;setvalidator(function ($answer) use ($metainfo): string { $key = array_keys($metainfo['select_var'])[(int)$answer] ?? false; // find key based selected value ($key === false) { throw new \runtimeexception('invalid selection.'); } return $key; }); } } elseif ($metainfo['type'] == 'text') { $default = $metainfo['value'] ?? ''; ($show_options_only) { $update_options[] = [ 'name' =&gt; $update_field, 'question' =&gt; $question_text, 'default' =&gt; $default, 'choices' =&gt; php_eol ]; } else { $question = new question($question_text . (!empty($metainfo['value']) ? ' [' . $metainfo['value'] . ']' : ''), $default); $question-&gt;setvalidator(function (string $answer) use ($metainfo): string { (($metainfo['mandatory'] ?? false) &amp;&amp; empty($answer)) { throw new \runtimeexception( 'answer cannot empty' ); } (!empty($metainfo['pattern'] ?? "") &amp;&amp; !preg_match("/" . $metainfo['pattern'] . "/", $answer)) { throw new \runtimeexception('answer seem valid format'); } return $answer; }); } } else { $output-&gt;writeln("&lt;error&gt;unknown type " . $metainfo['type'] . "&lt;/error&gt;"); continue; } (!$show_options_only) { ($yestoall) { $_post[$update_field] = $default; } else { $_post[$update_field] = $helper-&gt;ask($input, $output, $question); } } } } ($show_options_only) { $io = new symfonystyle($input, $output); $io-&gt;table( ['parameter', 'description', 'default', 'choices'], $update_options ); } } } private function mailnotify(inputinterface $input, outputinterface $output) { ($input-&gt;getoption('mail-notify')) { $last_check_version = settings::get('system.update_notify_last'); (update::versioninupdate($last_check_version, autoupdate::getfromresult('version'))) { $text = lng('update.uc_newinfo', [(settings::get('system.update_channel') != 'stable' ? settings::get('system.update_channel') . ' ' : ''), autoupdate::getfromresult('version'), froxlor::version]); $mail = new mailer(true); $mail-&gt;body = $text; $mail-&gt;subject = "[froxlor] " . lng('update.notify_subject'); $mail-&gt;addaddress(settings::get('panel.adminmail'), settings::get('panel.adminmail_defname')); (!$mail-&gt;send() &amp;&amp; $input-&gt;getoption('integer-return') == null) { $output-&gt;writeln('&lt;error&gt;' . $mail-&gt;errorinfo . '&lt;/&gt;'); } settings::set('system.update_notify_last', autoupdate::getfromresult('version')); } } } }</file><file name="lib/Froxlor/Cli/CliCommand.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cli; use exception; use froxlor\database\database; use froxlor\froxlor; use froxlor\settings; use pdo; use symfony\component\console\command\command; use symfony\component\console\output\outputinterface; class clicommand extends command { protected function validaterequirements(outputinterface $output, bool $ignore_has_updates = false): int { (!file_exists(froxlor::getinstalldir() . '/lib/userdata.inc.php')) { $output-&gt;writeln("&lt;error&gt;could find froxlor's userdata.inc.php file. use script installed froxlor system.&lt;/&gt;"); return self::invalid; } // try database connection try { database::query("select 1"); } catch (exception $e) { // proceed database connection could established $output-&gt;writeln("&lt;error&gt;" . $e-&gt;getmessage() . "&lt;/&gt;"); return self::invalid; } (!$ignore_has_updates &amp;&amp; (froxlor::hasupdates() || froxlor::hasdbupdates())) { ((int)settings::get('system.cron_allowautoupdate') == 1) { return $this-&gt;runupdate($output); } else { $output-&gt;writeln("&lt;error&gt;it seems froxlor files updated. please login finish update procedure.&lt;/&gt;"); return self::invalid; } } return self::success; } protected function getuserbyname(?string $loginname, bool $deactivated_check = true): array { (empty($loginname)) { throw new exception("empty username"); } $stmt = database::prepare(" select `loginname` `customer` `" . table_panel_customers . "` `loginname`= :loginname "); database::pexecute($stmt, [ "loginname" =&gt; $loginname ]); $row = $stmt-&gt;fetch(pdo::fetch_assoc); ($row &amp;&amp; $row['customer'] == $loginname) { $table = "`" . table_panel_customers . "`"; $adminsession = '0'; } else { $stmt = database::prepare(" select `loginname` `admin` `" . table_panel_admins . "` `loginname`= :loginname "); database::pexecute($stmt, [ "loginname" =&gt; $loginname ]); $row = $stmt-&gt;fetch(pdo::fetch_assoc); ($row &amp;&amp; $row['admin'] == $loginname) { $table = "`" . table_panel_admins . "`"; $adminsession = '1'; } else { throw new exception("unknown user '" . $loginname . "'"); } } $userinfo_stmt = database::prepare(" select * $table `loginname`= :loginname "); database::pexecute($userinfo_stmt, [ "loginname" =&gt; $loginname ]); $userinfo = $userinfo_stmt-&gt;fetch(pdo::fetch_assoc); $userinfo['adminsession'] = $adminsession; ($deactivated_check &amp;&amp; $userinfo['deactivated']) { throw new exception("user '" . $loginname . "' currently deactivated"); } return $userinfo; } protected function runupdate(outputinterface $output, bool $manual = false): int { (!$manual) { $output-&gt;writeln('&lt;comment&gt;automatic update activated going proceed without notices&lt;/&gt;'); } include_once froxlor::getinstalldir() . '/lib/tables.inc.php'; define('_cron_update', 1); ob_start([ $this, 'cleanupdateoutput' ]); include_once froxlor::getinstalldir() . '/install/updatesql.php'; ob_end_flush(); $output-&gt;writeln('&lt;info&gt;' . ($manual ? 'database' : 'automatic') . ' update done - check settings sure everything fine&lt;/&gt;'); return self::success; } private function cleanupdateoutput($buffer): string { return strip_tags(preg_replace("/&lt;br\w*?\/&gt;/", "\n", $buffer)); } }</file><file name="lib/Froxlor/Cli/ConfigDiff.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\cli; use froxlor\config\configparser; use froxlor\filedir; use froxlor\froxlor; use symfony\component\console\input\inputargument; use symfony\component\console\input\inputinterface; use symfony\component\console\input\inputoption; use symfony\component\console\output\outputinterface; final class configdiff extends clicommand { protected function configure(): void { $this-&gt;setname('froxlor:config-diff') -&gt;setdescription('shows differences config templates os versions') -&gt;addargument('from', inputargument::optional, 'os version compare against') -&gt;addargument('to', inputargument::optional, 'os version compare from') -&gt;addoption('list', 'l', inputoption::value_none, 'list possible os versions') -&gt;addoption('diff-params', '', inputoption::value_required, 'additional parameters `diff`, e.g. --diff-params="--color=always"'); } /** * @throws \exception */ protected function execute(inputinterface $input, outputinterface $output): int { require froxlor::getinstalldir() . '/lib/functions.php'; $parsers = $versions = []; foreach (glob(froxlor::getinstalldir() . '/lib/configfiles/*.xml') $config) { $name = str_replace(".xml", "", strtolower(basename($config))); $parser = new configparser($config); $versions[$name] = $parser-&gt;getcompletedistroname(); $parsers[$name] = $parser; } asort($versions); ($input-&gt;getoption('list') === true) { $output-&gt;writeln('the following os version templates available:'); foreach ($versions $k =&gt; $v) { $output-&gt;writeln(str_pad($k, 20) . $v); } return self::success; } (!$input-&gt;hasargument('from') || !array_key_exists($input-&gt;getargument('from'), $versions)) { $output-&gt;writeln('&lt;error&gt;missing invalid "from" argument.&lt;/error&gt;'); $output-&gt;writeln('available versions: ' . implode(', ', array_keys($versions))); return self::invalid; } (!$input-&gt;hasargument('to') || !array_key_exists($input-&gt;getargument('to'), $versions)) { $output-&gt;writeln('&lt;error&gt;missing invalid "to" argument.&lt;/error&gt;'); $output-&gt;writeln('available versions: ' . implode(', ', array_keys($versions))); return self::invalid; } // make sure diff installed $check_diff_installed = filedir::safe_exec('which diff'); (count($check_diff_installed) === 0) { $output-&gt;writeln('&lt;error&gt;unable find "diff" installation system.&lt;/error&gt;'); return self::invalid; } $parser_from = $parsers[$input-&gt;getargument('from')]; $parser_to = $parsers[$input-&gt;getargument('to')]; $tmp_from = tempnam(sys_get_temp_dir(), 'froxlor_config_diff_from'); $tmp_to = tempnam(sys_get_temp_dir(), 'froxlor_config_diff_to'); $files = []; $titles_by_key = []; // aggregate content config file foreach ([[$parser_from, 'from'], [$parser_to, 'to']] $todo) { foreach ($todo[0]-&gt;getservices() $service_type =&gt; $service) { foreach ($service-&gt;getdaemons() $daemon_name =&gt; $daemon) { foreach ($daemon-&gt;getconfig() $instruction) { ($instruction['type'] !== 'file') { continue; } (isset($instruction['subcommands'])) { foreach ($instruction['subcommands'] $subinstruction) { ($subinstruction['type'] !== 'file') { continue; } $content = $subinstruction['content']; } } else { $content = $instruction['content']; } (!isset($content)) { throw new \exception("cannot find content {$instruction['name']}"); } $key = "{$service_type}_{$daemon_name}_{$instruction['name']}"; $titles_by_key[$key] = "{$service-&gt;title} : {$daemon-&gt;title} : {$instruction['name']}"; (!isset($files[$key])) { $files[$key] = ['from' =&gt; '', 'to' =&gt; '']; } $files[$key][$todo[1]] = $this-&gt;filtercontent($content); } } } } ksort($files); $diff_params = ''; ($input-&gt;hasoption('diff-params') &amp;&amp; trim($input-&gt;getoption('diff-params')) !== '') { $diff_params = trim($input-&gt;getoption('diff-params')); } // run diff file output, anything changed foreach ($files $file_key =&gt; $content) { file_put_contents($tmp_from, $content['from']); file_put_contents($tmp_to, $content['to']); $diff_output = filedir::safe_exec("{$check_diff_installed[0]} {$diff_params} {$tmp_from} {$tmp_to}"); (count($diff_output) === 0) { continue; } $output-&gt;writeln('&lt;info&gt;# ' . $titles_by_key[$file_key] . '&lt;/info&gt;'); $output-&gt;writeln(implode("\n", $diff_output) . "\n"); unset($diff_output); } // remove tmp files unlink($tmp_from); unlink($tmp_to); return self::success; } private function filtercontent(string $content): string { $new_content = ''; foreach (explode("\n", $content) $n) { $n = trim($n); (!$n) { continue; } (str_starts_with($n, '#')) { continue; } $new_content .= $n . "\n"; } return $new_content; } }</file><file name="lib/Froxlor/Ajax/Ajax.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ajax; use exception; use datetime; use froxlor\config\configdisplay; use froxlor\config\configparser; use froxlor\currentuser; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlor; use froxlor\http\httpclient; use froxlor\install\update; use froxlor\settings; use froxlor\ui\listing; use froxlor\ui\panel\ui; use froxlor\ui\request; use froxlor\ui\response; use froxlor\validate\validate; class ajax { protected string $action; protected string $theme; protected array $userinfo; /** * @throws exception */ public function __construct() { $this-&gt;action = request::any('action'); $this-&gt;theme = request::any('theme', 'froxlor'); ui::sendheaders(); ui::sendsslheaders(); } /** * @throws exception */ public function handle() { $this-&gt;userinfo = $this-&gt;getvalidatedsession(); switch ($this-&gt;action) { case 'newsfeed': return $this-&gt;getnewsfeed(); case 'updatecheck': return $this-&gt;getupdatecheck(); case 'searchglobal': return $this-&gt;searchglobal(); case 'updatetablelisting': return $this-&gt;updatetablelisting(); case 'resettablelisting': return $this-&gt;resettablelisting(); case 'editapikey': return $this-&gt;editapikey(); case 'getconfigdetails': return $this-&gt;getconfigdetails(); case 'getconfigjsonexport': return $this-&gt;getconfigjsonexport(); case 'loadlanguagestring': return $this-&gt;loadlanguagestring(); default: return $this-&gt;errorresponse('action found!'); } } /** * @throws exception */ private function getvalidatedsession(): array { (currentuser::hassession() == false) { throw new exception("no valid session"); } return currentuser::getdata(); } /** * @throws exception */ private function getnewsfeed() { ui::inittwig(); $feed = "https://inside.froxlor.org/news/"; // set custom feed provided $role = request::get('role'); ($role == "customer") { $custom_feed = settings::get("customer.news_feed_url"); (!empty(trim($custom_feed))) { $feed = $custom_feed; } } // check simplexml_load_file (!function_exists("simplexml_load_file")) { return $this-&gt;errorresponse([ "newsfeed available due missing php-simplexml extension", "please install php-simplexml extension order view newsfeed." ]); } // check curl_version (!function_exists('curl_version')) { return $this-&gt;errorresponse([ "newsfeed available due missing php-curl extension", "please install php-curl extension order view newsfeed." ]); } $output = httpclient::urlget($feed); $news = simplexml_load_string(trim($output)); ($news === false) { $err = []; foreach (libxml_get_errors() $error) { $err[] = $error-&gt;message; } return $this-&gt;errorresponse( $err ); } // handle items ($news) { $items = null; ($i = 0; $i &lt; 3; $i++) { $item = $news-&gt;channel-&gt;item[$i]; $title = (string)$item-&gt;title; $link = (string)$item-&gt;link; $date = date("d.m.y", strtotime($item-&gt;pubdate)); $content = preg_replace("/[\r\n]+/", " ", strip_tags($item-&gt;description)); $content = substr($content, 0, 150) . "..."; $items .= ui::twig()-&gt;render(ui::validatethemetemplate('/user/newsfeeditem.html.twig', $this-&gt;theme), [ 'link' =&gt; $link, 'title' =&gt; $title, 'date' =&gt; $date, 'content' =&gt; $content ]); } return $this-&gt;jsonresponse($items); } else { return $this-&gt;errorresponse('no newsfeeds available moment.'); } } public function errorresponse($message, int $response_code = 500) { header("content-type: application/json"); return \froxlor\api\response::jsonerrorresponse($message, $response_code); } public function jsonresponse($value, int $response_code = 200) { header("content-type: application/json"); return \froxlor\api\response::jsonresponse($value, $response_code); } private function getupdatecheck() { ui::inittwig(); try { $force = request::get('force', 0); $json_result = \froxlor\api\commands\froxlor::getlocal($this-&gt;userinfo, ['force' =&gt; $force])-&gt;checkupdate(); $result = json_decode($json_result, true)['data']; $result['full_version'] = froxlor::getfullversion(); $result['dbversion'] = froxlor::dbversion; $uc_data = update::getupdatecheckdata(); $result['last_update_check'] = $uc_data['ts']; $result['channel'] = settings::get('system.update_channel'); $result_rendered = ui::twig()-&gt;render(ui::validatethemetemplate('/misc/version_top.html.twig', $this-&gt;theme), $result); return $this-&gt;jsonresponse($result_rendered); } catch (exception $e) { // display anything allowed due permissions ($e-&gt;getcode() != 403) { return $this-&gt;errorresponse($e-&gt;getmessage(), $e-&gt;getcode()); } } } /** * search globally various resources */ private function searchglobal() { $searchtext = request::any('searchtext'); $result = []; // settings $result_settings = []; (isset($this-&gt;userinfo['adminsession']) &amp;&amp; $this-&gt;userinfo['adminsession'] == 1 &amp;&amp; $this-&gt;userinfo['change_serversettings'] == 1) { $result_settings = globalsearch::searchsettings($searchtext, $this-&gt;userinfo); } // searchable entities $result_entities = globalsearch::searchglobal($searchtext, $this-&gt;userinfo); $result = array_merge($result_settings, $result_entities); return $this-&gt;jsonresponse($result); } private function updatetablelisting() { $columns = []; foreach ((request::post('columns') ?? []) $value) { $columns[] = $value; } (!empty($columns)) { $columns = listing::storecolumnlistingforuser([request::get('listing') =&gt; $columns]); return $this-&gt;jsonresponse($columns); } return $this-&gt;errorresponse('at least one column must selected', 406); } private function resettablelisting() { listing::deletecolumnlistingforuser([request::get('listing') =&gt; []]); return $this-&gt;jsonresponse([]); } private function editapikey() { $keyid = request::post('id', 0); $allowed_from = request::post('allowed_from', ""); $valid_until = request::post('valid_until', ""); (empty($keyid)) { return $this-&gt;errorresponse('invalid call', 406); } // validate allowed_from (!empty($allowed_from)) { $ip_list = array_map('trim', explode(",", $allowed_from)); $_check_list = $ip_list; foreach ($_check_list $idx =&gt; $ip) { (validate::validate_ip2($ip, true, 'invalidip', true, true, true) == false) { return $this-&gt;errorresponse('invalid ip address', 406); } // check cidr (strpos($ip, '/') !== false) { $ipparts = explode("/", $ip); // shorten ip $ip = inet_ntop(inet_pton($ipparts[0])); // re-add cidr $ip .= '/' . $ipparts[1]; } else { // shorten ip $ip = inet_ntop(inet_pton($ip)); } $ip_list[$idx] = $ip; } $allowed_from = implode(",", array_unique($ip_list)); } (!empty($valid_until)) { $valid_until_db = datetime::createfromformat('y-m-d\th:i', $valid_until)-&gt;format('u'); } else { $valid_until_db = -1; } $upd_stmt = database::prepare(" update `" . table_api_keys . "` set `valid_until` = :vu, `allowed_from` = :af `id` = :keyid `adminid` = :aid `customerid` = :cid "); ((int)$this-&gt;userinfo['adminsession'] == 1) { $cid = 0; } else { $cid = $this-&gt;userinfo['customerid']; } database::pexecute($upd_stmt, [ 'keyid' =&gt; $keyid, 'af' =&gt; $allowed_from, 'vu' =&gt; $valid_until_db, 'aid' =&gt; $this-&gt;userinfo['adminid'], 'cid' =&gt; $cid ]); return $this-&gt;jsonresponse(['allowed_from' =&gt; $allowed_from, 'valid_until' =&gt; $valid_until]); } /** * return parsed commands/files configuration templates */ private function getconfigdetails() { (isset($this-&gt;userinfo['adminsession']) &amp;&amp; $this-&gt;userinfo['adminsession'] == 1 &amp;&amp; $this-&gt;userinfo['change_serversettings'] == 1) { $distribution = request::post('distro', ""); $section = request::post('section', ""); $daemon = request::post('daemon', ""); // validate distribution config-xml exists $config_dir = filedir::makecorrectdir(froxlor::getinstalldir() . '/lib/configfiles/'); (!file_exists($config_dir . "/" . $distribution . ".xml")) { return $this-&gt;errorresponse("unknown distribution. configuration could found."); } // read configurations $configfiles = new configparser($config_dir . "/" . $distribution . ".xml"); // get services $services = $configfiles-&gt;getservices(); // validate selected service exists distribution (!isset($services[$section])) { return $this-&gt;errorresponse("unknown category selected distribution"); } // get daemons $daemons = $services[$section]-&gt;getdaemons(); // validate selected daemon exists section (!isset($daemons[$daemon])) { return $this-&gt;errorresponse("unknown service selected category"); } // finally config-steps $confarr = $daemons[$daemon]-&gt;getconfig(); // get parsed content ui::inittwig(); $content = configdisplay::fromconfigarr($confarr, $configfiles-&gt;distributioneditor, $this-&gt;theme); return $this-&gt;jsonresponse([ 'title' =&gt; $configfiles-&gt;getcompletedistroname() . '&amp;nbsp;&amp;raquo;&amp;nbsp' . $services[$section]-&gt;title . '&amp;nbsp;&amp;raquo;&amp;nbsp' . $daemons[$daemon]-&gt;title, 'content' =&gt; $content ]); } return $this-&gt;errorresponse('not allowed', 403); } /** * download json export config-selection */ private function getconfigjsonexport() { (isset($this-&gt;userinfo['adminsession']) &amp;&amp; $this-&gt;userinfo['adminsession'] == 1 &amp;&amp; $this-&gt;userinfo['change_serversettings'] == 1) { $params = $_get; unset($params['action']); unset($params['finish']); unset($params['csrf_token']); header('content-disposition: attachment; filename=froxlor-config-' . time() . '.json'); return $this-&gt;jsonresponse($params); } return $this-&gt;errorresponse('not allowed', 403); } /** * loads given language string identifier */ private function loadlanguagestring() { $langid = request::post('langid', ""); (preg_match('/^([a-za-z\.]+)$/', $langid)) { return $this-&gt;jsonresponse(lng($langid)); } return $this-&gt;errorresponse('invalid identifier: ' . $langid, 406); } }</file><file name="lib/Froxlor/Ajax/GlobalSearch.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ajax; use froxlor\api\commands\admins; use froxlor\api\commands\customers; use froxlor\api\commands\domains; use froxlor\api\commands\emaildomains; use froxlor\api\commands\emails; use froxlor\api\commands\fpmdaemons; use froxlor\api\commands\ftps; use froxlor\api\commands\hostingplans; use froxlor\api\commands\ipsandports; use froxlor\api\commands\mysqls; use froxlor\api\commands\phpsettings; use froxlor\api\commands\subdomains; use froxlor\froxlor; use froxlor\phphelper; use froxlor\settings; use froxlor\ui\collection; class globalsearch { protected array $userinfo; public static function searchsettings(string $searchtext, array $userinfo): array { $result = []; ($searchtext &amp;&amp; strlen(trim($searchtext)) &gt; 2) { $processed = []; $stparts = explode(" ", $searchtext); foreach ($stparts $searchtext) { $searchtext = trim($searchtext); (preg_match('/^([a-z]+):$/', $searchtext, $matches)) { // search settings specific search 'settings', else skip ($matches[1] == 'settings') { continue; } else { break; } } $settings_data = phphelper::loadconfigarraydir(froxlor::getinstalldir() . '/actions/admin/settings/'); $results = []; (!isset($processed['settings'])) { $processed['settings'] = []; } phphelper::recursive_array_search($searchtext, $settings_data, $results); foreach ($results $pathkey) { $pk = explode(".", $pathkey); (count($pk) &gt; 4) { $settingkey = $pk[0] . '.' . $pk[1] . '.' . $pk[2] . '.' . $pk[3]; (isset($settings_data[$pk[0]][$pk[1]]['advanced_mode']) &amp;&amp; $settings_data[$pk[0]][$pk[1]]['advanced_mode'] &amp;&amp; (int)settings::get('panel.settings_mode') == 0) { continue; } (is_array($processed['settings']) &amp;&amp; !array_key_exists($settingkey, $processed['settings'])) { $processed['settings'][$settingkey] = true; $sresult = $settings_data[$pk[0]][$pk[1]][$pk[2]][$pk[3]]; (isset($sresult['advanced_mode']) &amp;&amp; $sresult['advanced_mode'] &amp;&amp; (int)settings::get('panel.settings_mode') == 0) { continue; } ($sresult['type'] != 'hidden') { (!isset($result['settings'])) { $result['settings'] = []; } $result['settings'][] = [ 'title' =&gt; (is_array($sresult['label']) ? $sresult['label']['title'] : $sresult['label']), 'href' =&gt; 'admin_settings.php?page=overview&amp;part=' . $pk[1] . '&amp;em=' . $pk[3] ]; } // hidden } // processed } // correct settingkey } // foreach } // foreach } // searchtext min 3 chars return $result; } /** * */ public static function searchglobal(string $searchtext, array $userinfo): array { $result = []; ($searchtext &amp;&amp; strlen(trim($searchtext)) &gt; 2) { $processed = []; $stparts = explode(" ", $searchtext); $module = ""; foreach ($stparts $searchtext) { $searchtext = trim($searchtext); (preg_match('/^([a-z]+):$/', $searchtext, $matches)) { $module = $matches[1]; ($matches[1] == 'settings') { break; } else { continue; } } // admin (isset($userinfo['adminsession']) &amp;&amp; $userinfo['adminsession'] == 1) { $tosearch = [ // customers 'customer' =&gt; [ 'class' =&gt; customers::class, 'searchfields' =&gt; [ 'c.loginname', 'c.name', 'c.firstname', 'c.company', 'c.street', 'c.zipcode', 'c.city', 'c.email', 'c.customernumber', 'c.custom_notes' ], 'result_key' =&gt; 'loginname', 'result_format' =&gt; [ 'title' =&gt; ['\\froxlor\\user', 'getcorrectfulluserdetails'], 'href' =&gt; 'admin_customers.php?page=customers&amp;searchfield=c.loginname&amp;searchtext=' ] ], // domains 'domains' =&gt; [ 'class' =&gt; domains::class, 'searchfields' =&gt; [ 'd.domain', 'd.domain_ace', 'd.documentroot' ], 'result_key' =&gt; 'domain_ace', 'result_format' =&gt; [ 'title' =&gt; ['\\froxlor\\ajax\\globalsearch', 'getfieldfromresult'], 'title_args' =&gt; 'domain_ace', 'href' =&gt; 'admin_domains.php?page=domains&amp;searchfield=d.domain_ace&amp;searchtext=' ] ], // ips ports 'ipsandports' =&gt; [ 'class' =&gt; ipsandports::class, 'searchfields' =&gt; [ 'ip', 'vhostcontainer', 'specialsettings' ], 'result_key' =&gt; 'ip', 'result_groupkey' =&gt; 'ip', 'result_format' =&gt; [ 'title' =&gt; ['\\froxlor\\ajax\\globalsearch', 'getfieldfromresult'], 'title_args' =&gt; 'ip', 'href' =&gt; 'admin_ipsandports.php?page=ipsandports&amp;searchfield=ip&amp;searchtext=' ] ], // hosting-plans 'hostingplans' =&gt; [ 'class' =&gt; hostingplans::class, 'searchfields' =&gt; [ 'p.name', 'p.description' ], 'result_key' =&gt; 'id', 'result_format' =&gt; [ 'title' =&gt; ['\\froxlor\\ajax\\globalsearch', 'getfieldfromresult'], 'title_args' =&gt; 'name', 'href' =&gt; 'admin_plans.php?page=overview&amp;searchfield=id&amp;searchtext=' ] ], // php configs 'phpconfigs' =&gt; [ 'class' =&gt; phpsettings::class, 'searchfields' =&gt; [ 'c.description', 'fd.description', 'c.binary' ], 'result_key' =&gt; 'id', 'result_format' =&gt; [ 'title' =&gt; ['\\froxlor\\ajax\\globalsearch', 'getfieldfromresult'], 'title_args' =&gt; 'description', 'href' =&gt; 'admin_phpsettings.php?page=overview&amp;searchfield=id&amp;searchtext=' ] ], // fpm daemons 'fpmconfigs' =&gt; [ 'class' =&gt; fpmdaemons::class, 'searchfields' =&gt; [ 'description', 'reload_cmd' ], 'result_key' =&gt; 'id', 'result_format' =&gt; [ 'title' =&gt; ['\\froxlor\\ajax\\globalsearch', 'getfieldfromresult'], 'title_args' =&gt; 'description', 'href' =&gt; 'admin_phpsettings.php?page=fpmdaemons&amp;searchfield=id&amp;searchtext=' ] ] ]; ((bool)$userinfo['change_serversettings']) { // admins $tosearch['admins'] = [ 'class' =&gt; admins::class, 'searchfields' =&gt; [ 'loginname', 'name', 'email', 'custom_notes' ], 'result_key' =&gt; 'loginname', 'result_format' =&gt; [ 'title' =&gt; ['\\froxlor\\ajax\\globalsearch', 'getfieldfromresult'], 'title_args' =&gt; 'name', 'href' =&gt; 'admin_admins.php?page=admins&amp;searchfield=loginname&amp;searchtext=' ] ]; } } else { $tosearch = [ // (sub)domains 'domains' =&gt; [ 'class' =&gt; subdomains::class, 'searchfields' =&gt; [ 'd.domain', 'd.domain_ace', 'd.documentroot' ], 'result_key' =&gt; 'domain_ace', 'result_format' =&gt; [ 'title' =&gt; ['\\froxlor\\ajax\\globalsearch', 'getfieldfromresult'], 'title_args' =&gt; 'domain_ace', 'href' =&gt; 'customer_domains.php?page=domains&amp;searchfield=d.domain_ace&amp;searchtext=' ] ], // email addresses 'emails' =&gt; [ 'class' =&gt; emails::class, 'searchfields' =&gt; [ 'm.email', 'm.email_full' ], 'result_key' =&gt; 'email', 'result_format' =&gt; [ 'title' =&gt; ['\\froxlor\\ajax\\globalsearch', 'getfieldfromresult'], 'title_args' =&gt; 'email', 'href' =&gt; 'customer_email.php?page=email_domain&amp;domainid={domainid}&amp;searchfield=m.email&amp;searchtext=' ] ], // email-domains 'email_domains' =&gt; [ 'class' =&gt; emaildomains::class, 'searchfields' =&gt; [ 'd.domain', ], 'result_key' =&gt; 'domain', 'result_format' =&gt; [ 'title' =&gt; ['\\froxlor\\ajax\\globalsearch', 'getfieldfromresult'], 'title_args' =&gt; 'domain', 'href' =&gt; 'customer_email.php?page=emails&amp;searchfield=d.domain&amp;searchtext=' ] ], // databases 'databases' =&gt; [ 'class' =&gt; mysqls::class, 'searchfields' =&gt; [ 'databasename', 'description' ], 'result_key' =&gt; 'databasename', 'result_format' =&gt; [ 'title' =&gt; ['\\froxlor\\ajax\\globalsearch', 'getfieldfromresult'], 'title_args' =&gt; 'databasename', 'href' =&gt; 'customer_mysql.php?page=mysqls&amp;searchfield=databasename&amp;searchtext=' ] ], // ftp user 'ftpuser' =&gt; [ 'class' =&gt; ftps::class, 'searchfields' =&gt; [ 'username', 'description' ], 'result_key' =&gt; 'username', 'result_format' =&gt; [ 'title' =&gt; ['\\froxlor\\ajax\\globalsearch', 'getfieldfromresult'], 'title_args' =&gt; 'username', 'href' =&gt; 'customer_ftp.php?page=accounts&amp;searchfield=username&amp;searchtext=' ] ] ]; } // module specific search (!empty($module)) { $modsearch = $tosearch[$module] ?? []; $tosearch = [$module =&gt; $modsearch]; } foreach ($tosearch $entity =&gt; $edata) { $collection = (new collection($edata['class'], $userinfo)) -&gt;setinternal(true) -&gt;addparam([ 'sql_search' =&gt; [ '_plainsql' =&gt; self::searchstringsql($edata['searchfields'], $searchtext) ] ]); ($collection-&gt;count() &gt; 0) { (!isset($processed[$entity])) { $processed[$entity] = []; } $group_key = $edata['result_groupkey'] ?? $edata['result_key']; foreach ($collection-&gt;getlist() $cresult) { (is_array($processed[$entity]) &amp;&amp; !array_key_exists($cresult[$group_key], $processed[$entity])) { $processed[$entity][$cresult[$group_key]] = true; (!isset($result[$entity])) { $result[$entity] = []; } // replacer result href $href_replacer = []; (preg_match_all('/\{([a-z]+)\}/', $edata['result_format']['href'], $href_replacer) !== false) { foreach ($href_replacer[1] $href_field) { $href_field_value = self::getfieldfromresult($cresult, $href_field); $edata['result_format']['href'] = str_replace('{'.$href_field.'}', $href_field_value, $edata['result_format']['href']); } } $result[$entity][] = [ 'title' =&gt; call_user_func($edata['result_format']['title'], $cresult, ($edata['result_format']['title_args'] ?? null)), 'href' =&gt; $edata['result_format']['href'] . $cresult[$edata['result_key']] ]; } } } } // foreach entity } // foreach split search-term } return $result; } private static function searchstringsql(array $searchfields, $searchtext) { $result = ['sql' =&gt; [], 'values' =&gt; []]; $result['sql'] = "("; foreach ($searchfields $sf) { $result['sql'] .= $sf . " like :searchtext "; } $result['sql'] = substr($result['sql'], 0, -3) . ")"; $result['values'] = ['searchtext' =&gt; '%' . $searchtext . '%']; return $result; } private static function getfieldfromresult(array $resultset, string $field = null) { return $resultset[$field] ?? ''; } }</file><file name="lib/Froxlor/Ajax/index.html" /><file name="lib/Froxlor/UI/Form.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui; use froxlor\currentuser; use froxlor\froxlortwofactorauth; use froxlor\settings; use froxlor\validate\check; class form { public static function buildform(array $form, string $part = ''): array { $fields = []; (\froxlor\validate\form::validateformdefinition($form)) { foreach ($form['groups'] $groupname =&gt; $groupdetails) { // check advanced mode sections (isset($groupdetails['advanced_mode']) &amp;&amp; $groupdetails['advanced_mode'] &amp;&amp; (int)settings::get('panel.settings_mode') == 0) { continue; } // show overview ($part == '' || $part == 'all') { (isset($groupdetails['title']) &amp;&amp; $groupdetails['title'] != '') { $fields[] = self::getformoverviewgroupoutput($groupname, $groupdetails); } } elseif ($part != '' &amp;&amp; $groupname == $part) { // show one section /** * part checks 'websrv_avail' entry settings-array * found, check current webserver array. * * case, change setting type "hidden", #502 */ $do_show = true; (isset($groupdetails['websrv_avail']) &amp;&amp; is_array($groupdetails['websrv_avail'])) { $websrv = settings::get('system.webserver'); (!in_array($websrv, $groupdetails['websrv_avail'])) { $do_show = false; } } // visible = settings::get('phpfpm.enabled') example would result false enabled // therefore shown intended. check do_show still true might // false due websrv_avail (isset($groupdetails['visible']) &amp;&amp; $do_show) { $do_show = $groupdetails['visible']; } $fields['_group'] = [ 'title' =&gt; $groupdetails['title'] ?? 'unknown group', 'do_show' =&gt; $do_show ]; (\froxlor\validate\form::validatefielddefinition($groupdetails)) { // collect form field output foreach ($groupdetails['fields'] $fieldname =&gt; $fielddetails) { // check advanced mode sections (isset($fielddetails['advanced_mode']) &amp;&amp; $fielddetails['advanced_mode'] &amp;&amp; (int)settings::get('panel.settings_mode') == 0) { continue; } $fields[$fieldname] = self::getformfieldoutput($fieldname, $fielddetails); $fields[$fieldname] = array_merge($fields[$fieldname], self::prefetchformfielddata($fieldname, $fielddetails)); } } } } } return $fields; } public static function getformoverviewgroupoutput($groupname, $groupdetails) { $activated = true; (isset($groupdetails['fields'])) { foreach ($groupdetails['fields'] $fielddetails) { (isset($fielddetails['overview_option']) &amp;&amp; $fielddetails['overview_option'] == true) { ($fielddetails['type'] != 'checkbox') { // throw exception likely internal issue // messed arrays response::standarderror('overviewsettingoptionisnotavalidfield', '', true); } $activated = (int)settings::get($fielddetails['settinggroup'] . '.' . $fielddetails['varname']); break; } } } $item = [ 'title' =&gt; $groupdetails['title'], 'icon' =&gt; $groupdetails['icon'] ?? 'fa-solid fa-circle-question', 'part' =&gt; $groupname, 'activated' =&gt; $activated ]; /** * part checks 'websrv_avail' entry settings * found, check current webserver array. * case, change setting type "hidden", #502 */ (isset($groupdetails['websrv_avail']) &amp;&amp; is_array($groupdetails['websrv_avail'])) { $websrv = settings::get('system.webserver'); (!in_array($websrv, $groupdetails['websrv_avail'])) { $item['info'] = lng('serversettings.option_unavailable_websrv', [implode(", ", $groupdetails['websrv_avail'])]); $item['visible'] = false; } } return $item; } public static function getformfieldoutput($fieldname, $fielddata): array { $returnvalue = []; (is_array($fielddata) &amp;&amp; isset($fielddata['type']) &amp;&amp; $fielddata['type'] != '') { (!isset($fielddata['value'])) { (isset($fielddata['default'])) { $fielddata['value'] = $fielddata['default']; } else { $fielddata['value'] = null; } } // set value according type switch ($fielddata['type']) { case 'select': $fielddata['selected'] = $fielddata['value']; unset($fielddata['value']); (isset($fielddata['select_mode']) &amp;&amp; $fielddata['select_mode'] == 'multiple') { $fielddata['selected'] = array_flip(explode(",", $fielddata['selected'])); } break; case 'checkbox': $fielddata['checked'] = (bool)$fielddata['value']; $fielddata['value'] = 1; break; } /** * part checks 'websrv_avail' entry settings-array * found, check current webserver array. * * case, change setting type "hidden", #502 */ $do_show = true; (isset($fielddata['websrv_avail']) &amp;&amp; is_array($fielddata['websrv_avail'])) { $websrv = settings::get('system.webserver'); (!in_array($websrv, $fielddata['websrv_avail'])) { $do_show = false; $fielddata['note'] = lng('serversettings.option_unavailable_websrv', [implode(", ", $fielddata['websrv_avail'])]); } } // visible = settings::get('phpfpm.enabled') example would result false enabled // therefore shown intended. check do_show still true might // false due websrv_avail (isset($fielddata['visible']) &amp;&amp; $do_show) { $do_show = $fielddata['visible']; (!$do_show) { $fielddata['note'] = lng('serversettings.option_unavailable'); } } // otp security validation sensitive settings (!settings::config('disable_otp_security_check') &amp;&amp; isset($fielddata['required_otp']) &amp;&amp; $do_show) { $otp_enabled_system = (bool)settings::get('2fa.enabled'); $otp_enabled_user = (int)currentuser::getfield('type_2fa') != 0; $do_show = !$fielddata['required_otp'] || ($otp_enabled_system &amp;&amp; $otp_enabled_user); (!$do_show) { $fielddata['note'] = lng('serversettings.option_requires_otp'); (!$otp_enabled_system) { $fielddata['disabled'] = true; $fielddata['note'] .= '&lt;br&gt;' . lng('2fa.2fa_not_activated'); } elseif (!$otp_enabled_user) { $fielddata['disabled'] = true; $fielddata['note'] .= '&lt;br&gt;' . lng('2fa.2fa_not_activated_for_user'); } // show field case $do_show = true; } } (!$do_show) { $fielddata['visible'] = false; } $returnvalue = $fielddata; } return $returnvalue; } public static function prefetchformfielddata($fieldname, $fielddata) { $returnvalue = []; (is_array($fielddata) &amp;&amp; isset($fielddata['type']) &amp;&amp; $fielddata['type'] == 'select') { ((empty($fielddata['select_var']) || !is_array($fielddata['select_var'])) &amp;&amp; (isset($fielddata['option_options_method'])) ) { $returnvalue['select_var'] = call_user_func($fielddata['option_options_method']); } } return $returnvalue; } public static function processform(&amp;$form, &amp;$input, $url_params = [], $part = null, bool $settings_all = false, $settings_part = null, bool $only_enabledisable = false) { (\froxlor\validate\form::validateformdefinition($form)) { $submitted_fields = []; $changed_fields = []; $saved_fields = []; foreach ($form['groups'] $groupname =&gt; $groupdetails) { (($settings_part &amp;&amp; $part == $groupname) || $settings_all || $only_enabledisable) { (\froxlor\validate\form::validatefielddefinition($groupdetails)) { // prefetch form fields foreach ($groupdetails['fields'] $fieldname =&gt; $fielddetails) { (!$only_enabledisable || isset($fielddetails['overview_option'])) { $groupdetails['fields'][$fieldname] = array_merge($fielddetails, self::prefetchformfielddata($fieldname, $fielddetails)); $form['groups'][$groupname]['fields'][$fieldname] = $groupdetails['fields'][$fieldname]; } } } } } foreach ($form['groups'] $groupname =&gt; $groupdetails) { (($settings_part &amp;&amp; $part == $groupname) || $settings_all || $only_enabledisable) { (\froxlor\validate\form::validatefielddefinition($groupdetails)) { // validate fields foreach ($groupdetails['fields'] $fieldname =&gt; $fielddetails) { (((isset($fielddetails['visible']) &amp;&amp; $fielddetails['visible']) || !isset($fielddetails['visible'])) &amp;&amp; (!$only_enabledisable || ($only_enabledisable &amp;&amp; isset($fielddetails['overview_option'])))) { $newfieldvalue = self::getformfielddata($fieldname, $fielddetails, $input); ($newfieldvalue != $fielddetails['value']) { (($error = \froxlor\validate\form::validateformfield($fieldname, $fielddetails, $newfieldvalue)) !== true) { response::standarderror($error, $fieldname); } else { $changed_fields[$fieldname] = $newfieldvalue; } } $submitted_fields[$fieldname] = $newfieldvalue; } } } } } foreach ($form['groups'] $groupname =&gt; $groupdetails) { (($settings_part &amp;&amp; $part == $groupname) || $settings_all || $only_enabledisable) { (\froxlor\validate\form::validatefielddefinition($groupdetails)) { // check fields plausibility foreach ($groupdetails['fields'] $fieldname =&gt; $fielddetails) { (!isset($submitted_fields[$fieldname])) { // skip unset fields due unavailability system/settings-set continue; } (!$only_enabledisable || ($only_enabledisable &amp;&amp; isset($fielddetails['overview_option']))) { (($plausibility_check = self::checkplausibilityformfield($fieldname, $fielddetails, $submitted_fields[$fieldname], $submitted_fields)) !== false) { (is_array($plausibility_check) &amp;&amp; isset($plausibility_check[0])) { ($plausibility_check[0] == check::formfields_plausibility_check_ok) { // nothing here, everything's okay } elseif ($plausibility_check[0] == check::formfields_plausibility_check_error) { unset($plausibility_check[0]); $error = $plausibility_check[1]; unset($plausibility_check[1]); $targetname = implode(' ', $plausibility_check); response::standarderror($error, $targetname); } elseif ($plausibility_check[0] == check::formfields_plausibility_check_question) { unset($plausibility_check[0]); $question = $plausibility_check[1]; unset($plausibility_check[1]); $targetname = implode(' ', $plausibility_check); (!isset($input[$question])) { (is_array($url_params) &amp;&amp; isset($url_params['filename'])) { $filename = $url_params['filename']; unset($url_params['filename']); } else { $filename = ''; } html::askyesno($question, $filename, array_merge($url_params, $submitted_fields, [ $question =&gt; $question ]), $targetname); } } else { response::standarderror('plausibilitychecknotunderstood'); } } } (!settings::config('disable_otp_security_check') &amp;&amp; isset($fielddetails['required_otp']) &amp;&amp; isset($changed_fields[$fieldname])) { $otp_enabled_system = (bool)settings::get('2fa.enabled'); $otp_enabled_user = (int)currentuser::getfield('type_2fa') != 0; $do_update = !$fielddetails['required_otp'] || ($otp_enabled_system &amp;&amp; $otp_enabled_user); ($do_update) { // setting requires otp verification (empty($input['otp_verification'])) { // case email 2fa enabled, send currentuser::sendotpemail(); // build form (is_array($url_params) &amp;&amp; isset($url_params['filename'])) { $filename = $url_params['filename']; unset($url_params['filename']); } else { $filename = ''; } html::askotp('please_enter_otp', $filename, array_merge($url_params, $submitted_fields)); } else { // validate given otp code $code = trim($input['otp_verification']); $tfa = new froxlortwofactorauth('froxlor ' . settings::get('system.hostname')); $result = $tfa-&gt;verifycode(currentuser::getfield('data_2fa'), $code, 3); (!$result) { response::standarderror('otpnotvalidated'); } } } else { // update setting unset($changed_fields[$fieldname]); } } } } } } } foreach ($form['groups'] $groupname =&gt; $groupdetails) { (($settings_part &amp;&amp; $part == $groupname) || $settings_all || $only_enabledisable) { (\froxlor\validate\form::validatefielddefinition($groupdetails)) { // save fields foreach ($groupdetails['fields'] $fieldname =&gt; $fielddetails) { (!$only_enabledisable || (isset($fielddetails['overview_option']))) { (isset($changed_fields[$fieldname])) { (($saved_field = self::saveformfield($fieldname, $fielddetails, self::manipulateformfielddata($fieldname, $fielddetails, $changed_fields[$fieldname]))) !== false) { $saved_fields = array_merge($saved_fields, $saved_field); } else { response::standarderror('errorwhensaving', $fieldname); } } } } } } } // save form return self::saveform($form, $saved_fields); } return false; } public static function getformfielddata($fieldname, $fielddata, &amp;$input) { (is_array($fielddata) &amp;&amp; isset($fielddata['type']) &amp;&amp; $fielddata['type'] != '' &amp;&amp; method_exists('\\froxlor\\ui\\data', 'getformfielddata' . ucfirst($fielddata['type']))) { $newfieldvalue = call_user_func([ '\\froxlor\\ui\\data', 'getformfielddata' . ucfirst($fielddata['type']) ], $fieldname, $fielddata, $input); } else { (isset($input[$fieldname])) { $newfieldvalue = $input[$fieldname]; } elseif (isset($fielddata['default'])) { $newfieldvalue = $fielddata['default']; } else { $newfieldvalue = false; } } return trim($newfieldvalue); } public static function checkplausibilityformfield($fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues) { $returnvalue = ''; (is_array($fielddata) &amp;&amp; isset($fielddata['plausibility_check_method']) &amp;&amp; $fielddata['plausibility_check_method'] != '' &amp;&amp; method_exists($fielddata['plausibility_check_method'][0], $fielddata['plausibility_check_method'][1])) { $returnvalue = call_user_func($fielddata['plausibility_check_method'], $fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues); } else { $returnvalue = false; } return $returnvalue; } public static function saveformfield($fieldname, $fielddata, $newfieldvalue) { $returnvalue = ''; (is_array($fielddata) &amp;&amp; isset($fielddata['save_method']) &amp;&amp; $fielddata['save_method'] != '') { $returnvalue = call_user_func([ '\\froxlor\\settings\\store', $fielddata['save_method'] ], $fieldname, $fielddata, $newfieldvalue); } elseif (is_array($fielddata) &amp;&amp; !isset($fielddata['save_method'])) { $returnvalue = []; } else { $returnvalue = false; } return $returnvalue; } public static function manipulateformfielddata($fieldname, $fielddata, $newfieldvalue) { (is_array($fielddata) &amp;&amp; isset($fielddata['type']) &amp;&amp; $fielddata['type'] != '' &amp;&amp; method_exists('\\froxlor\\ui\\data', 'manipulateformfielddata' . ucfirst($fielddata['type']))) { $newfieldvalue = call_user_func([ '\\froxlor\\ui\\data', 'manipulateformfielddata' . ucfirst($fielddata['type']) ], $fieldname, $fielddata, $newfieldvalue); } return $newfieldvalue; } public static function saveform($fielddata, $newfieldvalue) { $returnvalue = ''; (is_array($fielddata) &amp;&amp; isset($fielddata['save_method']) &amp;&amp; $fielddata['save_method'] != '') { $returnvalue = call_user_func([ '\\froxlor\\settings\\store', $fielddata['save_method'] ], $fielddata, $newfieldvalue); } elseif (is_array($fielddata) &amp;&amp; !isset($fielddata['save_method'])) { $returnvalue = true; } else { $returnvalue = false; } return $returnvalue; } }</file><file name="lib/Froxlor/UI/Linker.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui; class linker { private $protocol = ''; private $username = ''; private $password = ''; private $hostname = ''; private $port = 80; private $filename = 'index.php'; private $args = []; public function __construct($file = 'index.php', $hostname = '', $protocol = '', $port = '', $username = '', $password = '') { // set basic parts url $this-&gt;protocol = $protocol; $this-&gt;username = $username; $this-&gt;password = $password; $this-&gt;hostname = $hostname; $this-&gt;port = $port; $this-&gt;filename = $file; } public function __set($key, $value) { switch (strtolower($key)) { case 'protocol': $this-&gt;protocol = $value; break; case 'username': $this-&gt;username = $value; break; case 'password': $this-&gt;password = $value; break; case 'hostname': $this-&gt;hostname = $value; break; case 'port': $this-&gt;port = $value; break; case 'filename': $this-&gt;filename = $value; break; default: return false; } return true; } public function add($key, $value) { // add new value parameters (overwrite = enabled) $this-&gt;args[$key] = $value; } public function del($key) { // key exists array -&gt; delete (isset($this-&gt;args[$key])) { unset($this-&gt;args[$key]); } } public function getlink() { $link = ''; // build basic url (strlen($this-&gt;protocol) &gt; 0 &amp;&amp; strlen($this-&gt;hostname) &gt; 0) { $link = $this-&gt;protocol . '://'; } // let's see shall use username url // available hostname used well (strlen($this-&gt;username) &gt; 0 &amp;&amp; strlen($this-&gt;hostname) &gt; 0) { $link .= urlencode($this-&gt;username); // maybe even append password? ($this-&gt;password != '') { $link .= ':' . urlencode($this-&gt;password); } // least username given, add @ allow appending hostname $link .= '@'; } // add hostname, port filename url (strlen($this-&gt;hostname) &gt; 0) { $link .= $this-&gt;hostname; // port may used hostname used well (strlen($this-&gt;port) &gt; 0) { $link .= ':' . $this-&gt;port; } } // overwrite $this-&gt;args parameters function (if necessary) (func_num_args() == 1 &amp;&amp; is_array(func_get_arg(0))) { $arguments = func_get_arg(0); $this-&gt;args = array_merge($this-&gt;args, $arguments); } // temporary frontcontroller exists // got section url -&gt; morph area section filename // @todo: remove (isset($this-&gt;args['section']) &amp;&amp; strlen($this-&gt;args['section']) &gt; 0) { $link .= area . '_' . $this-&gt;args['section'] . '.php'; unset($this-&gt;args['section']); } else { // filename prefixed slash $link .= $this-&gt;filename; } // let's see done (no arguments query) (count($this-&gt;args) == 0) { return $link; } // parameters, add "?" $link .= "?"; // loop arguments add link foreach ($this-&gt;args $key =&gt; $value) { // first argument, prepend "&amp;amp;" (substr($link, -1) != "?") { $link .= "&amp;"; } // encode parameters add link $link .= urlencode($key) . ($value !== "" ? '=' . urlencode($value) : ''); } // reset class use $this-&gt;delall(); return $link; } public function delall() { // resetting array $this-&gt;args = []; } }</file><file name="lib/Froxlor/UI/Pagination.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui; use froxlor\settings; /** * class manage pagination, limiting ordering */ class pagination { public string $sortorder = 'asc'; public $sortfield = null; private array $data = []; private ?array $fields = null; private ?string $searchtext = null; private $searchfield = null; private bool $is_search = false; private int $pageno = 0; private int $entries = 0; private int $perpage; private string $paginationadditional = ""; /** * create new pagination object search/filter, limit sort api-listing() calls * * @param array $fields * @param int $total_entries * @param int $perpage * @param array $default_sorting array key=sortfield,value=sortorder default sorting * @param array $pagination_additional_params */ public function __construct( array $fields = [], int $total_entries = 0, int $perpage = 20, array $default_sorting = [], array $pagination_additional_params = [] ) { $this-&gt;fields = $fields; $this-&gt;entries = $total_entries; $this-&gt;perpage = $perpage; $this-&gt;pageno = 1; // add default limitation settings (settings::get('panel.paging') &gt; 0) { $this-&gt;addlimit(settings::get('panel.paging')); } // check search request $this-&gt;searchtext = ''; (count($fields) &gt; 0) { $orderfields = array_keys($fields); $this-&gt;searchfield = $orderfields[0]; } $searchtext = request::any('searchtext'); (isset($searchtext) &amp;&amp; (preg_match('/[-_@\p{l}\p{n}*.]+$/u', $searchtext) || $searchtext === '')) { $this-&gt;searchtext = trim($searchtext); } $searchfield = request::any('searchfield'); (isset($searchfield) &amp;&amp; isset($fields[$searchfield])) { $this-&gt;searchfield = $searchfield; } (!empty($this-&gt;searchtext) &amp;&amp; !empty($this-&gt;searchfield)) { $this-&gt;addsearch($this-&gt;searchtext, $this-&gt;searchfield); $pagination_additional_params[] = 'searchfield=' . $this-&gt;searchfield; $pagination_additional_params[] = 'searchtext=' . $this-&gt;searchtext; } // check ordering requests $sortorder = request::any('sortorder'); (!empty($sortorder) &amp;&amp; (strtolower($sortorder) == 'desc' || strtolower($sortorder) == 'asc')) { $this-&gt;sortorder = strtoupper($sortorder); } $sortfield = request::any('sortfield'); (!empty($sortfield) &amp;&amp; isset($fields[$sortfield])) { $this-&gt;sortfield = $sortfield; $this-&gt;addorderby($this-&gt;sortfield, $this-&gt;sortorder); } else { // add default ordering given order (!empty($default_sorting)) { (!empty($default_sorting)) { $this-&gt;sortfield = array_key_first($default_sorting); $this-&gt;sortorder = array_shift($default_sorting) ?? $this-&gt;sortorder; $this-&gt;addorderby($this-&gt;sortfield, $this-&gt;sortorder); } } // add default ordering given fields (count($fields) &gt; 0 &amp;&amp; empty($this-&gt;sortfield)) { $orderfields = array_keys($fields); $this-&gt;sortfield = $orderfields[0]; $this-&gt;addorderby($orderfields[0], $this-&gt;sortorder); } } // check current page / pages $pageno = request::any('pageno'); (!empty($pageno) &amp;&amp; intval($pageno) != 0) { $this-&gt;pageno = intval($pageno); } (($this-&gt;pageno - 1) * settings::get('panel.paging') &gt; $this-&gt;entries) { $this-&gt;pageno = 1; } $this-&gt;addoffset(($this-&gt;pageno - 1) * settings::get('panel.paging')); // pagination additional parameters url (!empty($pagination_additional_params)) { foreach ($pagination_additional_params $pap) { $this-&gt;paginationadditional .= "&amp;" . $pap; } } } /** * add limit * * @param int $limit * optional, default 0 * * @return pagination */ public function addlimit(int $limit = 0): pagination { $this-&gt;data['sql_limit'] = $limit; return $this; } /** * add search operation * * @param string|null $searchtext * @param string|null $field * @param string|null $operator * * @return pagination */ public function addsearch(string $searchtext = null, string $field = null, string $operator = null): pagination { (!isset($this-&gt;data['sql_search'])) { $this-&gt;data['sql_search'] = []; } $this-&gt;data['sql_search'][$field] = [ 'value' =&gt; $searchtext, 'op' =&gt; $operator ]; // search performed, result-entries-count irrelevant // want pagination $this-&gt;is_search = true; // unset limit pagination showing search-results unset($this-&gt;data['sql_limit']); unset($this-&gt;data['sql_offset']); return $this; } /** * add field ordering * * @param string $field * @param string $order optional, default 'asc' * @return pagination */ public function addorderby($field = null, $order = 'asc'): pagination { (!isset($this-&gt;data['sql_orderby'])) { $this-&gt;data['sql_orderby'] = []; } $this-&gt;data['sql_orderby'][$field] = $order; return $this; } /** * add offset * * @param int $offset optional, default 0 * @return pagination */ public function addoffset(int $offset = 0): pagination { $this-&gt;data['sql_offset'] = $offset; return $this; } /** * return number total entries user access current resource * * @return number */ public function getentries(): int { return $this-&gt;entries; } public function getapicommandparams(): array { return $this-&gt;data; } public function getapiresponseparams(): array { return [ 'pagination' =&gt; [ "total" =&gt; $this-&gt;entries, "per_page" =&gt; $this-&gt;perpage, "current_page" =&gt; $this-&gt;pageno, "last_page" =&gt; (settings::get('panel.paging') &gt; 0) ? ceil($this-&gt;entries / $this-&gt;perpage) : -1, "from" =&gt; $this-&gt;data['sql_offset'] ?? null, "to" =&gt; min($this-&gt;data['sql_offset'] + $this-&gt;perpage, $this-&gt;entries), "sortfields" =&gt; array_keys($this-&gt;fields), "link_additions" =&gt; $this-&gt;paginationadditional, ] ]; } public function issearchresult(): bool { return $this-&gt;is_search; } }</file><file name="lib/Froxlor/UI/Listing.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui; use froxlor\currentuser; use froxlor\database\database; use froxlor\froxlor; use froxlor\ui\panel\ui; use invalidargumentexception; class listing { public static function format(collection $collection, array $tabellisting, string $id, array $listing_search_additional_param = []): array { $tabellisting = $tabellisting[$id]; $collection_data = $collection-&gt;get(); return [ 'id' =&gt; $id, 'title' =&gt; $tabellisting['title'], 'description' =&gt; $tabellisting['description'] ?? null, 'icon' =&gt; $tabellisting['icon'] ?? null, 'table' =&gt; [ 'th' =&gt; self::generatetableheadings($tabellisting), 'tr' =&gt; self::generatetablerows($collection_data['data']['list'], $tabellisting), ], 'pagination' =&gt; $collection_data['pagination'], 'empty_msg' =&gt; $tabellisting['empty_msg'] ?? null, 'total_entries' =&gt; ($collection-&gt;getpagination() instanceof pagination) ? $collection-&gt;getpagination()-&gt;getentries() : 0, 'is_search' =&gt; $collection-&gt;getpagination() instanceof pagination &amp;&amp; $collection-&gt;getpagination()-&gt;issearchresult(), 'self_overview' =&gt; $tabellisting['self_overview'] ?? [], 'available_columns' =&gt; self::getavailablecolumnsforlisting($tabellisting), 'no_search' =&gt; $tabellisting['no_search'] ?? false, 'listing_search_additional_param' =&gt; $listing_search_additional_param, ]; } public static function formatfromarray(array $collection, array $tabellisting, string $id): array { return [ 'id' =&gt; $id, 'title' =&gt; $tabellisting['title'], 'description' =&gt; $tabellisting['description'] ?? null, 'icon' =&gt; $tabellisting['icon'] ?? null, 'table' =&gt; [ 'th' =&gt; self::generatetableheadings($tabellisting), 'tr' =&gt; self::generatetablerows($collection['data'], $tabellisting), ], 'pagination' =&gt; $collection['pagination'], 'empty_msg' =&gt; $tabellisting['empty_msg'] ?? null, 'self_overview' =&gt; $tabellisting['self_overview'] ?? [], 'available_columns' =&gt; self::getavailablecolumnsforlisting($tabellisting), 'no_search' =&gt; $tabellisting['no_search'] ?? false, ]; } private static function generatetableheadings(array $tabellisting): array { $heading = []; // table headings columns foreach ($tabellisting['visible_columns'] $visible_column) { (isset($tabellisting['columns'][$visible_column]['visible']) &amp;&amp; !$tabellisting['columns'][$visible_column]['visible']) { continue; } $heading[$visible_column] = [ 'text' =&gt; $tabellisting['columns'][$visible_column]['label'], 'class' =&gt; $tabellisting['columns'][$visible_column]['class'] ?? null, ]; } // table headings actions (isset($tabellisting['actions'])) { $heading['actions'] = [ 'text' =&gt; lng('panel.options'), 'class' =&gt; 'text-end', ]; } return $heading; } /** * @throws exception */ private static function generatetablerows(array $list, array $tabellisting): array { $rows = []; // create new row item foreach ($list $row =&gt; $fields) { // generate columns item foreach ($tabellisting['visible_columns'] $col =&gt; $visible_column) { // continue column visible (isset($tabellisting['columns'][$visible_column]['visible']) &amp;&amp; !$tabellisting['columns'][$visible_column]['visible']) { continue; } // get data filed defined $field = $tabellisting['columns'][$visible_column]['field'] ?? null; $data = $field ? self::getmultiarrayfromstring($fields, $field) : null; // call user function given column defined return data field, otherwise throw exception $callback = $tabellisting['columns'][$visible_column]['callback'] ?? null; ($callback) { $rows[$row]['td'][$col]['data'] = call_user_func($callback, ['data' =&gt; $data, 'fields' =&gt; $fields]); } elseif ($field) { $rows[$row]['td'][$col]['data'] = $data; } else { throw new invalidargumentexception('the visible column "' . $visible_column . '" neither "callback" "field" set.'); } // set class table-row defined $rows[$row]['td'][$col]['class'] = $tabellisting['columns'][$visible_column]['class'] ?? null; } // set row classes format_callback (isset($tabellisting['format_callback'])) { $class = []; foreach ($tabellisting['format_callback'] $format_callback) { $class[] = call_user_func($format_callback, ['fields' =&gt; $fields]); } $rows[$row]['class'] = implode(' ', $class); } // set actions row (isset($tabellisting['actions'])) { $actions = self::setlinks($tabellisting['actions'], $fields); $rows[$row]['td'][] = [ 'class' =&gt; 'text-end', 'data' =&gt; [ 'macro' =&gt; 'actions', 'data' =&gt; $actions ] ]; } } return $rows; } public static function getmultiarrayfromstring(array $arr, ?string $str) { foreach (explode('.', $str) $key) { (!array_key_exists($key, $arr)) { return null; } $arr = $arr[$key]; } return $arr; } private static function setlinks(array $actions, array $item): array { $linker = ui::getlinker(); // check action href foreach ($actions $key =&gt; $action) { // complete link built via callback (isset($action['callback']) &amp;&amp; !empty($action['callback'])) { $action = call_user_func($action['callback'], ['fields' =&gt; $item]); $actions[$key] = $action; } // call user function visible array (isset($action['visible']) &amp;&amp; is_array($action['visible'])) { $actions[$key]['visible'] = call_user_func($action['visible'], ['fields' =&gt; $item]); } // set link href array (isset($action['href']) &amp;&amp; is_array($action['href'])) { // search "columns" href array foreach ($action['href'] $href_key =&gt; $href_value) { $length = strlen(':'); (substr($href_value, 0, $length) === ':') { $column = ltrim($href_value, ':'); $action['href'][$href_key] = $item[$column]; } } // set actual link linker $actions[$key]['href'] = $linker-&gt;getlink($action['href']); } // modal trigger - always require valid callback (isset($action['modal']) &amp;&amp; !empty($action['modal'])) { $actions[$key]['modal'] = call_user_func($action['modal'], ['fields' =&gt; $item]); } } return $actions; } private static function getavailablecolumnsforlisting(array $tabellisting): array { $result = []; (isset($tabellisting['columns'])) { foreach ($tabellisting['columns'] $column =&gt; $coldata) { (isset($coldata['visible']) &amp;&amp; !$coldata['visible']) { continue; } $result[$column] = [ 'label' =&gt; $coldata['label'], 'checked' =&gt; in_array($column, $tabellisting['visible_columns']), 'searchable' =&gt; $coldata['searchable'] ?? true, 'isdefaultsearchfield' =&gt; $coldata['isdefaultsearchfield'] ?? false, ]; } } return $result; } /** * store column listing selection user database * selection array look like this: * [ * 'section_name' =&gt; [ * 'column_name', * 'column_name', * 'column_name' * ] * ] * * @param array $tabellisting * @return array */ public static function storecolumnlistingforuser(array $tabellisting): array { $section = array_key_first($tabellisting); (empty($section) || !is_array($tabellisting[$section]) || empty($tabellisting[$section])) { throw new invalidargumentexception("invalid selection array " . __method__); } $userid = 'customerid'; (currentuser::isadmin()) { $userid = 'adminid'; } // include possible tablelisting-definitions check right section foreach(glob(froxlor::getinstalldir().'lib/tablelisting/{,*/}*.php', glob_brace) $tbl_file) { $table_listings = include $tbl_file; (!isset($table_listings[$section])) { continue; } else { break; } } $columns_available = array_keys($table_listings[$section]['columns']); // filter unknown columns foreach ($tabellisting[$section] $index =&gt; $column_changed) { (!in_array($column_changed, $columns_available)) { unset($tabellisting[$section][$index]); } } // delete possible existing entry self::deletecolumnlistingforuser($tabellisting); // add new entry $ins_stmt = database::prepare(" insert `" . table_panel_usercolumns . "` set `" . $userid . "` = :uid, `section` = :section, `columns` = :cols "); database::pexecute($ins_stmt, [ 'uid' =&gt; currentuser::getfield($userid), 'section' =&gt; $section, 'cols' =&gt; json_encode($tabellisting[$section]) ]); return $tabellisting[$section]; } /** * delete column listing selection user database * * @param array $tabellisting * @return bool */ public static function deletecolumnlistingforuser(array $tabellisting): bool { $section = array_key_first($tabellisting); (empty($section)) { throw new invalidargumentexception("invalid selection array " . __method__); } $userid = 'customerid'; (currentuser::isadmin()) { $userid = 'adminid'; } $del_stmt = database::prepare(" delete `" . table_panel_usercolumns . "` `" . $userid . "` = :uid `section` = :section "); database::pexecute($del_stmt, ['uid' =&gt; currentuser::getfield($userid), 'section' =&gt; $section]); return true; } public static function getvisiblecolumnsforlisting(string $listing, array $default_columns): array { $userid = 'customerid'; (currentuser::isadmin()) { $userid = 'adminid'; } $sel_stmt = database::prepare(" select `columns` `" . table_panel_usercolumns . "` `" . $userid . "` = :uid `section` = :section "); $columns_json = database::pexecute_first($sel_stmt, [ 'uid' =&gt; currentuser::getfield($userid), 'section' =&gt; $listing ]); ($columns_json &amp;&amp; isset($columns_json['columns'])) { return json_decode($columns_json['columns'], true); } return $default_columns; } }</file><file name="lib/Froxlor/UI/HTML.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui; use froxlor\settings; class html { /** * build navigation sidebar * * @param array $navigation data * @param array $userinfo userinfo user * * @return array content navigation bar according user-permissions */ public static function buildnavigation(array $navigation, array $userinfo) { $returnvalue = []; // sanitize user-given input (url-manipulation) $req_page = request::get('page'); (!empty($req_page) &amp;&amp; is_array($req_page)) { $req_page = (string)array_shift($req_page); } // need preserve $_get['page'] = $req_page; $req_action = request::get('action'); (!empty($req_action) &amp;&amp; is_array($req_action)) { $req_action = (string)array_shift($req_action); } // need preserve $_get['action'] = $req_action; foreach ($navigation $box) { ((!isset($box['show_element']) || $box['show_element'] === true) &amp;&amp; (!isset($box['required_resources']) || $box['required_resources'] == '' || (isset($userinfo[$box['required_resources']]) &amp;&amp; ((int)$userinfo[$box['required_resources']] &gt; 0 || $userinfo[$box['required_resources']] == '-1')))) { $navigation_links = []; $box_active = false; (isset($box['url']) &amp;&amp; $box['url'] == basename($_server["script_filename"])) { $box_active = true; } foreach ($box['elements'] $element) { ((!isset($element['show_element']) || $element['show_element'] === true) &amp;&amp; (!isset($element['required_resources']) || $element['required_resources'] == '' || (isset($userinfo[$element['required_resources']]) &amp;&amp; ((int)$userinfo[$element['required_resources']] &gt; 0 || $userinfo[$element['required_resources']] == '-1')))) { $target = ''; $active = false; $navurl = '#'; (isset($element['url']) &amp;&amp; trim($element['url']) != '') { (isset($element['new_window']) &amp;&amp; $element['new_window'] == true) { $target = ' target="_blank"'; } ( ((empty($req_page) &amp;&amp; substr_count($element['url'], "page=") == 0) || (!empty($req_page) &amp;&amp; substr_count($element['url'], "page=" . $req_page) &gt; 0)) &amp;&amp; substr_count($element['url'], basename($_server["script_filename"])) &gt; 0 ) { $active = true; $box_active = true; } $navurl = htmlspecialchars($element['url']); $navlabel = $element['label']; $icon = $element['icon'] ?? null; } else { $navlabel = $element['label']; $icon = $element['icon'] ?? null; } $navigation_links[] = [ 'url' =&gt; $navurl, 'target' =&gt; $target, 'active' =&gt; $active, 'label' =&gt; $navlabel, 'icon' =&gt; $icon, 'add_shortlink' =&gt; $element['add_shortlink'] ?? null, 'is_external' =&gt; $element['is_external'] ?? false, ]; } } (!empty($navigation_links)) { $target = ''; (isset($box['url']) &amp;&amp; trim($box['url']) != '') { (isset($box['new_window']) &amp;&amp; $box['new_window'] == true) { $target = ' target="_blank"'; } $navurl = htmlspecialchars($box['url']); $navlabel = $box['label']; $icon = $box['icon'] ?? null; } else { $navurl = "#"; $navlabel = $box['label']; $icon = $box['icon'] ?? null; } $returnvalue[] = [ 'url' =&gt; $navurl, 'target' =&gt; $target, 'label' =&gt; $navlabel, 'icon' =&gt; $icon, 'items' =&gt; $navigation_links, 'active' =&gt; ((int)settings::get('panel.menu_collapsed') == 0 ? 1 : $box_active) ]; } } } return $returnvalue; } /** * return html code option within &lt;select&gt; * * @param string $title * caption * @param string $value * value returned * @param string $selvalue * values selected default. * @param bool $title_trusted * whether title may contain html * @param bool $value_trusted * whether value may contain html * @param int $id * @param bool $disabled * * @return string html code * * @deprecated */ public static function makeoption($title, $value, $selvalue = null, $title_trusted = false, $value_trusted = false, $id = null, $disabled = false) { ($selvalue !== null &amp;&amp; ((is_array($selvalue) &amp;&amp; in_array($value, $selvalue)) || $value == $selvalue)) { $selected = 'selected="selected"'; } else { $selected = ''; } ($disabled) { $selected .= ' disabled="disabled"'; } (!$title_trusted) { $title = htmlspecialchars($title); } (!$value_trusted) { $value = htmlspecialchars($value); } $id_str = ' '; ($id !== null) { $id_str = 'id="' . $id . '"'; } $option = '&lt;option value="' . $value . '" ' . $id_str . $selected . ' &gt;' . $title . '&lt;/option&gt;'; return $option; } /** * output boolean confirm-dialog * * @param string $text * question * @param string $yesfile * file called post user clicks yes * @param array $params * values given $yesfile. format: array(variable1=&gt;value1, variable2=&gt;value2, * variable3=&gt;value3) * @param string $replacer * value possible existing string-replacer question * @param array $back_link * * @return string * @author froxlor team &lt;team@froxlor.org&gt; (2010-) * */ public static function askyesno(string $text, string $yesfile, array $params = [], string $replacer = '', array $back_link = []) { $text = lng('question.' . $text, [htmlspecialchars($replacer)]); panel\ui::view('form/yesnoquestion.html.twig', [ 'action' =&gt; $yesfile, 'url_params' =&gt; $params, 'question' =&gt; $text, 'back_link' =&gt; $back_link ]); exit(); } public static function askyesnowithcheckbox(string $text, string $chk_text, string $yesfile, array $params = [], string $replacer = '', bool $show_checkbox = true) { $text = lng('question.' . $text, [htmlspecialchars($replacer)]); $chk_text = lng('question.' . $chk_text); panel\ui::view('form/yesnoquestion.html.twig', [ 'action' =&gt; $yesfile, 'url_params' =&gt; $params, 'question' =&gt; $text, 'with_checkbox' =&gt; [ 'chk_text' =&gt; $chk_text, 'show' =&gt; $show_checkbox ] ]); exit(); } public static function askotp(string $text, string $targetfile, array $params = [], string $replacer = '', array $back_link = []) { $text = lng('question.' . $text, [htmlspecialchars($replacer)]); panel\ui::view('form/otpquestion.html.twig', [ 'action' =&gt; $targetfile, 'url_params' =&gt; $params, 'question' =&gt; $text, 'back_link' =&gt; $back_link ]); exit(); } }</file><file name="lib/Froxlor/UI/Data.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui; class data { public static function getformfielddataemail($fieldname, $fielddata, $input) { return self::getformfielddatatext($fieldname, $fielddata, $input); } public static function getformfielddatatext($fieldname, $fielddata, $input) { (isset($input[$fieldname])) { $newfieldvalue = str_replace("\r\n", "\n", $input[$fieldname]); } else { $newfieldvalue = $fielddata['default']; } return $newfieldvalue; } public static function getformfielddataurl($fieldname, $fielddata, $input) { return self::getformfielddatatext($fieldname, $fielddata, $input); } public static function getformfielddataselect($fieldname, $fielddata, $input) { (isset($input[$fieldname])) { $newfieldvalue = $input[$fieldname]; } else { $newfieldvalue = $fielddata['default']; } (is_array($newfieldvalue)) { $newfieldvalue = implode(',', $newfieldvalue); } return $newfieldvalue; } public static function getformfielddatanumber($fieldname, $fielddata, $input) { (isset($input[$fieldname])) { $newfieldvalue = (int)$input[$fieldname]; } else { $newfieldvalue = (int)$fielddata['default']; } return $newfieldvalue; } public static function getformfielddatacheckbox($fieldname, $fielddata, $input) { (isset($input[$fieldname]) &amp;&amp; ($input[$fieldname] === '1' || $input[$fieldname] === 1 || $input[$fieldname] === true || strtolower($input[$fieldname]) === 'yes' || strtolower($input[$fieldname]) === 'ja')) { $newfieldvalue = '1'; } else { $newfieldvalue = '0'; } return $newfieldvalue; } public static function getformfielddataimage($fieldname, $fielddata, $input) { // always make system think new data trigger save function actually check everything return time(); } public static function manipulateformfielddatadate($fieldname, $fielddata, $newfieldvalue) { (isset($fielddata['date_timestamp']) &amp;&amp; $fielddata['date_timestamp'] === true) { $newfieldvalue = strtotime($newfieldvalue); } return $newfieldvalue; } }</file><file name="lib/Froxlor/UI/Response.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui; use exception; use froxlor\ui\panel\ui; class response { /** * sends header ( 'location ...' ) browser. * * @param string $destination * destination * @param array $get_variables * get-variables * @param boolean $isrelative * target creating redirect * relative absolute url * * @return boolean false params array */ public static function redirectto($destination, $get_variables = null, $isrelative = true) { (is_array($get_variables)) { $linker = new linker($destination); foreach ($get_variables $key =&gt; $value) { $linker-&gt;add($key, $value); } ($isrelative) { $linker-&gt;protocol = ''; $linker-&gt;hostname = ''; $path = './'; } else { (isset($_server['https']) &amp;&amp; strtolower($_server['https']) == 'on') { $linker-&gt;protocol = 'https'; } else { $linker-&gt;protocol = 'http'; } $linker-&gt;hostname = $_server['http_host']; (dirname($_server['php_self']) == '/') { $path = '/'; } else { $path = dirname($_server['php_self']) . '/'; } $linker-&gt;filename = $path . $destination; } header('location: ' . $linker-&gt;getlink()); exit; } elseif ($get_variables == null) { $linker = new linker($destination); header('location: ' . $linker-&gt;getlink()); exit; } return false; } /** * prints one errormessages screen * * @param array $errors * errormessages * @param string $replacer * %s errormessage replaced string. * @param bool $throw_exception * * @throws exception * @author ron brand &lt;ron.brand@web.de&gt; * @author florian lippert &lt;flo@syscp.org&gt; (2003-2009) */ public static function standarderror($errors = '', $replacer = '', $throw_exception = false) { $_session['requestdata'] = $_post; $replacer = htmlentities($replacer); (!is_array($errors)) { $errors = [ $errors ]; } $link_ref = ''; (isset($_server['http_referer']) &amp;&amp; strpos($_server['http_referer'], $_server['http_host']) !== false) { $link_ref = htmlentities($_server['http_referer']); } $error = ''; foreach ($errors $single_error) { (strpos($single_error, ".") === false) { $single_error = 'error.' . $single_error; } $single_error = lng($single_error, [htmlentities($replacer)]); (empty($error)) { $error = $single_error; } else { $error .= ' ' . $single_error; } } ($throw_exception) { throw new exception(strip_tags($error), 400); } ui::view('misc/alert.html.twig', [ 'type' =&gt; 'danger', 'btntype' =&gt; 'light', 'heading' =&gt; lng('error.error'), 'alert_msg' =&gt; $error, 'redirect_link' =&gt; $link_ref ]); exit; } public static function dynamicerror($message, bool $nosession = false) { $_session['requestdata'] = $_post; $link_ref = ''; (isset($_server['http_referer']) &amp;&amp; strpos($_server['http_referer'], $_server['http_host']) !== false) { $link_ref = htmlentities($_server['http_referer']); } $tpl = $nosession ? 'misc/alert_nosession.html.twig' : 'misc/alert.html.twig'; ui::view($tpl, [ 'type' =&gt; 'danger', 'btntype' =&gt; 'light', 'heading' =&gt; lng('error.error'), 'alert_msg' =&gt; $message, 'redirect_link' =&gt; $link_ref ]); exit; } /** * prints one errormessages screen * * @param array $success_message * errormessages * @param string $replacer * %s errormessage replaced string. * @param array $params * @param bool $throw_exception * * @throws exception * @author florian lippert &lt;flo@syscp.org&gt; (2003-2009) */ public static function standardsuccess($success_message = '', $replacer = '', $params = [], $throw_exception = false) { (strpos($success_message, ".") === false) { $success_message = 'success.' . $success_message; } $success_message = lng($success_message, [htmlentities($replacer)]); ($throw_exception) { throw new exception(strip_tags($success_message), 200); } (is_array($params) &amp;&amp; isset($params['filename'])) { $redirect_url = $params['filename']; unset($params['filename']); $first = true; foreach ($params $varname =&gt; $value) { ($value != '') { $redirect_url .= ($first ? '?' : '&amp;amp;') . $varname . '=' . $value; ($first) { $first = false; } } } } else { $redirect_url = ''; } ui::view('misc/alert.html.twig', [ 'type' =&gt; 'success', 'btntype' =&gt; 'light', 'heading' =&gt; lng('success.success'), 'alert_msg' =&gt; $success_message, 'redirect_link' =&gt; $redirect_url ]); exit; } }</file><file name="lib/Froxlor/UI/Request.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui; use froxlor\phphelper; use voku\helper\antixss; class request { private static $cleaned = false; /** * get key current $_get $_post request. * * @param $key * @param mixed|null $default * @return mixed|string|null */ public static function any($key, $default = null) { self::cleanall(); return $_get[$key] ?? $_post[$key] ?? $default; } /** * get key current $_get request. * * @param $key * @param mixed|null $default * @return mixed|string|null */ public static function get($key, $default = null) { self::cleanall(); return $_get[$key] ?? $default; } /** * get key current $_post request. * * @param $key * @param mixed|null $default * @return mixed|string|null */ public static function post($key, $default = null) { self::cleanall(); return $_post[$key] ?? $default; } /** * return complete $_post array * * @return array */ public static function postall() { self::cleanall(); return $_post ?? []; } /** * check xss attempts clean important globals * unsetting every variable registered $_request variable */ public static function cleanall() { (!self::$cleaned) { foreach ($_request $key =&gt; $value) { (isset($$key)) { unset($$key); } } unset($value); $antixss = new antixss(); $antixss-&gt;addneverallowedregex([ '{{(.*)}}' =&gt; '' ]); // check $_get phphelper::cleanglobal($_get, $antixss); // check $_post phphelper::cleanglobal($_post, $antixss); // check $_cookie phphelper::cleanglobal($_cookie, $antixss); self::$cleaned = true; } } /** * check key existing current request. * * @param $key * @return bool|mixed */ public static function exist($key) { return (bool)$_get[$key] ?? $_post[$key] ?? false; } }</file><file name="lib/Froxlor/UI/index.html" /><file name="lib/Froxlor/UI/Collection.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui; use froxlor\settings; class collection { private string $class; private array $has = []; private array $params; private array $userinfo; private ?pagination $pagination = null; private bool $internal = false; public function __construct(string $class, array $userinfo, array $params = []) { $this-&gt;class = $class; $this-&gt;params = $params; $this-&gt;userinfo = $userinfo; } public function getlist(): array { return $this-&gt;getdata()['list']; } public function getdata(): array { return $this-&gt;get()['data']; } public function get(): array { $result = $this-&gt;getlisting($this-&gt;class, $this-&gt;params); // check api result contains items (not overall listingcount might search-resultset) (count($result)) { foreach ($this-&gt;has $has) { $attributes = $this-&gt;getlisting($has['class'], $has['params']); foreach ($result['data']['list'] $key =&gt; $item) { foreach ($attributes['data']['list'] $list) { ($item[$has['parentkey']] == $list[$has['childkey']]) { $result['data']['list'][$key][$has['column']] = $list; } } } } } // attach pagination available ($this-&gt;pagination) { $result = array_merge($result, $this-&gt;pagination-&gt;getapiresponseparams()); } return $result; } private function getlisting($class, $params): array { return json_decode($class::getlocal($this-&gt;userinfo, $params, $this-&gt;internal)-&gt;listing(), true); } public function getjson(): string { return json_encode($this-&gt;get()); } public function has(string $column, string $class, string $parentkey = 'id', string $childkey = 'id', array $params = []): collection { $this-&gt;has[] = [ 'column' =&gt; $column, 'class' =&gt; $class, 'parentkey' =&gt; $parentkey, 'childkey' =&gt; $childkey, 'params' =&gt; $params ]; return $this; } public function addparam(array $keyval): collection { $this-&gt;params = array_merge($this-&gt;params, $keyval); return $this; } public function withpagination(array $columns, array $default_sorting = [], array $pagination_additional_params = []): collection { // get searchable columns $sortablecolumns = []; foreach ($columns $key =&gt; $column) { (!isset($column['sortable']) || (isset($column['sortable']) &amp;&amp; $column['sortable'])) { $sortablecolumns[$key] = $column; } } // prepare pagination $this-&gt;pagination = new pagination($sortablecolumns, $this-&gt;count(), (int)settings::get('panel.paging'), $default_sorting, $pagination_additional_params); $this-&gt;params = array_merge($this-&gt;params, $this-&gt;pagination-&gt;getapicommandparams()); return $this; } public function count(): int { return json_decode($this-&gt;class::getlocal($this-&gt;userinfo, $this-&gt;params, $this-&gt;internal)-&gt;listingcount(), true)['data']; } public function getpagination(): ?pagination { return $this-&gt;pagination; } public function setinternal(bool $internal): collection { $this-&gt;internal = $internal; return $this; } }</file><file name="lib/Froxlor/UI/Panel/CustomReflection.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\panel; use reflectionclass; use runtimeexception; use twig\extension\abstractextension; use twig\twigfunction; class customreflection extends abstractextension { /** * * {@inheritdoc} */ public function getfunctions() { return [ new twigfunction('call_static', [ $this, 'callstaticmethod' ]), new twigfunction('get_static', [ $this, 'getstaticproperty' ]) ]; } public function callstaticmethod($class, $method, array $args = []) { $refl = new reflectionclass($class); // check method static public ($refl-&gt;hasmethod($method) &amp;&amp; $refl-&gt;getmethod($method)-&gt;isstatic() &amp;&amp; $refl-&gt;getmethod($method)-&gt;ispublic()) { return call_user_func_array($class . '::' . $method, $args); } throw new runtimeexception(sprintf('invalid static method call class %s method %s', $class, $method)); } public function getstaticproperty($class, $property) { $refl = new reflectionclass($class); // check property static public ($refl-&gt;hasproperty($property) &amp;&amp; $refl-&gt;getproperty($property)-&gt;isstatic() &amp;&amp; $refl-&gt;getproperty($property)-&gt;ispublic()) { return $refl-&gt;getproperty($property)-&gt;getvalue(); } throw new runtimeexception(sprintf('invalid static property get class %s property %s', $class, $property)); } /** * * {@inheritdoc} */ public function getname() { return 'customreflection'; } }</file><file name="lib/Froxlor/UI/Panel/FroxlorTwig.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ declare(strict_types=1); namespace froxlor\ui\panel; use froxlor\idna\idnawrapper; use froxlor\settings; use froxlor\system\markdown; use parsedown; use twig\extension\abstractextension; use twig\twigfilter; use twig\twigfunction; use twig\twigtest; class froxlortwig extends abstractextension { public function getfilters() { return [ new twigfilter('formatbytes', [ $this, 'formatbytesfilter' ]), new twigfilter('formatip', [ $this, 'formatipfilter' ]), new twigfilter('idndecode', [ $this, 'idndecodefilter' ]), new twigfilter('markdown', [ $this, 'callmarkdown' ]) ]; } public function gettests() { return [ new twigtest('numeric', function ($value) { return is_numeric($value); }) ]; } public function getfunctions() { return [ new twigfunction('get_setting', [ $this, 'getsetting' ]), new twigfunction('get_config', [ $this, 'getconfig' ]), new twigfunction('lng', [ $this, 'getlang' ]), new twigfunction('linker', [ $this, 'getlink' ]), new twigfunction('mix', [ $this, 'getmix' ]), new twigfunction('vite', [ $this, 'getvite' ]) ]; } public function formatbytesfilter($size, $suffix = "b", $factor = 1) { $size *= $factor; $units = [ '', 'k', 'm', 'g', 't', 'p', 'e', 'z', 'y' ]; $power = $size &gt; 0 ? floor(log($size, 1024)) : 0; ($power &lt; 0) { $size = 0.00; $power = 0; } return number_format($size / pow(1024, $power), 2, '.', ',') . ' ' . $units[$power] . $suffix; } public function formatipfilter($addr) { return inet_ntop(inet_pton($addr)); } public function idndecodefilter($entity) { $idna_convert = new idnawrapper(); return $idna_convert-&gt;decode($entity); } public function getsetting($setting = null) { return settings::get($setting); } public function getconfig($config = null) { return settings::config($config); } public function getlang($identifier = null, array $arguments = []) { return lng($identifier, $arguments); } public function getlink($linkopts) { return ui::getlinker()-&gt;getlink($linkopts); } public function callmarkdown($string): string { return markdown::cleancustomnotes($string ?? ""); } /** * * {@inheritdoc} */ public function getname() { return 'froxlortwig'; } public function getmix($mix = '') { return mix($mix); } public function getvite($basehref = '', $vite = [], $defaults = []) { return vite($basehref, $vite ?? $defaults); } }</file><file name="lib/Froxlor/UI/Panel/index.html" /><file name="lib/Froxlor/UI/Panel/UI.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ declare(strict_types=1); namespace froxlor\ui\panel; use directoryiterator; use exception; use froxlor\currentuser; use froxlor\filedir; use froxlor\froxlor; use froxlor\phphelper; use froxlor\settings; use froxlor\ui\linker; use twig\environment; use twig\extension\debugextension; use twig\loader\filesystemloader; class ui { /** * twig object * * @var environment */ private static $twig = null; /** * twig buffer * * @var array */ private static $twigbuf = []; /** * linker class object */ private static $linker = null; /** * current logged user * * @var array */ private static $userinfo = []; /** * default fallback theme * * @var string */ private static $default_theme = 'froxlor'; private static $install_mode = false; public static function requestishttps(): bool { $ishttps = $_server['https'] ?? $_server['request_scheme'] ?? $_server['http_x_forwarded_proto'] ?? null; return $ishttps &amp;&amp; (strcasecmp('on', $ishttps) == 0 || strcasecmp('https', $ishttps) == 0); } /** * extract cookie host http_host, stripping port. */ public static function getcookiehost(): ?string { (empty($_server['http_host'])) return null; $colonposition = strrpos($_server['http_host'], ':'); // there's port host ($colonposition === false) return $_server['http_host']; $closingsquarebracketposition = strrpos($_server['http_host'], ']'); // host ipv4 address hostname port ($closingsquarebracketposition === false) return substr($_server['http_host'], 0, $colonposition); // host ipv6 address port return substr($_server['http_host'], 0, $closingsquarebracketposition + 1); } /** * send various security related headers */ public static function sendheaders() { session_set_cookie_params([ 'lifetime' =&gt; self::$install_mode ? 7200 : 600, // renewed based settings lib/init.php 'path' =&gt; '/', 'domain' =&gt; self::getcookiehost(), 'secure' =&gt; self::requestishttps(), 'httponly' =&gt; true, 'samesite' =&gt; 'lax' ]); session_start(); header("content-type: text/html; charset=utf-8"); // prevent froxlor pages cached header("cache-control: no-store, no-cache, must-revalidate"); header("pragma: no-cache"); header('last-modified: ' . gmdate('d, h:i:s \g\m\t', time())); header('expires: ' . gmdate('d, h:i:s \g\m\t', time())); // prevent inline - js executed (i.e. xss) browsers support this, // inline-js longer allowed used // see: http://people.mozilla.org/~bsterne/content-security-policy/index.html // new stuff see: https://www.owasp.org/index.php/list_of_useful_http_headers https://www.owasp.org/index.php/content_security_policy $csp_content = "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; object-src 'self'; frame-src 'self'; frame-ancestors 'self';"; header("content-security-policy: " . $csp_content); header("x-content-security-policy: " . $csp_content); header("x-webkit-csp: " . $csp_content); // allow load froxlor iframe prevent i.e. clickjacking header("x-frame-options: deny"); // internet explorer shall guess content-type, see: // http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx header("x-content-type-options: nosniff"); // ensure default timezone set (function_exists("date_default_timezone_set") &amp;&amp; function_exists("date_default_timezone_get")) { @date_default_timezone_set(@date_default_timezone_get()); } } public static function sendsslheaders() { /** * froxlor called via https -&gt; enforce next time settings hsts header according settings */ (isset($_server['https']) &amp;&amp; (strtolower($_server['https']) != 'off')) { $maxage = settings::get('system.hsts_maxage'); (empty($maxage)) { $maxage = 0; } $hsts_header = "strict-transport-security: max-age=" . $maxage; (settings::get('system.hsts_incsub') == '1') { $hsts_header .= "; includesubdomains"; } (settings::get('system.hsts_preload') == '1') { $hsts_header .= "; preload"; } header($hsts_header); } } /** * initialize twig template engine */ public static function inittwig(bool $install_mode = false) { self::$install_mode = $install_mode; // init twig template engine $loader = new filesystemloader(froxlor::getinstalldir() . '/templates/'); $twig_params = [ 'auto_reload' =&gt; true, 'debug' =&gt; false, ]; (is_writable(froxlor::getinstalldir() . '/cache')) { $twig_params['cache'] = froxlor::getinstalldir() . '/cache'; } self::$twig = new environment($loader, $twig_params); self::$twig-&gt;addextension(new debugextension()); self::$twig-&gt;addextension(new customreflection()); self::$twig-&gt;addextension(new froxlortwig()); // empty buffer self::$twigbuf = []; } /** * twig wrapper * * @return environment */ public static function twig(): ?environment { return self::$twig; } public static function getlinker(): linker { return self::$linker; } public static function setlinker($linker = null) { self::$linker = $linker; } public static function setcurrentuser($userinfo = null) { self::$userinfo = $userinfo; } public static function getcurrentuser(): array { return self::$userinfo; } /** * returns array available themes * * @return array * @throws exception */ public static function getthemes(): array { $themespath = filedir::makecorrectdir(froxlor::getinstalldir() . '/templates/'); $themes_available = []; (is_dir($themespath)) { $its = new directoryiterator($themespath); foreach ($its $it) { ($it-&gt;isdir() &amp;&amp; $it-&gt;getfilename() != '.' &amp;&amp; $it-&gt;getfilename() != '..' &amp;&amp; $it-&gt;getfilename() != 'misc') { $theme = $themespath . $it-&gt;getfilename(); (file_exists($theme . '/config.json')) { $themeconfig = json_decode(file_get_contents($theme . '/config.json'), true); (array_key_exists('variants', $themeconfig) &amp;&amp; is_array($themeconfig['variants'])) { foreach ($themeconfig['variants'] $variant =&gt; $data) { ($variant == "default") { $themes_available[$it-&gt;getfilename()] = $it-&gt;getfilename(); } elseif (array_key_exists('description', $data)) { $themes_available[$it-&gt;getfilename() . '_' . $variant] = $data['description']; } else { $themes_available[$it-&gt;getfilename() . '_' . $variant] = $it-&gt;getfilename() . ' (' . $variant . ')'; } } } else { $themes_available[$it-&gt;getfilename()] = $it-&gt;getfilename(); } } } } } return $themes_available; } public static function view($name, array $context = []) { self::twigbuffer($name, $context); self::twigoutputbuffer(); } /** * wrapper twig's "render" function buffer output * * @see \twig\environment::render() */ public static function twigbuffer($name, array $context = []) { $template_file = self::validatethemetemplate($name); self::$twigbuf[] = [ $template_file =&gt; $context ]; } public static function validatethemetemplate(string $name, string $theme = "") { (empty(trim($theme))) { $theme = self::gettheme(); } $template_file = $theme . '/' . $name; (!file_exists(froxlor::getinstalldir() . '/templates/' . $template_file)) { phphelper::phperrhandler(e_user_warning, "template '" . $template_file . "' could found, trying fallback theme", __file__, __line__); $template_file = self::$default_theme . '/'. $name; (!file_exists(froxlor::getinstalldir() . '/templates/' . $template_file)) { phphelper::phperrhandler(e_user_error, "unknown template '" . $template_file . "'", __file__, __line__); } } return $template_file; } public static function gettheme() { // fallback $theme = self::$default_theme; (!self::$install_mode) { // system default (froxlor::versioncompare2(settings::get('panel.version'), '2.0.0-beta1') == -1) { // pre 2.0 settings::set('panel.default_theme', 'froxlor'); } else { $theme = (settings::get('panel.default_theme') !== null) ? settings::get('panel.default_theme') : $theme; // customer theme (currentuser::hassession() &amp;&amp; currentuser::getfield('theme') != $theme) { $theme = currentuser::getfield('theme'); } } } // check template-variant (preg_match("/([a-z0-9.\-]+)_([a-z0-9.\-]+)/i", $theme, $matches)) { $theme = $matches[1]; } (!file_exists(froxlor::getinstalldir() . '/templates/' . $theme)) { phphelper::phperrhandler(e_user_warning, "theme '" . $theme . "' could found.", __file__, __line__); $theme = self::$default_theme; } return $theme; } /** * echo output buffer empty buffer-content */ public static function twigoutputbuffer() { $output = ""; foreach (self::$twigbuf $buf) { foreach ($buf $name =&gt; $context) { try { $output .= self::$twig-&gt;render($name, $context); } catch (exception $e) { // whoops, template error $errtpl = 'alert_nosession.html.twig'; (self::activeusersession()) { $errtpl = 'alert.html.twig'; } $edata = [ 'type' =&gt; "danger", 'heading' =&gt; "template error", 'alert_msg' =&gt; $e-&gt;getmessage(), 'alert_info' =&gt; $e-&gt;gettraceasstring() ]; try { // try user theme set $output .= self::$twig-&gt;render(self::gettheme() . '/misc/' . $errtpl, $edata); } catch (exception $e) { // try default theme different user theme (self::gettheme() != self::$default_theme) { $output .= self::$twig-&gt;render(self::$default_theme . '/misc/' . $errtpl, $edata); } else { throw $e; } } } } } echo $output; // empty buffer self::$twigbuf = []; } public static function activeusersession(): bool { return !empty(self::$userinfo); } }</file><file name="lib/Froxlor/UI/Callbacks/PHPConf.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; use froxlor\settings; use froxlor\idna\idnawrapper; use froxlor\ui\panel\ui; class phpconf { public static function domainlist(array $attributes): string { $idna = new idnawrapper; $domains = ""; $subdomains_count = count($attributes['fields']['subdomains']); foreach ($attributes['fields']['domains'] $configdomain) { $domains .= $idna-&gt;decode($configdomain) . "&lt;br&gt;"; } ($subdomains_count == 0 &amp;&amp; empty($domains)) { $domains = lng('admin.phpsettings.notused'); } else { (settings::get('panel.phpconfigs_hidesubdomains') == '1') { $domains .= !empty($subdomains_count) ? ((!empty($domains) ? '+ ' : '') . $subdomains_count . ' ' . lng('customer.subdomains')) : ''; } else { foreach ($attributes['fields']['subdomains'] $configdomain) { $domains .= $idna-&gt;decode($configdomain) . "&lt;br&gt;"; } } } return $domains; } public static function configslist(array $attributes) { $configs = ""; foreach ($attributes['fields']['configs'] $configused) { $configs .= $configused . "&lt;br&gt;"; } return $configs; } public static function isnotdefault(array $attributes) { (ui::getcurrentuser()['change_serversettings']) { return $attributes['fields']['id'] != 1; } return false; } public static function fpmconflink(array $attributes) { (ui::getcurrentuser()['change_serversettings']) { $linker = ui::getlinker(); return [ 'macro' =&gt; 'link', 'data' =&gt; [ 'text' =&gt; $attributes['data'], 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'phpsettings', 'page' =&gt; 'fpmdaemons', 'searchfield' =&gt; 'id', 'searchtext' =&gt; $attributes['fields']['fpmsettingid'], ]), ] ]; } return $attributes['data']; } }</file><file name="lib/Froxlor/UI/Callbacks/Text.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; use froxlor\currentuser; use froxlor\database\database; use froxlor\froxlor; use froxlor\phphelper; use froxlor\system\markdown; use froxlor\ui\panel\ui; use froxlor\user; use pdo; class text { public static function boolean(array $attributes): array { return [ 'macro' =&gt; 'boolean', 'data' =&gt; (bool)$attributes['data'] ]; } public static function yesno(array $attributes): array { return [ 'macro' =&gt; 'boolean', 'data' =&gt; $attributes['data'] == 'y' ]; } public static function type2fa(array $attributes): array { return [ 'macro' =&gt; 'type2fa', 'data' =&gt; (int)$attributes['data'] ]; } public static function customerfullname(array $attributes): string { return user::getcorrectfulluserdetails($attributes['fields'], true); } public static function size(array $attributes): string { return phphelper::sizereadable($attributes['data'], null, 'bi'); } public static function timestamp(array $attributes): string { return (int)$attributes['data'] &gt; 0 ? date('d.m.y h:i', (int)$attributes['data']) : lng('panel.never'); } public static function timestampuntil(array $attributes): string { return (int)$attributes['data'] &gt; 0 ? date('d.m.y h:i', (int)$attributes['data']) : lng('panel.unlimited'); } public static function crondesc(array $attributes): string { return lng('crondesc.' . $attributes['data']); } public static function shorten(array $attributes): string { return substr($attributes['data'], 0, 20) . '...'; } public static function wordwrap(array $attributes): string { return wordwrap($attributes['data'], 100, '&lt;br&gt;', true); } public static function customernotedetailmodal(array $attributes): array { $note = $attributes['fields']['custom_notes'] ?? ''; $key = $attributes['fields']['customerid'] ?? $attributes['fields']['adminid']; return [ 'entry' =&gt; $key, 'id' =&gt; 'cnmodal' . $key, 'title' =&gt; lng('usersettings.custom_notes.title') . ': ' . ($attributes['fields']['loginname'] ?? $attributes['fields']['adminname']), 'body' =&gt; nl2br(markdown::cleancustomnotes($note)) ]; } public static function apikeydetailmodal(array $attributes): array { $linker = ui::getlinker(); $result = $attributes['fields']; $apikey_data = include froxlor::getinstalldir() . '/lib/formfields/formfield.api_key.php'; $body = ui::twig()-&gt;render(ui::validatethemetemplate('/user/inline-form.html.twig'), [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'index', 'page' =&gt; 'apikeys']), 'formdata' =&gt; $apikey_data['apikey'], 'editid' =&gt; $attributes['fields']['id'] ]); return [ 'entry' =&gt; $attributes['fields']['id'], 'id' =&gt; 'akmodal' . $attributes['fields']['id'], 'title' =&gt; 'api-key ' . ($attributes['fields']['loginname'] ?? $attributes['fields']['adminname']), 'action' =&gt; 'apikeys', 'body' =&gt; $body ]; } public static function domainduplicatemodal(array $attributes): array { $linker = ui::getlinker(); $result = $attributes['fields']; $customers = [ 0 =&gt; lng('panel.please_choose') ]; $result_customers_stmt = database::prepare(" select `customerid`, `loginname`, `name`, `firstname`, `company` `" . table_panel_customers . "` " . (currentuser::getfield('customers_see_all') ? '' : " `adminid` = :adminid ") . " order coalesce(nullif(`name`,''), `company`) asc "); $params = []; (currentuser::getfield('customers_see_all') == '0') { $params['adminid'] = currentuser::getfield('adminid'); } database::pexecute($result_customers_stmt, $params); ($row_customer = $result_customers_stmt-&gt;fetch(pdo::fetch_assoc)) { $customers[$row_customer['customerid']] = user::getcorrectfulluserdetails($row_customer) . ' (' . $row_customer['loginname'] . ')'; } $domdup_data = include froxlor::getinstalldir() . '/lib/formfields/admin/domains/formfield.domains_duplicate.php'; $body = ui::twig()-&gt;render(ui::validatethemetemplate('/user/inline-form.html.twig'), [ 'formaction' =&gt; $linker-&gt;getlink(['section' =&gt; 'domains', 'page' =&gt; 'domains', 'action' =&gt; 'duplicate']), 'formdata' =&gt; $domdup_data['domain_duplicate'], 'editid' =&gt; $attributes['fields']['id'], 'nosubmit' =&gt; 0 ]); return [ 'entry' =&gt; $attributes['fields']['id'], 'id' =&gt; 'ddmodal' . $attributes['fields']['id'], 'title' =&gt; lng('admin.domain_duplicate_named', [$attributes['fields']['domain']]), 'action' =&gt; 'duplicate', 'body' =&gt; $body ]; } }</file><file name="lib/Froxlor/UI/Callbacks/Admin.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; use froxlor\ui\panel\ui; class admin { public static function canchangeserversettings(array $attributes) { return (bool)ui::getcurrentuser()['change_serversettings']; } public static function isnotme(array $attributes) { return (ui::getcurrentuser()['adminid'] != $attributes['fields']['adminid']); } }</file><file name="lib/Froxlor/UI/Callbacks/SysLog.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; use froxlor\froxlorlogger; class syslog { public static function typedescription(array $attributes): string { return froxlorlogger::getinstanceof()-&gt;getlogleveldesc($attributes['data']); } }</file><file name="lib/Froxlor/UI/Callbacks/Mysql.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; use froxlor\database\database; class mysql { public static function dbserver(array $attributes): string { // get sql-root access data database::needroot(true, (int)$attributes['data'], false); database::needsqldata(); $sql_root = database::getsqldata(); database::needroot(false); return $sql_root['caption'] . '&lt;br&gt;&lt;small&gt;' . $sql_root['host'] . '&lt;/small&gt;'; } }</file><file name="lib/Froxlor/UI/Callbacks/Email.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; use froxlor\phphelper; use froxlor\settings; class email { public static function account(array $attributes) { return [ 'macro' =&gt; 'booleanwithinfo', 'data' =&gt; [ 'checked' =&gt; $attributes['data'] != 0, 'info' =&gt; $attributes['data'] != 0 ? phphelper::sizereadable($attributes['fields']['mboxsize'], 'gib', 'bi', '%01.' . (int)settings::get('panel.decimal_places') . 'f %s') : '' ] ]; } public static function forwarderlist(array $attributes) { $forwarders = explode(" ", $attributes['data']); (($key = array_search($attributes['fields']['email_full'], $forwarders)) !== false) { unset($forwarders[$key]); } (count($forwarders) &gt; 0) { return implode("&lt;br&gt;", $forwarders); } return ""; } }</file><file name="lib/Froxlor/UI/Callbacks/Domain.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; use froxlor\currentuser; use froxlor\database\database; use froxlor\domain\domain ddomain; use froxlor\filedir; use froxlor\settings; use froxlor\ui\panel\ui; class domain { public static function domaineditlink(array $attributes): array { $linker = ui::getlinker(); return [ 'macro' =&gt; 'link', 'data' =&gt; [ 'text' =&gt; $attributes['data'], 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'domains', 'page' =&gt; 'domains', 'action' =&gt; 'edit', 'id' =&gt; $attributes['fields']['id'], ]), 'target' =&gt; '_blank' ] ]; } public static function domainwithcustomerlink(array $attributes): string { $linker = ui::getlinker(); $result = '&lt;a href="https://' . $attributes['data'] . '" target="_blank"&gt;' . $attributes['data'] . '&lt;/a&gt;'; ((int)ui::getcurrentuser()['adminsession'] == 1 &amp;&amp; $attributes['fields']['customerid']) { $result .= ' (&lt;a href="' . $linker-&gt;getlink([ 'section' =&gt; 'customers', 'page' =&gt; 'customers', 'action' =&gt; 'su', 'sort' =&gt; $attributes['fields']['loginname'], 'id' =&gt; $attributes['fields']['customerid'], ]) . '"&gt;' . $attributes['fields']['loginname'] . '&lt;/a&gt;)'; } return $result; } public static function domaintarget(array $attributes) { (empty($attributes['fields']['aliasdomain'])) { ($attributes['fields']['deactivated']) { return lng('admin.deactivated'); } ($attributes['fields']['email_only']) { return lng('domains.email_only'); } // path redirect (preg_match('/^https?\:\/\//', $attributes['fields']['documentroot'])) { return [ 'macro' =&gt; 'link', 'data' =&gt; [ 'text' =&gt; $attributes['fields']['documentroot'], 'href' =&gt; $attributes['fields']['documentroot'], 'target' =&gt; '_blank' ] ]; } else { // show docroot nicely (strpos($attributes['fields']['documentroot'], ui::getcurrentuser()['documentroot']) === 0) { $attributes['fields']['documentroot'] = filedir::makecorrectdir(str_replace(ui::getcurrentuser()['documentroot'], "/", $attributes['fields']['documentroot'])); } return $attributes['fields']['documentroot']; } } return lng('domains.aliasdomain') . ' ' . $attributes['fields']['aliasdomain']; } public static function domainexternallinkinfo(array $attributes): string { $result = ''; ($attributes['fields']['parentdomainid'] != 0) { $result = '&lt;i class="fa-solid fa-turn-up me-2 fa-rotate-90 opacity-50"&gt;&lt;/i&gt;'; } $result .= '&lt;a href="http://' . $attributes['data'] . '" target="_blank"&gt;' . $attributes['data'] . '&lt;/a&gt;'; // check statistics parentdomainid==0 show stats-link customers ((int)ui::getcurrentuser()['adminsession'] == 0 &amp;&amp; $attributes['fields']['parentdomainid'] == 0 &amp;&amp; $attributes['fields']['deactivated'] == 0 &amp;&amp; preg_match('/^https?:\/\/(.*)/i', $attributes['fields']['documentroot']) == false ) { $statsapp = settings::get('system.traffictool'); $result .= ' &lt;a href="http://' . $attributes['data'] . '/' . $statsapp . '" rel="external" target="_blank" title="' . lng('domains.statstics') . '"&gt;&lt;i class="fa-solid fa-chart-line text-secondary"&gt;&lt;/i&gt;&lt;/a&gt;'; } ($attributes['fields']['registration_date'] != '') { $result .= '&lt;br&gt;&lt;small&gt;' . lng('domains.registration_date') . ': ' . $attributes['fields']['registration_date'] . '&lt;/small&gt;'; } ($attributes['fields']['termination_date'] != '') { $result .= '&lt;br&gt;&lt;small&gt;' . lng('domains.termination_date_overview') . ': ' . $attributes['fields']['termination_date'] . '&lt;/small&gt;'; } return $result; } public static function canedit(array $attributes): bool { return $attributes['fields']['caneditdomain'] &amp;&amp; !$attributes['fields']['deactivated']; } public static function canviewlogs(array $attributes): bool { ((int)$attributes['fields']['email_only'] == 0 &amp;&amp; !$attributes['fields']['deactivated']) { ((int)ui::getcurrentuser()['adminsession'] == 0 &amp;&amp; (bool)ui::getcurrentuser()['logviewenabled']) { return true; } elseif ((int)ui::getcurrentuser()['adminsession'] == 1) { return true; } } return false; } public static function candelete(array $attributes): bool { return $attributes['fields']['parentdomainid'] != '0' &amp;&amp; empty($attributes['fields']['domainaliasid']); } public static function admincandelete(array $attributes): bool { return $attributes['fields']['id'] != settings::get('system.hostname_id') &amp;&amp; empty($attributes['fields']['domainaliasid']) &amp;&amp; $attributes['fields']['standardsubdomain'] != $attributes['fields']['id']; } public static function caneditdns(array $attributes): bool { return $attributes['fields']['isbinddomain'] == '1' &amp;&amp; ui::getcurrentuser()['dnsenabled'] == '1' &amp;&amp; $attributes['fields']['caneditdomain'] == '1' &amp;&amp; settings::get('system.bind_enable') == '1' &amp;&amp; settings::get('system.dnsenabled') == '1' &amp;&amp; !$attributes['fields']['email_only'] &amp;&amp; !$attributes['fields']['deactivated']; } public static function admincaneditdns(array $attributes): bool { return $attributes['fields']['isbinddomain'] == '1' &amp;&amp; settings::get('system.bind_enable') == '1' &amp;&amp; settings::get('system.dnsenabled') == '1'; } public static function hasletsencryptactivated(array $attributes): bool { return ((bool)$attributes['fields']['letsencrypt'] &amp;&amp; (int)$attributes['fields']['email_only'] == 0); } /** * @throws \exception */ public static function caneditssl(array $attributes): bool { (settings::get('system.use_ssl') == '1' &amp;&amp; ddomain::domainhassslipport($attributes['fields']['id']) &amp;&amp; (currentuser::isadmin() || (!currentuser::isadmin() &amp;&amp; (int)$attributes['fields']['caneditdomain'] == 1)) &amp;&amp; (int)$attributes['fields']['letsencrypt'] == 0 &amp;&amp; !(int)$attributes['fields']['email_only'] &amp;&amp; !$attributes['fields']['deactivated'] ) { return true; } return false; } public static function caneditalias(array $attributes): bool { return !empty($attributes['fields']['domainaliasid']); } public static function isassigned(array $attributes): bool { return ($attributes['fields']['parentdomainid'] == 0 &amp;&amp; empty($attributes['fields']['domainaliasid'])); } public static function editsslbuttons(array $attributes): array { $result = [ 'icon' =&gt; 'fa-solid fa-shield', 'title' =&gt; lng('panel.ssleditor'), 'href' =&gt; [ 'section' =&gt; 'domains', 'page' =&gt; 'domainssleditor', 'action' =&gt; 'view', 'id' =&gt; ':id' ], ]; ($attributes['fields']['domain_hascert'] == 1) { // specified certificate domain $result['icon'] .= ' text-success'; } elseif ($attributes['fields']['domain_hascert'] == 2) { // shared certificates (e.g. subdomain domain certificate specified) $result['icon'] .= ' text-warning'; $result['title'] .= "\n" . lng('panel.ssleditor_infoshared'); } elseif ($attributes['fields']['domain_hascert'] == 0) { // certificate specified, using global fallbacks (ips ports empty ssl settings) $result['icon'] .= ' text-danger'; $result['title'] .= "\n" . lng('panel.ssleditor_infoglobal'); } $result['visible'] = [domain::class, 'caneditssl']; return $result; } public static function listips(array $attributes): string { (!empty($attributes['fields']['ipsandports'])) { $iplist = ""; foreach ($attributes['fields']['ipsandports'] $ipport) { $iplist .= $ipport['ip'] . ':' . $ipport['port'] . '&lt;br&gt;'; } return $iplist; } return lng('panel.listing_empty'); } /** * @throws \exception */ public static function getphpconfigname(array $attributes): string { $sel_stmt = database::prepare("select `description` `" . table_panel_phpconfigs . "` `id` = :id"); $phpconfig = database::pexecute_first($sel_stmt, ['id' =&gt; $attributes['data']]); ((int)ui::getcurrentuser()['adminsession'] == 1) { $linker = ui::getlinker(); $result = '&lt;a href="' . $linker-&gt;getlink([ 'section' =&gt; 'phpsettings', 'page' =&gt; 'overview', 'searchfield' =&gt; 'c.id', 'searchtext' =&gt; $attributes['data'], ]) . '"&gt;' . $phpconfig['description'] . '&lt;/a&gt;'; } else { $result = $phpconfig['description']; } return $result; } }</file><file name="lib/Froxlor/UI/Callbacks/ProgressBar.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; use exception; use froxlor\traffic\traffic; use froxlor\phphelper; use froxlor\settings; use froxlor\ui\response; class progressbar { /** * get progressbar data used diskspace * * @param array $attributes * @return array */ public static function diskspace(array $attributes): array { $infotext = null; (isset($attributes['fields']['webspace_used']) &amp;&amp; isset($attributes['fields']['mailspace_used']) &amp;&amp; isset($attributes['fields']['dbspace_used'])) { $infotext = lng('panel.used') . ':' . php_eol; $infotext .= 'web: ' . phphelper::sizereadable($attributes['fields']['webspace_used'] * 1024, null, 'bi') . php_eol; $infotext .= 'mail: ' . phphelper::sizereadable($attributes['fields']['mailspace_used'] * 1024, null, 'bi') . php_eol; $infotext .= 'mysql: ' . phphelper::sizereadable($attributes['fields']['dbspace_used'] * 1024, null, 'bi'); } return self::pbdata('diskspace', $attributes['fields'], 1024, (int)settings::get('system.report_webmax'), $infotext); } /** * needed calculations */ private static function pbdata(string $field, array $attributes, int $size_factor = 1024, int $report_max = 90, $infotext = null): array { $percent = 0; $style = 'bg-primary'; $text = phphelper::sizereadable($attributes[$field . '_used'] * $size_factor, null, 'bi') . ' / ' . lng('panel.unlimited'); ((int)$attributes[$field] &gt;= 0) { (($attributes[$field] / 100) * $report_max &lt; $attributes[$field . '_used']) { $style = 'bg-danger'; } elseif (($attributes[$field] / 100) * ($report_max - 15) &lt; $attributes[$field . '_used']) { $style = 'bg-warning'; } $percent = round(($attributes[$field . '_used'] * 100) / ($attributes[$field] == 0 ? 1 : $attributes[$field]), 0); ($percent &gt; 100) { $percent = 100; } $text = phphelper::sizereadable($attributes[$field . '_used'] * $size_factor, null, 'bi') . ' / ' . phphelper::sizereadable($attributes[$field] * $size_factor, null, 'bi'); } return [ 'macro' =&gt; 'progressbar', 'data' =&gt; [ 'percent' =&gt; $percent, 'style' =&gt; $style, 'text' =&gt; $text, 'infotext' =&gt; $infotext ] ]; } /** * get progressbar data traffic * * @param array $attributes ['fields'] * @return array */ public static function traffic(array $attributes): array { $skip_customer_traffic = false; try { $attributes['fields']['deactivated'] = 0; $result = traffic::getcustomerstats($attributes['fields'], 'currentmonth', true); } catch (exception $e) { ($e-&gt;getcode() === 405) { $skip_customer_traffic = true; } else { response::dynamicerror($e-&gt;getmessage()); } } $infotext = null; (isset($result['metrics']['http']) &amp;&amp; !$skip_customer_traffic) { $infotext = lng('panel.used') . ':' . php_eol; $infotext .= 'http: ' . phphelper::sizereadable($result['metrics']['http'], null, 'bi') . php_eol; $infotext .= 'ftp: ' . phphelper::sizereadable($result['metrics']['ftp'], null, 'bi') . php_eol; $infotext .= 'mail: ' . phphelper::sizereadable($result['metrics']['mail'], null, 'bi'); } return self::pbdata('traffic', $attributes['fields'], 1024, (int)settings::get('system.report_trafficmax'), $infotext); } /** * get progressbar data traffic admin overview * (key set 'adminsession' admin-users traffic-api selects * correct customer data corresponsing admin/reseller) * * @param array $attributes ['fields'] * @return array */ public static function traffic_admins(array $attributes): array { $attributes['fields']['adminsession'] = 1; return self::traffic($attributes); } }</file><file name="lib/Froxlor/UI/Callbacks/Dns.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; class dns { public static function prio(array $attributes): string { return ($attributes['fields']['prio'] &lt;= 0 &amp;&amp; $attributes['fields']['type'] != 'mx' &amp;&amp; $attributes['fields']['type'] != 'srv') ? '' : $attributes['data']; } }</file><file name="lib/Froxlor/UI/Callbacks/Customer.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; use froxlor\settings; use froxlor\system\markdown; class customer { public static function islocked(array $attributes): bool { return $attributes['fields']['loginfail_count'] &gt;= settings::get('login.maxloginattempts') &amp;&amp; $attributes['fields']['lastlogin_fail'] &gt; (time() - settings::get('login.deactivatetime')); } public static function hasnote(array $attributes): bool { $cleannote = markdown::cleancustomnotes($attributes['fields']['custom_notes'] ?? ""); return !empty($cleannote); } }</file><file name="lib/Froxlor/UI/Callbacks/SSLCertificate.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; class sslcertificate { public static function domainwithsan(array $attributes): array { return [ 'macro' =&gt; 'domainwithsan', 'data' =&gt; [ 'domain' =&gt; $attributes['data'], 'san' =&gt; implode(', ', $attributes['fields']['san'] ?? []), ] ]; } public static function caneditssl(array $attributes): bool { ((int)$attributes['fields']['domainid'] &gt; 0 &amp;&amp; (int)$attributes['fields']['letsencrypt'] == 0 ) { return true; } return false; } public static function isnotletsencrypt(array $attributes): bool { return (int)$attributes['fields']['letsencrypt'] == 0; } }</file><file name="lib/Froxlor/UI/Callbacks/Impersonate.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; use froxlor\ui\panel\ui; class impersonate { public static function apiadmincustomerlink(array $attributes) { // key $ismykey = false; ($attributes['fields']['adminid'] == ui::getcurrentuser()['adminid'] &amp;&amp; ((area == 'admin' &amp;&amp; $attributes['fields']['customerid'] == 0) || (area == 'customer' &amp;&amp; $attributes['fields']['customerid'] == ui::getcurrentuser()['customerid']) ) ) { // mine $ismykey = true; } $admincustomerlink = ""; (area == 'admin') { ($ismykey) { $admincustomerlink = $attributes['fields']['adminname']; } else { (empty($attributes['fields']['customerid'])) { $admincustomerlink = self::admin($attributes); } else { $attributes['data'] = $attributes['fields']['loginname']; $admincustomerlink = self::customer($attributes); } } } else { // customer need links $admincustomerlink = $attributes['fields']['loginname']; } return $admincustomerlink; } public static function admin(array $attributes) { (ui::getcurrentuser()['adminid'] != $attributes['fields']['adminid']) { $linker = ui::getlinker(); return [ 'macro' =&gt; 'link', 'data' =&gt; [ 'text' =&gt; $attributes['data'], 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'admins', 'page' =&gt; 'admins', 'action' =&gt; 'su', 'id' =&gt; $attributes['fields']['adminid'], ]), ] ]; } return $attributes['data']; } public static function customer(array $attributes): array { $linker = ui::getlinker(); return [ 'macro' =&gt; 'link', 'data' =&gt; [ 'text' =&gt; $attributes['data'], 'href' =&gt; $linker-&gt;getlink([ 'section' =&gt; 'customers', 'page' =&gt; 'customers', 'action' =&gt; 'su', 'sort' =&gt; $attributes['fields']['loginname'], 'id' =&gt; $attributes['fields']['customerid'], ]), ] ]; } }</file><file name="lib/Froxlor/UI/Callbacks/Ftp.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; use froxlor\filedir; use froxlor\ui\panel\ui; class ftp { public static function pathrelative(array $attributes): string { (strpos($attributes['data'], ui::getcurrentuser()['documentroot']) === 0) { $attributes['data'] = str_replace(ui::getcurrentuser()['documentroot'], "/", $attributes['data']); } $attributes['data'] = filedir::makecorrectdir($attributes['data']); return $attributes['data']; } }</file><file name="lib/Froxlor/UI/Callbacks/index.html" /><file name="lib/Froxlor/UI/Callbacks/Style.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\ui\callbacks; use froxlor\currentuser; use froxlor\settings; class style { public static function deactivated(array $attributes): string { return $attributes['fields']['deactivated'] ? 'table-danger' : ''; } public static function logindisabled(array $attributes): string { return $attributes['fields']['login_enabled'] == 'n' ? 'table-danger' : ''; } public static function resultintegritybad(array $attributes): string { return $attributes['fields']['result'] ? '' : 'table-warning'; } public static function invalidapikey(array $attributes): string { // check whether api key valid anymore $isvalid = true; ($attributes['fields']['valid_until'] &gt;= 0) { ($attributes['fields']['valid_until'] &lt; time()) { $isvalid = false; } } return $isvalid ? '' : 'table-danger'; } public static function resultdomainterminatedordeactivated(array $attributes): string { $termination_date = str_replace("0000-00-00", "", $attributes['fields']['termination_date'] ?? ''); $termination_css = ''; (!empty($termination_date)) { $cdate = strtotime($termination_date . " 23:59:59"); $today = time(); $termination_css = 'table-warning'; ($cdate &lt; $today) { $termination_css = 'table-danger'; } } $deactivated = $attributes['fields']['deactivated'] || (currentuser::isadmin() &amp;&amp; $attributes['fields']['customer_deactivated']); return $deactivated ? 'table-info' : $termination_css; } public static function resultcustomerlockedordeactivated(array $attributes): string { $row_css = ''; ((int)$attributes['fields']['deactivated'] == 1) { $row_css = 'table-info'; } elseif ($attributes['fields']['loginfail_count'] &gt;= settings::get('login.maxloginattempts') &amp;&amp; $attributes['fields']['lastlogin_fail'] &gt; (time() - settings::get('login.deactivatetime')) ) { $row_css = 'table-warning'; } return $row_css; } public static function diskspacewarning(array $attributes): string { return self::getwarningstyle('diskspace', $attributes['fields'], (int)settings::get('system.report_webmax')); } private static function getwarningstyle(string $field, array $attributes, int $report_max = 90): string { $style = ''; ((int)$attributes[$field] &gt;= 0) { (($attributes[$field] / 100) * $report_max &lt; $attributes[$field . '_used']) { $style = 'table-danger'; } elseif (($attributes[$field] / 100) * ($report_max - 15) &lt; $attributes[$field . '_used']) { $style = 'table-warning'; } } return $style; } public static function trafficwarning(array $attributes): string { return self::getwarningstyle('traffic', $attributes['fields'], (int)settings::get('system.report_trafficmax')); } }</file><file name="lib/Froxlor/Api/ResourceEntity.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api; /** * @since 0.10.0 */ interface resourceentity { public function listing(); public function listingcount(); public function get(); public function add(); public function update(); public function delete(); }</file><file name="lib/Froxlor/Api/ApiCommand.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api; use exception; use froxlor\database\database; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\language; use froxlor\phphelper; use froxlor\settings; use froxlor\system\mailer; abstract class apicommand extends apiparameter { /** * froxlor version * * @var string */ protected $version = null; /** * froxlor dbversion * * @var int */ protected $dbversion = null; /** * froxlor version-branding * * @var string */ protected $branding = null; /** * debug flag * * @var boolean */ private $debug = false; /** * admin flag * * @var boolean */ private $is_admin = false; /** * internal user data array * * @var array */ private $user_data = null; /** * logger interface * * @var froxlorlogger */ private $logger = null; /** * mail interface * * @var mailer */ private $mail = null; /** * whether call internal one * * @var boolean */ private $internal_call = false; /** * * @param array $header * optional, passed via api * @param array $params * optional, array parameters (var=&gt;value) command * @param array $userinfo * optional, passed via webinterface (instead $header) * @param boolean $internal * optional whether called internally, default false * * @throws exception */ final public function __construct($header = null, $params = null, $userinfo = null, $internal = false) { parent::__construct($params); $this-&gt;version = froxlor::version; $this-&gt;dbversion = froxlor::dbversion; $this-&gt;branding = froxlor::branding; (!empty($header)) { $this-&gt;readuserdata($header); } elseif (!empty($userinfo)) { $this-&gt;user_data = $userinfo; $this-&gt;is_admin = (isset($userinfo['adminsession']) &amp;&amp; $userinfo['adminsession'] == 1 &amp;&amp; $userinfo['adminid'] &gt; 0) ? true : false; } else { throw new exception("invalid user data", 500); } $this-&gt;logger = froxlorlogger::getinstanceof($this-&gt;user_data); // check whether user deactivated ($this-&gt;getuserdetail('deactivated') == 1) { $this-&gt;logger()-&gt;logaction(froxlorlogger::log_error, log_info, "[api] user '" . $this-&gt;getuserdetail('loginnname') . "' tried use api deactivated"); throw new exception("account suspended", 406); } $this-&gt;initlang(); /** * initialize mailingsystem */ $this-&gt;mail = new mailer(true); ($this-&gt;debug) { $this-&gt;logger()-&gt;logaction(froxlorlogger::log_error, log_debug, "[api] " . get_called_class() . ": " . json_encode($params, json_unescaped_slashes)); } // set internal call flag $this-&gt;internal_call = $internal; } /** * read user data database api-request-header fields * * @param array $header * api-request header * * @return boolean * @throws exception */ private function readuserdata($header = null) { $sel_stmt = database::prepare("select * `api_keys` `apikey` = :ak `secret` = :as"); $result = database::pexecute_first($sel_stmt, [ 'ak' =&gt; $header['apikey'], 'as' =&gt; $header['secret'] ], true, true); ($result) { // admin customer? ($result['customerid'] == 0 &amp;&amp; $result['adminid'] &gt; 0) { $this-&gt;is_admin = true; $table = 'panel_admins'; $key = "adminid"; } elseif ($result['customerid'] &gt; 0 &amp;&amp; $result['adminid'] &gt; 0) { $this-&gt;is_admin = false; $table = 'panel_customers'; $key = "customerid"; } else { // neither adminid &gt; 0 customerid &gt; 0 - sorry man, way throw new exception("invalid api credentials", 400); } $sel_stmt = database::prepare("select * `" . $table . "` `" . $key . "` = :id"); $this-&gt;user_data = database::pexecute_first($sel_stmt, [ 'id' =&gt; ($this-&gt;is_admin ? $result['adminid'] : $result['customerid']) ], true, true); ($this-&gt;is_admin) { $this-&gt;user_data['adminsession'] = 1; } return true; } throw new exception("invalid api credentials", 400); } /** * return field user-table * * @param string $detail * * @return string|null */ protected function getuserdetail($detail = null) { return ($this-&gt;user_data[$detail] ?? null); } /** * return logger instance * * @return froxlorlogger */ protected function logger() { return $this-&gt;logger; } /** * initialize language localized strings available apicommands */ private function initlang() { language::setlanguage(settings::get('panel.standardlanguage')); ($this-&gt;getuserdetail('language') !== null &amp;&amp; isset(language::getlanguages()[$this-&gt;getuserdetail('language')])) { language::setlanguage($this-&gt;getuserdetail('language')); } elseif ($this-&gt;getuserdetail('def_language') !== null) { language::setlanguage($this-&gt;getuserdetail('def_language')); } } /** * increase/decrease resource field customers/admins * * @param string $table * @param string $keyfield * @param int $key * @param string $operator * @param string $resource * @param string $extra * @param int $step */ protected static function updateresourceusage($table = null, $keyfield = null, $key = null, $operator = '+', $resource = null, $extra = null, $step = 1) { $stmt = database::prepare(" update `" . $table . "` set `" . $resource . "` = `" . $resource . "` " . $operator . " " . (int)$step . " " . $extra . " `" . $keyfield . "` = :key "); database::pexecute($stmt, [ 'key' =&gt; $key ], true, true); } /** * return sql parameter $sql_search given via api * * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param array $query_fields * optional array placeholders mapped actual value used api commands * executing statement [internal] * @param boolean $append * optional append clause rather create new one, default false [internal] * * @return string */ protected function getsearchwhere(&amp;$query_fields = [], $append = false) { $search = $this-&gt;getparam('sql_search', true, []); $condition = ''; (!empty($search)) { ($append == true) { $condition = ' '; } else { $condition = ' '; } $ops = [ '&lt;', '&gt;', '=', '&lt;&gt;' ]; $first = true; foreach ($search $field =&gt; $valoper) { ($field == '_plainsql' &amp;&amp; $this-&gt;internal_call) { (isset($valoper['sql']) &amp;&amp; isset($valoper['values']) &amp;&amp; is_array($valoper['values'])) { (preg_match('/^([a-z0-9\-\.,=\+_`\(\)\:\'\"\!\&lt;\&gt;\ ]+)$/i', $valoper['sql']) == false) { // skip continue; } $condition .= $valoper['sql']; foreach ($valoper['values'] $var =&gt; $value) { $query_fields[':' . $var] = $value; } } } else { $cleanfield = str_replace(".", "", $field); $sortfield = explode('.', $field); foreach ($sortfield $id =&gt; $sfield) { (substr($sfield, -1, 1) != '`') { $sfield .= '`'; } ($sfield[0] != '`') { $sfield = '`' . $sfield; } $sortfield[$id] = $sfield; } $field = implode('.', $sortfield); (preg_match('/^([a-z0-9\-\._`]+)$/i', $field) == false) { // skip continue; } (!$first) { $condition .= ' '; } (!is_array($valoper) || !isset($valoper['op']) || empty($valoper['op'])) { $condition .= $field . ' like :' . $cleanfield; (!is_array($valoper)) { $query_fields[':' . $cleanfield] = '%' . $valoper . '%'; } else { $query_fields[':' . $cleanfield] = '%' . $valoper['value'] . '%'; } } elseif (in_array($valoper['op'], $ops)) { $condition .= $field . ' ' . $valoper['op'] . ':' . $cleanfield; $query_fields[':' . $cleanfield] = $valoper['value'] ?? ''; } elseif (strtolower($valoper['op']) == 'in' &amp;&amp; is_array($valoper['value']) &amp;&amp; count($valoper['value']) &gt; 0) { $condition .= $field . ' ' . $valoper['op'] . ' ('; foreach ($valoper['value'] $incnt =&gt; $invalue) { (!is_numeric($incnt)) { // skip continue; } (!empty($invalue) &amp;&amp; preg_match('/^([a-z0-9\-\._`]+)$/i', $invalue) == false) { // skip continue; } $condition .= ":" . $cleanfield . $incnt . ", "; $query_fields[':' . $cleanfield . $incnt] = $invalue ?? ''; } $condition = substr($condition, 0, -2) . ')'; } else { continue; } ($first) { $first = false; } } } } return $condition; } /** * return limit clause least $sql_limit parameter given via api * * @param int $sql_limit * optional, limit resultset, default 0 * @param int $sql_offset * optional, offset limitation, default 0 * * @return string */ protected function getlimit() { $limit = $this-&gt;getparam('sql_limit', true, 0); $offset = $this-&gt;getparam('sql_offset', true, 0); (!is_numeric($limit)) { $limit = 0; } (!is_numeric($offset)) { $offset = 0; } ($limit &gt; 0) { return ' limit ' . $offset . ',' . $limit; } return ''; } /** * return order clause parameter $sql_orderby parameter given via api * * @param array $sql_orderby * optional array index = fieldname value = asc|desc * @param boolean $append * optional append order clause rather create new one, default false [internal] * * @return string */ protected function getorderby($append = false) { $orderby = $this-&gt;getparam('sql_orderby', true, []); $order = ""; (!empty($orderby)) { ($append) { $order .= ", "; } else { $order .= " order "; } $nat_fields = [ '`c`.`loginname`', '`c`.`name`', '`a`.`loginname`', '`adminname`', '`databasename`', '`username`' ]; foreach ($orderby $field =&gt; $by) { $sortfield = explode('.', $field); foreach ($sortfield $id =&gt; $sfield) { (substr($sfield, -1, 1) != '`') { $sfield .= '`'; } ($sfield[0] != '`') { $sfield = '`' . $sfield; } $sortfield[$id] = $sfield; } $field = implode('.', $sortfield); (preg_match('/^([a-z0-9\-\._`]+)$/i', $field) == false) { // skip continue; } $by = strtoupper($by); (!in_array($by, [ 'asc', 'desc' ])) { $by = 'asc'; } (settings::get('panel.natsorting') == 1 &amp;&amp; in_array($field, $nat_fields)) { // acts similar php's natsort(), found one comment http://my.opera.com/cpr/blog/show.dml/160556 $order .= "concat( if( ascii( left( " . $field . ", 5 ) ) &gt; 57, left( " . $field . ", 1 ), 0 ), if( ascii( right( " . $field . ", 1 ) ) &gt; 57, lpad( " . $field . ", 255, '0' ), lpad( concat( " . $field . ", '-' ), 255, '0' ) )) " . $by . ", "; } else { $order .= $field . " " . $by . ", "; } } $order = substr($order, 0, -2); } return $order; } /** * return mailer instance * * @return mailer */ protected function mailer() { return $this-&gt;mail; } /** * return api-compatible response json format send corresponding http-header * * @param mixed $data * @param int $response_code * @return string json-encoded response message */ protected function response($data = null, int $response_code = 200) { return response::jsondataresponse($data, $response_code); } /** * returns array customers current user access * * @param string $customer_hide_option * optional, called customer, options might hidden due * panel.customer_hide_options settings * * @return array * @throws exception */ protected function getallowedcustomerids($customer_hide_option = '') { $customer_ids = []; ($this-&gt;isadmin()) { // we're admin, list admins customers // optionally one specific customer identified id loginname $customerid = $this-&gt;getparam('customerid', true, 0); $loginname = $this-&gt;getparam('loginname', true, ''); (!empty($customerid) || !empty($loginname)) { $_result = $this-&gt;apicall('customers.get', [ 'id' =&gt; $customerid, 'loginname' =&gt; $loginname ]); $custom_list_result = [ $_result ]; } else { $_custom_list_result = $this-&gt;apicall('customers.listing'); $custom_list_result = $_custom_list_result['list']; } foreach ($custom_list_result $customer) { $customer_ids[] = $customer['customerid']; } } else { (!$this-&gt;isinternal() &amp;&amp; !empty($customer_hide_option) &amp;&amp; settings::isinlist('panel.customer_hide_options', $customer_hide_option)) { throw new exception("you cannot access resource", 405); } $customer_ids = [ $this-&gt;getuserdetail('customerid') ]; } (empty($customer_ids)) { throw new exception("required resource unsatisfied.", 405); } return $customer_ids; } /** * admin flag * * @return boolean */ protected function isadmin() { return $this-&gt;is_admin; } /** * call api-command internally * * @param string $command * @param array|null $params * @param boolean $internal * optional whether called internally, default false * * * @return array */ protected function apicall($command = null, $params = null, $internal = false) { $_command = explode(".", $command); $module = __namespace__ . "\commands\\" . $_command[0]; $function = $_command[1]; $json_result = $module::getlocal($this-&gt;getuserdata(), $params, $internal)-&gt;{$function}(); return json_decode($json_result, true)['data']; } /** * returns instance wanted apicommand (e.g. * customers, domains, etc); * used widely webinterface * * @param array $userinfo * array user-data * @param array $params * array parameters command * @param boolean $internal * optional whether called internally, default false * * @return static * @throws exception */ public static function getlocal($userinfo = null, $params = null, $internal = false) { return new static(null, $params, $userinfo, $internal); } /** * return user-data array * * @return array */ protected function getuserdata() { return $this-&gt;user_data; } /** * internal call flag * * @return boolean */ protected function isinternal() { return $this-&gt;internal_call; } /** * returns array customer data customer, customer-id/loginname admin/reseller * * @param int $customerid * optional, required loginname empty * @param string $loginname * optional, required customerid empty * @param string $customer_resource_check * optional, called admin, check resources target customer * * @return array * @throws exception */ protected function getcustomerdata($customer_resource_check = '') { ($this-&gt;isadmin()) { $customerid = $this-&gt;getparam('customerid', true, 0); $loginname = $this-&gt;getparam('loginname', true, ''); $customer = $this-&gt;apicall('customers.get', [ 'id' =&gt; $customerid, 'loginname' =&gt; $loginname ]); // check whether customer enough resources (!empty($customer_resource_check) &amp;&amp; $customer[$customer_resource_check . '_used'] &gt;= $customer[$customer_resource_check] &amp;&amp; $customer[$customer_resource_check] != '-1') { throw new exception("customer resources available", 406); } } else { $customer = $this-&gt;getuserdata(); } return $customer; } /** * return email template content database global language file found db * * @param array $customerdata * @param string $group * @param string $varname * @param array $replace_arr * @param string $default * * @return string */ protected function getmailtemplate($customerdata = null, $group = null, $varname = null, $replace_arr = [], $default = "") { // get template $stmt = database::prepare(" select `value` `" . table_panel_templates . "` `adminid`= :adminid `language`= :lang `templategroup`= :group `varname`= :var "); $result = database::pexecute_first($stmt, [ "adminid" =&gt; $customerdata['adminid'], "lang" =&gt; $customerdata['def_language'], "group" =&gt; $group, "var" =&gt; $varname ], true, true); $content = $default; ($result) { $content = $result['value'] ?? $default; } // @fixme html_entity_decode $content = html_entity_decode(phphelper::replacevariables($content, $replace_arr)); return $content; } }</file><file name="lib/Froxlor/Api/ApiParameter.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api; use exception; abstract class apiparameter { /** * array parameters passed command * * @var array */ private $cmd_params = null; /** * * @param array|null $params * optional, array parameters (var=&gt;value) command * * @throws exception */ public function __construct(array $params = null) { (!is_null($params)) { $params = $this-&gt;trimarray($params); } $this-&gt;cmd_params = $params; } /** * run 'trim' function array recursively * * @param array $input * * @return string|array */ private function trimarray($input) { ($input === '') { return ""; } (is_numeric($input) || is_null($input)) { return $input; } (!is_array($input)) { return trim($input); } return array_map([ $this, 'trimarray' ], $input); } /** * get specific parameter also unlimited-field * * @param string|null $param * parameter get request-parameter list * @param string|null $ul_field * parameter get request-parameter list * @param bool $optional * default: false * @param mixed $default * value returned optional=true param set * * @return mixed * @throws exception */ protected function getulparam(string $param = null, string $ul_field = null, bool $optional = false, $default = 0) { $param_value = (int)$this-&gt;getparam($param, $optional, $default); $ul_field_value = $this-&gt;getboolparam($ul_field, true, 0); ($ul_field_value != '0') { $param_value = -1; } return $param_value; } /** * get specific parameter parameter list; * check existence != empty needed. * maybe future * * @param string|null $param * parameter get request-parameter list * @param bool $optional * default: false * @param mixed $default * value returned optional=true param set * * @return mixed * @throws exception */ protected function getparam(string $param = null, bool $optional = false, $default = '') { // exist? (!isset($this-&gt;cmd_params[$param])) { ($optional === false) { // get module + function better error-messages $inmod = $this-&gt;getmodfunctionstring(); throw new exception('requested parameter "' . $param . '" could found "' . $inmod . '"', 404); } return $default; } // empty? - test really string, value 0 seen empty php (!is_array($this-&gt;cmd_params[$param]) &amp;&amp; trim($this-&gt;cmd_params[$param]) === "") { ($optional === false) { // get module + function better error-messages $inmod = $this-&gt;getmodfunctionstring(); throw new exception('requested parameter "' . $param . '" empty "' . $inmod . '"', 406); } return ''; } // everything else fine return $this-&gt;cmd_params[$param]; } /** * returns "module::function()" better error-messages (missing parameter etc.) * makes debugging lot comfortable * * @param int $level * depth backtrace, default 2 * * @param int $max_level * @param array|null $trace * * @return string */ private function getmodfunctionstring(int $level = 1, int $max_level = 5, $trace = null) { // class called us $_class = get_called_class(); (empty($trace)) { // get backtrace $trace = debug_backtrace(debug_backtrace_ignore_args); } // check class function $class = $trace[$level]['class']; $func = $trace[$level]['function']; // one looking for? ($class != $_class &amp;&amp; $level &lt;= $max_level) { // check one level deeper return $this-&gt;getmodfunctionstring(++$level, $max_level, $trace); } return str_replace("froxlor\\api\\commands\\", "", $class) . ':' . $func; } /** * getparam wrapper boolean parameter * * @param string|null $param * parameter get request-parameter list * @param bool $optional * default: false * @param mixed $default * value returned optional=true param set * * @return string */ protected function getboolparam(string $param = null, bool $optional = false, $default = false) { $_default = '0'; ($default) { $_default = '1'; } $param_value = $this-&gt;getparam($param, $optional, $_default); ($param_value &amp;&amp; intval($param_value) != 0) { return '1'; } return '0'; } /** * return list parameters * * @return array */ protected function getparamlist() { return $this-&gt;cmd_params; } }</file><file name="lib/Froxlor/Api/Api.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api; use exception; use froxlor\http\ratelimiter; use froxlor\settings; use voku\helper\antixss; class api { protected array $headers; protected $request = null; /** * api constructor. * * @throws exception */ public function __construct() { $this-&gt;headers = getallheaders(); // set header response header("accept: application/json"); header("content-type: application/json"); // check whether api interface enabled (settings::get('api.enabled') != 1) { throw new exception('api enabled. please contact administrator think wrong.', 400); } ratelimiter::run(); } /** * @param mixed $request * * @return api */ public function formatmiddleware($request): api { // check auf restful api call $this-&gt;request = $request; $uri = parse_url($_server["request_uri"], php_url_query); // map /module/command internal request array match (!empty($uri) &amp;&amp; preg_match("/^\/([a-z]+)\/([a-z]+)\/?/", $uri, $matches)) { $request = []; $request['command'] = ucfirst($matches[1]) . '.' . $matches[2]; $request['params'] = !empty($this-&gt;request) ? json_decode($this-&gt;request, true) : null; $this-&gt;request = json_encode($request); } return $this; } /** * handle incoming api request backend. * * @throws exception */ public function handle() { $request = $this-&gt;request; // validate content $request = froxlorrpc::validaterequest($request); $request = (new antixss())-&gt;xss_clean( $this-&gt;stripcslashesdeep($request) ); // actually $cls = "\\froxlor\\api\\commands\\" . $request['command']['class']; $method = $request['command']['method']; $apiobj = new $cls([ 'apikey' =&gt; $_server['php_auth_user'], 'secret' =&gt; $_server['php_auth_pw'] ], $request['params']); // call method params return $apiobj-&gt;$method(); } /** * api php error handler always return valid json response * * @param mixed $errno * @param mixed $errstr * @param mixed $errfile * @param mixed $errline * @return never */ public static function phperrhandler($errno, $errstr, $errfile, $errline) { throw new exception('internal php error: #' . $errno . ' ' . $errstr /* . ' ' . $errfile . ':' . $errline */, 500); } private function stripcslashesdeep($value) { return is_array($value) ? array_map([$this, 'stripcslashesdeep'], $value) : (!empty($value) ? stripcslashes($value) : $value); } }</file><file name="lib/Froxlor/Api/Response.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api; class response { public static function jsondataresponse($data = null, int $response_code = 200) { return self::jsonresponse(['data' =&gt; $data], $response_code); } public static function jsonresponse($data = null, int $response_code = 200) { http_response_code($response_code); return json_encode($data, json_unescaped_slashes | json_pretty_print); } public static function jsonerrorresponse($message = null, int $response_code = 400) { return self::jsonresponse(['message' =&gt; $message], $response_code); } }</file><file name="lib/Froxlor/Api/index.html" /><file name="lib/Froxlor/Api/FroxlorRPC.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api; use exception; use froxlor\database\database; use froxlor\system\iptools; class froxlorrpc { /** * validate given request * * @param $request * @return array * @throws exception */ public static function validaterequest($request): array { // make basic authentication (!isset($_server['php_auth_user']) || !self::validateauth($_server['php_auth_user'], $_server['php_auth_pw'])) { (@php_sapi_name() !== 'cli') { header('www-authenticate: basic realm="api"'); } throw new exception('unauthenticated. please provide api user credentials.', 401); } // check present (empty($request)) { throw new exception('empty request body.', 400); } // decode json request $decoded_request = json_decode($request, true); // valid? (is_null($decoded_request)) { throw new exception('invalid json format.', 400); } return self::validatebody($decoded_request); } /** * validates given api credentials * * @param string $key * @param string $secret * * @return bool */ private static function validateauth(string $key, string $secret): bool { $sel_stmt = database::prepare( " select ak.*, a.api_allowed admin_api_allowed, c.api_allowed cust_api_allowed, c.deactivated `api_keys` ak left join `panel_admins` a.adminid = ak.adminid left join `panel_customers` c c.customerid = ak.customerid `apikey` = :ak `secret` = :as " ); $result = database::pexecute_first($sel_stmt, [ 'ak' =&gt; $key, 'as' =&gt; $secret ], true, true); ($result) { ($result['apikey'] == $key &amp;&amp; $result['secret'] == $secret &amp;&amp; ($result['valid_until'] == -1 || $result['valid_until'] &gt;= time()) &amp;&amp; (($result['customerid'] == 0 &amp;&amp; $result['admin_api_allowed'] == 1) || ($result['customerid'] &gt; 0 &amp;&amp; $result['cust_api_allowed'] == 1 &amp;&amp; $result['deactivated'] == 0))) { // get user check whether api call allowed (!empty($result['allowed_from'])) { // @todo allow specification validating whole subnets later $ip_list = explode(",", $result['allowed_from']); (self::validateallowedfrom($ip_list, $_server['remote_addr'])) { return true; } } else { return true; } } } throw new exception('invalid authorization credentials', 403); } /** * validate given remote_addr within list allowed ip/ip-ranges * * @param array $allowed_from * @param string $remote_addr * * @return bool */ public static function validateallowedfrom(array $allowed_from, string $remote_addr): bool { // shorten ip comparison $remote_addr = inet_ntop(inet_pton($remote_addr)); // check direct matches (in_array($remote_addr, $allowed_from)) { return true; } // check possible cidr ranges foreach ($allowed_from $ip) { $ip_cidr = explode("/", $ip); (count($ip_cidr) == 2 &amp;&amp; iptools::ip_in_range($ip_cidr, $remote_addr)) { return true; } } return false; } /** * validates given command * * @param array $request * * @return array * @throws exception */ private static function validatebody($request) { // check command exists (empty($request['command'])) { throw new exception("please provide command.", 400); } $command = explode(".", $request['command']); (count($command) != 2) { throw new exception("the given command invalid.", 400); } // simply check file-existance, want use autoloader way // recognize non-api classes+methods valid commands $apiclass = '\\froxlor\\api\\commands\\' . $command[0]; (!class_exists($apiclass) || !@method_exists($apiclass, $command[1])) { throw new exception("unknown command", 400); } return [ 'command' =&gt; [ 'class' =&gt; $command[0], 'method' =&gt; $command[1] ], 'params' =&gt; $request['params'] ?? null ]; } }</file><file name="lib/Froxlor/Api/Commands/Admins.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\idna\idnawrapper; use froxlor\settings; use froxlor\system\crypt; use froxlor\ui\response; use froxlor\user; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class admins extends apicommand implements resourceentity { /** * increase resource-usage * * @param int $adminid * @param string $resource * @param string $extra * optional, default empty * @param int $increase_by * optional, default 1 */ public static function increaseusage($adminid = 0, $resource = null, $extra = '', $increase_by = 1) { self::updateresourceusage(table_panel_admins, 'adminid', $adminid, '+', $resource, $extra, $increase_by); } /** * decrease resource-usage * * @param int $adminid * @param string $resource * @param string $extra * optional, default empty * @param int $decrease_by * optional, default 1 */ public static function decreaseusage($adminid = 0, $resource = null, $extra = '', $decrease_by = 1) { self::updateresourceusage(table_panel_admins, 'adminid', $adminid, '-', $resource, $extra, $decrease_by); } /** * lists admin entries * * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin * @return string json-encoded array count|list * @throws exception */ public function listing() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 1) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_info, "[api] list admins"); $query_fields = []; $result_stmt = database::prepare(" select * `" . table_panel_admins . "`" . $this-&gt;getsearchwhere($query_fields) . $this-&gt;getorderby() . $this-&gt;getlimit()); database::pexecute($result_stmt, $query_fields, true, true); $result = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $result[] = $row; } return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } throw new exception("not allowed execute given command.", 403); } /** * returns total number admins given admin * * @access admin * @return string json-encoded response message * @throws exception */ public function listingcount() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 1) { $result_stmt = database::prepare(" select count(*) num_admins `" . table_panel_admins . "` "); $result = database::pexecute_first($result_stmt, null, true, true); ($result) { return $this-&gt;response($result['num_admins']); } $this-&gt;response(0); } throw new exception("not allowed execute given command.", 403); } /** * create new admin user * * @param string $name * required, name adminstrator * @param string $email * required, email address administrator * @param string $new_loginname * required, loginname/username administrator * @param string $admin_password * optional, default auto-generated * @param string $def_language * * optional, iso 639-1 language code (e.g. 'en', 'de', see lng-folder supported languages), * * default system-default language * @param bool $gui_access * optional, allow login via webui, false login via webui disallowed; default true * @param bool $api_allowed * optional, default true system setting api.enabled true, else false * @param string $custom_notes * optional, default empty * @param bool $custom_notes_show * optional, default false * @param int $diskspace * optional, default 0 * @param bool $diskspace_ul * optional, default false * @param int $traffic * optional, default 0 * @param bool $traffic_ul * optional, default false * @param int $customers * optional, default 0 * @param bool $customers_ul * optional, default false * @param int $domains * optional, default 0 * @param bool $domains_ul * optional, default false * @param int $subdomains * optional, default 0 * @param bool $subdomains_ul * optional, default false * @param int $emails * optional, default 0 * @param bool $emails_ul * optional, default false * @param int $email_accounts * optional, default 0 * @param bool $email_accounts_ul * optional, default false * @param int $email_forwarders * optional, default 0 * @param bool $email_forwarders_ul * optional, default false * @param int $email_quota * optional, default 0 * @param bool $email_quota_ul * optional, default false * @param int $ftps * optional, default 0 * @param bool $ftps_ul * optional, default false * @param int $mysqls * optional, default 0 * @param bool $mysqls_ul * optional, default false * @param bool $customers_see_all * optional, default false * @param bool $caneditphpsettings * optional, default false * @param bool $change_serversettings * optional, default false * @param array $ipaddress * optional, list ip-address id's; default -1 (all ip's) * * @access admin * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 1) { // required parameters $name = $this-&gt;getparam('name'); $email = $this-&gt;getparam('email'); $loginname = $this-&gt;getparam('new_loginname'); // parameters $def_language = $this-&gt;getparam('def_language', true, settings::get('panel.standardlanguage')); $gui_access = $this-&gt;getboolparam('gui_access', true, true); $api_allowed = $this-&gt;getboolparam('api_allowed', true, settings::get('api.enabled')); $custom_notes = $this-&gt;getparam('custom_notes', true, ''); $custom_notes_show = $this-&gt;getboolparam('custom_notes_show', true, 0); $password = $this-&gt;getparam('admin_password', true, ''); $diskspace = $this-&gt;getulparam('diskspace', 'diskspace_ul', true, 0); $traffic = $this-&gt;getulparam('traffic', 'traffic_ul', true, 0); $customers = $this-&gt;getulparam('customers', 'customers_ul', true, 0); $domains = $this-&gt;getulparam('domains', 'domains_ul', true, 0); $subdomains = $this-&gt;getulparam('subdomains', 'subdomains_ul', true, 0); $emails = $this-&gt;getulparam('emails', 'emails_ul', true, 0); $email_accounts = $this-&gt;getulparam('email_accounts', 'email_accounts_ul', true, 0); $email_forwarders = $this-&gt;getulparam('email_forwarders', 'email_forwarders_ul', true, 0); $email_quota = $this-&gt;getulparam('email_quota', 'email_quota_ul', true, 0); $ftps = $this-&gt;getulparam('ftps', 'ftps_ul', true, 0); $mysqls = $this-&gt;getulparam('mysqls', 'mysqls_ul', true, 0); $customers_see_all = $this-&gt;getboolparam('customers_see_all', true, 0); $caneditphpsettings = $this-&gt;getboolparam('caneditphpsettings', true, 0); $change_serversettings = $this-&gt;getboolparam('change_serversettings', true, 0); $ipaddress = $this-&gt;getparam('ipaddress', true, -1); // validation $name = validate::validate($name, 'name', validate::regex_desc_text, '', [], true); $idna_convert = new idnawrapper(); $email = $idna_convert-&gt;encode(validate::validate($email, 'email', '', '', [], true)); $def_language = validate::validate($def_language, 'default language', '', '', [], true); $custom_notes = validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', validate::regex_conf_text, '', [], true); (settings::get('system.mail_quota_enabled') != '1') { $email_quota = -1; } $password = validate::validate($password, 'password', '', '', [], true); // check empty, // cause empty == generate password automatically ($password != '') { $password = crypt::validatepassword($password, true); } $diskspace *= 1024; $traffic *= 1024 * 1024; // check account already exists // check via api skip permission checks task $loginname_check_stmt = database::prepare(" select `loginname` `" . table_panel_customers . "` `loginname` = :login "); $loginname_check = database::pexecute_first($loginname_check_stmt, [ 'login' =&gt; $loginname ], true, true); // check admin loginname already exists // check via api skip permission checks task $loginname_check_admin_stmt = database::prepare(" select `loginname` `" . table_panel_admins . "` `loginname` = :login "); $loginname_check_admin = database::pexecute_first($loginname_check_admin_stmt, [ 'login' =&gt; $loginname ], true, true); // check existing email address // check via api skip permission checks task $email_check_admin_stmt = database::prepare(" select `email` `" . table_panel_admins . "` `email` = :email "); $email_check_admin = database::pexecute_first($email_check_admin_stmt, [ 'email' =&gt; $email ], true, true); (($loginname_check &amp;&amp; strtolower($loginname_check['loginname']) == strtolower($loginname)) || ($loginname_check_admin &amp;&amp; strtolower($loginname_check_admin['loginname']) == strtolower($loginname))) { response::standarderror('loginnameexists', $loginname, true); } elseif (preg_match('/^' . preg_quote(settings::get('customer.accountprefix'), '/') . '([0-9]+)/', $loginname)) { // accounts match systemaccounts allowed, filtering response::standarderror('loginnameisusingprefix', settings::get('customer.accountprefix'), true); } elseif (function_exists('posix_getpwnam') &amp;&amp; !in_array("posix_getpwnam", explode(",", ini_get('disable_functions'))) &amp;&amp; posix_getpwnam($loginname)) { response::standarderror('loginnameissystemaccount', $loginname, true); } elseif (!validate::validateusername($loginname)) { response::standarderror('loginnameiswrong', $loginname, true); } elseif (!validate::validateemail($email)) { response::standarderror('emailiswrong', $email, true); } elseif ($email_check_admin &amp;&amp; strtolower($email_check_admin['email']) == strtolower($email)) { response::standarderror('emailexists', $email, true); } else { ($customers_see_all != '1') { $customers_see_all = '0'; } ($caneditphpsettings != '1') { $caneditphpsettings = '0'; } ($change_serversettings != '1') { $change_serversettings = '0'; } ($password == '') { $password = crypt::generatepassword(); } $_theme = settings::get('panel.default_theme'); $ins_data = [ 'loginname' =&gt; $loginname, 'password' =&gt; crypt::makecryptpassword($password), 'name' =&gt; $name, 'email' =&gt; $email, 'lang' =&gt; $def_language, 'gui_access' =&gt; $gui_access, 'api_allowed' =&gt; $api_allowed, 'change_serversettings' =&gt; $change_serversettings, 'customers' =&gt; $customers, 'customers_see_all' =&gt; $customers_see_all, 'domains' =&gt; $domains, 'caneditphpsettings' =&gt; $caneditphpsettings, 'diskspace' =&gt; $diskspace, 'traffic' =&gt; $traffic, 'subdomains' =&gt; $subdomains, 'emails' =&gt; $emails, 'accounts' =&gt; $email_accounts, 'forwarders' =&gt; $email_forwarders, 'quota' =&gt; $email_quota, 'ftps' =&gt; $ftps, 'mysqls' =&gt; $mysqls, 'ip' =&gt; empty($ipaddress) ? "" : (is_array($ipaddress) &amp;&amp; $ipaddress &gt; 0 ? json_encode($ipaddress) : -1), 'theme' =&gt; $_theme, 'custom_notes' =&gt; $custom_notes, 'custom_notes_show' =&gt; $custom_notes_show ]; $ins_stmt = database::prepare(" insert `" . table_panel_admins . "` set `loginname` = :loginname, `password` = :password, `name` = :name, `email` = :email, `def_language` = :lang, `gui_access` = :gui_access, `api_allowed` = :api_allowed, `change_serversettings` = :change_serversettings, `customers` = :customers, `customers_see_all` = :customers_see_all, `domains` = :domains, `caneditphpsettings` = :caneditphpsettings, `diskspace` = :diskspace, `traffic` = :traffic, `subdomains` = :subdomains, `emails` = :emails, `email_accounts` = :accounts, `email_forwarders` = :forwarders, `email_quota` = :quota, `ftps` = :ftps, `mysqls` = :mysqls, `ip` = :ip, `theme` = :theme, `custom_notes` = :custom_notes, `custom_notes_show` = :custom_notes_show "); database::pexecute($ins_stmt, $ins_data, true, true); $adminid = database::lastinsertid(); $ins_data['adminid'] = $adminid; $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] added admin '" . $loginname . "'"); // get admin-data return-array $result = $this-&gt;apicall('admins.get', [ 'id' =&gt; $adminid ]); return $this-&gt;response($result); } } throw new exception("not allowed execute given command.", 403); } /** * return admin entry either id loginname * * @param int $id * optional, admin-id * @param string $loginname * optional, loginname * * @access admin * @return string json-encoded array * @throws exception */ public function get() { $id = $this-&gt;getparam('id', true, 0); $ln_optional = $id &gt; 0; $loginname = $this-&gt;getparam('loginname', $ln_optional, ''); ($this-&gt;isadmin() &amp;&amp; ($this-&gt;getuserdetail('change_serversettings') == 1 || ($this-&gt;getuserdetail('adminid') == $id || $this-&gt;getuserdetail('loginname') == $loginname))) { $result_stmt = database::prepare(" select * `" . table_panel_admins . "` " . ($id &gt; 0 ? "`adminid` = :idln" : "`loginname` = :idln")); $params = [ 'idln' =&gt; ($id &lt;= 0 ? $loginname : $id) ]; $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_info, "[api] get admin '" . $result['loginname'] . "'"); return $this-&gt;response($result); } $key = ($id &gt; 0 ? "id #" . $id : "loginname '" . $loginname . "'"); throw new exception("admin " . $key . " could found", 404); } throw new exception("not allowed execute given command.", 403); } /** * update admin user given id loginname * * @param int $id * optional, admin-id * @param string $loginname * optional, loginname * @param string $name * optional * @param string $email * optional * @param string $admin_password * optional, default auto-generated * @param string $def_language * * optional, iso 639-1 language code (e.g. 'en', 'de', see lng-folder supported languages), * * default system-default language * @param bool $gui_access * * optional, allow login via webui, false login via webui disallowed; default true * @param bool $api_allowed * optional, default true system setting api.enabled true, else false * @param string $custom_notes * optional, default empty * @param string $theme * optional * @param bool $deactivated * optional, default false * @param bool $custom_notes_show * optional, default false * @param int $diskspace * optional, default 0 * @param bool $diskspace_ul * optional, default false * @param int $traffic * optional, default 0 * @param bool $traffic_ul * optional, default false * @param int $customers * optional, default 0 * @param bool $customers_ul * optional, default false * @param int $domains * optional, default 0 * @param bool $domains_ul * optional, default false * @param int $subdomains * optional, default 0 * @param bool $subdomains_ul * optional, default false * @param int $emails * optional, default 0 * @param bool $emails_ul * optional, default false * @param int $email_accounts * optional, default 0 * @param bool $email_accounts_ul * optional, default false * @param int $email_forwarders * optional, default 0 * @param bool $email_forwarders_ul * optional, default false * @param int $email_quota * optional, default 0 * @param bool $email_quota_ul * optional, default false * @param int $ftps * optional, default 0 * @param bool $ftps_ul * optional, default false * @param int $mysqls * optional, default 0 * @param bool $mysqls_ul * optional, default false * @param bool $customers_see_all * optional, default false * @param bool $caneditphpsettings * optional, default false * @param bool $change_serversettings * optional, default false * @param array $ipaddress * optional, list ip-address id's; default -1 (all ip's) * * @access admin * @return string json-encoded array * @throws exception */ public function update() { ($this-&gt;isadmin()) { $id = $this-&gt;getparam('id', true, 0); $ln_optional = $id &gt; 0; $loginname = $this-&gt;getparam('loginname', $ln_optional, ''); $result = $this-&gt;apicall('admins.get', [ 'id' =&gt; $id, 'loginname' =&gt; $loginname ]); $id = $result['adminid']; ($this-&gt;getuserdetail('change_serversettings') == 1 || $result['adminid'] == $this-&gt;getuserdetail('adminid')) { // parameters $name = $this-&gt;getparam('name', true, $result['name']); $idna_convert = new idnawrapper(); $email = $this-&gt;getparam('email', true, $idna_convert-&gt;decode($result['email'])); $password = $this-&gt;getparam('admin_password', true, ''); $def_language = $this-&gt;getparam('def_language', true, $result['def_language']); $custom_notes = $this-&gt;getparam('custom_notes', true, ($result['custom_notes'] ?? "")); $custom_notes_show = $this-&gt;getboolparam('custom_notes_show', true, $result['custom_notes_show']); $theme = $this-&gt;getparam('theme', true, $result['theme']); // cannot edit details ($result['adminid'] == $this-&gt;getuserdetail('adminid')) { $gui_access = $result['gui_access']; $api_allowed = $result['api_allowed']; $deactivated = $result['deactivated']; $customers = $result['customers']; $domains = $result['domains']; $subdomains = $result['subdomains']; $emails = $result['emails']; $email_accounts = $result['email_accounts']; $email_forwarders = $result['email_forwarders']; $email_quota = $result['email_quota']; $ftps = $result['ftps']; $mysqls = $result['mysqls']; $customers_see_all = $result['customers_see_all']; $caneditphpsettings = $result['caneditphpsettings']; $change_serversettings = $result['change_serversettings']; $diskspace = $result['diskspace']; $traffic = $result['traffic']; $ipaddress = ($result['ip'] != -1 ? json_decode($result['ip'], true) : -1); } else { $gui_access = $this-&gt;getboolparam('gui_access', true, $result['gui_access']); $api_allowed = $this-&gt;getboolparam('api_allowed', true, $result['api_allowed']); $deactivated = $this-&gt;getboolparam('deactivated', true, $result['deactivated']); $dec_places = settings::get('panel.decimal_places'); $diskspace = $this-&gt;getulparam('diskspace', 'diskspace_ul', true, round($result['diskspace'] / 1024, $dec_places)); $traffic = $this-&gt;getulparam('traffic', 'traffic_ul', true, round($result['traffic'] / (1024 * 1024), $dec_places)); $customers = $this-&gt;getulparam('customers', 'customers_ul', true, $result['customers']); $domains = $this-&gt;getulparam('domains', 'domains_ul', true, $result['domains']); $subdomains = $this-&gt;getulparam('subdomains', 'subdomains_ul', true, $result['subdomains']); $emails = $this-&gt;getulparam('emails', 'emails_ul', true, $result['emails']); $email_accounts = $this-&gt;getulparam('email_accounts', 'email_accounts_ul', true, $result['email_accounts']); $email_forwarders = $this-&gt;getulparam('email_forwarders', 'email_forwarders_ul', true, $result['email_forwarders']); $email_quota = $this-&gt;getulparam('email_quota', 'email_quota_ul', true, $result['email_quota']); $ftps = $this-&gt;getulparam('ftps', 'ftps_ul', true, $result['ftps']); $mysqls = $this-&gt;getulparam('mysqls', 'mysqls_ul', true, $result['mysqls']); $customers_see_all = $this-&gt;getboolparam('customers_see_all', true, $result['customers_see_all']); $caneditphpsettings = $this-&gt;getboolparam('caneditphpsettings', true, $result['caneditphpsettings']); $change_serversettings = $this-&gt;getboolparam('change_serversettings', true, $result['change_serversettings']); $ipaddress = $this-&gt;getparam('ipaddress', true, ($result['ip'] != -1 ? json_decode($result['ip'], true) : -1)); $diskspace *= 1024; $traffic *= 1024 * 1024; } // validation $name = validate::validate($name, 'name', validate::regex_desc_text, '', [], true); $idna_convert = new idnawrapper(); $email = $idna_convert-&gt;encode(validate::validate($email, 'email', '', '', [], true)); $def_language = validate::validate($def_language, 'default language', '', '', [], true); $custom_notes = validate::validate(str_replace("\r\n", "\n", $custom_notes ?? ""), 'custom_notes', validate::regex_conf_text, '', [], true); $theme = validate::validate($theme, 'theme', '', '', [], true); $password = validate::validate($password, 'password', '', '', [], true); (settings::get('system.mail_quota_enabled') != '1') { $email_quota = -1; } (empty($theme)) { $theme = settings::get('panel.default_theme'); } (empty(trim($name))) { response::standarderror([ 'stringisempty', 'admin.name' ], '', true); } (empty(trim($email))) { response::standarderror([ 'stringisempty', 'admin.email' ], '', true); } // check existing email address // check via api skip permission checks task $email_check_admin_stmt = database::prepare(" select `email` `" . table_panel_admins . "` `email` = :email `adminid` &lt;&gt; :adminid "); $email_check_admin = database::pexecute_first($email_check_admin_stmt, [ 'email' =&gt; $email, 'adminid' =&gt; $id, ], true, true); (!validate::validateemail($email)) { response::standarderror('emailiswrong', $email, true); } elseif ($email_check_admin &amp;&amp; strtolower($email_check_admin['email']) == strtolower($email)) { response::standarderror('emailexists', $email, true); } else { ($deactivated != '1') { $deactivated = '0'; } ($customers_see_all != '1') { $customers_see_all = '0'; } ($caneditphpsettings != '1') { $caneditphpsettings = '0'; } ($change_serversettings != '1') { $change_serversettings = '0'; } ($password != '') { $password = crypt::validatepassword($password, true); $password = crypt::makecryptpassword($password); } else { $password = $result['password']; } // check resource set something lower // actually used admin/reseller $res_warning = ""; ($customers != $result['customers'] &amp;&amp; $customers != -1 &amp;&amp; $customers &lt; $result['customers_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['customers']); } ($domains != $result['domains'] &amp;&amp; $domains != -1 &amp;&amp; $domains &lt; $result['domains_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['domains']); } ($diskspace != $result['diskspace'] &amp;&amp; ($diskspace / 1024) != -1 &amp;&amp; $diskspace &lt; $result['diskspace_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['diskspace']); } ($traffic != $result['traffic'] &amp;&amp; ($traffic / 1024 / 1024) != -1 &amp;&amp; $traffic &lt; $result['traffic_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['traffic']); } ($emails != $result['emails'] &amp;&amp; $emails != -1 &amp;&amp; $emails &lt; $result['emails_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['emails']); } ($email_accounts != $result['email_accounts'] &amp;&amp; $email_accounts != -1 &amp;&amp; $email_accounts &lt; $result['email_accounts_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['email accounts']); } ($email_forwarders != $result['email_forwarders'] &amp;&amp; $email_forwarders != -1 &amp;&amp; $email_forwarders &lt; $result['email_forwarders_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['email forwarders']); } ($email_quota != $result['email_quota'] &amp;&amp; $email_quota != -1 &amp;&amp; $email_quota &lt; $result['email_quota_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['email quota']); } ($ftps != $result['ftps'] &amp;&amp; $ftps != -1 &amp;&amp; $ftps &lt; $result['ftps_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['ftps']); } ($mysqls != $result['mysqls'] &amp;&amp; $mysqls != -1 &amp;&amp; $mysqls &lt; $result['mysqls_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['mysqls']); } (!empty($res_warning)) { throw new exception($res_warning, 406); } $upd_data = [ 'password' =&gt; $password, 'name' =&gt; $name, 'email' =&gt; $email, 'lang' =&gt; $def_language, 'gui_access' =&gt; $gui_access, 'api_allowed' =&gt; $api_allowed, 'change_serversettings' =&gt; $change_serversettings, 'customers' =&gt; $customers, 'customers_see_all' =&gt; $customers_see_all, 'domains' =&gt; $domains, 'caneditphpsettings' =&gt; $caneditphpsettings, 'diskspace' =&gt; $diskspace, 'traffic' =&gt; $traffic, 'subdomains' =&gt; $subdomains, 'emails' =&gt; $emails, 'accounts' =&gt; $email_accounts, 'forwarders' =&gt; $email_forwarders, 'quota' =&gt; $email_quota, 'ftps' =&gt; $ftps, 'mysqls' =&gt; $mysqls, 'ip' =&gt; empty($ipaddress) ? "" : (is_array($ipaddress) &amp;&amp; $ipaddress &gt; 0 ? json_encode($ipaddress) : -1), 'deactivated' =&gt; $deactivated, 'custom_notes' =&gt; $custom_notes, 'custom_notes_show' =&gt; $custom_notes_show, 'theme' =&gt; $theme, 'adminid' =&gt; $id ]; $upd_stmt = database::prepare(" update `" . table_panel_admins . "` set `password` = :password, `name` = :name, `email` = :email, `def_language` = :lang, `gui_access` = :gui_access, `api_allowed` = :api_allowed, `change_serversettings` = :change_serversettings, `customers` = :customers, `customers_see_all` = :customers_see_all, `domains` = :domains, `caneditphpsettings` = :caneditphpsettings, `diskspace` = :diskspace, `traffic` = :traffic, `subdomains` = :subdomains, `emails` = :emails, `email_accounts` = :accounts, `email_forwarders` = :forwarders, `email_quota` = :quota, `ftps` = :ftps, `mysqls` = :mysqls, `ip` = :ip, `deactivated` = :deactivated, `custom_notes` = :custom_notes, `custom_notes_show` = :custom_notes_show, `theme` = :theme `adminid` = :adminid "); database::pexecute($upd_stmt, $upd_data, true, true); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] edited admin '" . $result['loginname'] . "'"); // get admin-data return-array $result = $this-&gt;apicall('admins.get', [ 'id' =&gt; $result['adminid'] ]); return $this-&gt;response($result); } } } throw new exception("not allowed execute given command.", 403); } /** * delete admin entry either id loginname * * @param int $id * optional, admin-id * @param string $loginname * optional, loginname * * @access admin * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 1) { $id = $this-&gt;getparam('id', true, 0); $ln_optional = $id &gt; 0; $loginname = $this-&gt;getparam('loginname', $ln_optional, ''); $result = $this-&gt;apicall('admins.get', [ 'id' =&gt; $id, 'loginname' =&gt; $loginname ]); $id = $result['adminid']; // stupid ($id == $this-&gt;getuserdetail('adminid')) { response::standarderror('youcantdeleteyourself', '', true); } // can't delete first superadmin ($id == 1) { response::standarderror('cannotdeletesuperadmin', '', true); } // delete admin $del_stmt = database::prepare(" delete `" . table_panel_admins . "` `adminid` = :adminid "); database::pexecute($del_stmt, [ 'adminid' =&gt; $id ], true, true); // delete traffic-usage $del_stmt = database::prepare(" delete `" . table_panel_traffic_admins . "` `adminid` = :adminid "); database::pexecute($del_stmt, [ 'adminid' =&gt; $id ], true, true); // set admin-id old admin's customer current admins $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `adminid` = :userid `adminid` = :adminid "); database::pexecute($upd_stmt, [ 'userid' =&gt; $this-&gt;getuserdetail('adminid'), 'adminid' =&gt; $id ], true, true); // set admin-id old admin's domains current admins $upd_stmt = database::prepare(" update `" . table_panel_domains . "` set `adminid` = :userid `adminid` = :adminid "); database::pexecute($upd_stmt, [ 'userid' =&gt; $this-&gt;getuserdetail('adminid'), 'adminid' =&gt; $id ], true, true); // delete old admin's api keys exists (no customer keys) $upd_stmt = database::prepare(" delete `" . table_api_keys . "` `adminid` = :adminid `customerid` = '0' "); database::pexecute($upd_stmt, [ 'adminid' =&gt; $id ], true, true); // set admin-id old admin's api-keys current admins $upd_stmt = database::prepare(" update `" . table_api_keys . "` set `adminid` = :userid `adminid` = :adminid "); database::pexecute($upd_stmt, [ 'userid' =&gt; $this-&gt;getuserdetail('adminid'), 'adminid' =&gt; $id ], true, true); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] deleted admin '" . $result['loginname'] . "'"); user::updatecounters(); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } /** * unlock locked admin either id loginname * * @param int $id * optional, admin-id * @param string $loginname * optional, loginname * * @access admin * @return string json-encoded array * @throws exception */ public function unlock() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 1) { $id = $this-&gt;getparam('id', true, 0); $ln_optional = $id &gt; 0; $loginname = $this-&gt;getparam('loginname', $ln_optional, ''); $result = $this-&gt;apicall('admins.get', [ 'id' =&gt; $id, 'loginname' =&gt; $loginname ]); $id = $result['adminid']; $result_stmt = database::prepare(" update `" . table_panel_admins . "` set `loginfail_count` = '0' `adminid`= :id "); database::pexecute($result_stmt, [ 'id' =&gt; $id ], true, true); // set new value result-array $result['loginfail_count'] = 0; $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] unlocked admin '" . $result['loginname'] . "'"); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } }</file><file name="lib/Froxlor/Api/Commands/EmailAccounts.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\idna\idnawrapper; use froxlor\settings; use froxlor\system\cronjob; use froxlor\system\crypt; use froxlor\ui\response; use froxlor\user; use froxlor\validate\check; use froxlor\validate\validate; /** * @since 0.10.0 */ class emailaccounts extends apicommand implements resourceentity { /** * add new email account given email-address either id emailaddr * * @param int $id * optional email-address-id email-address add account * @param string $emailaddr * optional email-address add account * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param string $email_password * password account * @param string $alternative_email * optional email address send account information to, default account created * @param int $email_quota * optional quota enabled mb, default setting: system.mail_quota * @param bool $sendinfomail * optional, sends welcome message new account (needed creation, without user * able login mail received), default 1 (true) * * @access admin, customer * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } ($this-&gt;getuserdetail('email_accounts_used') &lt; $this-&gt;getuserdetail('email_accounts') || $this-&gt;getuserdetail('email_accounts') == '-1') { // parameter $id = $this-&gt;getparam('id', true, 0); $ea_optional = $id &gt; 0; $emailaddr = $this-&gt;getparam('emailaddr', $ea_optional, ''); $email_password = $this-&gt;getparam('email_password'); $alternative_email = $this-&gt;getparam('alternative_email', true, ''); $quota = $this-&gt;getparam('email_quota', true, settings::get('system.mail_quota') ?? 0); $sendinfomail = $this-&gt;getboolparam('sendinfomail', true, 1); // validation $quota = validate::validate($quota, 'email_quota', '/^\d+$/', 'vmailquotawrong', [], true); // get needed customer info reduce email-account-counter one $customer = $this-&gt;getcustomerdata('email_accounts'); // check imap||pop3 == 1, see #1298 // d00p, 6.5.2023 @revert - customer resources allow email accounts // implicitly allowed smtp, e.g. sending emails also requires account exist /* ($customer['imap'] != '1' &amp;&amp; $customer['pop3'] != '1') { response::standarderror('notallowedtouseaccounts', '', true); } */ (!empty($emailaddr)) { $idna_convert = new idnawrapper(); $emailaddr = $idna_convert-&gt;encode($emailaddr); } // get email address $result = $this-&gt;apicall('emails.get', [ 'id' =&gt; $id, 'emailaddr' =&gt; $emailaddr ]); $id = $result['id']; $idna_convert = new idnawrapper(); $email_full = $result['email_full']; $username = $email_full; $password = validate::validate($email_password, 'password', '', '', [], true); $password = crypt::validatepassword($password, true); ($result['popaccountid'] != 0) { throw new exception("email address '" . $email_full . "' already account assigned.", 406); } (check::checkmailaccdeletionstate($email_full)) { response::standarderror([ 'mailaccistobedeleted' ], $email_full, true); } // alternative email address send info (settings::get('panel.sendalternativemail') == 1) { $alternative_email = $idna_convert-&gt;encode(validate::validate($alternative_email, 'alternative_email', '', '', [], true)); (!empty($alternative_email) &amp;&amp; !validate::validateemail($alternative_email)) { response::standarderror('alternativeemailiswrong', $alternative_email, true); } } else { $alternative_email = ''; } // validate quota enabled (settings::get('system.mail_quota_enabled') == 1) { ($customer['email_quota'] != '-1' &amp;&amp; ($quota == 0 || ($quota + $customer['email_quota_used']) &gt; $customer['email_quota'])) { response::standarderror('allocatetoomuchquota', $quota, true); } } else { // disable $quota = 0; } ($password == $email_full) { response::standarderror('passwordshouldnotbeusername', '', true); } // prefix hash-algo switch (settings::get('system.passwordcryptfunc')) { case 'argon2i': $cpprefix = '{argon2i}'; break; case 'argon2id': $cpprefix = '{argon2id}'; break; default: $cpprefix = '{blf-crypt}'; break; } // encrypt password $cryptpassword = $cpprefix . crypt::makecryptpassword($password); $email_user = substr($email_full, 0, strrpos($email_full, "@")); $email_domain = substr($email_full, strrpos($email_full, "@") + 1); $maildirname = trim(settings::get('system.vmail_maildirname')); // add trailing slash maildir needed $maildirpath = $maildirname; (!empty($maildirname) &amp;&amp; substr($maildirname, -1) != "/") { $maildirpath .= "/"; } // insert data $stmt = database::prepare("insert `" . table_mail_users . "` set `customerid` = :cid, `email` = :email, `username` = :username," . (settings::get('system.mailpwcleartext') == '1' ? '`password` = :password, ' : '') . " `password_enc` = :password_enc, `homedir` = :homedir, `maildir` = :maildir, `uid` = :uid, `gid` = :gid, `domainid` = :domainid, `postfix` = 'y', `quota` = :quota, `imap` = :imap, `pop3` = :pop3 "); $params = [ "cid" =&gt; $customer['customerid'], "email" =&gt; $email_full, "username" =&gt; $username, "password_enc" =&gt; $cryptpassword, "homedir" =&gt; settings::get('system.vmail_homedir'), "maildir" =&gt; $customer['loginname'] . '/' . $email_domain . "/" . $email_user . "/" . $maildirpath, "uid" =&gt; settings::get('system.vmail_uid'), "gid" =&gt; settings::get('system.vmail_gid'), "domainid" =&gt; $result['domainid'], "quota" =&gt; $quota, "imap" =&gt; $customer['imap'], "pop3" =&gt; $customer['pop3'] ]; (settings::get('system.mailpwcleartext') == '1') { $params["password"] = $password; } database::pexecute($stmt, $params, true, true); $popaccountid = database::lastinsertid(); // add email address destination field $result['destination'] .= ' ' . $email_full; $stmt = database::prepare(" update `" . table_mail_virtual . "` set `destination` = :destination, `popaccountid` = :popaccountid `customerid`= :cid `id`= :id "); $params = [ "destination" =&gt; filedir::makecorrectdestination($result['destination']), "popaccountid" =&gt; $popaccountid, "cid" =&gt; $customer['customerid'], "id" =&gt; $id ]; database::pexecute($stmt, $params, true, true); // update customer usage customers::increaseusage($customer['customerid'], 'email_accounts_used'); customers::increaseusage($customer['customerid'], 'email_quota_used', '', $quota); ($sendinfomail) { // replacer array mail create account server $replace_arr = [ 'email' =&gt; $email_full, 'password' =&gt; htmlentities(htmlentities($password)), 'salutation' =&gt; user::getcorrectusersalutation($customer), 'name' =&gt; $customer['name'], 'firstname' =&gt; $customer['firstname'], 'company' =&gt; $customer['company'], 'username' =&gt; $customer['loginname'], 'customer_no' =&gt; $customer['customernumber'] ]; // get customers admin $stmt = database::prepare("select `name`, `email` `" . table_panel_admins . "` `adminid`= :adminid"); $admin = database::pexecute_first($stmt, [ "adminid" =&gt; $customer['adminid'] ]); // get template mail subject $mail_subject = $this-&gt;getmailtemplate($customer, 'mails', 'pop_success_subject', $replace_arr, lng('mails.pop_success.subject')); // get template mail body $mail_body = $this-&gt;getmailtemplate($customer, 'mails', 'pop_success_mailbody', $replace_arr, lng('mails.pop_success.mailbody')); $_mailerror = false; $mailerr_msg = ""; try { $this-&gt;mailer()-&gt;setfrom(settings::get('panel.adminmail'), user::getcorrectusersalutation($admin)); $this-&gt;mailer()-&gt;clearreplytos(); $this-&gt;mailer()-&gt;addreplyto($admin['email'], user::getcorrectusersalutation($admin)); $this-&gt;mailer()-&gt;subject = $mail_subject; $this-&gt;mailer()-&gt;altbody = $mail_body; $this-&gt;mailer()-&gt;body = str_replace("\n", "&lt;br /&gt;", $mail_body); $this-&gt;mailer()-&gt;addaddress($email_full); $this-&gt;mailer()-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_err, "[api] error sending mail: " . $mailerr_msg); response::standarderror('errorsendingmail', $email_full, true); } $this-&gt;mailer()-&gt;clearaddresses(); // customer wants send e-mail alternative email address (settings::get('panel.sendalternativemail') == 1 &amp;&amp; !empty($alternative_email)) { // get template mail subject $mail_subject = $this-&gt;getmailtemplate($customer, 'mails', 'pop_success_alternative_subject', $replace_arr, lng('mails.pop_success_alternative.subject')); // get template mail body $mail_body = $this-&gt;getmailtemplate($customer, 'mails', 'pop_success_alternative_mailbody', $replace_arr, lng('mails.pop_success_alternative.mailbody')); $_mailerror = false; try { $this-&gt;mailer()-&gt;setfrom(settings::get('panel.adminmail'), user::getcorrectusersalutation($admin)); $this-&gt;mailer()-&gt;clearreplytos(); $this-&gt;mailer()-&gt;addreplyto($admin['email'], user::getcorrectusersalutation($admin)); $this-&gt;mailer()-&gt;subject = $mail_subject; $this-&gt;mailer()-&gt;altbody = $mail_body; $this-&gt;mailer()-&gt;msghtml(str_replace("\n", "&lt;br /&gt;", $mail_body)); $this-&gt;mailer()-&gt;addaddress($idna_convert-&gt;encode($alternative_email), user::getcorrectusersalutation($customer)); $this-&gt;mailer()-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_err, "[api] error sending mail: " . $mailerr_msg); response::standarderror([ 'errorsendingmail' ], $alternative_email, true); } $this-&gt;mailer()-&gt;clearaddresses(); } } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] added email account '" . $result['email_full'] . "'"); $result = $this-&gt;apicall('emails.get', [ 'emailaddr' =&gt; $result['email_full'] ]); return $this-&gt;response($result); } throw new exception("no resources available", 406); } /** * cannot directly get email account. * need call emails.get() */ public function get() { throw new exception('you cannot directly get email account. need call emails.get()', 303); } /** * update email-account entry given email-address either id email-address * * @param int $id * optional, email-address-id * @param string $emailaddr * optional, email-address update * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param int $email_quota * optional, update quota * @param string $email_password * optional, update password * @param bool $deactivated * optional, admin-only * * @access admin, customer * @return string json-encoded array * @throws exception */ public function update() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } // parameter $id = $this-&gt;getparam('id', true, 0); $ea_optional = $id &gt; 0; $emailaddr = $this-&gt;getparam('emailaddr', $ea_optional, ''); (!empty($emailaddr)) { $idna_convert = new idnawrapper(); $emailaddr = $idna_convert-&gt;encode($emailaddr); } // validation $result = $this-&gt;apicall('emails.get', [ 'id' =&gt; $id, 'emailaddr' =&gt; $emailaddr ]); $id = $result['id']; (empty($result['popaccountid']) || $result['popaccountid'] == 0) { throw new exception("email address '" . $result['email_full'] . "' account assigned.", 406); } $password = $this-&gt;getparam('email_password', true, ''); $quota = $this-&gt;getparam('email_quota', true, $result['quota']); $deactivated = $this-&gt;getboolparam('deactivated', true, strtolower($result['postfix']) == 'n'); // get needed customer info reduce email-account-counter one $customer = $this-&gt;getcustomerdata(); // validation $quota = validate::validate($quota, 'email_quota', '/^\d+$/', 'vmailquotawrong', [], true); $upd_query = ""; $upd_params = [ "id" =&gt; $result['popaccountid'], "cid" =&gt; $customer['customerid'] ]; (!empty($password)) { ($password == $result['email_full']) { response::standarderror('passwordshouldnotbeusername', '', true); } $password = crypt::validatepassword($password, true); // prefix hash-algo switch (settings::get('system.passwordcryptfunc')) { case 'argon2i': $cpprefix = '{argon2i}'; break; case 'argon2id': $cpprefix = '{argon2id}'; break; default: $cpprefix = '{blf-crypt}'; break; } // encrypt password $cryptpassword = $cpprefix . crypt::makecryptpassword($password); $upd_query .= (settings::get('system.mailpwcleartext') == '1' ? "`password` = :password, " : '') . "`password_enc`= :password_enc"; $upd_params['password_enc'] = $cryptpassword; (settings::get('system.mailpwcleartext') == '1') { $upd_params['password'] = $password; } } (settings::get('system.mail_quota_enabled') == 1) { ($quota != $result['quota']) { ($customer['email_quota'] != '-1' &amp;&amp; ($quota == 0 || ($quota + $customer['email_quota_used'] - $result['quota']) &gt; $customer['email_quota'])) { response::standarderror('allocatetoomuchquota', $quota, true); } (!empty($upd_query)) { $upd_query .= ", "; } $upd_query .= "`quota` = :quota"; $upd_params['quota'] = $quota; } } else { // disable $quota = 0; } ($this-&gt;isadmin()) { (($deactivated == true &amp;&amp; strtolower($result['postfix']) == 'y') || ($deactivated == false &amp;&amp; strtolower($result['postfix']) == 'n')) { (!empty($upd_query)) { $upd_query .= ", "; } $upd_query .= "`postfix` = :postfix, `imap` = :imap, `pop3` = :pop3"; $upd_params['postfix'] = $deactivated ? 'n' : 'y'; $upd_params['imap'] = $deactivated ? '0' : '1'; $upd_params['pop3'] = $deactivated ? '0' : '1'; } } // build update query (!empty($upd_query)) { $upd_stmt = database::prepare(" update `" . table_mail_users . "` set " . $upd_query . " `id` = :id `customerid`= :cid "); database::pexecute($upd_stmt, $upd_params, true, true); } ($customer['email_quota'] != '-1') { customers::increaseusage($customer['customerid'], 'email_quota_used', '', ($quota - $result['quota'])); admins::increaseusage($customer['adminid'], 'email_quota_used', '', ($quota - $result['quota'])); } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] updated email account '" . $result['email_full'] . "'"); $result = $this-&gt;apicall('emails.get', [ 'emailaddr' =&gt; $result['email_full'] ]); return $this-&gt;response($result); } /** * cannot directly list email accounts. * need call emails.listing() */ public function listing() { throw new exception('you cannot directly list email accounts. need call emails.listing()', 303); } /** * cannot directly count email accounts. * need call emails.listingcount() */ public function listingcount() { throw new exception('you cannot directly count email accounts. need call emails.listingcount()', 303); } /** * delete email-account entry given email-address either id email-address * * @param int $id * optional, email-address-id * @param string $emailaddr * optional, email-address delete account * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param bool $delete_userfiles * optional, default false * * @access admin, customer * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } // parameter $id = $this-&gt;getparam('id', true, 0); $ea_optional = $id &gt; 0; $emailaddr = $this-&gt;getparam('emailaddr', $ea_optional, ''); $delete_userfiles = $this-&gt;getboolparam('delete_userfiles', true, 0); // validation $result = $this-&gt;apicall('emails.get', [ 'id' =&gt; $id, 'emailaddr' =&gt; $emailaddr ], true); $id = $result['id']; (empty($result['popaccountid']) || $result['popaccountid'] == 0) { throw new exception("email address '" . $result['email_full'] . "' account assigned.", 406); } // get needed customer info reduce email-account-counter one $customer = $this-&gt;getcustomerdata(); // delete entry $stmt = database::prepare(" delete `" . table_mail_users . "` `customerid`= :cid `id`= :id "); database::pexecute($stmt, [ "cid" =&gt; $customer['customerid'], "id" =&gt; $result['popaccountid'] ], true, true); // update mail-virtual entry $result['destination'] = str_replace($result['email_full'], '', $result['destination']); $stmt = database::prepare(" update `" . table_mail_virtual . "` set `destination` = :dest, `popaccountid` = '0' `customerid`= :cid `id`= :id "); $params = [ "dest" =&gt; filedir::makecorrectdestination($result['destination']), "cid" =&gt; $customer['customerid'], "id" =&gt; $id ]; database::pexecute($stmt, $params, true, true); $result['popaccountid'] = 0; (settings::get('system.mail_quota_enabled') == '1' &amp;&amp; $customer['email_quota'] != '-1') { $quota = (int)$result['quota']; } else { $quota = 0; } ($delete_userfiles) { cronjob::inserttask(taskid::delete_email_data, $customer['loginname'], filedir::makecorrectdir($result['homedir'] . '/' . $result['maildir'])); } // decrease usage customer customers::decreaseusage($customer['customerid'], 'email_accounts_used'); customers::decreaseusage($customer['customerid'], 'email_quota_used', '', $quota); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_warning, "[api] deleted email account '" . $result['email_full'] . "'"); return $this-&gt;response($result); } }</file><file name="lib/Froxlor/Api/Commands/EmailDomains.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\settings; use pdo; /** * @since 2.0 */ class emaildomains extends apicommand implements resourceentity { /** * list domains email addresses connected it. * called admin, list domains email addresses * connected customers allowed view, * specify id loginname one specific customer * * @param int $customerid * optional, admin-only, select email addresses specific customer id * @param string $loginname * optional, admin-only, select email addresses specific customer loginname * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin, customer * @return string json-encoded array count|list * @throws exception */ public function listing() { $customer_ids = $this-&gt;getallowedcustomerids('email'); $result = []; $query_fields = []; $result_stmt = database::prepare(" select distinct d.domain, d.domain_ace, e.domainid, count(e.email) addresses, ifnull(sum(case e.popaccountid &gt; 0 1 else 0 end), 0) accounts, ifnull(sum( case length(replace(e.destination, concat(e.email_full, ' '), '')) - length(replace(replace(e.destination, concat(e.email_full, ' '), ''), ' ', '')) &gt; 0 length(replace(e.destination, concat(e.email_full, ' '), '')) - length(replace(replace(e.destination, concat(e.email_full, ' '), ''), ' ', '')) e.destination &lt;&gt; e.email_full 1 else 0 end ), 0) forwarder `" . table_mail_virtual . "` e left join `" . table_panel_domains . "` d.id = e.domainid e.customerid (" . implode(", ", $customer_ids) . ") d.domain null " . $this-&gt;getsearchwhere($query_fields, true) . " group e.domainid " . $this-&gt;getorderby() . $this-&gt;getlimit()); database::pexecute($result_stmt, $query_fields, true, true); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $result[] = $row; } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] list email-domains"); return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } /** * returns total number accessible domains email addresses connected * * @param int $customerid * optional, admin-only, select email addresses specific customer id * @param string $loginname * optional, admin-only, select email addresses specific customer loginname * * @access admin, customer * @return string json-encoded response message * @throws exception */ public function listingcount() { $customer_ids = $this-&gt;getallowedcustomerids('email'); $result_stmt = database::prepare(" select count(distinct d.domain) num_emaildomains `" . table_mail_virtual . "` e left join `" . table_panel_domains . "` d.id = e.domainid e.customerid (" . implode(", ", $customer_ids) . ") d.domain null "); $result = database::pexecute_first($result_stmt, null, true, true); ($result) { return $this-&gt;response($result['num_emaildomains']); } return $this-&gt;response(0); } /** * cannot directly access email-domains * * @access admin, customer * @return string json-encoded array * @throws exception */ public function get() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } throw new exception('you cannot directly access resource.', 303); } /** * cannot directly add email-domains * * @access admin, customer * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } throw new exception('you cannot directly add resource.', 303); } /** * toggle catchall flag given email address either id email-address * * @access admin, customer * @return string json-encoded array * @throws exception */ public function update() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } throw new exception('you cannot directly update resource.', 303); } /** * cannot directly delete email-domains * * @access admin, customer * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } throw new exception('you cannot directly delete resource.', 303); } }</file><file name="lib/Froxlor/Api/Commands/Traffic.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\database\database; use froxlor\froxlorlogger; use pdo; /** * @since 0.10.0 */ class traffic extends apicommand implements resourceentity { /** * cannot add traffic data * * @throws exception */ public function add() { throw new exception('you cannot add traffic data', 303); } /** * get specific traffic details use year, month and/or day parameter traffic.listing() * * @throws exception */ public function get() { throw new exception('to get specific traffic details use year, month and/or day parameter traffic.listing()', 303); } /** * cannot update traffic data * * @throws exception */ public function update() { throw new exception('you cannot update traffic data', 303); } /** * list traffic information * * @param int $year * optional, default empty * @param int $month * optional, default empty * @param int $day * optional, default empty * @param int $date_from * optional timestamp, default empty, specified, $year, $month $day ignored * @param int $date_until * optional timestamp, default empty, specified, $year, $month $day ignored * @param bool $customer_traffic * optional, admin-only, whether output ones traffic ones customers, default 0 * (false) * @param int $customerid * optional, admin-only, select traffic specific customer id * @param string $loginname * optional, admin-only, select traffic specific customer loginname * * @access admin, customer * @return string json-encoded array count|list * @throws exception */ public function listing() { $year = $this-&gt;getparam('year', true, ""); $month = $this-&gt;getparam('month', true, ""); $day = $this-&gt;getparam('day', true, ""); $date_from = $this-&gt;getparam('date_from', true, -1); $date_until = $this-&gt;getparam('date_until', true, -1); $customer_traffic = $this-&gt;getboolparam('customer_traffic', true, 0); $customer_ids = $this-&gt;getallowedcustomerids(); $result = []; $params = []; // validate parameters ($date_from &gt;= 0 || $date_until &gt;= 0) { $year = ""; $month = ""; $day = ""; ($date_from == $date_until) { $date_until = -1; } ($date_from &gt;= 0 &amp;&amp; $date_until &gt;= 0 &amp;&amp; $date_until &lt; $date_from) { // switch $temp_ts = $date_from; $date_from = $date_until; $date_until = $temp_ts; } } // check year/month/day $where_str = ""; (!empty($year) &amp;&amp; is_numeric($year)) { $where_str .= " `year` = :year"; $params['year'] = $year; } (!empty($month) &amp;&amp; is_numeric($month)) { $where_str .= " `month` = :month"; $params['month'] = $month; } (!empty($day) &amp;&amp; is_numeric($day)) { $where_str .= " `day` = :day"; $params['day'] = $day; } ($date_from &gt;= 0 &amp;&amp; $date_until &gt;= 0) { $where_str .= " `stamp` :df :du"; $params['df'] = $date_from; $params['du'] = $date_until; } elseif ($date_from &gt;= 0 &amp;&amp; $date_until &lt; 0) { $where_str .= " `stamp` &gt; :df"; $params['df'] = $date_from; } elseif ($date_from &lt; 0 &amp;&amp; $date_until &gt;= 0) { $where_str .= " `stamp` &lt; :du"; $params['du'] = $date_until; } (!$this-&gt;isadmin() || ($this-&gt;isadmin() &amp;&amp; $customer_traffic)) { $result_stmt = database::prepare(" select * `" . table_panel_traffic . "` `customerid` (" . implode(", ", $customer_ids) . ")" . $where_str); } else { $params['adminid'] = $this-&gt;getuserdetail('adminid'); $result_stmt = database::prepare(" select * `" . table_panel_traffic_admins . "` `adminid` = :adminid" . $where_str); } database::pexecute($result_stmt, $params, true, true); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { // make bytes kb $row['http'] *= 1024; $row['ftp_up'] *= 1024; $row['ftp_down'] *= 1024; $row['mail'] *= 1024; $result[] = $row; } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] list traffic"); return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } /** * cannot count traffic data list * * @throws exception */ public function listingcount() { throw new exception('you cannot count traffic data list', 303); } /** * cannot delete traffic data * * @throws exception */ public function delete() { throw new exception('you cannot delete traffic data', 303); } }</file><file name="lib/Froxlor/Api/Commands/SysLog.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\database\database; use froxlor\froxlorlogger; use pdo; /** * @since 0.10.6 */ class syslog extends apicommand implements resourceentity { /** * list log-entries * * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin, customer * @return string json-encoded array count|list * @throws exception */ public function listing() { $result = []; $query_fields = []; ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('customers_see_all') == '1') { $result_stmt = database::prepare(" select * `" . table_panel_log . "` " . $this-&gt;getsearchwhere($query_fields) . $this-&gt;getorderby() . $this-&gt;getlimit()); } elseif ($this-&gt;isadmin()) { // get admin customers $_custom_list_result = $this-&gt;apicall('customers.listing'); $custom_list_result = $_custom_list_result['list']; $customer_names = []; foreach ($custom_list_result $customer) { $customer_names[] = $customer['loginname']; } (count($customer_names) &gt; 0) { $result_stmt = database::prepare(" select * `" . table_panel_log . "` `user` = :loginname `user` ('" . implode("', '", $customer_names) . "')" . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); } else { $result_stmt = database::prepare(" select * `" . table_panel_log . "` `user` = :loginname" . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); } $query_fields['loginname'] = $this-&gt;getuserdetail('loginname'); } else { // every one else sees logs $result_stmt = database::prepare(" select * `" . table_panel_log . "` `user` = :loginname `action` &lt;&gt; 99 " . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); $query_fields['loginname'] = $this-&gt;getuserdetail('loginname'); } database::pexecute($result_stmt, $query_fields, true, true); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { // clean log-text $row['text'] = preg_replace("/[^\w @#\"':.,()\[\]+\-_\/\\\!]/i", "_", $row['text']); $result[] = $row; } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] list log-entries"); return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } /** * returns total number log-entries * * @access admin * @return string json-encoded response message * @throws exception */ public function listingcount() { $params = null; ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('customers_see_all') == '1') { $result_stmt = database::prepare(" select count(*) num_logs `" . table_panel_log . "` "); } elseif ($this-&gt;isadmin()) { // get admin customers $_custom_list_result = $this-&gt;apicall('customers.listing'); $custom_list_result = $_custom_list_result['list']; $customer_names = []; foreach ($custom_list_result $customer) { $customer_names[] = $customer['loginname']; } (count($customer_names) &gt; 0) { $result_stmt = database::prepare(" select count(*) num_logs `" . table_panel_log . "` `user` = :loginname `user` ('" . implode("', '", $customer_names) . "') "); } else { $result_stmt = database::prepare(" select count(*) num_logs `" . table_panel_log . "` `user` = :loginname "); } $params = [ 'loginname' =&gt; $this-&gt;getuserdetail('loginname') ]; } else { // every one else sees logs $result_stmt = database::prepare(" select count(*) num_logs `" . table_panel_log . "` `user` = :loginname `action` &lt;&gt; 99 "); $params = [ 'loginname' =&gt; $this-&gt;getuserdetail('loginname') ]; } $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { return $this-&gt;response($result['num_logs']); } return $this-&gt;response(0); } /** * cannot get log entries */ public function get() { throw new exception('you cannot get log entries', 303); } /** * cannot add log entries */ public function add() { throw new exception('you cannot add log entries', 303); } /** * cannot update log entries */ public function update() { throw new exception('you cannot update log entries', 303); } /** * delete log entries * * @param int $min_to_keep * optional minutes keep, default 10 * * @access admin * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin()) { $min_to_keep = self::getparam('min_to_keep', true, 10); ($min_to_keep &lt; 0) { $min_to_keep = 0; } $truncatedate = time() - (60 * $min_to_keep); $params = []; ($this-&gt;getuserdetail('customers_see_all') == '1') { $result_stmt = database::prepare(" delete `" . table_panel_log . "` `date` &lt; :trunc "); } else { // get admin customers $_custom_list_result = $this-&gt;apicall('customers.listing'); $custom_list_result = $_custom_list_result['list']; $customer_names = []; foreach ($custom_list_result $customer) { $customer_names[] = $customer['loginname']; } (count($customer_names) &gt; 0) { $result_stmt = database::prepare(" delete `" . table_panel_log . "` `date` &lt; :trunc `user` = :loginname `user` ('" . implode("', '", $customer_names) . "') "); } else { $result_stmt = database::prepare(" delete `" . table_panel_log . "` `date` &lt; :trunc `user` = :loginname "); } $params = [ 'loginname' =&gt; $this-&gt;getuserdetail('loginname') ]; } $params['trunc'] = $truncatedate; database::pexecute($result_stmt, $params, true, true); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] truncated froxlor syslog"); return $this-&gt;response(true); } throw new exception("not allowed execute given command.", 403); } }</file><file name="lib/Froxlor/Api/Commands/Ftps.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\idna\idnawrapper; use froxlor\settings; use froxlor\system\cronjob; use froxlor\system\crypt; use froxlor\ui\response; use froxlor\user; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class ftps extends apicommand implements resourceentity { /** * add new ftp-user * * @param string $ftp_password * password created database database-user * @param string $path * destination path relative customers-homedir * @param string $ftp_description * optional, description ftp-user * @param bool $sendinfomail * optional, send created resource-information customer, default: false * @param string $shell * optional, default /bin/false (not changeable deactivated) * @param string $ftp_username * optional customer.ftpatdomain allowed, specify username * @param string $ftp_domain * optional customer.ftpatdomain allowed, specify domain (customer must owner) * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param array $additional_members * optional whether add additional usernames group * @param bool $is_defaultuser * optional whether standard default ftp user added usage decreased * @param bool $login_enabled * optional whether allow login (default) * * @access admin, customer * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'ftp')) { throw new exception("you cannot access resource", 405); } $is_defaultuser = $this-&gt;getboolparam('is_defaultuser', true, 0); $login_enabled = $this-&gt;getboolparam('login_enabled', true, 1); (($this-&gt;getuserdetail('ftps_used') &lt; $this-&gt;getuserdetail('ftps') || $this-&gt;getuserdetail('ftps') == '-1') || $this-&gt;isadmin() &amp;&amp; $is_defaultuser == 1) { // required parameters $path = $this-&gt;getparam('path'); $password = $this-&gt;getparam('ftp_password'); // parameters $description = $this-&gt;getparam('ftp_description', true, ''); $sendinfomail = $this-&gt;getboolparam('sendinfomail', true, 0); $shell = $this-&gt;getparam('shell', true, '/bin/false'); $ftpusername = $this-&gt;getparam('ftp_username', true, ''); $ftpdomain = $this-&gt;getparam('ftp_domain', true, ''); $additional_members = $this-&gt;getparam('additional_members', true, []); // validation $password = validate::validate($password, 'password', '', '', [], true); $password = crypt::validatepassword($password, true); $description = validate::validate(trim($description), 'description', validate::regex_desc_text, '', [], true); (settings::get('system.allow_customer_shell') == '1') { $shell = validate::validate(trim($shell), 'shell', '', '', [], true); } else { $shell = "/bin/false"; } (settings::get('customer.ftpatdomain') == '1') { $ftpusername = validate::validate(trim($ftpusername), 'username', '/^[a-za-z0-9][a-za-z0-9\-_]+\$?$/', '', [], true); (substr($ftpdomain, 0, 4) != 'xn--') { $idna_convert = new idnawrapper(); $ftpdomain = $idna_convert-&gt;encode(validate::validate($ftpdomain, 'domain', '', '', [], true)); } } $params = []; // get needed customer info reduce ftp-user-counter one ($is_defaultuser) { // resource check default user $customer = $this-&gt;getcustomerdata(); } else { $customer = $this-&gt;getcustomerdata('ftps'); } ($sendinfomail != 1) { $sendinfomail = 0; } (settings::get('customer.ftpatdomain') == '1' &amp;&amp; !$is_defaultuser) { ($ftpusername == '') { response::standarderror([ 'stringisempty', 'username' ], '', true); } $ftpdomain_check_stmt = database::prepare("select `id`, `domain`, `customerid` `" . table_panel_domains . "` `domain` = :domain `customerid` = :customerid"); $ftpdomain_check = database::pexecute_first($ftpdomain_check_stmt, [ "domain" =&gt; $ftpdomain, "customerid" =&gt; $customer['customerid'] ], true, true); ($ftpdomain_check &amp;&amp; $ftpdomain_check['domain'] != $ftpdomain) { response::standarderror('maindomainnonexist', $ftpdomain, true); } $username = $ftpusername . "@" . $ftpdomain; } else { ($is_defaultuser) { $username = $customer['loginname']; } else { $username = $customer['loginname'] . settings::get('customer.ftpprefix') . (intval($customer['ftp_lastaccountnumber']) + 1); } } $username_check_stmt = database::prepare(" select * `" . table_ftp_users . "` `username` = :username "); $username_check = database::pexecute_first($username_check_stmt, [ "username" =&gt; $username ], true, true); (!empty($username_check) &amp;&amp; $username_check['username'] = $username) { response::standarderror('usernamealreadyexists', $username, true); } elseif ($username == $password) { response::standarderror('passwordshouldnotbeusername', '', true); } else { $path = filedir::makecorrectdir($customer['documentroot'] . '/' . $path, $customer['documentroot']); $cryptpassword = crypt::makecryptpassword($password, false, true); $stmt = database::prepare("insert `" . table_ftp_users . "` (`customerid`, `username`, `description`, `password`, `homedir`, `login_enabled`, `uid`, `gid`, `shell`) values (:customerid, :username, :description, :password, :homedir, :loginenabled, :guid, :guid, :shell)"); $params = [ "customerid" =&gt; $customer['customerid'], "username" =&gt; $username, "description" =&gt; $description, "password" =&gt; $cryptpassword, "homedir" =&gt; $path, "loginenabled" =&gt; $login_enabled ? 'y' : 'n', "guid" =&gt; $customer['guid'], "shell" =&gt; $shell ]; database::pexecute($stmt, $params, true, true); $result_stmt = database::prepare(" select `bytes_in_used` `" . table_ftp_quotatallies . "` `name` = :name "); database::pexecute($result_stmt, [ "name" =&gt; $customer['loginname'] ], true, true); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $stmt = database::prepare("insert `" . table_ftp_quotatallies . "` (`name`, `quota_type`, `bytes_in_used`, `bytes_out_used`, `bytes_xfer_used`, `files_in_used`, `files_out_used`, `files_xfer_used`) values (:name, 'user', :bytes_in_used, '0', '0', '0', '0', '0') "); database::pexecute($stmt, [ "name" =&gt; $username, "bytes_in_used" =&gt; $row['bytes_in_used'] ], true, true); } // create quotatallies entry exists, refs #885 ($result_stmt-&gt;rowcount() == 0) { $stmt = database::prepare("insert `" . table_ftp_quotatallies . "` (`name`, `quota_type`, `bytes_in_used`, `bytes_out_used`, `bytes_xfer_used`, `files_in_used`, `files_out_used`, `files_xfer_used`) values (:name, 'user', '0', '0', '0', '0', '0', '0') "); database::pexecute($stmt, [ "name" =&gt; $username ], true, true); } $group_upd_stmt = database::prepare(" update `" . table_ftp_groups . "` set `members` = concat_ws(',',`members`, :username) `customerid`= :customerid `gid`= :guid "); $params = [ "username" =&gt; $username, "customerid" =&gt; $customer['customerid'], "guid" =&gt; $customer['guid'] ]; ($is_defaultuser) { // add new group $group_ins_stmt = database::prepare(" insert `" . table_ftp_groups . "` set `customerid`= :customerid, `gid`= :guid, `groupname` = :username, `members` = :username "); database::pexecute($group_ins_stmt, $params, true, true); } else { // update database::pexecute($group_upd_stmt, $params, true, true); } (count($additional_members) &gt; 0) { foreach ($additional_members $add_member) { $params = [ "username" =&gt; $add_member, "customerid" =&gt; $customer['customerid'], "guid" =&gt; $customer['guid'] ]; database::pexecute($group_upd_stmt, $params, true, true); } } (!$is_defaultuser) { // update customer usage customers::increaseusage($customer['customerid'], 'ftps_used'); customers::increaseusage($customer['customerid'], 'ftp_lastaccountnumber'); } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] added ftp-account '" . $username . " (" . $path . ")'"); cronjob::inserttask(taskid::create_ftp); ($sendinfomail == 1) { $replace_arr = [ 'salutation' =&gt; user::getcorrectusersalutation($customer), 'cust_name' =&gt; user::getcorrectusersalutation($customer), // &lt; keep compatibility 'name' =&gt; $customer['name'], 'firstname' =&gt; $customer['firstname'], 'company' =&gt; $customer['company'], 'username' =&gt; $customer['loginname'], 'customer_no' =&gt; $customer['customernumber'], 'usr_name' =&gt; $username, 'usr_pass' =&gt; htmlentities(htmlentities($password)), 'usr_path' =&gt; filedir::makecorrectdir(str_replace($customer['documentroot'], "/", $path)) ]; // get template mail subject $mail_subject = $this-&gt;getmailtemplate($customer, 'mails', 'new_ftpaccount_by_customer_subject', $replace_arr, lng('mails.new_ftpaccount_by_customer.subject')); // get template mail body $mail_body = $this-&gt;getmailtemplate($customer, 'mails', 'new_ftpaccount_by_customer_mailbody', $replace_arr, lng('mails.new_ftpaccount_by_customer.mailbody')); $_mailerror = false; $mailerr_msg = ""; try { $this-&gt;mailer()-&gt;subject = $mail_subject; $this-&gt;mailer()-&gt;altbody = $mail_body; $this-&gt;mailer()-&gt;body = str_replace("\n", "&lt;br /&gt;", $mail_body); $this-&gt;mailer()-&gt;addaddress($customer['email'], user::getcorrectusersalutation($customer)); $this-&gt;mailer()-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_err, "[api] error sending mail: " . $mailerr_msg); response::standarderror('errorsendingmail', $customer['email'], true); } $this-&gt;mailer()-&gt;clearaddresses(); } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] added ftp-user '" . $username . "'"); $result = $this-&gt;apicall('ftps.get', [ 'username' =&gt; $username ]); return $this-&gt;response($result); } } throw new exception("no resources available", 406); } /** * return ftp-user entry either id username * * @param int $id * optional, customer-id * @param string $username * optional, username * * @access admin, customer * @return string json-encoded array * @throws exception */ public function get() { $id = $this-&gt;getparam('id', true, 0); $un_optional = $id &gt; 0; $username = $this-&gt;getparam('username', $un_optional, ''); $params = []; ($this-&gt;isadmin()) { ($this-&gt;getuserdetail('customers_see_all') == false) { // reseller admin cannot see customers, need check // whether database belongs one customers $_custom_list_result = $this-&gt;apicall('customers.listing'); $custom_list_result = $_custom_list_result['list']; $customer_ids = []; foreach ($custom_list_result $customer) { $customer_ids[] = $customer['customerid']; } $result_stmt = database::prepare(" select * `" . table_ftp_users . "` `customerid` (" . implode(", ", $customer_ids) . ") (`id` = :idun `username` = :idun) "); } else { $result_stmt = database::prepare(" select * `" . table_ftp_users . "` (`id` = :idun `username` = :idun) "); } } else { (settings::isinlist('panel.customer_hide_options', 'ftp')) { throw new exception("you cannot access resource", 405); } $result_stmt = database::prepare(" select * `" . table_ftp_users . "` `customerid` = :customerid (`id` = :idun `username` = :idun) "); $params['customerid'] = $this-&gt;getuserdetail('customerid'); } $params['idun'] = ($id &lt;= 0 ? $username : $id); $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] get ftp-user '" . $result['username'] . "'"); return $this-&gt;response($result); } $key = ($id &gt; 0 ? "id #" . $id : "username '" . $username . "'"); throw new exception("ftp user " . $key . " could found", 404); } /** * update given ftp-user id username * * @param int $id * optional, ftp-user-id * @param string $username * optional, username * @param string $ftp_password * optional, update password specified * @param string $path * destination path relative customers-homedir * @param string $ftp_description * optional, description ftp-user * @param string $shell * optional, default /bin/false (not changeable deactivated) * @param bool $login_enabled * optional whether allow login (default) * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * * @access admin, customer * @return string json-encoded array * @throws exception */ public function update() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'ftp')) { throw new exception("you cannot access resource", 405); } $id = $this-&gt;getparam('id', true, 0); $un_optional = $id &gt; 0; $username = $this-&gt;getparam('username', $un_optional, ''); $result = $this-&gt;apicall('ftps.get', [ 'id' =&gt; $id, 'username' =&gt; $username ]); $id = $result['id']; // parameters $path = $this-&gt;getparam('path', true, ''); $password = $this-&gt;getparam('ftp_password', true, ''); $description = $this-&gt;getparam('ftp_description', true, $result['description']); $shell = $this-&gt;getparam('shell', true, $result['shell']); $login_enabled = $this-&gt;getboolparam('login_enabled', true, ($result['login_enabled'] == 'y' ? 1 : 0)); // validation $password = validate::validate($password, 'password', '', '', [], true); $description = validate::validate(trim($description), 'description', validate::regex_desc_text, '', [], true); (settings::get('system.allow_customer_shell') == '1') { $shell = validate::validate(trim($shell), 'shell', '', '', [], true); } else { $shell = "/bin/false"; } ($login_enabled != 1) { $login_enabled = 0; } // get needed customer info reduce ftp-user-counter one $customer = $this-&gt;getcustomerdata(); // password update? ($password != '') { // validate password $password = crypt::validatepassword($password, true); ($password == $result['username']) { response::standarderror('passwordshouldnotbeusername', '', true); } $cryptpassword = crypt::makecryptpassword($password, false, true); $stmt = database::prepare("update `" . table_ftp_users . "` set `password` = :password `customerid` = :customerid `id` = :id "); database::pexecute($stmt, [ "customerid" =&gt; $customer['customerid'], "id" =&gt; $id, "password" =&gt; $cryptpassword ], true, true); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] updated ftp-account password '" . $result['username'] . "'"); } // path update? ($path != '') { $path = filedir::makecorrectdir($customer['documentroot'] . '/' . $path, $customer['documentroot']); ($path != $result['homedir']) { $stmt = database::prepare("update `" . table_ftp_users . "` set `homedir` = :homedir `customerid` = :customerid `id` = :id "); database::pexecute($stmt, [ "homedir" =&gt; $path, "customerid" =&gt; $customer['customerid'], "id" =&gt; $id ], true, true); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] updated ftp-account homdir '" . $result['username'] . "'"); } } // task "new ftp" // create directories correct permissions cronjob::inserttask(taskid::create_ftp); $stmt = database::prepare(" update `" . table_ftp_users . "` set `description` = :desc, `shell` = :shell, `login_enabled` = :loginenabled `customerid` = :customerid `id` = :id "); database::pexecute($stmt, [ "desc" =&gt; $description, "shell" =&gt; $shell, "loginenabled" =&gt; $login_enabled ? 'y' : 'n', "customerid" =&gt; $customer['customerid'], "id" =&gt; $id ], true, true); $result = $this-&gt;apicall('ftps.get', [ 'username' =&gt; $result['username'] ]); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] updated ftp-user '" . $result['username'] . "'"); return $this-&gt;response($result); } /** * list ftp-users, called admin, list ftp-users customers allowed view, * specify id loginname one specific customer * * @param int $customerid * optional, admin-only, select ftp-users specific customer id * @param string $loginname * optional, admin-only, select ftp-users specific customer loginname * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin, customer * @return string json-encoded array count|list * @throws exception */ public function listing() { $customer_ids = $this-&gt;getallowedcustomerids('ftp'); $result = []; $query_fields = []; $result_stmt = database::prepare(" select * `" . table_ftp_users . "` `customerid` (" . implode(", ", $customer_ids) . ")" . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); database::pexecute($result_stmt, $query_fields, true, true); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $result[] = $row; } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] list ftp-users"); return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } /** * returns total number accessible ftp accounts * * @param int $customerid * optional, admin-only, select ftp-users specific customer id * @param string $loginname * optional, admin-only, select ftp-users specific customer loginname * * @access admin, customer * @return string json-encoded response message * @throws exception */ public function listingcount() { $customer_ids = $this-&gt;getallowedcustomerids('ftp'); $result = []; $result_stmt = database::prepare(" select count(*) num_ftps `" . table_ftp_users . "` `customerid` (" . implode(", ", $customer_ids) . ") "); $result = database::pexecute_first($result_stmt, null, true, true); ($result) { return $this-&gt;response($result['num_ftps']); } return $this-&gt;response(0); } /** * delete ftp-user either id username * * @param int $id * optional, ftp-user-id * @param string $username * optional, username * @param bool $delete_userfiles * optional, default false * * @access admin, customer * @return string json-encoded array * @throws exception */ public function delete() { $id = $this-&gt;getparam('id', true, 0); $un_optional = $id &gt; 0; $username = $this-&gt;getparam('username', $un_optional, ''); $delete_userfiles = $this-&gt;getboolparam('delete_userfiles', true, 0); ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'ftp')) { throw new exception("you cannot access resource", 405); } // get ftp-user $result = $this-&gt;apicall('ftps.get', [ 'id' =&gt; $id, 'username' =&gt; $username ]); $id = $result['id']; ($this-&gt;isadmin()) { // get customer-data $customer_data = $this-&gt;apicall('customers.get', [ 'id' =&gt; $result['customerid'] ]); } else { $customer_data = $this-&gt;getuserdata(); } // add usage ftp-user main-ftp user customer different ($result['username'] != $customer_data['loginname']) { $stmt = database::prepare("update `" . table_ftp_users . "` set `up_count` = `up_count` + :up_count, `up_bytes` = `up_bytes` + :up_bytes, `down_count` = `down_count` + :down_count, `down_bytes` = `down_bytes` + :down_bytes `username` = :username "); $params = [ "up_count" =&gt; $result['up_count'], "up_bytes" =&gt; $result['up_bytes'], "down_count" =&gt; $result['down_count'], "down_bytes" =&gt; $result['down_bytes'], "username" =&gt; $customer_data['loginname'] ]; database::pexecute($stmt, $params, true, true); } else { // allow removing default ftp-account response::standarderror('ftp_cantdeletemainaccount', '', true); } // remove quotatallies $stmt = database::prepare("delete `" . table_ftp_quotatallies . "` `name` = :name"); database::pexecute($stmt, [ "name" =&gt; $result['username'] ], true, true); // remove user $stmt = database::prepare(" delete `" . table_ftp_users . "` `customerid` = :customerid `id` = :id "); database::pexecute($stmt, [ "customerid" =&gt; $customer_data['customerid'], "id" =&gt; $id ], true, true); // update ftp-groups $stmt = database::prepare(" update `" . table_ftp_groups . "` set `members` = replace(`members`, :username,'') `customerid` = :customerid "); database::pexecute($stmt, [ "username" =&gt; "," . $result['username'], "customerid" =&gt; $customer_data['customerid'] ], true, true); // refs #293 ($delete_userfiles == 1) { cronjob::inserttask(taskid::delete_ftp_data, $customer_data['loginname'], $result['homedir']); } else { (settings::get('system.nssextrausers') == 1) { // used libnss-extrausers cron fired cronjob::inserttask(taskid::create_ftp); } } // decrease ftp-user usage customer $resetaccnumber = ($customer_data['ftps_used'] == '1') ? " , `ftp_lastaccountnumber`='0'" : ''; customers::decreaseusage($customer_data['customerid'], 'ftps_used', $resetaccnumber); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_warning, "[api] deleted ftp-user '" . $result['username'] . "'"); return $this-&gt;response($result); } }</file><file name="lib/Froxlor/Api/Commands/Cronjobs.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\system\cronjob; use froxlor\ui\response; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class cronjobs extends apicommand implements resourceentity { private array $allowed_intervals = [ 'minute', 'hour', 'day', 'week', 'month' ]; /** * cannot add new cronjobs yet. */ public function add() { throw new exception('you cannot add new cronjobs yet.', 303); } /** * return cronjob entry id * * @param int $id * cronjob-id * * @access admin * @return string json-encoded array * @throws exception */ public function get() { ($this-&gt;isadmin()) { $id = $this-&gt;getparam('id'); $result_stmt = database::prepare(" select * `" . table_panel_cronruns . "` `id` = :id "); $result = database::pexecute_first($result_stmt, [ 'id' =&gt; $id ], true, true); ($result) { return $this-&gt;response($result); } throw new exception("cronjob id #" . $id . " could found", 404); } throw new exception("not allowed execute given command.", 403); } /** * update cronjob entry given id * * @param int $id * @param bool $isactive * optional whether cronjob active * @param int $interval_value * optional number seconds/minutes/hours/etc. interval * @param string $interval_interval * optional interval cronjob (minute, hour, day, week month) * * @access admin * @return string json-encoded array * @throws exception */ public function update() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 1) { // required parameter $id = $this-&gt;getparam('id'); $result = $this-&gt;apicall('cronjobs.get', [ 'id' =&gt; $id ]); // split interval $cur_int = explode(" ", $result['interval']); // parameter $isactive = $this-&gt;getboolparam('isactive', true, $result['isactive']); $interval_value = $this-&gt;getparam('interval_value', true, $cur_int[0]); $interval_interval = $this-&gt;getparam('interval_interval', true, $cur_int[1]); // validation ($isactive != 1) { $isactive = 0; } $interval_value = validate::validate($interval_value, 'interval_value', '/^([0-9]+)$/di', 'stringisempty', [], true); $interval_interval = validate::validate($interval_interval, 'interval_interval', '', '', [], true); (!in_array(strtoupper($interval_interval), $this-&gt;allowed_intervals)) { response::standarderror('invalidcronjobintervalvalue', implode(", ", $this-&gt;allowed_intervals), true); } // put together interval value $interval = $interval_value . ' ' . strtoupper($interval_interval); $upd_stmt = database::prepare(" update `" . table_panel_cronruns . "` set `isactive` = :isactive, `interval` = :int `id` = :id "); database::pexecute($upd_stmt, [ 'isactive' =&gt; $isactive, 'int' =&gt; $interval, 'id' =&gt; $id ], true, true); // insert task re-generate cron.d-file cronjob::inserttask(taskid::rebuild_cron); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] cronjob description '" . $result['module'] . '/' . $result['cronfile'] . "' updated '" . $this-&gt;getuserdetail('loginname') . "'"); $result = $this-&gt;apicall('cronjobs.get', [ 'id' =&gt; $id ]); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } /** * lists cronjob entries * * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin * @return string json-encoded array count|list * @throws exception */ public function listing() { ($this-&gt;isadmin()) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_info, "[api] list cronjobs"); $query_fields = []; $result_stmt = database::prepare(" select `c`.* `" . table_panel_cronruns . "` `c` " . $this-&gt;getsearchwhere($query_fields) . $this-&gt;getorderby() . $this-&gt;getlimit()); database::pexecute($result_stmt, $query_fields, true, true); $result = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $result[] = $row; } return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } throw new exception("not allowed execute given command.", 403); } /** * returns total number cronjobs * * @access admin * @return string json-encoded response message * @throws exception */ public function listingcount() { ($this-&gt;isadmin()) { $result_stmt = database::prepare(" select count(*) num_crons `" . table_panel_cronruns . "` `c` "); $result = database::pexecute_first($result_stmt, null, true, true); ($result) { return $this-&gt;response($result['num_crons']); } return $this-&gt;response(0); } throw new exception("not allowed execute given command.", 403); } /** * cannot delete system cronjobs. */ public function delete() { throw new exception('you cannot delete system cronjobs.', 303); } }</file><file name="lib/Froxlor/Api/Commands/PhpSettings.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\system\cronjob; use froxlor\ui\response; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class phpsettings extends apicommand implements resourceentity { /** * lists php-setting entries * * @param bool $with_subdomains * optional, also include subdomains list domains use config, default 0 (false) * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin * @return string json-encoded array count|list * @throws exception */ public function listing() { ($this-&gt;isadmin()) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_info, "[api] list php-configs"); $with_subdomains = $this-&gt;getboolparam('with_subdomains', true, false); $query_fields = []; $result_stmt = database::prepare(" select c.*, fd.description fpmdesc `" . table_panel_phpconfigs . "` c left join `" . table_panel_fpmdaemons . "` fd fd.id = c.fpmsettingid" . $this-&gt;getsearchwhere($query_fields) . $this-&gt;getorderby() . $this-&gt;getlimit()); database::pexecute($result_stmt, $query_fields, true, true); $phpconfigs = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $query_params = [ 'id' =&gt; $row['id'] ]; $query = "select * `" . table_panel_domains . "` `phpsettingid` = :id `email_only` = '0' `phpenabled` = '1'"; (!$with_subdomains) { $query .= " `parentdomainid` = '0'"; } ((int)$this-&gt;getuserdetail('customers_see_all') == 0) { $query .= " `adminid` = :adminid"; $query_params['adminid'] = $this-&gt;getuserdetail('adminid'); } ((int)settings::get('panel.phpconfigs_hidestdsubdomain') == 1) { $ssdids_res = database::query(" select distinct `standardsubdomain` `" . table_panel_customers . "` `standardsubdomain` &gt; 0 order `standardsubdomain` asc;"); $ssdids = []; ($ssd = $ssdids_res-&gt;fetch(pdo::fetch_assoc)) { $ssdids[] = $ssd['standardsubdomain']; } (count($ssdids) &gt; 0) { $query .= " `id` (" . implode(', ', $ssdids) . ")"; } } $domains = []; $subdomains = []; $domainresult_stmt = database::prepare($query); database::pexecute($domainresult_stmt, $query_params, true, true); (database::num_rows() &gt; 0) { ($row2 = $domainresult_stmt-&gt;fetch(pdo::fetch_assoc)) { ($row2['parentdomainid'] != 0) { $subdomains[] = $row2['domain']; } else { $domains[] = $row2['domain']; } } } // check whether use config froxor-vhost config ((settings::get('system.mod_fcgid') == '1' &amp;&amp; settings::get('system.mod_fcgid_defaultini_ownvhost') == $row['id']) || (settings::get('phpfpm.enabled') == '1' &amp;&amp; settings::get('phpfpm.vhost_defaultini') == $row['id'])) { $domains[] = settings::get('system.hostname'); } // check whether default config ((settings::get('system.mod_fcgid') == '1' &amp;&amp; settings::get('system.mod_fcgid_defaultini') == $row['id']) || (settings::get('phpfpm.enabled') == '1' &amp;&amp; settings::get('phpfpm.defaultini') == $row['id'])) { $row['is_default'] = true; } $row['domains'] = $domains; $row['subdomains'] = $subdomains; $phpconfigs[] = $row; } return $this-&gt;response([ 'count' =&gt; count($phpconfigs), 'list' =&gt; $phpconfigs ]); } throw new exception("not allowed execute given command.", 403); } /** * return php-setting entry id * * @param int $id * php-settings-id * * @access admin * @return string json-encoded array * @throws exception */ public function get() { ($this-&gt;isadmin()) { $id = $this-&gt;getparam('id'); $result_stmt = database::prepare(" select * `" . table_panel_phpconfigs . "` `id` = :id "); $result = database::pexecute_first($result_stmt, [ 'id' =&gt; $id ], true, true); ($result) { return $this-&gt;response($result); } throw new exception("php-config id #" . $id . " could found", 404); } throw new exception("not allowed execute given command.", 403); } /** * returns total number accessible php-setting entries * * @access admin * @return string json-encoded response message * @throws exception */ public function listingcount() { ($this-&gt;isadmin()) { $result_stmt = database::prepare(" select count(*) num_phps `" . table_panel_phpconfigs . "` c "); $result = database::pexecute_first($result_stmt, null, true, true); ($result) { return $this-&gt;response($result['num_phps']); } return $this-&gt;response(0); } throw new exception("not allowed execute given command.", 403); } /** * add new php-settings entry * * @param string $description * description php-config * @param string $phpsettings * actual ini-settings * @param string $binary * optional binary php-cgi fcgid used * @param string $file_extensions * optional allowed php-file-extensions fcgid used, default 'php' * @param int $mod_fcgid_starter * optional number fcgid-starters fcgid used, default -1 * @param int $mod_fcgid_maxrequests * optional number fcgid-maxrequests fcgid used, default -1 * @param string $mod_fcgid_umask * optional umask fcgid used, default '022' * @param int $fpmconfig * optional id fpm-daemon-config fpm used * @param bool $phpfpm_enable_slowlog * optional whether write slowlog fpm used, default 0 (false) * @param string $phpfpm_reqtermtimeout * optional request terminate timeout fpm used, default '60s' * @param string $phpfpm_reqslowtimeout * optional request slowlog timeout fpm used, default '5s' * @param bool $pass_authorizationheader * optional whether pass authorization header webserver fpm/fcgid used, default 0 (false) * @param bool $override_fpmconfig * optional whether override fpm-daemon-config value following settings fpm used, * default 0 (false) * @param string $pm * optional process-manager use fpm used (allowed values 'static', 'dynamic' * 'ondemand'), default fpm-daemon-value * @param int $max_children * optional number max children fpm used, default fpm-daemon-value * @param int $start_server * optional number servers start fpm used, default fpm-daemon-value * @param int $min_spare_servers * optional number minimum spare servers fpm used, default fpm-daemon-value * @param int $max_spare_servers * optional number maximum spare servers fpm used, default fpm-daemon-value * @param int $max_requests * optional number maximum requests fpm used, default fpm-daemon-value * @param int $idle_timeout * optional number seconds idle-timeout fpm used, default fpm-daemon-value * @param string $limit_extensions * optional limitation php-file-extensions fpm used, default fpm-daemon-value * @param bool $allow_all_customers * optional add configuration list every existing customer's allowed-fpm-config list, * default false (no) * * @access admin * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 1) { // required parameter $description = $this-&gt;getparam('description'); $phpsettings = $this-&gt;getparam('phpsettings'); (settings::get('system.mod_fcgid') == 1) { $binary = $this-&gt;getparam('binary'); $fpm_config_id = 1; } elseif (settings::get('phpfpm.enabled') == 1) { $fpm_config_id = intval($this-&gt;getparam('fpmconfig')); } else { $fpm_config_id = 1; } // parameters $file_extensions = $this-&gt;getparam('file_extensions', true, 'php'); $mod_fcgid_starter = $this-&gt;getparam('mod_fcgid_starter', true, -1); $mod_fcgid_maxrequests = $this-&gt;getparam('mod_fcgid_maxrequests', true, -1); $mod_fcgid_umask = $this-&gt;getparam('mod_fcgid_umask', true, "022"); $fpm_enableslowlog = $this-&gt;getboolparam('phpfpm_enable_slowlog', true, 0); $fpm_reqtermtimeout = $this-&gt;getparam('phpfpm_reqtermtimeout', true, "60s"); $fpm_reqslowtimeout = $this-&gt;getparam('phpfpm_reqslowtimeout', true, "5s"); $pass_authorizationheader = $this-&gt;getboolparam('pass_authorizationheader', true, 0); $override_fpmconfig = $this-&gt;getboolparam('override_fpmconfig', true, 0); $def_fpmconfig = $this-&gt;apicall('fpmdaemons.get', [ 'id' =&gt; $fpm_config_id ]); $pmanager = $this-&gt;getparam('pm', true, $def_fpmconfig['pm']); $max_children = $this-&gt;getparam('max_children', true, $def_fpmconfig['max_children']); $start_servers = $this-&gt;getparam('start_servers', true, $def_fpmconfig['start_servers']); $min_spare_servers = $this-&gt;getparam('min_spare_servers', true, $def_fpmconfig['min_spare_servers']); $max_spare_servers = $this-&gt;getparam('max_spare_servers', true, $def_fpmconfig['max_spare_servers']); $max_requests = $this-&gt;getparam('max_requests', true, $def_fpmconfig['max_requests']); $idle_timeout = $this-&gt;getparam('idle_timeout', true, $def_fpmconfig['idle_timeout']); $limit_extensions = $this-&gt;getparam('limit_extensions', true, $def_fpmconfig['limit_extensions']); $allow_all_customers = $this-&gt;getboolparam('allow_all_customers', true, 0); // validation $description = validate::validate($description, 'description', validate::regex_desc_text, '', [], true); $phpsettings = validate::validate(str_replace("\r\n", "\n", $phpsettings), 'phpsettings', '/^[^\0]*$/', '', [], true); (settings::get('system.mod_fcgid') == 1) { $binary = filedir::makecorrectfile(validate::validate($binary, 'binary', '', '', [], true)); $file_extensions = validate::validate($file_extensions, 'file_extensions', '/^[a-za-z0-9\s]*$/', '', [], true); $mod_fcgid_starter = validate::validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', [ '-1', '' ], true); $mod_fcgid_maxrequests = validate::validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', [ '-1', '' ], true); $mod_fcgid_umask = validate::validate($mod_fcgid_umask, 'mod_fcgid_umask', '/^[0-9]*$/', '', [], true); // disable fpm stuff $fpm_config_id = 1; $fpm_enableslowlog = 0; $fpm_reqtermtimeout = 0; $fpm_reqslowtimeout = 0; $override_fpmconfig = 0; } elseif (settings::get('phpfpm.enabled') == 1) { $fpm_reqtermtimeout = validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true); $fpm_reqslowtimeout = validate::validate($fpm_reqslowtimeout, 'phpfpm_reqslowtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true); (!in_array($pmanager, [ 'static', 'dynamic', 'ondemand' ])) { throw new exception("unknown process manager", 406); } (empty($limit_extensions)) { $limit_extensions = '.php'; } $limit_extensions = validate::validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', [], true); // disable fcgid stuff $binary = '/usr/bin/php-cgi'; $file_extensions = 'php'; $mod_fcgid_starter = 0; $mod_fcgid_maxrequests = 0; $mod_fcgid_umask = "022"; } (strlen($description) == 0 || strlen($description) &gt; 50) { response::standarderror('descriptioninvalid', '', true); } $ins_stmt = database::prepare(" insert `" . table_panel_phpconfigs . "` set `description` = :desc, `binary` = :binary, `file_extensions` = :fext, `mod_fcgid_starter` = :starter, `mod_fcgid_maxrequests` = :mreq, `mod_fcgid_umask` = :umask, `fpm_slowlog` = :fpmslow, `fpm_reqterm` = :fpmreqterm, `fpm_reqslow` = :fpmreqslow, `phpsettings` = :phpsettings, `fpmsettingid` = :fpmsettingid, `pass_authorizationheader` = :fpmpassauth, `override_fpmconfig` = :ofc, `pm` = :pm, `max_children` = :max_children, `start_servers` = :start_servers, `min_spare_servers` = :min_spare_servers, `max_spare_servers` = :max_spare_servers, `max_requests` = :max_requests, `idle_timeout` = :idle_timeout, `limit_extensions` = :limit_extensions "); $ins_data = [ 'desc' =&gt; $description, 'binary' =&gt; $binary, 'fext' =&gt; $file_extensions, 'starter' =&gt; $mod_fcgid_starter, 'mreq' =&gt; $mod_fcgid_maxrequests, 'umask' =&gt; $mod_fcgid_umask, 'fpmslow' =&gt; $fpm_enableslowlog, 'fpmreqterm' =&gt; $fpm_reqtermtimeout, 'fpmreqslow' =&gt; $fpm_reqslowtimeout, 'phpsettings' =&gt; $phpsettings, 'fpmsettingid' =&gt; $fpm_config_id, 'fpmpassauth' =&gt; $pass_authorizationheader, 'ofc' =&gt; $override_fpmconfig, 'pm' =&gt; $pmanager, 'max_children' =&gt; $max_children, 'start_servers' =&gt; $start_servers, 'min_spare_servers' =&gt; $min_spare_servers, 'max_spare_servers' =&gt; $max_spare_servers, 'max_requests' =&gt; $max_requests, 'idle_timeout' =&gt; $idle_timeout, 'limit_extensions' =&gt; $limit_extensions ]; database::pexecute($ins_stmt, $ins_data, true, true); $ins_data['id'] = database::lastinsertid(); cronjob::inserttask(taskid::rebuild_vhost); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] php setting description '" . $description . "' created '" . $this-&gt;getuserdetail('loginname') . "'"); $result = $this-&gt;apicall('phpsettings.get', [ 'id' =&gt; $ins_data['id'] ]); $this-&gt;addforallcustomers($allow_all_customers, $ins_data['id']); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } /** * add given php-config id list allowed php-config currently existing customers * allow_all_customers parameter true phpsettings::add() phpsettings::update() * * @param bool $allow_all_customers * @param int $config_id */ private function addforallcustomers(bool $allow_all_customers, int $config_id) { // config added allowed list existing customers? ($allow_all_customers) { $sel_stmt = database::prepare("select customerid, allowed_phpconfigs `" . table_panel_customers . "`"); $upd_stmt = database::prepare("update `" . table_panel_customers . "` set allowed_phpconfigs = :ap customerid = :cid"); database::pexecute($sel_stmt); ($cust = $sel_stmt-&gt;fetch(pdo::fetch_assoc)) { // get existing entries customer $ap = json_decode($cust['allowed_phpconfigs'], true); // initialize array empty (empty($ap)) { $ap = []; } // add config $ap[] = $config_id; // check duplicates force value-type int $ap = array_map('intval', array_unique($ap)); // update customer-entry database::pexecute($upd_stmt, [ 'ap' =&gt; json_encode($ap), 'cid' =&gt; $cust['customerid'] ]); } } } /** * update php-setting entry given id * * @param int $id * @param string $description * description php-config * @param string $phpsettings * actual ini-settings * @param string $binary * optional binary php-cgi fcgid used * @param string $file_extensions * optional allowed php-file-extensions fcgid used, default 'php' * @param int $mod_fcgid_starter * optional number fcgid-starters fcgid used, default -1 * @param int $mod_fcgid_maxrequests * optional number fcgid-maxrequests fcgid used, default -1 * @param string $mod_fcgid_umask * optional umask fcgid used, default '022' * @param int $fpmconfig * optional id fpm-daemon-config fpm used * @param bool $phpfpm_enable_slowlog * optional whether write slowlog fpm used, default 0 (false) * @param string $phpfpm_reqtermtimeout * optional request terminate timeout fpm used, default '60s' * @param string $phpfpm_reqslowtimeout * optional request slowlog timeout fpm used, default '5s' * @param bool $pass_authorizationheader * optional whether pass authorization header webserver fpm used, default 0 (false) * @param bool $override_fpmconfig * optional whether override fpm-daemon-config value following settings fpm used, * default 0 (false) * @param string $pm * optional process-manager use fpm used (allowed values 'static', 'dynamic' * 'ondemand'), default fpm-daemon-value * @param int $max_children * optional number max children fpm used, default fpm-daemon-value * @param int $start_server * optional number servers start fpm used, default fpm-daemon-value * @param int $min_spare_servers * optional number minimum spare servers fpm used, default fpm-daemon-value * @param int $max_spare_servers * optional number maximum spare servers fpm used, default fpm-daemon-value * @param int $max_requests * optional number maximum requests fpm used, default fpm-daemon-value * @param int $idle_timeout * optional number seconds idle-timeout fpm used, default fpm-daemon-value * @param string $limit_extensions * optional limitation php-file-extensions fpm used, default fpm-daemon-value * @param bool $allow_all_customers * optional add configuration list every existing customer's allowed-fpm-config list, * default false (no) * * @access admin * @return string json-encoded array * @throws exception */ public function update() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 1) { // required parameter $id = $this-&gt;getparam('id'); $result = $this-&gt;apicall('phpsettings.get', [ 'id' =&gt; $id ]); // parameters $description = $this-&gt;getparam('description', true, $result['description']); $phpsettings = $this-&gt;getparam('phpsettings', true, $result['phpsettings']); $binary = $this-&gt;getparam('binary', true, $result['binary']); $fpm_config_id = intval($this-&gt;getparam('fpmconfig', true, $result['fpmsettingid'])); $file_extensions = $this-&gt;getparam('file_extensions', true, $result['file_extensions']); $mod_fcgid_starter = $this-&gt;getparam('mod_fcgid_starter', true, $result['mod_fcgid_starter']); $mod_fcgid_maxrequests = $this-&gt;getparam('mod_fcgid_maxrequests', true, $result['mod_fcgid_maxrequests']); $mod_fcgid_umask = $this-&gt;getparam('mod_fcgid_umask', true, $result['mod_fcgid_umask']); $fpm_enableslowlog = $this-&gt;getboolparam('phpfpm_enable_slowlog', true, $result['fpm_slowlog']); $fpm_reqtermtimeout = $this-&gt;getparam('phpfpm_reqtermtimeout', true, $result['fpm_reqterm']); $fpm_reqslowtimeout = $this-&gt;getparam('phpfpm_reqslowtimeout', true, $result['fpm_reqslow']); $pass_authorizationheader = $this-&gt;getboolparam('pass_authorizationheader', true, $result['pass_authorizationheader']); $override_fpmconfig = $this-&gt;getboolparam('override_fpmconfig', true, $result['override_fpmconfig']); $pmanager = $this-&gt;getparam('pm', true, $result['pm']); $max_children = $this-&gt;getparam('max_children', true, $result['max_children']); $start_servers = $this-&gt;getparam('start_servers', true, $result['start_servers']); $min_spare_servers = $this-&gt;getparam('min_spare_servers', true, $result['min_spare_servers']); $max_spare_servers = $this-&gt;getparam('max_spare_servers', true, $result['max_spare_servers']); $max_requests = $this-&gt;getparam('max_requests', true, $result['max_requests']); $idle_timeout = $this-&gt;getparam('idle_timeout', true, $result['idle_timeout']); $limit_extensions = $this-&gt;getparam('limit_extensions', true, $result['limit_extensions']); $allow_all_customers = $this-&gt;getboolparam('allow_all_customers', true, 0); // validation $description = validate::validate($description, 'description', validate::regex_desc_text, '', [], true); $phpsettings = validate::validate(str_replace("\r\n", "\n", $phpsettings), 'phpsettings', '/^[^\0]*$/', '', [], true); (settings::get('system.mod_fcgid') == 1) { $binary = filedir::makecorrectfile(validate::validate($binary, 'binary', '', '', [], true)); $file_extensions = validate::validate($file_extensions, 'file_extensions', '/^[a-za-z0-9\s]*$/', '', [], true); $mod_fcgid_starter = validate::validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', [ '-1', '' ], true); $mod_fcgid_maxrequests = validate::validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', [ '-1', '' ], true); $mod_fcgid_umask = validate::validate($mod_fcgid_umask, 'mod_fcgid_umask', '/^[0-9]*$/', '', [], true); // disable fpm stuff $fpm_config_id = 1; $fpm_enableslowlog = 0; $fpm_reqtermtimeout = 0; $fpm_reqslowtimeout = 0; $override_fpmconfig = 0; } elseif (settings::get('phpfpm.enabled') == 1) { $fpm_reqtermtimeout = validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true); $fpm_reqslowtimeout = validate::validate($fpm_reqslowtimeout, 'phpfpm_reqslowtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true); (!in_array($pmanager, [ 'static', 'dynamic', 'ondemand' ])) { throw new exception("unknown process manager", 406); } (empty($limit_extensions)) { $limit_extensions = '.php'; } $limit_extensions = validate::validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', [], true); // disable fcgid stuff $binary = '/usr/bin/php-cgi'; $file_extensions = 'php'; $mod_fcgid_starter = 0; $mod_fcgid_maxrequests = 0; $mod_fcgid_umask = "022"; } (strlen($description) == 0 || strlen($description) &gt; 50) { response::standarderror('descriptioninvalid', '', true); } $upd_stmt = database::prepare(" update `" . table_panel_phpconfigs . "` set `description` = :desc, `binary` = :binary, `file_extensions` = :fext, `mod_fcgid_starter` = :starter, `mod_fcgid_maxrequests` = :mreq, `mod_fcgid_umask` = :umask, `fpm_slowlog` = :fpmslow, `fpm_reqterm` = :fpmreqterm, `fpm_reqslow` = :fpmreqslow, `phpsettings` = :phpsettings, `fpmsettingid` = :fpmsettingid, `pass_authorizationheader` = :fpmpassauth, `override_fpmconfig` = :ofc, `pm` = :pm, `max_children` = :max_children, `start_servers` = :start_servers, `min_spare_servers` = :min_spare_servers, `max_spare_servers` = :max_spare_servers, `max_requests` = :max_requests, `idle_timeout` = :idle_timeout, `limit_extensions` = :limit_extensions `id` = :id "); $upd_data = [ 'desc' =&gt; $description, 'binary' =&gt; $binary, 'fext' =&gt; $file_extensions, 'starter' =&gt; $mod_fcgid_starter, 'mreq' =&gt; $mod_fcgid_maxrequests, 'umask' =&gt; $mod_fcgid_umask, 'fpmslow' =&gt; $fpm_enableslowlog, 'fpmreqterm' =&gt; $fpm_reqtermtimeout, 'fpmreqslow' =&gt; $fpm_reqslowtimeout, 'phpsettings' =&gt; $phpsettings, 'fpmsettingid' =&gt; $fpm_config_id, 'fpmpassauth' =&gt; $pass_authorizationheader, 'ofc' =&gt; $override_fpmconfig, 'pm' =&gt; $pmanager, 'max_children' =&gt; $max_children, 'start_servers' =&gt; $start_servers, 'min_spare_servers' =&gt; $min_spare_servers, 'max_spare_servers' =&gt; $max_spare_servers, 'max_requests' =&gt; $max_requests, 'idle_timeout' =&gt; $idle_timeout, 'limit_extensions' =&gt; $limit_extensions, 'id' =&gt; $id ]; database::pexecute($upd_stmt, $upd_data, true, true); cronjob::inserttask(taskid::rebuild_vhost); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] php setting description '" . $description . "' updated '" . $this-&gt;getuserdetail('loginname') . "'"); $result = $this-&gt;apicall('phpsettings.get', [ 'id' =&gt; $id ]); $this-&gt;addforallcustomers($allow_all_customers, $id); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } /** * delete php-setting entry id * * @param int $id * php-settings-id * * @access admin * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 1) { $id = $this-&gt;getparam('id'); $result = $this-&gt;apicall('phpsettings.get', [ 'id' =&gt; $id ]); ((settings::get('system.mod_fcgid') == '1' &amp;&amp; settings::get('system.mod_fcgid_defaultini_ownvhost') == $id) || (settings::get('phpfpm.enabled') == '1' &amp;&amp; settings::get('phpfpm.vhost_defaultini') == $id)) { response::standarderror('cannotdeletehostnamephpconfig', '', true); } ((settings::get('system.mod_fcgid') == '1' &amp;&amp; settings::get('system.mod_fcgid_defaultini') == $id) || (settings::get('phpfpm.enabled') == '1' &amp;&amp; settings::get('phpfpm.defaultini') == $id)) { response::standarderror('cannotdeletedefaultphpconfig', '', true); } // set php-config default domains using // config deleted $upd_stmt = database::prepare(" update `" . table_panel_domains . "` set `phpsettingid` = '1' `phpsettingid` = :id "); database::pexecute($upd_stmt, [ 'id' =&gt; $id ], true, true); $del_stmt = database::prepare(" delete `" . table_panel_phpconfigs . "` `id` = :id "); database::pexecute($del_stmt, [ 'id' =&gt; $id ], true, true); cronjob::inserttask(taskid::rebuild_vhost); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] php setting '" . $result['description'] . "' deleted '" . $this-&gt;getuserdetail('loginname') . "'"); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } }</file><file name="lib/Froxlor/Api/Commands/IpsAndPorts.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\system\cronjob; use froxlor\ui\response; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class ipsandports extends apicommand implements resourceentity { /** * lists ip/port entries * * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin * @return string json-encoded array count|list * @throws exception */ public function listing() { ($this-&gt;isadmin() &amp;&amp; ($this-&gt;getuserdetail('change_serversettings') || !empty($this-&gt;getuserdetail('ip')))) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_info, "[api] list ips ports"); $ip_where = ""; $append_where = false; (!empty($this-&gt;getuserdetail('ip')) &amp;&amp; $this-&gt;getuserdetail('ip') != -1) { $ip_where = "where `id` (" . implode(", ", json_decode($this-&gt;getuserdetail('ip'), true)) . ")"; $append_where = true; } $query_fields = []; $result_stmt = database::prepare(" select * `" . table_panel_ipsandports . "` " . $ip_where . $this-&gt;getsearchwhere($query_fields, $append_where) . $this-&gt;getorderby() . $this-&gt;getlimit()); database::pexecute($result_stmt, $query_fields, true, true); $result = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $result[] = $row; } return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } throw new exception("not allowed execute given command.", 403); } /** * returns total number accessible ip/port entries * * @access admin * @return string json-encoded response message * @throws exception */ public function listingcount() { ($this-&gt;isadmin() &amp;&amp; ($this-&gt;getuserdetail('change_serversettings') || !empty($this-&gt;getuserdetail('ip')))) { $ip_where = ""; (!empty($this-&gt;getuserdetail('ip')) &amp;&amp; $this-&gt;getuserdetail('ip') != -1) { $ip_where = "where `id` (" . implode(", ", json_decode($this-&gt;getuserdetail('ip'), true)) . ")"; } $result_stmt = database::prepare(" select count(*) num_ips `" . table_panel_ipsandports . "` " . $ip_where); $result = database::pexecute_first($result_stmt, null, true, true); ($result) { return $this-&gt;response($result['num_ips']); } return $this-&gt;response(0); } throw new exception("not allowed execute given command.", 403); } /** * create new ip/port entry * * @param string $ip * @param int $port * optional, default 80 * @param bool $listen_statement * optional, default 0 (false) * @param bool $namevirtualhost_statement * optional, default 0 (false) * @param bool $vhostcontainer * optional, default 0 (false) * @param string $specialsettings * optional, default empty * @param bool $vhostcontainer_servername_statement * optional, default 0 (false) * @param string $default_vhostconf_domain * optional, defatul empty * @param string $docroot * optional, default empty (point froxlor) * @param bool $ssl * optional, default 0 (false) * @param string $ssl_cert_file * optional, requires $ssl = 1, default empty * @param string $ssl_key_file * optional, requires $ssl = 1, default empty * @param string $ssl_ca_file * optional, requires $ssl = 1, default empty * @param string $ssl_cert_chainfile * optional, requires $ssl = 1, default empty * @param string $ssl_specialsettings * optional, requires $ssl = 1, default empty * @param bool $include_specialsettings * optional, requires $ssl = 1, whether include non-ssl specialsettings, default false * @param string $ssl_default_vhostconf_domain * optional, requires $ssl = 1, defatul empty * @param bool $include_default_vhostconf_domain * optional, requires $ssl = 1, whether include non-ssl default_vhostconf_domain, default false * * @access admin * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings')) { $ip = validate::validate_ip2($this-&gt;getparam('ip'), false, 'invalidip', false, true, false, false, true); $port = validate::validate($this-&gt;getparam('port', true, 80), 'port', validate::regex_port, [ 'stringisempty', 'myport' ], [], true); $listen_statement = !empty($this-&gt;getboolparam('listen_statement', true, 0)) ? 1 : 0; $namevirtualhost_statement = !empty($this-&gt;getboolparam('namevirtualhost_statement', true, 0)) ? 1 : 0; $vhostcontainer = !empty($this-&gt;getboolparam('vhostcontainer', true, 0)) ? 1 : 0; $ss = $this-&gt;getparam('specialsettings', true, ''); $specialsettings = validate::validate(str_replace("\r\n", "\n", $ss ?? ""), 'specialsettings', validate::regex_conf_text, '', [], true); $vhostcontainer_servername_statement = !empty($this-&gt;getboolparam('vhostcontainer_servername_statement', true, 1)) ? 1 : 0; $dvd = $this-&gt;getparam('default_vhostconf_domain', true, ''); $default_vhostconf_domain = validate::validate(str_replace("\r\n", "\n", $dvd), 'default_vhostconf_domain', validate::regex_conf_text, '', [], true); $docroot = validate::validate($this-&gt;getparam('docroot', true, ''), 'docroot', validate::regex_dir, '', [], true); ((int)settings::get('system.use_ssl') == 1) { $ssl = (bool)$this-&gt;getboolparam('ssl', true, 0); $cert_optional = !($ssl &amp;&amp; empty(settings::get('system.ssl_cert_file'))); $ssl_cert_file = validate::validate($this-&gt;getparam('ssl_cert_file', $cert_optional, ''), 'ssl_cert_file', '', '', [], true); $ssl_key_file = validate::validate($this-&gt;getparam('ssl_key_file', $cert_optional, ''), 'ssl_key_file', '', '', [], true); $ssl_ca_file = validate::validate($this-&gt;getparam('ssl_ca_file', true, ''), 'ssl_ca_file', '', '', [], true); $ssl_cert_chainfile = validate::validate($this-&gt;getparam('ssl_cert_chainfile', true, ''), 'ssl_cert_chainfile', '', '', [], true); $sslss = $this-&gt;getparam('ssl_specialsettings', true, ''); $ssl_specialsettings = validate::validate(str_replace("\r\n", "\n", $sslss ?? ""), 'ssl_specialsettings', validate::regex_conf_text, '', [], true); $include_specialsettings = !empty($this-&gt;getboolparam('include_specialsettings', true, 0)) ? 1 : 0; $ssldvd = $this-&gt;getparam('ssl_default_vhostconf_domain', true, ''); $ssl_default_vhostconf_domain = validate::validate(str_replace("\r\n", "\n", $ssldvd ?? ""), 'ssl_default_vhostconf_domain', validate::regex_conf_text, '', [], true); $include_default_vhostconf_domain = !empty($this-&gt;getboolparam('include_default_vhostconf_domain', true, 0)) ? 1 : 0; } else { $ssl = 0; $ssl_cert_file = ''; $ssl_key_file = ''; $ssl_ca_file = ''; $ssl_cert_chainfile = ''; $ssl_specialsettings = ''; $include_specialsettings = 0; $ssl_default_vhostconf_domain = ''; $include_default_vhostconf_domain = 0; } ($listen_statement != '1') { $listen_statement = '0'; } ($namevirtualhost_statement != '1') { $namevirtualhost_statement = '0'; } ($vhostcontainer != '1') { $vhostcontainer = '0'; } ($vhostcontainer_servername_statement != '1') { $vhostcontainer_servername_statement = '0'; } ($ssl != '1') { $ssl = '0'; } ($ssl_cert_file != '') { $ssl_cert_file = filedir::makecorrectfile($ssl_cert_file); } ($ssl_key_file != '') { $ssl_key_file = filedir::makecorrectfile($ssl_key_file); } ($ssl_ca_file != '') { $ssl_ca_file = filedir::makecorrectfile($ssl_ca_file); } ($ssl_cert_chainfile != '') { $ssl_cert_chainfile = filedir::makecorrectfile($ssl_cert_chainfile); } (strlen(trim($docroot)) &gt; 0) { $docroot = filedir::makecorrectdir($docroot); } else { $docroot = ''; } // always use compressed ipv6 format $ip = inet_ntop(inet_pton($ip)); $result_checkfordouble_stmt = database::prepare(" select `id` `" . table_panel_ipsandports . "` `ip` = :ip `port` = :port"); $result_checkfordouble = database::pexecute_first($result_checkfordouble_stmt, [ 'ip' =&gt; $ip, 'port' =&gt; $port ]); ($result_checkfordouble &amp;&amp; $result_checkfordouble['id'] != '') { response::standarderror('myipnotdouble', '', true); } $ins_stmt = database::prepare(" insert `" . table_panel_ipsandports . "` set `ip` = :ip, `port` = :port, `listen_statement` = :ls, `namevirtualhost_statement` = :nvhs, `vhostcontainer` = :vhc, `vhostcontainer_servername_statement` = :vhcss, `specialsettings` = :ss, `ssl` = :ssl, `ssl_cert_file` = :ssl_cert, `ssl_key_file` = :ssl_key, `ssl_ca_file` = :ssl_ca, `ssl_cert_chainfile` = :ssl_chain, `default_vhostconf_domain` = :dvhd, `docroot` = :docroot, `ssl_specialsettings` = :ssl_ss, `include_specialsettings` = :incss, `ssl_default_vhostconf_domain` = :ssl_dvhd, `include_default_vhostconf_domain` = :incdvhd; "); $ins_data = [ 'ip' =&gt; $ip, 'port' =&gt; $port, 'ls' =&gt; $listen_statement, 'nvhs' =&gt; $namevirtualhost_statement, 'vhc' =&gt; $vhostcontainer, 'vhcss' =&gt; $vhostcontainer_servername_statement, 'ss' =&gt; $specialsettings, 'ssl' =&gt; $ssl, 'ssl_cert' =&gt; $ssl_cert_file, 'ssl_key' =&gt; $ssl_key_file, 'ssl_ca' =&gt; $ssl_ca_file, 'ssl_chain' =&gt; $ssl_cert_chainfile, 'dvhd' =&gt; $default_vhostconf_domain, 'docroot' =&gt; $docroot, 'ssl_ss' =&gt; $ssl_specialsettings, 'incss' =&gt; $include_specialsettings, 'ssl_dvhd' =&gt; $ssl_default_vhostconf_domain, 'incdvhd' =&gt; $include_default_vhostconf_domain ]; database::pexecute($ins_stmt, $ins_data); $ins_data['id'] = database::lastinsertid(); cronjob::inserttask(taskid::rebuild_vhost); // using nameserver, insert task rebuilds server config cronjob::inserttask(taskid::rebuild_dns); (filter_var($ip, filter_validate_ip, filter_flag_ipv6)) { $ip = '[' . $ip . ']'; } $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] added ip/port '" . $ip . ":" . $port . "'"); // get ip return-array $result = $this-&gt;apicall('ipsandports.get', [ 'id' =&gt; $ins_data['id'] ]); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } /** * return ip/port entry id * * @param int $id * ip-port-id * * @access admin * @return string json-encoded array * @throws exception */ public function get() { ($this-&gt;isadmin() &amp;&amp; ($this-&gt;getuserdetail('change_serversettings') || !empty($this-&gt;getuserdetail('ip')))) { $id = $this-&gt;getparam('id'); (!empty($this-&gt;getuserdetail('ip')) &amp;&amp; $this-&gt;getuserdetail('ip') != -1) { $allowed_ips = json_decode($this-&gt;getuserdetail('ip'), true); (!in_array($id, $allowed_ips)) { throw new exception("you cannot access resource", 405); } } $result_stmt = database::prepare(" select * `" . table_panel_ipsandports . "` `id` = :id "); $result = database::pexecute_first($result_stmt, [ 'id' =&gt; $id ], true, true); ($result) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_info, "[api] get ip " . $result['ip'] . " " . $result['port']); return $this-&gt;response($result); } throw new exception("ip/port id #" . $id . " could found", 404); } throw new exception("not allowed execute given command.", 403); } /** * update ip/port entry given id * * @param int $id * @param string $ip * optional * @param int $port * optional, default 80 * @param bool $listen_statement * optional, default 0 (false) * @param bool $namevirtualhost_statement * optional, default 0 (false) * @param bool $vhostcontainer * optional, default 0 (false) * @param string $specialsettings * optional, default empty * @param bool $vhostcontainer_servername_statement * optional, default 0 (false) * @param string $default_vhostconf_domain * optional, defatul empty * @param string $docroot * optional, default empty (point froxlor) * @param bool $ssl * optional, default 0 (false) * @param string $ssl_cert_file * optional, requires $ssl = 1, default empty * @param string $ssl_key_file * optional, requires $ssl = 1, default empty * @param string $ssl_ca_file * optional, requires $ssl = 1, default empty * @param string $ssl_cert_chainfile * optional, requires $ssl = 1, default empty * @param string $ssl_specialsettings * optional, requires $ssl = 1, default empty * @param bool $include_specialsettings * optional, requires $ssl = 1, whether include non-ssl specialsettings, default false * @param string $ssl_default_vhostconf_domain * optional, requires $ssl = 1, defatul empty * @param bool $include_default_vhostconf_domain * optional, requires $ssl = 1, whether include non-ssl default_vhostconf_domain, default false * * * @access admin * @return string json-encoded array * @throws exception */ public function update() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings')) { $id = $this-&gt;getparam('id'); $result = $this-&gt;apicall('ipsandports.get', [ 'id' =&gt; $id ]); $ip = validate::validate_ip2($this-&gt;getparam('ip', true, $result['ip']), false, 'invalidip', false, true, false, false, true); $port = validate::validate($this-&gt;getparam('port', true, $result['port']), 'port', validate::regex_port, [ 'stringisempty', 'myport' ], [], true); $listen_statement = $this-&gt;getboolparam('listen_statement', true, $result['listen_statement']); $namevirtualhost_statement = $this-&gt;getboolparam('namevirtualhost_statement', true, $result['namevirtualhost_statement']); $vhostcontainer = $this-&gt;getboolparam('vhostcontainer', true, $result['vhostcontainer']); $ss = $this-&gt;getparam('specialsettings', true, $result['specialsettings']); $specialsettings = validate::validate(str_replace("\r\n", "\n", $ss ?? ""), 'specialsettings', validate::regex_conf_text, '', [], true); $vhostcontainer_servername_statement = $this-&gt;getparam('vhostcontainer_servername_statement', true, $result['vhostcontainer_servername_statement']); $dvd = $this-&gt;getparam('default_vhostconf_domain', true, $result['default_vhostconf_domain']); $default_vhostconf_domain = validate::validate(str_replace("\r\n", "\n", $dvd ?? ""), 'default_vhostconf_domain', validate::regex_conf_text, '', [], true); $docroot = validate::validate($this-&gt;getparam('docroot', true, $result['docroot']), 'docroot', validate::regex_dir, '', [], true); ((int)settings::get('system.use_ssl') == 1) { $ssl = (bool)$this-&gt;getboolparam('ssl', true, $result['ssl']); $cert_optional = !($ssl &amp;&amp; empty(settings::get('system.ssl_cert_file'))); $ssl_cert_file = validate::validate($this-&gt;getparam('ssl_cert_file', $cert_optional, $result['ssl_cert_file']), 'ssl_cert_file', '', '', [], true); $ssl_key_file = validate::validate($this-&gt;getparam('ssl_key_file', $cert_optional, $result['ssl_key_file']), 'ssl_key_file', '', '', [], true); $ssl_ca_file = validate::validate($this-&gt;getparam('ssl_ca_file', true, $result['ssl_ca_file']), 'ssl_ca_file', '', '', [], true); $ssl_cert_chainfile = validate::validate($this-&gt;getparam('ssl_cert_chainfile', true, $result['ssl_cert_chainfile']), 'ssl_cert_chainfile', '', '', [], true); $sslss = $this-&gt;getparam('ssl_specialsettings', true, $result['ssl_specialsettings']); $ssl_specialsettings = validate::validate(str_replace("\r\n", "\n", $sslss ?? ""), 'ssl_specialsettings', validate::regex_conf_text, '', [], true); $include_specialsettings = $this-&gt;getboolparam('include_specialsettings', true, $result['include_specialsettings']); $ssldvd = $this-&gt;getparam('ssl_default_vhostconf_domain', true, $result['ssl_default_vhostconf_domain']); $ssl_default_vhostconf_domain = validate::validate(str_replace("\r\n", "\n", $ssldvd ?? ""), 'ssl_default_vhostconf_domain', validate::regex_conf_text, '', [], true); $include_default_vhostconf_domain = $this-&gt;getboolparam('include_default_vhostconf_domain', true, $result['include_default_vhostconf_domain']); } else { $ssl = 0; $ssl_cert_file = ''; $ssl_key_file = ''; $ssl_ca_file = ''; $ssl_cert_chainfile = ''; $ssl_specialsettings = ''; $include_specialsettings = 0; $ssl_default_vhostconf_domain = ''; $include_default_vhostconf_domain = 0; } $result_checkfordouble_stmt = database::prepare(" select `id` `" . table_panel_ipsandports . "` `ip` = :ip `port` = :port "); $result_checkfordouble = database::pexecute_first($result_checkfordouble_stmt, [ 'ip' =&gt; $ip, 'port' =&gt; $port ]); $result_sameipotherport_stmt = database::prepare(" select `id` `" . table_panel_ipsandports . "` `ip` = :ip `id` &lt;&gt; :id "); $result_sameipotherport = database::pexecute_first($result_sameipotherport_stmt, [ 'ip' =&gt; $ip, 'id' =&gt; $id ], true, true); ($listen_statement != '1') { $listen_statement = '0'; } ($namevirtualhost_statement != '1') { $namevirtualhost_statement = '0'; } ($vhostcontainer != '1') { $vhostcontainer = '0'; } ($vhostcontainer_servername_statement != '1') { $vhostcontainer_servername_statement = '0'; } ($ssl != '1') { $ssl = '0'; } ($ssl_cert_file != '') { $ssl_cert_file = filedir::makecorrectfile($ssl_cert_file); } ($ssl_key_file != '') { $ssl_key_file = filedir::makecorrectfile($ssl_key_file); } ($ssl_ca_file != '') { $ssl_ca_file = filedir::makecorrectfile($ssl_ca_file); } ($ssl_cert_chainfile != '') { $ssl_cert_chainfile = filedir::makecorrectfile($ssl_cert_chainfile); } (strlen(trim($docroot)) &gt; 0) { $docroot = filedir::makecorrectdir($docroot); } else { $docroot = ''; } // always use compressed ipv6 format $ip = inet_ntop(inet_pton($ip)); ($result['ip'] != $ip &amp;&amp; $result['ip'] == settings::get('system.ipaddress') &amp;&amp; $result_sameipotherport == false) { response::standarderror('cantchangesystemip', '', true); } elseif ($result_checkfordouble &amp;&amp; $result_checkfordouble['id'] != '' &amp;&amp; $result_checkfordouble['id'] != $id) { response::standarderror('myipnotdouble', '', true); } else { $upd_stmt = database::prepare(" update `" . table_panel_ipsandports . "` set `ip` = :ip, `port` = :port, `listen_statement` = :ls, `namevirtualhost_statement` = :nvhs, `vhostcontainer` = :vhc, `vhostcontainer_servername_statement` = :vhcss, `specialsettings` = :ss, `ssl` = :ssl, `ssl_cert_file` = :ssl_cert, `ssl_key_file` = :ssl_key, `ssl_ca_file` = :ssl_ca, `ssl_cert_chainfile` = :ssl_chain, `default_vhostconf_domain` = :dvhd, `docroot` = :docroot, `ssl_specialsettings` = :ssl_ss, `include_specialsettings` = :incss, `ssl_default_vhostconf_domain` = :ssl_dvhd, `include_default_vhostconf_domain` = :incdvhd `id` = :id; "); $upd_data = [ 'ip' =&gt; $ip, 'port' =&gt; $port, 'ls' =&gt; $listen_statement, 'nvhs' =&gt; $namevirtualhost_statement, 'vhc' =&gt; $vhostcontainer, 'vhcss' =&gt; $vhostcontainer_servername_statement, 'ss' =&gt; $specialsettings, 'ssl' =&gt; $ssl, 'ssl_cert' =&gt; $ssl_cert_file, 'ssl_key' =&gt; $ssl_key_file, 'ssl_ca' =&gt; $ssl_ca_file, 'ssl_chain' =&gt; $ssl_cert_chainfile, 'dvhd' =&gt; $default_vhostconf_domain, 'docroot' =&gt; $docroot, 'ssl_ss' =&gt; $ssl_specialsettings, 'incss' =&gt; $include_specialsettings, 'ssl_dvhd' =&gt; $ssl_default_vhostconf_domain, 'incdvhd' =&gt; $include_default_vhostconf_domain, 'id' =&gt; $id ]; database::pexecute($upd_stmt, $upd_data); cronjob::inserttask(taskid::rebuild_vhost); // using nameserver, insert task rebuilds server config cronjob::inserttask(taskid::rebuild_dns); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] changed ip/port '" . $result['ip'] . ":" . $result['port'] . "' '" . $ip . ":" . $port . "'"); $result = $this-&gt;apicall('ipsandports.get', [ 'id' =&gt; $result['id'] ]); return $this-&gt;response($result); } } throw new exception("not allowed execute given command.", 403); } /** * delete ip/port entry id * * @param int $id * ip-port-id * * @access admin * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings')) { $id = $this-&gt;getparam('id'); $result = $this-&gt;apicall('ipsandports.get', [ 'id' =&gt; $id ]); $result_checkdomain_stmt = database::prepare(" select `id_domain` `" . table_domaintoip . "` `id_ipandports` = :id "); $result_checkdomain = database::pexecute_first($result_checkdomain_stmt, [ 'id' =&gt; $id ], true, true); (empty($result_checkdomain)) { (!in_array($result['id'], explode(',', settings::get('system.defaultip'))) &amp;&amp; !in_array($result['id'], explode(',', settings::get('system.defaultsslip')))) { // check whether ip different port // case ip-address system.ipaddress therefore // one - alternative $result_sameipotherport_stmt = database::prepare(" select `id` `" . table_panel_ipsandports . "` `ip` = :ip `id` &lt;&gt; :id"); $result_sameipotherport = database::pexecute_first($result_sameipotherport_stmt, [ 'id' =&gt; $id, 'ip' =&gt; $result['ip'] ]); (($result['ip'] != settings::get('system.ipaddress')) || ($result['ip'] == settings::get('system.ipaddress') &amp;&amp; $result_sameipotherport != false)) { $del_stmt = database::prepare(" delete `" . table_panel_ipsandports . "` `id` = :id "); database::pexecute($del_stmt, [ 'id' =&gt; $id ], true, true); // also, remove connections domains (multi-stack) $del_stmt = database::prepare(" delete `" . table_domaintoip . "` `id_ipandports` = :id "); database::pexecute($del_stmt, [ 'id' =&gt; $id ], true, true); cronjob::inserttask(taskid::rebuild_vhost); // using nameserver, insert task rebuilds server config cronjob::inserttask(taskid::rebuild_dns); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] deleted ip/port '" . $result['ip'] . ":" . $result['port'] . "'"); return $this-&gt;response($result); } else { response::standarderror('cantdeletesystemip', '', true); } } else { response::standarderror('cantdeletedefaultip', '', true); } } else { response::standarderror('ipstillhasdomains', '', true); } } throw new exception("not allowed execute given command.", 403); } }</file><file name="lib/Froxlor/Api/Commands/Domains.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\domain\domain; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\idna\idnawrapper; use froxlor\phphelper; use froxlor\settings; use froxlor\system\cronjob; use froxlor\ui\response; use froxlor\user; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class domains extends apicommand implements resourceentity { /** * lists domain entries * * @param bool $with_ips * optional, default true * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin * @return string json-encoded array count|list * @throws exception */ public function listing() { ($this-&gt;isadmin()) { $with_ips = $this-&gt;getparam('with_ips', true, true); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] list domains"); $query_fields = []; $result_stmt = database::prepare(" select `d`.*, `c`.`loginname`, `c`.`deactivated` `customer_deactivated`, `c`.`name`, `c`.`firstname`, `c`.`company`, `c`.`standardsubdomain`, `c`.`adminid` customeradmin, `ad`.`id` `aliasdomainid`, `ad`.`domain` `aliasdomain` `" . table_panel_domains . "` `d` left join `" . table_panel_customers . "` `c` using(`customerid`) left join `" . table_panel_domains . "` `ad` `d`.`aliasdomain`=`ad`.`id` `d`.`parentdomainid`='0' " . ($this-&gt;getuserdetail('customers_see_all') ? '' : " `d`.`adminid` = :adminid ") . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); $params = []; ($this-&gt;getuserdetail('customers_see_all') == '0') { $params['adminid'] = $this-&gt;getuserdetail('adminid'); } $params = array_merge($params, $query_fields); database::pexecute($result_stmt, $params, true, true); $result = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $row['ipsandports'] = []; ($with_ips) { $row['ipsandports'] = $this-&gt;getipsfordomain($row['id']); } $row['domain_hascert'] = $this-&gt;gethascertvaluefordomain((int)$row['id'], (int)$row['parentdomainid']); $result[] = $row; } return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } throw new exception("not allowed execute given command.", 403); } /** * get ips connected given domain array * * @param number $domain_id * @param bool $ssl_only * optional, return ssl enabled ips, default false * @return array */ private function getipsfordomain($domain_id = 0, $ssl_only = false) { $resultips_stmt = database::prepare(" select `ips`.* `" . table_domaintoip . "` `dti`, `" . table_panel_ipsandports . "` `ips` `dti`.`id_ipandports` = `ips`.`id` `dti`.`id_domain` = :domainid " . ($ssl_only ? " `ips`.`ssl` = '1'" : "")); database::pexecute($resultips_stmt, [ 'domainid' =&gt; $domain_id ]); $ipandports = []; ($rowip = $resultips_stmt-&gt;fetch(pdo::fetch_assoc)) { (filter_var($rowip['ip'], filter_validate_ip, filter_flag_ipv6)) { $rowip['is_ipv6'] = true; } $ipandports[] = $rowip; } return $ipandports; } /** * returns total number accessible domains * * @access admin * @return string json-encoded array count|list * @throws exception */ public function listingcount() { ($this-&gt;isadmin()) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] list domains"); $result_stmt = database::prepare(" select count(*) num_domains `" . table_panel_domains . "` `d` left join `" . table_panel_customers . "` `c` using(`customerid`) left join `" . table_panel_domains . "` `ad` `d`.`aliasdomain`=`ad`.`id` `d`.`parentdomainid`='0' " . ($this-&gt;getuserdetail('customers_see_all') ? '' : " `d`.`adminid` = :adminid ")); $params = []; ($this-&gt;getuserdetail('customers_see_all') == '0') { $params['adminid'] = $this-&gt;getuserdetail('adminid'); } $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { return $this-&gt;response($result['num_domains']); } } throw new exception("not allowed execute given command.", 403); } /** * add new domain entry * * @param string $domain * domain-name * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param int $adminid * optional, default calling admin's id * @param array $ipandport * optional list ip/ports assign domain, default system-default-ips * @param int $subcanemaildomain * optional, allow subdomains domain email domains, 1 = choosable (default no), 2 = choosable * (default yes), 3 = always, default 0 (never) * @param bool $isemaildomain * optional, allow email usage domain, default 0 (false) * @param bool $email_only * optional, restrict domain email usage, default 0 (false) * @param int $selectserveralias * optional, 0 = wildcard, 1 = www-alias, 2 = none, default [system.domaindefaultalias] * @param bool $speciallogfile * optional, whether create exclusive web-logfile domain, default 0 (false) * @param int $alias * optional, domain-id domain new domain alias of, default 0 (none) * @param string $registration_date * optional, date domain registration form yyyy-mm-dd, default empty (none) * @param string $termination_date * optional, date domain termination form yyyy-mm-dd, default empty (none) * @param bool $caneditdomain * optional, whether allow customer edit domain settings, default 0 (false) * @param bool $isbinddomain * optional, whether generate dns-zone (only nameserver activated), default 0 (false) * @param string $zonefile * optional, custom dns zone filename (only nameserver activated), default empty (auto-generated) * @param bool $dkim * optional, whether domain use dkim antispam activated, default 0 (false) * @param string $specialsettings * optional, custom webserver vhost-content added generated vhost, default empty * @param string $ssl_specialsettings * optional, custom webserver vhost-content added generated ssl-vhost, default empty * @param bool $include_specialsettings * optional, whether include non-ssl specialsettings generated ssl-vhost, default false * @param bool $notryfiles * optional, [nginx only] generate default try-files directive, default 0 (false) * @param bool $writeaccesslog * optional, enable writing access-log file domain, default 1 (true) * @param bool $writeerrorlog * optional, enable writing error-log file domain, default 1 (true) * @param string $documentroot * optional, specify homedir domain specifying directory (relative customer-docroot), * aware, path starts / considered full path, relative customer-docroot. also * specifying url possible (redirect), default empty (autogenerated) * @param bool $phpenabled * optional, whether php enabled domain, default 0 (false) * @param bool $openbasedir * optional, whether activate openbasedir restriction domain, default 0 (false) * @param int $openbasedir_path * optional, either 0 domains-docroot, 1 customers-homedir 2 parent-directory domains-docroot * @param int $phpsettingid * optional, specify php-configuration used id, default 1 (system-default) * @param int $mod_fcgid_starter * optional number fcgid-starters fcgid used, default -1 * @param int $mod_fcgid_maxrequests * optional number fcgid-maxrequests fcgid used, default -1 * @param bool $ssl_redirect * optional, whether generate https-redirect not, default false; requires ssl enabled * @param bool $letsencrypt * optional, whether generate let's encrypt certificate domain, default false; requires * ssl enabled * @param array $ssl_ipandport * optional, list ssl-enabled ip/port id's assign domain, default empty * @param bool $dont_use_default_ssl_ipandport_if_empty * optional, set systems default ssl ip addresses none given via $ssl_ipandport * parameter * @param bool $sslenabled * optional, whether ssl enabled domain, regardless assigned ssl-ips, default * 1 (true) * @param bool $http2 * optional, whether enable http/2 domain (requires enabled settings), default * 0 (false) * @param int $hsts_maxage * optional max-age value hsts header * @param bool $hsts_sub * optional whether add subdomains hsts header * @param bool $hsts_preload * optional whether preload hsts header value * @param bool $ocsp_stapling * optional whether enable ocsp-stapling domain. default 0 (false), requires ssl * @param bool $honorcipherorder * optional whether honor (server) cipher order domain. default 0 (false), requires ssl * @param bool $sessiontickets * optional whether enable disable tls sessiontickets (rfc 5077) domain. default 1 * (true), requires ssl * @param bool $override_tls * optional whether override system-tls settings like protocol, ssl-ciphers applicable * tls-1.3 ciphers, requires change_serversettings flag admin, default false * @param array $ssl_protocols * optional list allowed/used ssl/tls protocols, see system.ssl_protocols setting, used/required * $override_tls true, default empty system.ssl_protocols setting $override_tls true * @param string $ssl_cipher_list * optional list allowed/used ssl/tls ciphers, see system.ssl_cipher_list setting, used/required * $override_tls true, default empty system.ssl_cipher_list setting $override_tls true * @param string $tlsv13_cipher_list * optional list allowed/used tls-1.3 specific ciphers, see system.tlsv13_cipher_list setting, * used/required $override_tls true, default empty system.tlsv13_cipher_list setting * $override_tls true * @param string $description * optional custom description (currently used/shown frontend), default empty * @param bool $is_stdsubdomain (internally) * optional whether standard subdomain customer added usage decreased * @access admin * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin()) { $is_stdsubdomain = $this-&gt;isinternal() ? $this-&gt;getboolparam('is_stdsubdomain', true, 0) : false; ($is_stdsubdomain || $this-&gt;getuserdetail('domains_used') &lt; $this-&gt;getuserdetail('domains') || $this-&gt;getuserdetail('domains') == '-1') { // parameters $p_domain = $this-&gt;getparam('domain'); // optional parameters $p_ipandports = $this-&gt;getparam('ipandport', true, explode(',', settings::get('system.defaultip'))); $adminid = intval($this-&gt;getparam('adminid', true, $this-&gt;getuserdetail('adminid'))); $subcanemaildomain = $this-&gt;getparam('subcanemaildomain', true, 0); $isemaildomain = $this-&gt;getboolparam('isemaildomain', true, 0); $email_only = $this-&gt;getboolparam('email_only', true, 0); $serveraliasoption = $this-&gt;getparam('selectserveralias', true, settings::get('system.domaindefaultalias')); $speciallogfile = $this-&gt;getboolparam('speciallogfile', true, 0); $aliasdomain = intval($this-&gt;getparam('alias', true, 0)); $registration_date = $this-&gt;getparam('registration_date', true, ''); $termination_date = $this-&gt;getparam('termination_date', true, ''); $caneditdomain = $this-&gt;getboolparam('caneditdomain', true, 0); $isbinddomain = $this-&gt;getboolparam('isbinddomain', true, 0); $zonefile = $this-&gt;getparam('zonefile', true, ''); $dkim = $this-&gt;getboolparam('dkim', true, 0); $specialsettings = $this-&gt;getparam('specialsettings', true, ''); $ssl_specialsettings = $this-&gt;getparam('ssl_specialsettings', true, ''); $include_specialsettings = $this-&gt;getboolparam('include_specialsettings', true, 0); $notryfiles = $this-&gt;getboolparam('notryfiles', true, 0); $writeaccesslog = $this-&gt;getboolparam('writeaccesslog', true, 1); $writeerrorlog = $this-&gt;getboolparam('writeerrorlog', true, 1); $documentroot = $this-&gt;getparam('documentroot', true, ''); $phpenabled = $this-&gt;getboolparam('phpenabled', true, 0); $openbasedir = $this-&gt;getboolparam('openbasedir', true, 0); $openbasedir_path = $this-&gt;getparam('openbasedir_path', true, 0); $phpsettingid = $this-&gt;getparam('phpsettingid', true, 1); $mod_fcgid_starter = $this-&gt;getparam('mod_fcgid_starter', true, -1); $mod_fcgid_maxrequests = $this-&gt;getparam('mod_fcgid_maxrequests', true, -1); $ssl_redirect = $this-&gt;getboolparam('ssl_redirect', true, 0); $letsencrypt = $this-&gt;getboolparam('letsencrypt', true, 0); $sslenabled = $this-&gt;getboolparam('sslenabled', true, 1); $dont_use_default_ssl_ipandport_if_empty = $this-&gt;getboolparam('dont_use_default_ssl_ipandport_if_empty', true, 0); $p_ssl_ipandports = $this-&gt;getparam('ssl_ipandport', true, $dont_use_default_ssl_ipandport_if_empty ? [] : explode(',', settings::get('system.defaultsslip'))); $http2 = $this-&gt;getboolparam('http2', true, 0); $hsts_maxage = $this-&gt;getparam('hsts_maxage', true, 0); $hsts_sub = $this-&gt;getboolparam('hsts_sub', true, 0); $hsts_preload = $this-&gt;getboolparam('hsts_preload', true, 0); $ocsp_stapling = $this-&gt;getboolparam('ocsp_stapling', true, 0); $honorcipherorder = $this-&gt;getboolparam('honorcipherorder', true, 0); $sessiontickets = $this-&gt;getboolparam('sessiontickets', true, 1); $override_tls = $this-&gt;getboolparam('override_tls', true, 0); $p_ssl_protocols = []; $ssl_cipher_list = ""; $tlsv13_cipher_list = ""; ($this-&gt;getuserdetail('change_serversettings') == '1') { ($override_tls) { $p_ssl_protocols = $this-&gt;getparam('ssl_protocols', true, explode(',', settings::get('system.ssl_protocols'))); $ssl_cipher_list = $this-&gt;getparam('ssl_cipher_list', true, settings::get('system.ssl_cipher_list')); $tlsv13_cipher_list = $this-&gt;getparam('tlsv13_cipher_list', true, settings::get('system.tlsv13_cipher_list')); } } $description = $this-&gt;getparam('description', true, ''); // validation $p_domain = strtolower($p_domain); ($p_domain == strtolower(settings::get('system.hostname'))) { response::standarderror('admin_domain_emailsystemhostname', '', true); } (substr($p_domain, 0, 4) == 'xn--') { response::standarderror('domain_nopunycode', '', true); } elseif (validate::validate_ip2($p_domain, true, '', true, true)) { response::standarderror('domain_noipaddress', '', true); } $idna_convert = new idnawrapper(); $domain = $idna_convert-&gt;encode(preg_replace([ '/\:(\d)+$/', '/^https?\:\/\//' ], '', validate::validate($p_domain, 'domain'))); // check whether domain validation enabled if, validate domain (settings::get('system.validate_domain') &amp;&amp; !validate::validatedomain($domain)) { response::standarderror([ 'stringiswrong', 'mydomain' ], '', true); } $customer = $this-&gt;getcustomerdata(); $customerid = $customer['customerid']; ($this-&gt;getuserdetail('customers_see_all') == '1' &amp;&amp; $adminid != $this-&gt;getuserdetail('adminid')) { $admin_stmt = database::prepare(" select * `" . table_panel_admins . "` `adminid` = :adminid (`domains_used` &lt; `domains` `domains` = '-1')"); $admin = database::pexecute_first($admin_stmt, [ 'adminid' =&gt; $adminid ], true, true); (empty($admin)) { response::dynamicerror("selected admin cannot domains could found"); } unset($admin); } // set default path admin/reseller "change_serversettings == false" still // need respect documentroot_use_default_value - setting $path_suffix = ''; (settings::get('system.documentroot_use_default_value') == 1) { $path_suffix = '/' . $domain; } $_documentroot = filedir::makecorrectdir($customer['documentroot'] . $path_suffix); $documentroot = validate::validate($documentroot, 'documentroot', validate::regex_dir, '', [], true); // path empty 'use domain name default value documentroot path' enabled settings, // set default path subdomain domain name (!empty($documentroot)) { (substr($documentroot, 0, 1) != '/' &amp;&amp; !preg_match('/^https?\:\/\//', $documentroot)) { $documentroot = $_documentroot . '/' . $documentroot; } elseif (substr($documentroot, 0, 1) == '/' &amp;&amp; $this-&gt;getuserdetail('change_serversettings') != '1') { response::standarderror('pathmustberelative', '', true); } } else { $documentroot = $_documentroot; } (!is_null($registration_date)) { $registration_date = validate::validate($registration_date, 'registration_date', validate::regex_yyyy_mm_dd, '', [ '0000-00-00', '0', '' ], true); } ($registration_date == '0000-00-00' || empty($registration_date)) { $registration_date = null; } (!is_null($termination_date)) { $termination_date = validate::validate($termination_date, 'termination_date', validate::regex_yyyy_mm_dd, '', [ '0000-00-00', '0', '' ], true); } ($termination_date == '0000-00-00' || empty($termination_date)) { $termination_date = null; } ($this-&gt;getuserdetail('change_serversettings') == '1') { (settings::get('system.bind_enable') == '1') { $zonefile = validate::validate($zonefile, 'zonefile', '', '', [], true); } else { $isbinddomain = 0; $zonefile = ''; } $specialsettings = validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', validate::regex_conf_text, '', [], true); $ssl_protocols = []; (!empty($p_ssl_protocols) &amp;&amp; is_numeric($p_ssl_protocols)) { $p_ssl_protocols = [ $p_ssl_protocols ]; } (!empty($p_ssl_protocols) &amp;&amp; !is_array($p_ssl_protocols)) { $p_ssl_protocols = json_decode($p_ssl_protocols, true); } (!empty($p_ssl_protocols) &amp;&amp; is_array($p_ssl_protocols)) { $protocols_available = [ 'tlsv1', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3' ]; foreach ($p_ssl_protocols $ssl_protocol) { (!in_array(trim($ssl_protocol), $protocols_available)) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_debug, "[api] unknown ssl protocol '" . trim($ssl_protocol) . "'"); continue; } $ssl_protocols[] = $ssl_protocol; } } (empty($ssl_protocols)) { $override_tls = '0'; } } else { $isbinddomain = '0'; (settings::get('system.bind_enable') == '1') { $isbinddomain = '1'; } $caneditdomain = '1'; $zonefile = ''; $specialsettings = ''; $ssl_specialsettings = ''; $include_specialsettings = 0; $notryfiles = '0'; $writeaccesslog = '1'; $writeerrorlog = '1'; $override_tls = '0'; $ssl_protocols = []; } ($this-&gt;getuserdetail('caneditphpsettings') == '1' || $this-&gt;getuserdetail('change_serversettings') == '1') { ((int)settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1) { $phpsettingid_check_stmt = database::prepare(" select * `" . table_panel_phpconfigs . "` `id` = :phpsettingid"); $phpsettingid_check = database::pexecute_first($phpsettingid_check_stmt, [ 'phpsettingid' =&gt; $phpsettingid ], true, true); (!isset($phpsettingid_check['id']) || $phpsettingid_check['id'] == '0' || $phpsettingid_check['id'] != $phpsettingid) { response::standarderror('phpsettingidwrong', '', true); } ((int)settings::get('system.mod_fcgid') == 1) { $mod_fcgid_starter = validate::validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', [ '-1', '' ], true); $mod_fcgid_maxrequests = validate::validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', [ '-1', '' ], true); } else { $mod_fcgid_starter = '-1'; $mod_fcgid_maxrequests = '-1'; } } else { ((int)settings::get('phpfpm.enabled') == 1) { $phpsettingid = settings::get('phpfpm.defaultini'); } else { $phpsettingid = settings::get('system.mod_fcgid_defaultini'); } $mod_fcgid_starter = '-1'; $mod_fcgid_maxrequests = '-1'; } } else { // set default whether customer php enabled $phpenabled = $customer['phpenabled']; $openbasedir = '1'; ((int)settings::get('phpfpm.enabled') == 1) { $phpsettingid = settings::get('phpfpm.defaultini'); } else { $phpsettingid = settings::get('system.mod_fcgid_defaultini'); } $mod_fcgid_starter = '-1'; $mod_fcgid_maxrequests = '-1'; } ($openbasedir_path &gt; 2 &amp;&amp; $openbasedir_path &lt; 0) { $openbasedir_path = 0; } // check non-ssl ip $ipandports = $this-&gt;validateipaddresses($p_ipandports); // check ssl ip $ssl_ipandports = []; (settings::get('system.use_ssl') == "1" &amp;&amp; !empty($p_ssl_ipandports)) { $ssl_ipandports = $this-&gt;validateipaddresses($p_ssl_ipandports, true); ($this-&gt;getuserdetail('change_serversettings') == '1') { $ssl_specialsettings = validate::validate(str_replace("\r\n", "\n", $ssl_specialsettings), 'ssl_specialsettings', '/^[^\0]*$/', '', [], true); } } (settings::get('system.use_ssl') == "1" &amp;&amp; $sslenabled == 1 &amp;&amp; empty($ssl_ipandports)) { // customer standard-subdomain, simply ignore disable ssl-related settings (see if-statement below) (!$is_stdsubdomain) { // enabled ssl domain ssl ip/port selected response::standarderror('nosslippportgiven', '', true); } } (settings::get('system.use_ssl') == "0" || empty($ssl_ipandports)) { $ssl_redirect = 0; $letsencrypt = 0; $http2 = 0; // need json_encode // ssl disabled ssl-ip/port exists $ssl_ipandports[] = -1; // hsts $hsts_maxage = 0; $hsts_sub = 0; $hsts_preload = 0; // ocsp stapling $ocsp_stapling = 0; // vhost container settings $ssl_specialsettings = ''; $include_specialsettings = 0; } // validate dns lets encrypt enabled check whether use ($letsencrypt == '1' &amp;&amp; settings::get('system.le_domain_dnscheck') == '1') { $domain_ips = phphelper::gethostbynamel6($domain, true, settings::get('system.le_domain_dnscheck_resolver')); $selected_ips = $this-&gt;getipsfromidarray($ssl_ipandports); ($domain_ips == false || count(array_intersect($selected_ips, $domain_ips)) &lt;= 0) { response::standarderror('invaliddnsforletsencrypt', '', true); } } // can't enable let's encrypt wildcard-domains ($serveraliasoption == '0' &amp;&amp; $letsencrypt == '1') { response::standarderror('nowildcardwithletsencrypt', '', true); } // temporarily deactivate ssl_redirect let's encrypt certificate generated ($ssl_redirect &gt; 0 &amp;&amp; $letsencrypt == 1) { $ssl_redirect = 2; } (!preg_match('/^https?\:\/\//', $documentroot)) { (strstr($documentroot, ":") !== false) { response::standarderror('pathmaynotcontaincolon', '', true); } else { $documentroot = filedir::makecorrectdir($documentroot); } } $domain_check_stmt = database::prepare(" select `id`, `domain` `" . table_panel_domains . "` `domain` = :domain"); $domain_check = database::pexecute_first($domain_check_stmt, [ 'domain' =&gt; strtolower($domain) ], true, true); $aliasdomain_check = [ 'id' =&gt; 0 ]; ($aliasdomain != 0) { // overwrite given ipandports "main" domain $ipandports = []; $ssl_ipandports = []; $origipresult_stmt = database::prepare(" select `id_ipandports` `" . table_domaintoip . "` `id_domain` = :id"); database::pexecute($origipresult_stmt, [ 'id' =&gt; $aliasdomain ], true, true); $ipdata_stmt = database::prepare("select * `" . table_panel_ipsandports . "` `id` = :ipid"); ($origip = $origipresult_stmt-&gt;fetch(pdo::fetch_assoc)) { $_origip_tmp = database::pexecute_first($ipdata_stmt, [ 'ipid' =&gt; $origip['id_ipandports'] ], true, true); ($_origip_tmp['ssl'] == 0) { $ipandports[] = $origip['id_ipandports']; } else { $ssl_ipandports[] = $origip['id_ipandports']; } } (count($ssl_ipandports) == 0) { // need json_encode // ssl disabled ssl-ip/port exists $ssl_ipandports[] = -1; } $aliasdomain_check_stmt = database::prepare(" select `d`.`id` `" . table_panel_domains . "` `d`, `" . table_panel_customers . "` `c` `d`.`customerid` = :customerid `d`.`aliasdomain` null `d`.`id` &lt;&gt; `c`.`standardsubdomain` `c`.`customerid` = :customerid `d`.`id` = :aliasdomainid"); $alias_params = [ 'customerid' =&gt; $customerid, 'aliasdomainid' =&gt; $aliasdomain ]; $aliasdomain_check = database::pexecute_first($aliasdomain_check_stmt, $alias_params, true, true); } (count($ipandports) == 0) { response::standarderror('noipportgiven', '', true); } ($email_only == '1') { $isemaildomain = '1'; } else { $email_only = '0'; } ($subcanemaildomain != '1' &amp;&amp; $subcanemaildomain != '2' &amp;&amp; $subcanemaildomain != '3') { $subcanemaildomain = '0'; } ($serveraliasoption != '1' &amp;&amp; $serveraliasoption != '2') { $serveraliasoption = '0'; } $idna_convert = new idnawrapper(); ($domain == '') { response::standarderror([ 'stringisempty', 'mydomain' ], '', true); } elseif ($documentroot == '') { response::standarderror([ 'stringisempty', 'mydocumentroot' ], '', true); } elseif ($customerid == 0) { response::standarderror('adduserfirst', '', true); } elseif ($domain_check &amp;&amp; strtolower($domain_check['domain']) == strtolower($domain)) { response::standarderror('domainalreadyexists', $idna_convert-&gt;decode($domain), true); } elseif ($aliasdomain_check &amp;&amp; $aliasdomain_check['id'] != $aliasdomain) { response::standarderror('domainisaliasorothercustomer', '', true); } else { $wwwserveralias = ($serveraliasoption == '1') ? '1' : '0'; $iswildcarddomain = ($serveraliasoption == '0') ? '1' : '0'; $ins_data = [ 'domain' =&gt; $domain, 'domain_ace' =&gt; $idna_convert-&gt;decode($domain), 'customerid' =&gt; $customerid, 'adminid' =&gt; $adminid, 'documentroot' =&gt; $documentroot, 'aliasdomain' =&gt; ($aliasdomain != 0 ? $aliasdomain : null), 'zonefile' =&gt; $zonefile, 'dkim' =&gt; $dkim, 'wwwserveralias' =&gt; $wwwserveralias, 'iswildcarddomain' =&gt; $iswildcarddomain, 'isbinddomain' =&gt; $isbinddomain, 'isemaildomain' =&gt; $isemaildomain, 'email_only' =&gt; $email_only, 'subcanemaildomain' =&gt; $subcanemaildomain, 'caneditdomain' =&gt; $caneditdomain, 'phpenabled' =&gt; $phpenabled, 'openbasedir' =&gt; $openbasedir, 'openbasedir_path' =&gt; $openbasedir_path, 'speciallogfile' =&gt; $speciallogfile, 'specialsettings' =&gt; $specialsettings, 'ssl_specialsettings' =&gt; $ssl_specialsettings, 'include_specialsettings' =&gt; $include_specialsettings, 'notryfiles' =&gt; $notryfiles, 'writeaccesslog' =&gt; $writeaccesslog, 'writeerrorlog' =&gt; $writeerrorlog, 'ssl_redirect' =&gt; $ssl_redirect, 'add_date' =&gt; time(), 'registration_date' =&gt; $registration_date, 'termination_date' =&gt; $termination_date, 'phpsettingid' =&gt; $phpsettingid, 'mod_fcgid_starter' =&gt; $mod_fcgid_starter, 'mod_fcgid_maxrequests' =&gt; $mod_fcgid_maxrequests, 'letsencrypt' =&gt; $letsencrypt, 'http2' =&gt; $http2, 'hsts' =&gt; $hsts_maxage, 'hsts_sub' =&gt; $hsts_sub, 'hsts_preload' =&gt; $hsts_preload, 'ocsp_stapling' =&gt; $ocsp_stapling, 'override_tls' =&gt; $override_tls, 'ssl_protocols' =&gt; implode(",", $ssl_protocols), 'ssl_cipher_list' =&gt; $ssl_cipher_list, 'tlsv13_cipher_list' =&gt; $tlsv13_cipher_list, 'sslenabled' =&gt; $sslenabled, 'honorcipherorder' =&gt; $honorcipherorder, 'sessiontickets' =&gt; $sessiontickets, 'description' =&gt; $description ]; $ins_stmt = database::prepare(" insert `" . table_panel_domains . "` set `domain` = :domain, `domain_ace` = :domain_ace, `customerid` = :customerid, `adminid` = :adminid, `documentroot` = :documentroot, `aliasdomain` = :aliasdomain, `zonefile` = :zonefile, `dkim` = :dkim, `dkim_id` = '0', `dkim_privkey` = '', `dkim_pubkey` = '', `wwwserveralias` = :wwwserveralias, `iswildcarddomain` = :iswildcarddomain, `isbinddomain` = :isbinddomain, `isemaildomain` = :isemaildomain, `email_only` = :email_only, `subcanemaildomain` = :subcanemaildomain, `caneditdomain` = :caneditdomain, `phpenabled` = :phpenabled, `openbasedir` = :openbasedir, `openbasedir_path` = :openbasedir_path, `speciallogfile` = :speciallogfile, `specialsettings` = :specialsettings, `ssl_specialsettings` = :ssl_specialsettings, `include_specialsettings` = :include_specialsettings, `notryfiles` = :notryfiles, `writeaccesslog` = :writeaccesslog, `writeerrorlog` = :writeerrorlog, `ssl_redirect` = :ssl_redirect, `add_date` = :add_date, `registration_date` = :registration_date, `termination_date` = :termination_date, `phpsettingid` = :phpsettingid, `mod_fcgid_starter` = :mod_fcgid_starter, `mod_fcgid_maxrequests` = :mod_fcgid_maxrequests, `letsencrypt` = :letsencrypt, `http2` = :http2, `hsts` = :hsts, `hsts_sub` = :hsts_sub, `hsts_preload` = :hsts_preload, `ocsp_stapling` = :ocsp_stapling, `override_tls` = :override_tls, `ssl_protocols` = :ssl_protocols, `ssl_cipher_list` = :ssl_cipher_list, `tlsv13_cipher_list` = :tlsv13_cipher_list, `ssl_enabled` = :sslenabled, `ssl_honorcipherorder` = :honorcipherorder, `ssl_sessiontickets` = :sessiontickets, `description` = :description "); database::pexecute($ins_stmt, $ins_data, true, true); $domainid = database::lastinsertid(); $ins_data['id'] = $domainid; unset($ins_data); (!$is_stdsubdomain) { $upd_stmt = database::prepare(" update `" . table_panel_admins . "` set `domains_used` = `domains_used` + 1 `adminid` = :adminid "); database::pexecute($upd_stmt, [ 'adminid' =&gt; $adminid ], true, true); } $ins_stmt = database::prepare(" insert `" . table_domaintoip . "` set `id_domain` = :domainid, `id_ipandports` = :ipandportsid "); foreach ($ipandports $ipportid) { $ins_data = [ 'domainid' =&gt; $domainid, 'ipandportsid' =&gt; $ipportid ]; database::pexecute($ins_stmt, $ins_data, true, true); } foreach ($ssl_ipandports $ssl_ipportid) { ($ssl_ipportid &gt; 0) { $ins_data = [ 'domainid' =&gt; $domainid, 'ipandportsid' =&gt; $ssl_ipportid ]; database::pexecute($ins_stmt, $ins_data, true, true); } } domain::triggerletsencryptcsrforaliasdestinationdomain($aliasdomain, $this-&gt;logger()); cronjob::inserttask(taskid::rebuild_vhost); // using nameserver, insert task rebuilds server config cronjob::inserttask(taskid::rebuild_dns); ($dkim == '1') { cronjob::inserttask(taskid::rebuild_rspamd); } $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] added domain '" . $domain . "'"); $result = $this-&gt;apicall('domains.get', [ 'domainname' =&gt; $domain ]); return $this-&gt;response($result); } } throw new exception("no resources available", 406); } throw new exception("not allowed execute given command.", 403); } /** * return domain entry either id domainname * * @param int $id * optional, domain-id * @param string $domainname * optional, domainname * @param bool $with_ips * optional, default true * @param bool $no_std_subdomain * optional, default false * * @access admin * @return string json-encoded array * @throws exception */ public function get() { ($this-&gt;isadmin()) { $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); $with_ips = $this-&gt;getparam('with_ips', true, true); $no_std_subdomain = $this-&gt;getparam('no_std_subdomain', true, false); // convert possible idn domain punycode (substr($domainname, 0, 4) != 'xn--') { $idna_convert = new idnawrapper(); $domainname = $idna_convert-&gt;encode($domainname); } $result_stmt = database::prepare(" select `d`.*, `c`.`customerid` `" . table_panel_domains . "` `d` left join `" . table_panel_customers . "` `c` using(`customerid`) `d`.`parentdomainid` = '0' " . ($id &gt; 0 ? "`d`.`id` = :iddn" : "`d`.`domain` = :iddn") . ($no_std_subdomain ? ' `d`.`id` &lt;&gt; `c`.`standardsubdomain`' : '') . ($this-&gt;getuserdetail('customers_see_all') ? '' : " `d`.`adminid` = :adminid")); $params = [ 'iddn' =&gt; ($id &lt;= 0 ? $domainname : $id) ]; ($this-&gt;getuserdetail('customers_see_all') == '0') { $params['adminid'] = $this-&gt;getuserdetail('adminid'); } $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { $result['ipsandports'] = []; ($with_ips) { $result['ipsandports'] = $this-&gt;getipsfordomain($result['id']); } $result['domain_hascert'] = $this-&gt;gethascertvaluefordomain((int)$result['id'], (int)$result['parentdomainid']); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_info, "[api] get domain '" . $result['domain'] . "'"); return $this-&gt;response($result); } $key = ($id &gt; 0 ? "id #" . $id : "domainname '" . $domainname . "'"); throw new exception("domain " . $key . " could found", 404); } throw new exception("not allowed execute given command.", 403); } private function gethascertvaluefordomain(int $domainid, int $parentdomainid): int { // nothing (ssl_global) $domain_hascert = 0; $ssl_stmt = database::prepare("select * `" . table_panel_domain_ssl_settings . "` `domainid` = :domainid"); database::pexecute($ssl_stmt, array( "domainid" =&gt; $domainid )); $ssl_result = $ssl_stmt-&gt;fetch(pdo::fetch_assoc); (is_array($ssl_result) &amp;&amp; isset($ssl_result['ssl_cert_file']) &amp;&amp; $ssl_result['ssl_cert_file'] != '') { // certificate (ssl_customer_green) $domain_hascert = 1; } else { // check parent one set (shared) ($parentdomainid != 0) { $ssl_stmt = database::prepare("select * `" . table_panel_domain_ssl_settings . "` `domainid` = :domainid"); database::pexecute($ssl_stmt, array( "domainid" =&gt; $parentdomainid )); $ssl_result = $ssl_stmt-&gt;fetch(pdo::fetch_assoc); (is_array($ssl_result) &amp;&amp; isset($ssl_result['ssl_cert_file']) &amp;&amp; $ssl_result['ssl_cert_file'] != '') { // parent certificate (ssl_shared) $domain_hascert = 2; } } } return $domain_hascert; } /** * validate given ips * * @param int|string|array $p_ipandports * @param boolean $ssl * default false * @param int $edit_id * default 0 * * @return array * @throws exception */ private function validateipaddresses($p_ipandports = null, $ssl = false, $edit_id = 0) { // adding new domain ip given, try use // system-default, check none // required ssl-enabled ip's ($edit_id &lt;= 0 &amp;&amp; !$ssl &amp;&amp; empty($p_ipandports)) { throw new exception("no ips given, unable add domain (no default ips set?)", 406); } // convert given value(s) correctly $ipandports = []; (!empty($p_ipandports) &amp;&amp; is_numeric($p_ipandports)) { $p_ipandports = [ $p_ipandports ]; } (!empty($p_ipandports) &amp;&amp; !is_array($p_ipandports)) { $p_ipandports = json_decode($p_ipandports, true); } // check whether ip usage restrictions $additional_ip_condition = ''; $aip_param = []; ($this-&gt;getuserdetail('ip') != "-1") { // handle multiple-ip-array $additional_ip_condition = " `ip` (" . implode(",", json_decode($this-&gt;getuserdetail('ip'), true)) . ") "; } (!empty($p_ipandports) &amp;&amp; is_array($p_ipandports)) { $ipandport_check_stmt = database::prepare(" select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `id` = :ipandport " . ($ssl ? " `ssl` = '1'" : "") . $additional_ip_condition); foreach ($p_ipandports $ipandport) { (trim($ipandport) == "") { continue; } // fix ip/port checked (trim($ipandport) &lt; 1) { continue; } $ipandport = intval($ipandport); $ip_params = array_merge([ 'ipandport' =&gt; $ipandport ], $aip_param); $ipandport_check = database::pexecute_first($ipandport_check_stmt, $ip_params, true, true); (!isset($ipandport_check['id']) || $ipandport_check['id'] == '0' || $ipandport_check['id'] != $ipandport) { response::standarderror('ipportdoesntexist', '', true); } else { $ipandports[] = $ipandport; } } } elseif ($edit_id &gt; 0) { // set currently used ip's $ipsresult_stmt = database::prepare(" select d2i.`id_ipandports` `" . table_domaintoip . "` d2i left join `" . table_panel_ipsandports . "` i.id = d2i.id_ipandports d2i.`id_domain` = :id i.`ssl` = " . ($ssl ? "'1'" : "'0'")); database::pexecute($ipsresult_stmt, [ 'id' =&gt; $edit_id ], true, true); ($ipsresultrow = $ipsresult_stmt-&gt;fetch(pdo::fetch_assoc)) { $ipandports[] = $ipsresultrow['id_ipandports']; } } return $ipandports; } /** * get ips array id's * * @param array $ips * @return array */ private function getipsfromidarray(array $ids) { $resultips_stmt = database::prepare(" select `ip` `" . table_panel_ipsandports . "` id = :id "); $result = []; foreach ($ids $id) { $entry = database::pexecute_first($resultips_stmt, [ 'id' =&gt; $id ]); $result[] = $entry['ip']; } return $result; } /** * update domain entry either id domainname * * @param int $id * optional, domain-id * @param string $domainname * optional, domainname * @param int $customerid * required (if $loginname specified) * @param string $loginname * required (if $customerid specified) * @param int $adminid * optional, default calling admin's id * @param array $ipandport * optional list ip/ports assign domain, default system-default-ips * @param int $subcanemaildomain * optional, allow subdomains domain email domains, 1 = choosable (default no), 2 = choosable * (default yes), 3 = always, default 0 (never) * @param bool $isemaildomain * optional, allow email usage domain, default 0 (false) * @param bool $emaildomainverified * optional, setting $isemaildomain false, needs set true confirm action case email addresses exist domain, * default 0 (false) * @param bool $email_only * optional, restrict domain email usage, default 0 (false) * @param int $selectserveralias * optional, 0 = wildcard, 1 = www-alias, 2 = none, default 0 * @param bool $speciallogfile * optional, whether create exclusive web-logfile domain, default 0 (false) * @param bool $speciallogverified * optional, setting $speciallogfile false, needs set true confirm action, * default 0 (false) * @param int $alias * optional, domain-id domain new domain alias of, default 0 (none) * @param string $registration_date * optional, date domain registration form yyyy-mm-dd, default empty (none) * @param string $termination_date * optional, date domain termination form yyyy-mm-dd, default empty (none) * @param bool $caneditdomain * optional, whether allow customer edit domain settings, default 0 (false) * @param bool $isbinddomain * optional, whether generate dns-zone (only nameserver activated), default 0 (false) * @param string $zonefile * optional, custom dns zone filename (only nameserver activated), default empty (auto-generated) * @param bool $dkim * optional, whether domain use dkim antispam activated, default 0 (false) * @param string $specialsettings * optional, custom webserver vhost-content added generated vhost, default empty * @param string $ssl_specialsettings * optional, custom webserver vhost-content added generated ssl-vhost, default empty * @param bool $include_specialsettings * optional, whether include non-ssl specialsettings generated ssl-vhost, default false * @param bool $specialsettingsforsubdomains * optional, whether apply specialsettings subdomains domain, default read * setting system.apply_specialsettings_default * @param bool $notryfiles * optional, [nginx only] generate default try-files directive, default 0 (false) * @param bool $writeaccesslog * optional, enable writing access-log file domain, default 1 (true) * @param bool $writeerrorlog * optional, enable writing error-log file domain, default 1 (true) * @param string $documentroot * optional, specify homedir domain specifying directory (relative customer-docroot), * aware, path starts / considered full path, relative customer-docroot. also * specifying url possible (redirect), default empty (autogenerated) * @param bool $phpenabled * optional, whether php enabled domain, default 0 (false) * @param bool $phpsettingsforsubdomains * optional, whether apply php-setting apply subdomains domain, default read * setting system.apply_phpconfigs_default * @param bool $openbasedir * optional, whether activate openbasedir restriction domain, default 0 (false) * @param int $openbasedir_path * optional, either 0 domains-docroot, 1 customers-homedir 2 parent-directory domains-docroot * @param int $phpsettingid * optional, specify php-configuration used id, default 1 (system-default) * @param int $mod_fcgid_starter * optional number fcgid-starters fcgid used, default -1 * @param int $mod_fcgid_maxrequests * optional number fcgid-maxrequests fcgid used, default -1 * @param bool $ssl_redirect * optional, whether generate https-redirect not, default false; requires ssl enabled * @param bool $letsencrypt * optional, whether generate let's encrypt certificate domain, default false; requires * ssl enabled * @param array $ssl_ipandport * optional, list ssl-enabled ip/port id's assign domain, left empty, current set * value used, remove ssl ips use $remove_ssl_ipandport * @param bool $remove_ssl_ipandport * optional, set true $ssl_ipandport value given, ip's get removed, otherwise, * currently set value used, default false * @param bool $sslenabled * optional, whether ssl enabled domain, regardless assigned ssl-ips, default * 1 (true) * @param bool $http2 * optional, whether enable http/2 domain (requires enabled settings), default * 0 (false) * @param int $hsts_maxage * optional max-age value hsts header * @param bool $hsts_sub * optional whether add subdomains hsts header * @param bool $hsts_preload * optional whether preload hsts header value * @param bool $ocsp_stapling * optional whether enable ocsp-stapling domain. default 0 (false), requires ssl * @param bool $honorcipherorder * optional whether honor (server) cipher order domain. default 0 (false), requires ssl * @param bool $sessiontickets * optional whether enable disable tls sessiontickets (rfc 5077) domain. default 1 * (true), requires ssl * @param string $description * optional custom description (currently used/shown frontend), default empty * @param bool $deactivated * optional, 1 (true) domain deactivated/suspended * * @access admin * @return string json-encoded array * @throws exception */ public function update() { ($this-&gt;isadmin()) { // parameters $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); // get requested domain $result = $this-&gt;apicall('domains.get', [ 'id' =&gt; $id, 'domainname' =&gt; $domainname ]); $id = $result['id']; // optional parameters $p_ipandports = $this-&gt;getparam('ipandport', true, []); $adminid = intval($this-&gt;getparam('adminid', true, $result['adminid'])); ($this-&gt;getparam('customerid', true, 0) == 0 &amp;&amp; $this-&gt;getparam('loginname', true, '') == '') { $customerid = $result['customerid']; $customer = $this-&gt;apicall('customers.get', [ 'id' =&gt; $customerid ]); } else { $customer = $this-&gt;getcustomerdata(); $customerid = $customer['customerid']; } $subcanemaildomain = $this-&gt;getparam('subcanemaildomain', true, $result['subcanemaildomain']); $isemaildomain = $this-&gt;getboolparam('isemaildomain', true, $result['isemaildomain']); $emaildomainverified = $this-&gt;getboolparam('emaildomainverified', true, 0); $email_only = $this-&gt;getboolparam('email_only', true, $result['email_only']); $p_serveraliasoption = $this-&gt;getparam('selectserveralias', true, -1); $speciallogfile = $this-&gt;getboolparam('speciallogfile', true, $result['speciallogfile']); $speciallogverified = $this-&gt;getboolparam('speciallogverified', true, 0); $aliasdomain = intval($this-&gt;getparam('alias', true, $result['aliasdomain'])); $registration_date = $this-&gt;getparam('registration_date', true, $result['registration_date']); $termination_date = $this-&gt;getparam('termination_date', true, $result['termination_date']); $caneditdomain = $this-&gt;getboolparam('caneditdomain', true, $result['caneditdomain']); $isbinddomain = $this-&gt;getboolparam('isbinddomain', true, $result['isbinddomain']); $zonefile = $this-&gt;getparam('zonefile', true, $result['zonefile']); $dkim = $this-&gt;getboolparam('dkim', true, $result['dkim']); $specialsettings = $this-&gt;getparam('specialsettings', true, $result['specialsettings']); $ssl_specialsettings = $this-&gt;getparam('ssl_specialsettings', true, $result['ssl_specialsettings']); $include_specialsettings = $this-&gt;getboolparam('include_specialsettings', true, $result['include_specialsettings']); $ssfs = $this-&gt;getboolparam('specialsettingsforsubdomains', true, settings::get('system.apply_specialsettings_default')); $notryfiles = $this-&gt;getboolparam('notryfiles', true, $result['notryfiles']); $writeaccesslog = $this-&gt;getboolparam('writeaccesslog', true, $result['writeaccesslog']); $writeerrorlog = $this-&gt;getboolparam('writeerrorlog', true, $result['writeerrorlog']); $documentroot = $this-&gt;getparam('documentroot', true, $result['documentroot']); $phpenabled = $this-&gt;getboolparam('phpenabled', true, $result['phpenabled']); $phpfs = $this-&gt;getboolparam('phpsettingsforsubdomains', true, settings::get('system.apply_phpconfigs_default')); $openbasedir = $this-&gt;getboolparam('openbasedir', true, $result['openbasedir']); $openbasedir_path = $this-&gt;getparam('openbasedir_path', true, $result['openbasedir_path']); $phpsettingid = $this-&gt;getparam('phpsettingid', true, $result['phpsettingid']); $mod_fcgid_starter = $this-&gt;getparam('mod_fcgid_starter', true, $result['mod_fcgid_starter']); $mod_fcgid_maxrequests = $this-&gt;getparam('mod_fcgid_maxrequests', true, $result['mod_fcgid_maxrequests']); $ssl_redirect = $this-&gt;getboolparam('ssl_redirect', true, $result['ssl_redirect']); $letsencrypt = $this-&gt;getboolparam('letsencrypt', true, $result['letsencrypt']); $remove_ssl_ipandport = $this-&gt;getboolparam('remove_ssl_ipandport', true, 0); $p_ssl_ipandports = $this-&gt;getparam('ssl_ipandport', true, $remove_ssl_ipandport ? [ -1 ] : null); $sslenabled = $remove_ssl_ipandport ? false : $this-&gt;getboolparam('sslenabled', true, $result['ssl_enabled']); $http2 = $this-&gt;getboolparam('http2', true, $result['http2']); $hsts_maxage = $this-&gt;getparam('hsts_maxage', true, $result['hsts']); $hsts_sub = $this-&gt;getboolparam('hsts_sub', true, $result['hsts_sub']); $hsts_preload = $this-&gt;getboolparam('hsts_preload', true, $result['hsts_preload']); $ocsp_stapling = $this-&gt;getboolparam('ocsp_stapling', true, $result['ocsp_stapling']); $honorcipherorder = $this-&gt;getboolparam('honorcipherorder', true, $result['ssl_honorcipherorder']); $sessiontickets = $this-&gt;getboolparam('sessiontickets', true, $result['ssl_sessiontickets']); $override_tls = $this-&gt;getboolparam('override_tls', true, $result['override_tls']); ($this-&gt;getuserdetail('change_serversettings') == '1') { ($override_tls) { $p_ssl_protocols = $this-&gt;getparam('ssl_protocols', true, explode(',', $result['ssl_protocols'])); $ssl_cipher_list = $this-&gt;getparam('ssl_cipher_list', true, $result['ssl_cipher_list']); $tlsv13_cipher_list = $this-&gt;getparam('tlsv13_cipher_list', true, $result['tlsv13_cipher_list']); } else { $p_ssl_protocols = []; $ssl_cipher_list = ""; $tlsv13_cipher_list = ""; } } else { $p_ssl_protocols = explode(',', $result['ssl_protocols']); $ssl_cipher_list = $result['ssl_cipher_list']; $tlsv13_cipher_list = $result['tlsv13_cipher_list']; } $description = $this-&gt;getparam('description', true, $result['description']); $deactivated = $this-&gt;getboolparam('deactivated', true, $result['deactivated']); // count subdomain usage source-domain $subdomains_stmt = database::prepare(" select count(`id`) count `" . table_panel_domains . "` `parentdomainid` = :resultid "); $subdomains = database::pexecute_first($subdomains_stmt, [ 'resultid' =&gt; $result['id'] ], true, true); $subdomains = $subdomains['count']; // count domain alias domain $alias_check_stmt = database::prepare(" select count(`id`) count `" . table_panel_domains . "` `aliasdomain` = :resultid "); $alias_check = database::pexecute_first($alias_check_stmt, [ 'resultid' =&gt; $result['id'] ], true, true); $alias_check = $alias_check['count']; // count used email-accounts $domain_emails_result_stmt = database::prepare(" select `email`, `email_full`, `destination`, `popaccountid` `" . table_mail_virtual . "` `customerid` = :customerid `domainid` = :id "); database::pexecute($domain_emails_result_stmt, [ 'customerid' =&gt; $result['customerid'], 'id' =&gt; $result['id'] ], true, true); $emails = database::num_rows(); $email_forwarders = 0; $email_accounts = 0; ($domain_emails_row = $domain_emails_result_stmt-&gt;fetch(pdo::fetch_assoc)) { ($domain_emails_row['destination'] != '') { $domain_emails_row['destination'] = explode(' ', filedir::makecorrectdestination($domain_emails_row['destination'])); $email_forwarders += count($domain_emails_row['destination']); (in_array($domain_emails_row['email_full'], $domain_emails_row['destination'])) { $email_forwarders -= 1; $email_accounts++; } } } ($emails &gt; 0 &amp;&amp; (int)$isemaildomain == 0 &amp;&amp; (int)$result['isemaildomain'] == 1 &amp;&amp; (int)$emaildomainverified == 0) { response::standarderror('emaildomainstillhasaddresses', '', true); } // handle change customer (move domain customer customer) ($customerid &gt; 0 &amp;&amp; $customerid != $result['customerid'] &amp;&amp; settings::get('panel.allow_domain_change_customer') == '1') { // check whether target customer enough resources $customer_stmt = database::prepare(" select * `" . table_panel_customers . "` `customerid` = :customerid (`subdomains_used` + :subdomains &lt;= `subdomains` `subdomains` = '-1' ) (`emails_used` + :emails &lt;= `emails` `emails` = '-1' ) (`email_forwarders_used` + :forwarders &lt;= `email_forwarders` `email_forwarders` = '-1' ) (`email_accounts_used` + :accounts &lt;= `email_accounts` `email_accounts` = '-1' ) " . ($this-&gt;getuserdetail('customers_see_all') ? '' : " `adminid` = :adminid")); $params = [ 'customerid' =&gt; $customerid, 'subdomains' =&gt; $subdomains, 'emails' =&gt; $emails, 'forwarders' =&gt; $email_forwarders, 'accounts' =&gt; $email_accounts ]; ($this-&gt;getuserdetail('customers_see_all') == '0') { $params['adminid'] = $this-&gt;getuserdetail('adminid'); } $customer = database::pexecute_first($customer_stmt, $params, true, true); (empty($customer) || $customer['customerid'] != $customerid) { response::standarderror('customerdoesntexist', '', true); } } // handle change admin (move domain admin admin) ($this-&gt;getuserdetail('customers_see_all') == '1') { ($adminid &gt; 0 &amp;&amp; $adminid != $result['adminid'] &amp;&amp; settings::get('panel.allow_domain_change_admin') == '1') { $admin_stmt = database::prepare(" select * `" . table_panel_admins . "` `adminid` = :adminid ( `domains_used` &lt; `domains` `domains` = '-1' ) "); $admin = database::pexecute_first($admin_stmt, [ 'adminid' =&gt; $adminid ], true, true); (empty($admin) || $admin['adminid'] != $adminid) { response::standarderror('admindoesntexist', '', true); } } else { $adminid = $result['adminid']; } } else { $adminid = $result['adminid']; } (!is_null($registration_date)) { $registration_date = validate::validate($registration_date, 'registration_date', validate::regex_yyyy_mm_dd, '', [ '0000-00-00', '0', '' ], true); } ($registration_date == '0000-00-00' || empty($registration_date)) { $registration_date = null; } (!is_null($termination_date)) { $termination_date = validate::validate($termination_date, 'termination_date', validate::regex_yyyy_mm_dd, '', [ '0000-00-00', '0', '' ], true); } ($termination_date == '0000-00-00' || empty($termination_date)) { $termination_date = null; } $serveraliasoption = '2'; ($result['iswildcarddomain'] == '1') { $serveraliasoption = '0'; } elseif ($result['wwwserveralias'] == '1') { $serveraliasoption = '1'; } ($p_serveraliasoption &gt; -1) { $serveraliasoption = $p_serveraliasoption; } $documentroot = validate::validate($documentroot, 'documentroot', validate::regex_dir, '', [], true); (!empty($documentroot) &amp;&amp; $documentroot != $result['documentroot'] &amp;&amp; substr($documentroot, 0, 1) == '/' &amp;&amp; substr($documentroot, 0, strlen($customer['documentroot'])) != $customer['documentroot'] &amp;&amp; $this-&gt;getuserdetail('change_serversettings') != '1') { response::standarderror('pathmustberelative', '', true); } // moving customer path specified, update would normally reuse current document-root // would point wrong customer, therefore re-create directory (!empty($documentroot) &amp;&amp; $customerid &gt; 0 &amp;&amp; $customerid != $result['customerid'] &amp;&amp; settings::get('panel.allow_domain_change_customer') == '1') { (settings::get('system.documentroot_use_default_value') == 1) { $_documentroot = filedir::makecorrectdir($customer['documentroot'] . '/' . $result['domain']); } else { $_documentroot = $customer['documentroot']; } // set customers default docroot $documentroot = $_documentroot; } ($documentroot == '') { // path empty 'use domain name default value documentroot path' enabled settings, // set default path subdomain domain name (settings::get('system.documentroot_use_default_value') == 1) { $documentroot = filedir::makecorrectdir($customer['documentroot'] . '/' . $result['domain']); } else { $documentroot = $customer['documentroot']; } } (!preg_match('/^https?\:\/\//', $documentroot) &amp;&amp; strstr($documentroot, ":") !== false) { response::standarderror('pathmaynotcontaincolon', '', true); } ($this-&gt;getuserdetail('change_serversettings') == '1') { (settings::get('system.bind_enable') == '1') { $zonefile = validate::validate($zonefile, 'zonefile', '', '', [], true); } else { $isbinddomain = $result['isbinddomain']; $zonefile = $result['zonefile']; } (settings::get('antispam.activated') != '1') { $dkim = $result['dkim']; } $specialsettings = validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', validate::regex_conf_text, '', [], true); $ssl_protocols = []; (!empty($p_ssl_protocols) &amp;&amp; is_numeric($p_ssl_protocols)) { $p_ssl_protocols = [ $p_ssl_protocols ]; } (!empty($p_ssl_protocols) &amp;&amp; !is_array($p_ssl_protocols)) { $p_ssl_protocols = json_decode($p_ssl_protocols, true); } (!empty($p_ssl_protocols) &amp;&amp; is_array($p_ssl_protocols)) { $protocols_available = [ 'tlsv1', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3' ]; foreach ($p_ssl_protocols $ssl_protocol) { (!in_array(trim($ssl_protocol), $protocols_available)) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_debug, "[api] unknown ssl protocol '" . trim($ssl_protocol) . "'"); continue; } $ssl_protocols[] = $ssl_protocol; } } (empty($ssl_protocols)) { $override_tls = '0'; } } else { $isbinddomain = $result['isbinddomain']; $zonefile = $result['zonefile']; $specialsettings = $result['specialsettings']; $ssl_specialsettings = $result['ssl_specialsettings']; $include_specialsettings = $result['include_specialsettings']; $ssfs = (empty($specialsettings) ? 0 : 1); $notryfiles = $result['notryfiles']; $writeaccesslog = $result['writeaccesslog']; $writeerrorlog = $result['writeerrorlog']; $ssl_protocols = $p_ssl_protocols; $override_tls = $result['override_tls']; } ($this-&gt;getuserdetail('caneditphpsettings') == '1' || $this-&gt;getuserdetail('change_serversettings') == '1') { ((int)settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1) { $phpsettingid_check_stmt = database::prepare(" select * `" . table_panel_phpconfigs . "` `id` = :phpid "); $phpsettingid_check = database::pexecute_first($phpsettingid_check_stmt, [ 'phpid' =&gt; $phpsettingid ], true, true); (!isset($phpsettingid_check['id']) || $phpsettingid_check['id'] == '0' || $phpsettingid_check['id'] != $phpsettingid) { response::standarderror('phpsettingidwrong', '', true); } ((int)settings::get('system.mod_fcgid') == 1) { $mod_fcgid_starter = validate::validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', [ '-1', '' ], true); $mod_fcgid_maxrequests = validate::validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', [ '-1', '' ], true); } else { $mod_fcgid_starter = $result['mod_fcgid_starter']; $mod_fcgid_maxrequests = $result['mod_fcgid_maxrequests']; } } else { $phpsettingid = $result['phpsettingid']; $phpfs = 1; $mod_fcgid_starter = $result['mod_fcgid_starter']; $mod_fcgid_maxrequests = $result['mod_fcgid_maxrequests']; } } else { $phpenabled = $result['phpenabled']; $openbasedir = $result['openbasedir']; $phpsettingid = $result['phpsettingid']; $phpfs = 1; $mod_fcgid_starter = $result['mod_fcgid_starter']; $mod_fcgid_maxrequests = $result['mod_fcgid_maxrequests']; } // check changes openbasedir-path variable ($openbasedir_path &gt; 2 &amp;&amp; $openbasedir_path &lt; 0) { $openbasedir_path = 0; } // check non-ssl ip $ipandports = $this-&gt;validateipaddresses($p_ipandports, false, $result['id']); // check ssl ip (empty($p_ssl_ipandports) || (!is_array($p_ssl_ipandports) &amp;&amp; is_null($p_ssl_ipandports))) { $p_ssl_ipandports = []; foreach ($result['ipsandports'] $ip) { ($ip['ssl'] == 1) { $p_ssl_ipandports[] = $ip['id']; } } } $ssl_ipandports = []; (settings::get('system.use_ssl') == "1" &amp;&amp; !empty($p_ssl_ipandports) &amp;&amp; $p_ssl_ipandports[0] != -1) { $ssl_ipandports = $this-&gt;validateipaddresses($p_ssl_ipandports, true, $result['id']); ($this-&gt;getuserdetail('change_serversettings') == '1') { $ssl_specialsettings = validate::validate(str_replace("\r\n", "\n", $ssl_specialsettings), 'ssl_specialsettings', '/^[^\0]*$/', '', [], true); } } ($remove_ssl_ipandport || (!empty($p_ssl_ipandports) &amp;&amp; $p_ssl_ipandports[0] == -1)) { $ssl_ipandports = []; } (settings::get('system.use_ssl') == "1" &amp;&amp; $sslenabled &amp;&amp; empty($ssl_ipandports)) { // enabled ssl domain ssl ip/port selected response::standarderror('nosslippportgiven', '', true); } (settings::get('system.use_ssl') == "0" || empty($ssl_ipandports) || !$sslenabled) { $ssl_redirect = 0; $letsencrypt = 0; $http2 = 0; // act like $remove_ssl_ipandport $ssl_ipandports = []; // hsts $hsts_maxage = 0; $hsts_sub = 0; $hsts_preload = 0; // ocsp stapling $ocsp_stapling = 0; // vhost container settings $ssl_specialsettings = ''; $include_specialsettings = 0; } // validate dns lets encrypt enabled check whether use ($letsencrypt == '1' &amp;&amp; settings::get('system.le_domain_dnscheck') == '1') { $domain_ips = phphelper::gethostbynamel6($result['domain'], true, settings::get('system.le_domain_dnscheck_resolver')); $selected_ips = $this-&gt;getipsfromidarray($ssl_ipandports); ($domain_ips == false || count(array_intersect($selected_ips, $domain_ips)) &lt;= 0) { response::standarderror('invaliddnsforletsencrypt', '', true); } } // can't enable let's encrypt wildcard-domains ($serveraliasoption == '0' &amp;&amp; $letsencrypt == '1') { response::standarderror('nowildcardwithletsencrypt', '', true); } // temporarily deactivate ssl_redirect let's encrypt certificate generated ($result['letsencrypt'] != $letsencrypt &amp;&amp; $ssl_redirect &gt; 0 &amp;&amp; $letsencrypt == 1) { $ssl_redirect = 2; } (!preg_match('/^https?\:\/\//', $documentroot)) { ($documentroot != $result['documentroot']) { (substr($documentroot, 0, 1) != "/") { $documentroot = $customer['documentroot'] . '/' . $documentroot; } $documentroot = filedir::makecorrectdir($documentroot); } } ($email_only == '1') { $isemaildomain = '1'; } else { $email_only = '0'; } ($subcanemaildomain != '1' &amp;&amp; $subcanemaildomain != '2' &amp;&amp; $subcanemaildomain != '3') { $subcanemaildomain = '0'; } $aliasdomain_check = [ 'id' =&gt; 0 ]; ($aliasdomain != 0) { // overwrite given ipandports "main" domain $ipandports = []; $ssl_ipandports = []; $origipresult_stmt = database::prepare(" select `id_ipandports` `" . table_domaintoip . "` `id_domain` = :aliasdomain "); database::pexecute($origipresult_stmt, [ 'aliasdomain' =&gt; $aliasdomain ], true, true); $ipdata_stmt = database::prepare("select * `" . table_panel_ipsandports . "` `id` = :ipid"); ($origip = $origipresult_stmt-&gt;fetch(pdo::fetch_assoc)) { $_origip_tmp = database::pexecute_first($ipdata_stmt, [ 'ipid' =&gt; $origip['id_ipandports'] ], true, true); ($_origip_tmp['ssl'] == 0) { $ipandports[] = $origip['id_ipandports']; } else { $ssl_ipandports[] = $origip['id_ipandports']; } } (count($ssl_ipandports) == 0) { // need json_encode // ssl disabled ssl-ip/port exists $ssl_ipandports[] = -1; } $aliasdomain_check_stmt = database::prepare(" select `d`.`id` `" . table_panel_domains . "` `d`, `" . table_panel_customers . "` `c` `d`.`customerid` = :customerid `d`.`aliasdomain` null `d`.`id` &lt;&gt; `c`.`standardsubdomain` `c`.`customerid` = :customerid `d`.`id` = :aliasdomain "); $aliasdomain_check = database::pexecute_first($aliasdomain_check_stmt, [ 'customerid' =&gt; $customerid, 'aliasdomain' =&gt; $aliasdomain ], true, true); } (count($ipandports) == 0) { response::standarderror('noipportgiven', '', true); } ($aliasdomain_check['id'] != $aliasdomain) { response::standarderror('domainisaliasorothercustomer', '', true); } ($serveraliasoption != '1' &amp;&amp; $serveraliasoption != '2') { $serveraliasoption = '0'; } $wwwserveralias = ($serveraliasoption == '1') ? '1' : '0'; $iswildcarddomain = ($serveraliasoption == '0') ? '1' : '0'; ($documentroot != $result['documentroot'] || $ssl_redirect != $result['ssl_redirect'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $phpenabled != $result['phpenabled'] || $openbasedir != $result['openbasedir'] || $openbasedir_path != $result['openbasedir_path'] || $phpsettingid != $result['phpsettingid'] || $mod_fcgid_starter != $result['mod_fcgid_starter'] || $mod_fcgid_maxrequests != $result['mod_fcgid_maxrequests'] || $specialsettings != $result['specialsettings'] || $ssl_specialsettings != $result['ssl_specialsettings'] || $notryfiles != $result['notryfiles'] || $writeaccesslog != $result['writeaccesslog'] || $writeerrorlog != $result['writeerrorlog'] || $aliasdomain != $result['aliasdomain'] || $email_only != $result['email_only'] || ($speciallogfile != $result['speciallogfile'] &amp;&amp; $speciallogverified == '1') || $letsencrypt != $result['letsencrypt'] || $http2 != $result['http2'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload'] || $ocsp_stapling != $result['ocsp_stapling'] || $sslenabled != $result['ssl_enabled'] ) { cronjob::inserttask(taskid::rebuild_vhost); } ($dkim != $result['dkim']) { cronjob::inserttask(taskid::rebuild_rspamd); } ($speciallogfile != $result['speciallogfile'] &amp;&amp; $speciallogverified != '1') { $speciallogfile = $result['speciallogfile']; } ($isbinddomain != $result['isbinddomain'] || $zonefile != $result['zonefile'] || $dkim != $result['dkim'] || $isemaildomain != $result['isemaildomain']) { cronjob::inserttask(taskid::rebuild_dns); } // check whether nameserver disabled, #581 ($isbinddomain != $result['isbinddomain'] &amp;&amp; $isbinddomain == 0) { cronjob::inserttask(taskid::delete_domain_pdns, $result['domain']); } ($isemaildomain == '0' &amp;&amp; $result['isemaildomain'] == '1') { $del_stmt = database::prepare(" delete `" . table_mail_users . "` `domainid` = :id "); database::pexecute($del_stmt, [ 'id' =&gt; $id ], true, true); $del_stmt = database::prepare(" delete `" . table_mail_virtual . "` `domainid` = :id "); database::pexecute($del_stmt, [ 'id' =&gt; $id ], true, true); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] deleted domain #" . $id . " mail-tables is-email-domain set 0"); } // check whether le disabled, remove certificate ($letsencrypt == '0' &amp;&amp; $result['letsencrypt'] == '1') { $del_stmt = database::prepare(" delete `" . table_panel_domain_ssl_settings . "` `domainid` = :id "); database::pexecute($del_stmt, [ 'id' =&gt; $id ], true, true); // remove domain acme.sh / lets encrypt used cronjob::inserttask(taskid::delete_domain_ssl, $result['domain']); } $updatechildren = ''; ($subcanemaildomain == '0' &amp;&amp; $result['subcanemaildomain'] != '0') { $updatechildren = ", `isemaildomain` = '0' "; } elseif ($subcanemaildomain == '3' &amp;&amp; $result['subcanemaildomain'] != '3') { $updatechildren = ", `isemaildomain` = '1' "; } ($customerid != $result['customerid'] &amp;&amp; settings::get('panel.allow_domain_change_customer') == '1') { $upd_data = [ 'customerid' =&gt; $customerid, 'domainid' =&gt; $result['id'] ]; $upd_stmt = database::prepare(" update `" . table_mail_users . "` set `customerid` = :customerid `domainid` = :domainid "); database::pexecute($upd_stmt, $upd_data, true, true); $upd_stmt = database::prepare(" update `" . table_mail_virtual . "` set `customerid` = :customerid `domainid` = :domainid "); database::pexecute($upd_stmt, $upd_data, true, true); $upd_data = [ 'subdomains' =&gt; $subdomains, 'emails' =&gt; $emails, 'forwarders' =&gt; $email_forwarders, 'accounts' =&gt; $email_accounts ]; $upd_data['customerid'] = $customerid; $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `subdomains_used` = `subdomains_used` + :subdomains, `emails_used` = `emails_used` + :emails, `email_forwarders_used` = `email_forwarders_used` + :forwarders, `email_accounts_used` = `email_accounts_used` + :accounts `customerid` = :customerid "); database::pexecute($upd_stmt, $upd_data, true, true); $upd_data['customerid'] = $result['customerid']; $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `subdomains_used` = `subdomains_used` - :subdomains, `emails_used` = `emails_used` - :emails, `email_forwarders_used` = `email_forwarders_used` - :forwarders, `email_accounts_used` = `email_accounts_used` - :accounts `customerid` = :customerid "); database::pexecute($upd_stmt, $upd_data, true, true); } ($adminid != $result['adminid'] &amp;&amp; settings::get('panel.allow_domain_change_admin') == '1') { $upd_stmt = database::prepare(" update `" . table_panel_admins . "` set `domains_used` = `domains_used` + 1 `adminid` = :adminid "); database::pexecute($upd_stmt, [ 'adminid' =&gt; $adminid ], true, true); $upd_stmt = database::prepare(" update `" . table_panel_admins . "` set `domains_used` = `domains_used` - 1 `adminid` = :adminid "); database::pexecute($upd_stmt, [ 'adminid' =&gt; $result['adminid'] ], true, true); } $_update_data = []; ($ssfs == 1) { $_update_data['specialsettings'] = $specialsettings; $_update_data['ssl_specialsettings'] = $ssl_specialsettings; $_update_data['include_specialsettings'] = $include_specialsettings; $upd_specialsettings = ", `specialsettings` = :specialsettings, `ssl_specialsettings` = :ssl_specialsettings, `include_specialsettings` = :include_specialsettings "; } else { $upd_specialsettings = ''; $upd_stmt = database::prepare(" update `" . table_panel_domains . "` set `specialsettings`='', `ssl_specialsettings`='', `include_specialsettings`='0' `parentdomainid` = :id "); database::pexecute($upd_stmt, [ 'id' =&gt; $id ], true, true); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] removed specialsettings subdomains domain #" . $id); } $wwwserveralias = ($serveraliasoption == '1') ? '1' : '0'; $iswildcarddomain = ($serveraliasoption == '0') ? '1' : '0'; $update_data = []; $update_data['customerid'] = $customerid; $update_data['adminid'] = $adminid; $update_data['documentroot'] = $documentroot; $update_data['ssl_redirect'] = $ssl_redirect; $update_data['aliasdomain'] = ($aliasdomain != 0 &amp;&amp; $alias_check == 0) ? $aliasdomain : null; $update_data['isbinddomain'] = $isbinddomain; $update_data['isemaildomain'] = $isemaildomain; $update_data['email_only'] = $email_only; $update_data['subcanemaildomain'] = $subcanemaildomain; $update_data['dkim'] = $dkim; $update_data['caneditdomain'] = $caneditdomain; $update_data['zonefile'] = $zonefile; $update_data['wwwserveralias'] = $wwwserveralias; $update_data['iswildcarddomain'] = $iswildcarddomain; $update_data['phpenabled'] = $phpenabled; $update_data['openbasedir'] = $openbasedir; $update_data['openbasedir_path'] = $openbasedir_path; $update_data['speciallogfile'] = $speciallogfile; $update_data['phpsettingid'] = $phpsettingid; $update_data['mod_fcgid_starter'] = $mod_fcgid_starter; $update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests; $update_data['specialsettings'] = $specialsettings; $update_data['ssl_specialsettings'] = $ssl_specialsettings; $update_data['include_specialsettings'] = $include_specialsettings; $update_data['notryfiles'] = $notryfiles; $update_data['writeaccesslog'] = $writeaccesslog; $update_data['writeerrorlog'] = $writeerrorlog; $update_data['registration_date'] = $registration_date; $update_data['termination_date'] = $termination_date; $update_data['letsencrypt'] = $letsencrypt; $update_data['http2'] = $http2; $update_data['hsts'] = $hsts_maxage; $update_data['hsts_sub'] = $hsts_sub; $update_data['hsts_preload'] = $hsts_preload; $update_data['ocsp_stapling'] = $ocsp_stapling; $update_data['override_tls'] = $override_tls; $update_data['ssl_protocols'] = implode(",", $ssl_protocols); $update_data['ssl_cipher_list'] = $ssl_cipher_list; $update_data['tlsv13_cipher_list'] = $tlsv13_cipher_list; $update_data['sslenabled'] = $sslenabled; $update_data['honorcipherorder'] = $honorcipherorder; $update_data['sessiontickets'] = $sessiontickets; $update_data['description'] = $description; $update_data['deactivated'] = $deactivated; $update_data['id'] = $id; $update_stmt = database::prepare(" update `" . table_panel_domains . "` set `customerid` = :customerid, `adminid` = :adminid, `documentroot` = :documentroot, `ssl_redirect` = :ssl_redirect, `aliasdomain` = :aliasdomain, `isbinddomain` = :isbinddomain, `isemaildomain` = :isemaildomain, `email_only` = :email_only, `subcanemaildomain` = :subcanemaildomain, `dkim` = :dkim, `caneditdomain` = :caneditdomain, `zonefile` = :zonefile, `wwwserveralias` = :wwwserveralias, `iswildcarddomain` = :iswildcarddomain, `phpenabled` = :phpenabled, `openbasedir` = :openbasedir, `openbasedir_path` = :openbasedir_path, `speciallogfile` = :speciallogfile, `phpsettingid` = :phpsettingid, `mod_fcgid_starter` = :mod_fcgid_starter, `mod_fcgid_maxrequests` = :mod_fcgid_maxrequests, `specialsettings` = :specialsettings, `ssl_specialsettings` = :ssl_specialsettings, `include_specialsettings` = :include_specialsettings, `notryfiles` = :notryfiles, `writeaccesslog` = :writeaccesslog, `writeerrorlog` = :writeerrorlog, `registration_date` = :registration_date, `termination_date` = :termination_date, `letsencrypt` = :letsencrypt, `http2` = :http2, `hsts` = :hsts, `hsts_sub` = :hsts_sub, `hsts_preload` = :hsts_preload, `ocsp_stapling` = :ocsp_stapling, `override_tls` = :override_tls, `ssl_protocols` = :ssl_protocols, `ssl_cipher_list` = :ssl_cipher_list, `tlsv13_cipher_list` = :tlsv13_cipher_list, `ssl_enabled` = :sslenabled, `ssl_honorcipherorder` = :honorcipherorder, `ssl_sessiontickets` = :sessiontickets, `description` = :description, `deactivated` = :deactivated `id` = :id "); database::pexecute($update_stmt, $update_data, true, true); // activate/deactivate domain-based services ($deactivated != $result['deactivated']) { // deactivate email accounts $yesno = ($deactivated ? 'n' : 'y'); $pop3 = ($deactivated ? '0' : (int)$customer['pop3']); $imap = ($deactivated ? '0' : (int)$customer['imap']); $upd_stmt = database::prepare(" update `" . table_mail_users . "` set `postfix`= :yesno, `pop3` = :pop3, `imap` = :imap `customerid` = :customerid `domainid` = :domainid "); database::pexecute($upd_stmt, [ 'yesno' =&gt; $yesno, 'pop3' =&gt; $pop3, 'imap' =&gt; $imap, 'customerid' =&gt; $customerid, 'domainid' =&gt; $id ]); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] " . ($deactivated ? 'deactivated' : 'reactivated') . " domain '" . $result['domain'] . "'"); cronjob::inserttask(taskid::rebuild_vhost); } $_update_data['customerid'] = $customerid; $_update_data['adminid'] = $adminid; $_update_data['phpenabled'] = $phpenabled; $_update_data['openbasedir'] = $openbasedir; $_update_data['openbasedir_path'] = $openbasedir_path; $_update_data['mod_fcgid_starter'] = $mod_fcgid_starter; $_update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests; $_update_data['notryfiles'] = $notryfiles; $_update_data['writeaccesslog'] = $writeaccesslog; $_update_data['writeerrorlog'] = $writeerrorlog; $_update_data['override_tls'] = $override_tls; $_update_data['ssl_protocols'] = implode(",", $ssl_protocols); $_update_data['ssl_cipher_list'] = $ssl_cipher_list; $_update_data['tlsv13_cipher_list'] = $tlsv13_cipher_list; $_update_data['honorcipherorder'] = $honorcipherorder; $_update_data['sessiontickets'] = $sessiontickets; $_update_data['parentdomainid'] = $id; $_update_data['deactivated'] = $deactivated; // php config set subdomains, check $update_phpconfig = ''; ($phpfs == 1) { $_update_data['phpsettingid'] = $phpsettingid; $update_phpconfig = ", `phpsettingid` = :phpsettingid"; } // ssl-ip's domain, // subdomains must "ssl-redirect = 0" // disable let's encrypt $update_sslredirect = ''; (count($ssl_ipandports) == 1 &amp;&amp; $ssl_ipandports[0] == -1) { $update_sslredirect = ", `ssl_redirect` = '0', `letsencrypt` = '0' "; } $_update_stmt = database::prepare(" update `" . table_panel_domains . "` set `customerid` = :customerid, `adminid` = :adminid, `phpenabled` = :phpenabled, `openbasedir` = :openbasedir, `openbasedir_path` = :openbasedir_path, `mod_fcgid_starter` = :mod_fcgid_starter, `mod_fcgid_maxrequests` = :mod_fcgid_maxrequests, `notryfiles` = :notryfiles, `writeaccesslog` = :writeaccesslog, `writeerrorlog` = :writeerrorlog, `override_tls` = :override_tls, `ssl_protocols` = :ssl_protocols, `ssl_cipher_list` = :ssl_cipher_list, `tlsv13_cipher_list` = :tlsv13_cipher_list, `ssl_honorcipherorder` = :honorcipherorder, `ssl_sessiontickets` = :sessiontickets, `deactivated` = :deactivated " . $update_phpconfig . $upd_specialsettings . $updatechildren . $update_sslredirect . " `parentdomainid` = :parentdomainid "); database::pexecute($_update_stmt, $_update_data, true, true); // get current ip&lt;&gt;domain entries $ip_sel_stmt = database::prepare(" select id_ipandports `" . table_domaintoip . "` `id_domain` = :id "); database::pexecute($ip_sel_stmt, [ 'id' =&gt; $id ], true, true); $current_ips = []; ($cip = $ip_sel_stmt-&gt;fetch(\pdo::fetch_assoc)) { $current_ips[] = $cip['id_ipandports']; } // cleanup domain &lt;-&gt; ip mapping $del_stmt = database::prepare(" delete `" . table_domaintoip . "` `id_domain` = :id "); database::pexecute($del_stmt, [ 'id' =&gt; $id ], true, true); $ins_stmt = database::prepare(" insert `" . table_domaintoip . "` set `id_domain` = :domainid, `id_ipandports` = :ipportid "); foreach ($ipandports $ipportid) { database::pexecute($ins_stmt, [ 'domainid' =&gt; $id, 'ipportid' =&gt; $ipportid ], true, true); } foreach ($ssl_ipandports $ssl_ipportid) { ($ssl_ipportid &gt; 0) { database::pexecute($ins_stmt, [ 'domainid' =&gt; $id, 'ipportid' =&gt; $ssl_ipportid ], true, true); } } // check ip changes $all_new_ips = array_merge($ipandports, $ssl_ipandports); (count(array_diff($current_ips, $all_new_ips)) != 0 || count(array_diff($all_new_ips, $current_ips)) != 0) { cronjob::inserttask(taskid::rebuild_vhost); } // cleanup domain &lt;-&gt; ip mapping subdomains $domainidsresult_stmt = database::prepare(" select `id` `" . table_panel_domains . "` `parentdomainid` = :id "); database::pexecute($domainidsresult_stmt, [ 'id' =&gt; $id ], true, true); ($row = $domainidsresult_stmt-&gt;fetch(pdo::fetch_assoc)) { $del_stmt = database::prepare(" delete `" . table_domaintoip . "` `id_domain` = :rowid "); database::pexecute($del_stmt, [ 'rowid' =&gt; $row['id'] ], true, true); $ins_stmt = database::prepare(" insert `" . table_domaintoip . "` set `id_domain` = :rowid, `id_ipandports` = :ipportid "); foreach ($ipandports $ipportid) { database::pexecute($ins_stmt, [ 'rowid' =&gt; $row['id'], 'ipportid' =&gt; $ipportid ], true, true); } foreach ($ssl_ipandports $ssl_ipportid) { ($ssl_ipportid &gt; 0) { database::pexecute($ins_stmt, [ 'rowid' =&gt; $row['id'], 'ipportid' =&gt; $ssl_ipportid ], true, true); } } } ($result['aliasdomain'] != $aliasdomain &amp;&amp; is_numeric($result['aliasdomain'])) { // trigger domain id alias destination changed: old new destination domain::triggerletsencryptcsrforaliasdestinationdomain($result['aliasdomain'], $this-&gt;logger()); domain::triggerletsencryptcsrforaliasdestinationdomain($aliasdomain, $this-&gt;logger()); } ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) { // wwwserveralias letsencrypt changed ((int)$aliasdomain === 0) { // case wwwserveralias set main domain, $aliasdomain 0 domain::triggerletsencryptcsrforaliasdestinationdomain($id, $this-&gt;logger()); } else { domain::triggerletsencryptcsrforaliasdestinationdomain($aliasdomain, $this-&gt;logger()); } } $idna_convert = new idnawrapper(); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] updated domain '" . $idna_convert-&gt;decode($result['domain']) . "'"); $result = $this-&gt;apicall('domains.get', [ 'domainname' =&gt; $result['domain'] ]); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } /** * delete domain entry either id domainname * * @param int $id * optional, domain-id * @param string $domainname * optional, domainname * @param bool $is_stdsubdomain * optional, default false, specify whether std-subdomain deleting count * subdomain-resource * @param bool $delete_userfiles * optional, delete email account files filesystem (if any), default false * * @access admin * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin()) { $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); $is_stdsubdomain = $this-&gt;getboolparam('is_stdsubdomain', true, 0); $delete_user_emailfiles = $this-&gt;getboolparam('delete_userfiles', true, 0); $result = $this-&gt;apicall('domains.get', [ 'id' =&gt; $id, 'domainname' =&gt; $domainname ]); $id = $result['id']; $subresult_stmt = database::prepare(" select `id` `" . table_panel_domains . "` (`id` = :id `parentdomainid` = :id) "); database::pexecute($subresult_stmt, [ 'id' =&gt; $id ], true, true); $idstring = []; $paramstring = []; ($subrow = $subresult_stmt-&gt;fetch(pdo::fetch_assoc)) { $idstring[] = "`domainid` = :domain_" . (int)$subrow['id']; $paramstring['domain_' . $subrow['id']] = $subrow['id']; } $idstring = implode(' ', $idstring); ($idstring != '') { ($delete_user_emailfiles) { // determine connected email-accounts $emailaccount_sel = database::prepare("select `email`, `homedir`, `maildir` `" . table_mail_users . "` " . $idstring); database::pexecute($emailaccount_sel, $paramstring, true, true); ($emailacc_row = $emailaccount_sel-&gt;fetch(pdo::fetch_assoc)) { cronjob::inserttask(taskid::delete_email_data, $emailacc_row['email'], filedir::makecorrectdir($emailacc_row['homedir'] . '/' . $emailacc_row['maildir'])); } } $del_stmt = database::prepare(" delete `" . table_mail_users . "` " . $idstring); database::pexecute($del_stmt, $paramstring, true, true); $del_stmt = database::prepare(" delete `" . table_mail_virtual . "` " . $idstring); database::pexecute($del_stmt, $paramstring, true, true); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] deleted domain/s mail-tables"); } $del_stmt = database::prepare(" delete `" . table_panel_domains . "` `id` = :id `parentdomainid` = :id "); database::pexecute($del_stmt, [ 'id' =&gt; $id ], true, true); $deleted_domains = $del_stmt-&gt;rowcount(); ($is_stdsubdomain == 0) { $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `subdomains_used` = `subdomains_used` - :domaincount `customerid` = :customerid"); database::pexecute($upd_stmt, [ 'domaincount' =&gt; ($deleted_domains - 1), 'customerid' =&gt; $result['customerid'] ], true, true); $upd_stmt = database::prepare(" update `" . table_panel_admins . "` set `domains_used` = `domains_used` - 1 `adminid` = :adminid"); database::pexecute($upd_stmt, [ 'adminid' =&gt; $this-&gt;getuserdetail('adminid') ], true, true); } $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `standardsubdomain` = '0' `standardsubdomain` = :id `customerid` = :customerid"); database::pexecute($upd_stmt, [ 'id' =&gt; $result['id'], 'customerid' =&gt; $result['customerid'] ], true, true); $del_stmt = database::prepare(" delete `" . table_domaintoip . "` `id_domain` = :domainid"); database::pexecute($del_stmt, [ 'domainid' =&gt; $id ], true, true); $del_stmt = database::prepare(" delete `" . table_panel_domainredirects . "` `did` = :domainid"); database::pexecute($del_stmt, [ 'domainid' =&gt; $id ], true, true); // remove certificate domain_ssl_settings, fixes #1596 $del_stmt = database::prepare(" delete `" . table_panel_domain_ssl_settings . "` `domainid` = :domainid"); database::pexecute($del_stmt, [ 'domainid' =&gt; $id ], true, true); // remove possible existing dns entries $del_stmt = database::prepare(" delete `" . table_domain_dns . "` `domain_id` = :domainid "); database::pexecute($del_stmt, [ 'domainid' =&gt; $id ], true, true); ((int)$result['aliasdomain'] !== 0) { domain::triggerletsencryptcsrforaliasdestinationdomain($result['aliasdomain'], $this-&gt;logger()); } // remove domains dns powerdns used, #581 cronjob::inserttask(taskid::delete_domain_pdns, $result['domain']); // remove domain acme.sh / lets encrypt used cronjob::inserttask(taskid::delete_domain_ssl, $result['domain']); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] deleted domain/subdomains (#" . $result['id'] . ")"); user::updatecounters(); cronjob::inserttask(taskid::rebuild_vhost); // using nameserver, insert task rebuilds server config cronjob::inserttask(taskid::rebuild_dns); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } /** * duplicate domain entry either id domainname. parameters domains.add() used * overwrite source entity values necessary. * * @param int $id * optional, domain-id * @param string $domainname * optional, domainname * @param string $domain * required, name new domain added * * @access admin * @return string json-encoded array * @throws exception */ public function duplicate() { ($this-&gt;isadmin()) { // parameters $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); $p_domain = $this-&gt;getparam('domain'); // get requested domain $result = $this-&gt;apicall('domains.get', [ 'id' =&gt; $id, 'domainname' =&gt; $domainname, ]); // clear defaults unset($result['domain_ace']); unset($result['adminid']); unset($result['documentroot']); unset($result['registration_date']); unset($result['termination_date']); unset($result['zonefile']); // clear auto-generated values unset($result['bindserial']); unset($result['dkim_privkey']); unset($result['dkim_pubkey']); // clear api-call generated fields unset($result['domain_hascert']); // set correct ip/port information $domain_ips = $result['ipsandports']; unset($result['ipsandports']); $result['ipandport'] = []; $result['ssl_ipandport'] = []; foreach ($domain_ips $dip) { ($dip['ssl'] == 1) { $result['ssl_ipandport'][] = $dip['id']; } else { $result['ipandport'][] = $dip['id']; } } // check whether changing customer/owner ($this-&gt;getparam('customerid', true, 0) == 0 &amp;&amp; $this-&gt;getparam('loginname', true, '') == '') { $customerid = $result['customerid']; } else { $customer = $this-&gt;getcustomerdata(); $customerid = $customer['customerid']; } // check alias-domain whether belongs target user (!empty($result['aliasdomain']) &amp;&amp; $customerid == $result['customerid']) { // duplicate alias entry $result['alias'] = $result['aliasdomain']; } unset($result['aliasdomain']); // validate possible fpm configs whether customer allowed use ($customerid != $result['customerid']) { $allowed_phpconfigs = json_decode($customer['allowed_phpconfigs'] ?? '[]', true); (empty($allowed_phpconfigs)) { // system defaults unset($result['phpsettingid']); } elseif (!in_array($result['phpsettingid'], $allowed_phpconfigs)) { // use first customer allowed config $result['phpsettingid'] = array_shift($allowed_phpconfigs); } } // translate serveralias values $result['selectserveralias'] = 2; ((int)$result['wwwserveralias'] == 1) { $result['selectserveralias'] = 1; } elseif ((int)$result['iswildcarddomain'] == 1) { $result['selectserveralias'] = 0; } unset($result['wwwserveralias']); unset($result['iswildcarddomain']); // translate sslenabled flag $result['sslenabled'] = $result['ssl_enabled']; unset($result['ssl_enabled']); $additional_params = $this-&gt;getparamlist(); // unset unneeded params call unset($additional_params['id']); unset($additional_params['domainname']); unset($additional_params['domain']); // set new values merge optional add() parameters $new_domain = array_merge($result, $additional_params); $new_domain['domain'] = $p_domain; $result_new = $this-&gt;apicall('domains.add', $new_domain); return $this-&gt;response($result_new); } throw new exception("not allowed execute given command.", 403); } }</file><file name="lib/Froxlor/Api/Commands/DirOptions.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\system\cronjob; use froxlor\ui\response; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class diroptions extends apicommand implements resourceentity { /** * add options given directory * * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param string $path * path relative customer's home-directory * @param bool $options_indexes * optional, activate directory-listing path, default 0 (false) * @param bool $options_cgi * optional, allow perl/cgi execution, default 0 (false) * @param string $error404path * optional, custom 404 error string/file * @param string $error403path * optional, custom 403 error string/file * @param string $error500path * optional, custom 500 error string/file * * @access admin, customer * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras')) { throw new exception("you cannot access resource", 405); } ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras.pathoptions')) { throw new exception("you cannot access resource", 405); } // get needed customer info reduce email-address-counter one $customer = $this-&gt;getcustomerdata(); // required parameters $path = $this-&gt;getparam('path'); // parameters $options_indexes = $this-&gt;getboolparam('options_indexes', true, 0); $options_cgi = $this-&gt;getboolparam('options_cgi', true, 0); $error404path = $this-&gt;getparam('error404path', true, ''); $error403path = $this-&gt;getparam('error403path', true, ''); $error500path = $this-&gt;getparam('error500path', true, ''); // validation $path = filedir::makecorrectdir(validate::validate($path, 'path', validate::regex_dir, '', [], true)); $userpath = $path; $path = filedir::makecorrectdir($customer['documentroot'] . '/' . $path, $customer['documentroot']); (!empty($error404path)) { $error404path = $this-&gt;correcterrordocument($error404path, true); } (!empty($error403path)) { $error403path = $this-&gt;correcterrordocument($error403path, true); } (!empty($error500path)) { $error500path = $this-&gt;correcterrordocument($error500path, true); } // check duplicate path $path_dupe_check_stmt = database::prepare(" select `id`, `path` `" . table_panel_htaccess . "` `path`= :path `customerid`= :customerid "); $path_dupe_check = database::pexecute_first($path_dupe_check_stmt, [ "path" =&gt; $path, "customerid" =&gt; $customer['customerid'] ], true, true); // duplicate check ($path_dupe_check &amp;&amp; $path_dupe_check['path'] == $path) { response::standarderror('errordocpathdupe', $userpath, true); } // insert entry $stmt = database::prepare(' insert `' . table_panel_htaccess . '` set `customerid` = :customerid, `path` = :path, `options_indexes` = :options_indexes, `error404path` = :error404path, `error403path` = :error403path, `error500path` = :error500path, `options_cgi` = :options_cgi '); $params = [ "customerid" =&gt; $customer['customerid'], "path" =&gt; $path, "options_indexes" =&gt; $options_indexes, "error403path" =&gt; $error403path, "error404path" =&gt; $error404path, "error500path" =&gt; $error500path, "options_cgi" =&gt; $options_cgi ]; database::pexecute($stmt, $params, true, true); $id = database::lastinsertid(); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] added directory-option '" . $userpath . "'"); cronjob::inserttask(taskid::rebuild_vhost); $result = $this-&gt;apicall('diroptions.get', [ 'id' =&gt; $id ]); return $this-&gt;response($result); } /** * functions validates given value errordocument * refs #267 * * @param string $errdoc * @param bool $throw_exception * * @return string error-document-string * */ private function correcterrordocument(string $errdoc, $throw_exception = false) { (trim($errdoc) != '') { // url ((strtoupper(substr($errdoc, 0, 5)) != 'http:' &amp;&amp; strtoupper(substr($errdoc, 0, 6)) != 'https:') || !validate::validateurl($errdoc)) { // file (substr($errdoc, 0, 1) != '"') { $errdoc = filedir::makecorrectfile($errdoc); // apache needs starting-slash (starting domains-docroot) (!substr($errdoc, 0, 1) == '/') { $errdoc = '/' . $errdoc; } } elseif (preg_match('/^"([^\r\n\t\f\0"]+)"$/', $errdoc)) { // string (check ending ") // string work lighty (settings::get('system.webserver') == 'lighttpd') { response::standarderror('stringerrordocumentnotvalidforlighty', '', $throw_exception); } } else { response::standarderror('invaliderrordocumentvalue', '', $throw_exception); } } else { (settings::get('system.webserver') == 'lighttpd') { response::standarderror('urlerrordocumentnotvalidforlighty', '', $throw_exception); } } } return trim($errdoc); } /** * return directory-protection entry id * * @param int $id * id dir-protection entry * * @access admin, customer * @return string json-encoded array * @throws exception */ public function get() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras')) { throw new exception("you cannot access resource", 405); } $id = $this-&gt;getparam('id', true, 0); $params = []; ($this-&gt;isadmin()) { ($this-&gt;getuserdetail('customers_see_all') == false) { // reseller admin cannot see customers, need check // whether database belongs one customers $_custom_list_result = $this-&gt;apicall('customers.listing'); $custom_list_result = $_custom_list_result['list']; $customer_ids = []; foreach ($custom_list_result $customer) { $customer_ids[] = $customer['customerid']; } $result_stmt = database::prepare(" select * `" . table_panel_htaccess . "` `customerid` (" . implode(", ", $customer_ids) . ") `id` = :id "); } else { $result_stmt = database::prepare(" select * `" . table_panel_htaccess . "` `id` = :id "); } } else { (settings::isinlist('panel.customer_hide_options', 'extras.pathoptions')) { throw new exception("you cannot access resource", 405); } $result_stmt = database::prepare(" select * `" . table_panel_htaccess . "` `customerid` = :customerid `id` = :id "); $params['customerid'] = $this-&gt;getuserdetail('customerid'); } $params['id'] = $id; $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] get directory options '" . $result['path'] . "'"); return $this-&gt;response($result); } $key = "id #" . $id; throw new exception("directory option " . $key . " could found", 404); } /** * update options given directory id * * @param int $id * id dir-protection entry * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param bool $options_indexes * optional, activate directory-listing path, default 0 (false) * @param bool $options_cgi * optional, allow perl/cgi execution, default 0 (false) * @param string $error404path * optional, custom 404 error string/file * @param string $error403path * optional, custom 403 error string/file * @param string $error500path * optional, custom 500 error string/file * * @access admin, customer * @return string json-encoded array * @throws exception */ public function update() { $id = $this-&gt;getparam('id', true, 0); // validation $result = $this-&gt;apicall('diroptions.get', [ 'id' =&gt; $id ]); // get needed customer info reduce email-address-counter one $customer = $this-&gt;getcustomerdata(); // parameters $options_indexes = $this-&gt;getboolparam('options_indexes', true, $result['options_indexes']); $options_cgi = $this-&gt;getboolparam('options_cgi', true, $result['options_cgi']); $error404path = $this-&gt;getparam('error404path', true, $result['error404path']); $error403path = $this-&gt;getparam('error403path', true, $result['error403path']); $error500path = $this-&gt;getparam('error500path', true, $result['error500path']); (!empty($error404path)) { $error404path = $this-&gt;correcterrordocument($error404path, true); } (!empty($error403path)) { $error403path = $this-&gt;correcterrordocument($error403path, true); } (!empty($error500path)) { $error500path = $this-&gt;correcterrordocument($error500path, true); } (($options_indexes != $result['options_indexes']) || ($error404path != $result['error404path']) || ($error403path != $result['error403path']) || ($error500path != $result['error500path']) || ($options_cgi != $result['options_cgi'])) { cronjob::inserttask(taskid::rebuild_vhost); $stmt = database::prepare(" update `" . table_panel_htaccess . "` set `options_indexes` = :options_indexes, `error404path` = :error404path, `error403path` = :error403path, `error500path` = :error500path, `options_cgi` = :options_cgi `customerid` = :customerid `id` = :id "); $params = [ "customerid" =&gt; $customer['customerid'], "options_indexes" =&gt; $options_indexes, "error403path" =&gt; $error403path, "error404path" =&gt; $error404path, "error500path" =&gt; $error500path, "options_cgi" =&gt; $options_cgi, "id" =&gt; $id ]; database::pexecute($stmt, $params, true, true); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] edited directory options '" . str_replace($customer['documentroot'], '/', $result['path']) . "'"); } $result = $this-&gt;apicall('diroptions.get', [ 'id' =&gt; $id ]); return $this-&gt;response($result); } /** * list directory-options, called admin, list directory-options customers allowed * view, specify id loginname one specific customer * * @param int $customerid * optional, admin-only, select directory-protections specific customer id * @param string $loginname * optional, admin-only, select directory-protections specific customer loginname * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin, customer * @return string json-encoded array count|list * @throws exception */ public function listing() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras')) { throw new exception("you cannot access resource", 405); } $customer_ids = $this-&gt;getallowedcustomerids('extras.pathoptions'); $result = []; $query_fields = []; $result_stmt = database::prepare(" select * `" . table_panel_htaccess . "` `customerid` (" . implode(', ', $customer_ids) . ")" . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); database::pexecute($result_stmt, $query_fields, true, true); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $result[] = $row; } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] list directory-options"); return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } /** * returns total number accessible directory options * * @param int $customerid * optional, admin-only, select directory-protections specific customer id * @param string $loginname * optional, admin-only, select directory-protections specific customer loginname * * @access admin, customer * @return string json-encoded response message * @throws exception */ public function listingcount() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras')) { throw new exception("you cannot access resource", 405); } $customer_ids = $this-&gt;getallowedcustomerids('extras.pathoptions'); $result = []; $result_stmt = database::prepare(" select count(*) num_htaccess `" . table_panel_htaccess . "` `customerid` (" . implode(', ', $customer_ids) . ") "); $result = database::pexecute_first($result_stmt, null, true, true); ($result) { return $this-&gt;response($result['num_htaccess']); } return $this-&gt;response(0); } /** * delete directory-options id * * @param int $id * id dir-protection entry * * @access admin, customer * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras')) { throw new exception("you cannot access resource", 405); } $id = $this-&gt;getparam('id'); ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras.pathoptions')) { throw new exception("you cannot access resource", 405); } // get directory-option $result = $this-&gt;apicall('diroptions.get', [ 'id' =&gt; $id ]); ($this-&gt;isadmin()) { // get customer-data $customer_data = $this-&gt;apicall('customers.get', [ 'id' =&gt; $result['customerid'] ]); } else { $customer_data = $this-&gt;getuserdata(); } // remove symlink folder suexecpath? ((int)settings::get('perl.suexecworkaround') == 1) { $loginname = $customer_data['loginname']; $suexecpath = filedir::makecorrectdir(settings::get('perl.suexecpath') . '/' . $loginname . '/' . md5($result['path']) . '/'); $perlsymlink = filedir::makecorrectfile($result['path'] . '/cgi-bin'); // remove symlink (file_exists($perlsymlink)) { filedir::safe_exec('rm -f ' . escapeshellarg($perlsymlink)); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_debug, "[api] deleted suexecworkaround symlink '" . $perlsymlink . "'"); } // remove folder suexec-path (file_exists($suexecpath)) { filedir::safe_exec('rm -rf ' . escapeshellarg($suexecpath)); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_debug, "[api] deleted suexecworkaround path '" . $suexecpath . "'"); } } $stmt = database::prepare(" delete `" . table_panel_htaccess . "` `customerid`= :customerid `id`= :id "); database::pexecute($stmt, [ "customerid" =&gt; $customer_data['customerid'], "id" =&gt; $id ], true, true); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] deleted directory-option '" . str_replace($customer_data['documentroot'], '/', $result['path']) . "'"); cronjob::inserttask(taskid::rebuild_vhost); return $this-&gt;response($result); } }</file><file name="lib/Froxlor/Api/Commands/DirProtections.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\system\cronjob; use froxlor\system\crypt; use froxlor\ui\response; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class dirprotections extends apicommand implements resourceentity { /** * add htaccess protection given directory * * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param string $path * @param string $username * @param string $directory_password * @param string $directory_authname * optional name/description protection * * @access admin, customer * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras')) { throw new exception("you cannot access resource", 405); } ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras.directoryprotection')) { throw new exception("you cannot access resource", 405); } // get needed customer info reduce email-address-counter one $customer = $this-&gt;getcustomerdata(); // required parameters $path = $this-&gt;getparam('path'); $username = $this-&gt;getparam('username'); $password = $this-&gt;getparam('directory_password'); // parameters $authname = $this-&gt;getparam('directory_authname', true, ''); // validation $path = filedir::makecorrectdir(validate::validate($path, 'path', validate::regex_dir, '', [], true)); $path = filedir::makecorrectdir($customer['documentroot'] . '/' . $path, $customer['documentroot']); $username = validate::validate($username, 'username', '/^[a-za-z0-9][a-za-z0-9\-_]+\$?$/', '', [], true); $authname = validate::validate($authname, 'directory_authname', '/^[a-za-z0-9][a-za-z0-9\-_ ]+\$?$/', '', [], true); $password = validate::validate($password, 'password', '', '', [], true); $password = crypt::validatepassword($password, true); // check duplicate usernames path $username_path_check_stmt = database::prepare(" select `id`, `username`, `path` `" . table_panel_htpasswds . "` `username`= :username `path`= :path `customerid`= :customerid "); $params = [ "username" =&gt; $username, "path" =&gt; $path, "customerid" =&gt; $customer['customerid'] ]; $username_path_check = database::pexecute_first($username_path_check_stmt, $params, true, true); $password_enc = crypt::makecryptpassword($password, true); // duplicate check ($username_path_check &amp;&amp; $username_path_check['username'] == $username &amp;&amp; $username_path_check['path'] == $path) { response::standarderror('userpathcombinationdupe', '', true); } elseif ($password == $username) { response::standarderror('passwordshouldnotbeusername', '', true); } // insert entry $stmt = database::prepare(" insert `" . table_panel_htpasswds . "` set `customerid` = :customerid, `username` = :username, `password` = :password, `path` = :path, `authname` = :authname "); $params = [ "customerid" =&gt; $customer['customerid'], "username" =&gt; $username, "password" =&gt; $password_enc, "path" =&gt; $path, "authname" =&gt; $authname ]; database::pexecute($stmt, $params, true, true); $id = database::lastinsertid(); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] added directory-protection '" . $username . " (" . $path . ")'"); cronjob::inserttask(taskid::rebuild_vhost); $result = $this-&gt;apicall('dirprotections.get', [ 'id' =&gt; $id ]); return $this-&gt;response($result); } /** * return directory-protection entry either id username * * @param int $id * optional, directory-protection-id * @param string $username * optional, username * * @access admin, customer * @return string json-encoded array * @throws exception */ public function get() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras')) { throw new exception("you cannot access resource", 405); } $id = $this-&gt;getparam('id', true, 0); $un_optional = $id &gt; 0; $username = $this-&gt;getparam('username', $un_optional, ''); $params = []; ($this-&gt;isadmin()) { ($this-&gt;getuserdetail('customers_see_all') == false) { // reseller admin cannot see customers, need check // whether database belongs one customers $_custom_list_result = $this-&gt;apicall('customers.listing'); $custom_list_result = $_custom_list_result['list']; $customer_ids = []; foreach ($custom_list_result $customer) { $customer_ids[] = $customer['customerid']; } $result_stmt = database::prepare(" select * `" . table_panel_htpasswds . "` `customerid` (" . implode(", ", $customer_ids) . ") (`id` = :idun `username` = :idun) "); } else { $result_stmt = database::prepare(" select * `" . table_panel_htpasswds . "` (`id` = :idun `username` = :idun) "); } } else { (settings::isinlist('panel.customer_hide_options', 'extras.directoryprotection')) { throw new exception("you cannot access resource", 405); } $result_stmt = database::prepare(" select * `" . table_panel_htpasswds . "` `customerid` = :customerid (`id` = :idun `username` = :idun) "); $params['customerid'] = $this-&gt;getuserdetail('customerid'); } $params['idun'] = ($id &lt;= 0 ? $username : $id); $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] get directory protection '" . $result['path'] . "'"); return $this-&gt;response($result); } $key = ($id &gt; 0 ? "id #" . $id : "username '" . $username . "'"); throw new exception("directory protection " . $key . " could found", 404); } /** * update htaccess protection given directory * * @param int $id * optional directory-protection-id * @param string $username * optional, username * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param string $directory_password * optional, leave empty change * @param string $directory_authname * optional name/description protection * * @access admin, customer * @return string json-encoded array * @throws exception */ public function update() { $id = $this-&gt;getparam('id', true, 0); $un_optional = $id &gt; 0; $username = $this-&gt;getparam('username', $un_optional, ''); // validation $result = $this-&gt;apicall('dirprotections.get', [ 'id' =&gt; $id, 'username' =&gt; $username ]); $id = $result['id']; // parameters $password = $this-&gt;getparam('directory_password', true, ''); $authname = $this-&gt;getparam('directory_authname', true, $result['authname']); // get needed customer info $customer = $this-&gt;getcustomerdata(); // validation $authname = validate::validate($authname, 'directory_authname', '/^[a-za-z0-9][a-za-z0-9\-_ ]+\$?$/', '', [], true); $password = validate::validate($password, 'password', '', '', [], true); $password = crypt::validatepassword($password, true); $upd_query = ""; $upd_params = [ "id" =&gt; $result['id'], "cid" =&gt; $customer['customerid'] ]; (!empty($password)) { ($password == $result['username']) { response::standarderror('passwordshouldnotbeusername', '', true); } $password_enc = crypt::makecryptpassword($password, true); $upd_query .= "`password`= :password_enc"; $upd_params['password_enc'] = $password_enc; } ($authname != $result['authname']) { (!empty($upd_query)) { $upd_query .= ", "; } $upd_query .= "`authname` = :authname"; $upd_params['authname'] = $authname; } // build update query (!empty($upd_query)) { $upd_stmt = database::prepare(" update `" . table_panel_htpasswds . "` set " . $upd_query . " `id` = :id `customerid`= :cid "); database::pexecute($upd_stmt, $upd_params, true, true); cronjob::inserttask(taskid::rebuild_vhost); } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] updated directory-protection '" . $result['username'] . " (" . $result['path'] . ")'"); $result = $this-&gt;apicall('dirprotections.get', [ 'id' =&gt; $result['id'] ]); return $this-&gt;response($result); } /** * list directory-protections, called admin, list directory-protections customers * allowed view, specify id loginname one specific customer * * @param int $customerid * optional, admin-only, select directory-protections specific customer id * @param string $loginname * optional, admin-only, select directory-protections specific customer loginname * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin, customer * @return string json-encoded array count|list * @throws exception */ public function listing() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras')) { throw new exception("you cannot access resource", 405); } $customer_ids = $this-&gt;getallowedcustomerids('extras.directoryprotection'); $result = []; $query_fields = []; $result_stmt = database::prepare(" select * `" . table_panel_htpasswds . "` `customerid` (" . implode(', ', $customer_ids) . ")" . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); database::pexecute($result_stmt, $query_fields, true, true); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $result[] = $row; } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] list directory-protections"); return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } /** * returns total number accessible directory protections * * @param int $customerid * optional, admin-only, select directory-protections specific customer id * @param string $loginname * optional, admin-only, select directory-protections specific customer loginname * * @access admin, customer * @return string json-encoded response message * @throws exception */ public function listingcount() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras')) { throw new exception("you cannot access resource", 405); } $customer_ids = $this-&gt;getallowedcustomerids('extras.directoryprotection'); $result = []; $result_stmt = database::prepare(" select count(*) num_htpasswd `" . table_panel_htpasswds . "` `customerid` (" . implode(', ', $customer_ids) . ") "); $result = database::pexecute_first($result_stmt, null, true, true); ($result) { return $this-&gt;response($result['num_htpasswd']); } return $this-&gt;response(0); } /** * delete directory-protection either id username * * @param int $id * optional, directory-protection-id * @param string $username * optional, username * * @access admin, customer * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras')) { throw new exception("you cannot access resource", 405); } $id = $this-&gt;getparam('id', true, 0); $un_optional = $id &gt; 0; $username = $this-&gt;getparam('username', $un_optional, ''); ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras.directoryprotection')) { throw new exception("you cannot access resource", 405); } // get directory protection $result = $this-&gt;apicall('dirprotections.get', [ 'id' =&gt; $id, 'username' =&gt; $username ]); $id = $result['id']; ($this-&gt;isadmin()) { // get customer-data $customer_data = $this-&gt;apicall('customers.get', [ 'id' =&gt; $result['customerid'] ]); } else { $customer_data = $this-&gt;getuserdata(); } $stmt = database::prepare(" delete `" . table_panel_htpasswds . "` `customerid`= :customerid `id`= :id "); database::pexecute($stmt, [ "customerid" =&gt; $customer_data['customerid'], "id" =&gt; $id ]); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_warning, "[api] deleted htpasswd '" . $result['username'] . " (" . $result['path'] . ")'"); cronjob::inserttask(taskid::rebuild_vhost); return $this-&gt;response($result); } }</file><file name="lib/Froxlor/Api/Commands/HostingPlans.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class hostingplans extends apicommand implements resourceentity { /** * list available hosting plans * * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin * @return string json-encoded array count|list * @throws exception */ public function listing() { ($this-&gt;isadmin()) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_info, "[api] list hosting-plans"); $query_fields = []; $result_stmt = database::prepare(" select p.*, a.loginname adminname `" . table_panel_plans . "` p, `" . table_panel_admins . "` `p`.`adminid` = `a`.`adminid`" . ($this-&gt;getuserdetail('customers_see_all') ? '' : " `p`.`adminid` = :adminid ") . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); $params = []; ($this-&gt;getuserdetail('customers_see_all') == '0') { $params['adminid'] = $this-&gt;getuserdetail('adminid'); } $params = array_merge($params, $query_fields); database::pexecute($result_stmt, $params, true, true); $result = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $result[] = $row; } return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } throw new exception("not allowed execute given command.", 403); } /** * returns total number accessible hosting plans * * @access admin * @return string json-encoded response message * @throws exception */ public function listingcount() { ($this-&gt;isadmin()) { $result_stmt = database::prepare(" select count(*) num_plans `" . table_panel_plans . "` p, `" . table_panel_admins . "` `p`.`adminid` = `a`.`adminid`" . ($this-&gt;getuserdetail('customers_see_all') ? '' : " `p`.`adminid` = :adminid ")); $params = []; ($this-&gt;getuserdetail('customers_see_all') == '0') { $params['adminid'] = $this-&gt;getuserdetail('adminid'); } $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { return $this-&gt;response($result['num_plans']); } return $this-&gt;response(0); } throw new exception("not allowed execute given command.", 403); } /** * add new hosting-plan * * @param string $name * name plan * @param string $description * optional, description hosting-plan * @param int $diskspace * optional disk-space available customer mb, default 0 * @param bool $diskspace_ul * optional, whether customer unlimited diskspace, default 0 (false) * @param int $traffic * optional traffic available customer gb, default 0 * @param bool $traffic_ul * optional, whether customer unlimited traffic, default 0 (false) * @param int $subdomains * optional amount subdomains available customer, default 0 * @param bool $subdomains_ul * optional, whether customer unlimited subdomains, default 0 (false) * @param int $emails * optional amount emails available customer, default 0 * @param bool $emails_ul * optional, whether customer unlimited emails, default 0 (false) * @param int $email_accounts * optional amount email-accounts available customer, default 0 * @param bool $email_accounts_ul * optional, whether customer unlimited email-accounts, default 0 (false) * @param int $email_forwarders * optional amount email-forwarders available customer, default 0 * @param bool $email_forwarders_ul * optional, whether customer unlimited email-forwarders, default 0 (false) * @param int $email_quota * optional size email-quota available customer mb, default system-setting mail_quota * @param bool $email_quota_ul * optional, whether customer unlimited email-quota, default 0 (false) * @param bool $email_imap * optional, whether allow imap access, default 0 (false) * @param bool $email_pop3 * optional, whether allow pop3 access, default 0 (false) * @param int $ftps * optional amount ftp-accounts available customer, default 0 * @param bool $ftps_ul * optional, whether customer unlimited ftp-accounts, default 0 (false) * @param int $mysqls * optional amount mysql-databases available customer, default 0 * @param bool $mysqls_ul * optional, whether customer unlimited mysql-databases, default 0 (false) * @param bool $phpenabled * optional, whether allow usage php, default 0 (false) * @param array $allowed_phpconfigs * optional, array ids php-config customer allowed use, default empty (none) * @param bool $perlenabled * optional, whether allow usage perl/cgi, default 0 (false) * @param bool $dnsenabled * optional, whether allow usage dns editor (requires activated nameserver settings), * default 0 (false) * @param bool $logviewenabled * optional, whether allow access webserver access/error-logs, default 0 (false) * * @access admin * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin()) { $name = $this-&gt;getparam('name'); $description = $this-&gt;getparam('description', true, ''); $value_arr = []; $value_arr['diskspace'] = $this-&gt;getulparam('diskspace', 'diskspace_ul', true, 0); $value_arr['traffic'] = $this-&gt;getulparam('traffic', 'traffic_ul', true, 0); $value_arr['subdomains'] = $this-&gt;getulparam('subdomains', 'subdomains_ul', true, 0); $value_arr['emails'] = $this-&gt;getulparam('emails', 'emails_ul', true, 0); $value_arr['email_accounts'] = $this-&gt;getulparam('email_accounts', 'email_accounts_ul', true, 0); $value_arr['email_forwarders'] = $this-&gt;getulparam('email_forwarders', 'email_forwarders_ul', true, 0); $value_arr['email_quota'] = $this-&gt;getulparam('email_quota', 'email_quota_ul', true, settings::get('system.mail_quota')); $value_arr['email_imap'] = $this-&gt;getboolparam('email_imap', true, 0); $value_arr['email_pop3'] = $this-&gt;getboolparam('email_pop3', true, 0); $value_arr['ftps'] = $this-&gt;getulparam('ftps', 'ftps_ul', true, 0); $value_arr['mysqls'] = $this-&gt;getulparam('mysqls', 'mysqls_ul', true, 0); $value_arr['phpenabled'] = $this-&gt;getboolparam('phpenabled', true, 0); $p_allowed_phpconfigs = $this-&gt;getparam('allowed_phpconfigs', true, []); $value_arr['perlenabled'] = $this-&gt;getboolparam('perlenabled', true, 0); $value_arr['dnsenabled'] = $this-&gt;getboolparam('dnsenabled', true, 0); $value_arr['logviewenabled'] = $this-&gt;getboolparam('logviewenabled', true, 0); // validation $name = validate::validate(trim($name), 'name', validate::regex_desc_text, '', [], true); $description = validate::validate(str_replace("\r\n", "\n", $description), 'description', validate::regex_desc_text); (settings::get('system.mail_quota_enabled') != '1') { $value_arr['email_quota'] = -1; } $value_arr['allowed_phpconfigs'] = []; (!empty($p_allowed_phpconfigs) &amp;&amp; is_array($p_allowed_phpconfigs)) { foreach ($p_allowed_phpconfigs $allowed_phpconfig) { $allowed_phpconfig = intval($allowed_phpconfig); $value_arr['allowed_phpconfigs'][] = $allowed_phpconfig; } } $value_arr['allowed_phpconfigs'] = array_map('intval', $value_arr['allowed_phpconfigs']); $ins_stmt = database::prepare(" insert `" . table_panel_plans . "` set `adminid` = :adminid, `name` = :name, `description` = :desc, `value` = :valuearr, `ts` = unix_timestamp(); "); $ins_data = [ 'adminid' =&gt; $this-&gt;getuserdetail('adminid'), 'name' =&gt; $name, 'desc' =&gt; $description, 'valuearr' =&gt; json_encode($value_arr) ]; database::pexecute($ins_stmt, $ins_data, true, true); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] added hosting-plan '" . $name . "'"); $result = $this-&gt;apicall('hostingplans.get', [ 'planname' =&gt; $name ]); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } /** * return hosting-plan entry either id plan-name * * @param int $id * optional, hosting-plan-id * @param string $planname * optional, hosting-plan-name * * @access admin * @return string json-encoded array * @throws exception */ public function get() { ($this-&gt;isadmin()) { $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $planname = $this-&gt;getparam('planname', $dn_optional, ''); $result_stmt = database::prepare(" select * `" . table_panel_plans . "` " . ($id &gt; 0 ? "`id` = :iddn" : "`name` = :iddn") . ($this-&gt;getuserdetail('customers_see_all') ? '' : " `adminid` = :adminid")); $params = [ 'iddn' =&gt; ($id &lt;= 0 ? $planname : $id) ]; ($this-&gt;getuserdetail('customers_see_all') == '0') { $params['adminid'] = $this-&gt;getuserdetail('adminid'); } $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_info, "[api] get hosting-plan '" . $result['name'] . "'"); return $this-&gt;response($result); } $key = ($id &gt; 0 ? "id #" . $id : "planname '" . $planname . "'"); throw new exception("hosting-plan " . $key . " could found", 404); } throw new exception("not allowed execute given command.", 403); } /** * update hosting-plan either id plan-name * * @param int $id * optional hosting-plan-id * @param string $planname * optional hosting-plan-name * @param string $name * optional name plan * @param string $description * optional description hosting-plan * @param int $diskspace * optional disk-space available customer mb, default 0 * @param bool $diskspace_ul * optional, whether customer unlimited diskspace, default 0 (false) * @param int $traffic * optional traffic available customer gb, default 0 * @param bool $traffic_ul * optional, whether customer unlimited traffic, default 0 (false) * @param int $subdomains * optional amount subdomains available customer, default 0 * @param bool $subdomains_ul * optional, whether customer unlimited subdomains, default 0 (false) * @param int $emails * optional amount emails available customer, default 0 * @param bool $emails_ul * optional, whether customer unlimited emails, default 0 (false) * @param int $email_accounts * optional amount email-accounts available customer, default 0 * @param bool $email_accounts_ul * optional, whether customer unlimited email-accounts, default 0 (false) * @param int $email_forwarders * optional amount email-forwarders available customer, default 0 * @param bool $email_forwarders_ul * optional, whether customer unlimited email-forwarders, default 0 (false) * @param int $email_quota * optional size email-quota available customer mb, default system-setting mail_quota * @param bool $email_quota_ul * optional, whether customer unlimited email-quota, default 0 (false) * @param bool $email_imap * optional, whether allow imap access, default 0 (false) * @param bool $email_pop3 * optional, whether allow pop3 access, default 0 (false) * @param int $ftps * optional amount ftp-accounts available customer, default 0 * @param bool $ftps_ul * optional, whether customer unlimited ftp-accounts, default 0 (false) * @param int $mysqls * optional amount mysql-databases available customer, default 0 * @param bool $mysqls_ul * optional, whether customer unlimited mysql-databases, default 0 (false) * @param bool $phpenabled * optional, whether allow usage php, default 0 (false) * @param array $allowed_phpconfigs * optional, array ids php-config customer allowed use, default empty (none) * @param bool $perlenabled * optional, whether allow usage perl/cgi, default 0 (false) * @param bool $dnsenabled * optional, either allow usage dns editor (requires activated nameserver settings), * default 0 (false) * @param bool $logviewenabled * optional, either allow access webserver access/error-logs, default 0 (false) * * @access admin * @return string json-encoded array * @throws exception */ public function update() { ($this-&gt;isadmin()) { // parameters $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $planname = $this-&gt;getparam('planname', $dn_optional, ''); // get requested hosting-plan $result = $this-&gt;apicall('hostingplans.get', [ 'id' =&gt; $id, 'planname' =&gt; $planname ]); $id = $result['id']; $result['value'] = json_decode($result['value'], true); foreach ($result['value'] $index =&gt; $value) { $result[$index] = $value; } $name = $this-&gt;getparam('name', true, $result['name']); $description = $this-&gt;getparam('description', true, $result['description']); $value_arr = []; $value_arr['diskspace'] = $this-&gt;getulparam('diskspace', 'diskspace_ul', true, $result['diskspace']); $value_arr['traffic'] = $this-&gt;getulparam('traffic', 'traffic_ul', true, $result['traffic']); $value_arr['subdomains'] = $this-&gt;getulparam('subdomains', 'subdomains_ul', true, $result['subdomains']); $value_arr['emails'] = $this-&gt;getulparam('emails', 'emails_ul', true, $result['emails']); $value_arr['email_accounts'] = $this-&gt;getulparam('email_accounts', 'email_accounts_ul', true, $result['email_accounts']); $value_arr['email_forwarders'] = $this-&gt;getulparam('email_forwarders', 'email_forwarders_ul', true, $result['email_forwarders']); $value_arr['email_quota'] = $this-&gt;getulparam('email_quota', 'email_quota_ul', true, $result['email_quota']); $value_arr['email_imap'] = $this-&gt;getparam('email_imap', true, $result['email_imap']); $value_arr['email_pop3'] = $this-&gt;getparam('email_pop3', true, $result['email_pop3']); $value_arr['ftps'] = $this-&gt;getulparam('ftps', 'ftps_ul', true, $result['ftps']); $value_arr['mysqls'] = $this-&gt;getulparam('mysqls', 'mysqls_ul', true, $result['mysqls']); $value_arr['phpenabled'] = $this-&gt;getboolparam('phpenabled', true, $result['phpenabled']); $p_allowed_phpconfigs = $this-&gt;getparam('allowed_phpconfigs', true, $result['allowed_phpconfigs']); $value_arr['perlenabled'] = $this-&gt;getboolparam('perlenabled', true, $result['perlenabled']); $value_arr['dnsenabled'] = $this-&gt;getboolparam('dnsenabled', true, $result['dnsenabled']); $value_arr['logviewenabled'] = $this-&gt;getboolparam('logviewenabled', true, $result['logviewenabled']); // validation $name = validate::validate(trim($name), 'name', validate::regex_desc_text, '', [], true); $description = validate::validate(str_replace("\r\n", "\n", $description), 'description', validate::regex_desc_text); (settings::get('system.mail_quota_enabled') != '1') { $value_arr['email_quota'] = -1; } (empty($name)) { $name = $result['name']; } $value_arr['allowed_phpconfigs'] = []; (!empty($p_allowed_phpconfigs) &amp;&amp; is_array($p_allowed_phpconfigs)) { foreach ($p_allowed_phpconfigs $allowed_phpconfig) { $allowed_phpconfig = intval($allowed_phpconfig); $value_arr['allowed_phpconfigs'][] = $allowed_phpconfig; } } $value_arr['allowed_phpconfigs'] = array_map('intval', $value_arr['allowed_phpconfigs']); $upd_stmt = database::prepare(" update `" . table_panel_plans . "` set `name` = :name, `description` = :desc, `value` = :valuearr, `ts` = unix_timestamp() `id` = :id "); $update_data = [ 'name' =&gt; $name, 'desc' =&gt; $description, 'valuearr' =&gt; json_encode($value_arr), 'id' =&gt; $id ]; database::pexecute($upd_stmt, $update_data, true, true); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] updated hosting-plan '" . $result['name'] . "'"); return $this-&gt;response($update_data); } throw new exception("not allowed execute given command.", 403); } /** * delete hosting-plan either id plan-name * * @param int $id * optional hosting-plan-id * @param string $planname * optional hosting-plan-name * * @access admin * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin()) { $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $planname = $this-&gt;getparam('planname', $dn_optional, ''); // get requested hosting-plan $result = $this-&gt;apicall('hostingplans.get', [ 'id' =&gt; $id, 'planname' =&gt; $planname ]); $id = $result['id']; $del_stmt = database::prepare(" delete `" . table_panel_plans . "` `id` = :id "); database::pexecute($del_stmt, [ 'id' =&gt; $id ], true, true); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] deleted hosting-plan '" . $result['name'] . "'"); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } }</file><file name="lib/Froxlor/Api/Commands/DataDump.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\system\cronjob; use froxlor\ui\response; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class datadump extends apicommand implements resourceentity { /** * add new data dump job * * @param string $path * path store dumped data * @param string $pgp_public_key * optional pgp public key encrypt archive, default empty * @param bool $dump_dbs * optional whether include databases, default 0 (false) * @param bool $dump_mail * optional whether include mail-data, default 0 (false) * @param bool $dump_web * optional whether incoude web-data, default 0 (false) * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * * @access admin, customer * @return string json-encoded array * @throws exception */ public function add() { $this-&gt;validateaccess(); // required parameter $path = $this-&gt;getparam('path'); // parameter $pgp_public_key = $this-&gt;getparam('pgp_public_key', true, ''); $dump_dbs = $this-&gt;getboolparam('dump_dbs', true, 0); $dump_mail = $this-&gt;getboolparam('dump_mail', true, 0); $dump_web = $this-&gt;getboolparam('dump_web', true, 0); // get customer data $customer = $this-&gt;getcustomerdata(); // validation $path = filedir::makecorrectdir(validate::validate($path, 'path', '', '', [], true)); $userpath = $path; $path = filedir::makecorrectdir($customer['documentroot'] . '/' . $path); // path cannot customers docroot ($path == filedir::makecorrectdir($customer['documentroot'])) { response::standarderror('dumpfoldercannotbedocroot', '', true); } // pgp public key validation (!empty($pgp_public_key)) { // check gnupg extension loaded (!extension_loaded('gnupg')) { response::standarderror('gnupgextensionnotavailable', '', true); } // check pgp public key valid key putenv('gnupghome='.sys_get_temp_dir()); (gnupg_import(gnupg_init(), $pgp_public_key) === false) { response::standarderror('invalidpgppublickey', '', true); } } ($dump_dbs != '1') { $dump_dbs = '0'; } ($dump_mail != '1') { $dump_mail = '0'; } ($dump_web != '1') { $dump_web = '0'; } $task_data = [ 'customerid' =&gt; $customer['customerid'], 'uid' =&gt; $customer['guid'], 'gid' =&gt; $customer['guid'], 'loginname' =&gt; $customer['loginname'], 'destdir' =&gt; $path, 'pgp_public_key' =&gt; $pgp_public_key, 'dump_dbs' =&gt; $dump_dbs, 'dump_mail' =&gt; $dump_mail, 'dump_web' =&gt; $dump_web ]; // schedule export job cronjob::inserttask(taskid::create_customer_datadump, $task_data); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] added customer data export job '" . $customer['loginname'] . "'. target directory: " . $userpath); return $this-&gt;response($task_data); } /** * check whether data dump enabled systemwide accessible customer (hide_options) * * @throws exception */ private function validateaccess() { (settings::get('system.exportenabled') != 1) { throw new exception("you cannot access resource", 405); } ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras')) { throw new exception("you cannot access resource", 405); } ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'extras.export')) { throw new exception("you cannot access resource", 405); } } /** * cannot get planned data export. * try datadump.listing() */ public function get() { throw new exception('you cannot get planned data export. try datadump.listing()', 303); } /** * cannot update planned data export. * need delete re-add it. */ public function update() { throw new exception('you cannot update planned data export. need delete re-add it.', 303); } /** * list planned data export jobs, called admin, list planned data export jobs customers * allowed view, specify id loginname one specific customer * * @param int $customerid * optional, admin-only, select data export jobs specific customer id * @param string $loginname * optional, admin-only, select data export jobs specific customer loginname * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin, customer * @return string json-encoded array count|list * @throws exception */ public function listing() { $this-&gt;validateaccess(); $customer_ids = $this-&gt;getallowedcustomerids('extras.export'); // check whether data export job customer $query_fields = []; $sel_stmt = database::prepare("select * `" . table_panel_tasks . "` `type` = '20'" . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); database::pexecute($sel_stmt, $query_fields, true, true); $result = []; ($entry = $sel_stmt-&gt;fetch(pdo::fetch_assoc)) { $entry['data'] = json_decode($entry['data'], true); (in_array($entry['data']['customerid'], $customer_ids)) { $result[] = $entry; } } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] list customer data dump jobs"); return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } /** * returns total number planned data exports * * @param int $customerid * optional, admin-only, select data export jobs specific customer id * @param string $loginname * optional, admin-only, select data export jobs specific customer loginname * * @access admin, customer * @return string json-encoded response message * @throws exception */ public function listingcount() { $this-&gt;validateaccess(); $customer_ids = $this-&gt;getallowedcustomerids('extras.export'); // check whether data export job customer $result_count = 0; $sel_stmt = database::prepare("select * `" . table_panel_tasks . "` `type` = '20'"); database::pexecute($sel_stmt, null, true, true); ($entry = $sel_stmt-&gt;fetch(pdo::fetch_assoc)) { $entry['data'] = json_decode($entry['data'], true); (in_array($entry['data']['customerid'], $customer_ids)) { $result_count++; } } return $this-&gt;response($result_count); } /** * delete planned data export jobs id, called admin need specify customerid/loginname * * @param int $job_entry * id data export job * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * * @access admin, customer * @return bool * @throws exception */ public function delete() { // get planned exports $result = $this-&gt;apicall('datadump.listing', $this-&gt;getparamlist()); $entry = $this-&gt;getparam('job_entry'); $customer_ids = $this-&gt;getallowedcustomerids('extras.export'); ($result['count'] &gt; 0 &amp;&amp; $entry &gt; 0) { // prepare statement $del_stmt = database::prepare("delete `" . table_panel_tasks . "` `id` = :tid"); // check correct job foreach ($result['list'] $exportjob) { ($exportjob['id'] == $entry &amp;&amp; in_array($exportjob['data']['customerid'], $customer_ids)) { database::pexecute($del_stmt, [ 'tid' =&gt; $entry ], true, true); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] deleted planned customer data export job #" . $entry); return $this-&gt;response(true); } } } throw new exception('data export job id #' . $entry . ' could found', 404); } }</file><file name="lib/Froxlor/Api/Commands/EmailForwarders.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\idna\idnawrapper; use froxlor\settings; use froxlor\ui\response; use froxlor\validate\validate; /** * @since 0.10.0 */ class emailforwarders extends apicommand implements resourceentity { /** * add new email-forwarder entry given email-address either id email-address * * @param int $id * optional, email-address-id * @param string $emailaddr * optional, email-address add forwarder * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param string $destination * email-address add forwarder * * @access admin,customer * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } ($this-&gt;getuserdetail('email_forwarders_used') &lt; $this-&gt;getuserdetail('email_forwarders') || $this-&gt;getuserdetail('email_forwarders') == '-1') { // parameter $id = $this-&gt;getparam('id', true, 0); $ea_optional = $id &gt; 0; $emailaddr = $this-&gt;getparam('emailaddr', $ea_optional, ''); $destination = $this-&gt;getparam('destination'); // validation $idna_convert = new idnawrapper(); $destination = $idna_convert-&gt;encode($destination); (!empty($emailaddr)) { $idna_convert = new idnawrapper(); $emailaddr = $idna_convert-&gt;encode($emailaddr); } $result = $this-&gt;apicall('emails.get', [ 'id' =&gt; $id, 'emailaddr' =&gt; $emailaddr ]); $id = $result['id']; // current destination array $result['destination_array'] = explode(' ', ($result['destination'] ?? "")); // prepare destination $destination = trim($destination); (!validate::validateemail($destination)) { response::standarderror('destinationiswrong', $destination, true); } elseif ($destination == $result['email']) { response::standarderror('destinationalreadyexistasmail', $destination, true); } elseif (in_array($destination, $result['destination_array'])) { response::standarderror('destinationalreadyexist', $destination, true); } // get needed customer info reduce email-forwarder-counter one $customer = $this-&gt;getcustomerdata('email_forwarders'); // add destination address $result['destination'] .= ' ' . $destination; $stmt = database::prepare(" update `" . table_mail_virtual . "` set `destination` = :dest `customerid`= :cid `id`= :id "); $params = [ "dest" =&gt; filedir::makecorrectdestination($result['destination']), "cid" =&gt; $customer['customerid'], "id" =&gt; $id ]; database::pexecute($stmt, $params, true, true); // update customer usage customers::increaseusage($customer['customerid'], 'email_forwarders_used'); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] added email forwarder '" . $result['email_full'] . "'"); $result = $this-&gt;apicall('emails.get', [ 'emailaddr' =&gt; $result['email_full'] ]); return $this-&gt;response($result); } throw new exception("no resources available", 406); } /** * cannot directly get email forwarder. * try emailforwarders.listing() */ public function get() { throw new exception('you cannot directly get email forwarder. try emailforwarders.listing()', 303); } /** * cannot update email forwarder. * need delete entry create new one. */ public function update() { throw new exception('you cannot update email forwarder. need delete entry create new one.', 303); } /** * list email forwarders given email address * * @param int $id * optional, email-address-id * @param string $emailaddr * optional, email-address delete forwarder * @param int $customerid * optional, admin-only, customer-id * @param string $loginname * optional, admin-only, loginname * * @access admin,customer * @return string json-encoded array count|list * @throws exception */ public function listing() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } // parameter $id = $this-&gt;getparam('id', true, 0); $ea_optional = $id &gt; 0; $emailaddr = $this-&gt;getparam('emailaddr', $ea_optional, ''); // validation $result = $this-&gt;apicall('emails.get', [ 'id' =&gt; $id, 'emailaddr' =&gt; $emailaddr ]); $id = $result['id']; $result['destination'] = explode(' ', $result['destination']); $destination = []; foreach ($result['destination'] $index =&gt; $address) { $destination[] = [ 'id' =&gt; $index, 'address' =&gt; $address ]; } return $this-&gt;response([ 'count' =&gt; count($destination), 'list' =&gt; $destination ]); } /** * count email forwarders given email address * * @param int $id * optional, email-address-id * @param string $emailaddr * optional, email-address delete forwarder * @param int $customerid * optional, admin-only, customer-id * @param string $loginname * optional, admin-only, loginname * * @access admin,customer * @return string json-encoded response message * @throws exception */ public function listingcount() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } // parameter $id = $this-&gt;getparam('id', true, 0); $ea_optional = $id &gt; 0; $emailaddr = $this-&gt;getparam('emailaddr', $ea_optional, ''); // validation $result = $this-&gt;apicall('emails.get', [ 'id' =&gt; $id, 'emailaddr' =&gt; $emailaddr ]); $id = $result['id']; $result['destination'] = explode(' ', $result['destination']); return $this-&gt;response(count($result['destination'])); } /** * delete email-forwarder entry given email-address either id email-address forwarder-id * * @param int $id * optional, email-address-id * @param string $emailaddr * optional, email-address delete forwarder * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param int $forwarderid * id forwarder delete * * @access admin,customer * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } // parameter $id = $this-&gt;getparam('id', true, 0); $ea_optional = $id &gt; 0; $emailaddr = $this-&gt;getparam('emailaddr', $ea_optional, ''); $forwarderid = $this-&gt;getparam('forwarderid'); // validation $result = $this-&gt;apicall('emails.get', [ 'id' =&gt; $id, 'emailaddr' =&gt; $emailaddr ]); $id = $result['id']; $result['destination'] = explode(' ', $result['destination']); (isset($result['destination'][$forwarderid]) &amp;&amp; $result['email'] != $result['destination'][$forwarderid]) { // get needed customer info reduce email-forwarder-counter one $customer = $this-&gt;getcustomerdata(); // unset array unset($result['destination'][$forwarderid]); // rebuild destination-string $result['destination'] = implode(' ', $result['destination']); // update db $stmt = database::prepare(" update `" . table_mail_virtual . "` set `destination` = :dest `customerid`= :cid `id`= :id "); $params = [ "dest" =&gt; filedir::makecorrectdestination($result['destination']), "cid" =&gt; $customer['customerid'], "id" =&gt; $id ]; database::pexecute($stmt, $params, true, true); // update customer usage customers::decreaseusage($customer['customerid'], 'email_forwarders_used'); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] deleted email forwarder '" . $result['email_full'] . "'"); $result = $this-&gt;apicall('emails.get', [ 'emailaddr' =&gt; $result['email_full'] ]); return $this-&gt;response($result); } throw new exception("unknown forwarder id", 404); } }</file><file name="lib/Froxlor/Api/Commands/SubDomains.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\domain\domain; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\idna\idnawrapper; use froxlor\phphelper; use froxlor\settings; use froxlor\system\cronjob; use froxlor\ui\response; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class subdomains extends apicommand implements resourceentity { /** * add new subdomain * * @param string $subdomain * part domain.tld create subdomain * @param string $domain * domainname main-domain * @param int $alias * optional, domain-id domain new domain alias * @param string $path * optional, destination path relative customers-homedir, default customers-homedir * @param string $url * optional, overwrites path value url generate redirect, alternatively use path * parameter also urls * @param int $openbasedir_path * optional, either 0 domains-docroot [default], 1 customers-homedir 2 parent-directory domains-docroot * @param int $phpsettingid * optional, php-settings-id, empty $domain value used * @param int $redirectcode * optional, redirect-code-id table_panel_redirectcodes * @param int $speciallogfile * optional, whether create exclusive web-logfile domain (1) (0) inherit value parentdomain (2, default) * @param bool $sslenabled * optional, whether ssl enabled domain, regardless assigned ssl-ips, default * 1 (true) * @param bool $ssl_redirect * optional, whether generate https-redirect not, default false; requires ssl enabled * @param bool $letsencrypt * optional, whether generate let's encrypt certificate domain, default false; requires * ssl enabled * @param bool $http2 * optional, whether enable http/2 subdomain (requires enabled settings), * default 0 (false) * @param int $hsts_maxage * optional max-age value hsts header, default 0 * @param bool $hsts_sub * optional whether add subdomains hsts header, default 0 * @param bool $hsts_preload * optional whether preload hsts header value, default 0 * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * * @access admin, customer * @return string json-encoded array * @throws exception */ public function add() { (($this-&gt;getuserdetail('subdomains_used') &lt; $this-&gt;getuserdetail('subdomains') || $this-&gt;getuserdetail('subdomains') == '-1') || $this-&gt;isadmin()) { // parameters $subdomain = $this-&gt;getparam('subdomain'); $domain = $this-&gt;getparam('domain'); // optional parameters $aliasdomain = $this-&gt;getparam('alias', true, 0); $path = $this-&gt;getparam('path', true, ''); $url = $this-&gt;getparam('url', true, ''); $openbasedir_path = $this-&gt;getparam('openbasedir_path', true, 0); $phpsettingid = $this-&gt;getparam('phpsettingid', true, 0); $redirectcode = $this-&gt;getparam('redirectcode', true, settings::get('customredirect.default')); $speciallogfile = intval($this-&gt;getparam('speciallogfile', true, 2)); $isemaildomain = $this-&gt;getparam('isemaildomain', true, 0); (settings::get('system.use_ssl')) { $sslenabled = $this-&gt;getboolparam('sslenabled', true, 1); $ssl_redirect = $this-&gt;getboolparam('ssl_redirect', true, 0); $letsencrypt = $this-&gt;getboolparam('letsencrypt', true, 0); $http2 = $this-&gt;getboolparam('http2', true, 0); $hsts_maxage = $this-&gt;getparam('hsts_maxage', true, 0); $hsts_sub = $this-&gt;getboolparam('hsts_sub', true, 0); $hsts_preload = $this-&gt;getboolparam('hsts_preload', true, 0); } else { $sslenabled = 0; $ssl_redirect = 0; $letsencrypt = 0; $http2 = 0; $hsts_maxage = 0; $hsts_sub = 0; $hsts_preload = 0; } // get needed customer info reduce subdomain-usage-counter one $customer = $this-&gt;getcustomerdata('subdomains'); // validation $subdomain = strtolower($subdomain); (substr($subdomain, 0, 4) == 'xn--') { response::standarderror('domain_nopunycode', '', true); } $idna_convert = new idnawrapper(); $subdomain = $idna_convert-&gt;encode(preg_replace([ '/\:(\d)+$/', '/^https?\:\/\//' ], '', validate::validate($subdomain, 'subdomain', '', 'subdomainiswrong', [], true))); // merge two parts together $completedomain = $subdomain . '.' . $domain; (settings::get('system.validate_domain') &amp;&amp; !validate::validatedomain($completedomain)) { response::standarderror([ 'stringiswrong', 'mydomain' ], '', true); } ($completedomain == strtolower(settings::get('system.hostname'))) { response::standarderror('admin_domain_emailsystemhostname', '', true); } // check whether domain already exists $completedomain_stmt = database::prepare(" select * `" . table_panel_domains . "` `domain` = :domain `customerid` = :customerid `email_only` = '0' `caneditdomain` = '1' "); $completedomain_check = database::pexecute_first($completedomain_stmt, [ "domain" =&gt; $completedomain, "customerid" =&gt; $customer['customerid'] ], true, true); ($completedomain_check) { // exception far - domain exists response::standarderror('domainexistalready', $completedomain, true); } // alias domain checked? ($aliasdomain != 0) { // also check ip/port combination same, #176 $aliasdomain_stmt = database::prepare(" select `d`.`id` `" . table_panel_domains . "` `d` , `" . table_panel_customers . "` `c` , `" . table_domaintoip . "` `dip` `d`.`aliasdomain` null `d`.`id` = :id `c`.`standardsubdomain` &lt;&gt; `d`.`id` `d`.`customerid` = :customerid `c`.`customerid` = `d`.`customerid` `d`.`id` = `dip`.`id_domain` `dip`.`id_ipandports` (select `id_ipandports` `" . table_domaintoip . "` `id_domain` = :id ) group `d`.`domain` order `d`.`domain` asc "); $aliasdomain_check = database::pexecute_first($aliasdomain_stmt, [ "id" =&gt; $aliasdomain, "customerid" =&gt; $customer['customerid'] ], true, true); ($aliasdomain_check['id'] != $aliasdomain) { response::standarderror('domainisaliasorothercustomer', '', true); } domain::triggerletsencryptcsrforaliasdestinationdomain($aliasdomain, $this-&gt;logger()); } // validate / correct path/url domain $_doredirect = false; $path = $this-&gt;validatedomaindocumentroot($path, $url, $customer, $completedomain, $_doredirect); ($openbasedir_path &gt; 2 &amp;&amp; $openbasedir_path &lt; 0) { $openbasedir_path = 0; } // get main domain various checks $domain_stmt = database::prepare(" select * `" . table_panel_domains . "` `domain` = :domain `customerid` = :customerid `parentdomainid` = '0' `email_only` = '0' `caneditdomain` = '1' "); $domain_check = database::pexecute_first($domain_stmt, [ "domain" =&gt; $domain, "customerid" =&gt; $customer['customerid'] ], true, true); (!$domain_check) { // given main-domain response::standarderror('maindomainnonexist', $domain, true); } elseif ($subdomain == 'www' &amp;&amp; $domain_check['wwwserveralias'] == '1') { // cannot add 'www' subdomain maindomain generates www-alias response::standarderror('wwwnotallowed', '', true); } elseif ($completedomain_check &amp;&amp; strtolower($completedomain_check['domain']) == strtolower($completedomain)) { // domain already exist main-domain response::standarderror('domainexistalready', $completedomain, true); } elseif ((int)$domain_check['deactivated'] == 1) { // main domain deactivated response::standarderror('maindomaindeactivated', $domain, true); } // allowed, check 'is email domain'-flag ($domain_check['subcanemaildomain'] == '1' || $domain_check['subcanemaildomain'] == '2') { $isemaildomain = intval($isemaildomain); } else { $isemaildomain = $domain_check['subcanemaildomain'] == '3' ? 1 : 0; } ($ssl_redirect != 0) { // ssl-redirect works actually // ssl ip/port assigned domain (domain::domainhassslipport($domain_check['id']) == true) { $ssl_redirect = '1'; $_doredirect = true; } else { response::standarderror('sslredirectonlypossiblewithsslipport', '', true); } } ($letsencrypt != 0) { // let's encrypt works actually // ssl ip/port assigned domain (domain::domainhassslipport($domain_check['id']) == true) { $letsencrypt = '1'; } else { response::standarderror('letsencryptonlypossiblewithsslipport', '', true); } } // validate dns lets encrypt enabled check whether use ($letsencrypt == '1' &amp;&amp; settings::get('system.le_domain_dnscheck') == '1') { $our_ips = domain::getipsofdomain($domain_check['id']); $domain_ips = phphelper::gethostbynamel6($completedomain, true, settings::get('system.le_domain_dnscheck_resolver')); ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) &lt;= 0) { response::standarderror('invaliddnsforletsencrypt', '', true); } } // temporarily deactivate ssl_redirect let's encrypt certificate generated ($ssl_redirect &gt; 0 &amp;&amp; $letsencrypt == 1) { $ssl_redirect = 2; } // validate speciallogfile value ($speciallogfile &lt; 0 || $speciallogfile &gt; 2) { $speciallogfile = 2; // inherit parent-domain } // get phpsettingid parentdomain, #107 $phpsid_stmt = database::prepare(" select `phpsettingid` `" . table_panel_domains . "` `id` = :id "); $phpsid_result = database::pexecute_first($phpsid_stmt, [ "id" =&gt; $domain_check['id'] ], true, true); (!isset($phpsid_result['phpsettingid']) || (int)$phpsid_result['phpsettingid'] &lt;= 0) { // assign default config $phpsid_result['phpsettingid'] = 1; } ($domain_check['phpenabled'] == 1) { // check whether customer chosen php-config ($phpsettingid &gt; 0 &amp;&amp; $phpsettingid != $phpsid_result['phpsettingid']) { $phpsid_result['phpsettingid'] = intval($phpsettingid); } $allowed_phpconfigs = $customer['allowed_phpconfigs']; (!empty($allowed_phpconfigs)) { $allowed_phpconfigs = json_decode($allowed_phpconfigs, true); } else { $allowed_phpconfigs = []; } // fcgid/fpm enabled possible select php-setting ((int)settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1) { (!in_array($phpsid_result['phpsettingid'], $allowed_phpconfigs)) { response::standarderror('notallowedphpconfigused', '', true); } } } // actually insert domain $stmt = database::prepare(" insert `" . table_panel_domains . "` set `customerid` = :customerid, `adminid` = :adminid, `domain` = :domain, `domain_ace` = :domain_ace, `documentroot` = :documentroot, `aliasdomain` = :aliasdomain, `parentdomainid` = :parentdomainid, `wwwserveralias` = :wwwserveralias, `isemaildomain` = :isemaildomain, `iswildcarddomain` = :iswildcarddomain, `phpenabled` = :phpenabled, `openbasedir` = :openbasedir, `openbasedir_path` = :openbasedir_path, `speciallogfile` = :speciallogfile, `specialsettings` = :specialsettings, `ssl_specialsettings` = :ssl_specialsettings, `include_specialsettings` = :include_specialsettings, `ssl_redirect` = :ssl_redirect, `phpsettingid` = :phpsettingid, `letsencrypt` = :letsencrypt, `http2` = :http2, `hsts` = :hsts, `hsts_sub` = :hsts_sub, `hsts_preload` = :hsts_preload, `ocsp_stapling` = :ocsp_stapling, `override_tls` = :override_tls, `ssl_protocols` = :ssl_protocols, `ssl_cipher_list` = :ssl_cipher_list, `tlsv13_cipher_list` = :tlsv13_cipher_list, `ssl_enabled` = :sslenabled "); $params = [ "customerid" =&gt; $customer['customerid'], "adminid" =&gt; $customer['adminid'], "domain" =&gt; $completedomain, "domain_ace" =&gt; $idna_convert-&gt;decode($completedomain), "documentroot" =&gt; $path, "aliasdomain" =&gt; $aliasdomain != 0 ? $aliasdomain : null, "parentdomainid" =&gt; $domain_check['id'], "wwwserveralias" =&gt; $domain_check['wwwserveralias'] == '1' ? '1' : '0', "iswildcarddomain" =&gt; $domain_check['iswildcarddomain'] == '1' ? '1' : '0', "isemaildomain" =&gt; $isemaildomain, "openbasedir" =&gt; $domain_check['openbasedir'], "openbasedir_path" =&gt; $openbasedir_path, "phpenabled" =&gt; $domain_check['phpenabled'], "speciallogfile" =&gt; $speciallogfile == 2 ? $domain_check['speciallogfile'] : $speciallogfile, "specialsettings" =&gt; $domain_check['specialsettings'], "ssl_specialsettings" =&gt; $domain_check['ssl_specialsettings'], "include_specialsettings" =&gt; $domain_check['include_specialsettings'], "ssl_redirect" =&gt; $ssl_redirect, "phpsettingid" =&gt; $phpsid_result['phpsettingid'], "letsencrypt" =&gt; $letsencrypt, "http2" =&gt; $http2, "hsts" =&gt; $hsts_maxage, "hsts_sub" =&gt; $hsts_sub, "hsts_preload" =&gt; $hsts_preload, "ocsp_stapling" =&gt; $domain_check['ocsp_stapling'], "override_tls" =&gt; $domain_check['override_tls'], "ssl_protocols" =&gt; $domain_check['ssl_protocols'], "ssl_cipher_list" =&gt; $domain_check['ssl_cipher_list'], "tlsv13_cipher_list" =&gt; $domain_check['tlsv13_cipher_list'], "sslenabled" =&gt; $sslenabled ]; database::pexecute($stmt, $params, true, true); $subdomain_id = database::lastinsertid(); $stmt = database::prepare(" insert `" . table_domaintoip . "` (`id_domain`, `id_ipandports`) select last_insert_id(), `id_ipandports` `" . table_domaintoip . "` `id_domain` = :id_domain "); database::pexecute($stmt, [ "id_domain" =&gt; $domain_check['id'] ]); ($_doredirect) { domain::addredirecttodomain($subdomain_id, $redirectcode); } cronjob::inserttask(taskid::rebuild_vhost); // using nameserver, insert task rebuilds server config cronjob::inserttask(taskid::rebuild_dns); customers::increaseusage($customer['customerid'], 'subdomains_used'); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] added subdomain '" . $completedomain . "'"); $result = $this-&gt;apicall('subdomains.get', [ 'id' =&gt; $subdomain_id ]); return $this-&gt;response($result); } throw new exception("no resources available", 406); } /** * return subdomain entry either id domainname * * @param int $id * optional, domain-id * @param string $domainname * optional, domainname * @param bool $with_ips * optional, default true * * @access admin, customer * @return string json-encoded array * @throws exception */ public function get() { $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); $with_ips = $this-&gt;getparam('with_ips', true, true); // convert possible idn domain punycode (substr($domainname, 0, 4) != 'xn--') { $idna_convert = new idnawrapper(); $domainname = $idna_convert-&gt;encode($domainname); } ($this-&gt;isadmin()) { ($this-&gt;getuserdetail('customers_see_all') != 1) { // reseller admin cannot see customers, need check // whether database belongs one customers $_custom_list_result = $this-&gt;apicall('customers.listing'); $custom_list_result = $_custom_list_result['list']; $customer_ids = []; foreach ($custom_list_result $customer) { $customer_ids[] = $customer['customerid']; } (count($customer_ids) &gt; 0) { $result_stmt = database::prepare(" select d.*, pd.`subcanemaildomain`, pd.`isbinddomain` subisbinddomain `" . table_panel_domains . "` d, `" . table_panel_domains . "` pd " . ($id &gt; 0 ? "d.`id` = :iddn" : "d.`domain` = :iddn") . " d.`customerid` (" . implode(", ", $customer_ids) . ") ((d.`parentdomainid`!='0' pd.`id` = d.`parentdomainid`) (d.`parentdomainid`='0' pd.`id` = d.`id`)) "); $params = [ 'iddn' =&gt; ($id &lt;= 0 ? $domainname : $id) ]; } else { throw new exception("you customers yet", 406); } } else { $result_stmt = database::prepare(" select d.*, pd.`subcanemaildomain`, pd.`isbinddomain` subisbinddomain `" . table_panel_domains . "` d, `" . table_panel_domains . "` pd " . ($id &gt; 0 ? "d.`id` = :iddn" : "d.`domain` = :iddn") . " ((d.`parentdomainid`!='0' pd.`id` = d.`parentdomainid`) (d.`parentdomainid`='0' pd.`id` = d.`id`)) "); $params = [ 'iddn' =&gt; ($id &lt;= 0 ? $domainname : $id) ]; } } else { (!$this-&gt;isinternal() &amp;&amp; settings::isinlist('panel.customer_hide_options', 'domains')) { throw new exception("you cannot access resource", 405); } $result_stmt = database::prepare(" select d.*, pd.`subcanemaildomain`, pd.`isbinddomain` subisbinddomain `" . table_panel_domains . "` d, `" . table_panel_domains . "` pd d.`customerid`= :customerid " . ($id &gt; 0 ? "d.`id` = :iddn" : "d.`domain` = :iddn") . " ((d.`parentdomainid`!='0' pd.`id` = d.`parentdomainid`) (d.`parentdomainid`='0' pd.`id` = d.`id`)) "); $params = [ 'customerid' =&gt; $this-&gt;getuserdetail('customerid'), 'iddn' =&gt; ($id &lt;= 0 ? $domainname : $id) ]; } $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { $result['ipsandports'] = []; ($with_ips) { $result['ipsandports'] = $this-&gt;getipsfordomain($result['id']); } $result['domain_hascert'] = $this-&gt;gethascertvaluefordomain((int)$result['id'], (int)$result['parentdomainid']); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] get subdomain '" . $result['domain'] . "'"); return $this-&gt;response($result); } throw new exception("requested subdomain could found", 404); } private function gethascertvaluefordomain(int $domainid, int $parentdomainid): int { // nothing (ssl_global) $domain_hascert = 0; $ssl_stmt = database::prepare("select * `" . table_panel_domain_ssl_settings . "` `domainid` = :domainid"); database::pexecute($ssl_stmt, array( "domainid" =&gt; $domainid )); $ssl_result = $ssl_stmt-&gt;fetch(pdo::fetch_assoc); (is_array($ssl_result) &amp;&amp; isset($ssl_result['ssl_cert_file']) &amp;&amp; $ssl_result['ssl_cert_file'] != '') { // certificate (ssl_customer_green) $domain_hascert = 1; } else { // check parent one set (shared) ($parentdomainid != 0) { $ssl_stmt = database::prepare("select * `" . table_panel_domain_ssl_settings . "` `domainid` = :domainid"); database::pexecute($ssl_stmt, array( "domainid" =&gt; $parentdomainid )); $ssl_result = $ssl_stmt-&gt;fetch(pdo::fetch_assoc); (is_array($ssl_result) &amp;&amp; isset($ssl_result['ssl_cert_file']) &amp;&amp; $ssl_result['ssl_cert_file'] != '') { // parent certificate (ssl_shared) $domain_hascert = 2; } } } return $domain_hascert; } /** * validate given path replace url given valid * * @param string $path * @param string $url * @param array $customer * @param string $completedomain * @param boolean $_doredirect * * @return string validated path * @throws exception */ private function validatedomaindocumentroot($path = null, $url = null, $customer = null, $completedomain = null, &amp;$_doredirect = false) { // check whether url specified $_doredirect = false; (!empty($url) &amp;&amp; validate::validateurl($url, true)) { $path = $url; $_doredirect = true; } else { $path = validate::validate($path, 'path', '', '', [], true); } // check whether path real path (!preg_match('/^https?\:\/\//', $path) || !validate::validateurl($path, true)) { (strstr($path, ":") !== false) { response::standarderror('pathmaynotcontaincolon', '', true); } // path empty '/' 'use domain name default value documentroot path' enabled settings, // set default path subdomain domain name ((($path == '') || ($path == '/')) &amp;&amp; settings::get('system.documentroot_use_default_value') == 1) { $path = filedir::makecorrectdir($customer['documentroot'] . '/' . $completedomain, $customer['documentroot']); } else { $path = filedir::makecorrectdir($customer['documentroot'] . '/' . $path, $customer['documentroot']); } } else { // not, create redirect $_doredirect = true; } return $path; } /** * update subdomain entry either id domainname * * @param int $id * optional, domain-id * @param string $domainname * optional, domainname * @param int $alias * optional, domain-id domain new domain alias * @param string $path * optional, destination path relative customers-homedir, default customers-homedir * @param string $url * optional, overwrites path value url generate redirect, alternatively use path * parameter also urls * @param int $selectserveralias * optional, 0 = wildcard, 1 = www-alias, 2 = none * @param bool $isemaildomain * optional * @param int $openbasedir_path * optional, either 0 domains-docroot, 1 customers-homedir 2 parent-directory domains-docroot * @param int $phpsettingid * optional, php-settings-id, empty $domain value used * @param int $redirectcode * optional, redirect-code-id table_panel_redirectcodes * @param bool $speciallogfile * optional, whether create exclusive web-logfile domain * @param bool $speciallogverified * optional, setting $speciallogfile false, needs set true confirm action, * default 0 (false) * @param bool $sslenabled * optional, whether ssl enabled domain, regardless assigned ssl-ips, default * 1 (true) * @param bool $ssl_redirect * optional, whether generate https-redirect not, default false; requires ssl enabled * @param bool $letsencrypt * optional, whether generate let's encrypt certificate domain, default false; requires * ssl enabled * @param bool $http2 * optional, whether enable http/2 domain (requires enabled settings), default * 0 (false) * @param int $hsts_maxage * optional max-age value hsts header * @param bool $hsts_sub * optional whether add subdomains hsts header * @param bool $hsts_preload * optional whether preload hsts header value * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * * @access admin, customer * @return string json-encoded array * @throws exception */ public function update() { $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'domains')) { throw new exception("you cannot access resource", 405); } $result = $this-&gt;apicall('subdomains.get', [ 'id' =&gt; $id, 'domainname' =&gt; $domainname ]); $id = $result['id']; ($this-&gt;isadmin() == false &amp;&amp; (int)$result['caneditdomain'] == 0) { throw new exception(lng('error.domaincannotbeedited', [$result['domain']]), 406); } // parameters $aliasdomain = $this-&gt;getparam('alias', true, 0); $path = $this-&gt;getparam('path', true, $result['documentroot']); $url = $this-&gt;getparam('url', true, ''); // default: 0 = wildcard, 1 = www-alias, 2 = none $_serveraliasdefault = $result['iswildcarddomain'] == '1' ? 0 : ($result['wwwserveralias'] == '1' ? 1 : 2); $selectserveralias = $this-&gt;getparam('selectserveralias', true, $_serveraliasdefault); $isemaildomain = $this-&gt;getboolparam('isemaildomain', true, $result['isemaildomain']); $openbasedir_path = $this-&gt;getparam('openbasedir_path', true, $result['openbasedir_path']); $phpsettingid = $this-&gt;getparam('phpsettingid', true, $result['phpsettingid']); $redirectcode = $this-&gt;getparam('redirectcode', true, domain::getdomainredirectid($id)); $speciallogfile = $this-&gt;getboolparam('speciallogfile', true, $result['speciallogfile']); $speciallogverified = $this-&gt;getboolparam('speciallogverified', true, 0); (settings::get('system.use_ssl')) { $sslenabled = $this-&gt;getboolparam('sslenabled', true, $result['ssl_enabled']); $ssl_redirect = $this-&gt;getboolparam('ssl_redirect', true, $result['ssl_redirect']); $letsencrypt = $this-&gt;getboolparam('letsencrypt', true, $result['letsencrypt']); $http2 = $this-&gt;getboolparam('http2', true, $result['http2']); $hsts_maxage = $this-&gt;getparam('hsts_maxage', true, $result['hsts']); $hsts_sub = $this-&gt;getboolparam('hsts_sub', true, $result['hsts_sub']); $hsts_preload = $this-&gt;getboolparam('hsts_preload', true, $result['hsts_preload']); } else { $sslenabled = 0; $ssl_redirect = 0; $letsencrypt = 0; $http2 = 0; $hsts_maxage = 0; $hsts_sub = 0; $hsts_preload = 0; } // get needed customer info reduce subdomain-usage-counter one $customer = $this-&gt;getcustomerdata(); $alias_stmt = database::prepare("select count(`id`) count `" . table_panel_domains . "` `aliasdomain`= :aliasdomain"); $alias_check = database::pexecute_first($alias_stmt, [ "aliasdomain" =&gt; $result['id'] ]); $alias_check = $alias_check['count']; // alias domain checked? ($aliasdomain != 0) { $aliasdomain_stmt = database::prepare(" select `id` `" . table_panel_domains . "` `d`,`" . table_panel_customers . "` `c` `d`.`customerid`= :customerid `d`.`aliasdomain` null `d`.`id`&lt;&gt;`c`.`standardsubdomain` `c`.`customerid`= :customerid `d`.`id`= :id "); $aliasdomain_check = database::pexecute_first($aliasdomain_stmt, [ "id" =&gt; $aliasdomain, "customerid" =&gt; $customer['customerid'] ], true, true); ($aliasdomain_check['id'] != $aliasdomain) { response::standarderror('domainisaliasorothercustomer', '', true); } domain::triggerletsencryptcsrforaliasdestinationdomain($aliasdomain, $this-&gt;logger()); } // validate / correct path/url domain $_doredirect = false; $path = $this-&gt;validatedomaindocumentroot($path, $url, $customer, $result['domain'], $_doredirect); // set alias-fields according selected alias mode $iswildcarddomain = ($selectserveralias == '0') ? '1' : '0'; $wwwserveralias = ($selectserveralias == '1') ? '1' : '0'; // allowed, check 'is email domain'-flag ($isemaildomain != $result['isemaildomain']) { ($result['parentdomainid'] != '0' &amp;&amp; ($result['subcanemaildomain'] == '1' || $result['subcanemaildomain'] == '2')) { $isemaildomain = intval($isemaildomain); } elseif ($result['parentdomainid'] != '0') { $isemaildomain = $result['subcanemaildomain'] == '3' ? 1 : 0; } } // check changes openbasedir-path variable ($openbasedir_path &gt; 2 &amp;&amp; $openbasedir_path &lt; 0) { $openbasedir_path = 0; } ($ssl_redirect != 0) { // ssl-redirect works actually // ssl ip/port assigned domain (domain::domainhassslipport($result['id']) == true) { $ssl_redirect = '1'; $_doredirect = true; } else { response::standarderror('sslredirectonlypossiblewithsslipport', '', true); } } ($letsencrypt != 0) { // let's encrypt works actually // ssl ip/port assigned domain (domain::domainhassslipport($result['id']) == true) { $letsencrypt = '1'; } else { response::standarderror('letsencryptonlypossiblewithsslipport', '', true); } } // validate dns lets encrypt enabled check whether use ($result['letsencrypt'] != $letsencrypt &amp;&amp; $letsencrypt == '1' &amp;&amp; settings::get('system.le_domain_dnscheck') == '1') { $our_ips = domain::getipsofdomain($result['parentdomainid']); $domain_ips = phphelper::gethostbynamel6($result['domain'], true, settings::get('system.le_domain_dnscheck_resolver')); ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) &lt;= 0) { response::standarderror('invaliddnsforletsencrypt', '', true); } } // can't enable let's encrypt wildcard-domains ($iswildcarddomain == '1' &amp;&amp; $letsencrypt == '1') { response::standarderror('nowildcardwithletsencrypt', '', true); } // temporarily deactivate ssl_redirect let's encrypt certificate generated ($ssl_redirect &gt; 0 &amp;&amp; $letsencrypt == 1 &amp;&amp; $result['letsencrypt'] != $letsencrypt) { $ssl_redirect = 2; } ($speciallogfile != $result['speciallogfile'] &amp;&amp; $speciallogverified != '1') { $speciallogfile = $result['speciallogfile']; } // is-email-domain flag changed - remove mail accounts mail-addresses (($result['isemaildomain'] == '1') &amp;&amp; $isemaildomain == '0') { $params = [ "customerid" =&gt; $customer['customerid'], "domainid" =&gt; $id ]; $stmt = database::prepare("delete `" . table_mail_users . "` `customerid`= :customerid `domainid`= :domainid"); database::pexecute($stmt, $params, true, true); $stmt = database::prepare("delete `" . table_mail_virtual . "` `customerid`= :customerid `domainid`= :domainid"); database::pexecute($stmt, $params, true, true); $idna_convert = new idnawrapper(); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] automatically deleted mail-table entries '" . $idna_convert-&gt;decode($result['domain']) . "'"); } $allowed_phpconfigs = $customer['allowed_phpconfigs']; (!empty($allowed_phpconfigs)) { $allowed_phpconfigs = json_decode($allowed_phpconfigs, true); } else { $allowed_phpconfigs = []; } // fcgid/fpm enabled possible select php-setting ((int)$result['phpenabled'] == 1 &amp;&amp; ((int)settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1)) { (!in_array($phpsettingid, $allowed_phpconfigs)) { response::standarderror('notallowedphpconfigused', '', true); } } // handle redirect ($_doredirect) { domain::updateredirectofdomain($id, $redirectcode); } ($path != $result['documentroot'] || $isemaildomain != $result['isemaildomain'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $aliasdomain != (int)$result['aliasdomain'] || $openbasedir_path != $result['openbasedir_path'] || $ssl_redirect != $result['ssl_redirect'] || $letsencrypt != $result['letsencrypt'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload'] || $phpsettingid != $result['phpsettingid'] || $http2 != $result['http2'] || ($speciallogfile != $result['speciallogfile'] &amp;&amp; $speciallogverified == '1') ) { $stmt = database::prepare(" update `" . table_panel_domains . "` set `documentroot` = :documentroot, `isemaildomain` = :isemaildomain, `wwwserveralias` = :wwwserveralias, `iswildcarddomain` = :iswildcarddomain, `aliasdomain` = :aliasdomain, `openbasedir_path` = :openbasedir_path, `ssl_enabled` = :sslenabled, `ssl_redirect` = :ssl_redirect, `letsencrypt` = :letsencrypt, `http2` = :http2, `hsts` = :hsts, `hsts_sub` = :hsts_sub, `hsts_preload` = :hsts_preload, `phpsettingid` = :phpsettingid, `speciallogfile` = :speciallogfile `customerid`= :customerid `id`= :id "); $params = [ "documentroot" =&gt; $path, "isemaildomain" =&gt; $isemaildomain, "wwwserveralias" =&gt; $wwwserveralias, "iswildcarddomain" =&gt; $iswildcarddomain, "aliasdomain" =&gt; ($aliasdomain != 0 &amp;&amp; $alias_check == 0) ? $aliasdomain : null, "openbasedir_path" =&gt; $openbasedir_path, "sslenabled" =&gt; $sslenabled, "ssl_redirect" =&gt; $ssl_redirect, "letsencrypt" =&gt; $letsencrypt, "http2" =&gt; $http2, "hsts" =&gt; $hsts_maxage, "hsts_sub" =&gt; $hsts_sub, "hsts_preload" =&gt; $hsts_preload, "phpsettingid" =&gt; $phpsettingid, "speciallogfile" =&gt; $speciallogfile, "customerid" =&gt; $customer['customerid'], "id" =&gt; $id ]; database::pexecute($stmt, $params, true, true); ($result['aliasdomain'] != $aliasdomain &amp;&amp; is_numeric($result['aliasdomain'])) { // trigger domain id alias destination changed: old new destination domain::triggerletsencryptcsrforaliasdestinationdomain($result['aliasdomain'], $this-&gt;logger()); domain::triggerletsencryptcsrforaliasdestinationdomain($aliasdomain, $this-&gt;logger()); } ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) { // wwwserveralias letsencrypt changed domain::triggerletsencryptcsrforaliasdestinationdomain($aliasdomain, $this-&gt;logger()); ((int)$aliasdomain === 0) { // case wwwserveralias set main domain, $aliasdomain 0 // --&gt; call triggerletsencryptcsrforaliasdestinationdomain // noop...let's repeat domain id main domain domain::triggerletsencryptcsrforaliasdestinationdomain($id, $this-&gt;logger()); } } // check whether le disabled, remove certificate ($letsencrypt == '0' &amp;&amp; $result['letsencrypt'] == '1') { $del_stmt = database::prepare(" delete `" . table_panel_domain_ssl_settings . "` `domainid` = :id "); database::pexecute($del_stmt, [ 'id' =&gt; $id ], true, true); // remove domain acme.sh / lets encrypt used cronjob::inserttask(taskid::delete_domain_ssl, $result['domain']); } cronjob::inserttask(taskid::rebuild_vhost); cronjob::inserttask(taskid::rebuild_dns); $idna_convert = new idnawrapper(); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] edited domain '" . $idna_convert-&gt;decode($result['domain']) . "'"); } $result = $this-&gt;apicall('subdomains.get', [ 'id' =&gt; $id ]); return $this-&gt;response($result); } /** * lists customer domain/subdomain entries * * @param bool $with_ips * optional, default true * @param int $customerid * optional, admin-only, select (sub)domains specific customer id * @param string $loginname * optional, admin-only, select (sub)domains specific customer loginname * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin, customer * @return string json-encoded array count|list * @throws exception */ public function listing() { $with_ips = $this-&gt;getparam('with_ips', true, true); ($this-&gt;isadmin()) { // we're admin, list subdomains admins customers // optionally one specific customer identified id loginname $customerid = $this-&gt;getparam('customerid', true, 0); $loginname = $this-&gt;getparam('loginname', true, ''); (!empty($customerid) || !empty($loginname)) { $result = $this-&gt;apicall('customers.get', [ 'id' =&gt; $customerid, 'loginname' =&gt; $loginname ]); $custom_list_result = [ $result ]; } else { $_custom_list_result = $this-&gt;apicall('customers.listing'); $custom_list_result = $_custom_list_result['list']; } $customer_ids = []; foreach ($custom_list_result $customer) { $customer_ids[] = $customer['customerid']; } (empty($customer_ids)) { throw new exception("required resource unsatisfied.", 405); } $select_fields = [ '`d`.*' ]; } else { (settings::isinlist('panel.customer_hide_options', 'domains')) { throw new exception("you cannot access resource", 405); } $customer_ids = [ $this-&gt;getuserdetail('customerid') ]; $select_fields = [ '`d`.`id`', '`d`.`customerid`', '`d`.`domain`', '`d`.`domain_ace`', '`d`.`documentroot`', '`d`.`isbinddomain`', '`d`.`isemaildomain`', '`d`.`caneditdomain`', '`d`.`iswildcarddomain`', '`d`.`parentdomainid`', '`d`.`letsencrypt`', '`d`.`registration_date`', '`d`.`termination_date`', '`d`.`deactivated`', '`d`.`email_only`', ]; } $query_fields = []; // prepare select statement $domains_stmt = database::prepare(" select " . implode(",", $select_fields) . ", if(`d`.`parentdomainid` &gt; 0, `pd`.`domain_ace`, `d`.`domain_ace`) `parentdomainname`, `ad`.`id` `aliasdomainid`, `ad`.`domain` `aliasdomain`, `da`.`id` `domainaliasid`, `da`.`domain` `domainalias` `" . table_panel_domains . "` `d` left join `" . table_panel_domains . "` `ad` `d`.`aliasdomain`=`ad`.`id` left join `" . table_panel_domains . "` `da` `da`.`aliasdomain`=`d`.`id` left join `" . table_panel_domains . "` `pd` `pd`.`id`=`d`.`parentdomainid` `d`.`customerid` (" . implode(', ', $customer_ids) . ") " . $this-&gt;getsearchwhere($query_fields, true) . " group `d`.`id` order `parentdomainname` asc, `d`.`parentdomainid` asc " . $this-&gt;getorderby(true) . $this-&gt;getlimit()); $result = []; database::pexecute($domains_stmt, $query_fields, true, true); ($row = $domains_stmt-&gt;fetch(pdo::fetch_assoc)) { $row['ipsandports'] = []; ($with_ips) { $row['ipsandports'] = $this-&gt;getipsfordomain($row['id']); } $row['domain_hascert'] = $this-&gt;gethascertvaluefordomain((int)$row['id'], (int)$row['parentdomainid']); $result[] = $row; } return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } /** * get ips connected given domain array * * @param number $domain_id * @param bool $ssl_only * optional, return ssl enabled ip's, default false * @return array */ private function getipsfordomain($domain_id = 0, $ssl_only = false) { $fields = '`ips`.ip, `ips`.port, `ips`.ssl'; ($this-&gt;isadmin()) { $fields = '`ips`.*'; } $resultips_stmt = database::prepare(" select " . $fields . " `" . table_domaintoip . "` `dti`, `" . table_panel_ipsandports . "` `ips` `dti`.`id_ipandports` = `ips`.`id` `dti`.`id_domain` = :domainid " . ($ssl_only ? " `ips`.`ssl` = '1'" : "")); database::pexecute($resultips_stmt, [ 'domainid' =&gt; $domain_id ]); $ipandports = []; ($rowip = $resultips_stmt-&gt;fetch(pdo::fetch_assoc)) { (filter_var($rowip['ip'], filter_validate_ip, filter_flag_ipv6)) { $rowip['is_ipv6'] = true; } $ipandports[] = $rowip; } return $ipandports; } /** * returns total number accessible subdomain entries * * @param int $customerid * optional, admin-only, select (sub)domains specific customer id * @param string $loginname * optional, admin-only, select (sub)domains specific customer loginname * * @access admin, customer * @return string json-encoded response message * @throws exception */ public function listingcount() { ($this-&gt;isadmin()) { // we're admin, list databases admins customers // optionally one specific customer identified id loginname $customerid = $this-&gt;getparam('customerid', true, 0); $loginname = $this-&gt;getparam('loginname', true, ''); (!empty($customerid) || !empty($loginname)) { $result = $this-&gt;apicall('customers.get', [ 'id' =&gt; $customerid, 'loginname' =&gt; $loginname ]); $custom_list_result = [ $result ]; } else { $_custom_list_result = $this-&gt;apicall('customers.listing'); $custom_list_result = $_custom_list_result['list']; } $customer_ids = []; foreach ($custom_list_result $customer) { $customer_ids[] = $customer['customerid']; } } else { (settings::isinlist('panel.customer_hide_options', 'domains')) { throw new exception("you cannot access resource", 405); } $customer_ids = [ $this-&gt;getuserdetail('customerid') ]; } (!empty($customer_ids)) { // prepare select statement $domains_stmt = database::prepare(" select count(*) num_subdom `" . table_panel_domains . "` `d` `d`.`customerid` (" . implode(', ', $customer_ids) . ") "); $result = database::pexecute_first($domains_stmt, null, true, true); ($result) { return $this-&gt;response($result['num_subdom']); } } return $this-&gt;response(0); } /** * delete subdomain either id domainname * * @param int $id * optional, domain-id * @param string $domainname * optional, domainname * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * * @access admin, customer * @return string json-encoded array * @throws exception */ public function delete() { $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'domains')) { throw new exception("you cannot access resource", 405); } $result = $this-&gt;apicall('subdomains.get', [ 'id' =&gt; $id, 'domainname' =&gt; $domainname ]); $id = $result['id']; // get needed customer info reduce subdomain-usage-counter one $customer = $this-&gt;getcustomerdata(); (!$this-&gt;isadmin() &amp;&amp; $result['caneditdomain'] == 0) { throw new exception("you cannot edit resource", 405); } ($result['isemaildomain'] == '1') { // check e-mail addresses $emails_stmt = database::prepare(" select count(`id`) `count` `" . table_mail_virtual . "` `customerid` = :customerid `domainid` = :domainid "); $emails = database::pexecute_first($emails_stmt, [ "customerid" =&gt; $customer['customerid'], "domainid" =&gt; $id ], true, true); ($emails['count'] != '0') { response::standarderror('domains_cantdeletedomainwithemail', '', true); } } ((int)$result['aliasdomain'] !== 0) { domain::triggerletsencryptcsrforaliasdestinationdomain($result['aliasdomain'], $this-&gt;logger()); } // delete domain table $stmt = database::prepare(" delete `" . table_panel_domains . "` `customerid` = :customerid `id` = :id "); database::pexecute($stmt, [ "customerid" =&gt; $customer['customerid'], "id" =&gt; $id ], true, true); // remove connections ips domainredirects $del_stmt = database::prepare(" delete `" . table_domaintoip . "` `id_domain` = :domainid "); database::pexecute($del_stmt, [ 'domainid' =&gt; $id ], true, true); // remove redirect-codes $del_stmt = database::prepare(" delete `" . table_panel_domainredirects . "` `did` = :domainid "); database::pexecute($del_stmt, [ 'domainid' =&gt; $id ], true, true); // remove certificate domain_ssl_settings, fixes #1596 $del_stmt = database::prepare(" delete `" . table_panel_domain_ssl_settings . "` `domainid` = :domainid "); database::pexecute($del_stmt, [ 'domainid' =&gt; $id ], true, true); // remove possible existing dns entries $del_stmt = database::prepare(" delete `" . table_domain_dns . "` `domain_id` = :domainid "); database::pexecute($del_stmt, [ 'domainid' =&gt; $id ], true, true); cronjob::inserttask(taskid::rebuild_vhost); // using nameserver, insert task rebuilds server config cronjob::inserttask(taskid::rebuild_dns); // remove domains dns powerdns used, #581 cronjob::inserttask(taskid::delete_domain_pdns, $result['domain']); // remove domain acme.sh / lets encrypt used cronjob::inserttask(taskid::delete_domain_ssl, $result['domain']); // reduce subdomain-usage-counter customers::decreaseusage($customer['customerid'], 'subdomains_used'); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_warning, "[api] deleted subdomain '" . $result['domain'] . "'"); return $this-&gt;response($result); } }</file><file name="lib/Froxlor/Api/Commands/FpmDaemons.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\system\cronjob; use froxlor\ui\response; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class fpmdaemons extends apicommand implements resourceentity { /** * lists fpm-daemon entries * * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin * @return string json-encoded array count|list * @throws exception */ public function listing() { ($this-&gt;isadmin()) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_info, "[api] list fpm-daemons"); $query_fields = []; $result_stmt = database::prepare(" select * `" . table_panel_fpmdaemons . "`" . $this-&gt;getsearchwhere($query_fields) . $this-&gt;getorderby() . $this-&gt;getlimit()); database::pexecute($result_stmt, $query_fields, true, true); $fpmdaemons = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $query_params = [ 'id' =&gt; $row['id'] ]; $configresult_stmt = database::prepare("select * `" . table_panel_phpconfigs . "` `fpmsettingid` = :id"); database::pexecute($configresult_stmt, $query_params, true, true); $configs = []; (database::num_rows() &gt; 0) { ($row2 = $configresult_stmt-&gt;fetch(pdo::fetch_assoc)) { $configs[] = $row2['description']; } } (empty($configs)) { $configs[] = lng('admin.phpsettings.notused'); } $row['configs'] = $configs; $fpmdaemons[] = $row; } return $this-&gt;response([ 'count' =&gt; count($fpmdaemons), 'list' =&gt; $fpmdaemons ]); } throw new exception("not allowed execute given command.", 403); } /** * returns total number accessible fpm daemons * * @access admin * @return string json-encoded response message * @throws exception */ public function listingcount() { ($this-&gt;isadmin()) { $result_stmt = database::prepare(" select count(*) num_fpms `" . table_panel_fpmdaemons . "` "); $result = database::pexecute_first($result_stmt, null, true, true); ($result) { return $this-&gt;response($result['num_fpms']); } return $this-&gt;response(0); } throw new exception("not allowed execute given command.", 403); } /** * return fpm-daemon entry id * * @param int $id * fpm-daemon-id * * @access admin * @return string json-encoded array * @throws exception */ public function get() { ($this-&gt;isadmin()) { $id = $this-&gt;getparam('id'); $result_stmt = database::prepare(" select * `" . table_panel_fpmdaemons . "` `id` = :id "); $result = database::pexecute_first($result_stmt, [ 'id' =&gt; $id ], true, true); ($result) { return $this-&gt;response($result); } throw new exception("fpm-daemon id #" . $id . " could found", 404); } throw new exception("not allowed execute given command.", 403); } /** * create new fpm-daemon entry * * @param string $description * @param string $reload_cmd * @param string $config_dir * @param string $pm * optional, process-manager, one 'static', 'dynamic' 'ondemand', default 'dynamic' * @param int $max_children * optional, default 5 * @param int $start_servers * optional, default 2 * @param int $min_spare_servers * optional, default 1 * @param int $max_spare_servers * optional, default 3 * @param int $max_requests * optional, default 0 * @param int $idle_timeout * optional, default 10 * @param string $limit_extensions * optional, limit execution following extensions, default '.php' * @param string $custom_config * optional, custom settings appended phpfpm pool configuration * * @access admin * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 1) { // required parameter $description = $this-&gt;getparam('description'); $reload_cmd = $this-&gt;getparam('reload_cmd'); $config_dir = $this-&gt;getparam('config_dir'); // parameters $pmanager = $this-&gt;getparam('pm', true, 'dynamic'); $max_children = $this-&gt;getparam('max_children', true, 5); $start_servers = $this-&gt;getparam('start_servers', true, 2); $min_spare_servers = $this-&gt;getparam('min_spare_servers', true, 1); $max_spare_servers = $this-&gt;getparam('max_spare_servers', true, 3); $max_requests = $this-&gt;getparam('max_requests', true, 0); $idle_timeout = $this-&gt;getparam('idle_timeout', true, 10); $limit_extensions = $this-&gt;getparam('limit_extensions', true, '.php'); $custom_config = $this-&gt;getparam('custom_config', true, ''); // validation $description = validate::validate($description, 'description', validate::regex_desc_text, '', [], true); $reload_cmd = validate::validate($reload_cmd, 'reload_cmd', '/^[a-z0-9\/\._\-@ ]+$/i', '', [], true); $sel_stmt = database::prepare("select `id` `".table_panel_fpmdaemons."` `reload_cmd` = :rc"); $dupcheck = database::pexecute_first($sel_stmt, ['rc' =&gt; $reload_cmd]); ($dupcheck &amp;&amp; $dupcheck['id']) { throw new exception("php-fpm version given restart command already exists", 406); } $config_dir = validate::validate($config_dir, 'config_dir', validate::regex_dir, '', [], true); (!in_array($pmanager, [ 'static', 'dynamic', 'ondemand' ])) { throw new exception("unknown process manager", 406); } (empty($limit_extensions)) { $limit_extensions = '.php'; } $limit_extensions = validate::validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', [], true); (strlen($description) == 0 || strlen($description) &gt; 50) { response::standarderror('descriptioninvalid', '', true); } $ins_stmt = database::prepare(" insert `" . table_panel_fpmdaemons . "` set `description` = :desc, `reload_cmd` = :reload_cmd, `config_dir` = :config_dir, `pm` = :pm, `max_children` = :max_children, `start_servers` = :start_servers, `min_spare_servers` = :min_spare_servers, `max_spare_servers` = :max_spare_servers, `max_requests` = :max_requests, `idle_timeout` = :idle_timeout, `limit_extensions` = :limit_extensions, `custom_config` = :custom_config "); $ins_data = [ 'desc' =&gt; $description, 'reload_cmd' =&gt; $reload_cmd, 'config_dir' =&gt; filedir::makecorrectdir($config_dir), 'pm' =&gt; $pmanager, 'max_children' =&gt; $max_children, 'start_servers' =&gt; $start_servers, 'min_spare_servers' =&gt; $min_spare_servers, 'max_spare_servers' =&gt; $max_spare_servers, 'max_requests' =&gt; $max_requests, 'idle_timeout' =&gt; $idle_timeout, 'limit_extensions' =&gt; $limit_extensions, 'custom_config' =&gt; $custom_config ]; database::pexecute($ins_stmt, $ins_data); $id = database::lastinsertid(); cronjob::inserttask(taskid::rebuild_vhost); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] fpm-daemon description '" . $description . "' created '" . $this-&gt;getuserdetail('loginname') . "'"); $result = $this-&gt;apicall('fpmdaemons.get', [ 'id' =&gt; $id ]); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } /** * update fpm-daemon entry given id * * @param int $id * fpm-daemon id * @param string $description * optional * @param string $reload_cmd * optional * @param string $config_dir * optional * @param string $pm * optional, process-manager, one 'static', 'dynamic' 'ondemand', default 'dynamic' * @param int $max_children * optional, default 5 * @param int $start_servers * optional, default 2 * @param int $min_spare_servers * optional, default 1 * @param int $max_spare_servers * optional, default 3 * @param int $max_requests * optional, default 0 * @param int $idle_timeout * optional, default 10 * @param string $limit_extensions * optional, limit execution following extensions, default '.php' * @param string $custom_config * optional, custom settings appended phpfpm pool configuration * * @access admin * @return string json-encoded array * @throws exception */ public function update() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 1) { // required parameter $id = $this-&gt;getparam('id'); $result = $this-&gt;apicall('fpmdaemons.get', [ 'id' =&gt; $id ]); // parameters $description = $this-&gt;getparam('description', true, $result['description']); $reload_cmd = $this-&gt;getparam('reload_cmd', true, $result['reload_cmd']); $config_dir = $this-&gt;getparam('config_dir', true, $result['config_dir']); $pmanager = $this-&gt;getparam('pm', true, $result['pm']); $max_children = $this-&gt;getparam('max_children', true, $result['max_children']); $start_servers = $this-&gt;getparam('start_servers', true, $result['start_servers']); $min_spare_servers = $this-&gt;getparam('min_spare_servers', true, $result['min_spare_servers']); $max_spare_servers = $this-&gt;getparam('max_spare_servers', true, $result['max_spare_servers']); $max_requests = $this-&gt;getparam('max_requests', true, $result['max_requests']); $idle_timeout = $this-&gt;getparam('idle_timeout', true, $result['idle_timeout']); $limit_extensions = $this-&gt;getparam('limit_extensions', true, $result['limit_extensions']); $custom_config = $this-&gt;getparam('custom_config', true, $result['custom_config']); // validation $description = validate::validate($description, 'description', validate::regex_desc_text, '', [], true); $reload_cmd = validate::validate($reload_cmd, 'reload_cmd', '/^[a-z0-9\/\._\-@ ]+$/i', '', [], true); $sel_stmt = database::prepare("select `id` `".table_panel_fpmdaemons."` `reload_cmd` = :rc"); $dupcheck = database::pexecute_first($sel_stmt, ['rc' =&gt; $reload_cmd]); ($dupcheck &amp;&amp; $dupcheck['id'] != $id) { throw new exception("php-fpm version given restart command already exists", 406); } $config_dir = validate::validate($config_dir, 'config_dir', validate::regex_dir, '', [], true); (!in_array($pmanager, [ 'static', 'dynamic', 'ondemand' ])) { throw new exception("unknown process manager", 406); } (empty($limit_extensions)) { $limit_extensions = '.php'; } $limit_extensions = validate::validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', [], true); (strlen($description) == 0 || strlen($description) &gt; 50) { response::standarderror('descriptioninvalid', '', true); } $upd_stmt = database::prepare(" update `" . table_panel_fpmdaemons . "` set `description` = :desc, `reload_cmd` = :reload_cmd, `config_dir` = :config_dir, `pm` = :pm, `max_children` = :max_children, `start_servers` = :start_servers, `min_spare_servers` = :min_spare_servers, `max_spare_servers` = :max_spare_servers, `max_requests` = :max_requests, `idle_timeout` = :idle_timeout, `limit_extensions` = :limit_extensions, `custom_config` = :custom_config `id` = :id "); $upd_data = [ 'desc' =&gt; $description, 'reload_cmd' =&gt; $reload_cmd, 'config_dir' =&gt; filedir::makecorrectdir($config_dir), 'pm' =&gt; $pmanager, 'max_children' =&gt; $max_children, 'start_servers' =&gt; $start_servers, 'min_spare_servers' =&gt; $min_spare_servers, 'max_spare_servers' =&gt; $max_spare_servers, 'max_requests' =&gt; $max_requests, 'idle_timeout' =&gt; $idle_timeout, 'limit_extensions' =&gt; $limit_extensions, 'custom_config' =&gt; $custom_config, 'id' =&gt; $id ]; database::pexecute($upd_stmt, $upd_data, true, true); cronjob::inserttask(taskid::rebuild_vhost); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] fpm-daemon description '" . $description . "' updated '" . $this-&gt;getuserdetail('loginname') . "'"); $result = $this-&gt;apicall('fpmdaemons.get', [ 'id' =&gt; $id ]); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } /** * delete fpm-daemon entry id * * @param int $id * fpm-daemon-id * * @access admin * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 1) { $id = $this-&gt;getparam('id'); ($id == 1) { response::standarderror('cannotdeletedefaultphpconfig', '', true); } $result = $this-&gt;apicall('fpmdaemons.get', [ 'id' =&gt; $id ]); // set default fpm daemon config php-config use config deleted $upd_stmt = database::prepare(" update `" . table_panel_phpconfigs . "` set `fpmsettingid` = '1' `fpmsettingid` = :id "); database::pexecute($upd_stmt, [ 'id' =&gt; $id ], true, true); $del_stmt = database::prepare(" delete `" . table_panel_fpmdaemons . "` `id` = :id "); database::pexecute($del_stmt, [ 'id' =&gt; $id ], true, true); cronjob::inserttask(taskid::rebuild_vhost); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] fpm-daemon setting '" . $result['description'] . "' deleted '" . $this-&gt;getuserdetail('loginname') . "'"); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } }</file><file name="lib/Froxlor/Api/Commands/Certificates.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\system\cronjob; use froxlor\ui\response; use pdo; /** * @since 0.10.0 */ class certificates extends apicommand implements resourceentity { /** * add new ssl-certificate entry given domain either id domainname * * @param int $id * optional, domain-id * @param string $domainname * optional, domainname * @param string $ssl_cert_file * @param string $ssl_key_file * @param string $ssl_ca_file * optional * @param string $ssl_cert_chainfile * optional * * @access admin, customer * @return string json-encoded array * @throws exception */ public function add() { $domainid = $this-&gt;getparam('domainid', true, 0); $dn_optional = $domainid &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'domains')) { throw new exception("you cannot access resource", 405); } $domain = $this-&gt;apicall('subdomains.get', [ 'id' =&gt; $domainid, 'domainname' =&gt; $domainname ]); $domainid = $domain['id']; // parameters $ssl_cert_file = $this-&gt;getparam('ssl_cert_file'); $ssl_key_file = $this-&gt;getparam('ssl_key_file'); $ssl_ca_file = $this-&gt;getparam('ssl_ca_file', true, ''); $ssl_cert_chainfile = $this-&gt;getparam('ssl_cert_chainfile', true, ''); // validate whether domain already entry $has_cert = true; try { $this-&gt;apicall('certificates.get', [ 'id' =&gt; $domainid ]); } catch (exception $e) { ($e-&gt;getcode() == 412) { $has_cert = false; } else { throw $e; } } (!$has_cert) { $this-&gt;addorupdatecertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, true); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] added ssl-certificate '" . $domain['domain'] . "'"); $result = $this-&gt;apicall('certificates.get', [ 'id' =&gt; $domain['id'] ]); return $this-&gt;response($result); } throw new exception("domain '" . $domain['domain'] . "' already certificate. mean call update?", 406); } /** * insert update certificates entry * * @param int $domainid * @param string $ssl_cert_file * @param string $ssl_key_file * @param string $ssl_ca_file * @param string $ssl_cert_chainfile * @param boolean $do_insert * optional default false * * @return boolean * @throws exception */ private function addorupdatecertificate($domainid = 0, $ssl_cert_file = '', $ssl_key_file = '', $ssl_ca_file = '', $ssl_cert_chainfile = '', $do_insert = false) { ($ssl_cert_file != '' &amp;&amp; $ssl_key_file == '') { response::standarderror('sslcertificateismissingprivatekey', '', true); } $do_verify = true; $validtodate = null; $validtodate = null; $issuer = ""; // cert-file given -&gt; forget everything ($ssl_cert_file == '') { $ssl_key_file = ''; $ssl_ca_file = ''; $ssl_cert_chainfile = ''; $do_verify = false; } // verify certificate content ($do_verify) { // array openssl_x509_parse ( mixed $x509cert [, bool $shortnames = true ] ) // openssl_x509_parse() returns information supplied x509cert, including fields // subject name, issuer name, purposes, valid valid dates etc. $cert_content = openssl_x509_parse($ssl_cert_file); (is_array($cert_content) &amp;&amp; isset($cert_content['subject']) &amp;&amp; isset($cert_content['subject']['cn'])) { // bool openssl_x509_check_private_key ( mixed $cert , mixed $key ) // checks whether given key private key corresponds cert. (openssl_x509_check_private_key($ssl_cert_file, $ssl_key_file) === false) { response::standarderror('sslcertificateinvalidcertkeypair', '', true); } // check optional stuff ($ssl_ca_file != '') { $ca_content = openssl_x509_parse($ssl_ca_file); (!is_array($ca_content)) { // invalid response::standarderror('sslcertificateinvalidca', '', true); } } ($ssl_cert_chainfile != '') { $chain_content = openssl_x509_parse($ssl_cert_chainfile); (!is_array($chain_content)) { // invalid response::standarderror('sslcertificateinvalidchain', '', true); } } } else { response::standarderror('sslcertificateinvalidcert', '', true); } // get data certificate store table $validfromdate = empty($cert_content['validfrom_time_t']) ? null : date("y-m-d h:i:s", $cert_content['validfrom_time_t']); $validtodate = empty($cert_content['validto_time_t']) ? null : date("y-m-d h:i:s", $cert_content['validto_time_t']); $issuer = $cert_content['issuer']['o'] ?? ""; } // add/update database entry $qrystart = "update "; $qrywhere = "where "; ($do_insert) { $qrystart = "insert "; $qrywhere = ", "; } $stmt = database::prepare($qrystart . " `" . table_panel_domain_ssl_settings . "` set `ssl_cert_file` = :ssl_cert_file, `ssl_key_file` = :ssl_key_file, `ssl_ca_file` = :ssl_ca_file, `ssl_cert_chainfile` = :ssl_cert_chainfile, `validfromdate` = :validfromdate, `validtodate` = :validtodate, `issuer` = :issuer " . $qrywhere . " `domainid`= :domainid "); $params = [ "ssl_cert_file" =&gt; $ssl_cert_file, "ssl_key_file" =&gt; $ssl_key_file, "ssl_ca_file" =&gt; $ssl_ca_file, "ssl_cert_chainfile" =&gt; $ssl_cert_chainfile, "validfromdate" =&gt; $validfromdate, "validtodate" =&gt; $validtodate, "issuer" =&gt; $issuer, "domainid" =&gt; $domainid ]; database::pexecute($stmt, $params, true, true); // insert task re-generate webserver-configs (#1260) cronjob::inserttask(taskid::rebuild_vhost); return true; } /** * update ssl-certificate entry given domain either id domainname * * @param int $id * optional, domain-id * @param string $domainname * optional, domainname * @param string $ssl_cert_file * @param string $ssl_key_file * @param string $ssl_ca_file * optional * @param string $ssl_cert_chainfile * optional * * @access admin, customer * @return string json-encoded array * @throws exception */ public function update() { $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'domains')) { throw new exception("you cannot access resource", 405); } $domain = $this-&gt;apicall('subdomains.get', [ 'id' =&gt; $id, 'domainname' =&gt; $domainname ]); // parameters $ssl_cert_file = $this-&gt;getparam('ssl_cert_file'); $ssl_key_file = $this-&gt;getparam('ssl_key_file'); $ssl_ca_file = $this-&gt;getparam('ssl_ca_file', true, ''); $ssl_cert_chainfile = $this-&gt;getparam('ssl_cert_chainfile', true, ''); $this-&gt;addorupdatecertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, false); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] updated ssl-certificate '" . $domain['domain'] . "'"); $result = $this-&gt;apicall('certificates.get', [ 'id' =&gt; $domain['id'] ]); return $this-&gt;response($result); } /** * lists certificate entries * * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin, customer * @return string json-encoded array count|list * @throws exception */ public function listing() { // select (accessible) certificates $certs_stmt_query = "select s.*, d.domain, d.letsencrypt, c.customerid, c.loginname `" . table_panel_domain_ssl_settings . "` left join `" . table_panel_domains . "` `d`.`id` = `s`.`domainid` left join `" . table_panel_customers . "` c `c`.`customerid` = `d`.`customerid` "; $qry_params = []; $query_fields = []; ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('customers_see_all') == '0') { // admin customer-specific permissions $certs_stmt_query .= "d.adminid = :adminid "; $qry_params['adminid'] = $this-&gt;getuserdetail('adminid'); } elseif ($this-&gt;isadmin() == false) { // customer-area $certs_stmt_query .= "d.customerid = :cid "; $qry_params['cid'] = $this-&gt;getuserdetail('customerid'); } else { $certs_stmt_query .= "1 "; } $certs_stmt = database::prepare($certs_stmt_query . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); $qry_params = array_merge($qry_params, $query_fields); database::pexecute($certs_stmt, $qry_params, true, true); $result = []; ($cert = $certs_stmt-&gt;fetch(pdo::fetch_assoc)) { // respect froxlor-hostname ($cert['domainid'] == 0) { $cert['domain'] = settings::get('system.hostname'); $cert['letsencrypt'] = settings::get('system.le_froxlor_enabled'); $cert['loginname'] = 'froxlor.panel'; } // set data certificate $cert['isvalid'] = false; $cert['san'] = null; $cert_data = openssl_x509_parse($cert['ssl_cert_file']); ($cert_data) { $cert['isvalid'] = (bool)$cert_data['validto_time_t'] &gt; time(); // set subject alt names certificate (isset($cert_data['extensions']['subjectaltname']) &amp;&amp; !empty($cert_data['extensions']['subjectaltname'])) { $sans = explode(",", $cert_data['extensions']['subjectaltname']); $sans = array_map('trim', $sans); foreach ($sans $san) { $san = str_replace("dns:", "", $san); ($san != $cert_data['subject']['cn'] &amp;&amp; strpos($san, "othername:") === false) { $cert['san'][] = $san; } } } } $result[] = $cert; } return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } /** * return ssl-certificate entry given domain either id domainname * * @param int $id * optional, domain-id * @param string $domainname * optional, domainname * * @access admin, customer * @return string json-encoded array * @throws exception */ public function get() { $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'domains')) { throw new exception("you cannot access resource", 405); } $domain = $this-&gt;apicall('subdomains.get', [ 'id' =&gt; $id, 'domainname' =&gt; $domainname ]); $domainid = $domain['id']; $stmt = database::prepare("select * `" . table_panel_domain_ssl_settings . "` `domainid`= :domainid"); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] get ssl-certificate '" . $domain['domain'] . "'"); $result = database::pexecute_first($stmt, [ "domainid" =&gt; $domainid ]); (!$result) { throw new exception("domain '" . $domain['domain'] . "' certificate.", 412); } return $this-&gt;response($result); } /** * returns total number certificates given user * * @access admin, customer * @return string json-encoded response message * @throws exception */ public function listingcount() { // select (accessible) certificates $certs_stmt_query = "select count(*) num_certs `" . table_panel_domain_ssl_settings . "` left join `" . table_panel_domains . "` `d`.`id` = `s`.`domainid` left join `" . table_panel_customers . "` c `c`.`customerid` = `d`.`customerid` "; $qry_params = []; ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('customers_see_all') == '0') { // admin customer-specific permissions $certs_stmt_query .= "d.adminid = :adminid "; $qry_params['adminid'] = $this-&gt;getuserdetail('adminid'); } elseif ($this-&gt;isadmin() == false) { // customer-area $certs_stmt_query .= "d.customerid = :cid "; $qry_params['cid'] = $this-&gt;getuserdetail('customerid'); } else { $certs_stmt_query .= "1 "; } $certs_stmt = database::prepare($certs_stmt_query); $result = database::pexecute_first($certs_stmt, $qry_params, true, true); ($result) { return $this-&gt;response($result['num_certs']); } return $this-&gt;response(0); } /** * delete certificates entry id * * @param int $id * * @return string json-encoded array * @throws exception */ public function delete() { $id = $this-&gt;getparam('id'); ($this-&gt;isadmin() == false) { $chk_stmt = database::prepare(" select d.domain, d.letsencrypt `" . table_panel_domains . "` left join `" . table_panel_domain_ssl_settings . "` s.domainid = d.id s.`id` = :id d.`customerid` = :cid "); $chk = database::pexecute_first($chk_stmt, [ 'id' =&gt; $id, 'cid' =&gt; $this-&gt;getuserdetail('customerid') ]); } elseif ($this-&gt;isadmin()) { $chk_stmt = database::prepare(" select d.domain, d.letsencrypt `" . table_panel_domains . "` left join `" . table_panel_domain_ssl_settings . "` s.domainid = d.id s.`id` = :id" . ($this-&gt;getuserdetail('customers_see_all') == '0' ? " d.`adminid` = :aid" : "")); $params = [ 'id' =&gt; $id ]; ($this-&gt;getuserdetail('customers_see_all') == '0') { $params['aid'] = $this-&gt;getuserdetail('adminid'); } $chk = database::pexecute_first($chk_stmt, $params); ($chk == false &amp;&amp; $this-&gt;getuserdetail('change_serversettings')) { // check whether might froxlor-vhost certificate $chk_stmt = database::prepare(" select \"" . settings::get('system.hostname') . "\" domain, \"" . settings::get('system.le_froxlor_enabled') . "\" letsencrypt `" . table_panel_domain_ssl_settings . "` `id` = :id `domainid` = '0'"); $params = [ 'id' =&gt; $id ]; $chk = database::pexecute_first($chk_stmt, $params); $chk['isfroxlorvhost'] = true; } } ($chk !== false) { // additional access check trying get certificate (isset($chk['isfroxlorvhost']) &amp;&amp; $chk['isfroxlorvhost'] == true) { $result = $chk; } else { $result = $this-&gt;apicall('certificates.get', [ 'domainname' =&gt; $chk['domain'] ]); } $del_stmt = database::prepare("delete `" . table_panel_domain_ssl_settings . "` id = :id"); database::pexecute($del_stmt, [ 'id' =&gt; $id ]); // trigger removing certificate acme.sh let's encrypt ($chk['letsencrypt'] == '1') { cronjob::inserttask(taskid::delete_domain_ssl, $chk['domain']); } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] removed ssl-certificate '" . $chk['domain'] . "'"); return $this-&gt;response($result); } throw new exception("unable determine ssl certificate. maybe access?", 406); } }</file><file name="lib/Froxlor/Api/Commands/MysqlServer.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\database\database; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\phphelper; use froxlor\validate\validate; use pdo; use pdoexception; class mysqlserver extends apicommand implements resourceentity { /** * check whether user allowed * * @throws exception */ private function validateaccess() { ($this-&gt;isadmin() == false || ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 0)) { throw new exception("you cannot access resource", 405); } } /** * add new mysql-server * * @param string $mysql_host * ip/hostname mysql-server * @param string $mysql_port * optional, port connect * @param string $mysql_ca * optional, path certificate file * @param string $mysql_verifycert * optional, verify server certificate * @param string $privileged_user * privileged user mysql-server (must grant privileges) * @param string $privileged_password * password privileged user * @param string $description * optional, description server * @param bool $allow_all_customers * optional add configuration list every existing customer's allowed-mysqlserver-config list, default false (no) * @param bool $test_connection * optional, test connection given credentials, default true (yes) * * @access admin * @return string json-encoded array * @throws exception */ public function add() { $this-&gt;validateaccess(); $mysql_host = $this-&gt;getparam('mysql_host'); $mysql_port = $this-&gt;getparam('mysql_port', true, 3306); $mysql_ca = $this-&gt;getparam('mysql_ca', true, ''); $mysql_verifycert = $this-&gt;getboolparam('mysql_verifycert', true, 0); $privileged_user = $this-&gt;getparam('privileged_user'); $privileged_password = $this-&gt;getparam('privileged_password'); $description = $this-&gt;getparam('description', true, ''); $allow_all_customers = $this-&gt;getparam('allow_all_customers', true, 0); $test_connection = $this-&gt;getparam('test_connection', true, 1); // validation $mysql_host_chk = validate::validate_ip2($mysql_host, true, 'invalidip', true, true, false); ($mysql_host_chk === false) { $mysql_host_chk = validate::validatelocalhostname($mysql_host); ($mysql_host_chk === false) { $mysql_host_chk = validate::validatedomain($mysql_host); ($mysql_host_chk === false) { throw new exception("invalid mysql server ip/hostname", 406); } } } $mysql_port = validate::validate($mysql_port, 'port', validate::regex_port, '', [3306], true); $privileged_password = validate::validate($privileged_password, 'password', '', '', [], true); $description = validate::validate(trim($description), 'description', validate::regex_desc_text, '', [], true); // testing connection given credentials ($test_connection) { $options = array( pdo::mysql_attr_init_command =&gt; 'set names utf8' ); (!empty($mysql_ca)) { $options[pdo::mysql_attr_ssl_ca] = $mysql_ca; $options[pdo::mysql_attr_ssl_verify_server_cert] = (bool)$mysql_verifycert; } $dsn = "mysql:host=" . $mysql_host . ";port=" . $mysql_port . ";"; try { $db_test = new \pdo($dsn, $privileged_user, $privileged_password, $options); unset($db_test); } catch (pdoexception $e) { throw new exception("connection given mysql database could established. error-message: " . $e-&gt;getmessage(), $e-&gt;getcode()); } } $sql = []; $sql_root = []; // get data lib/userdata require froxlor::getinstalldir() . "/lib/userdata.inc.php"; // le format (isset($sql['root_user']) &amp;&amp; isset($sql['root_password']) &amp;&amp; !is_array($sql_root)) { $sql_root = array( 0 =&gt; array( 'caption' =&gt; 'default', 'host' =&gt; $sql['host'], 'socket' =&gt; (isset($sql['socket']) ? $sql['socket'] : null), 'user' =&gt; $sql['root_user'], 'password' =&gt; $sql['root_password'] ) ); unset($sql['root_user']); unset($sql['root_password']); } // add new values sql_root array $sql_root[] = [ 'caption' =&gt; $description, 'host' =&gt; $mysql_host, 'port' =&gt; $mysql_port, 'user' =&gt; $privileged_user, 'password' =&gt; $privileged_password, 'ssl' =&gt; [ 'cafile' =&gt; $mysql_ca ?? "", 'verifyservercertificate' =&gt; $mysql_verifycert ] ]; $this-&gt;generatenewuserdata($sql, $sql_root); // last added array $newdbserver = array_key_last($sql_root); ($allow_all_customers) { $this-&gt;adddatabasefromcustomerallowedlist($newdbserver); } $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] added new database server '" . $description . "' (" . $mysql_host . ")"); return $this-&gt;response(['dbserver' =&gt; $newdbserver]); } /** * remove mysql-server * * @param int $id * optional number mysql server (either id dbserver must set) * @param int $dbserver * optional number mysql server (either id dbserver must set) * * @access admin * @return string json-encoded array * @throws exception */ public function delete() { $this-&gt;validateaccess(); $id = (int)$this-&gt;getparam('id', true, -1); $dn_optional = $id &gt;= 0; $dbserver = (int)$this-&gt;getparam('dbserver', $dn_optional, -1); $dbserver = $id &gt;= 0 ? $id : $dbserver; ($dbserver == 0) { throw new exception('cannot delete first/default mysql-server', 406); } $sql_root = []; // get data lib/userdata require froxlor::getinstalldir() . "/lib/userdata.inc.php"; (!isset($sql_root[$dbserver])) { throw new exception('mysql server found', 404); } // check whether server use customer $result_ms = $this-&gt;databasesonserver(true, $dbserver); ($result_ms &gt; 0) { throw new exception(lng('error.mysqlserverstillhasdbs'), 406); } // removing, remove list allowed_mysqlservers customers $this-&gt;removedatabasefromcustomerallowedlist($dbserver); $description = $sql_root[$dbserver]['caption'] ?? "unknown"; $mysql_host = $sql_root[$dbserver]['host'] ?? "unknown"; unset($sql_root[$dbserver]); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] removed database server '" . $description . "' (" . $mysql_host . ")"); $this-&gt;generatenewuserdata($sql, $sql_root); return $this-&gt;response(['true']); } /** * list available mysql-server * * @access admin, customer * @return string json-encoded array */ public function listing() { $sql = []; $sql_root = []; // get data lib/userdata require froxlor::getinstalldir() . "/lib/userdata.inc.php"; // limit customer allowed servers $allowed_mysqls = []; ($this-&gt;isadmin() == false) { $allowed_mysqls = json_decode($this-&gt;getuserdetail('allowed_mysqlserver'), true); } $result = []; foreach ($sql_root $index =&gt; $sqlrootdata) { ($this-&gt;isadmin() == false) { ($allowed_mysqls === false || empty($allowed_mysqls)) { break; } elseif (!in_array($index, $allowed_mysqls)) { continue; } // usernames required non-admins unset($sqlrootdata['user']); } // passwords returned case security reasons unset($sqlrootdata['password']); $sqlrootdata['id'] = $index; $result[$index] = $sqlrootdata; } return $this-&gt;response(['list' =&gt; $result, 'count' =&gt; count($result)]); } /** * returns total number mysql servers * * @access admin, customer * @return string json-encoded response message */ public function listingcount() { ($this-&gt;isadmin() == false) { $allowed_mysqls = json_decode($this-&gt;getuserdetail('allowed_mysqlserver'), true); ($allowed_mysqls) { return $this-&gt;response(count($allowed_mysqls)); } return $this-&gt;response(0); } $sql_root = []; // get data lib/userdata require froxlor::getinstalldir() . "/lib/userdata.inc.php"; return $this-&gt;response(count($sql_root)); } /** * return info specific mysql-server * * @param int $id * optional number mysql server (either id dbserver must set) * @param int $dbserver * optional number mysql server (either id dbserver must set) * * @access admin, customer * @return string json-encoded array * @throws exception */ public function get() { $id = (int)$this-&gt;getparam('id', true, -1); $dn_optional = $id &gt;= 0; $dbserver = (int)$this-&gt;getparam('dbserver', $dn_optional, -1); $dbserver = $id &gt;= 0 ? $id : $dbserver; $sql_root = []; // get data lib/userdata require froxlor::getinstalldir() . "/lib/userdata.inc.php"; (!isset($sql_root[$dbserver])) { throw new exception('mysql server found', 404); } // limit customer allowed servers ($this-&gt;isadmin() == false) { $allowed_mysqls = json_decode($this-&gt;getuserdetail('allowed_mysqlserver'), true); ($allowed_mysqls === false || empty($allowed_mysqls) || !in_array($dbserver, $allowed_mysqls)) { throw new exception("you cannot access resource", 405); } // usernames required non-admins unset($sql_root[$dbserver]['user']); } unset($sql_root[$dbserver]['password']); $sql_root[$dbserver]['id'] = $dbserver; $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_info, "[api] get database-server '" . $sql_root[$dbserver]['caption'] . "'"); return $this-&gt;response($sql_root[$dbserver]); } /** * update given mysql-server * * @param int $id * optional number mysql server (either id dbserver must set) * @param int $dbserver * optional number mysql server (either id dbserver must set) * @param string $mysql_host * ip/hostname mysql-server * @param string $mysql_port * optional, port connect * @param string $mysql_ca * optional, path certificate file * @param string $mysql_verifycert * optional, verify server certificate * @param string $privileged_user * privileged user mysql-server (must grant privileges) * @param string $privileged_password * password privileged user * @param string $description * optional, description server * @param bool $allow_all_customers * optional add configuration list every existing customer's allowed-mysqlserver-config list, default false (no) * @param bool $test_connection * optional, test connection given credentials, default true (yes) * * @access admin * @return string json-encoded array * @throws exception */ public function update() { $this-&gt;validateaccess(); $id = (int)$this-&gt;getparam('id', true, -1); $dn_optional = $id &gt;= 0; $dbserver = (int)$this-&gt;getparam('dbserver', $dn_optional, -1); $dbserver = $id &gt;= 0 ? $id : $dbserver; $sql_root = []; require froxlor::getinstalldir() . "/lib/userdata.inc.php"; (!isset($sql_root[$dbserver])) { throw new exception('mysql server found', 404); } $result = $sql_root[$dbserver]; ($dbserver == 0) { $mysql_host = $result['host']; } else { $mysql_host = $this-&gt;getparam('mysql_host', true, $result['host']); } $mysql_port = $this-&gt;getparam('mysql_port', true, $result['port'] ?? 3306); $mysql_ca = $this-&gt;getparam('mysql_ca', true, $result['ssl']['cafile'] ?? ''); $mysql_verifycert = $this-&gt;getboolparam('mysql_verifycert', true, $result['ssl']['verifyservercertificate'] ?? 0); $privileged_user = $this-&gt;getparam('privileged_user', true, $result['user']); $privileged_password = $this-&gt;getparam('privileged_password', true, ''); $description = $this-&gt;getparam('description', true, $result['caption']); $allow_all_customers = $this-&gt;getparam('allow_all_customers', true, 0); $test_connection = $this-&gt;getparam('test_connection', true, 1); // validation $mysql_host_chk = validate::validate_ip2($mysql_host, true, 'invalidip', true, true, false); ($mysql_host_chk === false) { $mysql_host_chk = validate::validatelocalhostname($mysql_host); ($mysql_host_chk === false) { $mysql_host_chk = validate::validatedomain($mysql_host); ($mysql_host_chk === false) { throw new exception("invalid mysql server ip/hostname", 406); } } } $mysql_port = validate::validate($mysql_port, 'port', validate::regex_port, '', [3306], true); $privileged_password = validate::validate($privileged_password, 'password', '', '', [], true); $description = validate::validate(trim($description), 'description', validate::regex_desc_text, '', [], true); // keep old password? (empty($privileged_password)) { $privileged_password = $result['password']; } ($mysql_host != $result['host']) { // check whether server use customer $result_ms = $this-&gt;databasesonserver(true, $dbserver); ($result_ms &gt; 0) { throw new exception("unable update mysql-host still databases it", 406); } } // testing connection given credentials ($test_connection) { $options = array( pdo::mysql_attr_init_command =&gt; 'set names utf8' ); (!empty($mysql_ca)) { $options[pdo::mysql_attr_ssl_ca] = $mysql_ca; $options[pdo::mysql_attr_ssl_verify_server_cert] = (bool)$mysql_verifycert; } $dsn = "mysql:host=" . $mysql_host . ";port=" . $mysql_port . ";"; try { $db_test = new \pdo($dsn, $privileged_user, $privileged_password, $options); unset($db_test); } catch (pdoexception $e) { throw new exception("connection given mysql database could established. error-message: " . $e-&gt;getmessage(), $e-&gt;getcode()); } } // set new values sql_root array $sql_root[$dbserver] = [ 'caption' =&gt; $description, 'host' =&gt; $mysql_host, 'port' =&gt; $mysql_port, 'user' =&gt; $privileged_user, 'password' =&gt; $privileged_password, 'ssl' =&gt; [ 'cafile' =&gt; $mysql_ca ?? "", 'verifyservercertificate' =&gt; $mysql_verifycert ?? false ] ]; $this-&gt;generatenewuserdata($sql, $sql_root); ($allow_all_customers) { $this-&gt;adddatabasefromcustomerallowedlist($dbserver); } $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] edited database server '" . $description . "' (" . $mysql_host . ")"); return $this-&gt;response(['true']); } /** * check whether given customer / current user (as customer) * databases given dbserver * * @param int $mysql_server * @param int $customerid * optional, admin-only, select ftp-users specific customer id * @param string $loginname * optional, admin-only, select ftp-users specific customer loginname * * @access admin, customer * @return string json-encoded array count */ public function databasesonserver(bool $internal_all = false, int $dbserver = 0) { ($internal_all) { $result_stmt = database::prepare(" select count(*) num_dbs `" . table_panel_databases . "` `dbserver` = :dbserver "); $result = database::pexecute_first($result_stmt, ['dbserver' =&gt; $dbserver], true, true); return (int)$result['num_dbs']; } else { $dbserver = $this-&gt;getparam('mysql_server'); $customer_ids = $this-&gt;getallowedcustomerids(); $result_stmt = database::prepare(" select count(*) num_dbs `" . table_panel_databases . "` `customerid` (" . implode(", ", $customer_ids) . ") `dbserver` = :dbserver "); $result = database::pexecute_first($result_stmt, ['dbserver' =&gt; $dbserver], true, true); return $this-&gt;response(['count' =&gt; $result['num_dbs']]); } } private function removedatabasefromcustomerallowedlist(int $dbserver) { $sel_stmt = database::prepare(" select customerid, allowed_mysqlserver `" . table_panel_customers . "` "); database::pexecute($sel_stmt); $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `allowed_mysqlserver` = :am `customerid` = :cid "); ($customer = $sel_stmt-&gt;fetch(pdo::fetch_assoc)) { $allowed_mysqls = json_decode(($customer['allowed_mysqlserver'] ?? '[]'), true); (($key = array_search($dbserver, $allowed_mysqls)) !== false) { unset($allowed_mysqls[$key]); $allowed_mysqls = json_encode($allowed_mysqls); database::pexecute($upd_stmt, ['am' =&gt; $allowed_mysqls, 'cid' =&gt; $customer['customerid']]); } } } private function adddatabasefromcustomerallowedlist(int $dbserver) { $sel_stmt = database::prepare(" select customerid, allowed_mysqlserver `" . table_panel_customers . "` "); database::pexecute($sel_stmt); $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `allowed_mysqlserver` = :am `customerid` = :cid "); ($customer = $sel_stmt-&gt;fetch(pdo::fetch_assoc)) { $allowed_mysqls = json_decode(($customer['allowed_mysqlserver'] ?: '[]'), true); (!in_array($dbserver, $allowed_mysqls)) { $allowed_mysqls[] = $dbserver; $allowed_mysqls = json_encode($allowed_mysqls); database::pexecute($upd_stmt, ['am' =&gt; $allowed_mysqls, 'cid' =&gt; $customer['customerid']]); } } } /** * write new userdata.inc.php file */ private function generatenewuserdata(array $sql, array $sql_root) { $content = phphelper::parsearraytophpfile( ['sql' =&gt; $sql, 'sql_root' =&gt; $sql_root], 'automatically generated userdata.inc.php froxlor' ); chmod(froxlor::getinstalldir() . "/lib/userdata.inc.php", 0700); file_put_contents(froxlor::getinstalldir() . "/lib/userdata.inc.php", $content); chmod(froxlor::getinstalldir() . "/lib/userdata.inc.php", 0400); clearstatcache(); (function_exists('opcache_invalidate')) { @opcache_invalidate(froxlor::getinstalldir() . "/lib/userdata.inc.php", true); } } }</file><file name="lib/Froxlor/Api/Commands/DomainZones.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\dns\dns; use froxlor\froxlorlogger; use froxlor\idna\idnawrapper; use froxlor\settings; use froxlor\system\cronjob; use froxlor\ui\response; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class domainzones extends apicommand implements resourceentity { /** * add new dns zone given domain id domainname * * @param int $id * optional domain id * @param string $domainname * optional domain name * @param string $record * optional, default empty * @param string $type * optional, zone-entry type (a, aaaa, txt, etc.), default 'a' * @param int $prio * optional, priority, default empty * @param string $content * optional, default empty * @param int $ttl * optional, default 18000 * * @access admin, customer * @return string json-encoded array * @throws exception */ public function add() { (settings::get('system.dnsenabled') != '1') { throw new exception("dns service enabled system", 405); } ($this-&gt;isadmin() == false &amp;&amp; $this-&gt;getuserdetail('dnsenabled') != '1') { throw new exception("you cannot access resource", 405); } $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); // get requested domain $result = $this-&gt;apicall('subdomains.get', [ 'id' =&gt; $id, 'domainname' =&gt; $domainname ]); $id = $result['id']; // parameters $record = $this-&gt;getparam('record', true, null); $type = $this-&gt;getparam('type', true, 'a'); $prio = $this-&gt;getparam('prio', true, null); $content = $this-&gt;getparam('content', true, null); $ttl = $this-&gt;getparam('ttl', true, 18000); ($result['parentdomainid'] != '0') { throw new exception("dns zones generated main domain, subdomains", 406); } ($result['subisbinddomain'] != '1') { response::standarderror('dns_domain_nodns', '', true); } $idna_convert = new idnawrapper(); $domain = $idna_convert-&gt;encode($result['domain']); // select entries $sel_stmt = database::prepare("select * `" . table_domain_dns . "` domain_id = :did"); database::pexecute($sel_stmt, [ 'did' =&gt; $id ], true, true); $dom_entries = $sel_stmt-&gt;fetchall(pdo::fetch_assoc); // validation $errors = []; (empty(trim($record))) { $record = "@"; } $record = trim(strtolower($record)); ($record != '@' &amp;&amp; $record != '*') { // validate record (strpos($record, '--') !== false) { $errors[] = lng('error.domain_nopunycode'); } else { // check wildcard-record $add_wildcard_again = false; (substr($record, 0, 2) == '*.') { $record = substr($record, 2); $add_wildcard_again = true; } // convert entry $record = $idna_convert-&gt;encode($record); ($add_wildcard_again) { $record = '*.' . $record; } (strlen($record) &gt; 63) { $errors[] = lng('error.dns_record_toolong'); } } } // todo regex validate content invalid characters ($ttl &lt;= 0) { $ttl = 18000; } $content = trim($content); (empty($content)) { $errors[] = lng('error.dns_content_empty'); } // types ($type == 'a' &amp;&amp; filter_var($content, filter_validate_ip, filter_flag_ipv4) === false) { $errors[] = lng('error.dns_arec_noipv4'); } elseif ($type == 'a') { // check whether cname-record resource foreach ($dom_entries $existing_entries) { ($existing_entries['type'] == 'cname' &amp;&amp; $existing_entries['record'] == $record) { $errors[] = lng('error.dns_other_nomorerr'); break; } } } elseif ($type == 'aaaa' &amp;&amp; filter_var($content, filter_validate_ip, filter_flag_ipv6) === false) { $errors[] = lng('error.dns_aaaarec_noipv6'); } elseif ($type == 'aaaa') { // check whether cname-record resource foreach ($dom_entries $existing_entries) { ($existing_entries['type'] == 'cname' &amp;&amp; $existing_entries['record'] == $record) { $errors[] = lng('error.dns_other_nomorerr'); break; } } } elseif ($type == 'caa' &amp;&amp; !empty($content)) { $re = '/(?\'critical\'\d+)\h*(?\'type\'iodef|issue|issuewild)\h*(?\'value\'(?\'issuevalue\'"(?\'domain\'(?=.{3,128}$)(?&gt;(?&gt;[a-za-z0-9]+[a-za-z0-9-]*[a-za-z0-9]+|[a-za-z0-9]+)\.)*(?&gt;[a-za-z]{2,}|[a-za-z0-9]{2,}\.[a-za-z]{2,}))[;\h]*(?\'parameters\'(?&gt;[a-za-z0-9]{1,60}=[a-za-z0-9:\.\/\-]{1,60}\h*)+)?")|(?\'iodefvalue\'"(?\'url\'(mailto:.*|http:\/\/.*|https:\/\/.*))"))/'; preg_match($re, $content, $matches); (empty($matches)) { $errors[] = lng('error.dns_content_invalid'); } elseif (($matches['type'] == 'issue' || $matches['type'] == 'issuewild') &amp;&amp; !validate::validatedomain($matches['domain'])) { $errors[] = lng('error.dns_content_invalid'); } elseif ($matches['type'] == 'iodef' &amp;&amp; !validate::validateurl($matches['url'])) { $errors[] = lng('error.dns_content_invalid'); } else { $content = $matches[0]; } } elseif ($type == 'cname' || $type == 'dname') { // check trailing dot (substr($content, -1) == '.') { // remove checks $content = substr($content, 0, -1); } else { // add domain name $content .= '.' . $domain; } (!validate::validatedomain($content, true)) { $errors[] = lng('error.dns_cname_invaliddom'); } else { // check whether rr-records resource foreach ($dom_entries $existing_entries) { (($existing_entries['type'] == 'a' || $existing_entries['type'] == 'aaaa' || $existing_entries['type'] == 'mx' || $existing_entries['type'] == 'ns') &amp;&amp; $existing_entries['record'] == $record) { $errors[] = lng('error.dns_cname_nomorerr'); break; } } // check www-alias setting ($result['wwwserveralias'] == '1' &amp;&amp; $result['iswildcarddomain'] == '0' &amp;&amp; $record == 'www') { $errors[] = lng('error.no_wwwcnamae_ifwwwalias'); } } // append trailing dot (again) $content .= '.'; } elseif ($type == 'loc' &amp;&amp; !empty($content)) { $content = $content; } elseif ($type == 'mx') { ($prio === null || $prio &lt; 0) { $errors[] = lng('error.dns_mx_prioempty'); } // check trailing dot (substr($content, -1) == '.') { // remove checks $content = substr($content, 0, -1); } (!empty($content) &amp;&amp; !validate::validatedomain($content)) { $errors[] = lng('error.dns_mx_needdom'); } else { // check whether cname-record resource foreach ($dom_entries $existing_entries) { $fqdn = $existing_entries['record'] . '.' . $domain; ($existing_entries['type'] == 'cname' &amp;&amp; $fqdn == $content) { $errors[] = lng('error.dns_mx_noalias'); break; } elseif ($existing_entries['type'] == 'cname' &amp;&amp; $existing_entries['record'] == $record) { $errors[] = lng('error.dns_other_nomorerr'); break; } } } // append trailing dot (again) $content .= '.'; // content ".", prio needs 0 results "null mx" entry ($content == '.' &amp;&amp; $prio != 0) { $prio = 0; } } elseif ($type == 'ns') { // check trailing dot (substr($content, -1) == '.') { // remove checks $content = substr($content, 0, -1); } (!validate::validatedomain($content)) { $errors[] = lng('error.dns_ns_invaliddom'); } else { // check whether cname-record resource foreach ($dom_entries $existing_entries) { ($existing_entries['type'] == 'cname' &amp;&amp; $existing_entries['record'] == $record) { $errors[] = lng('error.dns_other_nomorerr'); break; } } } // append trailing dot (again) $content .= '.'; } elseif ($type == 'rp' &amp;&amp; !empty($content)) { $content = $content; } elseif ($type == 'srv') { ($prio === null || $prio &lt; 0) { $errors[] = lng('error.dns_srv_prioempty'); } // check last part content, look like: // _service._proto.name. ttl class srv priority weight port target. $_split_content = explode(" ", $content); // srv content must [weight] [port] [target] (count($_split_content) != 3) { $errors[] = lng('error.dns_srv_invalidcontent'); } $target = trim($_split_content[count($_split_content) - 1]); ($target != '.') { // check trailing dot (substr($target, -1) == '.') { // remove checks $target = substr($target, 0, -1); } } ($target != '.' &amp;&amp; !validate::validatedomain($target, true)) { $errors[] = lng('error.dns_srv_needdom'); } else { // check whether cname-record resource foreach ($dom_entries $existing_entries) { $fqdn = $existing_entries['record'] . '.' . $domain; ($existing_entries['type'] == 'cname' &amp;&amp; $fqdn == $target) { $errors[] = lng('error.dns_srv_noalias'); break; } } } // append trailing dot there's none (substr($content, -1) != '.') { $content .= '.'; } } elseif ($type == 'sshfp' &amp;&amp; !empty($content)) { $content = $content; } elseif ($type == 'tlsa' &amp;&amp; !empty($content)) { $content = $content; } elseif ($type == 'txt' &amp;&amp; !empty($content)) { // check txt content enclosed " " $content = dns::enclosetxtcontent($content); } $new_entry = [ 'record' =&gt; $record, 'type' =&gt; $type, 'prio' =&gt; (int)$prio, 'content' =&gt; $content, 'ttl' =&gt; (int)$ttl, 'domain_id' =&gt; (int)$id ]; ksort($new_entry); // check duplicate foreach ($dom_entries $existing_entry) { // compare json-encoded string array $check_entry = $existing_entry; // new entry id yet unset($check_entry['id']); // sort key ksort($check_entry); // format integer fields real integer (as read string db) $check_entry['prio'] = (int)$check_entry['prio']; $check_entry['ttl'] = (int)$check_entry['ttl']; $check_entry['domain_id'] = (int)$check_entry['domain_id']; // encode $check_entry = json_encode($check_entry); $new = json_encode($new_entry); // compare ($check_entry === $new) { $errors[] = lng('error.dns_duplicate_entry'); unset($check_entry); break; } } (empty($errors)) { $ins_stmt = database::prepare(" insert `" . table_domain_dns . "` set `record` = :record, `type` = :type, `prio` = :prio, `content` = :content, `ttl` = :ttl, `domain_id` = :domain_id "); database::pexecute($ins_stmt, $new_entry, true, true); $new_entry_id = database::lastinsertid(); // add temporary entries-array (no reread db necessary) $new_entry['id'] = $new_entry_id; $dom_entries[] = $new_entry; // re-generate bind configs cronjob::inserttask(taskid::rebuild_dns); $result = $this-&gt;apicall('domainzones.get', [ 'id' =&gt; $id ]); return $this-&gt;response($result); } // return $errors throw new exception(implode("\n", $errors), 406); } /** * return domain-dns entry either id domainname * * @param int $id * optional, domain id * @param string $domainname * optional, domain name * * @access admin, customer * @return string json-encoded array * @throws exception */ public function get() { (settings::get('system.dnsenabled') != '1') { throw new exception("dns service enabled system", 405); } ($this-&gt;isadmin() == false &amp;&amp; $this-&gt;getuserdetail('dnsenabled') != '1') { throw new exception("you cannot access resource", 405); } $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); // get requested domain $result = $this-&gt;apicall('subdomains.get', [ 'id' =&gt; $id, 'domainname' =&gt; $domainname ]); $id = $result['id']; ($result['parentdomainid'] != '0') { throw new exception("dns zones generated main domain, subdomains", 406); } ($result['subisbinddomain'] != '1') { response::standarderror('dns_domain_nodns', '', true); } $zone = dns::createdomainzone($id); $zonefile = (string)$zone; $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] get dns-zone '" . $result['domain'] . "'"); return $this-&gt;response(explode("\n", $zonefile)); } /** * cannot update dns zone entry. * need delete re-add it. */ public function update() { throw new exception('you cannot update dns zone entry. need delete re-add it.', 303); } /** * list entry records given domain either id domainname * * @param int $id * optional, domain id * @param string $domainname * optional, domain name * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin, customer * @return bool * @throws exception */ public function listing() { (settings::get('system.dnsenabled') != '1') { throw new exception("dns service enabled system", 405); } ($this-&gt;isadmin() == false &amp;&amp; $this-&gt;getuserdetail('dnsenabled') != '1') { throw new exception("you cannot access resource", 405); } $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); // get requested domain $result = $this-&gt;apicall('subdomains.get', [ 'id' =&gt; $id, 'domainname' =&gt; $domainname ]); $id = $result['id']; $query_fields = []; $sel_stmt = database::prepare("select * `" . table_domain_dns . "` `domain_id` = :did" . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); $query_fields['did'] = $id; database::pexecute($sel_stmt, $query_fields, true, true); $result = []; ($row = $sel_stmt-&gt;fetch(pdo::fetch_assoc)) { $result[] = $row; } return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } /** * returns total number domainzone-entries given domain * * @param int $id * optional, domain id * @param string $domainname * optional, domain name * * @access admin, customer * @return string json-encoded response message * @throws exception */ public function listingcount() { (settings::get('system.dnsenabled') != '1') { throw new exception("dns service enabled system", 405); } ($this-&gt;isadmin() == false &amp;&amp; $this-&gt;getuserdetail('dnsenabled') != '1') { throw new exception("you cannot access resource", 405); } $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); // get requested domain $result = $this-&gt;apicall('subdomains.get', [ 'id' =&gt; $id, 'domainname' =&gt; $domainname ]); $id = $result['id']; $sel_stmt = database::prepare("select count(*) num_dns `" . table_domain_dns . "` `domain_id` = :did"); $result = database::pexecute_first($sel_stmt, [ 'did' =&gt; $id ], true, true); ($result) { return $this-&gt;response($result['num_dns']); } return $this-&gt;response(0); } /** * deletes domain-dns entry id * * @param int $entry_id * @param int $id * optional, domain id * @param string $domainname * optional, domain name * * @access admin, customer * @return bool * @throws exception */ public function delete() { (settings::get('system.dnsenabled') != '1') { throw new exception("dns service enabled system", 405); } ($this-&gt;isadmin() == false &amp;&amp; $this-&gt;getuserdetail('dnsenabled') != '1') { throw new exception("you cannot access resource", 405); } $entry_id = $this-&gt;getparam('entry_id'); $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $domainname = $this-&gt;getparam('domainname', $dn_optional, ''); // get requested domain $result = $this-&gt;apicall('subdomains.get', [ 'id' =&gt; $id, 'domainname' =&gt; $domainname ]); $id = $result['id']; $del_stmt = database::prepare("delete `" . table_domain_dns . "` `id` = :id `domain_id` = :did"); database::pexecute($del_stmt, [ 'id' =&gt; $entry_id, 'did' =&gt; $id ], true, true); ($del_stmt-&gt;rowcount() &gt; 0) { // re-generate bind configs cronjob::inserttask(taskid::rebuild_dns); return $this-&gt;response(true); } return $this-&gt;response(true, 304); } }</file><file name="lib/Froxlor/Api/Commands/Emails.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\froxlorlogger; use froxlor\idna\idnawrapper; use froxlor\settings; use froxlor\system\cronjob; use froxlor\ui\response; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class emails extends apicommand implements resourceentity { /** * add new email address * * @param string $email_part * name address @ * @param string $domain * domain-name email-address * @param float $spam_tag_level * optional, score required tag emails spam, default: 7.0 * @param bool $rewrite_subject * optional, whether add ***spam*** email's subject applicable, default: [antispam.default_spam_rewrite_subject] * @param float $spam_kill_level * optional, score required discard emails, default: 14.0 * @param boolean $bypass_spam * optional, disable spam-filter entirely, default: [antispam.default_bypass_spam] * @param boolean $policy_greylist * optional, enable grey-listing, default: [antispam.default_policy_greylist] * @param boolean $iscatchall * optional, make address catchall address, default: * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param string $description * optional custom description (currently used/shown frontend), default empty * * @access admin, customer * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } ($this-&gt;getuserdetail('emails_used') &lt; $this-&gt;getuserdetail('emails') || $this-&gt;getuserdetail('emails') == '-1') { // required parameters $email_part = $this-&gt;getparam('email_part'); $domain = $this-&gt;getparam('domain'); // parameters $spam_tag_level = $this-&gt;getparam('spam_tag_level', true, '7.0'); $spam_kill_level = $this-&gt;getulparam('spam_kill_level', 'spam_kill_level_ul', true, '14.0'); $iscatchall = $this-&gt;getboolparam('iscatchall', true, 0); $description = $this-&gt;getparam('description', true, ''); ((int)settings::get('antispam.default_spam_rewrite_subject') &lt;= 2) { $rewrite_subject = $this-&gt;getboolparam('rewrite_subject', true, (int)settings::get('antispam.default_spam_rewrite_subject') == 1 ? 1 : 0); } else { $rewrite_subject = (int)settings::get('antispam.default_spam_rewrite_subject') == 3 ? 1 : 0; } ((int)settings::get('antispam.default_bypass_spam') &lt;= 2) { $bypass_spam = $this-&gt;getboolparam('bypass_spam', true, (int)settings::get('antispam.default_bypass_spam') == 1 ? 1 : 0); } else { $bypass_spam = (int)settings::get('antispam.default_bypass_spam') == 3 ? 1 : 0; } ((int)settings::get('antispam.default_policy_greylist') &lt;= 2) { $policy_greylist = $this-&gt;getboolparam('policy_greylist', true, (int)settings::get('antispam.default_policy_greylist') == 1 ? 1 : 0); } else { $policy_greylist = (int)settings::get('antispam.default_policy_greylist') == 3 ? 1 : 0; } // validation $idna_convert = new idnawrapper(); (substr($domain, 0, 4) != 'xn--') { $domain = $idna_convert-&gt;encode(validate::validate($domain, 'domain', '', '', [], true)); } $email_part = $idna_convert-&gt;encode($email_part); // check domain whether email-enabled domain // use internal call customer might 'domains' customer_hide_options $domain_check = $this-&gt;apicall('subdomains.get', [ 'domainname' =&gt; $domain ], true); ((int)$domain_check['isemaildomain'] == 0) { response::standarderror('maindomainnonexist', $idna_convert-&gt;decode($domain), true); } ((int)$domain_check['deactivated'] == 1) { response::standarderror('maindomaindeactivated', $idna_convert-&gt;decode($domain), true); } (settings::get('catchall.catchall_enabled') != '1') { $iscatchall = 0; } // check catchall-flag ($iscatchall) { $iscatchall = '1'; $email = '@' . $domain; } else { $iscatchall = '0'; $email = $email_part . '@' . $domain; } // full email value $email_full = $email_part . '@' . $domain; // validate (!validate::validateemail($email_full)) { response::standarderror('emailiswrong', $idna_convert-&gt;decode($email_full), true); } // get needed customer info reduce email-address-counter one $customer = $this-&gt;getcustomerdata('emails'); // duplicate check $stmt = database::prepare(" select `id`, `email`, `email_full`, `iscatchall`, `destination`, `customerid` `" . table_mail_virtual . "` (`email` = :email `email_full` = :emailfull ) `customerid`= :cid "); $params = [ "email" =&gt; $email, "emailfull" =&gt; $email_full, "cid" =&gt; $customer['customerid'] ]; $email_check = database::pexecute_first($stmt, $params, true, true); ($email_check) { (strtolower($email_check['email_full']) == strtolower($email_full)) { response::standarderror('emailexistalready', $idna_convert-&gt;decode($email_full), true); } elseif ($email_check['email'] == $email) { response::standarderror('youhavealreadyacatchallforthisdomain', '', true); } } $spam_tag_level = validate::validate($spam_tag_level, 'spam_tag_level', '/^\d{1,}(\.\d{1})?$/', '', [7.0], true); ($spam_kill_level &gt; -1) { $spam_kill_level = validate::validate($spam_kill_level, 'spam_kill_level', '/^\d{1,}(\.\d{1})?$/', '', [14.0], true); } $description = validate::validate(trim($description), 'description', validate::regex_desc_text, '', [], true); $stmt = database::prepare(" insert `" . table_mail_virtual . "` set `customerid` = :cid, `email` = :email, `email_full` = :email_full, `spam_tag_level` = :spam_tag_level, `rewrite_subject` = :rewrite_subject, `spam_kill_level` = :spam_kill_level, `bypass_spam` = :bypass_spam, `policy_greylist` = :policy_greylist, `iscatchall` = :iscatchall, `domainid` = :domainid, `description` = :description "); $params = [ "cid" =&gt; $customer['customerid'], "email" =&gt; $email, "email_full" =&gt; $email_full, "spam_tag_level" =&gt; $spam_tag_level, "rewrite_subject" =&gt; $rewrite_subject, "spam_kill_level" =&gt; $spam_kill_level, "bypass_spam" =&gt; $bypass_spam, "policy_greylist" =&gt; $policy_greylist, "iscatchall" =&gt; $iscatchall, "domainid" =&gt; $domain_check['id'], "description" =&gt; $description ]; database::pexecute($stmt, $params, true, true); // update customer usage customers::increaseusage($customer['customerid'], 'emails_used'); cronjob::inserttask(taskid::rebuild_rspamd); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] added email address '" . $email_full . "'"); $result = $this-&gt;apicall('emails.get', [ 'emailaddr' =&gt; $email_full ]); return $this-&gt;response($result); } throw new exception("no resources available", 406); } /** * return email-address entry either id email-address * * @param int $id * optional, email-address-id * @param string $emailaddr * optional, email-address * * @access admin, customer * @return string json-encoded array * @throws exception */ public function get() { $id = $this-&gt;getparam('id', true, 0); $ea_optional = $id &gt; 0; $emailaddr = $this-&gt;getparam('emailaddr', $ea_optional, ''); $params = []; $customer_ids = $this-&gt;getallowedcustomerids('email'); $params['idea'] = ($id &lt;= 0 ? $emailaddr : $id); $result_stmt = database::prepare("select v.*, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize` " . ($this-&gt;isinternal() ? ", `u`.`homedir`, `u`.`maildir`" : "") . " `" . table_mail_virtual . "` v left join `" . table_mail_users . "` u v.`popaccountid` = u.`id` v.`customerid` (" . implode(", ", $customer_ids) . ") " . (is_numeric($params['idea']) ? "v.`id`= :idea" : "(v.`email` = :idea v.`email_full` = :idea)" )); $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] get email address '" . $result['email_full'] . "'"); return $this-&gt;response($result); } $key = ($id &gt; 0 ? "id #" . $id : "emailaddr '" . $emailaddr . "'"); throw new exception("email address " . $key . " could found", 404); } /** * toggle catchall flag given email address either id email-address * * @param int $id * optional, email-address-id * @param string $emailaddr * optional, email-address * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param float $spam_tag_level * optional, score required tag emails spam, default: 7.0 * @param bool $rewrite_subject * optional, whether add ***spam*** email's subject applicable, default: [antispam.default_spam_rewrite_subject] * @param float $spam_kill_level * optional, score required discard emails, default: 14.0 * @param boolean $bypass_spam * optional, disable spam-filter entirely, default: [antispam.default_bypass_spam] * @param boolean $policy_greylist * optional, enable grey-listing, default: [antispam.default_policy_greylist] * @param boolean $iscatchall * optional * @param string $description * optional custom description (currently used/shown frontend), default empty * * @access admin, customer * @return string json-encoded array * @throws exception */ public function update() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } $id = $this-&gt;getparam('id', true, 0); $ea_optional = $id &gt; 0; $emailaddr = $this-&gt;getparam('emailaddr', $ea_optional, ''); $result = $this-&gt;apicall('emails.get', [ 'id' =&gt; $id, 'emailaddr' =&gt; $emailaddr ]); $id = $result['id']; // parameters $spam_tag_level = $this-&gt;getparam('spam_tag_level', true, $result['spam_tag_level']); $spam_kill_level = $this-&gt;getulparam('spam_kill_level', 'spam_kill_level_ul', true, $result['spam_kill_level']); $iscatchall = $this-&gt;getboolparam('iscatchall', true, $result['iscatchall']); $description = $this-&gt;getparam('description', true, $result['description']); ((int)settings::get('antispam.default_spam_rewrite_subject') &lt;= 2) { $rewrite_subject = $this-&gt;getboolparam('rewrite_subject', true, $result['rewrite_subject']); } else { $rewrite_subject = (int)settings::get('antispam.default_spam_rewrite_subject') == 3 ? 1 : 0; } ((int)settings::get('antispam.default_bypass_spam') &lt;= 2) { $bypass_spam = $this-&gt;getboolparam('bypass_spam', true, $result['bypass_spam']); } else { $bypass_spam = (int)settings::get('antispam.default_bypass_spam') == 3 ? 1 : 0; } ((int)settings::get('antispam.default_policy_greylist') &lt;= 2) { $policy_greylist = $this-&gt;getboolparam('policy_greylist', true, $result['policy_greylist']); } else { $policy_greylist = (int)settings::get('antispam.default_policy_greylist') == 3 ? 1 : 0; } // enabling catchall allowed settings, need // run update() ($iscatchall &amp;&amp; $result['iscatchall'] == 0 &amp;&amp; settings::get('catchall.catchall_enabled') != '1') { response::standarderror([ 'operationnotpermitted', 'featureisdisabled' ], 'catchall', true); } // get needed customer info reduce email-address-counter one $customer = $this-&gt;getcustomerdata(); // check catchall-flag $email = $result['email_full']; ($iscatchall) { $iscatchall = '1'; $email = $result['email']; // update required catchall ($result['iscatchall'] == 0) { $email_parts = explode('@', $result['email_full']); $email = '@' . $email_parts[1]; // catchall check $stmt = database::prepare(" select `email_full` `" . table_mail_virtual . "` `email` = :email `customerid` = :cid `iscatchall` = '1' "); $params = [ "email" =&gt; $email, "cid" =&gt; $customer['customerid'] ]; $email_check = database::pexecute_first($stmt, $params, true, true); ($email_check) { response::standarderror('youhavealreadyacatchallforthisdomain', '', true); } } } $spam_tag_level = validate::validate($spam_tag_level, 'spam_tag_level', '/^\d{1,}(\.\d{1,2})?$/', '', [7.0], true); ($spam_kill_level &gt; -1) { $spam_kill_level = validate::validate($spam_kill_level, 'spam_kill_level', '/^\d{1,}(\.\d{1,2})?$/', '', [14.0], true); } $description = validate::validate(trim($description), 'description', validate::regex_desc_text, '', [], true); $stmt = database::prepare(" update `" . table_mail_virtual . "` set `email` = :email , `spam_tag_level` = :spam_tag_level, `rewrite_subject` = :rewrite_subject, `spam_kill_level` = :spam_kill_level, `bypass_spam` = :bypass_spam, `policy_greylist` = :policy_greylist, `iscatchall` = :caflag, `description` = :description `customerid`= :cid `id`= :id "); $params = [ "email" =&gt; $email, "spam_tag_level" =&gt; $spam_tag_level, "rewrite_subject" =&gt; $rewrite_subject, "spam_kill_level" =&gt; $spam_kill_level, "bypass_spam" =&gt; $bypass_spam, "policy_greylist" =&gt; $policy_greylist, "caflag" =&gt; $iscatchall, "description" =&gt; $description, "cid" =&gt; $customer['customerid'], "id" =&gt; $id ]; database::pexecute($stmt, $params, true, true); cronjob::inserttask(taskid::rebuild_rspamd); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] toggled catchall-flag email address '" . $result['email_full'] . "'"); $result = $this-&gt;apicall('emails.get', [ 'emailaddr' =&gt; $result['email_full'] ]); return $this-&gt;response($result); } /** * list email addresses, called admin, list email addresses customers allowed * view, specify id loginname one specific customer * * @param int $customerid * optional, admin-only, select email addresses specific customer id * @param string $loginname * optional, admin-only, select email addresses specific customer loginname * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin, customer * @return string json-encoded array count|list * @throws exception */ public function listing() { $customer_ids = $this-&gt;getallowedcustomerids('email'); $result = []; $query_fields = []; $result_stmt = database::prepare(" select m.*, d.`domain`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize` `" . table_mail_virtual . "` left join `" . table_panel_domains . "` (m.`domainid` = d.`id`) left join `" . table_mail_users . "` u (m.`popaccountid` = u.`id`) m.`customerid` (" . implode(", ", $customer_ids) . ")" . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); database::pexecute($result_stmt, $query_fields, true, true); $idna_convert = new idnawrapper(); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $row['email'] = $idna_convert-&gt;decode($row['email']); $row['email_full'] = $idna_convert-&gt;decode($row['email_full']); $result[] = $row; } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] list email-addresses"); return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } /** * returns total number accessible email addresses * * @param int $customerid * optional, admin-only, select email addresses specific customer id * @param string $loginname * optional, admin-only, select email addresses specific customer loginname * * @access admin, customer * @return string json-encoded response message * @throws exception */ public function listingcount() { $customer_ids = $this-&gt;getallowedcustomerids('email'); $result_stmt = database::prepare(" select count(*) num_emails `" . table_mail_virtual . "` left join `" . table_panel_domains . "` (m.`domainid` = d.`id`) left join `" . table_mail_users . "` u (m.`popaccountid` = u.`id`) m.`customerid` (" . implode(", ", $customer_ids) . ") "); $result = database::pexecute_first($result_stmt, null, true, true); ($result) { return $this-&gt;response($result['num_emails']); } return $this-&gt;response(0); } /** * delete email address either id username * * @param int $id * optional, email-address-id * @param string $emailaddr * optional, email-address * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * @param boolean $delete_userfiles * optional, delete email data filesystem, default: 0 (false) * * @access admin, customer * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'email')) { throw new exception("you cannot access resource", 405); } $id = $this-&gt;getparam('id', true, 0); $ea_optional = $id &gt; 0; $emailaddr = $this-&gt;getparam('emailaddr', $ea_optional, ''); $result = $this-&gt;apicall('emails.get', [ 'id' =&gt; $id, 'emailaddr' =&gt; $emailaddr ]); $id = $result['id']; // parameters $delete_userfiles = $this-&gt;getboolparam('delete_userfiles', true, 0); // get needed customer info reduce email-address-counter one $customer = $this-&gt;getcustomerdata(); // check forwarders $number_forwarders = 0; ($result['destination'] != '') { $result['destination'] = explode(' ', $result['destination']); $number_forwarders = count($result['destination']); } // check whether address account ($result['popaccountid'] != 0) { // use emailaccounts.delete $this-&gt;apicall('emailaccounts.delete', [ 'id' =&gt; $result['id'], 'customerid' =&gt; $customer['customerid'], 'delete_userfiles' =&gt; $delete_userfiles ]); $number_forwarders--; } // decrease forwarder counter customers::decreaseusage($customer['customerid'], 'email_forwarders_used', '', $number_forwarders); admins::decreaseusage($customer['customerid'], 'email_forwarders_used', '', $number_forwarders); // delete address $stmt = database::prepare("delete `" . table_mail_virtual . "` `customerid`= :customerid `id`= :id"); database::pexecute($stmt, [ "customerid" =&gt; $customer['customerid'], "id" =&gt; $id ], true, true); customers::decreaseusage($customer['customerid'], 'emails_used'); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_warning, "[api] deleted email address '" . $result['email_full'] . "'"); return $this-&gt;response($result); } }</file><file name="lib/Froxlor/Api/Commands/Froxlor.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\database\integritycheck; use froxlor\froxlorlogger; use froxlor\install\autoupdate; use froxlor\install\update; use froxlor\settings; use froxlor\simexporter; use froxlor\system\cronjob; use froxlor\system\crypt; use froxlor\validate\validate; use pdo; use recursivedirectoryiterator; use recursiveiteratoriterator; use reflectionclass; use reflectionexception; use reflectionmethod; /** * @since 0.10.0 */ class froxlor extends apicommand { const update_check_interval = 21600; // 6 hrs /** * checks whether newer version froxlor available * * @param bool $force optional, force live update-check * * @access admin * @return string json-encoded array * @throws exception */ public function checkupdate() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings')) { $uc_data = update::getupdatecheckdata(); $force_ucheck = $this-&gt;getboolparam('force', true, 0); $response = $uc_data['data'] ?? []; (empty($uc_data) || empty($response) || $uc_data['ts'] + self::update_check_interval &lt; time() || $uc_data['channel'] != settings::get('system.update_channel') || $force_ucheck) { // log actions $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_info, "[api] checking updates"); // check new version $aucheck = autoupdate::checkversion(); $response = []; ($aucheck == 1) { // anzeige ber version-status mit ggfls. formular // zum update schritt #1 -&gt; download $text = lng('update.uc_newinfo', [(settings::get('system.update_channel') != 'stable' ? settings::get('system.update_channel').' ' : ''), autoupdate::getfromresult('version'), $this-&gt;version]); $response = [ 'isnewerversion' =&gt; (int) !autoupdate::getfromresult('has_latest'), 'version' =&gt; $this-&gt;version, 'message' =&gt; $text, 'link' =&gt; autoupdate::getfromresult('url'), 'additional_info' =&gt; autoupdate::getfromresult('info'), 'aucheck' =&gt; $aucheck ]; } elseif ($aucheck &lt; 0 || $aucheck &gt; 1) { // errors ($aucheck &lt; 0) { $errmsg = autoupdate::getlasterror(); } else { ($aucheck == 3) { $errmsg = lng('error.customized_version'); } else { $errmsg = lng('error.autoupdate_' . $aucheck); } } $response = [ 'isnewerversion' =&gt; 0, 'version' =&gt; $this-&gt;version, 'message' =&gt; '', 'link' =&gt; '', 'additional_info' =&gt; $errmsg, 'aucheck' =&gt; $aucheck ]; } else { $response = [ 'isnewerversion' =&gt; 0, 'version' =&gt; $this-&gt;version, 'message' =&gt; '', 'link' =&gt; '', 'additional_info' =&gt; autoupdate::getfromresult('info'), 'aucheck' =&gt; $aucheck ]; } update::storeupdatecheckdata($response); } return $this-&gt;response($response); } throw new exception("not allowed execute given command.", 403); } /** * import settings * * @param string $json_str * content exported froxlor-settings json file * * @access admin * @return string json-encoded bool * @throws exception */ public function importsettings() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings')) { $json_str = $this-&gt;getparam('json_str'); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "user " . $this-&gt;getuserdetail('loginname') . " imported settings"); try { simexporter::import($json_str); cronjob::inserttask(taskid::rebuild_vhost); cronjob::inserttask(taskid::create_quota); // using nameserver, insert task rebuilds server config cronjob::inserttask(taskid::rebuild_dns); // cron.d file cronjob::inserttask(taskid::rebuild_cron); return $this-&gt;response(true); } catch (exception $e) { throw new exception($e-&gt;getmessage(), 406); } } throw new exception("not allowed execute given command.", 403); } /** * export settings * * @access admin * @return string json-string * @throws exception */ public function exportsettings() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings')) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "user " . $this-&gt;getuserdetail('loginname') . " exported settings"); $json_export = simexporter::export(); return $this-&gt;response($json_export); } throw new exception("not allowed execute given command.", 403); } /** * return list settings * * @access admin * @return string json-encoded array count|list * @throws exception */ public function listsettings() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings')) { $sel_stmt = database::prepare(" select * `" . table_panel_settings . "` order settinggroup asc, varname asc "); database::pexecute($sel_stmt, null, true, true); $result = []; ($row = $sel_stmt-&gt;fetch(pdo::fetch_assoc)) { $result[] = [ 'key' =&gt; $row['settinggroup'] . '.' . $row['varname'], 'value' =&gt; $row['value'] ]; } return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } throw new exception("not allowed execute given command.", 403); } /** * return setting settinggroup.varname couple * * @param string $key * settinggroup.varname couple * * @access admin * @return string * @throws exception */ public function getsetting() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings')) { $setting = $this-&gt;getparam('key'); return $this-&gt;response(settings::get($setting)); } throw new exception("not allowed execute given command.", 403); } /** * updates setting * * @param string $key * settinggroup.varname couple * @param string $value * optional new value, default '' * * @access admin * @return string * @throws exception */ public function updatesetting() { // currently implemented requires validation wrong settings stored via api throw new exception("not available yet.", 501); ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings')) { $setting = $this-&gt;getparam('key'); $value = $this-&gt;getparam('value', true, ''); $oldvalue = settings::get($setting); (is_null($oldvalue)) { throw new exception("setting '" . $setting . "' could found"); } $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] changing setting '" . $setting . "' '" . $oldvalue . "' '" . $value . "'"); return $this-&gt;response(settings::set($setting, $value, true)); } throw new exception("not allowed execute given command.", 403); } /** * returns random password based froxlor settings min-length, included characters, etc. * * @param int $length * optional length password, defaults 0 (panel.password_min_length) * * @access admin, customer * @return string * @throws exception */ public function generatepassword(): string { $length = $this-&gt;getparam('length', true, 0); return $this-&gt;response(crypt::generatepassword($length)); } /** * return one-time login link url given user * * @param int $customerid optional, required $loginname specified, user create link * @param string $loginname optional, required $customerid specified, user create link * @param int $valid_time optional, value seconds long link valid, default 10 seconds, valid values numbers 10 120 * @param string $allowed_from optional, comma separated list ip addresses networks allow login via link * * @access admin * @return string json-encoded array [base =&gt; domain, uri =&gt; relative link] * @throws exception */ public function generateloginlink() { ($this-&gt;isadmin()) { $customer = $this-&gt;getcustomerdata(); // cannot create link deactivated users ((int)$customer['deactivated'] == 1) { throw new exception("cannot generate link deactivated user", 406); } $valid_time = (int)$this-&gt;getparam('valid_time', true, 10); $allowed_from = $this-&gt;getparam('allowed_from', true, ''); $valid_time = validate::validate($valid_time, 'valid time', '/^(1[0-1][0-9]|120|[1-9][0-9])$/', 'invalid_validtime', [10], true); // validate allowed_from (!empty($allowed_from)) { $ip_list = array_map('trim', explode(",", $allowed_from)); $_check_list = $ip_list; foreach ($_check_list $idx =&gt; $ip) { (validate::validate_ip2($ip, true, 'invalidip', true, true, true) == false) { throw new exception('invalid ip address', 406); } // check cidr (strpos($ip, '/') !== false) { $ipparts = explode("/", $ip); // shorten ip $ip = inet_ntop(inet_pton($ipparts[0])); // re-add cidr $ip .= '/' . $ipparts[1]; } else { // shorten ip $ip = inet_ntop(inet_pton($ip)); } $ip_list[$idx] = $ip; } $allowed_from = implode(",", array_unique($ip_list)); } $hash = hash('sha256', openssl_random_pseudo_bytes(64 * 64)); $ins_stmt = database::prepare(" insert `" . table_panel_loginlinks . "` set `hash` = :hash, `loginname` = :loginname, `valid_until` = :validuntil, `allowed_from` = :allowedfrom duplicate key update `hash` = :hash, `valid_until` = :validuntil, `allowed_from` = :allowedfrom "); database::pexecute($ins_stmt, [ 'hash' =&gt; $hash, 'loginname' =&gt; $customer['loginname'], 'validuntil' =&gt; time() + $valid_time, 'allowedfrom' =&gt; $allowed_from ]); return $this-&gt;response([ 'base' =&gt; 'https://' . settings::get('system.hostname') . '/' . (settings::get('system.froxlordirectlyviahostname') != 1 ? basename(\froxlor\froxlor::getinstalldir()) . '/' : ''), 'uri' =&gt; 'index.php?action=ll&amp;ln=' . $customer['loginname'] . '&amp;h=' . $hash ]); } throw new exception("not allowed execute given command.", 403); } /** * used remotely run integritiy checks froxlor implements * * @access admin * @return string * @throws exception */ public function integritycheck() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings')) { $integrity = new integritycheck(); $result = $integrity-&gt;checkall(); ($result) { return $this-&gt;response(null, 204); } throw new exception("some checks failed.", 406); } throw new exception("not allowed execute given command.", 403); } /** * returns list available api functions * * @param string $module * optional, return list functions specific module * @param string $function * optional, return parameter information specific module function * * @access admin, customer * @return string json-encoded array * @throws exception */ public function listfunctions() { $module = $this-&gt;getparam('module', true, ''); $function = $this-&gt;getparam('function', true, ''); $functions = []; ($module != null) { // check existence $this-&gt;requiremodules($module); // get static functions $reflection = new reflectionclass(__namespace__ . '\\' . $module); $_functions = $reflection-&gt;getmethods(reflectionmethod::is_public); foreach ($_functions $func) { (empty($function) || ($function != null &amp;&amp; $func-&gt;name == $function)) { ($func-&gt;class == __namespace__ . '\\' . $module &amp;&amp; $func-&gt;ispublic()) { array_push($functions, array_merge([ 'module' =&gt; $module, 'function' =&gt; $func-&gt;name ], $this-&gt;getparamlistfromdoc($module, $func-&gt;name))); } } } } else { // check modules $path = \froxlor\froxlor::getinstalldir() . '/lib/froxlor/api/commands/'; // valid directory? (is_dir($path)) { // create recursiveiteratoriterator $its = new recursiveiteratoriterator(new recursivedirectoryiterator($path)); // check every file foreach ($its $it) { // match filename pattern? $matches = []; (preg_match("/^(.+)\.php$/i", $it-&gt;getfilename(), $matches)) { // check existence try { // set module namespace $mod = $matches[1]; $this-&gt;requiremodules($mod); } catch (exception $e) { // @todo log? continue; } // get static functions $reflection = new reflectionclass(__namespace__ . '\\' . $mod); $_functions = $reflection-&gt;getmethods(reflectionmethod::is_public); foreach ($_functions $func) { ($func-&gt;class == __namespace__ . '\\' . $mod &amp;&amp; $func-&gt;ispublic() &amp;&amp; !$func-&gt;isstatic()) { array_push($functions, array_merge([ 'module' =&gt; $matches[1], 'function' =&gt; $func-&gt;name ], $this-&gt;getparamlistfromdoc($matches[1], $func-&gt;name))); } } } } } else { // yikes - valid directory check throw new exception("cannot search directory '" . $path . "'. directory.", 500); } } // return list return $this-&gt;response($functions); } /** * functions used check availability * given list modules. * either one * found, throw exception * * @param string|array $modules * * @throws exception */ private function requiremodules($modules = null) { ($modules != null) { // array -&gt; create one (!is_array($modules)) { $modules = [ $modules ]; } // check modules foreach ($modules $module) { try { $module = __namespace__ . '\\' . $module; // use class? (class_exists($module)) { continue; } else { throw new exception('the required class "' . $module . '" could found module-file exists', 404); } } catch (exception $e) { // autoloader throw exception // required class could found // want nicer error-message throw new exception('the required module "' . $module . '" could found', 404); } } } } /** * generate api-response list parameters return-value * given module.function-combination * * @param string $module * @param string $function * * @return array|bool * @throws exception */ private function getparamlistfromdoc($module = null, $function = null) { try { // set module $cls = new reflectionmethod(__namespace__ . '\\' . $module, $function); $comment = $cls-&gt;getdoccomment(); ($comment == false) { return [ 'head' =&gt; 'there comment-block "' . $module . '.' . $function . '"' ]; } $clines = explode("\n", $comment); $result = []; $result['params'] = []; $param_desc = false; $r = []; foreach ($clines $c) { $c = trim($c); // check param-section (strpos($c, '@param')) { preg_match('/^\*\s\@param\s(.+)\s(\$\w+)(\s.*)?/', $c, $r); // cut $ parameter-name wanted api-request $result['params'][] = [ 'parameter' =&gt; substr($r[2], 1), 'type' =&gt; $r[1], 'desc' =&gt; (isset($r[3]) ? trim($r['3']) : '') ]; $param_desc = true; } elseif (strpos($c, '@access')) { // check access-section preg_match('/^\*\s\@access\s(.*)/', $c, $r); (!isset($r[0]) || empty($r[0])) { $r[1] = 'this function restrictions'; } $result['access'] = [ 'groups' =&gt; (isset($r[1]) ? trim($r[1]) : '') ]; } elseif (strpos($c, '@return')) { // check return-section preg_match('/^\*\s\@return\s(\w+)(\s.*)?/', $c, $r); (!isset($r[0]) || empty($r[0])) { $r[1] = 'null'; $r[2] = 'this function return value given'; } $result['return'] = [ 'type' =&gt; $r[1], 'desc' =&gt; (isset($r[2]) ? trim($r[2]) : '') ]; } elseif (!empty($c) &amp;&amp; strpos($c, '@throws') === false) { // check throws-section (substr($c, 0, 3) == "/**") { continue; } (substr($c, 0, 2) == "*/") { continue; } (substr($c, 0, 1) == "*") { $c = trim(substr($c, 1)); (empty($c)) { continue; } ($param_desc) { $result['params'][count($result['params']) - 1]['desc'] .= $c; } else { (!isset($result['head']) || empty($result['head'])) { $result['head'] = $c . " "; } else { $result['head'] .= $c . " "; } } } } } $result['head'] = trim($result['head']); return $result; } catch (reflectionexception $e) { return []; } } }</file><file name="lib/Froxlor/Api/Commands/Mysqls.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\database\database; use froxlor\database\dbmanager; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\system\crypt; use froxlor\ui\response; use froxlor\user; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class mysqls extends apicommand implements resourceentity { /** * add new mysql-database * * @param string $mysql_password * password created database database-user * @param int $mysql_server * optional, default 0 * @param string $description * optional, description database * @param string $custom_suffix * optional, name database customer.mysqlprefix setting set "dbname" * @param bool $sendinfomail * optional, send created resource-information customer, default: false * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * * @access admin, customer * @return string json-encoded array * @throws exception */ public function add() { (($this-&gt;getuserdetail('mysqls_used') &lt; $this-&gt;getuserdetail('mysqls') || $this-&gt;getuserdetail('mysqls') == '-1') || $this-&gt;isadmin()) { // required parameters $password = $this-&gt;getparam('mysql_password'); // parameters $databasedescription = $this-&gt;getparam('description', true, ''); $databasename = $this-&gt;getparam('custom_suffix', true, ''); $sendinfomail = $this-&gt;getboolparam('sendinfomail', true, 0); // get needed customer info reduce mysql-usage-counter one $customer = $this-&gt;getcustomerdata('mysqls'); $dbserver = $this-&gt;getparam('mysql_server', true, $this-&gt;getdefaultmysqlserver($customer)); // validation $password = validate::validate($password, 'password', '', '', [], true); $password = crypt::validatepassword($password, true); $databasedescription = validate::validate(trim($databasedescription), 'description', validate::regex_desc_text, '', [], true); (!empty($databasename)) { $databasename = validate::validate(trim($databasename), 'database_name', '/^[a-za-z0-9][a-za-z0-9\-_]+$/i', '', [], true); } // validate whether dbserver exists $dbserver = validate::validate($dbserver, html_entity_decode(lng('mysql.mysql_server')), '/^[0-9]+$/', '', 0, true); database::needroot(true, $dbserver, false); database::needsqldata(); $sql_root = database::getsqldata(); database::needroot(false); (!is_array($sql_root)) { throw new exception("database server index #" . $dbserver . " unknown", 404); } ($sendinfomail != 1) { $sendinfomail = 0; } $newdb_params = [ 'loginname' =&gt; ($this-&gt;isadmin() ? $customer['loginname'] : $this-&gt;getuserdetail('loginname')), 'mysql_lastaccountnumber' =&gt; ($this-&gt;isadmin() ? $customer['mysql_lastaccountnumber'] : $this-&gt;getuserdetail('mysql_lastaccountnumber')) ]; // create database, user, set permissions, etc.pp. $dbm = new dbmanager($this-&gt;logger()); (strtoupper(settings::get('customer.mysqlprefix')) == 'dbname' &amp;&amp; !empty($databasename)) { (strlen($newdb_params['loginname'] . '_' . $databasename) &gt; database::getsqlusernamelength()) { throw new exception("database name cannot longer " . (database::getsqlusernamelength() - strlen($newdb_params['loginname'] . '_')) . " characters.", 406); } $username = $dbm-&gt;createdatabase($newdb_params['loginname'] . '_' . $databasename, $password, $dbserver, 0, $newdb_params['loginname']); } else { $username = $dbm-&gt;createdatabase($newdb_params['loginname'], $password, $dbserver, $newdb_params['mysql_lastaccountnumber'], $newdb_params['loginname']); } // we've checked password dbm-&gt;createdatabase ($username == false) { response::standarderror('passwordshouldnotbeusername', '', true); } // add database info froxlor $stmt = database::prepare(" insert `" . table_panel_databases . "` set `customerid` = :customerid, `databasename` = :databasename, `description` = :description, `dbserver` = :dbserver "); $params = [ "customerid" =&gt; $customer['customerid'], "databasename" =&gt; $username, "description" =&gt; $databasedescription, "dbserver" =&gt; $dbserver ]; database::pexecute($stmt, $params, true, true); $databaseid = database::lastinsertid(); $params['id'] = $databaseid; // update customer usage customers::increaseusage($customer['customerid'], 'mysqls_used'); customers::increaseusage($customer['customerid'], 'mysql_lastaccountnumber'); // send info-mail? ($sendinfomail == 1) { $pma = lng('admin.notgiven'); (settings::get('panel.phpmyadmin_url') != '') { $pma = settings::get('panel.phpmyadmin_url'); } database::needroot(true, $dbserver, false); database::needsqldata(); $sql_root = database::getsqldata(); database::needroot(false); $userinfo = $customer; $replace_arr = [ 'salutation' =&gt; user::getcorrectusersalutation($userinfo), 'cust_name' =&gt; user::getcorrectusersalutation($userinfo), // &lt; keep compatibility 'name' =&gt; $userinfo['name'], 'firstname' =&gt; $userinfo['firstname'], 'company' =&gt; $userinfo['company'], 'username' =&gt; $userinfo['loginname'], 'customer_no' =&gt; $userinfo['customernumber'], 'db_name' =&gt; $username, 'db_pass' =&gt; htmlentities(htmlentities($password)), 'db_desc' =&gt; $databasedescription, 'db_srv' =&gt; $sql_root['host'], 'pma_uri' =&gt; $pma ]; // get template mail subject $mail_subject = $this-&gt;getmailtemplate($userinfo, 'mails', 'new_database_by_customer_subject', $replace_arr, lng('mails.new_database_by_customer.subject')); // get template mail body $mail_body = $this-&gt;getmailtemplate($userinfo, 'mails', 'new_database_by_customer_mailbody', $replace_arr, lng('mails.new_database_by_customer.mailbody')); $_mailerror = false; $mailerr_msg = ""; try { $this-&gt;mailer()-&gt;subject = $mail_subject; $this-&gt;mailer()-&gt;altbody = $mail_body; $this-&gt;mailer()-&gt;body = str_replace("\n", "&lt;br /&gt;", $mail_body); $this-&gt;mailer()-&gt;addaddress($userinfo['email'], user::getcorrectusersalutation($userinfo)); $this-&gt;mailer()-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_err, "[api] error sending mail: " . $mailerr_msg); response::standarderror('errorsendingmail', $userinfo['email'], true); } $this-&gt;mailer()-&gt;clearaddresses(); } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] added mysql-database '" . $username . "'"); $result = $this-&gt;apicall('mysqls.get', [ 'dbname' =&gt; $username, 'mysql_server' =&gt; $dbserver ]); return $this-&gt;response($result); } throw new exception("no resources available", 406); } /** * return mysql database entry either id dbname * * @param int $id * optional, database-id * @param string $dbname * optional, databasename * @param int $mysql_server * optional, specify database-server, default none * * @access admin, customer * @return string json-encoded array * @throws exception */ public function get() { $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $dbname = $this-&gt;getparam('dbname', $dn_optional, ''); $dbserver = $this-&gt;getparam('mysql_server', true, -1); ($dbserver != -1) { $dbserver = validate::validate($dbserver, html_entity_decode(lng('mysql.mysql_server')), '/^[0-9]+$/', '', 0, true); } ($this-&gt;isadmin()) { ($this-&gt;getuserdetail('customers_see_all') != 1) { // reseller admin cannot see customers, need check // whether database belongs one customers $_custom_list_result = $this-&gt;apicall('customers.listing'); $custom_list_result = $_custom_list_result['list']; $customer_ids = []; foreach ($custom_list_result $customer) { $customer_ids[] = $customer['customerid']; } (count($customer_ids) &gt; 0) { $result_stmt = database::prepare(" select * `" . table_panel_databases . "` " . ($id &gt; 0 ? "`id` = :iddn" : "`databasename` = :iddn") . ($dbserver &gt;= 0 ? " `dbserver` = :dbserver" : "") . " `customerid` (" . implode(", ", $customer_ids) . ") "); $params = [ 'iddn' =&gt; ($id &lt;= 0 ? $dbname : $id) ]; ($dbserver &gt;= 0) { $params['dbserver'] = $dbserver; } } else { throw new exception("you customers yet", 406); } } else { $result_stmt = database::prepare(" select * `" . table_panel_databases . "` " . ($id &gt; 0 ? "`id` = :iddn" : "`databasename` = :iddn") . ($dbserver &gt;= 0 ? " `dbserver` = :dbserver" : "")); $params = [ 'iddn' =&gt; ($id &lt;= 0 ? $dbname : $id) ]; ($dbserver &gt;= 0) { $params['dbserver'] = $dbserver; } } } else { (settings::isinlist('panel.customer_hide_options', 'mysql')) { throw new exception("you cannot access resource", 405); } $result_stmt = database::prepare(" select * `" . table_panel_databases . "` `customerid`= :customerid " . ($id &gt; 0 ? "`id` = :iddn" : "`databasename` = :iddn") . ($dbserver &gt;= 0 ? " `dbserver` = :dbserver" : "")); $params = [ 'customerid' =&gt; $this-&gt;getuserdetail('customerid'), 'iddn' =&gt; ($id &lt;= 0 ? $dbname : $id) ]; ($dbserver &gt;= 0) { $params['dbserver'] = $dbserver; } } $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { database::needroot(true, $result['dbserver'], false); $mbdata_stmt = database::prepare(" select sum(data_length + index_length) mb information_schema.tables table_schema = :table_schema group table_schema "); database::pexecute($mbdata_stmt, [ "table_schema" =&gt; $result['databasename'] ], true, true); $mbdata = $mbdata_stmt-&gt;fetch(pdo::fetch_assoc); database::needroot(false); $result['size'] = $mbdata['mb'] ?? 0; $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] get database '" . $result['databasename'] . "'"); return $this-&gt;response($result); } $key = ($id &gt; 0 ? "id #" . $id : "dbname '" . $dbname . "'"); throw new exception("mysql database " . $key . " could found", 404); } /** * update mysql database entry either id dbname * * @param int $id * optional, database-id * @param string $dbname * optional, databasename * @param int $mysql_server * optional, specify database-server, default none * @param string $mysql_password * optional, update password database * @param string $description * optional, description database * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * * @access admin, customer * @return string json-encoded array * @throws exception */ public function update() { $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $dbname = $this-&gt;getparam('dbname', $dn_optional, ''); $dbserver = $this-&gt;getparam('mysql_server', true, -1); $customer = $this-&gt;getcustomerdata(); ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'mysql')) { throw new exception("you cannot access resource", 405); } $result = $this-&gt;apicall('mysqls.get', [ 'id' =&gt; $id, 'dbname' =&gt; $dbname, 'mysql_server' =&gt; $dbserver ]); $id = $result['id']; // parameters $password = $this-&gt;getparam('mysql_password', true, ''); $databasedescription = $this-&gt;getparam('description', true, $result['description']); // validation $password = validate::validate($password, 'password', '', '', [], true); $databasedescription = validate::validate(trim($databasedescription), 'description', validate::regex_desc_text, '', [], true); ($password != '') { // validate password $password = crypt::validatepassword($password, true); ($password == $result['databasename']) { response::standarderror('passwordshouldnotbeusername', '', true); } // begin root-session database::needroot(true, $result['dbserver'], false); $dbmgr = new dbmanager($this-&gt;logger()); foreach (array_map('trim', explode(',', settings::get('system.mysql_access_host'))) $mysql_access_host) { $dbmgr-&gt;getmanager()-&gt;grantprivilegesto($result['databasename'], $password, $mysql_access_host, false, true); } $stmt = database::prepare("flush privileges"); database::pexecute($stmt, null, true, true); database::needroot(false); // end root-session } $stmt = database::prepare(" update `" . table_panel_databases . "` set `description` = :desc `customerid` = :customerid `id` = :id "); $params = [ "desc" =&gt; $databasedescription, "customerid" =&gt; $customer['customerid'], "id" =&gt; $id ]; database::pexecute($stmt, $params, true, true); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] updated mysql-database '" . $result['databasename'] . "'"); $result = $this-&gt;apicall('mysqls.get', [ 'dbname' =&gt; $result['databasename'] ]); return $this-&gt;response($result); } /** * list databases, called admin, list databases customers allowed view, * specify id loginname one specific customer * * @param int $mysql_server * optional, specify dbserver select from, else use available * @param int $customerid * optional, admin-only, select dbs specific customer id * @param string $loginname * optional, admin-only, select dbs specific customer loginname * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * * @access admin, customer * @return string json-encoded array count|list * @throws exception */ public function listing() { $result = []; $dbserver = $this-&gt;getparam('mysql_server', true, -1); $customer_ids = $this-&gt;getallowedcustomerids('mysql'); $query_fields = []; $result_stmt = database::prepare(" select * `" . table_panel_databases . "` `customerid`= :customerid `dbserver` = :dbserver" . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); ($dbserver &lt; 0) { // use dbservers $dbservers_stmt = database::query("select distinct `dbserver` `" . table_panel_databases . "`"); $dbservers = $dbservers_stmt-&gt;fetchall(pdo::fetch_assoc); } else { // use specific dbserver $dbservers = [ [ 'dbserver' =&gt; $dbserver ] ]; } foreach ($customer_ids $customer_id) { foreach ($dbservers $_dbserver) { database::pexecute($result_stmt, array_merge([ 'customerid' =&gt; $customer_id, 'dbserver' =&gt; $_dbserver['dbserver'] ], $query_fields), true, true); // begin root-session database::needroot(true, $_dbserver['dbserver'], false); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $mbdata_stmt = database::prepare(" select sum(data_length + index_length) mb information_schema.tables table_schema = :table_schema group table_schema "); database::pexecute($mbdata_stmt, [ "table_schema" =&gt; $row['databasename'] ], true, true); $mbdata = $mbdata_stmt-&gt;fetch(pdo::fetch_assoc); $row['size'] = $mbdata['mb'] ?? 0; $result[] = $row; } database::needroot(false); } } return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } /** * returns total number accessible databases * * @param int $customerid * optional, admin-only, select dbs specific customer id * @param string $loginname * optional, admin-only, select dbs specific customer loginname * * @access admin, customer * @return string json-encoded response message * @throws exception */ public function listingcount() { $customer_ids = $this-&gt;getallowedcustomerids('mysql'); $result_stmt = database::prepare(" select count(*) num_dbs `" . table_panel_databases . "` `customerid` (" . implode(", ", $customer_ids) . ") "); $result = database::pexecute_first($result_stmt, null, true, true); ($result) { return $this-&gt;response($result['num_dbs']); } return $this-&gt;response(0); } /** * delete mysql database either id dbname * * @param int $id * optional, database-id * @param string $dbname * optional, databasename * @param int $mysql_server * optional, specify database-server, default none * @param int $customerid * optional, required called admin (if $loginname specified) * @param string $loginname * optional, required called admin (if $customerid specified) * * @access admin, customer * @return string json-encoded array * @throws exception */ public function delete() { $id = $this-&gt;getparam('id', true, 0); $dn_optional = $id &gt; 0; $dbname = $this-&gt;getparam('dbname', $dn_optional, ''); $dbserver = $this-&gt;getparam('mysql_server', true, -1); $customer = $this-&gt;getcustomerdata(); ($this-&gt;isadmin() == false &amp;&amp; settings::isinlist('panel.customer_hide_options', 'mysql')) { throw new exception("you cannot access resource", 405); } $result = $this-&gt;apicall('mysqls.get', [ 'id' =&gt; $id, 'dbname' =&gt; $dbname, 'mysql_server' =&gt; $dbserver ]); $id = $result['id']; // begin root-session database::needroot(true, $result['dbserver'], false); $dbm = new dbmanager($this-&gt;logger()); $dbm-&gt;getmanager()-&gt;deletedatabase($result['databasename'], $customer['loginname']); database::needroot(false); // end root-session // delete table $stmt = database::prepare("delete `" . table_panel_databases . "` `id` = :id"); database::pexecute($stmt, [ "id" =&gt; $id ], true, true); // get needed customer info reduce mysql-usage-counter one $mysql_used = $customer['mysqls_used']; // reduce mysql-usage-counter $resetaccnumber = ($mysql_used == '1') ? " , `mysql_lastaccountnumber` = '0' " : ''; customers::decreaseusage($customer['customerid'], 'mysqls_used', $resetaccnumber); $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_warning, "[api] deleted database '" . $result['databasename'] . "'"); return $this-&gt;response($result); } private function getdefaultmysqlserver(array $customer) { $allowed_mysqlservers = json_decode($customer['allowed_mysqlserver'] ?? '[]', true); asort($allowed_mysqlservers, sort_numeric); (count($allowed_mysqlservers) == 1 &amp;&amp; $allowed_mysqlservers[0] != 0) { return (int) $allowed_mysqlservers[0]; } return (int) array_shift($allowed_mysqlservers); } }</file><file name="lib/Froxlor/Api/Commands/index.html" /><file name="lib/Froxlor/Api/Commands/Customers.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\api\commands; use exception; use froxlor\api\apicommand; use froxlor\api\resourceentity; use froxlor\cron\taskid; use froxlor\database\database; use froxlor\database\dbmanager; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\idna\idnawrapper; use froxlor\settings; use froxlor\system\cronjob; use froxlor\system\crypt; use froxlor\ui\response; use froxlor\user; use froxlor\validate\validate; use pdo; /** * @since 0.10.0 */ class customers extends apicommand implements resourceentity { /** * lists customer entries * * @param array $sql_search * optional array index = fieldname, value = array 'op' =&gt; operator (one &lt;, &gt; =), * like used left empty 'value' =&gt; searchvalue * @param int $sql_limit * optional specify number results returned * @param int $sql_offset * optional specify offset resultset * @param array $sql_orderby * optional array index = fieldname value = asc|desc order resultset one * fields * @param bool $show_usages * optional, default false * * @access admin * @return string json-encoded array count|list * @throws exception */ public function listing() { ($this-&gt;isadmin()) { $show_usages = $this-&gt;getboolparam('show_usages', true, false); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] list customers"); $query_fields = []; $result_stmt = database::prepare(" select `c`.*, `a`.`loginname` `adminname` `" . table_panel_customers . "` `c`, `" . table_panel_admins . "` `a` " . ($this-&gt;getuserdetail('customers_see_all') ? '' : " `c`.`adminid` = :adminid ") . " `c`.`adminid` = `a`.`adminid`" . $this-&gt;getsearchwhere($query_fields, true) . $this-&gt;getorderby() . $this-&gt;getlimit()); $params = []; ($this-&gt;getuserdetail('customers_see_all') == '0') { $params = [ 'adminid' =&gt; $this-&gt;getuserdetail('adminid') ]; } $params = array_merge($params, $query_fields); database::pexecute($result_stmt, $params, true, true); $result = []; $domains_stmt = null; $usages_stmt = null; ($show_usages) { $domains_stmt = database::prepare(" select count(`id`) `domains` `" . table_panel_domains . "` `customerid` = :cid `parentdomainid` = '0' `id`&lt;&gt; :stdd "); $usages_stmt = database::prepare(" select webspace, mail, mysql `" . table_panel_diskspace . "` `customerid` = :cid order `stamp` desc limit 1 "); } ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { ($show_usages) { // get number domains $domains = database::pexecute_first($domains_stmt, [ 'cid' =&gt; $row['customerid'], 'stdd' =&gt; $row['standardsubdomain'] ]); $row['domains'] = intval($domains['domains']); // get disk-space usages web, mysql mail $usages = database::pexecute_first($usages_stmt, [ 'cid' =&gt; $row['customerid'] ]); ($usages) { $row['webspace_used'] = $usages['webspace']; $row['mailspace_used'] = $usages['mail']; $row['dbspace_used'] = $usages['mysql']; } else { $row['webspace_used'] = 0; $row['mailspace_used'] = 0; $row['dbspace_used'] = 0; } } $result[] = $row; } return $this-&gt;response([ 'count' =&gt; count($result), 'list' =&gt; $result ]); } throw new exception("not allowed execute given command.", 403); } /** * returns total number customers given admin * * @access admin * @return string json-encoded response message * @throws exception */ public function listingcount() { ($this-&gt;isadmin()) { $result_stmt = database::prepare(" select count(*) num_customers `" . table_panel_customers . "` " . ($this-&gt;getuserdetail('customers_see_all') ? "1" : " `adminid` = :adminid ")); $params = []; ($this-&gt;getuserdetail('customers_see_all') == '0') { $params = [ 'adminid' =&gt; $this-&gt;getuserdetail('adminid') ]; } $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { return $this-&gt;response($result['num_customers']); } return $this-&gt;response(0); } throw new exception("not allowed execute given command.", 403); } /** * create new customer default ftp-user standard-subdomain (if wanted) * * @param string $email * required, email address new customer * @param string $name * optional company set, else required * @param string $firstname * optional company set, else required * @param string $company * optional required name/firstname empty * @param string $street * optional * @param string $zipcode * optional * @param string $city * optional * @param string $phone * optional * @param string $fax * optional * @param int $customernumber * optional * @param string $def_language * optional, iso 639-1 language code (e.g. 'en', 'de', see lng-folder supported languages), * default system-default language * @param bool $gui_access * optional, allow login via webui, false login via webui disallowed; default true * @param bool $api_allowed * optional, default true system setting api.enabled true, else false * @param int $gender * optional, 0 = no-gender, 1 = male, 2 = female * @param string $custom_notes * optional notes * @param bool $custom_notes_show * optional, whether show content custom_notes customer, default 0 * (false) * @param string $new_loginname * optional, empty generated automatically using customer-prefix increasing * number * @param string $new_customer_password * optional, empty generated automatically send customer's email * $sendpassword 1 * @param bool $sendpassword * optional, whether send password customer creation, default 0 * (false) * @param int $diskspace * optional disk-space available customer mb, default 0 * @param bool $diskspace_ul * optional, whether customer unlimited diskspace, default 0 (false) * @param int $traffic * optional traffic available customer gb, default 0 * @param bool $traffic_ul * optional, whether customer unlimited traffic, default 0 (false) * @param int $subdomains * optional amount subdomains available customer, default 0 * @param bool $subdomains_ul * optional, whether customer unlimited subdomains, default 0 (false) * @param int $emails * optional amount emails available customer, default 0 * @param bool $emails_ul * optional, whether customer unlimited emails, default 0 (false) * @param int $email_accounts * optional amount email-accounts available customer, default 0 * @param bool $email_accounts_ul * optional, whether customer unlimited email-accounts, default 0 (false) * @param int $email_forwarders * optional amount email-forwarders available customer, default 0 * @param bool $email_forwarders_ul * optional, whether customer unlimited email-forwarders, default 0 (false) * @param int $email_quota * optional size email-quota available customer mb, default system-setting * mail_quota * @param bool $email_quota_ul * optional, whether customer unlimited email-quota, default 0 (false) * @param bool $email_imap * optional, whether allow imap access, default 0 (false) * @param bool $email_pop3 * optional, whether allow pop3 access, default 0 (false) * @param int $ftps * optional amount ftp-accounts available customer, default 0 * @param bool $ftps_ul * optional, whether customer unlimited ftp-accounts, default 0 (false) * @param int $mysqls * optional amount mysql-databases available customer, default 0 * @param bool $mysqls_ul * optional, whether customer unlimited mysql-databases, default 0 (false) * @param bool $createstdsubdomain * optional, whether create standard-subdomain ([loginname].froxlor-hostname.tld), * default [system.createstdsubdom_default] * @param bool $phpenabled * optional, whether allow usage php, default 0 (false) * @param array $allowed_phpconfigs * optional, array ids php-config customer allowed use, default * empty (none) * @param bool $perlenabled * optional, whether allow usage perl/cgi, default 0 (false) * @param bool $dnsenabled * optional, whether allow usage dns editor (requires activated nameserver * settings), default 0 (false) * @param bool $logviewenabled * optional, whether allow access webserver access/error-logs, default 0 (false) * @param bool $store_defaultindex * optional, whether store default index file customers homedir * @param int $hosting_plan_id * optional, specify hosting-plan set certain resource-values plan * instead specifying * @param array $allowed_mysqlserver * optional, array ids defined mysql-servers customer allowed use, * default allow default dbserver (id=0) * * @access admin * @return string json-encoded array * @throws exception */ public function add() { ($this-&gt;isadmin()) { ($this-&gt;getuserdetail('customers_used') &lt; $this-&gt;getuserdetail('customers') || $this-&gt;getuserdetail('customers') == '-1') { // required parameters $email = $this-&gt;getparam('email'); // parameters $name = $this-&gt;getparam('name', true, ''); $firstname = $this-&gt;getparam('firstname', true, ''); $company_required = (!empty($name) &amp;&amp; empty($firstname)) || (empty($name) &amp;&amp; !empty($firstname)) || (empty($name) &amp;&amp; empty($firstname)); $company = $this-&gt;getparam('company', !$company_required, ''); $street = $this-&gt;getparam('street', true, ''); $zipcode = $this-&gt;getparam('zipcode', true, ''); $city = $this-&gt;getparam('city', true, ''); $phone = $this-&gt;getparam('phone', true, ''); $fax = $this-&gt;getparam('fax', true, ''); $customernumber = $this-&gt;getparam('customernumber', true, ''); $def_language = $this-&gt;getparam('def_language', true, settings::get('panel.standardlanguage')); $gui_access = $this-&gt;getboolparam('gui_access', true, 1); $api_allowed = $this-&gt;getboolparam('api_allowed', true, (settings::get('api.enabled') &amp;&amp; settings::get('api.customer_default'))); $gender = (int)$this-&gt;getparam('gender', true, 0); $custom_notes = $this-&gt;getparam('custom_notes', true, ''); $custom_notes_show = $this-&gt;getboolparam('custom_notes_show', true, 0); $createstdsubdomain = $this-&gt;getboolparam('createstdsubdomain', true, settings::get('system.createstdsubdom_default')); $password = $this-&gt;getparam('new_customer_password', true, ''); $sendpassword = $this-&gt;getboolparam('sendpassword', true, 0); $store_defaultindex = $this-&gt;getboolparam('store_defaultindex', true, 0); $loginname = $this-&gt;getparam('new_loginname', true, ''); // hosting-plan values $hosting_plan_id = $this-&gt;getparam('hosting_plan_id', true, 0); ($hosting_plan_id &gt; 0) { $hp_result = $this-&gt;apicall('hostingplans.get', [ 'id' =&gt; $hosting_plan_id ]); $hp_result['value'] = json_decode($hp_result['value'], true); foreach ($hp_result['value'] $index =&gt; $value) { $hp_result[$index] = $value; } $diskspace = $hp_result['diskspace'] ?? 0; $traffic = $hp_result['traffic'] ?? 0; $subdomains = $hp_result['subdomains'] ?? 0; $emails = $hp_result['emails'] ?? 0; $email_accounts = $hp_result['email_accounts'] ?? 0; $email_forwarders = $hp_result['email_forwarders'] ?? 0; $email_quota = $hp_result['email_quota'] ?? settings::get('system.mail_quota'); $email_imap = $hp_result['email_imap'] ?? 0; $email_pop3 = $hp_result['email_pop3'] ?? 0; $ftps = $hp_result['ftps'] ?? 0; $mysqls = $hp_result['mysqls'] ?? 0; $phpenabled = $hp_result['phpenabled'] ?? 0; $p_allowed_phpconfigs = $hp_result['allowed_phpconfigs'] ?? 0; $perlenabled = $hp_result['perlenabled'] ?? 0; $dnsenabled = $hp_result['dnsenabled'] ?? 0; $logviewenabled = $hp_result['logviewenabled'] ?? 0; } else { $diskspace = $this-&gt;getulparam('diskspace', 'diskspace_ul', true, 0); $traffic = $this-&gt;getulparam('traffic', 'traffic_ul', true, 0); $subdomains = $this-&gt;getulparam('subdomains', 'subdomains_ul', true, 0); $emails = $this-&gt;getulparam('emails', 'emails_ul', true, 0); $email_accounts = $this-&gt;getulparam('email_accounts', 'email_accounts_ul', true, 0); $email_forwarders = $this-&gt;getulparam('email_forwarders', 'email_forwarders_ul', true, 0); $email_quota = $this-&gt;getulparam('email_quota', 'email_quota_ul', true, settings::get('system.mail_quota')); $email_imap = $this-&gt;getboolparam('email_imap', true, 0); $email_pop3 = $this-&gt;getboolparam('email_pop3', true, 0); $ftps = $this-&gt;getulparam('ftps', 'ftps_ul', true, 0); $mysqls = $this-&gt;getulparam('mysqls', 'mysqls_ul', true, 0); $phpenabled = $this-&gt;getboolparam('phpenabled', true, 0); $p_allowed_phpconfigs = $this-&gt;getparam('allowed_phpconfigs', true, []); $perlenabled = $this-&gt;getboolparam('perlenabled', true, 0); $dnsenabled = $this-&gt;getboolparam('dnsenabled', true, 0); $logviewenabled = $this-&gt;getboolparam('logviewenabled', true, 0); } ($mysqls == -1 || $mysqls &gt; 0) { $p_allowed_mysqlserver = $this-&gt;getparam('allowed_mysqlserver', true, [0]); } else { // mysql allowed, mysql available customer $p_allowed_mysqlserver = []; } // validation $name = validate::validate($name, 'name', validate::regex_desc_text, '', [], true); $firstname = validate::validate($firstname, 'first name', validate::regex_desc_text, '', [], true); $company = validate::validate($company, 'company', validate::regex_desc_text, '', [], true); $street = validate::validate($street, 'street', validate::regex_desc_text, '', [], true); $zipcode = validate::validate($zipcode, 'zipcode', '/^[0-9 \-a-z]*$/', '', [], true); $city = validate::validate($city, 'city', validate::regex_desc_text, '', [], true); $phone = validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', [], true); $fax = validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', [], true); $idna_convert = new idnawrapper(); $email = $idna_convert-&gt;encode(validate::validate($email, 'email', '', '', [], true)); $customernumber = validate::validate($customernumber, 'customer number', '/^[a-za-z0-9 \-]*$/di', '', [], true); $def_language = validate::validate($def_language, 'default language', '', '', [], true); $custom_notes = validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', validate::regex_conf_text, '', [], true); (settings::get('system.mail_quota_enabled') != '1') { $email_quota = -1; } $password = validate::validate($password, 'password', '', '', [], true); // check empty, // cause empty == generate password automatically ($password != '') { $password = crypt::validatepassword($password, true); } // gender range? [0,2] ($gender &lt; 0 || $gender &gt; 2) { $gender = 0; } $allowed_phpconfigs = []; (!empty($p_allowed_phpconfigs) &amp;&amp; is_array($p_allowed_phpconfigs)) { foreach ($p_allowed_phpconfigs $allowed_phpconfig) { $allowed_phpconfig = intval($allowed_phpconfig); $allowed_phpconfigs[] = $allowed_phpconfig; } } $allowed_phpconfigs = array_map('intval', $allowed_phpconfigs); (empty($allowed_phpconfigs) &amp;&amp; $phpenabled == 1) { // required using mod_php ((int)settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1) { response::standarderror('customerphpenabledbutnoconfig', '', true); } } $allowed_mysqlserver = array(); (!empty($p_allowed_mysqlserver) &amp;&amp; is_array($p_allowed_mysqlserver)) { foreach ($p_allowed_mysqlserver $allowed_ms) { $allowed_ms = intval($allowed_ms); $allowed_mysqlserver[] = $allowed_ms; } } $allowed_mysqlserver = array_map('intval', $allowed_mysqlserver); $diskspace *= 1024; $traffic *= 1024 * 1024; ( ($diskspace != 0 &amp;&amp; (($this-&gt;getuserdetail('diskspace_used') + $diskspace) &gt; $this-&gt;getuserdetail('diskspace')) &amp;&amp; ($this-&gt;getuserdetail('diskspace') / 1024) != '-1') || ($mysqls != 0 &amp;&amp; (($this-&gt;getuserdetail('mysqls_used') + $mysqls) &gt; $this-&gt;getuserdetail('mysqls')) &amp;&amp; $this-&gt;getuserdetail('mysqls') != '-1') || ($emails != 0 &amp;&amp; (($this-&gt;getuserdetail('emails_used') + $emails) &gt; $this-&gt;getuserdetail('emails')) &amp;&amp; $this-&gt;getuserdetail('emails') != '-1') || ($email_accounts != 0 &amp;&amp; (($this-&gt;getuserdetail('email_accounts_used') + $email_accounts) &gt; $this-&gt;getuserdetail('email_accounts')) &amp;&amp; $this-&gt;getuserdetail('email_accounts') != '-1') || ($email_forwarders != 0 &amp;&amp; (($this-&gt;getuserdetail('email_forwarders_used') + $email_forwarders) &gt; $this-&gt;getuserdetail('email_forwarders')) &amp;&amp; $this-&gt;getuserdetail('email_forwarders') != '-1') || ($email_quota != 0 &amp;&amp; (($this-&gt;getuserdetail('email_quota_used') + $email_quota) &gt; $this-&gt;getuserdetail('email_quota')) &amp;&amp; $this-&gt;getuserdetail('email_quota') != '-1' &amp;&amp; settings::get('system.mail_quota_enabled') == '1') || ($ftps != 0 &amp;&amp; (($this-&gt;getuserdetail('ftps_used') + $ftps) &gt; $this-&gt;getuserdetail('ftps')) &amp;&amp; $this-&gt;getuserdetail('ftps') != '-1') || ($subdomains != 0 &amp;&amp; (($this-&gt;getuserdetail('subdomains_used') + $subdomains) &gt; $this-&gt;getuserdetail('subdomains')) &amp;&amp; $this-&gt;getuserdetail('subdomains') != '-1') || (($diskspace / 1024) == '-1' &amp;&amp; ($this-&gt;getuserdetail('diskspace') / 1024) != '-1') || ($mysqls == '-1' &amp;&amp; $this-&gt;getuserdetail('mysqls') != '-1') || ($emails == '-1' &amp;&amp; $this-&gt;getuserdetail('emails') != '-1') || ($email_accounts == '-1' &amp;&amp; $this-&gt;getuserdetail('email_accounts') != '-1') || ($email_forwarders == '-1' &amp;&amp; $this-&gt;getuserdetail('email_forwarders') != '-1') || ($email_quota == '-1' &amp;&amp; $this-&gt;getuserdetail('email_quota') != '-1' &amp;&amp; settings::get('system.mail_quota_enabled') == '1') || ($ftps == '-1' &amp;&amp; $this-&gt;getuserdetail('ftps') != '-1') || ($subdomains == '-1' &amp;&amp; $this-&gt;getuserdetail('subdomains') != '-1') ) { response::standarderror('youcantallocatemorethanyouhave', '', true); } (!validate::validateemail($email)) { response::standarderror('emailiswrong', $email, true); } else { ($loginname != '') { $accountnumber = intval(settings::get('system.lastaccountnumber')); $loginname = validate::validate($loginname, 'loginname', '/^[a-z][a-z0-9\-_]+$/i', '', [], true); // accounts match systemaccounts allowed, filtering (preg_match('/^' . preg_quote(settings::get('customer.accountprefix'), '/') . '([0-9]+)/', $loginname)) { response::standarderror('loginnameisusingprefix', settings::get('customer.accountprefix'), true); } // additional filtering bug #962 (function_exists('posix_getpwnam') &amp;&amp; !in_array("posix_getpwnam", explode(",", ini_get('disable_functions'))) &amp;&amp; posix_getpwnam($loginname)) { response::standarderror('loginnameissystemaccount', $loginname, true); } // blacklist system-internal names might lead issues database::needsqldata(); $sqldata = database::getsqldata(); database::needroot(true); database::needsqldata(); $sqlrdata = database::getsqldata(); $login_blacklist = [ 'root', 'admin', 'froxroot', 'froxlor', $sqldata['user'], $sqldata['db'], $sqlrdata['user'], ]; unset($sqldata); unset($sqlrdata); $login_blacklist = array_unique($login_blacklist); (in_array($loginname, $login_blacklist)) { response::standarderror('loginnameisreservedname', $loginname, true); } } else { $accountnumber = intval(settings::get('system.lastaccountnumber')) + 1; $loginname = settings::get('customer.accountprefix') . $accountnumber; } // check account already exists // check via api skip permission checks task $loginname_check_stmt = database::prepare(" select `loginname` `" . table_panel_customers . "` `loginname` = :login "); $loginname_check = database::pexecute_first($loginname_check_stmt, [ 'login' =&gt; $loginname ], true, true); // check admin loginname already exists // check via api skip permission checks task $loginname_check_admin_stmt = database::prepare(" select `loginname` `" . table_panel_admins . "` `loginname` = :login "); $loginname_check_admin = database::pexecute_first($loginname_check_admin_stmt, [ 'login' =&gt; $loginname ], true, true); // check existing email address // check via api skip permission checks task $email_check_admin_stmt = database::prepare(" select `email` `" . table_panel_admins . "` `email` = :email "); $email_check_admin = database::pexecute_first($email_check_admin_stmt, [ 'email' =&gt; $email ], true, true); $mysql_maxlen = database::getsqlusernamelength() - strlen(settings::get('customer.mysqlprefix')); (($loginname_check &amp;&amp; strtolower($loginname_check['loginname']) == strtolower($loginname)) || ($loginname_check_admin &amp;&amp; strtolower($loginname_check_admin['loginname']) == strtolower($loginname))) { response::standarderror('loginnameexists', $loginname, true); } elseif (!validate::validateusername($loginname, settings::get('panel.unix_names'), $mysql_maxlen)) { (strlen($loginname) &gt; $mysql_maxlen) { response::standarderror('loginnameiswrong2', $mysql_maxlen, true); } else { response::standarderror('loginnameiswrong', $loginname, true); } } elseif ($email_check_admin &amp;&amp; strtolower($email_check_admin['email']) == strtolower($email)) { response::standarderror('emailexistsanon', $email, true); } $guid = intval(settings::get('system.lastguid')) + 1; $documentroot = filedir::makecorrectdir(settings::get('system.documentroot_prefix') . '/' . $loginname); (file_exists($documentroot)) { response::standarderror('documentrootexists', $documentroot, true); } ($password == '') { $password = crypt::generatepassword(); } $_theme = settings::get('panel.default_theme'); $ins_data = [ 'adminid' =&gt; $this-&gt;getuserdetail('adminid'), 'loginname' =&gt; $loginname, 'passwd' =&gt; crypt::makecryptpassword($password), 'name' =&gt; $name, 'firstname' =&gt; $firstname, 'gender' =&gt; $gender, 'company' =&gt; $company, 'street' =&gt; $street, 'zipcode' =&gt; $zipcode, 'city' =&gt; $city, 'phone' =&gt; $phone, 'fax' =&gt; $fax, 'email' =&gt; $email, 'customerno' =&gt; $customernumber, 'lang' =&gt; $def_language, 'gui_access' =&gt; $gui_access, 'api_allowed' =&gt; $api_allowed, 'docroot' =&gt; $documentroot, 'guid' =&gt; $guid, 'diskspace' =&gt; $diskspace, 'traffic' =&gt; $traffic, 'subdomains' =&gt; $subdomains, 'emails' =&gt; $emails, 'email_accounts' =&gt; $email_accounts, 'email_forwarders' =&gt; $email_forwarders, 'email_quota' =&gt; $email_quota, 'ftps' =&gt; $ftps, 'mysqls' =&gt; $mysqls, 'phpenabled' =&gt; $phpenabled, 'allowed_phpconfigs' =&gt; empty($allowed_phpconfigs) ? "" : json_encode($allowed_phpconfigs), 'imap' =&gt; $email_imap, 'pop3' =&gt; $email_pop3, 'perlenabled' =&gt; $perlenabled, 'dnsenabled' =&gt; $dnsenabled, 'logviewenabled' =&gt; $logviewenabled, 'theme' =&gt; $_theme, 'custom_notes' =&gt; $custom_notes, 'custom_notes_show' =&gt; $custom_notes_show, 'allowed_mysqlserver' =&gt; empty($allowed_mysqlserver) ? "" : json_encode($allowed_mysqlserver) ]; $ins_stmt = database::prepare(" insert `" . table_panel_customers . "` set `adminid` = :adminid, `loginname` = :loginname, `password` = :passwd, `name` = :name, `firstname` = :firstname, `gender` = :gender, `company` = :company, `street` = :street, `zipcode` = :zipcode, `city` = :city, `phone` = :phone, `fax` = :fax, `email` = :email, `customernumber` = :customerno, `def_language` = :lang, `gui_access` = :gui_access, `api_allowed` = :api_allowed, `documentroot` = :docroot, `guid` = :guid, `diskspace` = :diskspace, `traffic` = :traffic, `subdomains` = :subdomains, `emails` = :emails, `email_accounts` = :email_accounts, `email_forwarders` = :email_forwarders, `email_quota` = :email_quota, `ftps` = :ftps, `mysqls` = :mysqls, `standardsubdomain` = '0', `phpenabled` = :phpenabled, `allowed_phpconfigs` = :allowed_phpconfigs, `imap` = :imap, `pop3` = :pop3, `perlenabled` = :perlenabled, `dnsenabled` = :dnsenabled, `logviewenabled` = :logviewenabled, `theme` = :theme, `custom_notes` = :custom_notes, `custom_notes_show` = :custom_notes_show, `allowed_mysqlserver`= :allowed_mysqlserver "); database::pexecute($ins_stmt, $ins_data, true, true); $customerid = database::lastinsertid(); $ins_data['customerid'] = $customerid; admins::increaseusage($this-&gt;getuserdetail('adminid'), 'customers_used'); // update admin resource-usage ($mysqls != '-1') { admins::increaseusage($this-&gt;getuserdetail('adminid'), 'mysqls_used', '', (int)$mysqls); } ($emails != '-1') { admins::increaseusage($this-&gt;getuserdetail('adminid'), 'emails_used', '', (int)$emails); } ($email_accounts != '-1') { admins::increaseusage($this-&gt;getuserdetail('adminid'), 'email_accounts_used', '', (int)$email_accounts); } ($email_forwarders != '-1') { admins::increaseusage($this-&gt;getuserdetail('adminid'), 'email_forwarders_used', '', (int)$email_forwarders); } ($email_quota != '-1') { admins::increaseusage($this-&gt;getuserdetail('adminid'), 'email_quota_used', '', (int)$email_quota); } ($subdomains != '-1') { admins::increaseusage($this-&gt;getuserdetail('adminid'), 'subdomains_used', '', (int)$subdomains); } ($ftps != '-1') { admins::increaseusage($this-&gt;getuserdetail('adminid'), 'ftps_used', '', (int)$ftps); } (($diskspace / 1024) != '-1') { admins::increaseusage($this-&gt;getuserdetail('adminid'), 'diskspace_used', '', (int)$diskspace); } // update last guid settings::set('system.lastguid', $guid, true); ($accountnumber != intval(settings::get('system.lastaccountnumber'))) { // update last account number settings::set('system.lastaccountnumber', $accountnumber, true); } $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_info, "[api] added customer '" . $loginname . "'"); unset($ins_data); // insert task create homedir etc. cronjob::inserttask(taskid::create_home, $loginname, $guid, $guid, $store_defaultindex); // using filesystem - quota, insert task cleans filesystem - quota cronjob::inserttask(taskid::create_quota); // add htpasswd stats-pages $htpasswdpassword = crypt::makecryptpassword($password, true); $ins_stmt = database::prepare(" insert `" . table_panel_htpasswds . "` set `customerid` = :customerid, `username` = :username, `password` = :passwd, `path` = :path "); $ins_data = [ 'customerid' =&gt; $customerid, 'username' =&gt; $loginname, 'passwd' =&gt; $htpasswdpassword ]; $stats_folder = settings::get('system.traffictool'); $ins_data['path'] = filedir::makecorrectdir($documentroot . '/' . $stats_folder . '/'); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] automatically added " . $stats_folder . " htpasswd user '" . $loginname . "'"); database::pexecute($ins_stmt, $ins_data, true, true); cronjob::inserttask(taskid::rebuild_vhost); // add default ftp-user // also, add froxlor-local user ftp-group (if exists!) // allow access customer-directories within panel, // necessary pathedit = dropdown $local_users = [ settings::get('system.httpuser') ]; ((int)settings::get('system.mod_fcgid_ownvhost') == 1 || (int)settings::get('phpfpm.enabled_ownvhost') == 1) { ((int)settings::get('system.mod_fcgid') == 1) { $local_user = settings::get('system.mod_fcgid_httpuser'); } else { $local_user = settings::get('phpfpm.vhost_httpuser'); } // check froxlor-local user membership ftp-group // without check addition may duplicate user list httpuser == local_user (in_array($local_user, $local_users) == false) { $local_users[] = $local_user; } } $this-&gt;apicall('ftps.add', [ 'customerid' =&gt; $customerid, 'path' =&gt; '/', 'ftp_password' =&gt; $password, 'ftp_description' =&gt; "default", 'sendinfomail' =&gt; 0, 'ftp_username' =&gt; $loginname, 'additional_members' =&gt; $local_users, 'is_defaultuser' =&gt; 1 ]); $_stdsubdomain = ''; ($createstdsubdomain == '1') { (settings::get('system.stdsubdomain') !== null &amp;&amp; settings::get('system.stdsubdomain') != '') { $_stdsubdomain = $loginname . '.' . settings::get('system.stdsubdomain'); } else { $_stdsubdomain = $loginname . '.' . settings::get('system.hostname'); } $ins_data = [ 'domain' =&gt; $_stdsubdomain, 'customerid' =&gt; $customerid, 'adminid' =&gt; $this-&gt;getuserdetail('adminid'), 'docroot' =&gt; $documentroot, 'phpenabled' =&gt; $phpenabled, 'openbasedir' =&gt; '1', 'is_stdsubdomain' =&gt; 1 ]; $domainid = -1; try { $std_domain = $this-&gt;apicall('domains.add', $ins_data, true); $domainid = $std_domain['id']; } catch (exception $e) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_err, "[api] unable add standard-subdomain: " . $e-&gt;getmessage()); } ($domainid &gt; 0) { $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `standardsubdomain` = :domainid `customerid` = :customerid "); database::pexecute($upd_stmt, [ 'domainid' =&gt; $domainid, 'customerid' =&gt; $customerid ], true, true); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] automatically added standardsubdomain user '" . $loginname . "'"); cronjob::inserttask(taskid::rebuild_vhost); } } // create default mysql-user enabled ($mysqls != 0) { foreach ($allowed_mysqlserver $dbserver) { // require privileged access target db-server database::needroot(true, $dbserver, true); // get dbmanager $dbm = new dbmanager($this-&gt;logger()); // give permission user every access-host foreach (array_map('trim', explode(',', settings::get('system.mysql_access_host'))) $mysql_access_host) { $dbm-&gt;getmanager()-&gt;grantprivilegesto($loginname, $password, $mysql_access_host, false, false, true); } $dbm-&gt;getmanager()-&gt;flushprivileges(); database::needroot(false); } } ($sendpassword == '1') { $srv_hostname = settings::get('system.hostname'); (settings::get('system.froxlordirectlyviahostname') == '0') { $srv_hostname .= '/' . basename(\froxlor\froxlor::getinstalldir()); } $srv_ip_stmt = database::prepare(" select ip, port `" . table_panel_ipsandports . "` `id` = :defaultip "); $default_ips = settings::get('system.defaultip'); $default_ips = explode(',', $default_ips); $srv_ip = database::pexecute_first($srv_ip_stmt, [ 'defaultip' =&gt; reset($default_ips) ], true, true); $replace_arr = [ 'firstname' =&gt; $firstname, 'name' =&gt; $name, 'company' =&gt; $company, 'salutation' =&gt; user::getcorrectusersalutation([ 'firstname' =&gt; $firstname, 'name' =&gt; $name, 'company' =&gt; $company ]), 'customer_no' =&gt; $customernumber, 'username' =&gt; $loginname, 'password' =&gt; $password, 'server_hostname' =&gt; $srv_hostname, 'server_ip' =&gt; $srv_ip['ip'] ?? '', 'server_port' =&gt; $srv_ip['port'] ?? '', 'domainname' =&gt; $_stdsubdomain ]; // get template mail subject $mail_subject = $this-&gt;getmailtemplate([ 'adminid' =&gt; $this-&gt;getuserdetail('adminid'), 'def_language' =&gt; $def_language ], 'mails', 'createcustomer_subject', $replace_arr, lng('mails.createcustomer.subject')); // get template mail body $mail_body = $this-&gt;getmailtemplate([ 'adminid' =&gt; $this-&gt;getuserdetail('adminid'), 'def_language' =&gt; $def_language ], 'mails', 'createcustomer_mailbody', $replace_arr, lng('mails.createcustomer.mailbody')); $_mailerror = false; $mailerr_msg = ""; try { $this-&gt;mailer()-&gt;subject = $mail_subject; $this-&gt;mailer()-&gt;altbody = $mail_body; $this-&gt;mailer()-&gt;body = str_replace("\n", "&lt;br /&gt;", $mail_body); $this-&gt;mailer()-&gt;addaddress($email, user::getcorrectusersalutation([ 'firstname' =&gt; $firstname, 'name' =&gt; $name, 'company' =&gt; $company ])); $this-&gt;mailer()-&gt;send(); } catch (\phpmailer\phpmailer\exception $e) { $mailerr_msg = $e-&gt;errormessage(); $_mailerror = true; } catch (exception $e) { $mailerr_msg = $e-&gt;getmessage(); $_mailerror = true; } ($_mailerror) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_err, "[api] error sending mail: " . $mailerr_msg); response::standarderror('errorsendingmail', $email, true); } $this-&gt;mailer()-&gt;clearaddresses(); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] automatically sent password user '" . $loginname . "'"); } } $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] added customer '" . $loginname . "'"); $result = $this-&gt;apicall('customers.get', [ 'loginname' =&gt; $loginname ]); return $this-&gt;response($result); } throw new exception("no resources available", 406); } throw new exception("not allowed execute given command.", 403); } /** * return customer entry either id loginname * * @param int $id * optional, customer-id * @param string $loginname * optional, loginname * @param bool $show_usages * optional, default false * * @access admin, customer * @return string json-encoded array * @throws exception */ public function get() { $id = $this-&gt;getparam('id', true, 0); $ln_optional = $id &gt; 0; $loginname = $this-&gt;getparam('loginname', $ln_optional, ''); $show_usages = $this-&gt;getboolparam('show_usages', true, false); ($this-&gt;isadmin()) { $result_stmt = database::prepare(" select `c`.*, `a`.`loginname` `adminname` `" . table_panel_customers . "` `c`, `" . table_panel_admins . "` `a` " . ($id &gt; 0 ? "`c`.`customerid` = :idln" : "`c`.`loginname` = :idln") . ($this-&gt;getuserdetail('customers_see_all') ? '' : " `c`.`adminid` = :adminid") . " `c`.`adminid` = `a`.`adminid`"); $params = [ 'idln' =&gt; ($id &lt;= 0 ? $loginname : $id) ]; ($this-&gt;getuserdetail('customers_see_all') == '0') { $params['adminid'] = $this-&gt;getuserdetail('adminid'); } } else { (($id &gt; 0 &amp;&amp; $id != $this-&gt;getuserdetail('customerid')) || !empty($loginname) &amp;&amp; $loginname != $this-&gt;getuserdetail('loginname')) { throw new exception("you cannot access data customers", 401); } $result_stmt = database::prepare(" select * `" . table_panel_customers . "` " . ($id &gt; 0 ? "`customerid` = :idln" : "`loginname` = :idln")); $params = [ 'idln' =&gt; ($id &lt;= 0 ? $loginname : $id) ]; } $result = database::pexecute_first($result_stmt, $params, true, true); ($result) { // check whether admin want customer see notes (!$this-&gt;isadmin() &amp;&amp; $result['custom_notes_show'] != 1) { $result['custom_notes'] = ""; } ($show_usages) { // get number domains $domains_stmt = database::prepare(" select count(`id`) `domains` `" . table_panel_domains . "` `customerid` = :cid `parentdomainid` = '0' `id`&lt;&gt; :stdd "); database::pexecute($domains_stmt, [ 'cid' =&gt; $result['customerid'], 'stdd' =&gt; $result['standardsubdomain'] ]); $domains = $domains_stmt-&gt;fetch(pdo::fetch_assoc); $result['domains'] = intval($domains['domains']); // get disk-space usages web, mysql mail $usages_stmt = database::prepare(" select * `" . table_panel_diskspace . "` `customerid` = :cid order `stamp` desc limit 1 "); $usages = database::pexecute_first($usages_stmt, [ 'cid' =&gt; $result['customerid'] ]); ($usages) { $result['webspace_used'] = $usages['webspace']; $result['mailspace_used'] = $usages['mail']; $result['dbspace_used'] = $usages['mysql']; } else { $result['webspace_used'] = 0; $result['mailspace_used'] = 0; $result['dbspace_used'] = 0; } } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_info, "[api] get customer '" . $result['loginname'] . "'"); return $this-&gt;response($result); } $key = ($id &gt; 0 ? "id #" . $id : "loginname '" . $loginname . "'"); throw new exception("customer " . $key . " could found", 404); } /** * increase resource-usage * * @param int $customerid * @param string $resource * @param string $extra * optional, default empty * @param int $increase_by * optional, default 1 */ public static function increaseusage($customerid = 0, $resource = null, $extra = '', $increase_by = 1) { self::updateresourceusage(table_panel_customers, 'customerid', $customerid, '+', $resource, $extra, $increase_by); } /** * update customer entry either id loginname, customer change language, password theme * * @param int $id * optional, customer-id * @param string $loginname * optional, loginname * @param string $email * optional * @param string $name * optional company set, else required * @param string $firstname * optional company set, else required * @param string $company * optional required name/firstname empty * @param string $street * optional * @param string $zipcode * optional * @param string $city * optional * @param string $phone * optional * @param string $fax * optional * @param int $customernumber * optional * @param string $def_language * * optional, iso 639-1 language code (e.g. 'en', 'de', see lng-folder supported languages), * * default system-default language * @param bool $gui_access * optional, allow login via webui, false login via webui disallowed; default true * @param bool $api_allowed * optional, default true system setting api.enabled true, else false * @param int $gender * optional, 0 = no-gender, 1 = male, 2 = female * @param string $custom_notes * optional notes * @param bool $custom_notes_show * optional, whether show content custom_notes customer, default 0 * (false) * @param string $new_customer_password * optional, set new password * @param bool $sendpassword * optional, whether send password customer creation, default 0 * (false) * @param int $move_to_admin * optional, valid admin-id given here, customer's admin/reseller * changed * @param bool $deactivated * optional, 1 (true) customer deactivated/suspended * @param int $diskspace * optional disk-space available customer mb, default 0 * @param bool $diskspace_ul * optional, whether customer unlimited diskspace, default 0 (false) * @param int $traffic * optional traffic available customer gb, default 0 * @param bool $traffic_ul * optional, whether customer unlimited traffic, default 0 (false) * @param int $subdomains * optional amount subdomains available customer, default 0 * @param bool $subdomains_ul * optional, whether customer unlimited subdomains, default 0 (false) * @param int $emails * optional amount emails available customer, default 0 * @param bool $emails_ul * optional, whether customer unlimited emails, default 0 (false) * @param int $email_accounts * optional amount email-accounts available customer, default 0 * @param bool $email_accounts_ul * optional, whether customer unlimited email-accounts, default 0 (false) * @param int $email_forwarders * optional amount email-forwarders available customer, default 0 * @param bool $email_forwarders_ul * optional, whether customer unlimited email-forwarders, default 0 (false) * @param int $email_quota * optional size email-quota available customer mb, default system-setting * mail_quota * @param bool $email_quota_ul * optional, whether customer unlimited email-quota, default 0 (false) * @param bool $email_imap * optional, whether allow imap access, default 0 (false) * @param bool $email_pop3 * optional, whether allow pop3 access, default 0 (false) * @param int $ftps * optional amount ftp-accounts available customer, default 0 * @param bool $ftps_ul * optional, whether customer unlimited ftp-accounts, default 0 (false) * @param int $mysqls * optional amount mysql-databases available customer, default 0 * @param bool $mysqls_ul * optional, whether customer unlimited mysql-databases, default 0 (false) * @param bool $createstdsubdomain * optional, whether create standard-subdomain ([loginname].froxlor-hostname.tld), * default 1 (if customer std-subdomain) else 0 (false) * @param bool $phpenabled * optional, whether allow usage php, default 0 (false) * @param array $allowed_phpconfigs * optional, array ids php-config customer allowed use, default * empty (none) * @param bool $perlenabled * optional, whether allow usage perl/cgi, default 0 (false) * @param bool $dnsenabled * optional, whether allow usage dns editor (requires activated nameserver * settings), default 0 (false) * @param bool $logviewenabled * optional, whether allow access webserver access/error-logs, default 0 (false) * @param string $theme * optional, change theme * @param array $allowed_mysqlserver * optional, array ids defined mysql-servers customer allowed use, * default allow default dbserver (id=0) * * @access admin, customer * @return string json-encoded array * @throws exception */ public function update() { $id = $this-&gt;getparam('id', true, 0); $ln_optional = $id &gt; 0; $loginname = $this-&gt;getparam('loginname', $ln_optional, ''); $result = $this-&gt;apicall('customers.get', [ 'id' =&gt; $id, 'loginname' =&gt; $loginname ]); $id = $result['customerid']; ($this-&gt;isadmin()) { // parameters $move_to_admin = (int)($this-&gt;getparam('move_to_admin', true, 0)); $idna_convert = new idnawrapper(); $email = $this-&gt;getparam('email', true, $idna_convert-&gt;decode($result['email'])); $name = $this-&gt;getparam('name', true, $result['name']); $firstname = $this-&gt;getparam('firstname', true, $result['firstname']); $company_required = ((!empty($name) &amp;&amp; empty($firstname)) || (empty($name) &amp;&amp; !empty($firstname)) || (empty($name) &amp;&amp; empty($firstname))) &amp;&amp; empty($result['company']); $company = $this-&gt;getparam('company', !$company_required, $result['company']); $street = $this-&gt;getparam('street', true, $result['street']); $zipcode = $this-&gt;getparam('zipcode', true, $result['zipcode']); $city = $this-&gt;getparam('city', true, $result['city']); $phone = $this-&gt;getparam('phone', true, $result['phone']); $fax = $this-&gt;getparam('fax', true, $result['fax']); $customernumber = $this-&gt;getparam('customernumber', true, $result['customernumber']); $def_language = $this-&gt;getparam('def_language', true, $result['def_language']); $gui_access = $this-&gt;getboolparam('gui_access', true, $result['gui_access']); $api_allowed = $this-&gt;getboolparam('api_allowed', true, $result['api_allowed']); $gender = (int)$this-&gt;getparam('gender', true, $result['gender']); $custom_notes = $this-&gt;getparam('custom_notes', true, $result['custom_notes']); $custom_notes_show = $this-&gt;getboolparam('custom_notes_show', true, $result['custom_notes_show']); $dec_places = settings::get('panel.decimal_places'); $diskspace = $this-&gt;getulparam('diskspace', 'diskspace_ul', true, round($result['diskspace'] / 1024, $dec_places)); $traffic = $this-&gt;getulparam('traffic', 'traffic_ul', true, round($result['traffic'] / (1024 * 1024), $dec_places)); $subdomains = $this-&gt;getulparam('subdomains', 'subdomains_ul', true, $result['subdomains']); $emails = $this-&gt;getulparam('emails', 'emails_ul', true, $result['emails']); $email_accounts = $this-&gt;getulparam('email_accounts', 'email_accounts_ul', true, $result['email_accounts']); $email_forwarders = $this-&gt;getulparam('email_forwarders', 'email_forwarders_ul', true, $result['email_forwarders']); $email_quota = $this-&gt;getulparam('email_quota', 'email_quota_ul', true, $result['email_quota']); $email_imap = $this-&gt;getparam('email_imap', true, $result['imap']); $email_pop3 = $this-&gt;getparam('email_pop3', true, $result['pop3']); $ftps = $this-&gt;getulparam('ftps', 'ftps_ul', true, $result['ftps']); $mysqls = $this-&gt;getulparam('mysqls', 'mysqls_ul', true, $result['mysqls']); $createstdsubdomain = $this-&gt;getboolparam('createstdsubdomain', true, ($result['standardsubdomain'] != 0 ? 1 : 0)); $password = $this-&gt;getparam('new_customer_password', true, ''); $phpenabled = $this-&gt;getboolparam('phpenabled', true, $result['phpenabled']); $allowed_phpconfigs = $this-&gt;getparam('allowed_phpconfigs', true, json_decode($result['allowed_phpconfigs'], true)); $perlenabled = $this-&gt;getboolparam('perlenabled', true, $result['perlenabled']); $dnsenabled = $this-&gt;getboolparam('dnsenabled', true, $result['dnsenabled']); $logviewenabled = $this-&gt;getboolparam('logviewenabled', true, $result['logviewenabled']); $deactivated = $this-&gt;getboolparam('deactivated', true, $result['deactivated']); $theme = $this-&gt;getparam('theme', true, $result['theme']); $allowed_mysqlserver = $this-&gt;getparam('allowed_mysqlserver', true, json_decode($result['allowed_mysqlserver'], true)); } else { // allowed parameters $def_language = $this-&gt;getparam('def_language', true, $result['def_language']); $password = $this-&gt;getparam('new_customer_password', true, ''); $theme = $this-&gt;getparam('theme', true, $result['theme']); } // validation ($this-&gt;isadmin()) { $idna_convert = new idnawrapper(); $name = validate::validate($name, 'name', validate::regex_desc_text, '', [], true); $firstname = validate::validate($firstname, 'first name', validate::regex_desc_text, '', [], true); $company = validate::validate($company, 'company', validate::regex_desc_text, '', [], true); $street = validate::validate($street, 'street', validate::regex_desc_text, '', [], true); $zipcode = validate::validate($zipcode, 'zipcode', '/^[0-9 \-a-z]*$/', '', [], true); $city = validate::validate($city, 'city', validate::regex_desc_text, '', [], true); $phone = validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', [], true); $fax = validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', [], true); $email = $idna_convert-&gt;encode(validate::validate($email, 'email', '', '', [], true)); $customernumber = validate::validate($customernumber, 'customer number', '/^[a-za-z0-9 \-]*$/di', '', [], true); $custom_notes = validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', validate::regex_conf_text, '', [], true); (!empty($allowed_phpconfigs)) { $allowed_phpconfigs = array_map('intval', $allowed_phpconfigs); } (empty($allowed_phpconfigs) &amp;&amp; $phpenabled == 1) { // required using mod_php ((int)settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1) { response::standarderror('customerphpenabledbutnoconfig', '', true); } } // add permission allowed mysql usage customer allowed use mysql prior ($result['mysqls'] == 0 &amp;&amp; ($mysqls == -1 || $mysqls &gt; 0)) { $allowed_mysqlserver = $this-&gt;getparam('allowed_mysqlserver', true, [0]); } (!empty($allowed_mysqlserver)) { $allowed_mysqlserver = array_map('intval', $allowed_mysqlserver); } } $def_language = validate::validate($def_language, 'default language', '', '', [], true); $theme = validate::validate($theme, 'theme', '', '', [], true); (settings::get('system.mail_quota_enabled') != '1') { $email_quota = -1; } (empty($theme)) { $theme = settings::get('panel.default_theme'); } ($this-&gt;isadmin()) { $diskspace *= 1024; $traffic *= 1024 * 1024; ( ($diskspace != 0 &amp;&amp; (($this-&gt;getuserdetail('diskspace_used') + $diskspace - $result['diskspace']) &gt; $this-&gt;getuserdetail('diskspace')) &amp;&amp; ($this-&gt;getuserdetail('diskspace') / 1024) != '-1') || ($mysqls != 0 &amp;&amp; (($this-&gt;getuserdetail('mysqls_used') + $mysqls - $result['mysqls']) &gt; $this-&gt;getuserdetail('mysqls')) &amp;&amp; $this-&gt;getuserdetail('mysqls') != '-1') || ($emails != 0 &amp;&amp; (($this-&gt;getuserdetail('emails_used') + $emails - $result['emails']) &gt; $this-&gt;getuserdetail('emails')) &amp;&amp; $this-&gt;getuserdetail('emails') != '-1') || ($email_accounts != 0 &amp;&amp; (($this-&gt;getuserdetail('email_accounts_used') + $email_accounts - $result['email_accounts']) &gt; $this-&gt;getuserdetail('email_accounts')) &amp;&amp; $this-&gt;getuserdetail('email_accounts') != '-1') || ($email_forwarders != 0 &amp;&amp; (($this-&gt;getuserdetail('email_forwarders_used') + $email_forwarders - $result['email_forwarders']) &gt; $this-&gt;getuserdetail('email_forwarders')) &amp;&amp; $this-&gt;getuserdetail('email_forwarders') != '-1') || ($email_quota != 0 &amp;&amp; (($this-&gt;getuserdetail('email_quota_used') + $email_quota - $result['email_quota']) &gt; $this-&gt;getuserdetail('email_quota')) &amp;&amp; $this-&gt;getuserdetail('email_quota') != '-1' &amp;&amp; settings::get('system.mail_quota_enabled') == '1') || ($ftps != 0 &amp;&amp; (($this-&gt;getuserdetail('ftps_used') + $ftps - $result['ftps']) &gt; $this-&gt;getuserdetail('ftps')) &amp;&amp; $this-&gt;getuserdetail('ftps') != '-1') || ($subdomains != 0 &amp;&amp; (($this-&gt;getuserdetail('subdomains_used') + $subdomains - $result['subdomains']) &gt; $this-&gt;getuserdetail('subdomains')) &amp;&amp; $this-&gt;getuserdetail('subdomains') != '-1') || (($diskspace / 1024) == '-1' &amp;&amp; ($this-&gt;getuserdetail('diskspace') / 1024) != '-1') || ($mysqls == '-1' &amp;&amp; $this-&gt;getuserdetail('mysqls') != '-1') || ($emails == '-1' &amp;&amp; $this-&gt;getuserdetail('emails') != '-1') || ($email_accounts == '-1' &amp;&amp; $this-&gt;getuserdetail('email_accounts') != '-1') || ($email_forwarders == '-1' &amp;&amp; $this-&gt;getuserdetail('email_forwarders') != '-1') || ($email_quota == '-1' &amp;&amp; $this-&gt;getuserdetail('email_quota') != '-1' &amp;&amp; settings::get('system.mail_quota_enabled') == '1') || ($ftps == '-1' &amp;&amp; $this-&gt;getuserdetail('ftps') != '-1') || ($subdomains == '-1' &amp;&amp; $this-&gt;getuserdetail('subdomains') != '-1') ) { response::standarderror('youcantallocatemorethanyouhave', '', true); } // validate allowed_mysqls whether customer databases removed, disallowed db-server abort true $former_allowed_mysqlserver = json_decode($result['allowed_mysqlserver'], true); ($allowed_mysqlserver != $former_allowed_mysqlserver &amp;&amp; !empty($former_allowed_mysqlserver)) { $to_remove_mysqlserver = array_diff($former_allowed_mysqlserver, $allowed_mysqlserver); (count($to_remove_mysqlserver) &gt; 0) { foreach ($to_remove_mysqlserver $mysqlserver_check) { $result_ms = $this-&gt;apicall('mysqlserver.databasesonserver', [ 'mysql_server' =&gt; $mysqlserver_check, 'customerid' =&gt; $id ]); ($result_ms['count'] &gt; 0) { response::standarderror('mysqlserverstillhasdbs', '', true); } } } } ($email == '') { response::standarderror([ 'stringisempty', 'customer.email' ], '', true); } elseif (!validate::validateemail($email)) { response::standarderror('emailiswrong', $email, true); } else { // check existing email address // check via api skip permission checks task $email_check_admin_stmt = database::prepare(" select `email` `" . table_panel_admins . "` `email` = :email "); $email_check_admin = database::pexecute_first($email_check_admin_stmt, [ 'email' =&gt; $email ], true, true); ($email_check_admin &amp;&amp; strtolower($email_check_admin['email']) == strtolower($email)) { response::standarderror('emailexistsanon', $email, true); } } } ($password != '') { $password = crypt::validatepassword($password, true); $password = crypt::makecryptpassword($password); } else { $password = $result['password']; } ($this-&gt;isadmin()) { ($createstdsubdomain != '1' || $deactivated) { $createstdsubdomain = '0'; } ($createstdsubdomain == '1' &amp;&amp; $result['standardsubdomain'] == '0') { (settings::get('system.stdsubdomain') !== null &amp;&amp; settings::get('system.stdsubdomain') != '') { $_stdsubdomain = $result['loginname'] . '.' . settings::get('system.stdsubdomain'); } else { $_stdsubdomain = $result['loginname'] . '.' . settings::get('system.hostname'); } $ins_data = [ 'domain' =&gt; $_stdsubdomain, 'customerid' =&gt; $result['customerid'], 'adminid' =&gt; $this-&gt;getuserdetail('adminid'), 'docroot' =&gt; $result['documentroot'], 'phpenabled' =&gt; $phpenabled, 'openbasedir' =&gt; '1' ]; $domainid = -1; try { $std_domain = $this-&gt;apicall('domains.add', $ins_data); $domainid = $std_domain['id']; } catch (exception $e) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_err, "[api] unable add standard-subdomain: " . $e-&gt;getmessage()); } ($domainid &gt; 0) { $upd_stmt = database::prepare(" update `" . table_panel_customers . "` set `standardsubdomain` = :domainid `customerid` = :customerid "); database::pexecute($upd_stmt, [ 'domainid' =&gt; $domainid, 'customerid' =&gt; $result['customerid'] ], true, true); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] automatically added standardsubdomain user '" . $result['loginname'] . "'"); cronjob::inserttask(taskid::rebuild_vhost); } } ($createstdsubdomain == '0' &amp;&amp; $result['standardsubdomain'] != '0') { try { $std_domain = $this-&gt;apicall('domains.delete', [ 'id' =&gt; $result['standardsubdomain'], 'is_stdsubdomain' =&gt; 1 ]); } catch (exception $e) { $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_err, "[api] unable delete standard-subdomain: " . $e-&gt;getmessage()); } $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] automatically deleted standardsubdomain user '" . $result['loginname'] . "'"); cronjob::inserttask(taskid::rebuild_vhost); } ($phpenabled != $result['phpenabled'] || $perlenabled != $result['perlenabled'] || $email != $result['email']) { cronjob::inserttask(taskid::rebuild_vhost); } // activate/deactivate customer services ($deactivated != $result['deactivated']) { $yesno = ($deactivated ? 'n' : 'y'); $pop3 = ($deactivated ? '0' : (int)$result['pop3']); $imap = ($deactivated ? '0' : (int)$result['imap']); $upd_stmt = database::prepare(" update `" . table_mail_users . "` set `postfix`= :yesno, `pop3` = :pop3, `imap` = :imap `customerid` = :customerid "); database::pexecute($upd_stmt, [ 'yesno' =&gt; $yesno, 'pop3' =&gt; $pop3, 'imap' =&gt; $imap, 'customerid' =&gt; $id ]); $upd_stmt = database::prepare(" update `" . table_ftp_users . "` set `login_enabled` = :yesno `customerid` = :customerid "); database::pexecute($upd_stmt, [ 'yesno' =&gt; $yesno, 'customerid' =&gt; $id ]); $upd_stmt = database::prepare(" update `" . table_panel_domains . "` set `deactivated`= :deactivated `customerid` = :customerid "); database::pexecute($upd_stmt, [ 'deactivated' =&gt; $deactivated, 'customerid' =&gt; $id ]); // enable/disable global mysql-user (loginname) $current_allowed_mysqlserver = isset($result['allowed_mysqlserver']) &amp;&amp; !empty($result['allowed_mysqlserver']) ? json_decode($result['allowed_mysqlserver'], true) : []; foreach ($current_allowed_mysqlserver $dbserver) { // require privileged access target db-server database::needroot(true, $dbserver, true); // get dbmanager $dbm = new dbmanager($this-&gt;logger()); foreach (array_map('trim', explode(',', settings::get('system.mysql_access_host'))) $mysql_access_host) { // prevent access, deactivated ($deactivated) { // failsafe user deleted manually (requires mysql 4.1.2+) $dbm-&gt;getmanager()-&gt;disableuser($result['loginname'], $mysql_access_host); } else { // otherwise grant access $dbm-&gt;getmanager()-&gt;enableuser($result['loginname'], $mysql_access_host, true); } } $dbm-&gt;getmanager()-&gt;flushprivileges(); database::needroot(false); } // retrieve customer's databases $databases_stmt = database::prepare("select * " . table_panel_databases . " customerid = :customerid order `dbserver`"); database::pexecute($databases_stmt, [ 'customerid' =&gt; $id ]); database::needroot(true); $last_dbserver = 0; $dbm = new dbmanager($this-&gt;logger()); // $priv_changed = false; ($row_database = $databases_stmt-&gt;fetch(pdo::fetch_assoc)) { ($last_dbserver != $row_database['dbserver']) { $dbm-&gt;getmanager()-&gt;flushprivileges(); database::needroot(true, $row_database['dbserver']); $last_dbserver = $row_database['dbserver']; } foreach (array_map('trim', explode(',', settings::get('system.mysql_access_host'))) $mysql_access_host) { // prevent access, deactivated ($deactivated) { // failsafe user deleted manually (requires mysql 4.1.2+) $dbm-&gt;getmanager()-&gt;disableuser($row_database['databasename'], $mysql_access_host); } else { // otherwise grant access $dbm-&gt;getmanager()-&gt;enableuser($row_database['databasename'], $mysql_access_host); } } $priv_changed = true; } // last flush new privileges ($priv_changed) { $dbm-&gt;getmanager()-&gt;flushprivileges(); } database::needroot(false); // reactivate/deactivate api-keys $valid_until = $deactivated ? 0 : -1; $stmt = database::prepare("update `" . table_api_keys . "` set `valid_until` = :vu `customerid` = :id"); database::pexecute($stmt, [ 'id' =&gt; $id, 'vu' =&gt; $valid_until ], true, true); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] " . ($deactivated ? 'deactivated' : 'reactivated') . " user '" . $result['loginname'] . "'"); cronjob::inserttask(taskid::rebuild_vhost); } // disable enable pop3 login customers mail accounts ($email_pop3 != $result['pop3']) { $upd_stmt = database::prepare("update `" . table_mail_users . "` set `pop3` = :pop3 `customerid` = :customerid"); database::pexecute($upd_stmt, [ 'pop3' =&gt; $email_pop3, 'customerid' =&gt; $id ]); } // disable enable imap login customers mail accounts ($email_imap != $result['imap']) { $upd_stmt = database::prepare("update `" . table_mail_users . "` set `imap` = :imap `customerid` = :customerid"); database::pexecute($upd_stmt, [ 'imap' =&gt; $email_imap, 'customerid' =&gt; $id ]); } } $upd_data = [ 'customerid' =&gt; $id, 'passwd' =&gt; $password, 'lang' =&gt; $def_language, 'theme' =&gt; $theme ]; ($this-&gt;isadmin()) { $admin_upd_data = [ 'name' =&gt; $name, 'firstname' =&gt; $firstname, 'gender' =&gt; $gender, 'company' =&gt; $company, 'street' =&gt; $street, 'zipcode' =&gt; $zipcode, 'city' =&gt; $city, 'phone' =&gt; $phone, 'fax' =&gt; $fax, 'email' =&gt; $email, 'customerno' =&gt; $customernumber, 'diskspace' =&gt; $diskspace, 'traffic' =&gt; $traffic, 'subdomains' =&gt; $subdomains, 'emails' =&gt; $emails, 'email_accounts' =&gt; $email_accounts, 'email_forwarders' =&gt; $email_forwarders, 'email_quota' =&gt; $email_quota, 'ftps' =&gt; $ftps, 'mysqls' =&gt; $mysqls, 'deactivated' =&gt; $deactivated, 'phpenabled' =&gt; $phpenabled, 'allowed_phpconfigs' =&gt; empty($allowed_phpconfigs) ? "" : json_encode($allowed_phpconfigs), 'imap' =&gt; $email_imap, 'pop3' =&gt; $email_pop3, 'perlenabled' =&gt; $perlenabled, 'dnsenabled' =&gt; $dnsenabled, 'logviewenabled' =&gt; $logviewenabled, 'custom_notes' =&gt; $custom_notes, 'custom_notes_show' =&gt; $custom_notes_show, 'gui_access' =&gt; $gui_access, 'api_allowed' =&gt; $api_allowed, 'allowed_mysqlserver' =&gt; empty($allowed_mysqlserver) ? "" : json_encode($allowed_mysqlserver) ]; $upd_data += $admin_upd_data; } $upd_query = "update `" . table_panel_customers . "` set `def_language` = :lang, `password` = :passwd, `theme` = :theme"; ($this-&gt;isadmin()) { $admin_upd_query = ", `name` = :name, `firstname` = :firstname, `gender` = :gender, `company` = :company, `street` = :street, `zipcode` = :zipcode, `city` = :city, `phone` = :phone, `fax` = :fax, `email` = :email, `customernumber` = :customerno, `diskspace` = :diskspace, `traffic` = :traffic, `subdomains` = :subdomains, `emails` = :emails, `email_accounts` = :email_accounts, `email_forwarders` = :email_forwarders, `ftps` = :ftps, `mysqls` = :mysqls, `deactivated` = :deactivated, `phpenabled` = :phpenabled, `allowed_phpconfigs` = :allowed_phpconfigs, `email_quota` = :email_quota, `imap` = :imap, `pop3` = :pop3, `perlenabled` = :perlenabled, `dnsenabled` = :dnsenabled, `logviewenabled` = :logviewenabled, `custom_notes` = :custom_notes, `custom_notes_show` = :custom_notes_show, `gui_access` = :gui_access, `api_allowed` = :api_allowed, `allowed_mysqlserver` = :allowed_mysqlserver"; $upd_query .= $admin_upd_query; } $upd_query .= " `customerid` = :customerid"; $upd_stmt = database::prepare($upd_query); database::pexecute($upd_stmt, $upd_data); ($this-&gt;isadmin()) { // using filesystem - quota, insert task cleans filesystem - quota cronjob::inserttask(taskid::create_quota); $admin_update_query = "update `" . table_panel_admins . "` set `customers_used` = `customers_used` "; ($mysqls != '-1' || $result['mysqls'] != '-1') { $admin_update_query .= ", `mysqls_used` = `mysqls_used` "; ($mysqls != '-1') { $admin_update_query .= " + 0" . (int)$mysqls . " "; } ($result['mysqls'] != '-1') { $admin_update_query .= " - 0" . (int)$result['mysqls'] . " "; } } ($emails != '-1' || $result['emails'] != '-1') { $admin_update_query .= ", `emails_used` = `emails_used` "; ($emails != '-1') { $admin_update_query .= " + 0" . (int)$emails . " "; } ($result['emails'] != '-1') { $admin_update_query .= " - 0" . (int)$result['emails'] . " "; } } ($email_accounts != '-1' || $result['email_accounts'] != '-1') { $admin_update_query .= ", `email_accounts_used` = `email_accounts_used` "; ($email_accounts != '-1') { $admin_update_query .= " + 0" . (int)$email_accounts . " "; } ($result['email_accounts'] != '-1') { $admin_update_query .= " - 0" . (int)$result['email_accounts'] . " "; } } ($email_forwarders != '-1' || $result['email_forwarders'] != '-1') { $admin_update_query .= ", `email_forwarders_used` = `email_forwarders_used` "; ($email_forwarders != '-1') { $admin_update_query .= " + 0" . (int)$email_forwarders . " "; } ($result['email_forwarders'] != '-1') { $admin_update_query .= " - 0" . (int)$result['email_forwarders'] . " "; } } ($email_quota != '-1' || $result['email_quota'] != '-1') { $admin_update_query .= ", `email_quota_used` = `email_quota_used` "; ($email_quota != '-1') { $admin_update_query .= " + 0" . (int)$email_quota . " "; } ($result['email_quota'] != '-1') { $admin_update_query .= " - 0" . (int)$result['email_quota'] . " "; } } ($subdomains != '-1' || $result['subdomains'] != '-1') { $admin_update_query .= ", `subdomains_used` = `subdomains_used` "; ($subdomains != '-1') { $admin_update_query .= " + 0" . (int)$subdomains . " "; } ($result['subdomains'] != '-1') { $admin_update_query .= " - 0" . (int)$result['subdomains'] . " "; } } ($ftps != '-1' || $result['ftps'] != '-1') { $admin_update_query .= ", `ftps_used` = `ftps_used` "; ($ftps != '-1') { $admin_update_query .= " + 0" . (int)$ftps . " "; } ($result['ftps'] != '-1') { $admin_update_query .= " - 0" . (int)$result['ftps'] . " "; } } (($diskspace / 1024) != '-1' || ($result['diskspace'] / 1024) != '-1') { $admin_update_query .= ", `diskspace_used` = `diskspace_used` "; (($diskspace / 1024) != '-1') { $admin_update_query .= " + 0" . (int)$diskspace . " "; } (($result['diskspace'] / 1024) != '-1') { $admin_update_query .= " - 0" . (int)$result['diskspace'] . " "; } } $admin_update_query .= " `adminid` = '" . (int)$result['adminid'] . "'"; database::query($admin_update_query); } $this-&gt;logger()-&gt;logaction($this-&gt;isadmin() ? froxlorlogger::adm_action : froxlorlogger::usr_action, log_notice, "[api] edited user '" . $result['loginname'] . "'"); /* * move customer another admin/reseller; #1166 */ ($this-&gt;isadmin()) { ($move_to_admin &gt; 0 &amp;&amp; $move_to_admin != $result['adminid']) { $move_result = $this-&gt;apicall('customers.move', [ 'id' =&gt; $result['customerid'], 'adminid' =&gt; $move_to_admin ]); ($move_result != true) { response::standarderror('moveofcustomerfailed', $move_result, true); } } } $result = $this-&gt;apicall('customers.get', [ 'id' =&gt; $result['customerid'] ]); return $this-&gt;response($result); } /** * delete customer entry either id loginname * * @param int $id * optional, customer-id * @param string $loginname * optional, loginname * @param bool $delete_userfiles * optional, default false * * @access admin * @return string json-encoded array * @throws exception */ public function delete() { ($this-&gt;isadmin()) { $id = $this-&gt;getparam('id', true, 0); $ln_optional = $id &gt; 0; $loginname = $this-&gt;getparam('loginname', $ln_optional, ''); $delete_userfiles = $this-&gt;getparam('delete_userfiles', true, 0); $result = $this-&gt;apicall('customers.get', [ 'id' =&gt; $id, 'loginname' =&gt; $loginname ]); $id = $result['customerid']; // remove global mysql-user (loginname) $current_allowed_mysqlserver = isset($result['allowed_mysqlserver']) &amp;&amp; !empty($result['allowed_mysqlserver']) ? json_decode($result['allowed_mysqlserver'], true) : []; foreach ($current_allowed_mysqlserver $dbserver) { // require privileged access target db-server database::needroot(true, $dbserver, false); // get dbmanager $dbm = new dbmanager($this-&gt;logger()); foreach (array_map('trim', explode(',', settings::get('system.mysql_access_host'))) $mysql_access_host) { $dbm-&gt;getmanager()-&gt;deleteuser($result['loginname'], $mysql_access_host); } $dbm-&gt;getmanager()-&gt;flushprivileges(); database::needroot(false); } // remove databases $databases_stmt = database::prepare(" select * `" . table_panel_databases . "` `customerid` = :id order `dbserver` "); database::pexecute($databases_stmt, [ 'id' =&gt; $id ]); database::needroot(true); $last_dbserver = 0; $dbm = new dbmanager($this-&gt;logger()); $priv_changed = false; ($row_database = $databases_stmt-&gt;fetch(pdo::fetch_assoc)) { ($last_dbserver != $row_database['dbserver']) { $dbm-&gt;getmanager()-&gt;flushprivileges(); database::needroot(true, $row_database['dbserver']); $last_dbserver = $row_database['dbserver']; } $dbm-&gt;getmanager()-&gt;deletedatabase($row_database['databasename']); $priv_changed = true; } ($priv_changed) { $dbm-&gt;getmanager()-&gt;flushprivileges(); } database::needroot(false); // delete customer $stmt = database::prepare("delete `" . table_panel_customers . "` `customerid` = :id"); database::pexecute($stmt, [ 'id' =&gt; $id ], true, true); // delete customer databases $stmt = database::prepare("delete `" . table_panel_databases . "` `customerid` = :id"); database::pexecute($stmt, [ 'id' =&gt; $id ], true, true); // first gather domain-id's clean panel_domaintoip, dns-entries certificates accordingly $did_stmt = database::prepare("select `id`, `domain` `" . table_panel_domains . "` `customerid` = :id"); database::pexecute($did_stmt, [ 'id' =&gt; $id ], true, true); ($row = $did_stmt-&gt;fetch(pdo::fetch_assoc)) { // remove domain-&gt;ip connection $stmt = database::prepare("delete `" . table_domaintoip . "` `id_domain` = :did"); database::pexecute($stmt, [ 'did' =&gt; $row['id'] ], true, true); // remove domain-&gt;dns entries $stmt = database::prepare("delete `" . table_domain_dns . "` `domain_id` = :did"); database::pexecute($stmt, [ 'did' =&gt; $row['id'] ], true, true); // remove domain-&gt;certificates entries $stmt = database::prepare("delete `" . table_panel_domain_ssl_settings . "` `domainid` = :did"); database::pexecute($stmt, [ 'did' =&gt; $row['id'] ], true, true); // remove domains dns powerdns used, #581 cronjob::inserttask(taskid::delete_domain_pdns, $row['domain']); // remove domain acme.sh / lets encrypt used cronjob::inserttask(taskid::delete_domain_ssl, $row['domain']); } // remove customer domains $stmt = database::prepare("delete `" . table_panel_domains . "` `customerid` = :id"); database::pexecute($stmt, [ 'id' =&gt; $id ], true, true); $domains_deleted = $stmt-&gt;rowcount(); // delete htpasswds $stmt = database::prepare("delete `" . table_panel_htpasswds . "` `customerid` = :id"); database::pexecute($stmt, [ 'id' =&gt; $id ], true, true); // delete htaccess options $stmt = database::prepare("delete `" . table_panel_htaccess . "` `customerid` = :id"); database::pexecute($stmt, [ 'id' =&gt; $id ], true, true); // delete traffic information $stmt = database::prepare("delete `" . table_panel_traffic . "` `customerid` = :id"); database::pexecute($stmt, [ 'id' =&gt; $id ], true, true); // remove diskspace analysis $stmt = database::prepare("delete `" . table_panel_diskspace . "` `customerid` = :id"); database::pexecute($stmt, [ 'id' =&gt; $id ], true, true); // delete mail-accounts $stmt = database::prepare("delete `" . table_mail_users . "` `customerid` = :id"); database::pexecute($stmt, [ 'id' =&gt; $id ], true, true); // delete mail-addresses $stmt = database::prepare("delete `" . table_mail_virtual . "` `customerid` = :id"); database::pexecute($stmt, [ 'id' =&gt; $id ], true, true); // gather ftp-user names $result2_stmt = database::prepare("select `username` `" . table_ftp_users . "` `customerid` = :id"); database::pexecute($result2_stmt, [ 'id' =&gt; $id ], true, true); ($row = $result2_stmt-&gt;fetch(pdo::fetch_assoc)) { // delete ftp-quotatallies username $stmt = database::prepare("delete `" . table_ftp_quotatallies . "` `name` = :name"); database::pexecute($stmt, [ 'name' =&gt; $row['username'] ], true, true); } // remove ftp-group $stmt = database::prepare("delete `" . table_ftp_groups . "` `customerid` = :id"); database::pexecute($stmt, [ 'id' =&gt; $id ], true, true); // remove ftp-users $stmt = database::prepare("delete `" . table_ftp_users . "` `customerid` = :id"); database::pexecute($stmt, [ 'id' =&gt; $id ], true, true); // remove api-keys $stmt = database::prepare("delete `" . table_api_keys . "` `customerid` = :id"); database::pexecute($stmt, [ 'id' =&gt; $id ], true, true); // delete waiting "create user" -tasks user, #276 // note: selects part serialized array, safe way $del_stmt = database::prepare(" delete `" . table_panel_tasks . "` `type` = '2' `data` like :loginname "); database::pexecute($del_stmt, [ 'loginname' =&gt; "%:{$result['loginname']};%" ], true, true); // update admin-resource-usage admins::decreaseusage($result['adminid'], 'customers_used'); admins::decreaseusage($result['adminid'], 'domains_used', '', (int)($domains_deleted - $result['subdomains_used'])); ($result['mysqls'] != '-1') { admins::decreaseusage($result['adminid'], 'mysqls_used', '', (int)$result['mysqls']); } ($result['emails'] != '-1') { admins::decreaseusage($result['adminid'], 'emails_used', '', (int)$result['emails']); } ($result['email_accounts'] != '-1') { admins::decreaseusage($result['adminid'], 'email_accounts_used', '', (int)$result['email_accounts']); } ($result['email_forwarders'] != '-1') { admins::decreaseusage($result['adminid'], 'email_forwarders_used', '', (int)$result['email_forwarders']); } ($result['email_quota'] != '-1') { admins::decreaseusage($result['adminid'], 'email_quota_used', '', (int)$result['email_quota']); } ($result['subdomains'] != '-1') { admins::decreaseusage($result['adminid'], 'subdomains_used', '', (int)$result['subdomains']); } ($result['ftps'] != '-1') { admins::decreaseusage($result['adminid'], 'ftps_used', '', (int)$result['ftps']); } (($result['diskspace'] / 1024) != '-1') { admins::decreaseusage($result['adminid'], 'diskspace_used', '', (int)$result['diskspace']); } // rebuild configs cronjob::inserttask(taskid::rebuild_vhost); // using nameserver, insert task rebuilds server config cronjob::inserttask(taskid::rebuild_dns); ($delete_userfiles == 1) { // insert task remove customers files filesystem cronjob::inserttask(taskid::delete_customer_files, $result['loginname']); } // using filesystem - quota, insert task cleans filesystem - quota cronjob::inserttask(taskid::create_quota); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] deleted customer '" . $result['loginname'] . "'"); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } /** * decrease resource-usage * * @param int $customerid * @param string $resource * @param string $extra * optional, default empty * @param int $decrease_by * optional, default 1 */ public static function decreaseusage($customerid = 0, $resource = null, $extra = '', $decrease_by = 1) { self::updateresourceusage(table_panel_customers, 'customerid', $customerid, '-', $resource, $extra, $decrease_by); } /** * unlock locked customer either id loginname * * @param int $id * optional, customer-id * @param string $loginname * optional, loginname * * @access admin * @return string json-encoded array * @throws exception */ public function unlock() { ($this-&gt;isadmin()) { $id = $this-&gt;getparam('id', true, 0); $ln_optional = $id &gt; 0; $loginname = $this-&gt;getparam('loginname', $ln_optional, ''); $result = $this-&gt;apicall('customers.get', [ 'id' =&gt; $id, 'loginname' =&gt; $loginname ]); $id = $result['customerid']; $result_stmt = database::prepare(" update `" . table_panel_customers . "` set `loginfail_count` = '0' `customerid`= :id "); database::pexecute($result_stmt, [ 'id' =&gt; $id ], true, true); // set new value result-array $result['loginfail_count'] = 0; $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_warning, "[api] unlocked customer '" . $result['loginname'] . "'"); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } /** * function move given customer given admin/reseller * update references accordingly * * @param int $id * optional, customer-id * @param string $loginname * optional, loginname * @param int $adminid * target-admin-id * * @access admin * @return string json-encoded array * @throws exception */ public function move() { ($this-&gt;isadmin() &amp;&amp; $this-&gt;getuserdetail('change_serversettings') == 1) { $adminid = $this-&gt;getparam('adminid'); $id = $this-&gt;getparam('id', true, 0); $ln_optional = $id &gt; 0; $loginname = $this-&gt;getparam('loginname', $ln_optional, ''); $c_result = $this-&gt;apicall('customers.get', [ 'id' =&gt; $id, 'loginname' =&gt; $loginname ]); $id = $c_result['customerid']; // check target-admin current admin ($adminid == $c_result['adminid']) { throw new exception("cannot move customer admin/reseller currently assigned to", 406); } // get target admin $a_result = $this-&gt;apicall('admins.get', [ 'id' =&gt; $adminid ]); // update customer entry $updcustomer_stmt = database::prepare(" update `" . table_panel_customers . "` set `adminid` = :adminid `customerid` = :cid "); database::pexecute($updcustomer_stmt, [ 'adminid' =&gt; $adminid, 'cid' =&gt; $id ], true, true); // update customer-domains $upddomains_stmt = database::prepare(" update `" . table_panel_domains . "` set `adminid` = :adminid `customerid` = :cid "); database::pexecute($upddomains_stmt, [ 'adminid' =&gt; $adminid, 'cid' =&gt; $id ], true, true); // now, recalculate resource-usage old new admin user::updatecounters(false); $this-&gt;logger()-&gt;logaction(froxlorlogger::adm_action, log_notice, "[api] moved user '" . $c_result['loginname'] . "' admin/reseller '" . $c_result['adminname'] . " admin/reseller '" . $a_result['loginname'] . "'"); $result = $this-&gt;apicall('customers.get', [ 'id' =&gt; $c_result['customerid'] ]); return $this-&gt;response($result); } throw new exception("not allowed execute given command.", 403); } }</file><file name="lib/Froxlor/Database/DbManager.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\database; use exception; use froxlor\database\manager\dbmanagermysql; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\settings; use pdo; /** * class dbmanager * * wrapper-class database-management like creating * removing databases, users permissions */ class dbmanager { /** * froxlorlogger object * * @var object */ private $log = null; /** * manager object * * @var object */ private $manager = null; /** * main constructor * * @param froxlorlogger $log */ public function __construct($log = null) { $this-&gt;log = $log; $this-&gt;setmanager(); } /** * set manager-object type * dbms: mysql * * sets private $_manager variable */ private function setmanager() { // todo read different dbms settings later $this-&gt;manager = new dbmanagermysql($this-&gt;log); } /** * function called mysql-access-host setting changes * * @param array $mysql_access_host_array * * @return void * @throws exception */ public static function correctmysqlusers(array $mysql_access_host_array) { // get databases dbservers $databases = []; $databases_result_stmt = database::prepare(" select * `" . table_panel_databases . "` order `dbserver` asc "); database::pexecute($databases_result_stmt); ($databases_row = $databases_result_stmt-&gt;fetch(pdo::fetch_assoc)) { (!isset($databases[$databases_row['dbserver']])) { $databases[$databases_row['dbserver']] = []; } $databases[$databases_row['dbserver']][] = $databases_row['databasename']; } $customers_sel = database::query(" select distinct c.loginname `" . table_panel_customers . "` c left join `" . table_panel_databases . "` c.customerid = d.customerid c.deactivated = '0' d.id null "); $customers = []; ($customer = $customers_sel-&gt;fetch(\pdo::fetch_assoc)) { $customers[] = $customer['loginname']; } $dbservers_stmt = database::query("select distinct `dbserver` `" . table_panel_databases . "`"); ($dbserver = $dbservers_stmt-&gt;fetch(pdo::fetch_assoc)) { // add customer loginnames $databases array database-server correct // possible existing global mysql-user customer foreach ($customers $customer) { $databases[$dbserver['dbserver']][] = $customer; } // require privileged access target db-server database::needroot(true, $dbserver['dbserver'], false); $dbm = new dbmanager(froxlorlogger::getinstanceof()); $users = $dbm-&gt;getmanager()-&gt;getallsqlusers(false); foreach ($databases[$dbserver['dbserver']] $username) { (isset($users[$username]['hosts']) &amp;&amp; is_array($users[$username]['hosts'])) { $password = [ 'password' =&gt; $users[$username]['password'], 'plugin' =&gt; $users[$username]['plugin'] ]; foreach ($mysql_access_host_array $mysql_access_host) { $mysql_access_host = trim($mysql_access_host); (!in_array($mysql_access_host, $users[$username]['hosts'])) { $dbm-&gt;getmanager()-&gt;grantprivilegesto($username, $password, $mysql_access_host, true); } } foreach ($users[$username]['hosts'] $mysql_access_host) { (!in_array($mysql_access_host, $mysql_access_host_array)) { $dbm-&gt;getmanager()-&gt;deleteuser($username, $mysql_access_host); } } } } $dbm-&gt;getmanager()-&gt;flushprivileges(); database::needroot(false); unset($databases[$dbserver['dbserver']]); } } /** * creates new database user * name privileges granted db. * db-name user-name generated * password user set * * @param ?string $loginname * @param ?string $password * @param int $dbserver * @param int $last_accnumber * @param ?string $global_user * * @return string|bool $username successful false username equal password * @throws exception */ public function createdatabase(string $loginname = null, string $password = null, int $dbserver = 0, int $last_accnumber = 0, string $global_user = "") { database::needroot(true, $dbserver, true); // check whether shall create random username (strtoupper(settings::get('customer.mysqlprefix')) == 'random') { // get usernames db-manager $allsqlusers = $this-&gt;getmanager()-&gt;getallsqlusers(); // generate random username $username = $loginname . '-' . substr(froxlor::gensessionid(), 20, 3); // check whether exists dbms (in_array($username, $allsqlusers)) { $username = $loginname . '-' . substr(froxlor::gensessionid(), 20, 3); } } elseif (strtoupper(settings::get('customer.mysqlprefix')) == 'dbname') { $username = $loginname; } else { $username = $loginname . settings::get('customer.mysqlprefix') . (intval($last_accnumber) + 1); } // use password username ($username == $password) { return false; } // create database $this-&gt;getmanager()-&gt;createdatabase($username); // give permission user every access-host foreach (array_map('trim', explode(',', settings::get('system.mysql_access_host'))) $mysql_access_host) { $this-&gt;getmanager()-&gt;grantprivilegesto($username, $password, $mysql_access_host); (!empty($global_user)) { $this-&gt;getmanager()-&gt;grantcreatetodb($global_user, $username, $mysql_access_host); } } $this-&gt;getmanager()-&gt;flushprivileges(); database::needroot(false); $this-&gt;log-&gt;logaction(froxlorlogger::usr_action, log_info, "created database '" . $username . "'"); return $username; } /** * returns manager-object * control */ public function getmanager() { return $this-&gt;manager; } }</file><file name="lib/Froxlor/Database/Database.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\database; use exception; use froxlor\filedir; use froxlor\froxlor; use froxlor\phphelper; use froxlor\settings; use froxlor\ui\panel\ui; use pdo; use pdoexception; use pdostatement; /** * class database * * wrapper-class php-pdo * * @method static pdostatement prepare($statement, array $driver_options = null) prepares statement execution * returns statement object * @method static pdostatement query ($statement) executes sql statement, returning result set pdostatement * object * @method static string lastinsertid ($name = null) returns id last inserted row sequence value * @method static string quote ($string, $parameter_type = null) quotes string use query. * @method static mixed getattribute(int $attribute) retrieve database connection attribute */ class database { /** * current database link * * @var object */ private static $link = null; /** * indicator whether use root-connection */ private static bool $needroot = false; /** * indicator database-server we're (not really used) */ private static int $dbserver = 0; /** * used database-name */ private static ?string $dbname = null; /** * sql-access data */ private static bool $needsqldata = false; private static $sqldata = null; private static bool $need_dbname = true; /** * wrapper pdostatement::execute, catch pdoexception * display error nicely panel - also fetches * result statement returns resulting array * * @param pdostatement $stmt * @param array|null $params * (optional) * @param bool $showerror * suppress error display (default true) * @param bool $json_response * * @return mixed * @throws exception */ public static function pexecute_first(pdostatement &amp;$stmt, $params = null, bool $showerror = true, bool $json_response = false) { self::pexecute($stmt, $params, $showerror, $json_response); return $stmt-&gt;fetch(pdo::fetch_assoc); } /** * wrapper pdostatement::execute catch pdoexception * display error nicely panel * * @param pdostatement $stmt * @param array|null $params * (optional) * @param bool $showerror * suppress error display (default true) * @param bool $json_response * * @throws exception */ public static function pexecute(pdostatement &amp;$stmt, $params = null, bool $showerror = true, bool $json_response = false) { try { $stmt-&gt;execute($params); } catch (pdoexception $e) { self::showerror($e, $showerror, $json_response, $stmt); } } /** * display nice error occurs log everything * * @param pdoexception $error * @param bool $showerror * set false, error logged, go * @throws exception */ private static function showerror(exception $error, bool $showerror = true, bool $json_response = false, pdostatement $stmt = null) { global $userinfo, $theme, $linker; $sql = []; $sql_root = []; // include userdata.inc.php require froxlor::getinstalldir() . "/lib/userdata.inc.php"; // le format (isset($sql['root_user']) &amp;&amp; isset($sql['root_password']) &amp;&amp; empty($sql_root)) { $sql_root = [ 0 =&gt; [ 'caption' =&gt; 'default', 'host' =&gt; $sql['host'], 'socket' =&gt; ($sql['socket'] ?? null), 'user' =&gt; $sql['root_user'], 'password' =&gt; $sql['root_password'] ] ]; unset($sql['root_user']); unset($sql['root_password']); // write new layout happen self::generatenewuserdata($sql, $sql_root); // re-read file require froxlor::getinstalldir() . "/lib/userdata.inc.php"; } $substitutions = [ $sql['password'] =&gt; 'db_unpriv_pwd', ]; foreach ($sql_root $sql_root_data) { $substitutions[$sql_root_data['password']] = 'db_root_pwd'; } // hide username/password messages $error_message = $error-&gt;getmessage(); $error_trace = $error-&gt;gettraceasstring(); // error-message $error_message = self::substitute($error_message, $substitutions); // error-trace $error_trace = self::substitute($error_trace, $substitutions); ($error-&gt;getcode() == 2003) { $error_message = "unable connect database. either mysql-server running user/password wrong."; $error_trace = ""; } /** * log file, actually ask people error * (no one seems find stuff syslog) */ $sl_dir = filedir::makecorrectdir(froxlor::getinstalldir() . "/logs/"); (!file_exists($sl_dir)) { @mkdir($sl_dir, 0755); } openlog("froxlor", log_pid | log_perror, log_local0); syslog(log_warning, str_replace("\n", " ", $error_message)); syslog(log_warning, str_replace("\n", " ", "--- debug: " . $error_trace)); closelog(); /** * log error reporting */ $errid = self::genuniquetoken(); $err_file = filedir::makecorrectfile($sl_dir . "/" . $errid . "_sql-error.log"); $errlog = @fopen($err_file, 'w'); @fwrite($errlog, "|code " . $error-&gt;getcode() . "\n"); @fwrite($errlog, "|msg " . $error_message . "\n"); @fwrite($errlog, "|file " . $error-&gt;getfile() . "\n"); @fwrite($errlog, "|line " . $error-&gt;getline() . "\n"); @fwrite($errlog, "|trace\n" . $error_trace . "\n"); @fclose($errlog); (empty($sql['debug'])) { $error_trace = ''; } elseif (!is_null($stmt)) { $error_trace .= "\n\n" . $stmt-&gt;querystring; } ($showerror &amp;&amp; $json_response) { $exception_message = $error_message; (isset($sql['debug']) &amp;&amp; $sql['debug'] == true) { $exception_message .= "\n\n" . $error_trace; } throw new exception($exception_message, 500); } ($showerror) { // clean sensitive data unset($sql); unset($sql_root); ((isset($theme) &amp;&amp; $theme != '') &amp;&amp; !isset($_server['shell']) || (isset($_server['shell']) &amp;&amp; $_server['shell'] == '')) { // we're shell, output nice error $err_report_link = ''; (is_array($userinfo) &amp;&amp; (($userinfo['adminsession'] == '1' &amp;&amp; settings::get('system.allow_error_report_admin') == '1') || ($userinfo['adminsession'] == '0' &amp;&amp; settings::get('system.allow_error_report_customer') == '1'))) { $err_report_link = $linker-&gt;getlink([ 'section' =&gt; 'index', 'page' =&gt; 'send_error_report', 'errorid' =&gt; $errid ]); } // show ui::inittwig(true); ui::twig()-&gt;addglobal('install_mode', '1'); ui::view('misc/dberrornice.html.twig', [ 'page_title' =&gt; 'database error', 'message' =&gt; $error_message, 'debug' =&gt; $error_trace, 'report' =&gt; $err_report_link ]); die(); } die("we sorry, mysql - error occurred. administrator may find information syslog"); } } /** * substitutes patterns content. * * @param string $content * @param array $substitutions * @param int $minlength * @return string */ private static function substitute(string $content, array $substitutions, int $minlength = 6): string { $replacements = []; foreach ($substitutions $search =&gt; $replace) { $replacements += self::createshiftedsubstitutions($search, $replace, $minlength); } return str_replace(array_keys($replacements), array_values($replacements), $content); } /** * creates substitutions, shifted length, e.g. * * _createshiftedsubstitutions('abcdefgh', 'value', 4): * array( * 'abcdefgh' =&gt; 'value', * 'abcdefg' =&gt; 'value', * 'abcdef' =&gt; 'value', * 'abcde' =&gt; 'value', * 'abcd' =&gt; 'value', * ) * * @param string $search * @param string $replace * @param int $minlength * @return array */ private static function createshiftedsubstitutions(string $search, string $replace, int $minlength): array { $substitutions = []; $length = strlen($search); ($length &gt; $minlength) { ($shiftedlength = $length; $shiftedlength &gt;= $minlength; $shiftedlength--) { $substitutions[substr($search, 0, $shiftedlength)] = $replace; } } return $substitutions; } /** * generate safe unique token * * @param int $length * @return string * @throws exception */ private static function genuniquetoken(int $length = 16): string { (intval($length) &lt;= 8) { $length = 16; } (function_exists('random_bytes')) { return bin2hex(random_bytes($length)); } (function_exists('mcrypt_create_iv') &amp;&amp; defined('mcrypt_dev_urandom')) { return bin2hex(mcrypt_create_iv($length, mcrypt_dev_urandom)); } (function_exists('openssl_random_pseudo_bytes')) { return bin2hex(openssl_random_pseudo_bytes($length)); } // everything else fails, use unsafe fallback return substr(md5(uniqid(microtime(), 1)), 0, $length); } /** * returns number found rows last select query * * @return int */ public static function num_rows(): int { return database::query("select found_rows()")-&gt;fetchcolumn(); } /** * returns database-name used * * @return string */ public static function getdbname(): ?string { return self::$dbname; } /** * enabled usage root-connection database * note: must called *before* prepare/query/etc. * called 'false'-parameter resume * 'normal' database-connection * * @param bool $needroot * @param int $dbserver optional * @param bool $need_db */ public static function needroot(bool $needroot = false, int $dbserver = 0, bool $need_db = true) { // force re-connecting db corresponding user // set $dbserver (mostly 0 = default) self::setserver($dbserver); self::$needroot = $needroot; self::$need_dbname = $need_db; } /** * set database-server (relevant root-connection) * * @param int $dbserver */ private static function setserver(int $dbserver = 0) { self::$dbserver = $dbserver; self::$link = null; } /** * enable temporary access sql-access data * note: want root-sqldata need * call needroot(true) first. * also, * give data disable * first access data */ public static function needsqldata() { self::$needsqldata = true; self::$sqldata = []; self::$link = null; // need connection // getsqldata() called right // function "real" pdo // function called, getdb() // involved data collected self::getdb(); } /** * function called every static call * connects database necessary * * @return object * @throws exception */ private static function getdb() { (!extension_loaded('pdo') || !in_array("mysql", pdo::getavailabledrivers())) { self::showerror(new exception("the php pdo extension pdo-mysql driver available")); } // connection already? (self::$link) { // return return self::$link; } // include userdata.inc.php require froxlor::getinstalldir() . "/lib/userdata.inc.php"; // le format (isset($sql['root_user']) &amp;&amp; isset($sql['root_password']) &amp;&amp; (!isset($sql_root) || !is_array($sql_root))) { $sql_root = [ 0 =&gt; [ 'caption' =&gt; 'default', 'host' =&gt; $sql['host'], 'socket' =&gt; ($sql['socket'] ?? null), 'user' =&gt; $sql['root_user'], 'password' =&gt; $sql['root_password'] ] ]; unset($sql['root_user']); unset($sql['root_password']); // write new layout happen self::generatenewuserdata($sql, $sql_root); // re-read file require froxlor::getinstalldir() . "/lib/userdata.inc.php"; } // either root unprivileged user (self::$needroot) { $caption = $sql_root[self::$dbserver]['caption']; $user = $sql_root[self::$dbserver]['user']; $password = $sql_root[self::$dbserver]['password']; $host = $sql_root[self::$dbserver]['host']; $socket = $sql_root[self::$dbserver]['socket'] ?? null; $port = $sql_root[self::$dbserver]['port'] ?? '3306'; $sslcafile = $sql_root[self::$dbserver]['ssl']['cafile'] ?? ""; $sslverifyservercertificate = $sql_root[self::$dbserver]['ssl']['verifyservercertificate'] ?? false; } else { $caption = 'localhost'; $user = $sql["user"]; $password = $sql["password"]; $host = $sql["host"]; $socket = $sql['socket'] ?? null; $port = $sql['port'] ?? '3306'; $sslcafile = $sql['ssl']['cafile'] ?? ""; $sslverifyservercertificate = $sql['ssl']['verifyservercertificate'] ?? false; } // save sql-access-data needed (self::$needsqldata) { self::$sqldata = [ 'user' =&gt; $user, 'passwd' =&gt; $password, 'host' =&gt; $host, 'port' =&gt; $port, 'socket' =&gt; $socket, 'db' =&gt; $sql["db"], 'caption' =&gt; $caption, 'ssl_ca_file' =&gt; $sslcafile, 'ssl_verify_server_certificate' =&gt; $sslverifyservercertificate ]; } // build connection string $driver = 'mysql'; $dsn = $driver . ":"; $options = [ 'pdo::mysql_attr_init_command' =&gt; 'set names utf8' ]; $attributes = [ 'attr_errmode' =&gt; 'errmode_exception' ]; $dbconf["dsn"] = ['charset' =&gt; 'utf8']; (self::$need_dbname) { $dbconf["dsn"]['dbname'] = $sql["db"]; } ($socket != null) { $dbconf["dsn"]['unix_socket'] = filedir::makecorrectfile($socket); } else { $dbconf["dsn"]['host'] = $host; $dbconf["dsn"]['port'] = $port; (!empty(self::$sqldata['ssl_ca_file'])) { $options[pdo::mysql_attr_ssl_ca] = self::$sqldata['ssl_ca_file']; $options[pdo::mysql_attr_ssl_verify_server_cert] = (bool)self::$sqldata['ssl_verify_server_certificate']; } } self::$dbname = $sql["db"]; // add options dsn-string foreach ($dbconf["dsn"] $k =&gt; $v) { $dsn .= $k . "=" . $v . ";"; } // clean unset($dbconf); // try connect try { self::$link = new pdo($dsn, $user, $password, $options); } catch (pdoexception $e) { self::showerror($e); } // set attributes foreach ($attributes $k =&gt; $v) { self::$link-&gt;setattribute(constant("pdo::" . $k), constant("pdo::" . $v)); } $version_server = self::$link-&gt;getattribute(pdo::attr_server_version); $sql_mode = 'no_engine_substitution'; (version_compare($version_server, '8.0.11', '&lt;')) { $sql_mode .= ',no_auto_create_user'; } self::$link-&gt;exec('set sql_mode = "' . $sql_mode . '"'); // return pdo instance return self::$link; } /** * returns sql-access data array using indices * 'user', 'passwd' 'host'. * returns false enabled * * @return array|bool */ public static function getsqldata() { $return = false; (self::$sqldata !== null &amp;&amp; is_array(self::$sqldata) &amp;&amp; isset(self::$sqldata['user'])) { $return = self::$sqldata; // automatically disable sql-data self::$sqldata = null; self::$needsqldata = false; } return $return; } /** * return number characters allowed use username * * @return int */ public static function getsqlusernamelength(): int { // mariadb supports 80 characters 64 databases use login-name also // database names, set limit 64 (strpos(strtolower(database::getattribute(\pdo::attr_server_version)), "mariadb") !== false) { $mysql_max = 64; } else { // mysql user-names 32 characters long (16 characters mysql 5.7.8). $mysql_max = 32; (version_compare(database::getattribute(\pdo::attr_server_version), '5.7.8', '&lt;')) { $mysql_max = 16; } } return $mysql_max; } /** * lets us interact pdo-object using static * call like "database::function()" * * @param string $name * @param mixed $args * * @return mixed * @throws exception */ public static function __callstatic(string $name, $args) { $callback = [ self::getdb(), $name ]; $result = null; try { $result = call_user_func_array($callback, $args); } catch (pdoexception $e) { self::showerror($e); } return $result; } /** * write new userdata.inc.php file */ private static function generatenewuserdata(array $sql, array $sql_root) { $content = phphelper::parsearraytophpfile( ['sql' =&gt; $sql, 'sql_root' =&gt; $sql_root], 'automatically generated userdata.inc.php froxlor' ); chmod(froxlor::getinstalldir() . "/lib/userdata.inc.php", 0700); file_put_contents(froxlor::getinstalldir() . "/lib/userdata.inc.php", $content); chmod(froxlor::getinstalldir() . "/lib/userdata.inc.php", 0400); clearstatcache(); (function_exists('opcache_invalidate')) { @opcache_invalidate(froxlor::getinstalldir() . "/lib/userdata.inc.php", true); } } }</file><file name="lib/Froxlor/Database/IntegrityCheck.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\database; use froxlor\froxlorlogger; use froxlor\settings; use pdo; class integritycheck { // store available checks public $available = []; // logger object private $log = null; /** * constructor * parses available checks $this-&gt;available */ public function __construct() { global $userinfo; (!isset($userinfo) || !is_array($userinfo)) { $userinfo = [ 'loginname' =&gt; 'integrity-check' ]; } $this-&gt;log = froxlorlogger::getinstanceof($userinfo); $this-&gt;available = get_class_methods($this); unset($this-&gt;available[array_search('__construct', $this-&gt;available)]); unset($this-&gt;available[array_search('checkall', $this-&gt;available)]); unset($this-&gt;available[array_search('fixall', $this-&gt;available)]); sort($this-&gt;available); } /** * check occurring integrity problems */ public function checkall() { $integrityok = true; foreach ($this-&gt;available $check) { $integrityok = $this-&gt;$check() ? $integrityok : false; } return $integrityok; } /** * fix occurring integrity problems default settings */ public function fixall() { $integrityok = true; foreach ($this-&gt;available $check) { $integrityok = $this-&gt;$check(true) ? $integrityok : false; } return $integrityok; } /** * check whether froxlor database tables utf-8 character-set * * @param bool $fix fix db charset/collation utf8 * * @return bool * @throws \exception */ public function databasecharset(bool $fix = false): bool { // get character-set $cs_stmt = database::prepare('select default_character_set_name information_schema.schemata schema_name = :dbname'); $resp = database::pexecute_first($cs_stmt, [ 'dbname' =&gt; database::getdbname() ]); $charset = $resp['default_character_set_name'] ?? null; (!empty($charset) &amp;&amp; substr(strtolower($charset), 0, 4) != 'utf8') { $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_notice, "database charset seems different utf-8, integrity-check fix that"); ($fix) { // fix database database::query('alter database `' . database::getdbname() . '` character set utf8 collate utf8_general_ci'); // fix tables $handle = database::query('show full tables table_type != "view"'); ($row = $handle-&gt;fetch(pdo::fetch_both)) { $table = $row[0]; database::query('alter table `' . $table . '` convert character set utf8 collate utf8_general_ci;'); } $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_warning, "database charset different utf-8, integrity-check fixed that"); } else { return false; } } ($fix) { return $this-&gt;databasecharset(); } return true; } /** * check integrity domain ip/port - association * * @param bool $fix fix everything found directly * * @return bool * @throws \exception */ public function domainiptable(bool $fix = false): bool { $ips = []; $domains = []; $ipstodomains = []; $admips = []; ($fix) { // prepare insert / delete statement fixes $del_stmt = database::prepare(" delete `" . table_domaintoip . "` `id_domain` = :domainid `id_ipandports` = :ipandportid "); $ins_stmt = database::prepare(" insert `" . table_domaintoip . "` set `id_domain` = :domainid, `id_ipandports` = :ipandportid "); // cache ips admins assigned $adm_stmt = database::prepare("select `adminid`, `ip` `" . table_panel_admins . "` order `adminid` asc"); database::pexecute($adm_stmt); $default_ips = explode(',', settings::get('system.defaultip')); $default_ssl_ips = explode(',', settings::get('system.defaultsslip')); ($row = $adm_stmt-&gt;fetch(pdo::fetch_assoc)) { ($row['ip'] &lt; 0 || is_null($row['ip']) || empty($row['ip'])) { // admin uses default-ip $admips[$row['adminid']] = array_merge($default_ips, $default_ssl_ips); } else { $admips[$row['adminid']] = [ $row['ip'] ]; } } } // cache available ip/port - combinations $result_stmt = database::prepare("select `id`, `ip`, `port` `" . table_panel_ipsandports . "` order `id` asc"); database::pexecute($result_stmt); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $ips[$row['id']] = $row['ip'] . ':' . $row['port']; } // cache configured domains $result_stmt = database::prepare("select `id`, `adminid` `" . table_panel_domains . "` order `id` asc"); database::pexecute($result_stmt); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $domains[$row['id']] = $row['adminid']; } // check every domain ip/port - association valid table_domaintoip $result_stmt = database::prepare("select `id_domain`, `id_ipandports` `" . table_domaintoip . "`"); database::pexecute($result_stmt); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { (!array_key_exists($row['id_ipandports'], $ips)) { ($fix) { database::pexecute($del_stmt, [ 'domainid' =&gt; $row['id_domain'], 'ipandportid' =&gt; $row['id_ipandports'] ]); $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_warning, "found ip/port-id domain &lt;&gt; ip table exist, integrity check fixed this"); } else { $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_notice, "found ip/port-id domain &lt;&gt; ip table exist, integrity check fix this"); return false; } } (!array_key_exists($row['id_domain'], $domains)) { ($fix) { database::pexecute($del_stmt, [ 'domainid' =&gt; $row['id_domain'], 'ipandportid' =&gt; $row['id_ipandports'] ]); $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_warning, "found domain-id domain &lt;&gt; ip table exist, integrity check fixed this"); } else { $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_notice, "found domain-id domain &lt;&gt; ip table exist, integrity check fix this"); return false; } } // save one ip/port combination per domain, know, one domain missing ip $ipstodomains[$row['id_domain']] = $row['id_ipandports']; } // check domains least one ip/port combination foreach ($domains $domainid =&gt; $adminid) { (!array_key_exists($domainid, $ipstodomains)) { ($fix) { foreach ($admips[$adminid] $defaultip) { database::pexecute($ins_stmt, [ 'domainid' =&gt; $domainid, 'ipandportid' =&gt; $defaultip ]); } $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_warning, "found domain-id entry domain &lt;&gt; ip table, integrity check fixed this"); } else { $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_notice, "found domain-id entry domain &lt;&gt; ip table, integrity check fix this"); return false; } } } ($fix) { return $this-&gt;domainiptable(); } return true; } /** * check subdomains ssl-redirect = 0 domain ssl-port * * @param bool $fix fix everything found directly * * @return bool * @throws \exception */ public function subdomainsslredirect(bool $fix = false): bool { $ips = []; $parentdomains = []; $subdomains = []; ($fix) { // prepare update statement fixes $upd_stmt = database::prepare(" update `" . table_panel_domains . "` set `ssl_redirect` = 0 `parentdomainid` = :domainid"); } // cache ssl ip/port - combinations $result_stmt = database::prepare("select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `ssl` = 1 order `id` asc"); database::pexecute($result_stmt); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $ips[$row['id']] = $row['ip'] . ':' . $row['port']; } // cache configured domains $result_stmt = database::prepare("select `id`, `parentdomainid`, `ssl_redirect` `" . table_panel_domains . "` order `id` asc"); $ip_stmt = database::prepare("select `id_domain`, `id_ipandports` `" . table_domaintoip . "` `id_domain` = :domainid"); database::pexecute($result_stmt); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { ($row['parentdomainid'] == 0) { // parentdomains default ssl - ip/port $parentdomains[$row['id']] = false; database::pexecute($ip_stmt, [ 'domainid' =&gt; $row['id'] ]); ($iprow = $ip_stmt-&gt;fetch(pdo::fetch_assoc)) { // parentdomain ip/port assigned know ssl enabled, set parentdomain "true" (array_key_exists($iprow['id_ipandports'], $ips)) { $parentdomains[$row['id']] = true; } } } elseif ($row['ssl_redirect'] == 1) { // subdomains enabled ssl_redirect enabled stored (!isset($subdomains[$row['parentdomainid']])) { $subdomains[$row['parentdomainid']] = []; } $subdomains[$row['parentdomainid']][] = $row['id']; } } // check every parentdomain enabled ssl_redirect ssl enabled foreach ($parentdomains $id =&gt; $sslavailable) { // parentdomain subdomains (!isset($subdomains[$id])) { continue; } // parentdomain ssl enabled, matter status subdomains ($sslavailable) { continue; } // point parentdomains reside ssl_redirect enabled subdomains ($fix) { // make blanket update subdomains parentdomain, matter one wrong, disabled database::pexecute($upd_stmt, [ 'domainid' =&gt; $id ]); $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_warning, "found subdomain ssl_redirect=1 parent-domain ssl=0, integrity check fixed this"); } else { // check, let function fail $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_notice, "found subdomain ssl_redirect=1 parent-domain ssl=0, integrity check fix this"); return false; } } ($fix) { return $this-&gt;subdomainsslredirect(); } return true; } /** * check subdomain letsencrypt = 0 domain ssl-port * * @param bool $fix fix everything found directly * * @return bool * @throws \exception */ public function subdomainletsencrypt(bool $fix = false): bool { $ips = []; $parentdomains = []; $subdomains = []; ($fix) { // prepare update statement fixes $upd_stmt = database::prepare(" update `" . table_panel_domains . "` set `letsencrypt` = 0 `parentdomainid` = :domainid"); } // cache ssl ip/port - combinations $result_stmt = database::prepare("select `id`, `ip`, `port` `" . table_panel_ipsandports . "` `ssl` = 1 order `id` asc"); database::pexecute($result_stmt); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { $ips[$row['id']] = $row['ip'] . ':' . $row['port']; } // cache configured domains $result_stmt = database::prepare("select `id`, `parentdomainid`, `letsencrypt` `" . table_panel_domains . "` order `id` asc"); $ip_stmt = database::prepare("select `id_domain`, `id_ipandports` `" . table_domaintoip . "` `id_domain` = :domainid"); database::pexecute($result_stmt); ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { ($row['parentdomainid'] == 0) { // parentdomains default ssl - ip/port $parentdomains[$row['id']] = false; database::pexecute($ip_stmt, [ 'domainid' =&gt; $row['id'] ]); ($iprow = $ip_stmt-&gt;fetch(pdo::fetch_assoc)) { // parentdomain ip/port assigned know ssl enabled, set parentdomain "true" (array_key_exists($iprow['id_ipandports'], $ips)) { $parentdomains[$row['id']] = true; } } } elseif ($row['letsencrypt'] == 1) { // subdomains enabled letsencrypt enabled stored (!isset($subdomains[$row['parentdomainid']])) { $subdomains[$row['parentdomainid']] = []; } $subdomains[$row['parentdomainid']][] = $row['id']; } } // check every parentdomain enabled letsencrypt ssl enabled foreach ($parentdomains $id =&gt; $sslavailable) { // parentdomain subdomains (!isset($subdomains[$id])) { continue; } // parentdomain ssl enabled, matter status subdomains ($sslavailable) { continue; } // point parentdomains reside letsencrypt enabled subdomains ($fix) { // make blanket update subdomains parentdomain, matter one wrong, disabled database::pexecute($upd_stmt, [ 'domainid' =&gt; $id ]); $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_warning, "found subdomain letsencrypt=1 parent-domain ssl=0, integrity check fixed this"); } else { // check, let function fail $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_notice, "found subdomain letsencrypt=1 parent-domain ssl=0, integrity check fix this"); return false; } } ($fix) { return $this-&gt;subdomainletsencrypt(); } return true; } /** * check whether webserveruser * customers groups fcgid / php-fpm used * * @param bool $fix fix member/groups * * @return bool * @throws \exception */ public function webservergroupmemberforfcgidphpfpm(bool $fix = false): bool { (settings::get('system.mod_fcgid') == 0 &amp;&amp; settings::get('phpfpm.enabled') == 0) { return true; } // get customers webserver-user group $cwg_stmt = database::prepare(" select `id` `" . table_ftp_groups . "` find_in_set(:webserveruser, `members`) "); database::pexecute($cwg_stmt, [ 'webserveruser' =&gt; settings::get('system.httpuser') ]); ($cwg_stmt-&gt;rowcount() &gt; 0) { $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_notice, "customers missing webserver-user group-member, integrity-check fix that"); ($fix) { // prepare update statement $upd_stmt = database::prepare(" update `" . table_ftp_groups . "` set `members` = concat(`members`, :additionaluser) `id` = :id "); $upd_data = [ 'additionaluser' =&gt; "," . settings::get('system.httpuser') ]; ($cwg_row = $cwg_stmt-&gt;fetch()) { $upd_data['id'] = $cwg_row['id']; database::pexecute($upd_stmt, $upd_data); } $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_notice, "customers missing webserver-user group-member, integrity-check fixed that"); } else { return false; } } ($fix) { return $this-&gt;webservergroupmemberforfcgidphpfpm(); } return true; } /** * check whether local froxlor user * customers groups fcgid / php-fpm * fcgid/fpm froxlor vhost used * * @param bool $fix fix member/groups * * @return bool * @throws \exception */ public function froxlorlocalgroupmemberforfcgidphpfpm(bool $fix = false): bool { (settings::get('system.mod_fcgid') == 0 &amp;&amp; settings::get('phpfpm.enabled') == 0) { return true; } (settings::get('system.mod_fcgid') == 1) { (settings::get('system.mod_fcgid_ownvhost') == 0) { return true; } else { $localuser = settings::get('system.mod_fcgid_httpuser'); } } (settings::get('phpfpm.enabled') == 1) { (settings::get('phpfpm.enabled_ownvhost') == 0) { return true; } else { $localuser = settings::get('phpfpm.vhost_httpuser'); } } // get customers webserver-user group $cwg_stmt = database::prepare(" select `id` `" . table_ftp_groups . "` find_in_set(:localuser, `members`) "); database::pexecute($cwg_stmt, [ 'localuser' =&gt; $localuser ]); ($cwg_stmt-&gt;rowcount() &gt; 0) { $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_notice, "customers missing local froxlor-user group-member, integrity-check fix that"); ($fix) { // prepare update statement $upd_stmt = database::prepare(" update `" . table_ftp_groups . "` set `members` = concat(`members`, :additionaluser) `id` = :id "); $upd_data = [ 'additionaluser' =&gt; "," . $localuser ]; ($cwg_row = $cwg_stmt-&gt;fetch()) { $upd_data['id'] = $cwg_row['id']; database::pexecute($upd_stmt, $upd_data); } $this-&gt;log-&gt;logaction(froxlorlogger::adm_action, log_notice, "customers missing local froxlor-user group-member, integrity-check fixed that"); } else { return false; } } ($fix) { return $this-&gt;froxlorlocalgroupmemberforfcgidphpfpm(); } return true; } }</file><file name="lib/Froxlor/Database/index.html" /><file name="lib/Froxlor/Database/Manager/index.html" /><file name="lib/Froxlor/Database/Manager/DbManagerMySQL.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ namespace froxlor\database\manager; use froxlor\database\database; use froxlor\froxlorlogger; use pdo; /** * class dbmanagermysql * * explicit class database-management like creating * removing databases, users permissions mysql */ class dbmanagermysql { /** * froxlorlogger object * * @var object */ private $log = null; /** * main constructor * * @param froxlorlogger|null $log */ public function __construct(&amp;$log = null) { $this-&gt;log = $log; } /** * creates database * * @param string|null $dbname */ public function createdatabase(string $dbname = null) { database::query("create database `" . $dbname . "`"); } /** * grants access privileges database * username sets password user given access_host * * @param string $username * @param string|array $password * @param ?string $access_host * @param bool $p_encrypted * optional, whether password encrypted not, default false * @param bool $update * optional, whether update password (not create user) * @param bool $grant_access_prefix * optional, whether given user access databases starting username, default false * @throws \exception */ public function grantprivilegesto(string $username, $password, string $access_host = null, bool $p_encrypted = false, bool $update = false, bool $grant_access_prefix = false) { // required mysql8 $pwd_plugin = 'caching_sha2_password'; (is_array($password) &amp;&amp; count($password) == 2) { $pwd_plugin = $password['plugin']; $password = $password['password']; } (!$update) { // create user ($p_encrypted) { (version_compare(database::getattribute(\pdo::attr_server_version), '5.7.0', '&lt;') || version_compare(database::getattribute(\pdo::attr_server_version), '10.0.0', '&gt;=')) { $stmt = database::prepare(" create user '" . $username . "'@'" . $access_host . "' identified password :password "); } else { $stmt = database::prepare(" create user '" . $username . "'@'" . $access_host . "' identified " . $pwd_plugin . " :password "); } } else { $stmt = database::prepare(" create user '" . $username . "'@'" . $access_host . "' identified :password "); } database::pexecute($stmt, [ "password" =&gt; $password ]); // grant privileges $grants = "all"; ($grant_access_prefix) { $grants = "select, insert, update, delete, drop, index, alter"; } $stmt = database::prepare(" grant " . $grants . " `" . $username . ($grant_access_prefix ? '%' : '') . "`.* :username@:host "); database::pexecute($stmt, [ "username" =&gt; $username, "host" =&gt; $access_host ]); ($grant_access_prefix) { $this-&gt;grantcreatetocustomerdbs($username, $access_host); } } else { // set password (version_compare(database::getattribute(\pdo::attr_server_version), '5.7.6', '&lt;') || version_compare(database::getattribute(\pdo::attr_server_version), '10.0.0', '&gt;=')) { ($p_encrypted) { $stmt = database::prepare("set password :username@:host = :password"); } else { $stmt = database::prepare("set password :username@:host = password(:password)"); } } else { ($p_encrypted) { $stmt = database::prepare("alter user :username@:host identified " . $pwd_plugin . " :password"); } else { $stmt = database::prepare("alter user :username@:host identified :password"); } } database::pexecute($stmt, [ "username" =&gt; $username, "host" =&gt; $access_host, "password" =&gt; $password ]); } } /** * removes given database dbms also * takes away privileges user db * * @param string $dbname * @param ?string $global_user * @throws \exception */ public function deletedatabase(string $dbname, string $global_user = "") { (version_compare(database::getattribute(pdo::attr_server_version), '5.0.2', '&lt;')) { // failsafe user deleted manually (requires mysql 4.1.2+) $stmt = database::prepare("revoke privileges, grant option `" . $dbname . "`"); database::pexecute($stmt, [], false); } $host_res_stmt = database::prepare(" select `host` `mysql`.`user` `user` = :dbname"); database::pexecute($host_res_stmt, [ 'dbname' =&gt; $dbname ]); // mysql 5.0.2 also revokes privileges. (requires mysql 4.1.2+) (version_compare(database::getattribute(pdo::attr_server_version), '5.7.0', '&lt;')) { $drop_stmt = database::prepare("drop user :dbname@:host"); } else { $drop_stmt = database::prepare("drop user exists :dbname@:host"); } $rev_stmt = database::prepare("revoke privileges `" . $dbname . "`.* :guser@:host;"); ($host = $host_res_stmt-&gt;fetch(pdo::fetch_assoc)) { database::pexecute($drop_stmt, [ 'dbname' =&gt; $dbname, 'host' =&gt; $host['host'] ], false); (!empty($global_user)) { database::pexecute($rev_stmt, [ 'guser' =&gt; $global_user, 'host' =&gt; $host['host'] ], false); } } $drop_stmt = database::prepare("drop database exists `" . $dbname . "`"); database::pexecute($drop_stmt); } /** * removes user dbms revokes privileges * * @param string $username * @param string $host * @throws \exception */ public function deleteuser(string $username, string $host) { ($this-&gt;userexistsonhost($username, $host)) { (version_compare(database::getattribute(pdo::attr_server_version), '5.0.2', '&lt;')) { // revoke privileges (only required mysql 4.1.2 - 5.0.1) $stmt = database::prepare("revoke privileges * . * `" . $username . "`@`" . $host . "`"); database::pexecute($stmt); } // mysql 5.0.2 also revokes privileges. (requires mysql 4.1.2+) (version_compare(database::getattribute(pdo::attr_server_version), '5.7.0', '&lt;')) { $stmt = database::prepare("drop user :username@:host"); } else { $stmt = database::prepare("drop user exists :username@:host"); } database::pexecute($stmt, [ "username" =&gt; $username, "host" =&gt; $host ]); } } /** * removes permissions user * * @param string $username * @param string $host * @throws \exception */ public function disableuser(string $username, string $host) { $stmt = database::prepare('revoke privileges, grant option `' . $username . '`@`' . $host . '`'); database::pexecute($stmt, [], false); } /** * re-grant permissions user * * @param string $username * @param string $host * @param bool $grant_access_prefix * @throws \exception */ public function enableuser(string $username, string $host, bool $grant_access_prefix = false) { // check whether user exists avoid errors ($this-&gt;userexistsonhost($username, $host)) { $grants = "all privileges"; ($grant_access_prefix) { $grants = "select, insert, update, delete, drop, index, alter"; } database::query('grant ' . $grants . ' `' . $username . ($grant_access_prefix ? '%' : '') . '`.* `' . $username . '`@`' . $host . '`'); database::query('grant ' . $grants . ' `' . str_replace('_', '\_', $username) . ($grant_access_prefix ? '%' : '') . '` . * `' . $username . '`@`' . $host . '`'); ($grant_access_prefix) { $this-&gt;grantcreatetocustomerdbs($username, $host); } } } /** * check whether given username exists given host * * @param string $username * @param string $host * @return bool * @throws \exception */ public function userexistsonhost(string $username, string $host): bool { $exist_check_stmt = database::prepare("select exists(select 1 mysql.user user = '" . $username . "' host = '" . $host . "')"); $exist_check = database::pexecute_first($exist_check_stmt); return ($exist_check &amp;&amp; array_pop($exist_check) == '1'); } /** * flushes privileges...pretty obvious eh? */ public function flushprivileges() { database::query("flush privileges"); } /** * return array usernames used dbms * * @param bool $user_only false, selected mysql.user slightly different array generated * * @return array * @throws \exception */ public function getallsqlusers(bool $user_only = true): array { (!$user_only) { $result_stmt = database::prepare('select * mysql.user'); } else { $result_stmt = database::prepare('select `user` mysql.user'); } database::pexecute($result_stmt); $allsqlusers = []; ($row = $result_stmt-&gt;fetch(pdo::fetch_assoc)) { ($user_only == false) { (!isset($allsqlusers[$row['user']]) || !is_array($allsqlusers[$row['user']])) { $allsqlusers[$row['user']] = [ 'password' =&gt; $row['password'] ?? $row['authentication_string'], 'plugin' =&gt; $row['plugin'] ?? 'caching_sha2_password', 'hosts' =&gt; [] ]; } $allsqlusers[$row['user']]['hosts'][] = $row['host']; } else { $allsqlusers[] = $row['user']; } } return $allsqlusers; } /** * grant "create" prefix user existing databases customer * * @param string $username * @param string $access_host * @return void * @throws \exception */ private function grantcreatetocustomerdbs(string $username, string $access_host) { $cus_stmt = database::prepare("select customerid `" . table_panel_customers . "` loginname = :username"); $cust = database::pexecute_first($cus_stmt, ['username' =&gt; $username]); ($cust) { $sel_stmt = database::prepare("select databasename `" . table_panel_databases . "` `customerid` = :cid"); database::pexecute($sel_stmt, ['cid' =&gt; $cust['customerid']]); ($dbdata = $sel_stmt-&gt;fetch(\pdo::fetch_assoc)) { $stmt = database::prepare(" grant `" . $dbdata['databasename'] . "`.* :username@:host "); database::pexecute($stmt, [ "username" =&gt; $username, "host" =&gt; $access_host ]); } } } /** * grant "create" prefix user existing databases customer * * @param string $username * @param string $database * @param string $access_host * @return void * @throws \exception */ public function grantcreatetodb(string $username, string $database, string $access_host) { $stmt = database::prepare(" grant `" . $database . "`.* :username@:host "); database::pexecute($stmt, [ "username" =&gt; $username, "host" =&gt; $access_host ]); } }</file><file name="lib/formfields/formfield.domain_ssleditor.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'domain_ssleditor' =&gt; [ 'title' =&gt; lng('panel.ssleditor'), 'image' =&gt; 'fa-solid fa-lock', 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; 'ssl certificates', 'image' =&gt; 'icons/ssl.png', 'fields' =&gt; [ 'domainname' =&gt; [ 'label' =&gt; lng('domains.domainname'), 'type' =&gt; 'label', 'value' =&gt; $result_domain['domain'] ], 'ssl_cert_file' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_cert_file_content'), 'desc' =&gt; lng('admin.ipsandports.ssl_paste_description'), 'type' =&gt; 'textarea', 'cols' =&gt; 100, 'rows' =&gt; 15, 'value' =&gt; $result['ssl_cert_file'], 'placeholder' =&gt; lng('domain.ssl_certificate_placeholder'), 'mandatory' =&gt; true ], 'ssl_key_file' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_key_file_content'), 'desc' =&gt; lng('admin.ipsandports.ssl_paste_description'), 'type' =&gt; 'textarea', 'cols' =&gt; 100, 'rows' =&gt; 15, 'value' =&gt; $result['ssl_key_file'], 'placeholder' =&gt; lng('domain.ssl_key_placeholder'), 'mandatory' =&gt; true ], 'ssl_cert_chainfile' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_cert_chainfile_content'), 'desc' =&gt; lng('admin.ipsandports.ssl_paste_description') . lng('admin.ipsandports.ssl_cert_chainfile_content_desc'), 'type' =&gt; 'textarea', 'cols' =&gt; 100, 'rows' =&gt; 15, 'value' =&gt; $result['ssl_cert_chainfile'] ], 'ssl_ca_file' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_ca_file_content'), 'desc' =&gt; lng('admin.ipsandports.ssl_paste_description') . lng('admin.ipsandports.ssl_ca_file_content_desc'), 'type' =&gt; 'textarea', 'cols' =&gt; 100, 'rows' =&gt; 15, 'value' =&gt; $result['ssl_ca_file'] ], 'do_insert' =&gt; [ 'type' =&gt; 'hidden', 'value' =&gt; '1', 'visible' =&gt; empty($result['ssl_cert_file']) ] ] ] ] ] ];</file><file name="lib/formfields/formfield.api_key.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'apikey' =&gt; [ 'title' =&gt; lng('menue.main.apikeys'), 'sections' =&gt; [ 'section_a' =&gt; [ 'fields' =&gt; [ 'loginname' =&gt; [ 'label' =&gt; lng('login.username'), 'type' =&gt; 'label', 'value' =&gt; $result['loginname'] ?? $result['adminname'] ], 'apikey' =&gt; [ 'label' =&gt; 'api key', 'type' =&gt; 'text', 'readonly' =&gt; true, 'value' =&gt; $result['apikey'] ], 'secret' =&gt; [ 'label' =&gt; 'secret', 'type' =&gt; 'text', 'readonly' =&gt; true, 'value' =&gt; $result['secret'] ], 'allowed_from' =&gt; [ 'label' =&gt; [ 'title' =&gt; lng('apikeys.allowed_from'), 'description' =&gt; lng('apikeys.allowed_from_help') ], 'type' =&gt; 'text', 'value' =&gt; $result['allowed_from'], ], 'valid_until' =&gt; [ 'label' =&gt; [ 'title' =&gt; lng('apikeys.valid_until'), 'description' =&gt; lng('apikeys.valid_until_help') ], 'type' =&gt; 'datetime-local', 'value' =&gt; $result['valid_until'] &lt; 0 ? "" : date('y-m-d\th:i', $result['valid_until']) ] ] ] ] ] ];</file><file name="lib/formfields/formfield.dns_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'dns_add' =&gt; [ 'title' =&gt; 'dns editor', 'image' =&gt; 'fa-solid fa-globe', 'sections' =&gt; [ 'section_a' =&gt; [ 'fields' =&gt; [ 'dns_record' =&gt; [ 'label' =&gt; 'record', 'type' =&gt; 'text', 'value' =&gt; $record, 'mandatory' =&gt; true ], 'dns_type' =&gt; [ 'label' =&gt; 'type', 'type' =&gt; 'select', 'select_var' =&gt; [ 'a' =&gt; 'a', 'aaaa' =&gt; 'aaaa', 'caa' =&gt; 'caa', 'cname' =&gt; 'cname', 'dname' =&gt; 'dname', 'loc' =&gt; 'loc', 'mx' =&gt; 'mx', 'ns' =&gt; 'ns', 'rp' =&gt; 'rp', 'srv' =&gt; 'srv', 'sshfp' =&gt; 'sshfp', 'tlsa' =&gt; 'tlsa', 'txt' =&gt; 'txt' ], 'selected' =&gt; $type ], 'dns_mxp' =&gt; [ 'label' =&gt; 'priority', 'type' =&gt; 'number', 'value' =&gt; $prio ], 'dns_content' =&gt; [ 'label' =&gt; 'content', 'type' =&gt; 'text', 'value' =&gt; $content, 'note' =&gt; lng('dnseditor.notes.a') ], 'dns_ttl' =&gt; [ 'label' =&gt; 'ttl', 'type' =&gt; 'number', 'min' =&gt; 30, 'value' =&gt; $ttl ] ] ] ] ] ];</file><file name="lib/formfields/index.html" /><file name="lib/formfields/customer/index.html" /><file name="lib/formfields/customer/extras/formfield.export.php">&lt;?php /** * file part froxlor project. * copyright (c) 2016 froxlor team (see authors). * * full copyright license information, please view copying * file distributed source code. also view * copying file online https://files.froxlor.org/misc/copying.txt * * @copyright (c) authors * @author froxlor team &lt;team@froxlor.org&gt; (2010-) * @license gplv2 https://files.froxlor.org/misc/copying.txt * @package formfields * */ use froxlor\settings; return [ 'export' =&gt; [ 'title' =&gt; lng('extras.export'), 'image' =&gt; 'fa-solid fa-server', 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('extras.export'), 'fields' =&gt; [ 'path' =&gt; [ 'label' =&gt; lng('panel.exportpath.title'), 'desc' =&gt; lng('panel.exportpath.description') . '&lt;br&gt;' . (settings::get('panel.pathedit') != 'dropdown' ? lng('panel.pathdescription') : null), 'type' =&gt; $pathselect['type'], 'select_var' =&gt; $pathselect['select_var'] ?? '', 'selected' =&gt; $pathselect['value'], 'value' =&gt; $pathselect['value'], 'note' =&gt; $pathselect['note'] ?? '', ], 'pgp_public_key' =&gt; [ 'label' =&gt; lng('panel.export_pgp_public_key.title'), 'desc' =&gt; lng('panel.export_pgp_public_key.description'), 'type' =&gt; 'textarea', ], 'path_protection_info' =&gt; [ 'label' =&gt; lng('extras.path_protection_label'), 'type' =&gt; 'infotext', 'value' =&gt; lng('extras.path_protection_info'), 'classes' =&gt; 'fw-bold text-danger' ], 'dump_web' =&gt; [ 'label' =&gt; lng('extras.dump_web'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'dump_mail' =&gt; [ 'label' =&gt; lng('extras.dump_mail'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'dump_dbs' =&gt; [ 'label' =&gt; lng('extras.dump_dbs'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ] ] ] ] ] ];</file><file name="lib/formfields/customer/extras/formfield.htpasswd_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; use froxlor\system\crypt; return [ 'htpasswd_edit' =&gt; [ 'title' =&gt; lng('extras.directoryprotection_edit'), 'image' =&gt; 'fa-solid fa-lock', 'self_overview' =&gt; ['section' =&gt; 'extras', 'page' =&gt; 'htpasswds'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('extras.directoryprotection_edit'), 'image' =&gt; 'icons/htpasswd_edit.png', 'fields' =&gt; [ 'path' =&gt; [ 'label' =&gt; lng('panel.path'), 'type' =&gt; 'label', 'value' =&gt; $result['path'] ], 'username' =&gt; [ 'label' =&gt; lng('login.username'), 'type' =&gt; 'label', 'value' =&gt; $result['username'] ], 'directory_password' =&gt; [ 'label' =&gt; lng('login.password'), 'type' =&gt; 'password', 'autocomplete' =&gt; 'off', 'next_to' =&gt; [ 'directory_password_suggestion' =&gt; [ 'next_to_prefix' =&gt; lng('customer.generated_pwd') . ':', 'type' =&gt; 'text', 'visible' =&gt; (settings::get('panel.password_regex') == ''), 'value' =&gt; crypt::generatepassword(), 'readonly' =&gt; true ] ] ], 'directory_authname' =&gt; [ 'label' =&gt; lng('extras.htpasswdauthname'), 'type' =&gt; 'text', 'value' =&gt; $result['authname'], 'mandatory' =&gt; true ] ] ] ] ] ];</file><file name="lib/formfields/customer/extras/formfield.htaccess_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'htaccess_edit' =&gt; [ 'title' =&gt; lng('extras.pathoptions_edit'), 'image' =&gt; 'fa-solid fa-folder', 'self_overview' =&gt; ['section' =&gt; 'extras', 'page' =&gt; 'htaccess'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('extras.pathoptions_edit'), 'image' =&gt; 'icons/htpasswd_edit.png', 'fields' =&gt; [ 'path' =&gt; [ 'label' =&gt; lng('panel.path'), 'type' =&gt; 'label', 'value' =&gt; $result['path'] ], 'options_indexes' =&gt; [ 'label' =&gt; lng('extras.directory_browsing'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['options_indexes'] ], 'error404path' =&gt; [ 'label' =&gt; lng('extras.errordocument404path'), 'desc' =&gt; lng('panel.descriptionerrordocument'), 'type' =&gt; 'text', 'value' =&gt; $result['error404path'] ], 'error403path' =&gt; [ 'visible' =&gt; (settings::get('system.webserver') == 'apache2'), 'label' =&gt; lng('extras.errordocument403path'), 'desc' =&gt; lng('panel.descriptionerrordocument'), 'type' =&gt; 'text', 'value' =&gt; $result['error403path'] ], 'error500path' =&gt; [ 'visible' =&gt; (settings::get('system.webserver') == 'apache2'), 'label' =&gt; lng('extras.errordocument500path'), 'desc' =&gt; lng('panel.descriptionerrordocument'), 'type' =&gt; 'text', 'value' =&gt; $result['error500path'] ], 'options_cgi' =&gt; [ 'visible' =&gt; ($cperlenabled == 1), 'label' =&gt; lng('extras.execute_perl'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['options_cgi'] ] ] ] ] ] ];</file><file name="lib/formfields/customer/extras/formfield.htaccess_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'htaccess_add' =&gt; [ 'title' =&gt; lng('extras.pathoptions_add'), 'image' =&gt; 'fa-solid fa-folder', 'self_overview' =&gt; ['section' =&gt; 'extras', 'page' =&gt; 'htaccess'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('extras.pathoptions_add'), 'image' =&gt; 'icons/htpasswd_add.png', 'fields' =&gt; [ 'path' =&gt; [ 'label' =&gt; lng('panel.path'), 'desc' =&gt; (settings::get('panel.pathedit') != 'dropdown' ? lng('panel.pathdescription') : null), 'type' =&gt; $pathselect['type'], 'select_var' =&gt; $pathselect['select_var'] ?? '', 'selected' =&gt; $pathselect['value'], 'value' =&gt; $pathselect['value'], 'note' =&gt; $pathselect['note'] ?? '', 'mandatory' =&gt; true ], 'options_indexes' =&gt; [ 'label' =&gt; lng('extras.directory_browsing'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'error404path' =&gt; [ 'label' =&gt; lng('extras.errordocument404path'), 'desc' =&gt; lng('panel.descriptionerrordocument'), 'type' =&gt; 'text' ], 'error403path' =&gt; [ 'visible' =&gt; (settings::get('system.webserver') == 'apache2'), 'label' =&gt; lng('extras.errordocument403path'), 'desc' =&gt; lng('panel.descriptionerrordocument'), 'type' =&gt; 'text' ], 'error500path' =&gt; [ 'visible' =&gt; (settings::get('system.webserver') == 'apache2'), 'label' =&gt; lng('extras.errordocument500path'), 'desc' =&gt; lng('panel.descriptionerrordocument'), 'type' =&gt; 'text' ], 'options_cgi' =&gt; [ 'visible' =&gt; ($cperlenabled == 1), 'label' =&gt; lng('extras.execute_perl'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ] ] ] ] ] ];</file><file name="lib/formfields/customer/extras/formfield.htpasswd_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; use froxlor\system\crypt; return [ 'htpasswd_add' =&gt; [ 'title' =&gt; lng('extras.directoryprotection_add'), 'image' =&gt; 'fa-solid fa-lock', 'self_overview' =&gt; ['section' =&gt; 'extras', 'page' =&gt; 'htpasswds'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('extras.directoryprotection_add'), 'image' =&gt; 'icons/htpasswd_add.png', 'fields' =&gt; [ 'path' =&gt; [ 'label' =&gt; lng('panel.path'), 'desc' =&gt; (settings::get('panel.pathedit') != 'dropdown' ? lng('panel.pathdescription') : null), 'type' =&gt; $pathselect['type'], 'select_var' =&gt; $pathselect['select_var'] ?? '', 'selected' =&gt; $pathselect['value'], 'value' =&gt; $pathselect['value'], 'note' =&gt; $pathselect['note'] ?? '', 'mandatory' =&gt; true ], 'username' =&gt; [ 'label' =&gt; lng('login.username'), 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'directory_password' =&gt; [ 'label' =&gt; lng('login.password'), 'type' =&gt; 'password', 'autocomplete' =&gt; 'off', 'mandatory' =&gt; true, 'next_to' =&gt; [ 'directory_password_suggestion' =&gt; [ 'next_to_prefix' =&gt; lng('customer.generated_pwd') . ':', 'type' =&gt; 'text', 'visible' =&gt; (settings::get('panel.password_regex') == ''), 'value' =&gt; crypt::generatepassword(), 'readonly' =&gt; true ] ] ], 'directory_authname' =&gt; [ 'label' =&gt; lng('extras.htpasswdauthname'), 'type' =&gt; 'text', 'mandatory' =&gt; true ] ] ] ] ] ];</file><file name="lib/formfields/customer/extras/index.html" /><file name="lib/formfields/customer/domains/formfield.domains_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'domain_add' =&gt; [ 'title' =&gt; lng('domains.subdomain_add'), 'image' =&gt; 'fa-solid fa-plus', 'self_overview' =&gt; ['section' =&gt; 'domains', 'page' =&gt; 'domains'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('domains.subdomain_add'), 'image' =&gt; 'icons/domain_add.png', 'fields' =&gt; [ 'subdomain' =&gt; [ 'label' =&gt; lng('domains.domainname'), 'type' =&gt; 'text', 'next_to' =&gt; [ 'domain' =&gt; [ 'next_to_prefix' =&gt; '.', 'type' =&gt; 'select', 'select_var' =&gt; $domains ] ] ], 'alias' =&gt; [ 'label' =&gt; lng('domains.aliasdomain'), 'type' =&gt; 'select', 'select_var' =&gt; $aliasdomains ], 'path' =&gt; [ 'label' =&gt; lng('panel.path'), 'desc' =&gt; (settings::get('panel.pathedit') != 'dropdown' ? lng('panel.pathdescriptionsubdomain').(settings::get('system.documentroot_use_default_value') == 1 ? lng('panel.pathdescriptionex') : '') : null), 'type' =&gt; $pathselect['type'], 'select_var' =&gt; $pathselect['select_var'] ?? '', 'selected' =&gt; $pathselect['value'], 'value' =&gt; $pathselect['value'], 'note' =&gt; $pathselect['note'] ?? '', ], 'url' =&gt; [ 'visible' =&gt; settings::get('panel.pathedit') == 'dropdown', 'label' =&gt; lng('panel.urloverridespath'), 'type' =&gt; 'text' ], 'redirectcode' =&gt; [ 'visible' =&gt; settings::get('customredirect.enabled') == '1', 'label' =&gt; lng('domains.redirectifpathisurl'), 'desc' =&gt; lng('domains.redirectifpathisurlinfo'), 'type' =&gt; 'select', 'select_var' =&gt; isset($redirectcode) ? $redirectcode : null ], 'selectserveralias' =&gt; [ 'label' =&gt; lng('admin.selectserveralias'), 'desc' =&gt; lng('admin.selectserveralias_desc'), 'type' =&gt; 'label', 'value' =&gt; lng('customer.selectserveralias_addinfo') ], 'openbasedir_path' =&gt; [ 'label' =&gt; lng('domain.openbasedirpath'), 'type' =&gt; 'select', 'select_var' =&gt; $openbasedir ], 'phpsettingid' =&gt; [ 'visible' =&gt; ((int)settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1) &amp;&amp; count($phpconfigs) &gt; 0 &amp;&amp; $userinfo['phpenabled'] == '1', 'label' =&gt; lng('admin.phpsettings.title'), 'type' =&gt; 'select', 'select_var' =&gt; $phpconfigs, 'selected' =&gt; (int)settings::get('phpfpm.enabled') == 1 ? settings::get('phpfpm.defaultini') : settings::get('system.mod_fcgid_defaultini') ], 'speciallogfile' =&gt; [ 'label' =&gt; lng('admin.speciallogfile.title'), 'desc' =&gt; lng('admin.speciallogfile.description'), 'type' =&gt; 'select', 'select_var' =&gt; [ 0 =&gt; lng('panel.no'), 1 =&gt; lng('panel.yes'), 2 =&gt; lng('domain.inherited') ], 'selected' =&gt; 2 ], ] ], 'section_bssl' =&gt; [ 'title' =&gt; lng('admin.webserversettings_ssl'), 'image' =&gt; 'icons/domain_add.png', 'visible' =&gt; settings::get('system.use_ssl') == '1' &amp;&amp; $ssl_ipsandports, 'fields' =&gt; [ 'sslenabled' =&gt; [ 'label' =&gt; lng('admin.domain_sslenabled'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'ssl_redirect' =&gt; [ 'label' =&gt; lng('domains.ssl_redirect.title'), 'desc' =&gt; lng('domains.ssl_redirect.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'letsencrypt' =&gt; [ 'visible' =&gt; settings::get('system.leenabled') == '1', 'label' =&gt; lng('customer.letsencrypt.title'), 'desc' =&gt; lng('customer.letsencrypt.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'http2' =&gt; [ 'visible' =&gt; $ssl_ipsandports &amp;&amp; settings::get('system.webserver') != 'lighttpd' &amp;&amp; settings::get('system.http2_support') == '1', 'label' =&gt; lng('admin.domain_http2.title'), 'desc' =&gt; lng('admin.domain_http2.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'hsts_maxage' =&gt; [ 'label' =&gt; lng('admin.domain_hsts_maxage.title'), 'desc' =&gt; lng('admin.domain_hsts_maxage.description'), 'type' =&gt; 'number', 'min' =&gt; 0, 'max' =&gt; 94608000, // 3-years 'value' =&gt; 0 ], 'hsts_sub' =&gt; [ 'label' =&gt; lng('admin.domain_hsts_incsub.title'), 'desc' =&gt; lng('admin.domain_hsts_incsub.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'hsts_preload' =&gt; [ 'label' =&gt; lng('admin.domain_hsts_preload.title'), 'desc' =&gt; lng('admin.domain_hsts_preload.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ] ] ] ] ] ];</file><file name="lib/formfields/customer/domains/formfield.domains_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\domain\domain; use froxlor\settings; return [ 'domain_edit' =&gt; [ 'title' =&gt; lng('domains.subdomain_edit'), 'image' =&gt; 'fa-solid fa-pen', 'self_overview' =&gt; ['section' =&gt; 'domains', 'page' =&gt; 'domains'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('domains.subdomain_edit'), 'image' =&gt; 'icons/domain_edit.png', 'fields' =&gt; [ 'domain' =&gt; [ 'label' =&gt; lng('domains.domainname'), 'type' =&gt; 'label', 'value' =&gt; $result['domain'] ], 'dns' =&gt; [ 'label' =&gt; lng('dns.destinationip'), 'type' =&gt; 'itemlist', 'values' =&gt; $domainips ], 'alias' =&gt; [ 'visible' =&gt; $alias_check == '0' &amp;&amp; (int)$result['email_only'] == 0, 'label' =&gt; lng('domains.aliasdomain'), 'type' =&gt; 'select', 'select_var' =&gt; $domains, 'selected' =&gt; $result['aliasdomain'] ], 'path' =&gt; [ 'visible' =&gt; (int)$result['email_only'] == 0, 'label' =&gt; lng('panel.path'), 'desc' =&gt; (settings::get('panel.pathedit') != 'dropdown' ? lng('panel.pathdescriptionsubdomain').(settings::get('system.documentroot_use_default_value') == 1 ? lng('panel.pathdescriptionex') : '') : null), 'type' =&gt; $pathselect['type'], 'select_var' =&gt; $pathselect['select_var'] ?? '', 'selected' =&gt; $pathselect['value'], 'value' =&gt; $pathselect['value'], 'note' =&gt; $pathselect['note'] ?? '', ], 'url' =&gt; [ 'visible' =&gt; settings::get('panel.pathedit') == 'dropdown' &amp;&amp; (int)$result['email_only'] == 0, 'label' =&gt; lng('panel.urloverridespath'), 'type' =&gt; 'text', 'value' =&gt; $urlvalue ], 'redirectcode' =&gt; [ 'visible' =&gt; settings::get('customredirect.enabled') == '1' &amp;&amp; (int)$result['email_only'] == 0, 'label' =&gt; lng('domains.redirectifpathisurl'), 'desc' =&gt; lng('domains.redirectifpathisurlinfo'), 'type' =&gt; 'select', 'select_var' =&gt; $redirectcode, 'selected' =&gt; $def_code ], 'selectserveralias' =&gt; [ 'visible' =&gt; (($result['parentdomainid'] == '0' &amp;&amp; $userinfo['subdomains'] != '0') || $result['parentdomainid'] != '0') &amp;&amp; (int)$result['email_only'] == 0, 'label' =&gt; lng('admin.selectserveralias'), 'desc' =&gt; lng('admin.selectserveralias_desc'), 'type' =&gt; 'select', 'select_var' =&gt; $serveraliasoptions, 'selected' =&gt; $serveraliasoptions_selected ], 'isemaildomain' =&gt; [ 'visible' =&gt; (($result['subcanemaildomain'] == '1' || $result['subcanemaildomain'] == '2') &amp;&amp; $result['parentdomainid'] != '0') &amp;&amp; (int)$result['email_only'] == 0, 'label' =&gt; 'emaildomain', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['isemaildomain'] ], 'openbasedir_path' =&gt; [ 'visible' =&gt; $result['openbasedir'] == '1' &amp;&amp; (int)$result['email_only'] == 0, 'label' =&gt; lng('domain.openbasedirpath'), 'type' =&gt; 'select', 'select_var' =&gt; $openbasedir, 'selected' =&gt; $result['openbasedir_path'] ], 'phpsettingid' =&gt; [ 'visible' =&gt; ((int)settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1) &amp;&amp; count($phpconfigs) &gt; 0 &amp;&amp; $userinfo['phpenabled'] == '1' &amp;&amp; $result['phpenabled'] == '1' &amp;&amp; (int)$result['email_only'] == 0, 'label' =&gt; lng('admin.phpsettings.title'), 'type' =&gt; 'select', 'select_var' =&gt; $phpconfigs, 'selected' =&gt; $result['phpsettingid'] ], 'speciallogfile' =&gt; [ 'visible' =&gt; (int)$result['email_only'] == 0, 'label' =&gt; lng('admin.speciallogfile.title'), 'desc' =&gt; lng('admin.speciallogfile.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['speciallogfile'] ], 'speciallogverified' =&gt; [ 'type' =&gt; 'hidden', 'value' =&gt; '0' ], 'spf_entry' =&gt; [ 'visible' =&gt; (settings::get('system.bind_enable') == '0' &amp;&amp; settings::get('spf.use_spf') == '1' &amp;&amp; $result['isemaildomain'] == '1'), 'label' =&gt; lng('antispam.required_spf_dns'), 'type' =&gt; 'longtext', 'value' =&gt; (string)(new \froxlor\dns\dnsentry('@', 'txt', \froxlor\dns\dns::enclosetxtcontent(settings::get('spf.spf_entry')))) ], 'dmarc_entry' =&gt; [ 'visible' =&gt; (settings::get('system.bind_enable') == '0' &amp;&amp; settings::get('dmarc.use_dmarc') == '1' &amp;&amp; $result['isemaildomain'] == '1'), 'label' =&gt; lng('antispam.required_dmarc_dns'), 'type' =&gt; 'longtext', 'value' =&gt; (string)(new \froxlor\dns\dnsentry('_dmarc', 'txt', \froxlor\dns\dns::enclosetxtcontent(settings::get('dmarc.dmarc_entry')))) ], 'dkim_entry' =&gt; [ 'visible' =&gt; (settings::get('system.bind_enable') == '0' &amp;&amp; settings::get('antispam.activated') == '1' &amp;&amp; $result['dkim'] == '1' &amp;&amp; $result['dkim_pubkey'] != ''), 'label' =&gt; lng('antispam.required_dkim_dns'), 'type' =&gt; 'longtext', 'value' =&gt; (string)(new \froxlor\dns\dnsentry('dkim' . $result['dkim_id'] . '._domainkey', 'txt', '"v=dkim1; k=rsa; p='.trim($result['dkim_pubkey']).'"')) ], ] ], 'section_bssl' =&gt; [ 'title' =&gt; lng('admin.webserversettings_ssl'), 'image' =&gt; 'icons/domain_edit.png', 'visible' =&gt; settings::get('system.use_ssl') == '1' &amp;&amp; $ssl_ipsandports &amp;&amp; domain::domainhassslipport($result['id']) &amp;&amp; (int)$result['email_only'] == 0, 'fields' =&gt; [ 'sslenabled' =&gt; [ 'label' =&gt; lng('admin.domain_sslenabled'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['ssl_enabled'] ], 'ssl_redirect' =&gt; [ 'label' =&gt; lng('domains.ssl_redirect.title'), 'desc' =&gt; lng('domains.ssl_redirect.description') . ($result['temporary_ssl_redirect'] &gt; 1 ? lng('domains.ssl_redirect_temporarilydisabled') : ''), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['ssl_redirect'] ], 'letsencrypt' =&gt; [ 'visible' =&gt; settings::get('system.leenabled') == '1', 'label' =&gt; lng('customer.letsencrypt.title'), 'desc' =&gt; lng('customer.letsencrypt.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['letsencrypt'] ], 'http2' =&gt; [ 'visible' =&gt; $ssl_ipsandports &amp;&amp; settings::get('system.webserver') != 'lighttpd' &amp;&amp; settings::get('system.http2_support') == '1', 'label' =&gt; lng('admin.domain_http2.title'), 'desc' =&gt; lng('admin.domain_http2.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['http2'] ], 'hsts_maxage' =&gt; [ 'label' =&gt; lng('admin.domain_hsts_maxage.title'), 'desc' =&gt; lng('admin.domain_hsts_maxage.description'), 'type' =&gt; 'number', 'min' =&gt; 0, 'max' =&gt; 94608000, // 3-years 'value' =&gt; $result['hsts'] ], 'hsts_sub' =&gt; [ 'label' =&gt; lng('admin.domain_hsts_incsub.title'), 'desc' =&gt; lng('admin.domain_hsts_incsub.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['hsts_sub'] ], 'hsts_preload' =&gt; [ 'label' =&gt; lng('admin.domain_hsts_preload.title'), 'desc' =&gt; lng('admin.domain_hsts_preload.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['hsts_preload'] ] ] ] ], 'buttons' =&gt; ((int)$result['email_only'] == 1) ? [] : null ] ];</file><file name="lib/formfields/customer/domains/index.html" /><file name="lib/formfields/customer/mysql/formfield.mysql_add.php">&lt;?php use froxlor\settings; use froxlor\system\crypt; /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * full copyright license information, please view copying * file distributed source code. also view * copying file online https://files.froxlor.org/misc/copying.txt * * @copyright (c) authors * @author froxlor team &lt;team@froxlor.org&gt; (2010-) * @license gplv2 https://files.froxlor.org/misc/copying.txt * @package formfields */ return [ 'mysql_add' =&gt; [ 'title' =&gt; lng('mysql.database_create'), 'image' =&gt; 'icons/mysql_add.png', 'self_overview' =&gt; ['section' =&gt; 'mysql', 'page' =&gt; 'mysqls'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('mysql.database_create'), 'image' =&gt; 'icons/mysql_add.png', 'fields' =&gt; [ 'custom_suffix' =&gt; [ 'visible' =&gt; strtoupper(settings::get('customer.mysqlprefix')) == 'dbname', 'label' =&gt; lng('mysql.databasename'), 'type' =&gt; 'text' ], 'description' =&gt; [ 'label' =&gt; lng('mysql.databasedescription'), 'type' =&gt; 'text' ], 'mysql_server' =&gt; [ 'visible' =&gt; count($mysql_servers) &gt; 1, 'label' =&gt; lng('mysql.mysql_server'), 'type' =&gt; 'select', 'select_var' =&gt; $mysql_servers ], 'mysql_password' =&gt; [ 'label' =&gt; lng('login.password'), 'type' =&gt; 'password', 'autocomplete' =&gt; 'off', 'mandatory' =&gt; true, 'next_to' =&gt; [ 'mysql_password_suggestion' =&gt; [ 'next_to_prefix' =&gt; lng('customer.generated_pwd') . ':', 'type' =&gt; 'text', 'visible' =&gt; (settings::get('panel.password_regex') == ''), 'value' =&gt; crypt::generatepassword(), 'readonly' =&gt; true ] ] ], 'sendinfomail' =&gt; [ 'label' =&gt; lng('customer.sendinfomail'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ] ] ] ] ] ];</file><file name="lib/formfields/customer/mysql/formfield.mysql_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * full copyright license information, please view copying * file distributed source code. also view * copying file online https://files.froxlor.org/misc/copying.txt * * @copyright (c) authors * @author froxlor team &lt;team@froxlor.org&gt; (2010-) * @license gplv2 https://files.froxlor.org/misc/copying.txt * @package formfields */ use froxlor\settings; use froxlor\system\crypt; return [ 'mysql_edit' =&gt; [ 'title' =&gt; lng('mysql.database_edit'), 'image' =&gt; 'icons/mysql_edit.png', 'self_overview' =&gt; ['section' =&gt; 'mysql', 'page' =&gt; 'mysqls'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('mysql.database_edit'), 'image' =&gt; 'icons/mysql_edit.png', 'fields' =&gt; [ 'databasename' =&gt; [ 'label' =&gt; lng('mysql.databasename'), 'type' =&gt; 'label', 'value' =&gt; $result['databasename'] ], 'mysql_server' =&gt; [ 'visible' =&gt; count($mysql_servers) &gt; 1, 'type' =&gt; 'hidden', 'value' =&gt; $result['dbserver'] ?? 0, ], 'mysql_server_info' =&gt; [ 'visible' =&gt; count($mysql_servers) &gt; 1, 'label' =&gt; lng('mysql.mysql_server'), 'type' =&gt; 'label', 'disabled' =&gt; true, 'value' =&gt; $mysql_servers[$result['dbserver']] ?? 'unknown db server', ], 'description' =&gt; [ 'label' =&gt; lng('mysql.databasedescription'), 'type' =&gt; 'text', 'value' =&gt; $result['description'] ], 'mysql_password' =&gt; [ 'label' =&gt; lng('changepassword.new_password_ifnotempty'), 'type' =&gt; 'password', 'autocomplete' =&gt; 'off', 'next_to' =&gt; [ 'mysql_password_suggestion' =&gt; [ 'next_to_prefix' =&gt; lng('customer.generated_pwd') . ':', 'type' =&gt; 'text', 'visible' =&gt; (settings::get('panel.password_regex') == ''), 'value' =&gt; crypt::generatepassword(), 'readonly' =&gt; true ] ] ] ] ] ] ] ];</file><file name="lib/formfields/customer/mysql/formfield.mysql_global_user.php">&lt;?php use froxlor\settings; use froxlor\system\crypt; /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * full copyright license information, please view copying * file distributed source code. also view * copying file online https://files.froxlor.org/misc/copying.txt * * @copyright (c) authors * @author froxlor team &lt;team@froxlor.org&gt; (2010-) * @license gplv2 https://files.froxlor.org/misc/copying.txt * @package formfields */ return [ 'mysql_global_user' =&gt; [ 'title' =&gt; lng('mysql.edit_global_user'), 'self_overview' =&gt; ['section' =&gt; 'mysql', 'page' =&gt; 'mysqls'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('mysql.edit_global_user'), 'fields' =&gt; [ 'username' =&gt; [ 'label' =&gt; lng('login.username'), 'value' =&gt; $userinfo['loginname'], 'type' =&gt; 'text', 'readonly' =&gt; true ], 'mysql_password' =&gt; [ 'label' =&gt; lng('login.password'), 'type' =&gt; 'password', 'autocomplete' =&gt; 'off', 'mandatory' =&gt; true, 'next_to' =&gt; [ 'mysql_password_suggestion' =&gt; [ 'next_to_prefix' =&gt; lng('customer.generated_pwd') . ':', 'type' =&gt; 'text', 'visible' =&gt; (settings::get('panel.password_regex') == ''), 'value' =&gt; crypt::generatepassword(), 'readonly' =&gt; true ] ] ] ] ] ] ] ];</file><file name="lib/formfields/customer/mysql/index.html" /><file name="lib/formfields/customer/ftp/formfield.ftp_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * full copyright license information, please view copying * file distributed source code. also view * copying file online https://files.froxlor.org/misc/copying.txt * * @copyright (c) authors * @author froxlor team &lt;team@froxlor.org&gt; (2010-) * @license gplv2 https://files.froxlor.org/misc/copying.txt * @package formfields */ use froxlor\settings; use froxlor\system\crypt; return [ 'ftp_edit' =&gt; [ 'title' =&gt; lng('ftp.account_edit'), 'image' =&gt; 'icons/user_edit.png', 'self_overview' =&gt; ['section' =&gt; 'ftp', 'page' =&gt; 'accounts'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('ftp.account_edit'), 'image' =&gt; 'icons/user_edit.png', 'fields' =&gt; [ 'username' =&gt; [ 'label' =&gt; lng('login.username'), 'type' =&gt; 'label', 'value' =&gt; $result['username'] ], 'ftp_description' =&gt; [ 'label' =&gt; lng('panel.ftpdesc'), 'type' =&gt; 'text', 'value' =&gt; $result['description'] ], 'path' =&gt; [ 'label' =&gt; lng('panel.path'), 'desc' =&gt; (settings::get('panel.pathedit') != 'dropdown' ? lng('panel.pathdescription') : null), 'type' =&gt; $pathselect['type'], 'select_var' =&gt; $pathselect['select_var'] ?? '', 'selected' =&gt; $pathselect['value'], 'value' =&gt; $pathselect['value'], 'note' =&gt; $pathselect['note'] ?? '', 'mandatory' =&gt; true ], 'ftp_password' =&gt; [ 'label' =&gt; lng('login.password'), 'desc' =&gt; lng('ftp.editpassdescription'), 'type' =&gt; 'password', 'autocomplete' =&gt; 'off', 'next_to' =&gt; [ 'ftp_password_suggestion' =&gt; [ 'next_to_prefix' =&gt; lng('customer.generated_pwd') . ':', 'type' =&gt; 'text', 'visible' =&gt; (settings::get('panel.password_regex') == ''), 'value' =&gt; crypt::generatepassword(), 'readonly' =&gt; true ] ] ], 'shell' =&gt; [ 'visible' =&gt; settings::get('system.allow_customer_shell') == '1', 'label' =&gt; lng('panel.shell'), 'type' =&gt; 'select', 'select_var' =&gt; $shells, 'selected' =&gt; $result['shell'] ?? '/bin/false' ], 'login_enabled' =&gt; [ 'label' =&gt; lng('panel.active'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['login_enabled'] == 'y', ], ] ] ] ] ];</file><file name="lib/formfields/customer/ftp/formfield.ftp_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * full copyright license information, please view copying * file distributed source code. also view * copying file online https://files.froxlor.org/misc/copying.txt * * @copyright (c) authors * @author froxlor team &lt;team@froxlor.org&gt; (2010-) * @license gplv2 https://files.froxlor.org/misc/copying.txt * @package formfields */ use froxlor\settings; use froxlor\system\crypt; return [ 'ftp_add' =&gt; [ 'title' =&gt; lng('ftp.account_add'), 'image' =&gt; 'icons/user_add.png', 'self_overview' =&gt; ['section' =&gt; 'ftp', 'page' =&gt; 'accounts'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('ftp.account_add'), 'image' =&gt; 'icons/user_add.png', 'fields' =&gt; [ 'ftp_username' =&gt; [ 'visible' =&gt; settings::get('customer.ftpatdomain') == '1', 'label' =&gt; lng('login.username'), 'type' =&gt; 'text', 'next_to' =&gt; (settings::get('customer.ftpatdomain') == '1' &amp;&amp; count($domainlist) &gt; 0 ? [ 'ftp_domain' =&gt; [ 'next_to_prefix' =&gt; '@', 'label' =&gt; lng('domains.domainname'), 'type' =&gt; 'select', 'select_var' =&gt; $domainlist ], ] : []) ], 'ftp_description' =&gt; [ 'label' =&gt; lng('panel.ftpdesc'), 'type' =&gt; 'text' ], 'path' =&gt; [ 'label' =&gt; lng('panel.path'), 'desc' =&gt; (settings::get('panel.pathedit') != 'dropdown' ? lng('panel.pathdescription') : null), 'type' =&gt; $pathselect['type'], 'select_var' =&gt; $pathselect['select_var'] ?? '', 'selected' =&gt; $pathselect['value'], 'value' =&gt; $pathselect['value'], 'note' =&gt; $pathselect['note'] ?? '', 'mandatory' =&gt; true ], 'ftp_password' =&gt; [ 'label' =&gt; lng('login.password'), 'type' =&gt; 'password', 'autocomplete' =&gt; 'off', 'mandatory' =&gt; true, 'next_to' =&gt; [ 'ftp_password_suggestion' =&gt; [ 'next_to_prefix' =&gt; lng('customer.generated_pwd') . ':', 'type' =&gt; 'text', 'visible' =&gt; (settings::get('panel.password_regex') == ''), 'value' =&gt; crypt::generatepassword(), 'readonly' =&gt; true ] ] ], 'sendinfomail' =&gt; [ 'label' =&gt; lng('customer.sendinfomail'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'shell' =&gt; [ 'visible' =&gt; settings::get('system.allow_customer_shell') == '1', 'label' =&gt; lng('panel.shell'), 'type' =&gt; 'select', 'select_var' =&gt; $shells, 'selected' =&gt; '/bin/false' ], 'login_enabled' =&gt; [ 'label' =&gt; lng('panel.active'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], ] ] ] ] ];</file><file name="lib/formfields/customer/ftp/index.html" /><file name="lib/formfields/customer/email/formfield.emails_addforwarder.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'emails_addforwarder' =&gt; [ 'title' =&gt; lng('emails.forwarder_add'), 'image' =&gt; 'fa-solid fa-plus', 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('emails.forwarder_add'), 'image' =&gt; 'icons/autoresponder_add.png', 'fields' =&gt; [ 'emailaddr' =&gt; [ 'label' =&gt; lng('emails.from'), 'type' =&gt; 'label', 'value' =&gt; $result['email_full'] ], 'destination' =&gt; [ 'label' =&gt; lng('emails.to'), 'type' =&gt; 'email', 'mandatory' =&gt; true ] ] ] ] ] ];</file><file name="lib/formfields/customer/email/formfield.emails_accountchangepasswd.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; use froxlor\system\crypt; return [ 'emails_accountchangepasswd' =&gt; [ 'title' =&gt; lng('menue.main.changepassword'), 'image' =&gt; 'icons/email_edit.png', 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('menue.main.changepassword'), 'image' =&gt; 'icons/email_edit.png', 'fields' =&gt; [ 'emailaddr' =&gt; [ 'label' =&gt; lng('emails.emailaddress'), 'type' =&gt; 'label', 'value' =&gt; $result['email_full'] ], 'email_password' =&gt; [ 'label' =&gt; lng('login.password'), 'type' =&gt; 'password', 'autocomplete' =&gt; 'off', 'next_to' =&gt; [ 'email_password_suggestion' =&gt; [ 'next_to_prefix' =&gt; lng('customer.generated_pwd') . ':', 'type' =&gt; 'text', 'visible' =&gt; (settings::get('panel.password_regex') == ''), 'value' =&gt; crypt::generatepassword(), 'readonly' =&gt; true ] ] ] ] ] ] ] ];</file><file name="lib/formfields/customer/email/formfield.emails_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'emails_edit' =&gt; [ 'title' =&gt; lng('emails.emails_edit'), 'image' =&gt; 'fa-solid fa-pen', 'self_overview' =&gt; ['section' =&gt; 'email', 'page' =&gt; 'email_domain', 'domainid' =&gt; $result['domainid']], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('emails.emails_edit'), 'image' =&gt; 'icons/email_edit.png', 'fields' =&gt; [ 'email_full' =&gt; [ 'label' =&gt; lng('emails.emailaddress'), 'type' =&gt; 'label', 'value' =&gt; $result['email_full'] ], 'account_yes' =&gt; [ 'visible' =&gt; (int)$result['popaccountid'] != 0, 'label' =&gt; lng('emails.account'), 'type' =&gt; 'label', 'value' =&gt; lng('panel.yes'), 'next_to' =&gt; [ 'edit_link' =&gt; [ 'type' =&gt; 'link', 'href' =&gt; $filename . '?page=accounts&amp;amp;domainid=' . $result['domainid'] . '&amp;amp;action=changepw&amp;amp;id=' . $result['id'], 'label' =&gt; lng('menue.main.changepassword'), 'classes' =&gt; 'btn btn-sm btn-secondary' ], 'del_link' =&gt; [ 'type' =&gt; 'link', 'href' =&gt; $filename . '?page=accounts&amp;amp;domainid=' . $result['domainid'] . '&amp;amp;action=delete&amp;amp;id=' . $result['id'], 'label' =&gt; lng('emails.account_delete'), 'classes' =&gt; 'btn btn-sm btn-danger' ] ] ], 'account_no' =&gt; [ 'visible' =&gt; (int)$result['popaccountid'] == 0, 'label' =&gt; lng('emails.account'), 'type' =&gt; 'label', 'value' =&gt; lng('panel.no'), 'next_to' =&gt; [ 'add_link' =&gt; [ 'type' =&gt; 'link', 'href' =&gt; $filename . '?page=accounts&amp;amp;domainid=' . $result['domainid'] . '&amp;amp;action=add&amp;amp;id=' . $result['id'], 'label' =&gt; lng('emails.account_add'), 'classes' =&gt; 'btn btn-sm btn-primary' ] ] ], 'mail_quota' =&gt; [ 'visible' =&gt; ((int)$result['popaccountid'] != 0 &amp;&amp; settings::get('system.mail_quota_enabled')), 'label' =&gt; lng('customer.email_quota'), 'type' =&gt; 'label', 'value' =&gt; $result['quota'] . ' mib', 'next_to' =&gt; [ 'add_link' =&gt; [ 'visible' =&gt; ((int)$result['popaccountid'] != 0 &amp;&amp; settings::get('system.mail_quota_enabled')), 'type' =&gt; 'link', 'href' =&gt; $filename . '?page=accounts&amp;amp;domainid=' . $result['domainid'] . '&amp;amp;action=changequota&amp;amp;id=' . $result['id'], 'label' =&gt; lng('emails.quota_edit'), 'classes' =&gt; 'btn btn-sm btn-secondary' ] ] ], 'iscatchall' =&gt; [ 'visible' =&gt; settings::get('catchall.catchall_enabled') == '1', 'label' =&gt; lng('emails.catchall'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; (int)$result['iscatchall'], ], 'bypass_spam' =&gt; [ 'visible' =&gt; settings::get('antispam.activated') == '1' &amp;&amp; (int)settings::get('antispam.default_bypass_spam') &lt;= 2, 'label' =&gt; lng('antispam.bypass_spam'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; (int)$result['bypass_spam'], ], 'spam_tag_level' =&gt; [ 'visible' =&gt; settings::get('antispam.activated') == '1', 'label' =&gt; lng('antispam.spam_tag_level'), 'type' =&gt; 'number', 'min' =&gt; 0, 'step' =&gt; 0.1, 'value' =&gt; $result['spam_tag_level'], ], 'spam_rewrite_subject' =&gt; [ 'visible' =&gt; settings::get('antispam.activated') == '1' &amp;&amp; (int)settings::get('antispam.default_spam_rewrite_subject') &lt;= 2, 'label' =&gt; lng('antispam.rewrite_subject'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; (int)$result['rewrite_subject'], ], 'spam_kill_level' =&gt; [ 'visible' =&gt; settings::get('antispam.activated') == '1', 'label' =&gt; lng('antispam.spam_kill_level'), 'desc' =&gt; lng('panel.use_checkbox_to_disable'), 'type' =&gt; 'textul', 'step' =&gt; 0.1, 'value' =&gt; $result['spam_kill_level'] ], 'policy_greylist' =&gt; [ 'visible' =&gt; settings::get('antispam.activated') == '1' &amp;&amp; (int)settings::get('antispam.default_policy_greylist') &lt;= 2, 'label' =&gt; lng('antispam.policy_greylist'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; (int)$result['policy_greylist'], ], 'mail_fwds' =&gt; [ 'label' =&gt; lng('emails.forwarders') . ' (' . $forwarders_count . ')', 'type' =&gt; 'itemlist', 'values' =&gt; $forwarders, 'next_to' =&gt; [ 'add_link' =&gt; [ 'type' =&gt; 'link', 'href' =&gt; $filename . '?page=forwarders&amp;amp;domainid=' . $result['domainid'] . '&amp;amp;action=add&amp;amp;id=' . $result['id'], 'label' =&gt; lng('emails.forwarder_add'), 'classes' =&gt; 'btn btn-sm btn-primary' ] ] ] ] ] ], 'buttons' =&gt; [ [ 'label' =&gt; lng('panel.save') ] ] ] ];</file><file name="lib/formfields/customer/email/formfield.emails_accountchangequota.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'emails_accountchangequota' =&gt; [ 'title' =&gt; lng('emails.quota_edit'), 'image' =&gt; 'icons/email_edit.png', 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('emails.quota_edit'), 'image' =&gt; 'icons/email_edit.png', 'fields' =&gt; [ 'emailaddr' =&gt; [ 'label' =&gt; lng('emails.emailaddress'), 'type' =&gt; 'label', 'value' =&gt; $result['email_full'] ], 'email_quota' =&gt; [ 'label' =&gt; lng('emails.quota') . ' (mib)', 'type' =&gt; 'text', 'value' =&gt; $result['quota'] ] ] ] ] ] ];</file><file name="lib/formfields/customer/email/formfield.emails_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ $email_domainid ?: 0; return [ 'emails_add' =&gt; [ 'title' =&gt; lng('emails.emails_add'), 'image' =&gt; 'fa-solid fa-plus', 'self_overview' =&gt; ['section' =&gt; 'email', 'page' =&gt; $email_domainid != 0 ? 'email_domain' : 'emails', 'domainid' =&gt; $email_domainid], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('emails.emails_add'), 'image' =&gt; 'icons/email_add.png', 'fields' =&gt; [ 'email_part' =&gt; [ 'label' =&gt; lng('emails.emailaddress'), 'type' =&gt; 'text', 'next_to' =&gt; [ 'domain' =&gt; [ 'next_to_prefix' =&gt; '@', 'type' =&gt; 'select', 'select_var' =&gt; $domains, 'selected' =&gt; $selected_domain ] ] ], 'iscatchall' =&gt; [ 'label' =&gt; lng('emails.iscatchall'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ] ] ] ] ] ];</file><file name="lib/formfields/customer/email/formfield.emails_addaccount.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; use froxlor\system\crypt; return [ 'emails_addaccount' =&gt; [ 'title' =&gt; lng('emails.account_add'), 'image' =&gt; 'fa-solid fa-plus', 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('emails.account_add'), 'image' =&gt; 'icons/email_add.png', 'fields' =&gt; [ 'emailaddr' =&gt; [ 'label' =&gt; lng('emails.emailaddress'), 'type' =&gt; 'label', 'value' =&gt; $result['email_full'] ], 'email_password' =&gt; [ 'label' =&gt; lng('login.password'), 'type' =&gt; 'password', 'autocomplete' =&gt; 'off', 'mandatory' =&gt; true, 'next_to' =&gt; [ 'email_password_suggestion' =&gt; [ 'next_to_prefix' =&gt; lng('customer.generated_pwd') . ':', 'type' =&gt; 'text', 'visible' =&gt; (settings::get('panel.password_regex') == ''), 'value' =&gt; crypt::generatepassword(), 'readonly' =&gt; true ] ] ], 'email_quota' =&gt; [ 'visible' =&gt; settings::get('system.mail_quota_enabled') == '1', 'label' =&gt; lng('emails.quota'), 'desc' =&gt; "mib", 'type' =&gt; 'number', 'value' =&gt; $quota ], 'alternative_email' =&gt; [ 'visible' =&gt; settings::get('panel.sendalternativemail') == '1', 'label' =&gt; lng('emails.alternative_emailaddress'), 'type' =&gt; 'text' ] ] ] ] ] ];</file><file name="lib/formfields/customer/email/index.html" /><file name="lib/formfields/admin/index.html" /><file name="lib/formfields/admin/customer/formfield.customer_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\language; use froxlor\settings; use froxlor\system\crypt; return [ 'customer_add' =&gt; [ 'title' =&gt; lng('admin.customer_add'), 'image' =&gt; 'fa-solid fa-user-plus', 'self_overview' =&gt; ['section' =&gt; 'customers', 'page' =&gt; 'customers'], 'id' =&gt; 'customer_add', 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.accountdata'), 'image' =&gt; 'icons/user_add.png', 'fields' =&gt; [ 'new_loginname' =&gt; [ 'label' =&gt; lng('login.username'), 'type' =&gt; 'text', 'placeholder' =&gt; lng('admin.username_default_msg') ], 'createstdsubdomain' =&gt; [ 'label' =&gt; lng('admin.stdsubdomain_add') . '?', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; settings::get('system.createstdsubdom_default') ], 'store_defaultindex' =&gt; [ 'label' =&gt; lng('admin.store_defaultindex') . '?', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'new_customer_password' =&gt; [ 'label' =&gt; lng('login.password'), 'type' =&gt; 'password', 'autocomplete' =&gt; 'off', 'placeholder' =&gt; lng('admin.password_default_msg'), 'next_to' =&gt; [ 'new_customer_password_suggestion' =&gt; [ 'next_to_prefix' =&gt; lng('customer.generated_pwd') . ':', 'type' =&gt; 'text', 'visible' =&gt; (settings::get('panel.password_regex') == ''), 'value' =&gt; crypt::generatepassword(), 'readonly' =&gt; true ] ] ], 'sendpassword' =&gt; [ 'label' =&gt; lng('admin.sendpassword'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'def_language' =&gt; [ 'label' =&gt; lng('login.language'), 'type' =&gt; 'select', 'select_var' =&gt; language::getlanguages(), 'selected' =&gt; settings::get('panel.standardlanguage') ], 'gui_access' =&gt; [ 'label' =&gt; lng('usersettings.gui_access.title'), 'desc' =&gt; lng('usersettings.gui_access.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; 1 ], 'api_allowed' =&gt; [ 'label' =&gt; lng('usersettings.api_allowed.title'), 'desc' =&gt; lng('usersettings.api_allowed.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; settings::get('api.enabled') == '1' &amp;&amp; settings::get('api.customer_default'), 'visible' =&gt; settings::get('api.enabled') == '1' ], ] ], 'section_b' =&gt; [ 'title' =&gt; lng('admin.contactdata'), 'image' =&gt; 'icons/user_add.png', 'fields' =&gt; [ 'gender' =&gt; [ 'label' =&gt; lng('gender.title'), 'type' =&gt; 'select', 'select_var' =&gt; [ 0 =&gt; lng('gender.undef'), 1 =&gt; lng('gender.male'), 2 =&gt; lng('gender.female') ] ], 'firstname' =&gt; [ 'label' =&gt; lng('customer.firstname'), 'desc' =&gt; lng('customer.nameorcompany_desc'), 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'name' =&gt; [ 'label' =&gt; lng('customer.lastname'), 'desc' =&gt; lng('customer.nameorcompany_desc'), 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'company' =&gt; [ 'label' =&gt; lng('customer.company'), 'desc' =&gt; lng('customer.nameorcompany_desc'), 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'street' =&gt; [ 'label' =&gt; lng('customer.street'), 'type' =&gt; 'text' ], 'zipcode' =&gt; [ 'label' =&gt; lng('customer.zipcode') . ' / ' . lng('customer.city'), 'type' =&gt; 'text', 'next_to' =&gt; [ 'city' =&gt; [ 'next_to_prefix' =&gt; ' / ', 'type' =&gt; 'text' ] ] ], 'phone' =&gt; [ 'label' =&gt; lng('customer.phone'), 'type' =&gt; 'text' ], 'fax' =&gt; [ 'label' =&gt; lng('customer.fax'), 'type' =&gt; 'text' ], 'email' =&gt; [ 'label' =&gt; lng('customer.email'), 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'customernumber' =&gt; [ 'label' =&gt; lng('customer.customernumber'), 'type' =&gt; 'text' ], 'custom_notes' =&gt; [ 'label' =&gt; lng('usersettings.custom_notes.title'), 'desc' =&gt; lng('usersettings.custom_notes.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12 ], 'custom_notes_show' =&gt; [ 'label' =&gt; lng('usersettings.custom_notes.show'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ] ] ], 'section_cpre' =&gt; [ 'visible' =&gt; !empty($hosting_plans), 'title' =&gt; lng('admin.plans.use_plan'), 'image' =&gt; 'icons/user_add.png', 'fields' =&gt; [ 'use_plan' =&gt; [ 'label' =&gt; lng('admin.plans.use_plan'), 'type' =&gt; 'select', 'select_var' =&gt; $hosting_plans ] ] ], 'section_c' =&gt; [ 'title' =&gt; lng('admin.servicedata'), 'image' =&gt; 'icons/user_add.png', 'fields' =&gt; [ 'diskspace' =&gt; [ 'label' =&gt; lng('customer.diskspace') . ' (' . lng('customer.mib') . ')', 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 16, 'mandatory' =&gt; true ], 'traffic' =&gt; [ 'label' =&gt; lng('customer.traffic') . ' (' . lng('customer.gib') . ')', 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 14, 'mandatory' =&gt; true ], 'subdomains' =&gt; [ 'label' =&gt; lng('customer.subdomains'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'emails' =&gt; [ 'label' =&gt; lng('customer.emails'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'email_accounts' =&gt; [ 'label' =&gt; lng('customer.accounts'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'email_forwarders' =&gt; [ 'label' =&gt; lng('customer.forwarders'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'email_quota' =&gt; [ 'label' =&gt; lng('customer.email_quota') . ' (' . lng('customer.mib') . ')', 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'visible' =&gt; settings::get('system.mail_quota_enabled') == '1', 'mandatory' =&gt; true ], 'email_imap' =&gt; [ 'label' =&gt; lng('customer.email_imap'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true, 'mandatory' =&gt; true ], 'email_pop3' =&gt; [ 'label' =&gt; lng('customer.email_pop3'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true, 'mandatory' =&gt; true ], 'ftps' =&gt; [ 'label' =&gt; lng('customer.ftps'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9 ], 'mysqls' =&gt; [ 'label' =&gt; lng('customer.mysqls'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'allowed_mysqlserver' =&gt; [ 'visible' =&gt; count($mysql_servers) &gt; 1, 'label' =&gt; lng('customer.mysqlserver'), 'type' =&gt; 'checkbox', 'values' =&gt; $mysql_servers, 'value' =&gt; [0], 'is_array' =&gt; 1 ], 'phpenabled' =&gt; [ 'label' =&gt; lng('admin.phpenabled') . '?', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'allowed_phpconfigs' =&gt; [ 'visible' =&gt; (((int)settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1)), 'label' =&gt; lng('admin.phpsettings.title'), 'type' =&gt; 'checkbox', 'values' =&gt; $phpconfigs, 'value' =&gt; ((int)settings::get('system.mod_fcgid') == 1 ? [settings::get('system.mod_fcgid_defaultini')] : ((int)settings::get('phpfpm.enabled') == 1 ? [settings::get('phpfpm.defaultini')] : null)), 'is_array' =&gt; 1 ], 'perlenabled' =&gt; [ 'label' =&gt; lng('admin.perlenabled') . '?', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'dnsenabled' =&gt; [ 'label' =&gt; lng('admin.dnsenabled') . '?', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; settings::get('system.dnsenabled') == '1', 'visible' =&gt; settings::get('system.dnsenabled') == '1' ], 'logviewenabled' =&gt; [ 'label' =&gt; lng('admin.logviewenabled') . '?', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], ] ] ] ] ];</file><file name="lib/formfields/admin/customer/formfield.customer_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\language; use froxlor\settings; use froxlor\system\crypt; return [ 'customer_edit' =&gt; [ 'title' =&gt; lng('admin.customer_edit'), 'image' =&gt; 'fa-solid fa-user-pen', 'self_overview' =&gt; ['section' =&gt; 'customers', 'page' =&gt; 'customers'], 'id' =&gt; 'customer_edit', 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.accountdata'), 'image' =&gt; 'icons/user_edit.png', 'fields' =&gt; [ 'loginname' =&gt; [ 'label' =&gt; lng('login.username'), 'type' =&gt; 'label', 'value' =&gt; $result['loginname'] ], 'documentroot' =&gt; [ 'label' =&gt; lng('customer.documentroot'), 'type' =&gt; 'label', 'value' =&gt; $result['documentroot'] ], 'createstdsubdomain' =&gt; [ 'label' =&gt; lng('admin.stdsubdomain_add') . '?', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; (bool)$result['standardsubdomain'] ], 'deactivated' =&gt; [ 'label' =&gt; lng('admin.deactivated_user'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['deactivated'] ], 'new_customer_password' =&gt; [ 'label' =&gt; lng('login.password') . '&amp;nbsp;(' . lng('panel.emptyfornochanges') . ')', 'type' =&gt; 'password', 'autocomplete' =&gt; 'off', 'next_to' =&gt; [ 'new_customer_password_suggestion' =&gt; [ 'next_to_prefix' =&gt; lng('customer.generated_pwd') . ':', 'type' =&gt; 'text', 'visible' =&gt; (settings::get('panel.password_regex') == ''), 'value' =&gt; crypt::generatepassword(), 'readonly' =&gt; true ] ] ], 'def_language' =&gt; [ 'label' =&gt; lng('login.language'), 'type' =&gt; 'select', 'select_var' =&gt; language::getlanguages(), 'selected' =&gt; $result['def_language'] ], 'gui_access' =&gt; [ 'label' =&gt; lng('usersettings.gui_access.title'), 'desc' =&gt; lng('usersettings.gui_access.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['gui_access'], ], 'api_allowed' =&gt; [ 'label' =&gt; lng('usersettings.api_allowed.title'), 'desc' =&gt; lng('usersettings.api_allowed.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['api_allowed'], 'visible' =&gt; settings::get('api.enabled') == '1' ], ] ], 'section_b' =&gt; [ 'title' =&gt; lng('admin.contactdata'), 'image' =&gt; 'icons/user_edit.png', 'fields' =&gt; [ 'gender' =&gt; [ 'label' =&gt; lng('gender.title'), 'type' =&gt; 'select', 'select_var' =&gt; [ 0 =&gt; lng('gender.undef'), 1 =&gt; lng('gender.male'), 2 =&gt; lng('gender.female') ], 'selected' =&gt; $result['gender'] ], 'firstname' =&gt; [ 'label' =&gt; lng('customer.firstname'), 'desc' =&gt; lng('customer.nameorcompany_desc'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; $result['firstname'] ], 'name' =&gt; [ 'label' =&gt; lng('customer.lastname'), 'desc' =&gt; lng('customer.nameorcompany_desc'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; $result['name'] ], 'company' =&gt; [ 'label' =&gt; lng('customer.company'), 'desc' =&gt; lng('customer.nameorcompany_desc'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; $result['company'] ], 'street' =&gt; [ 'label' =&gt; lng('customer.street'), 'type' =&gt; 'text', 'value' =&gt; $result['street'] ], 'zipcode' =&gt; [ 'label' =&gt; lng('customer.zipcode') . ' / ' . lng('customer.city'), 'type' =&gt; 'text', 'value' =&gt; $result['zipcode'], 'next_to' =&gt; [ 'city' =&gt; [ 'next_to_prefix' =&gt; ' / ', 'type' =&gt; 'text', 'value' =&gt; $result['city'] ] ] ], 'phone' =&gt; [ 'label' =&gt; lng('customer.phone'), 'type' =&gt; 'text', 'value' =&gt; $result['phone'] ], 'fax' =&gt; [ 'label' =&gt; lng('customer.fax'), 'type' =&gt; 'text', 'value' =&gt; $result['fax'] ], 'email' =&gt; [ 'label' =&gt; lng('customer.email'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; $result['email'] ], 'customernumber' =&gt; [ 'label' =&gt; lng('customer.customernumber'), 'type' =&gt; 'text', 'value' =&gt; $result['customernumber'] ], 'custom_notes' =&gt; [ 'style' =&gt; 'align-top', 'label' =&gt; lng('usersettings.custom_notes.title'), 'desc' =&gt; lng('usersettings.custom_notes.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12, 'value' =&gt; $result['custom_notes'] ], 'custom_notes_show' =&gt; [ 'label' =&gt; lng('usersettings.custom_notes.show'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['custom_notes_show'] ] ] ], 'section_cpre' =&gt; [ 'visible' =&gt; !empty($hosting_plans), 'title' =&gt; lng('admin.plans.use_plan'), 'image' =&gt; 'icons/user_add.png', 'fields' =&gt; [ 'use_plan' =&gt; [ 'label' =&gt; lng('admin.plans.use_plan'), 'type' =&gt; 'select', 'select_var' =&gt; $hosting_plans ] ] ], 'section_c' =&gt; [ 'title' =&gt; lng('admin.servicedata'), 'image' =&gt; 'icons/user_edit.png', 'fields' =&gt; [ 'diskspace' =&gt; [ 'label' =&gt; lng('customer.diskspace') . ' (' . lng('customer.mib') . ')', 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['diskspace']) ? '0' : $result['diskspace'], 'maxlength' =&gt; 16, 'mandatory' =&gt; true ], 'traffic' =&gt; [ 'label' =&gt; lng('customer.traffic') . ' (' . lng('customer.gib') . ')', 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['traffic']) ? '0' : $result['traffic'], 'maxlength' =&gt; 14, 'mandatory' =&gt; true ], 'subdomains' =&gt; [ 'label' =&gt; lng('customer.subdomains'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['subdomains']) ? '0' : $result['subdomains'], 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'emails' =&gt; [ 'label' =&gt; lng('customer.emails'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['emails']) ? '0' : $result['emails'], 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'email_accounts' =&gt; [ 'label' =&gt; lng('customer.accounts'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['email_accounts']) ? '0' : $result['email_accounts'], 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'email_forwarders' =&gt; [ 'label' =&gt; lng('customer.forwarders'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['email_forwarders']) ? '0' : $result['email_forwarders'], 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'email_quota' =&gt; [ 'label' =&gt; lng('customer.email_quota') . ' (' . lng('customer.mib') . ')', 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['email_quota']) ? '0' : $result['email_quota'], 'maxlength' =&gt; 9, 'visible' =&gt; settings::get('system.mail_quota_enabled') == '1', 'mandatory' =&gt; true ], 'email_imap' =&gt; [ 'label' =&gt; lng('customer.email_imap'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['imap'], 'mandatory' =&gt; true ], 'email_pop3' =&gt; [ 'label' =&gt; lng('customer.email_pop3'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['pop3'], 'mandatory' =&gt; true ], 'ftps' =&gt; [ 'label' =&gt; lng('customer.ftps'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['ftps']) ? '0' : $result['ftps'], 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'mysqls' =&gt; [ 'label' =&gt; lng('customer.mysqls'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['mysqls']) ? '0' : $result['mysqls'], 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'allowed_mysqlserver' =&gt; [ 'visible' =&gt; count($mysql_servers) &gt; 1, 'label' =&gt; lng('customer.mysqlserver'), 'type' =&gt; 'checkbox', 'values' =&gt; $mysql_servers, 'value' =&gt; isset($result['allowed_mysqlserver']) &amp;&amp; !empty($result['allowed_mysqlserver']) ? json_decode($result['allowed_mysqlserver'], json_object_as_array) : [], 'is_array' =&gt; 1 ], 'phpenabled' =&gt; [ 'label' =&gt; lng('admin.phpenabled') . '?', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['phpenabled'] ], 'allowed_phpconfigs' =&gt; [ 'visible' =&gt; (((int)settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1)), 'label' =&gt; lng('admin.phpsettings.title'), 'type' =&gt; 'checkbox', 'values' =&gt; $phpconfigs, 'value' =&gt; isset($result['allowed_phpconfigs']) &amp;&amp; !empty($result['allowed_phpconfigs']) ? json_decode($result['allowed_phpconfigs'], json_object_as_array) : [], 'is_array' =&gt; 1 ], 'perlenabled' =&gt; [ 'label' =&gt; lng('admin.perlenabled') . '?', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['perlenabled'] ], 'dnsenabled' =&gt; [ 'label' =&gt; lng('admin.dnsenabled') . '?', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['dnsenabled'], 'visible' =&gt; settings::get('system.dnsenabled') == '1' ], 'logviewenabled' =&gt; [ 'label' =&gt; lng('admin.logviewenabled') . '?', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['logviewenabled'] ], ] ], 'section_d' =&gt; [ 'title' =&gt; lng('admin.movetoadmin'), 'image' =&gt; 'icons/user_edit.png', 'visible' =&gt; count($admin_select) &gt; 0, 'fields' =&gt; [ 'move_to_admin' =&gt; [ 'label' =&gt; lng('admin.movecustomertoadmin'), 'type' =&gt; 'select', 'select_var' =&gt; $admin_select ] ] ] ] ] ];</file><file name="lib/formfields/admin/customer/index.html" /><file name="lib/formfields/admin/cronjobs/formfield.cronjobs_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'cronjobs_edit' =&gt; [ 'title' =&gt; lng('admin.cronjob_edit'), 'image' =&gt; 'fa-solid fa-clock-rotate-left', 'self_overview' =&gt; ['section' =&gt; 'cronjobs', 'page' =&gt; 'overview'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('cronjob.cronjobsettings'), 'image' =&gt; 'icons/clock_edit.png', 'fields' =&gt; [ 'cronfile' =&gt; [ 'label' =&gt; 'cronjob', 'type' =&gt; (substr($result['module'], 0, strpos($result['module'], '/')) != 'froxlor' ? 'text' : 'label'), 'value' =&gt; $result['cronfile'] ], 'isactive' =&gt; [ 'label' =&gt; lng('admin.activated'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['isactive'] ], 'interval_value' =&gt; [ 'label' =&gt; lng('cronjob.cronjobintervalv'), 'type' =&gt; 'text', 'value' =&gt; explode(' ', $result['interval'] ?? "5 minute")[0] ?? "" ], 'interval_interval' =&gt; [ 'label' =&gt; lng('cronjob.cronjobinterval'), 'type' =&gt; 'select', 'select_var' =&gt; [ 'minute' =&gt; lng('cronmgmt.minutes'), 'hour' =&gt; lng('cronmgmt.hours'), 'day' =&gt; lng('cronmgmt.days'), 'week' =&gt; lng('cronmgmt.weeks'), 'month' =&gt; lng('cronmgmt.months') ], 'selected' =&gt; explode(' ', $result['interval'] ?? "5 minute")[1] ?? null ] ] ] ] ] ];</file><file name="lib/formfields/admin/cronjobs/index.html" /><file name="lib/formfields/admin/plans/formfield.plans_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'plans_edit' =&gt; [ 'title' =&gt; lng('admin.plans.edit'), 'image' =&gt; 'fa-solid fa-pen', 'self_overview' =&gt; ['section' =&gt; 'plans', 'page' =&gt; 'overview'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.plans.plan_details'), 'image' =&gt; 'icons/templates_edit_big.png', 'fields' =&gt; [ 'name' =&gt; [ 'label' =&gt; lng('admin.plans.name'), 'type' =&gt; 'text', 'value' =&gt; $result['name'], 'mandatory' =&gt; true ], 'description' =&gt; [ 'label' =&gt; lng('admin.plans.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12, 'value' =&gt; $result['description'] ] ] ] ] ] ];</file><file name="lib/formfields/admin/plans/index.html" /><file name="lib/formfields/admin/plans/formfield.plans_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'plans_add' =&gt; [ 'title' =&gt; lng('admin.plans.add'), 'image' =&gt; 'fa-solid fa-plus', 'self_overview' =&gt; ['section' =&gt; 'plans', 'page' =&gt; 'overview'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.plans.plan_details'), 'image' =&gt; 'icons/templates_add_big.png', 'fields' =&gt; [ 'name' =&gt; [ 'label' =&gt; lng('admin.plans.name'), 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'description' =&gt; [ 'label' =&gt; lng('admin.plans.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12 ] ] ] ] ] ];</file><file name="lib/formfields/admin/settings/index.html" /><file name="lib/formfields/admin/settings/formfield.settings_import.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'settings_import' =&gt; [ 'title' =&gt; lng('admin.configfiles.importexport'), 'image' =&gt; 'fa-solid fa-file-import', 'sections' =&gt; [ 'section_a' =&gt; [ 'fields' =&gt; [ 'import_file' =&gt; [ 'label' =&gt; lng('admin.settings_importfile'), 'type' =&gt; 'file', 'mandatory' =&gt; true ] ] ] ], 'buttons' =&gt; [ [ 'label' =&gt; lng('panel.upload_import') ] ] ] ];</file><file name="lib/formfields/admin/settings/formfield.settings_mailtest.php">&lt;?php use froxlor\settings; /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'mailtest' =&gt; [ 'title' =&gt; lng('admin.testmail'), 'image' =&gt; 'fa-solid fa-paper-plane', 'sections' =&gt; [ 'section_a' =&gt; [ 'fields' =&gt; [ 'smtp_user' =&gt; [ 'label' =&gt; lng('serversettings.mail_smtp_user'), 'type' =&gt; 'label', 'value' =&gt; (empty(settings::get('system.mail_smtp_user')) ? lng('panel.unspecified') : settings::get('system.mail_smtp_user')) ], 'smtp_host' =&gt; [ 'label' =&gt; lng('serversettings.mail_smtp_host'), 'type' =&gt; 'label', 'value' =&gt; (empty(settings::get('system.mail_smtp_host')) ? lng('panel.unspecified') : settings::get('system.mail_smtp_host')) ], 'smtp_port' =&gt; [ 'label' =&gt; lng('serversettings.mail_smtp_port'), 'type' =&gt; 'label', 'value' =&gt; (empty(settings::get('system.mail_smtp_port')) ? lng('panel.unspecified') : settings::get('system.mail_smtp_port')) ], 'smtp_auth' =&gt; [ 'label' =&gt; lng('serversettings.mail_smtp_auth'), 'type' =&gt; 'checkbox', 'value' =&gt; 1, 'checked' =&gt; (bool)settings::get('system.mail_use_smtp'), 'disabled' =&gt; true ], 'smtp_tls' =&gt; [ 'label' =&gt; lng('serversettings.mail_smtp_usetls'), 'type' =&gt; 'checkbox', 'value' =&gt; 1, 'checked' =&gt; (bool)settings::get('system.mail_smtp_usetls'), 'disabled' =&gt; true ], 'test_addr' =&gt; [ 'label' =&gt; lng('admin.smtptestaddr'), 'type' =&gt; 'email', 'mandatory' =&gt; true ] ] ] ], 'buttons' =&gt; [ [ 'label' =&gt; lng('admin.smtptestsend') ] ] ] ];</file><file name="lib/formfields/admin/ipsandports/formfield.ipsandports_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'ipsandports_edit' =&gt; [ 'title' =&gt; lng('admin.ipsandports.edit'), 'image' =&gt; 'fa-solid fa-pen', 'self_overview' =&gt; ['section' =&gt; 'ipsandports', 'page' =&gt; 'ipsandports'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.ipsandports.ipandport'), 'image' =&gt; 'icons/ipsports_add.png', 'fields' =&gt; [ 'ip' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ip'), 'type' =&gt; 'text', 'value' =&gt; $result['ip'], 'mandatory' =&gt; true ], 'port' =&gt; [ 'label' =&gt; lng('admin.ipsandports.port'), 'type' =&gt; 'number', 'value' =&gt; $result['port'], 'min' =&gt; 1, 'max' =&gt; 65535, 'mandatory' =&gt; true ] ] ], 'section_b' =&gt; [ 'title' =&gt; lng('admin.ipsandports.webserverdefaultconfig'), 'image' =&gt; 'icons/ipsports_edit.png', 'fields' =&gt; [ 'listen_statement' =&gt; [ 'visible' =&gt; settings::get('system.webserver') != 'nginx', 'label' =&gt; lng('admin.ipsandports.create_listen_statement'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['listen_statement'] ], 'namevirtualhost_statement' =&gt; [ 'visible' =&gt; settings::get('system.webserver') == 'apache2' &amp;&amp; (int)settings::get('system.apache24') == 0, 'label' =&gt; lng('admin.ipsandports.create_namevirtualhost_statement'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['namevirtualhost_statement'] ], 'vhostcontainer' =&gt; [ 'label' =&gt; lng('admin.ipsandports.create_vhostcontainer'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['vhostcontainer'] ], 'docroot' =&gt; [ 'label' =&gt; lng('admin.ipsandports.docroot.title'), 'desc' =&gt; lng('admin.ipsandports.docroot.description'), 'type' =&gt; 'text', 'value' =&gt; $result['docroot'] ], 'specialsettings' =&gt; [ 'label' =&gt; lng('admin.ownvhostsettings'), 'desc' =&gt; lng('serversettings.default_vhostconf.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12, 'value' =&gt; $result['specialsettings'] ], 'vhostcontainer_servername_statement' =&gt; [ 'visible' =&gt; settings::get('system.webserver') == 'apache2', 'label' =&gt; lng('admin.ipsandports.create_vhostcontainer_servername_statement'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['vhostcontainer_servername_statement'] ] ] ], 'section_c' =&gt; [ 'title' =&gt; lng('admin.ipsandports.webserverdomainconfig'), 'image' =&gt; 'icons/ipsports_edit.png', 'fields' =&gt; [ 'default_vhostconf_domain' =&gt; [ 'label' =&gt; lng('admin.ipsandports.default_vhostconf_domain'), 'desc' =&gt; lng('serversettings.default_vhostconf_domain.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12, 'value' =&gt; $result['default_vhostconf_domain'] ], 'ssl_default_vhostconf_domain' =&gt; [ 'visible' =&gt; settings::get('system.use_ssl') == 1, 'label' =&gt; lng('admin.ipsandports.ssl_default_vhostconf_domain'), 'desc' =&gt; lng('serversettings.default_vhostconf_domain.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12, 'value' =&gt; $result['ssl_default_vhostconf_domain'] ], 'include_default_vhostconf_domain' =&gt; [ 'label' =&gt; lng('serversettings.includedefault_sslvhostconf'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['include_default_vhostconf_domain'] ] ] ], 'section_d' =&gt; [ 'title' =&gt; lng('admin.ipsandports.webserverssldomainconfig'), 'image' =&gt; 'icons/ipsports_edit.png', 'visible' =&gt; settings::get('system.use_ssl') == 1, 'fields' =&gt; [ 'ssl' =&gt; [ 'label' =&gt; lng('admin.ipsandports.enable_ssl'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['ssl'] ], 'ssl_cert_file' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_cert_file'), 'type' =&gt; 'text', 'value' =&gt; $result['ssl_cert_file'] ], 'ssl_key_file' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_key_file'), 'type' =&gt; 'text', 'value' =&gt; $result['ssl_key_file'] ], 'ssl_ca_file' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_ca_file'), 'type' =&gt; 'text', 'value' =&gt; $result['ssl_ca_file'] ], 'ssl_cert_chainfile' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_cert_chainfile.title'), 'desc' =&gt; lng('admin.ipsandports.ssl_cert_chainfile.description'), 'type' =&gt; 'text', 'value' =&gt; $result['ssl_cert_chainfile'] ], 'ssl_specialsettings' =&gt; [ 'label' =&gt; lng('admin.ownsslvhostsettings'), 'desc' =&gt; lng('serversettings.default_vhostconf.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12, 'value' =&gt; $result['ssl_specialsettings'] ], 'include_specialsettings' =&gt; [ 'label' =&gt; lng('serversettings.includedefault_sslvhostconf'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['include_specialsettings'] ] ] ] ] ] ];</file><file name="lib/formfields/admin/ipsandports/formfield.ipsandports_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'ipsandports_add' =&gt; [ 'title' =&gt; lng('admin.ipsandports.add'), 'image' =&gt; 'fa-solid fa-plus', 'self_overview' =&gt; ['section' =&gt; 'ipsandports', 'page' =&gt; 'ipsandports'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.ipsandports.ipandport'), 'image' =&gt; 'icons/ipsports_add.png', 'fields' =&gt; [ 'ip' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ip'), 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'port' =&gt; [ 'label' =&gt; lng('admin.ipsandports.port'), 'type' =&gt; 'number', 'min' =&gt; 1, 'max' =&gt; 65535, 'value' =&gt; 80, 'mandatory' =&gt; true ] ] ], 'section_b' =&gt; [ 'title' =&gt; lng('admin.ipsandports.webserverdefaultconfig'), 'image' =&gt; 'icons/ipsports_add.png', 'fields' =&gt; [ 'listen_statement' =&gt; [ 'visible' =&gt; settings::get('system.webserver') != 'nginx', 'label' =&gt; lng('admin.ipsandports.create_listen_statement'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'namevirtualhost_statement' =&gt; [ 'visible' =&gt; settings::get('system.webserver') == 'apache2' &amp;&amp; (int)settings::get('system.apache24') == 0, 'label' =&gt; lng('admin.ipsandports.create_namevirtualhost_statement'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; settings::get('system.webserver') == 'apache2' &amp;&amp; (int)settings::get('system.apache24') == 0 ], 'vhostcontainer' =&gt; [ 'label' =&gt; lng('admin.ipsandports.create_vhostcontainer'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'docroot' =&gt; [ 'label' =&gt; lng('admin.ipsandports.docroot.title'), 'desc' =&gt; lng('admin.ipsandports.docroot.description'), 'type' =&gt; 'text' ], 'specialsettings' =&gt; [ 'label' =&gt; lng('admin.ownvhostsettings'), 'desc' =&gt; lng('serversettings.default_vhostconf.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12 ], 'vhostcontainer_servername_statement' =&gt; [ 'visible' =&gt; settings::get('system.webserver') == 'apache2', 'label' =&gt; lng('admin.ipsandports.create_vhostcontainer_servername_statement'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ] ] ], 'section_c' =&gt; [ 'title' =&gt; lng('admin.ipsandports.webserverdomainconfig'), 'image' =&gt; 'icons/ipsports_add.png', 'fields' =&gt; [ 'default_vhostconf_domain' =&gt; [ 'label' =&gt; lng('admin.ipsandports.default_vhostconf_domain'), 'desc' =&gt; lng('serversettings.default_vhostconf_domain.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12 ], 'ssl_default_vhostconf_domain' =&gt; [ 'visible' =&gt; settings::get('system.use_ssl') == 1, 'label' =&gt; lng('admin.ipsandports.ssl_default_vhostconf_domain'), 'desc' =&gt; lng('serversettings.default_vhostconf_domain.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12 ], 'include_default_vhostconf_domain' =&gt; [ 'label' =&gt; lng('serversettings.includedefault_sslvhostconf'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ] ] ], 'section_d' =&gt; [ 'title' =&gt; lng('admin.ipsandports.webserverssldomainconfig'), 'image' =&gt; 'icons/ipsports_add.png', 'visible' =&gt; settings::get('system.use_ssl') == 1, 'fields' =&gt; [ 'ssl' =&gt; [ 'label' =&gt; lng('admin.ipsandports.enable_ssl'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'ssl_cert_file' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_cert_file'), 'type' =&gt; 'text' ], 'ssl_key_file' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_key_file'), 'type' =&gt; 'text' ], 'ssl_ca_file' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_ca_file'), 'type' =&gt; 'text' ], 'ssl_cert_chainfile' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_cert_chainfile.title'), 'desc' =&gt; lng('admin.ipsandports.ssl_cert_chainfile.description'), 'type' =&gt; 'text' ], 'ssl_specialsettings' =&gt; [ 'label' =&gt; lng('admin.ownsslvhostsettings'), 'desc' =&gt; lng('serversettings.default_vhostconf.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12 ], 'include_specialsettings' =&gt; [ 'label' =&gt; lng('serversettings.includedefault_sslvhostconf'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ] ] ] ] ] ];</file><file name="lib/formfields/admin/ipsandports/index.html" /><file name="lib/formfields/admin/mysqlserver/formfield.mysqlserver_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'mysqlserver_edit' =&gt; [ 'title' =&gt; lng('admin.mysqlserver.edit'), 'image' =&gt; 'fa-solid fa-pen', 'self_overview' =&gt; ['section' =&gt; 'mysqlserver', 'page' =&gt; 'mysqlserver'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.mysqlserver.mysqlserver'), 'fields' =&gt; [ 'mysql_host' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.host'), 'type' =&gt; empty($result['id']) ? 'label' : 'text', 'value' =&gt; $result['host'], 'mandatory' =&gt; true, ], 'mysql_port' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.port'), 'type' =&gt; 'number', 'min' =&gt; 1, 'max' =&gt; 65535, 'value' =&gt; $result['port'], 'mandatory' =&gt; true ], 'description' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.caption'), 'type' =&gt; 'text', 'value' =&gt; $result['caption'], ], 'privileged_user' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.user'), 'type' =&gt; 'text', 'value' =&gt; $result['user'], 'mandatory' =&gt; true ], 'privileged_password' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.password_emptynochange'), 'type' =&gt; 'password' ], 'allow_all_customers' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.allowall'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'test_connection' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.testconn'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ] ] ], 'section_b' =&gt; [ 'title' =&gt; lng('admin.mysqlserver.ssl'), 'fields' =&gt; [ 'mysql_ca' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.ssl_cert_file'), 'type' =&gt; 'text', 'value' =&gt; $result['ssl']['cafile'] ?? "", ], 'mysql_verifycert' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.verify_ca'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['ssl']['verifyservercertificate'] ?? false, ] ] ] ] ] ];</file><file name="lib/formfields/admin/mysqlserver/formfield.mysqlserver_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'mysqlserver_add' =&gt; [ 'title' =&gt; lng('admin.mysqlserver.add'), 'image' =&gt; 'fa-solid fa-plus', 'self_overview' =&gt; ['section' =&gt; 'mysqlserver', 'page' =&gt; 'mysqlserver'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.mysqlserver.mysqlserver'), 'fields' =&gt; [ 'mysql_host' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.host'), 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'mysql_port' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.port'), 'type' =&gt; 'number', 'min' =&gt; 1, 'max' =&gt; 65535, 'value' =&gt; 3306, 'mandatory' =&gt; true ], 'description' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.caption'), 'type' =&gt; 'text', ], 'privileged_user' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.user'), 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'privileged_password' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.password'), 'type' =&gt; 'password', 'mandatory' =&gt; true ], 'allow_all_customers' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.allowall'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'test_connection' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.testconn'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ] ] ], 'section_b' =&gt; [ 'title' =&gt; lng('admin.mysqlserver.ssl'), 'fields' =&gt; [ 'mysql_ca' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.ssl_cert_file'), 'type' =&gt; 'text' ], 'mysql_verifycert' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.verify_ca'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ] ] ] ] ] ];</file><file name="lib/formfields/admin/mysqlserver/index.html" /><file name="lib/formfields/admin/domains/formfield.domains_duplicate.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'domain_duplicate' =&gt; [ 'title' =&gt; lng('admin.domain_duplicate'), 'image' =&gt; 'fa-solid fa-globe', 'self_overview' =&gt; ['section' =&gt; 'domains', 'page' =&gt; 'domains'], 'id' =&gt; 'domain_add', 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('domains.domainsettings'), 'image' =&gt; 'icons/domain_add.png', 'fields' =&gt; [ 'domain' =&gt; [ 'label' =&gt; 'domain', 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'customerid' =&gt; [ 'label' =&gt; lng('admin.customer'), 'type' =&gt; 'select', 'select_var' =&gt; $customers, 'selected' =&gt; $result['customerid'], 'mandatory' =&gt; true ], ] ] ], 'buttons' =&gt; [ [ 'label' =&gt; lng('admin.domain_duplicate') ] ] ] ];</file><file name="lib/formfields/admin/domains/formfield.domains_import.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'domain_import' =&gt; [ 'title' =&gt; lng('domains.domain_import'), 'image' =&gt; 'fa-solid fa-file-import', 'self_overview' =&gt; ['section' =&gt; 'domains', 'page' =&gt; 'domains'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('domains.domain_import'), 'image' =&gt; 'icons/domain_add.png', 'fields' =&gt; [ 'separator' =&gt; [ 'label' =&gt; lng('domains.import_separator'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'size' =&gt; 5, 'value' =&gt; ';' ], 'offset' =&gt; [ 'label' =&gt; lng('domains.import_offset'), 'type' =&gt; 'number', 'mandatory' =&gt; true, 'size' =&gt; 10, 'min' =&gt; 0, 'value' =&gt; '0' ], 'file' =&gt; [ 'label' =&gt; lng('domains.import_file'), 'type' =&gt; 'file', 'mandatory' =&gt; true ] ] ] ], 'buttons' =&gt; [ [ 'label' =&gt; lng('domains.domain_import') ] ] ] ];</file><file name="lib/formfields/admin/domains/formfield.domains_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'domain_add' =&gt; [ 'title' =&gt; lng('admin.domain_add'), 'image' =&gt; 'fa-solid fa-globe', 'self_overview' =&gt; ['section' =&gt; 'domains', 'page' =&gt; 'domains'], 'id' =&gt; 'domain_add', 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('domains.domainsettings'), 'image' =&gt; 'icons/domain_add.png', 'fields' =&gt; [ 'domain' =&gt; [ 'label' =&gt; 'domain', 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'customerid' =&gt; [ 'label' =&gt; lng('admin.customer'), 'type' =&gt; 'select', 'select_var' =&gt; $customers, 'mandatory' =&gt; true ], 'adminid' =&gt; [ 'visible' =&gt; $userinfo['customers_see_all'] == '1', 'label' =&gt; lng('admin.admin'), 'type' =&gt; 'select', 'select_var' =&gt; $admins, 'selected' =&gt; $userinfo['adminid'], 'mandatory' =&gt; true ], 'alias' =&gt; [ 'label' =&gt; lng('domains.aliasdomain'), 'type' =&gt; 'select', 'select_var' =&gt; $domains ], 'caneditdomain' =&gt; [ 'label' =&gt; lng('admin.domain_editable.title'), 'desc' =&gt; lng('admin.domain_editable.desc'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'add_date' =&gt; [ 'label' =&gt; lng('domains.add_date'), 'desc' =&gt; lng('panel.dateformat'), 'type' =&gt; 'date', 'readonly' =&gt; true, 'value' =&gt; date('y-m-d') ], 'registration_date' =&gt; [ 'label' =&gt; lng('domains.registration_date'), 'desc' =&gt; lng('panel.dateformat'), 'type' =&gt; 'date', 'size' =&gt; 10 ], 'termination_date' =&gt; [ 'label' =&gt; lng('domains.termination_date'), 'desc' =&gt; lng('panel.dateformat'), 'type' =&gt; 'date', 'size' =&gt; 10 ] ] ], 'section_e' =&gt; [ 'title' =&gt; lng('admin.mailserversettings'), 'image' =&gt; 'icons/domain_add.png', 'fields' =&gt; [ 'isemaildomain' =&gt; [ 'label' =&gt; lng('admin.emaildomain'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'email_only' =&gt; [ 'label' =&gt; lng('admin.email_only'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'subcanemaildomain' =&gt; [ 'label' =&gt; lng('admin.subdomainforemail'), 'type' =&gt; 'select', 'select_var' =&gt; $subcanemaildomain, 'selected' =&gt; 0 ], 'dkim' =&gt; [ 'visible' =&gt; settings::get('antispam.activated') == '1', 'label' =&gt; 'domainkeys', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ] ] ], 'section_b' =&gt; [ 'title' =&gt; lng('admin.webserversettings'), 'image' =&gt; 'icons/domain_add.png', 'fields' =&gt; [ 'documentroot' =&gt; [ 'label' =&gt; 'documentroot', 'desc' =&gt; lng('panel.emptyfordefault'), 'type' =&gt; 'text' ], 'ipandport' =&gt; [ 'label' =&gt; lng('domains.ipandport_multi.title'), 'desc' =&gt; lng('domains.ipandport_multi.description'), 'type' =&gt; 'checkbox', 'values' =&gt; $ipsandports, 'value' =&gt; explode(',', settings::get('system.defaultip')), 'is_array' =&gt; 1, 'mandatory' =&gt; true ], 'selectserveralias' =&gt; [ 'label' =&gt; lng('admin.selectserveralias'), 'desc' =&gt; lng('admin.selectserveralias_desc'), 'type' =&gt; 'select', 'select_var' =&gt; $serveraliasoptions, 'selected' =&gt; settings::get('system.domaindefaultalias') ], 'specialsettings' =&gt; [ 'visible' =&gt; $userinfo['change_serversettings'] == '1', 'label' =&gt; lng('admin.ownvhostsettings'), 'desc' =&gt; lng('serversettings.default_vhostconf.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12 ], 'notryfiles' =&gt; [ 'visible' =&gt; (settings::get('system.webserver') == 'nginx' &amp;&amp; $userinfo['change_serversettings'] == '1'), 'label' =&gt; lng('admin.notryfiles.title'), 'desc' =&gt; lng('admin.notryfiles.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'writeaccesslog' =&gt; [ 'label' =&gt; lng('admin.writeaccesslog.title'), 'desc' =&gt; lng('admin.writeaccesslog.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'writeerrorlog' =&gt; [ 'label' =&gt; lng('admin.writeerrorlog.title'), 'desc' =&gt; lng('admin.writeerrorlog.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'speciallogfile' =&gt; [ 'label' =&gt; lng('admin.speciallogfile.title'), 'desc' =&gt; lng('admin.speciallogfile.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], ] ], 'section_bssl' =&gt; [ 'title' =&gt; lng('admin.webserversettings_ssl'), 'image' =&gt; 'icons/domain_add.png', 'visible' =&gt; settings::get('system.use_ssl') == '1', 'fields' =&gt; [ 'sslenabled' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('admin.domain_sslenabled'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; !empty(settings::get('system.defaultsslip')) ], 'no_ssl_available_info' =&gt; [ 'visible' =&gt; empty($ssl_ipsandports), 'label' =&gt; 'ssl', 'type' =&gt; 'label', 'value' =&gt; lng('panel.nosslipsavailable') ], 'ssl_ipandport' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('domains.ipandport_ssl_multi.title'), 'desc' =&gt; lng('domains.ipandport_multi.description'), 'type' =&gt; 'checkbox', 'values' =&gt; $ssl_ipsandports, 'value' =&gt; explode(',', settings::get('system.defaultsslip')), 'is_array' =&gt; 1 ], 'ssl_redirect' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('domains.ssl_redirect.title'), 'desc' =&gt; lng('domains.ssl_redirect.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'letsencrypt' =&gt; [ 'visible' =&gt; (settings::get('system.leenabled') == '1' &amp;&amp; !empty($ssl_ipsandports)), 'label' =&gt; lng('admin.letsencrypt.title'), 'desc' =&gt; lng('admin.letsencrypt.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'http2' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; settings::get('system.webserver') != 'lighttpd' &amp;&amp; settings::get('system.http2_support') == '1', 'label' =&gt; lng('admin.domain_http2.title'), 'desc' =&gt; lng('admin.domain_http2.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'override_tls' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; $userinfo['change_serversettings'] == '1', 'label' =&gt; lng('admin.domain_override_tls'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'ssl_protocols' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; $userinfo['change_serversettings'] == '1' &amp;&amp; settings::get('system.webserver') != 'lighttpd', 'label' =&gt; lng('serversettings.ssl.ssl_protocols.title'), 'desc' =&gt; lng('serversettings.ssl.ssl_protocols.description').lng('admin.domain_override_tls_addinfo'), 'type' =&gt; 'checkbox', 'value' =&gt; [ 'tlsv1.2' ], 'values' =&gt; [ [ 'value' =&gt; 'tlsv1', 'label' =&gt; 'tlsv1' ], [ 'value' =&gt; 'tlsv1.1', 'label' =&gt; 'tlsv1.1' ], [ 'value' =&gt; 'tlsv1.2', 'label' =&gt; 'tlsv1.2' ], [ 'value' =&gt; 'tlsv1.3', 'label' =&gt; 'tlsv1.3' ] ], 'is_array' =&gt; 1 ], 'ssl_cipher_list' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; $userinfo['change_serversettings'] == '1', 'label' =&gt; lng('serversettings.ssl.ssl_cipher_list.title'), 'desc' =&gt; lng('serversettings.ssl.ssl_cipher_list.description').lng('admin.domain_override_tls_addinfo'), 'type' =&gt; 'text', 'value' =&gt; settings::get('system.ssl_cipher_list') ], 'tlsv13_cipher_list' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; $userinfo['change_serversettings'] == '1' &amp;&amp; settings::get('system.webserver') == "apache2" &amp;&amp; settings::get('system.apache24') == 1, 'label' =&gt; lng('serversettings.ssl.tlsv13_cipher_list.title'), 'desc' =&gt; lng('serversettings.ssl.tlsv13_cipher_list.description').lng('admin.domain_override_tls_addinfo'), 'type' =&gt; 'text', 'value' =&gt; settings::get('system.tlsv13_cipher_list') ], 'ssl_specialsettings' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; $userinfo['change_serversettings'] == '1', 'label' =&gt; lng('admin.ownsslvhostsettings'), 'desc' =&gt; lng('serversettings.default_vhostconf.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12 ], 'include_specialsettings' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; $userinfo['change_serversettings'] == '1', 'label' =&gt; lng('serversettings.includedefault_sslvhostconf'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'hsts_maxage' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('admin.domain_hsts_maxage.title'), 'desc' =&gt; lng('admin.domain_hsts_maxage.description'), 'type' =&gt; 'number', 'min' =&gt; 0, 'max' =&gt; 94608000, // 3-years 'value' =&gt; 0 ], 'hsts_sub' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('admin.domain_hsts_incsub.title'), 'desc' =&gt; lng('admin.domain_hsts_incsub.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'hsts_preload' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('admin.domain_hsts_preload.title'), 'desc' =&gt; lng('admin.domain_hsts_preload.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'ocsp_stapling' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; settings::get('system.webserver') != 'lighttpd', 'label' =&gt; lng('admin.domain_ocsp_stapling.title'), 'desc' =&gt; lng('admin.domain_ocsp_stapling.description') . (settings::get('system.webserver') == 'nginx' ? lng('admin.domain_ocsp_stapling.nginx_version_warning') : ""), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'honorcipherorder' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('admin.domain_honorcipherorder'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'sessiontickets' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; settings::get('system.webserver') != 'lighttpd' &amp;&amp; settings::get('system.sessionticketsenabled' != '1'), 'label' =&gt; lng('admin.domain_sessiontickets'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ] ] ], 'section_c' =&gt; [ 'title' =&gt; lng('admin.phpserversettings'), 'image' =&gt; 'icons/domain_add.png', 'visible' =&gt; $userinfo['change_serversettings'] == '1' || $userinfo['caneditphpsettings'] == '1', 'fields' =&gt; [ 'openbasedir' =&gt; [ 'label' =&gt; 'openbasedir', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'openbasedir_path' =&gt; [ 'label' =&gt; lng('domain.openbasedirpath'), 'type' =&gt; 'select', 'select_var' =&gt; $openbasedir, 'selected' =&gt; 0 ], 'phpenabled' =&gt; [ 'label' =&gt; lng('admin.phpenabled'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'phpsettingid' =&gt; [ 'visible' =&gt; (int)settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('admin.phpsettings.title'), 'type' =&gt; 'select', 'select_var' =&gt; $phpconfigs, 'selected' =&gt; (int)settings::get('phpfpm.enabled') == 1 ? settings::get('phpfpm.defaultini') : settings::get('system.mod_fcgid_defaultini') ], 'mod_fcgid_starter' =&gt; [ 'visible' =&gt; (int)settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.mod_fcgid_starter.title'), 'type' =&gt; 'number' ], 'mod_fcgid_maxrequests' =&gt; [ 'visible' =&gt; (int)settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.mod_fcgid_maxrequests.title'), 'type' =&gt; 'number' ] ] ], 'section_d' =&gt; [ 'title' =&gt; lng('admin.nameserversettings'), 'image' =&gt; 'icons/domain_add.png', 'visible' =&gt; settings::get('system.bind_enable') == '1' &amp;&amp; $userinfo['change_serversettings'] == '1', 'fields' =&gt; [ 'isbinddomain' =&gt; [ 'label' =&gt; lng('admin.createzonefile'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; true ], 'zonefile' =&gt; [ 'label' =&gt; lng('admin.custombindzone'), 'desc' =&gt; lng('admin.bindzonewarning'), 'type' =&gt; 'text' ] ] ] ] ] ];</file><file name="lib/formfields/admin/domains/formfield.domains_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'domain_edit' =&gt; [ 'title' =&gt; lng('admin.domain_edit'), 'image' =&gt; 'fa-solid fa-globe', 'self_overview' =&gt; ['section' =&gt; 'domains', 'page' =&gt; 'domains'], 'id' =&gt; 'domain_edit', 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('domains.domainsettings'), 'image' =&gt; 'icons/domain_edit.png', 'fields' =&gt; [ 'domain' =&gt; [ 'label' =&gt; 'domain', 'type' =&gt; 'label', 'value' =&gt; $result['domain_ace'] ], 'customerid' =&gt; [ 'label' =&gt; lng('admin.customer'), 'type' =&gt; (settings::get('panel.allow_domain_change_customer') == '1' ? 'select' : 'infotext'), 'select_var' =&gt; (isset($customers) ? $customers : null), 'selected' =&gt; $result['customerid'], 'value' =&gt; (isset($result['customername']) ? $result['customername'] : null), 'mandatory' =&gt; true ], 'adminid' =&gt; [ 'visible' =&gt; $userinfo['customers_see_all'] == '1', 'label' =&gt; lng('admin.admin'), 'type' =&gt; (settings::get('panel.allow_domain_change_admin') == '1' ? 'select' : 'infotext'), 'select_var' =&gt; (!empty($admins) ? $admins : null), 'selected' =&gt; (isset($result['adminid']) ? $result['adminid'] : $userinfo['adminid']), 'value' =&gt; (isset($result['adminname']) ? $result['adminname'] : null), 'mandatory' =&gt; true ], 'alias' =&gt; [ 'visible' =&gt; $alias_check == '0', 'label' =&gt; lng('domains.aliasdomain'), 'type' =&gt; 'select', 'select_var' =&gt; $domains, 'selected' =&gt; $result['aliasdomain'] ], 'associated_info' =&gt; [ 'label' =&gt; lng('domains.associated_with_domain'), 'type' =&gt; 'label', 'value' =&gt; $subdomains . ' ' . lng('customer.subdomains') . ', ' . $alias_check . ' ' . lng('domains.aliasdomains') . ', ' . $emails . ' ' . lng('customer.emails') . ', ' . $email_accounts . ' ' . lng('customer.accounts') . ', ' . $email_forwarders . ' ' . lng('customer.forwarders') ], 'caneditdomain' =&gt; [ 'label' =&gt; lng('admin.domain_editable.title'), 'desc' =&gt; lng('admin.domain_editable.desc'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['caneditdomain'] ], 'add_date' =&gt; [ 'label' =&gt; lng('domains.add_date'), 'desc' =&gt; lng('panel.dateformat'), 'type' =&gt; 'date', 'readonly' =&gt; true, 'value' =&gt; date('y-m-d', (int)$result['add_date']) ], 'registration_date' =&gt; [ 'label' =&gt; lng('domains.registration_date'), 'desc' =&gt; lng('panel.dateformat'), 'type' =&gt; 'date', 'value' =&gt; $result['registration_date'], 'size' =&gt; 10 ], 'termination_date' =&gt; [ 'label' =&gt; lng('domains.termination_date'), 'desc' =&gt; lng('panel.dateformat'), 'type' =&gt; 'date', 'value' =&gt; $result['termination_date'], 'size' =&gt; 10 ], 'deactivated' =&gt; [ 'label' =&gt; lng('admin.deactivated'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['deactivated'] ], ] ], 'section_e' =&gt; [ 'title' =&gt; lng('admin.mailserversettings'), 'image' =&gt; 'icons/domain_edit.png', 'fields' =&gt; [ 'isemaildomain' =&gt; [ 'label' =&gt; lng('admin.emaildomain'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['isemaildomain'] ], 'email_only' =&gt; [ 'label' =&gt; lng('admin.email_only'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['email_only'] ], 'subcanemaildomain' =&gt; [ 'label' =&gt; lng('admin.subdomainforemail'), 'type' =&gt; 'select', 'select_var' =&gt; $subcanemaildomain, 'selected' =&gt; $result['subcanemaildomain'] ], 'dkim' =&gt; [ 'visible' =&gt; settings::get('antispam.activated') == '1', 'label' =&gt; 'domainkeys', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['dkim'] ] ] ], 'section_b' =&gt; [ 'title' =&gt; lng('admin.webserversettings'), 'image' =&gt; 'icons/domain_edit.png', 'fields' =&gt; [ 'documentroot' =&gt; [ 'label' =&gt; 'documentroot', 'desc' =&gt; lng('panel.emptyfordefault'), 'type' =&gt; 'text', 'value' =&gt; $result['documentroot'] ], 'ipandport' =&gt; [ 'label' =&gt; lng('domains.ipandport_multi.title'), 'desc' =&gt; lng('domains.ipandport_multi.description'), 'type' =&gt; 'checkbox', 'values' =&gt; $ipsandports, 'value' =&gt; $usedips, 'is_array' =&gt; 1, 'mandatory' =&gt; true ], 'selectserveralias' =&gt; [ 'label' =&gt; lng('admin.selectserveralias'), 'desc' =&gt; lng('admin.selectserveralias_desc'), 'type' =&gt; 'select', 'select_var' =&gt; $serveraliasoptions, 'selected' =&gt; $result['iswildcarddomain'] == '1' ? 0 : ($result['wwwserveralias'] == '1' ? 1 : 2) ], 'specialsettings' =&gt; [ 'visible' =&gt; $userinfo['change_serversettings'] == '1', 'label' =&gt; lng('admin.ownvhostsettings'), 'desc' =&gt; lng('serversettings.default_vhostconf.description'), 'type' =&gt; 'textarea', 'value' =&gt; $result['specialsettings'], 'cols' =&gt; 60, 'rows' =&gt; 12 ], 'specialsettingsforsubdomains' =&gt; [ 'visible' =&gt; $userinfo['change_serversettings'] == '1', 'label' =&gt; lng('admin.specialsettingsforsubdomains'), 'desc' =&gt; lng('serversettings.specialsettingsforsubdomains.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; settings::get('system.apply_specialsettings_default') == 1 ? '1' : '0' ], 'notryfiles' =&gt; [ 'visible' =&gt; (settings::get('system.webserver') == 'nginx' &amp;&amp; $userinfo['change_serversettings'] == '1'), 'label' =&gt; lng('admin.notryfiles.title'), 'desc' =&gt; lng('admin.notryfiles.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['notryfiles'] ], 'writeaccesslog' =&gt; [ 'label' =&gt; lng('admin.writeaccesslog.title'), 'desc' =&gt; lng('admin.writeaccesslog.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['writeaccesslog'] ], 'writeerrorlog' =&gt; [ 'label' =&gt; lng('admin.writeerrorlog.title'), 'desc' =&gt; lng('admin.writeerrorlog.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['writeerrorlog'] ], 'speciallogfile' =&gt; [ 'label' =&gt; lng('admin.speciallogfile.title'), 'desc' =&gt; lng('admin.speciallogfile.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['speciallogfile'] ], 'speciallogverified' =&gt; [ 'type' =&gt; 'hidden', 'value' =&gt; '0' ], 'emaildomainverified' =&gt; [ 'type' =&gt; 'hidden', 'value' =&gt; '0' ], ] ], 'section_bssl' =&gt; [ 'title' =&gt; lng('admin.webserversettings_ssl'), 'image' =&gt; 'icons/domain_edit.png', 'visible' =&gt; settings::get('system.use_ssl') == '1', 'fields' =&gt; [ 'sslenabled' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('admin.domain_sslenabled'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['ssl_enabled'] ], 'no_ssl_available_info' =&gt; [ 'visible' =&gt; empty($ssl_ipsandports), 'label' =&gt; 'ssl', 'type' =&gt; 'label', 'value' =&gt; lng('panel.nosslipsavailable') ], 'ssl_ipandport' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('domains.ipandport_ssl_multi.title'), 'desc' =&gt; lng('domains.ipandport_multi.description'), 'type' =&gt; 'checkbox', 'values' =&gt; $ssl_ipsandports, 'value' =&gt; $usedips, 'is_array' =&gt; 1 ], 'ssl_redirect' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('domains.ssl_redirect.title'), 'desc' =&gt; lng('domains.ssl_redirect.description') . ($result['temporary_ssl_redirect'] &gt; 1 ? lng('domains.ssl_redirect_temporarilydisabled') : ''), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['ssl_redirect'] ], 'letsencrypt' =&gt; [ 'visible' =&gt; (settings::get('system.leenabled') == '1' &amp;&amp; !empty($ssl_ipsandports)), 'label' =&gt; lng('admin.letsencrypt.title'), 'desc' =&gt; lng('admin.letsencrypt.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['letsencrypt'] ], 'http2' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; settings::get('system.webserver') != 'lighttpd' &amp;&amp; settings::get('system.http2_support') == '1', 'label' =&gt; lng('admin.domain_http2.title'), 'desc' =&gt; lng('admin.domain_http2.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['http2'] ], 'override_tls' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; $userinfo['change_serversettings'] == '1', 'label' =&gt; lng('admin.domain_override_tls'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['override_tls'] ], 'ssl_protocols' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; $userinfo['change_serversettings'] == '1' &amp;&amp; settings::get('system.webserver') != 'lighttpd', 'label' =&gt; lng('serversettings.ssl.ssl_protocols.title'), 'desc' =&gt; lng('serversettings.ssl.ssl_protocols.description').lng('admin.domain_override_tls_addinfo'), 'type' =&gt; 'checkbox', 'value' =&gt; !empty($result['ssl_protocols']) ? explode(",", $result['ssl_protocols']) : explode(",", settings::get('system.ssl_protocols')), 'values' =&gt; [ [ 'value' =&gt; 'tlsv1', 'label' =&gt; 'tlsv1' ], [ 'value' =&gt; 'tlsv1.1', 'label' =&gt; 'tlsv1.1' ], [ 'value' =&gt; 'tlsv1.2', 'label' =&gt; 'tlsv1.2' ], [ 'value' =&gt; 'tlsv1.3', 'label' =&gt; 'tlsv1.3' ] ], 'is_array' =&gt; 1 ], 'ssl_cipher_list' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; $userinfo['change_serversettings'] == '1', 'label' =&gt; lng('serversettings.ssl.ssl_cipher_list.title'), 'desc' =&gt; lng('serversettings.ssl.ssl_cipher_list.description').lng('admin.domain_override_tls_addinfo'), 'type' =&gt; 'text', 'value' =&gt; !empty($result['ssl_cipher_list']) ? $result['ssl_cipher_list'] : settings::get('system.ssl_cipher_list') ], 'tlsv13_cipher_list' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; $userinfo['change_serversettings'] == '1' &amp;&amp; settings::get('system.webserver') == "apache2" &amp;&amp; settings::get('system.apache24') == 1, 'label' =&gt; lng('serversettings.ssl.tlsv13_cipher_list.title'), 'desc' =&gt; lng('serversettings.ssl.tlsv13_cipher_list.description').lng('admin.domain_override_tls_addinfo'), 'type' =&gt; 'text', 'value' =&gt; !empty($result['tlsv13_cipher_list']) ? $result['tlsv13_cipher_list'] : settings::get('system.tlsv13_cipher_list') ], 'ssl_specialsettings' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; $userinfo['change_serversettings'] == '1', 'label' =&gt; lng('admin.ownsslvhostsettings'), 'desc' =&gt; lng('serversettings.default_vhostconf.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12, 'value' =&gt; $result['ssl_specialsettings'] ], 'include_specialsettings' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; $userinfo['change_serversettings'] == '1', 'label' =&gt; lng('serversettings.includedefault_sslvhostconf'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['include_specialsettings'] ], 'hsts_maxage' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('admin.domain_hsts_maxage.title'), 'desc' =&gt; lng('admin.domain_hsts_maxage.description'), 'type' =&gt; 'number', 'min' =&gt; 0, 'max' =&gt; 94608000, // 3-years 'value' =&gt; $result['hsts'] ], 'hsts_sub' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('admin.domain_hsts_incsub.title'), 'desc' =&gt; lng('admin.domain_hsts_incsub.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['hsts_sub'] ], 'hsts_preload' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('admin.domain_hsts_preload.title'), 'desc' =&gt; lng('admin.domain_hsts_preload.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['hsts_preload'] ], 'ocsp_stapling' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; settings::get('system.webserver') != 'lighttpd', 'label' =&gt; lng('admin.domain_ocsp_stapling.title'), 'desc' =&gt; lng('admin.domain_ocsp_stapling.description') . (settings::get('system.webserver') == 'nginx' ? lng('admin.domain_ocsp_stapling.nginx_version_warning') : ""), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['ocsp_stapling'] ], 'honorcipherorder' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports), 'label' =&gt; lng('admin.domain_honorcipherorder'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['ssl_honorcipherorder'] ], 'sessiontickets' =&gt; [ 'visible' =&gt; !empty($ssl_ipsandports) &amp;&amp; settings::get('system.webserver') != 'lighttpd' &amp;&amp; settings::get('system.sessionticketsenabled' != '1'), 'label' =&gt; lng('admin.domain_sessiontickets'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['ssl_sessiontickets'] ] ] ], 'section_c' =&gt; [ 'title' =&gt; lng('admin.phpserversettings'), 'image' =&gt; 'icons/domain_edit.png', 'visible' =&gt; $userinfo['change_serversettings'] == '1' || $userinfo['caneditphpsettings'] == '1', 'fields' =&gt; [ 'openbasedir' =&gt; [ 'label' =&gt; 'openbasedir', 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['openbasedir'] ], 'openbasedir_path' =&gt; [ 'label' =&gt; lng('domain.openbasedirpath'), 'type' =&gt; 'select', 'select_var' =&gt; $openbasedir, 'selected' =&gt; $result['openbasedir_path'] ], 'phpenabled' =&gt; [ 'label' =&gt; lng('admin.phpenabled'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['phpenabled'] ], 'phpsettingid' =&gt; [ 'visible' =&gt; (((int)settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1)), 'label' =&gt; lng('admin.phpsettings.title'), 'type' =&gt; 'select', 'select_var' =&gt; $phpconfigs, 'selected' =&gt; $result['phpsettingid'] ], 'phpsettingsforsubdomains' =&gt; [ 'visible' =&gt; $userinfo['change_serversettings'] == '1', 'label' =&gt; lng('admin.phpsettingsforsubdomains'), 'desc' =&gt; lng('serversettings.phpsettingsforsubdomains.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; settings::get('system.apply_phpconfigs_default') == 1 ? '1' : '0' ], 'mod_fcgid_starter' =&gt; [ 'visible' =&gt; (int)settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.mod_fcgid_starter.title'), 'type' =&gt; 'number', 'value' =&gt; ((int)$result['mod_fcgid_starter'] != -1 ? $result['mod_fcgid_starter'] : '') ], 'mod_fcgid_maxrequests' =&gt; [ 'visible' =&gt; (int)settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.mod_fcgid_maxrequests.title'), 'type' =&gt; 'number', 'value' =&gt; ((int)$result['mod_fcgid_maxrequests'] != -1 ? $result['mod_fcgid_maxrequests'] : '') ] ] ], 'section_d' =&gt; [ 'title' =&gt; lng('admin.nameserversettings'), 'image' =&gt; 'icons/domain_edit.png', 'visible' =&gt; ($userinfo['change_serversettings'] == '1' &amp;&amp; settings::get('system.bind_enable') == '1') || ($result['isemaildomain'] == '1' &amp;&amp; (settings::get('spf.use_spf') == '1' || settings::get('dmarc.use_dmarc') == '1' || (settings::get('antispam.activated') == '1' &amp;&amp; $result['dkim'] == '1' &amp;&amp; $result['dkim_pubkey'] != ''))), 'fields' =&gt; [ 'isbinddomain' =&gt; [ 'visible' =&gt; $userinfo['change_serversettings'] == '1' &amp;&amp; settings::get('system.bind_enable') == '1', 'label' =&gt; lng('admin.createzonefile'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['isbinddomain'] ], 'zonefile' =&gt; [ 'visible' =&gt; $userinfo['change_serversettings'] == '1' &amp;&amp; settings::get('system.bind_enable') == '1', 'label' =&gt; lng('admin.custombindzone'), 'desc' =&gt; lng('admin.bindzonewarning'), 'type' =&gt; 'text', 'value' =&gt; $result['zonefile'] ], 'spf_entry' =&gt; [ 'visible' =&gt; (settings::get('spf.use_spf') == '1' &amp;&amp; $result['isemaildomain'] == '1'), 'label' =&gt; lng('antispam.required_spf_dns'), 'type' =&gt; 'longtext', 'value' =&gt; (string)(new \froxlor\dns\dnsentry('@', 'txt', \froxlor\dns\dns::enclosetxtcontent(settings::get('spf.spf_entry')))) ], 'dmarc_entry' =&gt; [ 'visible' =&gt; (settings::get('dmarc.use_dmarc') == '1' &amp;&amp; $result['isemaildomain'] == '1'), 'label' =&gt; lng('antispam.required_dmarc_dns'), 'type' =&gt; 'longtext', 'value' =&gt; (string)(new \froxlor\dns\dnsentry('_dmarc', 'txt', \froxlor\dns\dns::enclosetxtcontent(settings::get('dmarc.dmarc_entry')))) ], 'dkim_entry' =&gt; [ 'visible' =&gt; (settings::get('antispam.activated') == '1' &amp;&amp; $result['dkim'] == '1' &amp;&amp; $result['dkim_pubkey'] != '' &amp;&amp; $result['isemaildomain'] == '1'), 'label' =&gt; lng('antispam.required_dkim_dns'), 'type' =&gt; 'longtext', 'value' =&gt; (string)(new \froxlor\dns\dnsentry('dkim' . $result['dkim_id'] . '._domainkey', 'txt', \froxlor\dns\dns::enclosetxtcontent('v=dkim1; k=rsa; p='.trim($result['dkim_pubkey'])))) ], ] ] ] ] ];</file><file name="lib/formfields/admin/domains/index.html" /><file name="lib/formfields/admin/messages/formfield.messages_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'messages_add' =&gt; [ 'title' =&gt; lng('admin.message'), 'image' =&gt; 'fa-solid fa-paper-plane', 'sections' =&gt; [ 'section_a' =&gt; [ 'fields' =&gt; [ 'recipient' =&gt; [ 'label' =&gt; lng('admin.recipient'), 'type' =&gt; 'select', 'select_var' =&gt; $recipients, 'selected' =&gt; 1 ], 'subject' =&gt; [ 'label' =&gt; lng('admin.subject'), 'type' =&gt; 'text', 'value' =&gt; lng('admin.nosubject'), 'mandatory' =&gt; true ], 'message' =&gt; [ 'label' =&gt; lng('admin.text'), 'type' =&gt; 'textarea', 'mandatory' =&gt; true ] ] ] ], 'buttons' =&gt; [ [ 'label' =&gt; lng('admin.message') ] ] ] ];</file><file name="lib/formfields/admin/messages/index.html" /><file name="lib/formfields/admin/templates/template.replacers.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'replacers' =&gt; [ [ 'var' =&gt; 'salutation', 'description' =&gt; lng('admin.templates.salutation') ], [ 'var' =&gt; 'firstname', 'description' =&gt; lng('admin.templates.firstname') ], [ 'var' =&gt; 'name', 'description' =&gt; lng('admin.templates.name') ], [ 'var' =&gt; 'company', 'description' =&gt; lng('admin.templates.company') ], [ 'var' =&gt; 'customer_no', 'description' =&gt; lng('admin.templates.customer_no') ], [ 'var' =&gt; 'username', 'description' =&gt; lng('admin.templates.username') ], [ 'var' =&gt; 'password', 'description' =&gt; lng('admin.templates.password'), 'visible' =&gt; $template == 'createcustomer' ], [ 'var' =&gt; 'email', 'description' =&gt; lng('admin.templates.email'), 'visible' =&gt; $template == 'pop_success' ], [ 'var' =&gt; 'password', 'description' =&gt; lng('admin.templates.email_password'), 'visible' =&gt; $template == 'pop_success' ], [ 'var' =&gt; 'link', 'description' =&gt; lng('admin.templates.link'), 'visible' =&gt; $template == 'password_reset' ], [ 'var' =&gt; 'traffic', 'description' =&gt; lng('admin.templates.traffic'), 'visible' =&gt; $template == 'trafficmaxpercent' ], [ 'var' =&gt; 'trafficused', 'description' =&gt; lng('admin.templates.trafficused'), 'visible' =&gt; $template == 'trafficmaxpercent' ], [ 'var' =&gt; 'diskavailable', 'description' =&gt; lng('admin.templates.diskavailable'), 'visible' =&gt; $template == 'diskmaxpercent' ], [ 'var' =&gt; 'diskused', 'description' =&gt; lng('admin.templates.diskused'), 'visible' =&gt; $template == 'diskmaxpercent' ], [ 'var' =&gt; 'max_percent', 'description' =&gt; lng('admin.templates.max_percent'), 'visible' =&gt; $template == 'trafficmaxpercent' || $template == 'diskmaxpercent' ], [ 'var' =&gt; 'usage_percent', 'description' =&gt; lng('admin.templates.usage_percent'), 'visible' =&gt; $template == 'trafficmaxpercent' || $template == 'diskmaxpercent' ], [ 'var' =&gt; 'db_name', 'description' =&gt; lng('admin.templates.db_name'), 'visible' =&gt; $template == 'new_database_by_customer' ], [ 'var' =&gt; 'db_pass', 'description' =&gt; lng('admin.templates.db_pass'), 'visible' =&gt; $template == 'new_database_by_customer' ], [ 'var' =&gt; 'db_desc', 'description' =&gt; lng('admin.templates.db_desc'), 'visible' =&gt; $template == 'new_database_by_customer' ], [ 'var' =&gt; 'db_srv', 'description' =&gt; lng('admin.templates.db_srv'), 'visible' =&gt; $template == 'new_database_by_customer' ], [ 'var' =&gt; 'pma_uri', 'description' =&gt; lng('admin.templates.pma_uri'), 'visible' =&gt; $template == 'new_database_by_customer' ], [ 'var' =&gt; 'usr_name', 'description' =&gt; lng('admin.templates.usr_name'), 'visible' =&gt; $template == 'new_ftpaccount_by_customer' ], [ 'var' =&gt; 'usr_pass', 'description' =&gt; lng('admin.templates.usr_pass'), 'visible' =&gt; $template == 'new_ftpaccount_by_customer' ], [ 'var' =&gt; 'usr_path', 'description' =&gt; lng('admin.templates.usr_path'), 'visible' =&gt; $template == 'new_ftpaccount_by_customer' ] ] ];</file><file name="lib/formfields/admin/templates/formfield.template_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'template_add' =&gt; [ 'title' =&gt; lng('admin.templates.template_add'), 'image' =&gt; 'fa-solid fa-plus', 'self_overview' =&gt; ['section' =&gt; 'templates', 'page' =&gt; 'email', 'action' =&gt; 'add'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.templates.template_add'), 'image' =&gt; 'icons/templates_add.png', 'fields' =&gt; [ 'language' =&gt; [ 'label' =&gt; lng('login.language'), 'type' =&gt; 'hidden', 'value' =&gt; $language, 'display' =&gt; $language ], 'template' =&gt; [ 'label' =&gt; lng('admin.templates.action'), 'type' =&gt; 'hidden', 'value' =&gt; $template, 'display' =&gt; lng('admin.templates.' . $template) ], 'subject' =&gt; [ 'label' =&gt; lng('admin.templates.subject'), 'type' =&gt; 'text', 'value' =&gt; $subject ], 'mailbody' =&gt; [ 'label' =&gt; lng('admin.templates.mailbody'), 'type' =&gt; 'textarea', 'value' =&gt; $body, 'cols' =&gt; 60, 'rows' =&gt; 12 ] ] ] ] ], 'template_replacers' =&gt; include __dir__ . '/template.replacers.php' ];</file><file name="lib/formfields/admin/templates/formfield.template_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'template_edit' =&gt; [ 'title' =&gt; lng('admin.templates.template_edit'), 'image' =&gt; 'fa-solid fa-pen', 'self_overview' =&gt; ['section' =&gt; 'templates', 'page' =&gt; 'email'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.templates.template_edit'), 'image' =&gt; 'icons/templates_edit.png', 'fields' =&gt; [ 'language' =&gt; [ 'label' =&gt; lng('login.language'), 'type' =&gt; 'hidden', 'value' =&gt; $language, 'display' =&gt; $language ], 'template' =&gt; [ 'label' =&gt; lng('admin.templates.action'), 'type' =&gt; 'hidden', 'value' =&gt; $template_name, 'display' =&gt; $template_name ], 'subject' =&gt; [ 'label' =&gt; lng('admin.templates.subject'), 'type' =&gt; 'text', 'value' =&gt; $subject ], 'mailbody' =&gt; [ 'label' =&gt; lng('admin.templates.mailbody'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12, 'value' =&gt; $mailbody ], 'subjectid' =&gt; [ 'type' =&gt; 'hidden', 'value' =&gt; $subjectid ], 'mailbodyid' =&gt; [ 'type' =&gt; 'hidden', 'value' =&gt; $mailbodyid ] ] ] ] ], 'template_replacers' =&gt; include __dir__ . '/template.replacers.php' ];</file><file name="lib/formfields/admin/templates/formfield.filetemplate_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'filetemplate_edit' =&gt; [ 'title' =&gt; lng('admin.templates.template_edit'), 'image' =&gt; 'fa-solid fa-pen', 'self_overview' =&gt; ['section' =&gt; 'templates', 'page' =&gt; 'email'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.templates.template_edit'), 'image' =&gt; 'icons/templates_edit.png', 'fields' =&gt; [ 'template' =&gt; [ 'label' =&gt; lng('admin.templates.action'), 'type' =&gt; 'hidden', 'value' =&gt; lng('admin.templates.' . $row['varname']), 'display' =&gt; lng('admin.templates.' . $row['varname']) ], 'file_extension' =&gt; [ 'label' =&gt; lng('admin.templates.file_extension'), 'type' =&gt; 'text', 'string_regexp' =&gt; '/^[a-za-z0-9]{1,6}$/', 'value' =&gt; $row['file_extension'], 'default' =&gt; 'html', 'mandatory' =&gt; true ], 'filecontent' =&gt; [ 'label' =&gt; lng('admin.templates.filecontent'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12, 'value' =&gt; $row['value'], 'mandatory' =&gt; true ], 'filesend' =&gt; [ 'type' =&gt; 'hidden', 'value' =&gt; 'filesend' ] ] ] ] ], 'filetemplate_replacers' =&gt; [ 'replacers' =&gt; [ [ 'var' =&gt; 'servername', 'description' =&gt; lng('admin.templates.servername') ], [ 'var' =&gt; 'customer', 'description' =&gt; lng('admin.templates.customer') ], [ 'var' =&gt; 'admin', 'description' =&gt; lng('admin.templates.admin') ], [ 'var' =&gt; 'customer_email', 'description' =&gt; lng('admin.templates.customer_email') ], [ 'var' =&gt; 'admin_email', 'description' =&gt; lng('admin.templates.admin_email') ] ] ] ];</file><file name="lib/formfields/admin/templates/formfield.filetemplate_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'filetemplate_add' =&gt; [ 'title' =&gt; lng('admin.templates.template_add'), 'image' =&gt; 'fa-solid fa-plus', 'self_overview' =&gt; ['section' =&gt; 'templates', 'page' =&gt; 'email'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.templates.template_add'), 'image' =&gt; 'icons/templates_add.png', 'fields' =&gt; [ 'template' =&gt; [ 'label' =&gt; lng('admin.templates.action'), 'type' =&gt; 'select', 'select_var' =&gt; $free_templates ], 'file_extension' =&gt; [ 'label' =&gt; lng('admin.templates.file_extension'), 'type' =&gt; 'text', 'string_regexp' =&gt; '/^[a-za-z0-9]{1,6}$/', 'default' =&gt; 'html', 'value' =&gt; 'html', 'mandatory' =&gt; true ], 'filecontent' =&gt; [ 'label' =&gt; lng('admin.templates.filecontent'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12, 'mandatory' =&gt; true ], 'filesend' =&gt; [ 'type' =&gt; 'hidden', 'value' =&gt; 'filesend' ] ] ] ] ], 'filetemplate_replacers' =&gt; [ 'replacers' =&gt; [ [ 'var' =&gt; 'servername', 'description' =&gt; lng('admin.templates.servername') ], [ 'var' =&gt; 'customer', 'description' =&gt; lng('admin.templates.customer') ], [ 'var' =&gt; 'admin', 'description' =&gt; lng('admin.templates.admin') ], [ 'var' =&gt; 'customer_email', 'description' =&gt; lng('admin.templates.customer_email') ], [ 'var' =&gt; 'admin_email', 'description' =&gt; lng('admin.templates.admin_email') ] ] ] ];</file><file name="lib/formfields/admin/templates/index.html" /><file name="lib/formfields/admin/phpconfig/formfield.fpmconfig_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'fpmconfig_add' =&gt; [ 'title' =&gt; lng('admin.fpmsettings.addnew'), 'image' =&gt; 'fa-solid fa-plus', 'self_overview' =&gt; ['section' =&gt; 'phpsettings', 'page' =&gt; 'fpmdaemons'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.fpmsettings.addnew'), 'image' =&gt; 'icons/phpsettings_add.png', 'fields' =&gt; [ 'description' =&gt; [ 'label' =&gt; lng('admin.phpsettings.description'), 'type' =&gt; 'text', 'maxlength' =&gt; 50, 'mandatory' =&gt; true ], 'reload_cmd' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.reload'), 'type' =&gt; 'text', 'maxlength' =&gt; 255, 'value' =&gt; 'service php7.4-fpm restart', 'mandatory' =&gt; true, 'required_otp' =&gt; true ], 'config_dir' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.configdir'), 'type' =&gt; 'text', 'maxlength' =&gt; 255, 'value' =&gt; '/etc/php/7.4/fpm/pool.d/', 'mandatory' =&gt; true ], 'pm' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.pm'), 'type' =&gt; 'select', 'select_var' =&gt; [ 'static' =&gt; 'static', 'dynamic' =&gt; 'dynamic', 'ondemand' =&gt; 'ondemand' ] ], 'max_children' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.max_children.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.max_children.description'), 'type' =&gt; 'number', 'value' =&gt; 5, 'min' =&gt; 1 ], 'start_servers' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.start_servers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.start_servers.description'), 'type' =&gt; 'number', 'value' =&gt; 2, 'min' =&gt; 1 ], 'min_spare_servers' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.min_spare_servers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.min_spare_servers.description'), 'type' =&gt; 'number', 'value' =&gt; 1 ], 'max_spare_servers' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.max_spare_servers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.max_spare_servers.description'), 'type' =&gt; 'number', 'value' =&gt; 3 ], 'max_requests' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.max_requests.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.max_requests.description'), 'type' =&gt; 'number', 'value' =&gt; 0 ], 'idle_timeout' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.idle_timeout.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.idle_timeout.description'), 'type' =&gt; 'number', 'value' =&gt; 10 ], 'limit_extensions' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.limit_extensions.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.limit_extensions.description'), 'type' =&gt; 'text', 'value' =&gt; '.php' ], 'custom_config' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.custom_config.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.custom_config.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 50, 'rows' =&gt; 7 ] ] ] ] ], 'fpmconfig_replacers' =&gt; [ 'replacers' =&gt; [ [ 'var' =&gt; 'pear_dir', 'description' =&gt; lng('admin.phpconfig.pear_dir') ], [ 'var' =&gt; 'open_basedir_c', 'description' =&gt; lng('admin.phpconfig.open_basedir_c') ], [ 'var' =&gt; 'open_basedir', 'description' =&gt; lng('admin.phpconfig.open_basedir') ], [ 'var' =&gt; 'open_basedir_global', 'description' =&gt; lng('admin.phpconfig.open_basedir_global') ], [ 'var' =&gt; 'tmp_dir', 'description' =&gt; lng('admin.phpconfig.tmp_dir') ], [ 'var' =&gt; 'customer_email', 'description' =&gt; lng('admin.phpconfig.customer_email') ], [ 'var' =&gt; 'admin_email', 'description' =&gt; lng('admin.phpconfig.admin_email') ], [ 'var' =&gt; 'domain', 'description' =&gt; lng('admin.phpconfig.domain') ], [ 'var' =&gt; 'customer', 'description' =&gt; lng('admin.phpconfig.customer') ], [ 'var' =&gt; 'admin', 'description' =&gt; lng('admin.phpconfig.admin') ], [ 'var' =&gt; 'document_root', 'description' =&gt; lng('admin.phpconfig.docroot') ], [ 'var' =&gt; 'customer_homedir', 'description' =&gt; lng('admin.phpconfig.homedir') ] ] ] ];</file><file name="lib/formfields/admin/phpconfig/formfield.phpconfig_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'phpconfig_add' =&gt; [ 'title' =&gt; lng('admin.phpsettings.addsettings'), 'image' =&gt; 'fa-solid fa-plus', 'self_overview' =&gt; ['section' =&gt; 'phpsettings', 'page' =&gt; 'overview'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.phpsettings.addsettings'), 'image' =&gt; 'icons/phpsettings_add.png', 'fields' =&gt; [ 'description' =&gt; [ 'label' =&gt; lng('admin.phpsettings.description'), 'type' =&gt; 'text', 'maxlength' =&gt; 50, 'mandatory' =&gt; true ], 'binary' =&gt; [ 'visible' =&gt; settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.phpsettings.binary'), 'type' =&gt; 'text', 'maxlength' =&gt; 255, 'value' =&gt; '/usr/bin/php-cgi', 'required_otp' =&gt; true ], 'fpmconfig' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('admin.phpsettings.fpmdesc'), 'type' =&gt; 'select', 'select_var' =&gt; $fpmconfigs, 'selected' =&gt; 1 ], 'file_extensions' =&gt; [ 'visible' =&gt; settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.phpsettings.file_extensions'), 'desc' =&gt; lng('admin.phpsettings.file_extensions_note'), 'type' =&gt; 'text', 'maxlength' =&gt; 255, 'value' =&gt; 'php', 'required_otp' =&gt; true ], 'mod_fcgid_starter' =&gt; [ 'visible' =&gt; settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.mod_fcgid_starter.title'), 'type' =&gt; 'number' ], 'mod_fcgid_maxrequests' =&gt; [ 'visible' =&gt; settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.mod_fcgid_maxrequests.title'), 'type' =&gt; 'number' ], 'mod_fcgid_umask' =&gt; [ 'visible' =&gt; settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.mod_fcgid_umask.title'), 'type' =&gt; 'text', 'maxlength' =&gt; 3, 'value' =&gt; '022' ], 'phpfpm_enable_slowlog' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('admin.phpsettings.enable_slowlog'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'phpfpm_reqtermtimeout' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('admin.phpsettings.request_terminate_timeout'), 'type' =&gt; 'text', 'maxlength' =&gt; 10, 'value' =&gt; '60s' ], 'phpfpm_reqslowtimeout' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('admin.phpsettings.request_slowlog_timeout'), 'type' =&gt; 'text', 'maxlength' =&gt; 10, 'value' =&gt; '5s' ], 'pass_authorizationheader' =&gt; [ 'visible' =&gt; settings::get('system.webserver') == "apache2", 'label' =&gt; lng('admin.phpsettings.pass_authorizationheader'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'override_fpmconfig' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.override_fpmconfig'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'pm' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.pm'), 'desc' =&gt; lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'select', 'select_var' =&gt; [ 'static' =&gt; 'static', 'dynamic' =&gt; 'dynamic', 'ondemand' =&gt; 'ondemand' ] ], 'max_children' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.max_children.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.max_children.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'number', 'value' =&gt; 1 ], 'start_servers' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.start_servers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.start_servers.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'number', 'value' =&gt; 20 ], 'min_spare_servers' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.min_spare_servers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.min_spare_servers.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'number', 'value' =&gt; 5 ], 'max_spare_servers' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.max_spare_servers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.max_spare_servers.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'number', 'value' =&gt; 35 ], 'max_requests' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.max_requests.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.max_requests.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'number', 'value' =&gt; 0 ], 'idle_timeout' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.idle_timeout.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.idle_timeout.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'number', 'value' =&gt; 10 ], 'limit_extensions' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.limit_extensions.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.limit_extensions.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'text', 'value' =&gt; '.php' ], 'phpsettings' =&gt; [ 'label' =&gt; lng('admin.phpsettings.phpinisettings'), 'type' =&gt; 'textarea', 'cols' =&gt; 80, 'rows' =&gt; 20, 'value' =&gt; $result['phpsettings'], 'mandatory' =&gt; true, 'required_otp' =&gt; true ], 'allow_all_customers' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.allow_all_customers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.allow_all_customers.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ] ] ] ] ], 'phpconfig_replacers' =&gt; [ 'replacers' =&gt; [ [ 'var' =&gt; 'pear_dir', 'description' =&gt; lng('admin.phpconfig.pear_dir') ], [ 'var' =&gt; 'open_basedir_c', 'description' =&gt; lng('admin.phpconfig.open_basedir_c') ], [ 'var' =&gt; 'open_basedir', 'description' =&gt; lng('admin.phpconfig.open_basedir') ], [ 'var' =&gt; 'open_basedir_global', 'description' =&gt; lng('admin.phpconfig.open_basedir_global') ], [ 'var' =&gt; 'tmp_dir', 'description' =&gt; lng('admin.phpconfig.tmp_dir') ], [ 'var' =&gt; 'customer_email', 'description' =&gt; lng('admin.phpconfig.customer_email') ], [ 'var' =&gt; 'admin_email', 'description' =&gt; lng('admin.phpconfig.admin_email') ], [ 'var' =&gt; 'domain', 'description' =&gt; lng('admin.phpconfig.domain') ], [ 'var' =&gt; 'customer', 'description' =&gt; lng('admin.phpconfig.customer') ], [ 'var' =&gt; 'admin', 'description' =&gt; lng('admin.phpconfig.admin') ], [ 'var' =&gt; 'document_root', 'description' =&gt; lng('admin.phpconfig.docroot') ], [ 'var' =&gt; 'customer_homedir', 'description' =&gt; lng('admin.phpconfig.homedir') ] ] ] ];</file><file name="lib/formfields/admin/phpconfig/formfield.phpconfig_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; return [ 'phpconfig_edit' =&gt; [ 'title' =&gt; lng('admin.phpsettings.editsettings'), 'image' =&gt; 'fa-solid fa-pen', 'self_overview' =&gt; ['section' =&gt; 'phpsettings', 'page' =&gt; 'overview'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.phpsettings.editsettings'), 'image' =&gt; 'icons/phpsettings_edit.png', 'fields' =&gt; [ 'description' =&gt; [ 'label' =&gt; lng('admin.phpsettings.description'), 'type' =&gt; 'text', 'maxlength' =&gt; 50, 'value' =&gt; $result['description'], 'mandatory' =&gt; true ], 'binary' =&gt; [ 'visible' =&gt; settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.phpsettings.binary'), 'type' =&gt; 'text', 'maxlength' =&gt; 255, 'value' =&gt; $result['binary'], 'required_otp' =&gt; true ], 'fpmconfig' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('admin.phpsettings.fpmdesc'), 'type' =&gt; 'select', 'select_var' =&gt; $fpmconfigs, 'selected' =&gt; $result['fpmsettingid'] ], 'file_extensions' =&gt; [ 'visible' =&gt; settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.phpsettings.file_extensions'), 'desc' =&gt; lng('admin.phpsettings.file_extensions_note'), 'type' =&gt; 'text', 'maxlength' =&gt; 255, 'value' =&gt; $result['file_extensions'], 'required_otp' =&gt; true ], 'mod_fcgid_starter' =&gt; [ 'visible' =&gt; settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.mod_fcgid_starter.title'), 'type' =&gt; 'number', 'value' =&gt; ((int)$result['mod_fcgid_starter'] != -1 ? $result['mod_fcgid_starter'] : '') ], 'mod_fcgid_maxrequests' =&gt; [ 'visible' =&gt; settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.mod_fcgid_maxrequests.title'), 'type' =&gt; 'number', 'value' =&gt; ((int)$result['mod_fcgid_maxrequests'] != -1 ? $result['mod_fcgid_maxrequests'] : '') ], 'mod_fcgid_umask' =&gt; [ 'visible' =&gt; settings::get('system.mod_fcgid') == 1, 'label' =&gt; lng('admin.mod_fcgid_umask.title'), 'type' =&gt; 'text', 'maxlength' =&gt; 3, 'value' =&gt; $result['mod_fcgid_umask'] ], 'phpfpm_enable_slowlog' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('admin.phpsettings.enable_slowlog'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['fpm_slowlog'] ], 'phpfpm_reqtermtimeout' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('admin.phpsettings.request_terminate_timeout'), 'type' =&gt; 'text', 'maxlength' =&gt; 10, 'value' =&gt; $result['fpm_reqterm'] ], 'phpfpm_reqslowtimeout' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('admin.phpsettings.request_slowlog_timeout'), 'type' =&gt; 'text', 'maxlength' =&gt; 10, 'value' =&gt; $result['fpm_reqslow'] ], 'pass_authorizationheader' =&gt; [ 'visible' =&gt; settings::get('system.webserver') == "apache2", 'label' =&gt; lng('admin.phpsettings.pass_authorizationheader'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['pass_authorizationheader'] ], 'override_fpmconfig' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.override_fpmconfig'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['override_fpmconfig'] ], 'pm' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.pm'), 'desc' =&gt; lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'select', 'select_var' =&gt; [ 'static' =&gt; 'static', 'dynamic' =&gt; 'dynamic', 'ondemand' =&gt; 'ondemand' ], 'selected' =&gt; $result['pm'] ], 'max_children' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.max_children.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.max_children.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'number', 'value' =&gt; $result['max_children'] ], 'start_servers' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.start_servers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.start_servers.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'number', 'value' =&gt; $result['start_servers'] ], 'min_spare_servers' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.min_spare_servers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.min_spare_servers.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'number', 'value' =&gt; $result['min_spare_servers'] ], 'max_spare_servers' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.max_spare_servers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.max_spare_servers.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'number', 'value' =&gt; $result['max_spare_servers'] ], 'max_requests' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.max_requests.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.max_requests.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'number', 'value' =&gt; $result['max_requests'] ], 'idle_timeout' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.idle_timeout.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.idle_timeout.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'number', 'value' =&gt; $result['idle_timeout'] ], 'limit_extensions' =&gt; [ 'visible' =&gt; settings::get('phpfpm.enabled') == 1, 'label' =&gt; lng('serversettings.phpfpm_settings.limit_extensions.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.limit_extensions.description') . lng('serversettings.phpfpm_settings.override_fpmconfig_addinfo'), 'type' =&gt; 'text', 'value' =&gt; $result['limit_extensions'] ], 'phpsettings' =&gt; [ 'label' =&gt; lng('admin.phpsettings.phpinisettings'), 'type' =&gt; 'textarea', 'cols' =&gt; 80, 'rows' =&gt; 20, 'value' =&gt; $result['phpsettings'], 'mandatory' =&gt; true, 'required_otp' =&gt; true ], 'allow_all_customers' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.allow_all_customers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.allow_all_customers.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ] ] ] ] ], 'phpconfig_replacers' =&gt; [ 'replacers' =&gt; [ [ 'var' =&gt; 'pear_dir', 'description' =&gt; lng('admin.phpconfig.pear_dir') ], [ 'var' =&gt; 'open_basedir_c', 'description' =&gt; lng('admin.phpconfig.open_basedir_c') ], [ 'var' =&gt; 'open_basedir', 'description' =&gt; lng('admin.phpconfig.open_basedir') ], [ 'var' =&gt; 'open_basedir_global', 'description' =&gt; lng('admin.phpconfig.open_basedir_global') ], [ 'var' =&gt; 'tmp_dir', 'description' =&gt; lng('admin.phpconfig.tmp_dir') ], [ 'var' =&gt; 'customer_email', 'description' =&gt; lng('admin.phpconfig.customer_email') ], [ 'var' =&gt; 'admin_email', 'description' =&gt; lng('admin.phpconfig.admin_email') ], [ 'var' =&gt; 'domain', 'description' =&gt; lng('admin.phpconfig.domain') ], [ 'var' =&gt; 'customer', 'description' =&gt; lng('admin.phpconfig.customer') ], [ 'var' =&gt; 'admin', 'description' =&gt; lng('admin.phpconfig.admin') ], [ 'var' =&gt; 'document_root', 'description' =&gt; lng('admin.phpconfig.docroot') ], [ 'var' =&gt; 'customer_homedir', 'description' =&gt; lng('admin.phpconfig.homedir') ] ] ] ];</file><file name="lib/formfields/admin/phpconfig/index.html" /><file name="lib/formfields/admin/phpconfig/formfield.fpmconfig_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'fpmconfig_edit' =&gt; [ 'title' =&gt; lng('admin.fpmsettings.edit'), 'image' =&gt; 'fa-solid fa-pen', 'self_overview' =&gt; ['section' =&gt; 'phpsettings', 'page' =&gt; 'fpmdaemons'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.fpmsettings.edit'), 'image' =&gt; 'icons/phpsettings_edit.png', 'fields' =&gt; [ 'description' =&gt; [ 'label' =&gt; lng('admin.phpsettings.description'), 'type' =&gt; 'text', 'maxlength' =&gt; 50, 'value' =&gt; $result['description'], 'mandatory' =&gt; true ], 'reload_cmd' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.reload'), 'type' =&gt; 'text', 'maxlength' =&gt; 255, 'value' =&gt; $result['reload_cmd'], 'mandatory' =&gt; true, 'required_otp' =&gt; true ], 'config_dir' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.configdir'), 'type' =&gt; 'text', 'maxlength' =&gt; 255, 'value' =&gt; $result['config_dir'], 'mandatory' =&gt; true ], 'pm' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.pm'), 'type' =&gt; 'select', 'select_var' =&gt; [ 'static' =&gt; 'static', 'dynamic' =&gt; 'dynamic', 'ondemand' =&gt; 'ondemand' ], 'selected' =&gt; $result['pm'] ], 'max_children' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.max_children.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.max_children.description'), 'type' =&gt; 'number', 'value' =&gt; $result['max_children'], 'min' =&gt; 1 ], 'start_servers' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.start_servers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.start_servers.description'), 'type' =&gt; 'number', 'value' =&gt; $result['start_servers'], 'min' =&gt; 1 ], 'min_spare_servers' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.min_spare_servers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.min_spare_servers.description'), 'type' =&gt; 'number', 'value' =&gt; $result['min_spare_servers'] ], 'max_spare_servers' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.max_spare_servers.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.max_spare_servers.description'), 'type' =&gt; 'number', 'value' =&gt; $result['max_spare_servers'] ], 'max_requests' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.max_requests.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.max_requests.description'), 'type' =&gt; 'number', 'value' =&gt; $result['max_requests'] ], 'idle_timeout' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.idle_timeout.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.idle_timeout.description'), 'type' =&gt; 'number', 'value' =&gt; $result['idle_timeout'] ], 'limit_extensions' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.limit_extensions.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.limit_extensions.description'), 'type' =&gt; 'text', 'value' =&gt; $result['limit_extensions'] ], 'custom_config' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.custom_config.title'), 'desc' =&gt; lng('serversettings.phpfpm_settings.custom_config.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 50, 'rows' =&gt; 7, 'value' =&gt; $result['custom_config'] ] ] ] ] ], 'fpmconfig_replacers' =&gt; [ 'replacers' =&gt; [ [ 'var' =&gt; 'pear_dir', 'description' =&gt; lng('admin.phpconfig.pear_dir') ], [ 'var' =&gt; 'open_basedir_c', 'description' =&gt; lng('admin.phpconfig.open_basedir_c') ], [ 'var' =&gt; 'open_basedir', 'description' =&gt; lng('admin.phpconfig.open_basedir') ], [ 'var' =&gt; 'open_basedir_global', 'description' =&gt; lng('admin.phpconfig.open_basedir_global') ], [ 'var' =&gt; 'tmp_dir', 'description' =&gt; lng('admin.phpconfig.tmp_dir') ], [ 'var' =&gt; 'customer_email', 'description' =&gt; lng('admin.phpconfig.customer_email') ], [ 'var' =&gt; 'admin_email', 'description' =&gt; lng('admin.phpconfig.admin_email') ], [ 'var' =&gt; 'domain', 'description' =&gt; lng('admin.phpconfig.domain') ], [ 'var' =&gt; 'customer', 'description' =&gt; lng('admin.phpconfig.customer') ], [ 'var' =&gt; 'admin', 'description' =&gt; lng('admin.phpconfig.admin') ], [ 'var' =&gt; 'document_root', 'description' =&gt; lng('admin.phpconfig.docroot') ], [ 'var' =&gt; 'customer_homedir', 'description' =&gt; lng('admin.phpconfig.homedir') ] ] ] ];</file><file name="lib/formfields/admin/admin/formfield.admin_add.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\language; use froxlor\settings; use froxlor\system\crypt; return [ 'admin_add' =&gt; [ 'title' =&gt; lng('admin.admin_add'), 'image' =&gt; 'fa-solid fa-user-plus', 'self_overview' =&gt; ['section' =&gt; 'admins', 'page' =&gt; 'admins'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.accountdata'), 'image' =&gt; 'icons/user_add.png', 'fields' =&gt; [ 'new_loginname' =&gt; [ 'label' =&gt; lng('login.username'), 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'admin_password' =&gt; [ 'label' =&gt; lng('login.password'), 'type' =&gt; 'password', 'mandatory' =&gt; true, 'autocomplete' =&gt; 'off', 'next_to' =&gt; [ 'admin_password_suggestion' =&gt; [ 'next_to_prefix' =&gt; lng('customer.generated_pwd') . ':', 'type' =&gt; 'text', 'visible' =&gt; (settings::get('panel.password_regex') == ''), 'value' =&gt; crypt::generatepassword(), 'readonly' =&gt; true ] ] ], 'def_language' =&gt; [ 'label' =&gt; lng('login.language'), 'type' =&gt; 'select', 'select_var' =&gt; language::getlanguages(), 'selected' =&gt; $userinfo['language'] ], 'gui_access' =&gt; [ 'label' =&gt; lng('usersettings.gui_access.title'), 'desc' =&gt; lng('usersettings.gui_access.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; 1, ], 'api_allowed' =&gt; [ 'label' =&gt; lng('usersettings.api_allowed.title'), 'desc' =&gt; lng('usersettings.api_allowed.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; settings::get('api.enabled') == '1', 'visible' =&gt; settings::get('api.enabled') == '1' ], ] ], 'section_b' =&gt; [ 'title' =&gt; lng('admin.contactdata'), 'image' =&gt; 'icons/user_add.png', 'fields' =&gt; [ 'name' =&gt; [ 'label' =&gt; lng('customer.name'), 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'email' =&gt; [ 'label' =&gt; lng('customer.email'), 'type' =&gt; 'text', 'mandatory' =&gt; true ], 'custom_notes' =&gt; [ 'label' =&gt; lng('usersettings.custom_notes.title'), 'desc' =&gt; lng('usersettings.custom_notes.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12 ], 'custom_notes_show' =&gt; [ 'label' =&gt; lng('usersettings.custom_notes.show'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ] ] ], 'section_c' =&gt; [ 'title' =&gt; lng('admin.servicedata'), 'image' =&gt; 'icons/user_add.png', 'fields' =&gt; [ 'ipaddress' =&gt; [ 'label' =&gt; lng('serversettings.ipaddress.title'), 'type' =&gt; 'select', 'select_var' =&gt; $ipaddress ], 'change_serversettings' =&gt; [ 'label' =&gt; lng('admin.change_serversettings'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'customers' =&gt; [ 'label' =&gt; lng('admin.customers'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'customers_see_all' =&gt; [ 'label' =&gt; lng('admin.customers_see_all'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'domains' =&gt; [ 'label' =&gt; lng('admin.domains'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'caneditphpsettings' =&gt; [ 'label' =&gt; lng('admin.caneditphpsettings'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; false ], 'diskspace' =&gt; [ 'label' =&gt; lng('customer.diskspace') . ' (' . lng('customer.mib') . ')', 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 6, 'mandatory' =&gt; true ], 'traffic' =&gt; [ 'label' =&gt; lng('customer.traffic') . ' (' . lng('customer.gib') . ')', 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 4, 'mandatory' =&gt; true ], 'subdomains' =&gt; [ 'label' =&gt; lng('customer.subdomains'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'emails' =&gt; [ 'label' =&gt; lng('customer.emails'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'email_accounts' =&gt; [ 'label' =&gt; lng('customer.accounts'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'email_forwarders' =&gt; [ 'label' =&gt; lng('customer.forwarders'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'email_quota' =&gt; [ 'label' =&gt; lng('customer.email_quota') . ' (' . lng('customer.mib') . ')', 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'visible' =&gt; settings::get('system.mail_quota_enabled') == '1', 'mandatory' =&gt; true ], 'ftps' =&gt; [ 'label' =&gt; lng('customer.ftps'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9 ], 'mysqls' =&gt; [ 'label' =&gt; lng('customer.mysqls'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; 0, 'maxlength' =&gt; 9, 'mandatory' =&gt; true ] ] ] ] ] ];</file><file name="lib/formfields/admin/admin/formfield.admin_edit.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\language; use froxlor\settings; use froxlor\system\crypt; return [ 'admin_edit' =&gt; [ 'title' =&gt; lng('admin.admin_edit'), 'image' =&gt; 'fa-solid fa-user-pen', 'self_overview' =&gt; ['section' =&gt; 'admins', 'page' =&gt; 'admins'], 'sections' =&gt; [ 'section_a' =&gt; [ 'title' =&gt; lng('admin.accountdata'), 'image' =&gt; 'icons/user_edit.png', 'fields' =&gt; [ 'loginname' =&gt; [ 'label' =&gt; lng('login.username'), 'type' =&gt; 'label', 'value' =&gt; $result['loginname'] ], 'deactivated' =&gt; [ 'label' =&gt; lng('admin.deactivated_user'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['deactivated'], 'visible' =&gt; $result['adminid'] != $userinfo['userid'] ], 'admin_password' =&gt; [ 'label' =&gt; lng('login.password') . '&amp;nbsp;(' . lng('panel.emptyfornochanges') . ')', 'type' =&gt; 'password', 'autocomplete' =&gt; 'off', 'visible' =&gt; $result['adminid'] != $userinfo['userid'], 'next_to' =&gt; [ 'admin_password_suggestion' =&gt; [ 'next_to_prefix' =&gt; lng('customer.generated_pwd') . ':', 'type' =&gt; 'text', 'visible' =&gt; (settings::get('panel.password_regex') == '' &amp;&amp; !($result['adminid'] == $userinfo['userid'])), 'value' =&gt; crypt::generatepassword(), 'readonly' =&gt; true ] ] ], 'def_language' =&gt; [ 'label' =&gt; lng('login.language'), 'type' =&gt; 'select', 'select_var' =&gt; language::getlanguages(), 'selected' =&gt; $result['def_language'], 'visible' =&gt; $result['adminid'] != $userinfo['userid'] ], 'gui_access' =&gt; [ 'label' =&gt; lng('usersettings.gui_access.title'), 'desc' =&gt; lng('usersettings.gui_access.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['gui_access'], 'visible' =&gt; $result['adminid'] != $userinfo['userid'] ], 'api_allowed' =&gt; [ 'label' =&gt; lng('usersettings.api_allowed.title'), 'desc' =&gt; lng('usersettings.api_allowed.description'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['api_allowed'], 'visible' =&gt; settings::get('api.enabled') == '1' ], ] ], 'section_b' =&gt; [ 'title' =&gt; lng('admin.contactdata'), 'image' =&gt; 'icons/user_edit.png', 'fields' =&gt; [ 'name' =&gt; [ 'label' =&gt; lng('customer.name'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; $result['name'] ], 'email' =&gt; [ 'label' =&gt; lng('customer.email'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; $result['email'] ], 'custom_notes' =&gt; [ 'label' =&gt; lng('usersettings.custom_notes.title'), 'desc' =&gt; lng('usersettings.custom_notes.description'), 'type' =&gt; 'textarea', 'cols' =&gt; 60, 'rows' =&gt; 12, 'value' =&gt; $result['custom_notes'] ], 'custom_notes_show' =&gt; [ 'label' =&gt; lng('usersettings.custom_notes.show'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['custom_notes_show'] ] ] ], 'section_c' =&gt; [ 'title' =&gt; lng('admin.servicedata'), 'image' =&gt; 'icons/user_add.png', 'visible' =&gt; $result['adminid'] != $userinfo['userid'], 'fields' =&gt; [ 'ipaddress' =&gt; [ 'label' =&gt; lng('serversettings.ipaddress.title'), 'type' =&gt; 'select', 'select_var' =&gt; $ipaddress, 'selected' =&gt; $result['ip'] ], 'change_serversettings' =&gt; [ 'label' =&gt; lng('admin.change_serversettings'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['change_serversettings'] ], 'customers' =&gt; [ 'label' =&gt; lng('admin.customers'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['customers']) ? '0' : $result['customers'], 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'customers_see_all' =&gt; [ 'label' =&gt; lng('admin.customers_see_all'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['customers_see_all'] ], 'domains' =&gt; [ 'label' =&gt; lng('admin.domains'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['domains']) ? '0' : $result['domains'], 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'caneditphpsettings' =&gt; [ 'label' =&gt; lng('admin.caneditphpsettings'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; $result['caneditphpsettings'] ], 'diskspace' =&gt; [ 'label' =&gt; lng('customer.diskspace') . ' (' . lng('customer.mib') . ')', 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['diskspace']) ? '0' : $result['diskspace'], 'maxlength' =&gt; 6, 'mandatory' =&gt; true ], 'traffic' =&gt; [ 'label' =&gt; lng('customer.traffic') . ' (' . lng('customer.gib') . ')', 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['traffic']) ? '0' : $result['traffic'], 'maxlength' =&gt; 4, 'mandatory' =&gt; true ], 'subdomains' =&gt; [ 'label' =&gt; lng('customer.subdomains'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['subdomains']) ? '0' : $result['subdomains'], 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'emails' =&gt; [ 'label' =&gt; lng('customer.emails'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['emails']) ? '0' : $result['emails'], 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'email_accounts' =&gt; [ 'label' =&gt; lng('customer.accounts'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['email_accounts']) ? '0' : $result['email_accounts'], 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'email_forwarders' =&gt; [ 'label' =&gt; lng('customer.forwarders'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['email_forwarders']) ? '0' : $result['email_forwarders'], 'maxlength' =&gt; 9, 'mandatory' =&gt; true ], 'email_quota' =&gt; [ 'label' =&gt; lng('customer.email_quota') . ' (' . lng('customer.mib') . ')', 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['email_quota']) ? '0' : $result['email_quota'], 'maxlength' =&gt; 9, 'visible' =&gt; settings::get('system.mail_quota_enabled') == '1', 'mandatory' =&gt; true ], 'ftps' =&gt; [ 'label' =&gt; lng('customer.ftps'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['ftps']) ? '0' : $result['ftps'], 'maxlength' =&gt; 9 ], 'mysqls' =&gt; [ 'label' =&gt; lng('customer.mysqls'), 'desc' =&gt; lng('panel.use_checkbox_for_unlimited'), 'type' =&gt; 'textul', 'value' =&gt; empty($result['mysqls']) ? '0' : $result['mysqls'], 'maxlength' =&gt; 9, 'mandatory' =&gt; true ] ] ] ] ] ];</file><file name="lib/formfields/admin/admin/index.html" /><file name="lib/formfields/install/formfield.install.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\froxlor; $httpuser = ''; $httpgroup = ''; (extension_loaded('posix')) { $httpuser = posix_getpwuid(posix_getuid())['name'] ?? ''; $httpgroup = posix_getgrgid(posix_getgid())['name'] ?? ''; } return [ 'install' =&gt; [ 'title' =&gt; 'install', 'sections' =&gt; [ 'step1' =&gt; [ 'title' =&gt; lng('install.database.title'), 'description' =&gt; lng('install.database.description'), 'fields' =&gt; [ 'mysql_host' =&gt; [ 'label' =&gt; lng('mysql.mysql_server'), 'placeholder' =&gt; lng('mysql.mysql_server'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; old('mysql_host', 'localhost', 'installation') ], 'mysql_ssl_ca_file' =&gt; [ 'label' =&gt; lng('mysql.mysql_ssl_ca_file'), 'placeholder' =&gt; lng('mysql.mysql_ssl_ca_file'), 'type' =&gt; 'text', 'value' =&gt; old('mysql_ssl_ca_file', null, 'installation'), 'advanced' =&gt; true, ], 'mysql_ssl_verify_server_certificate' =&gt; [ 'label' =&gt; lng('mysql.mysql_ssl_verify_server_certificate'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; old('mysql_ssl_verify_server_certificate', '0', 'installation'), 'advanced' =&gt; true, ], 'mysql_root_user' =&gt; [ 'label' =&gt; lng('mysql.privileged_user'), 'placeholder' =&gt; lng('mysql.privileged_user'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; old('mysql_root_user', 'froxroot', 'installation'), ], 'mysql_root_pass' =&gt; [ 'label' =&gt; lng('mysql.privileged_passwd'), 'placeholder' =&gt; lng('mysql.privileged_passwd'), 'type' =&gt; 'password', 'mandatory' =&gt; true, 'value' =&gt; old('mysql_root_pass', null, 'installation'), ], 'mysql_unprivileged_user' =&gt; [ 'label' =&gt; lng('install.database.user'), 'placeholder' =&gt; lng('install.database.user'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; old('mysql_unprivileged_user', 'froxlor', 'installation'), ], 'mysql_unprivileged_pass' =&gt; [ 'label' =&gt; lng('mysql.unprivileged_passwd'), 'placeholder' =&gt; lng('mysql.unprivileged_passwd'), 'type' =&gt; 'password', 'mandatory' =&gt; true, 'value' =&gt; old('mysql_unprivileged_pass', null, 'installation'), ], 'mysql_database' =&gt; [ 'label' =&gt; lng('install.database.dbname'), 'placeholder' =&gt; lng('install.database.dbname'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; old('mysql_database', 'froxlor', 'installation'), ], 'mysql_force_create' =&gt; [ 'label' =&gt; lng('install.database.force_create'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; old('mysql_force_create', '0', 'installation') ], ] ], 'step2' =&gt; [ 'title' =&gt; lng('install.admin.title'), 'description' =&gt; lng('install.admin.description'), 'fields' =&gt; [ 'admin_name' =&gt; [ 'label' =&gt; lng('customer.name'), 'placeholder' =&gt; lng('customer.name'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; old('admin_name', 'administrator', 'installation'), ], 'admin_user' =&gt; [ 'label' =&gt; lng('login.username'), 'placeholder' =&gt; lng('login.username'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; old('admin_user', 'admin', 'installation'), ], 'admin_pass' =&gt; [ 'label' =&gt; lng('login.password'), 'placeholder' =&gt; lng('login.password'), 'type' =&gt; 'password', 'mandatory' =&gt; true, 'value' =&gt; old('admin_pass', null, 'installation'), ], 'admin_pass_confirm' =&gt; [ 'label' =&gt; lng('changepassword.new_password_confirm'), 'placeholder' =&gt; lng('changepassword.new_password_confirm'), 'type' =&gt; 'password', 'mandatory' =&gt; true, 'value' =&gt; old('admin_pass_confirm', null, 'installation'), ], 'admin_email' =&gt; [ 'label' =&gt; lng('customer.email'), 'placeholder' =&gt; lng('customer.email'), 'type' =&gt; 'email', 'mandatory' =&gt; true, 'value' =&gt; old('admin_email', null, 'installation'), ], 'use_admin_email_as_sender' =&gt; [ 'label' =&gt; lng('install.admin.use_admin_email_as_sender'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; old('use_admin_email_as_sender', '1', 'installation'), ], 'sender_email' =&gt; [ 'label' =&gt; lng('serversettings.adminmail.title'), 'placeholder' =&gt; lng('install.admin.use_autogenerated_email_as_sender'), 'type' =&gt; 'email', 'value' =&gt; old('sender_email', null, 'installation'), ], ] ], 'step3' =&gt; [ 'title' =&gt; lng('install.system.title'), 'description' =&gt; lng('install.system.description'), 'fields' =&gt; [ 'distribution' =&gt; [ 'label' =&gt; lng('admin.configfiles.distribution'), 'type' =&gt; 'select', 'mandatory' =&gt; true, 'select_var' =&gt; $supportedos, 'selected' =&gt; $guesseddistribution ], 'serveripv4' =&gt; [ 'label' =&gt; lng('install.system.ipv4'), 'placeholder' =&gt; lng('install.system.ipv4'), 'type' =&gt; 'text', 'value' =&gt; old('serveripv4', filter_var($_server['server_addr'] ?? "", filter_validate_ip, filter_flag_ipv4) ? ($_server['server_addr'] ?? "") : "", 'installation'), ], 'serveripv6' =&gt; [ 'label' =&gt; lng('install.system.ipv6'), 'placeholder' =&gt; lng('install.system.ipv6'), 'type' =&gt; 'text', 'value' =&gt; old('serveripv6', filter_var($_server['server_addr'] ?? "", filter_validate_ip, filter_flag_ipv6) ? ($_server['server_addr'] ?? "") : "", 'installation'), ], 'servername' =&gt; [ 'label' =&gt; lng('install.system.servername'), 'placeholder' =&gt; lng('install.system.servername'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; old('servername', filter_var($_server['server_name'] ?? "", filter_validate_ip) ? null : $_server['server_name'], 'installation'), ], 'use_ssl' =&gt; [ 'label' =&gt; lng('serversettings.ssl.use_ssl.title'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; old('use_ssl', '1', 'installation'), ], 'webserver' =&gt; [ 'label' =&gt; lng('admin.webserver'), 'type' =&gt; 'select', 'mandatory' =&gt; true, 'select_var' =&gt; ['apache24' =&gt; 'apache 2.4', 'nginx' =&gt; 'nginx', 'lighttpd' =&gt; 'lighttpd'], 'selected' =&gt; old('webserver', $guessedwebserver, 'installation'), ], 'webserver_backend' =&gt; [ 'label' =&gt; lng('install.system.phpbackend'), 'type' =&gt; 'select', 'mandatory' =&gt; true, 'select_var' =&gt; $webserverbackend, 'selected' =&gt; old('webserver_backend', 'php-fpm', 'installation'), ], 'httpuser' =&gt; [ 'label' =&gt; lng('admin.webserver_user'), 'placeholder' =&gt; lng('admin.webserver_user'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; old('httpuser', $httpuser, 'installation'), 'advanced' =&gt; true, ], 'httpgroup' =&gt; [ 'label' =&gt; lng('admin.webserver_group'), 'placeholder' =&gt; lng('admin.webserver_group'), 'type' =&gt; 'text', 'mandatory' =&gt; true, 'value' =&gt; old('httpgroup', $httpgroup, 'installation'), 'advanced' =&gt; true, ], 'activate_newsfeed' =&gt; [ 'label' =&gt; lng('install.system.activate_newsfeed'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; old('activate_newsfeed', '0', 'installation'), ], ] ], 'step4' =&gt; [ 'title' =&gt; lng('install.install.title'), 'description' =&gt; lng('install.install.description'), 'fields' =&gt; [ 'system' =&gt; [ 'label' =&gt; lng('install.install.runcmd'), 'type' =&gt; 'textarea', 'value' =&gt; (!empty($_session['installation']['ud_str']) ? froxlor::getinstalldir() . "bin/froxlor-cli froxlor:install -c '" . $_session['installation']['ud_str'] . "'\n" : "") . (!empty($_session['installation']['json_params']) ? froxlor::getinstalldir() . "bin/froxlor-cli froxlor:config-services -a '" . $_session['installation']['json_params'] . "' --yes-to-all" : "something went wrong..."), 'readonly' =&gt; true, 'rows' =&gt; 10, 'style' =&gt; 'min-height:16rem;' ], 'manual_config' =&gt; [ 'label' =&gt; lng('install.install.manual_config'), 'type' =&gt; 'checkbox', 'value' =&gt; '1', 'checked' =&gt; old('manual_config', '0', 'installation'), ], 'target_servername' =&gt; [ 'type' =&gt; 'hidden', 'value' =&gt; $_session['installation']['servername'] ?? "", ], ] ] ] ] ];</file><file name="lib/formfields/install/index.html" /><file name="lib/navigation/00.froxlor.main.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; use froxlor\currentuser; return [ 'customer' =&gt; [ 'email' =&gt; [ 'url' =&gt; 'customer_email.php', 'label' =&gt; lng('menue.email.email'), 'show_element' =&gt; (!settings::isinlist('panel.customer_hide_options', 'email')), 'icon' =&gt; 'fa-solid fa-envelope', 'elements' =&gt; [ [ 'url' =&gt; 'customer_email.php?page=emails', 'label' =&gt; lng('menue.email.emails'), 'required_resources' =&gt; 'emails', 'add_shortlink' =&gt; !currentuser::isadmin() &amp;&amp; currentuser::canaddresource('emails') ? 'customer_email.php?page=email_domain&amp;action=add' : null, ], [ 'url' =&gt; settings::get('panel.webmail_url'), 'new_window' =&gt; true, 'label' =&gt; lng('menue.email.webmail'), 'required_resources' =&gt; 'emails_used', 'show_element' =&gt; (settings::get('panel.webmail_url') != ''), 'is_external' =&gt; true, ] ] ], 'mysql' =&gt; [ 'url' =&gt; 'customer_mysql.php', 'label' =&gt; lng('menue.mysql.mysql'), 'show_element' =&gt; (!settings::isinlist('panel.customer_hide_options', 'mysql')), 'icon' =&gt; 'fa-solid fa-database', 'elements' =&gt; [ [ 'url' =&gt; 'customer_mysql.php?page=mysqls', 'label' =&gt; lng('menue.mysql.databases'), 'required_resources' =&gt; 'mysqls', 'add_shortlink' =&gt; !currentuser::isadmin() &amp;&amp; currentuser::canaddresource('mysqls')? 'customer_mysql.php?page=mysqls&amp;action=add' : null, ], [ 'url' =&gt; settings::get('panel.phpmyadmin_url'), 'new_window' =&gt; true, 'label' =&gt; lng('menue.mysql.phpmyadmin'), 'required_resources' =&gt; 'mysqls_used', 'show_element' =&gt; (settings::get('panel.phpmyadmin_url') != ''), 'is_external' =&gt; true, ] ] ], 'domains' =&gt; [ 'url' =&gt; 'customer_domains.php', 'label' =&gt; lng('menue.domains.domains'), 'show_element' =&gt; (!settings::isinlist('panel.customer_hide_options', 'domains')), 'icon' =&gt; 'fa-solid fa-globe', 'elements' =&gt; [ [ 'url' =&gt; 'customer_domains.php?page=domains', 'label' =&gt; lng('menue.domains.settings'), 'add_shortlink' =&gt; !currentuser::isadmin() &amp;&amp; currentuser::canaddresource('subdomains') ? 'customer_domains.php?page=domains&amp;action=add' : null, ], [ 'url' =&gt; 'customer_domains.php?page=sslcertificates', 'label' =&gt; lng('domains.ssl_certificates') ] ] ], 'ftp' =&gt; [ 'url' =&gt; 'customer_ftp.php', 'label' =&gt; lng('menue.ftp.ftp'), 'show_element' =&gt; (!settings::isinlist('panel.customer_hide_options', 'ftp')), 'icon' =&gt; 'fa-solid fa-users', 'elements' =&gt; [ [ 'url' =&gt; 'customer_ftp.php?page=accounts', 'label' =&gt; lng('menue.ftp.accounts'), 'add_shortlink' =&gt; !currentuser::isadmin() &amp;&amp; currentuser::canaddresource('ftps') ? 'customer_ftp.php?page=accounts&amp;action=add' : null, ], [ 'url' =&gt; settings::get('panel.webftp_url'), 'new_window' =&gt; true, 'label' =&gt; lng('menue.ftp.webftp'), 'show_element' =&gt; (settings::get('panel.webftp_url') != ''), 'is_external' =&gt; true, ] ] ], 'extras' =&gt; [ 'url' =&gt; 'customer_extras.php', 'label' =&gt; lng('menue.extras.extras'), 'show_element' =&gt; (!settings::isinlist('panel.customer_hide_options', 'extras')), 'icon' =&gt; 'fa-solid fa-wrench', 'elements' =&gt; [ [ 'url' =&gt; 'customer_extras.php?page=htpasswds', 'label' =&gt; lng('menue.extras.directoryprotection'), 'show_element' =&gt; (!settings::isinlist('panel.customer_hide_options', 'extras.directoryprotection')), 'add_shortlink' =&gt; 'customer_extras.php?page=htpasswds&amp;action=add', ], [ 'url' =&gt; 'customer_extras.php?page=htaccess', 'label' =&gt; lng('menue.extras.pathoptions'), 'show_element' =&gt; (!settings::isinlist('panel.customer_hide_options', 'extras.pathoptions')), 'add_shortlink' =&gt; 'customer_extras.php?page=htaccess&amp;action=add', ], [ 'url' =&gt; 'customer_logger.php?page=log', 'label' =&gt; lng('menue.logger.logger'), 'show_element' =&gt; (settings::get('logger.enabled') == true) &amp;&amp; (!settings::isinlist('panel.customer_hide_options', 'extras.logger')) ], [ 'url' =&gt; 'customer_extras.php?page=export', 'label' =&gt; lng('menue.extras.export'), 'show_element' =&gt; (settings::get('system.exportenabled') == true) &amp;&amp; (!settings::isinlist('panel.customer_hide_options', 'extras.export')) ] ] ], 'traffic' =&gt; [ 'url' =&gt; 'customer_traffic.php', 'label' =&gt; lng('menue.traffic.traffic'), 'show_element' =&gt; (!settings::isinlist('panel.customer_hide_options', 'traffic')), 'icon' =&gt; 'fa-solid fa-area-chart', 'elements' =&gt; [ [ 'url' =&gt; 'customer_traffic.php?page=current', 'label' =&gt; lng('menue.traffic.current') ], [ 'url' =&gt; 'customer_traffic.php', 'label' =&gt; lng('menue.traffic.overview') ] ] ], 'docs' =&gt; [ 'label' =&gt; lng('admin.documentation'), 'icon' =&gt; 'fa-solid fa-circle-info', 'show_element' =&gt; (!settings::isinlist('panel.customer_hide_options', 'misc.documentation')), 'elements' =&gt; [ [ 'url' =&gt; \froxlor\froxlor::getdocsurl() . 'user-guide/', 'label' =&gt; lng('admin.userguide'), 'new_window' =&gt; true, 'is_external' =&gt; true, ], [ 'url' =&gt; \froxlor\froxlor::getdocsurl() . 'api-guide/', 'label' =&gt; lng('admin.apiguide'), 'new_window' =&gt; true, 'show_element' =&gt; settings::get('api.enabled') == 1 &amp;&amp; currentuser::getfield('api_allowed') == 1, 'is_external' =&gt; true, ] ] ] ], 'admin' =&gt; [ 'resources' =&gt; [ 'label' =&gt; lng('admin.resources'), 'required_resources' =&gt; 'customers', 'icon' =&gt; 'fa-solid fa-box', 'elements' =&gt; [ [ 'url' =&gt; 'admin_customers.php?page=customers', 'label' =&gt; lng('admin.customers'), 'required_resources' =&gt; 'customers', 'add_shortlink' =&gt; currentuser::isadmin() &amp;&amp; currentuser::canaddresource('customers') ? 'admin_customers.php?page=customers&amp;action=add' : null, ], [ 'url' =&gt; 'admin_admins.php?page=admins', 'label' =&gt; lng('admin.admins'), 'required_resources' =&gt; 'change_serversettings', 'add_shortlink' =&gt; 'admin_admins.php?page=admins&amp;action=add' ], [ 'url' =&gt; 'admin_domains.php?page=domains', 'label' =&gt; lng('admin.domains'), 'required_resources' =&gt; 'domains', 'add_shortlink' =&gt; currentuser::isadmin() &amp;&amp; currentuser::canaddresource('domains') ? 'admin_domains.php?page=domains&amp;action=add' : null, ], [ 'url' =&gt; 'admin_domains.php?page=sslcertificates', 'label' =&gt; lng('domains.ssl_certificates'), 'required_resources' =&gt; 'domains' ], [ 'url' =&gt; 'admin_ipsandports.php?page=ipsandports', 'label' =&gt; lng('admin.ipsandports.ipsandports'), 'required_resources' =&gt; 'change_serversettings', 'add_shortlink' =&gt; 'admin_ipsandports.php?page=ipsandports&amp;action=add' ], [ 'url' =&gt; 'admin_mysqlserver.php?page=mysqlserver', 'label' =&gt; lng('admin.mysqlserver.mysqlserver'), 'required_resources' =&gt; 'change_serversettings', 'add_shortlink' =&gt; 'admin_mysqlserver.php?page=mysqlserver&amp;action=add' ], [ 'url' =&gt; 'admin_plans.php?page=overview', 'label' =&gt; lng('admin.plans.plans'), 'required_resources' =&gt; 'customers', 'add_shortlink' =&gt; 'admin_plans.php?page=overview&amp;action=add' ], [ 'url' =&gt; 'admin_settings.php?page=updatecounters', 'label' =&gt; lng('admin.updatecounters'), 'required_resources' =&gt; 'change_serversettings' ] ] ], 'traffic' =&gt; [ 'label' =&gt; lng('admin.traffic'), 'required_resources' =&gt; 'customers', 'icon' =&gt; 'fa-solid fa-area-chart', 'elements' =&gt; [ [ 'url' =&gt; 'admin_traffic.php?page=customers', 'label' =&gt; lng('admin.customertraffic'), 'required_resources' =&gt; 'customers' ] ] ], 'server' =&gt; [ 'label' =&gt; lng('admin.server'), 'icon' =&gt; 'fa-solid fa-server', 'elements' =&gt; [ [ 'url' =&gt; 'admin_configfiles.php?page=configfiles', 'label' =&gt; lng('admin.configfiles.serverconfiguration'), 'required_resources' =&gt; 'change_serversettings' ], [ 'url' =&gt; 'admin_settings.php?page=overview', 'label' =&gt; lng('admin.serversettings'), 'required_resources' =&gt; 'change_serversettings' ], [ 'url' =&gt; 'admin_cronjobs.php?page=overview', 'label' =&gt; lng('admin.cron.cronsettings'), 'required_resources' =&gt; 'change_serversettings' ], [ 'url' =&gt; 'admin_logger.php?page=log', 'label' =&gt; lng('menue.logger.logger'), 'show_element' =&gt; (settings::get('logger.enabled') == true) ], [ 'url' =&gt; 'admin_settings.php?page=rebuildconfigs', 'label' =&gt; lng('admin.rebuildconf'), 'required_resources' =&gt; 'change_serversettings' ], [ 'url' =&gt; 'admin_autoupdate.php?page=overview', 'label' =&gt; lng('admin.autoupdate'), 'required_resources' =&gt; 'change_serversettings', 'show_element' =&gt; extension_loaded('zip') &amp;&amp; settings::config('enable_webupdate') ], [ 'url' =&gt; 'admin_settings.php?page=wipecleartextmailpws', 'label' =&gt; lng('admin.wipecleartextmailpwd'), 'required_resources' =&gt; 'change_serversettings', 'show_element' =&gt; (settings::get('system.mailpwcleartext') == true) ] ] ], 'server_php' =&gt; [ 'label' =&gt; lng('admin.server_php'), 'icon' =&gt; 'fab fa-php', 'elements' =&gt; [ [ 'url' =&gt; 'admin_phpsettings.php?page=overview', 'label' =&gt; lng('menue.phpsettings.maintitle'), 'show_element' =&gt; (settings::get('system.mod_fcgid') == true || settings::get('phpfpm.enabled') == true), 'add_shortlink' =&gt; 'admin_phpsettings.php?page=overview&amp;action=add' ], [ 'url' =&gt; 'admin_phpsettings.php?page=fpmdaemons', 'label' =&gt; lng('menue.phpsettings.fpmdaemons'), 'show_element' =&gt; settings::get('phpfpm.enabled') == true, 'add_shortlink' =&gt; 'admin_phpsettings.php?page=fpmdaemons&amp;action=add' ], [ 'url' =&gt; 'admin_settings.php?page=phpinfo', 'label' =&gt; lng('admin.phpinfo'), 'required_resources' =&gt; 'change_serversettings' ], [ 'url' =&gt; 'admin_apcuinfo.php?page=showinfo', 'label' =&gt; lng('admin.apcuinfo'), 'required_resources' =&gt; 'change_serversettings', 'show_element' =&gt; (function_exists('apcu_cache_info') === true) ], [ 'url' =&gt; 'admin_opcacheinfo.php?page=showinfo', 'label' =&gt; lng('admin.opcacheinfo'), 'required_resources' =&gt; 'change_serversettings', 'show_element' =&gt; (function_exists('opcache_get_configuration') === true) ] ] ], 'misc' =&gt; [ 'label' =&gt; lng('admin.misc'), 'icon' =&gt; 'fa-solid fa-wrench', 'elements' =&gt; [ [ 'url' =&gt; 'admin_settings.php?page=integritycheck', 'label' =&gt; lng('admin.integritycheck'), 'required_resources' =&gt; 'change_serversettings' ], [ 'url' =&gt; 'admin_templates.php?page=email', 'label' =&gt; lng('admin.templates.email') ], [ 'url' =&gt; 'admin_message.php?page=message', 'label' =&gt; lng('admin.message') ], [ 'url' =&gt; 'admin_settings.php?page=testmail', 'label' =&gt; lng('admin.testmail') ] ] ], 'docs' =&gt; [ 'label' =&gt; lng('admin.documentation'), 'icon' =&gt; 'fa-solid fa-circle-info', 'elements' =&gt; [ [ 'url' =&gt; \froxlor\froxlor::getdocsurl() . 'admin-guide/', 'label' =&gt; lng('admin.adminguide'), 'new_window' =&gt; true, 'is_external' =&gt; true, ], [ 'url' =&gt; \froxlor\froxlor::getdocsurl() . 'api-guide/', 'label' =&gt; lng('admin.apiguide'), 'new_window' =&gt; true, 'show_element' =&gt; settings::get('api.enabled') == 1, 'is_external' =&gt; true, ] ] ] ] ];</file><file name="lib/navigation/index.html" /><file name="lib/configfiles/index.html" /><file name="lib/tablelisting/tablelisting.dns.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\dns; use froxlor\ui\callbacks\text; use froxlor\ui\listing; // used outside scope variables $domain = $domain ?? ''; $domain_id = $domain_id ?? ''; return [ 'dns_list' =&gt; [ 'title' =&gt; 'dns entries', 'description' =&gt; $domain, 'icon' =&gt; 'fa-solid fa-globe', 'self_overview' =&gt; ['section' =&gt; 'domains', 'page' =&gt; 'domaindnseditor'], 'default_sorting' =&gt; ['record' =&gt; 'asc'], 'columns' =&gt; [ 'record' =&gt; [ 'label' =&gt; 'record', 'field' =&gt; 'record' ], 'type' =&gt; [ 'label' =&gt; 'type', 'field' =&gt; 'type' ], 'prio' =&gt; [ 'label' =&gt; 'priority', 'field' =&gt; 'prio', 'callback' =&gt; [dns::class, 'prio'], ], 'content' =&gt; [ 'label' =&gt; 'content', 'field' =&gt; 'content', 'callback' =&gt; [text::class, 'wordwrap'], ], 'ttl' =&gt; [ 'label' =&gt; 'ttl', 'field' =&gt; 'ttl' ] ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('dns_list', [ 'record', 'type', 'prio', 'content', 'ttl' ]), 'actions' =&gt; [ 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'text-danger', 'href' =&gt; [ 'section' =&gt; 'domains', 'page' =&gt; 'domaindnseditor', 'action' =&gt; 'delete', 'domain_id' =&gt; $domain_id, 'id' =&gt; ':id' ], ], ] ] ];</file><file name="lib/tablelisting/tablelisting.syslog.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\syslog; use froxlor\ui\callbacks\text; use froxlor\ui\listing; return [ 'syslog_list' =&gt; [ 'title' =&gt; lng('menue.logger.logger'), 'icon' =&gt; 'fa-solid fa-file-lines', 'self_overview' =&gt; ['section' =&gt; 'logger', 'page' =&gt; 'log'], 'default_sorting' =&gt; ['date' =&gt; 'desc'], 'columns' =&gt; [ 'date' =&gt; [ 'label' =&gt; lng('logger.date'), 'field' =&gt; 'date', 'callback' =&gt; [text::class, 'timestamp'], ], 'type' =&gt; [ 'label' =&gt; lng('logger.type'), 'field' =&gt; 'type', 'callback' =&gt; [syslog::class, 'typedescription'], ], 'user' =&gt; [ 'label' =&gt; lng('logger.user'), 'field' =&gt; 'user', ], 'text' =&gt; [ 'label' =&gt; lng('logger.action'), 'field' =&gt; 'text', ] ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('syslog_list', [ 'date', 'type', 'user', 'text' ]) ] ];</file><file name="lib/tablelisting/tablelisting.apikeys.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\impersonate; use froxlor\ui\callbacks\style; use froxlor\ui\callbacks\text; use froxlor\ui\listing; return [ 'apikeys_list' =&gt; [ 'title' =&gt; lng('menue.main.apikeys'), 'icon' =&gt; 'fa-solid fa-key', 'self_overview' =&gt; ['section' =&gt; 'index', 'page' =&gt; 'apikeys'], 'no_search' =&gt; true, 'columns' =&gt; [ 'a.loginname' =&gt; [ 'label' =&gt; lng('login.username'), 'field' =&gt; 'loginname', 'callback' =&gt; [impersonate::class, 'apiadmincustomerlink'] ], 'ak.apikey' =&gt; [ 'label' =&gt; 'api-key', 'field' =&gt; 'apikey', 'callback' =&gt; [text::class, 'shorten'], ], 'ak.secret' =&gt; [ 'label' =&gt; 'secret', 'field' =&gt; 'secret', 'callback' =&gt; [text::class, 'shorten'], ], 'ak.allowed_from' =&gt; [ 'label' =&gt; lng('apikeys.allowed_from'), 'field' =&gt; 'allowed_from', ], 'ak.valid_until' =&gt; [ 'label' =&gt; lng('apikeys.valid_until'), 'field' =&gt; 'valid_until', 'callback' =&gt; [text::class, 'timestampuntil'], ] ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('apikeys_list', [ 'a.loginname', 'ak.apikey', 'ak.secret', 'ak.allowed_from', 'ak.valid_until' ]), 'actions' =&gt; [ 'show' =&gt; [ 'icon' =&gt; 'fa-solid fa-eye', 'title' =&gt; lng('apikeys.clicktoview'), 'modal' =&gt; [text::class, 'apikeydetailmodal'], ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'index', 'page' =&gt; 'apikeys', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], ], ], 'format_callback' =&gt; [ [style::class, 'invalidapikey'] ] ] ];</file><file name="lib/tablelisting/tablelisting.sslcertificates.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\domain; use froxlor\ui\callbacks\sslcertificate; use froxlor\ui\listing; return [ 'sslcertificates_list' =&gt; [ 'title' =&gt; lng('domains.ssl_certificates'), 'icon' =&gt; 'fa-solid fa-shield', 'self_overview' =&gt; ['section' =&gt; 'domains', 'page' =&gt; 'sslcertificates'], 'default_sorting' =&gt; ['d.domain' =&gt; 'asc'], 'columns' =&gt; [ 'd.domain' =&gt; [ 'label' =&gt; lng('domains.domainname'), 'field' =&gt; 'domain', 'callback' =&gt; [domain::class, 'domainwithcustomerlink'], ], 'c.domain' =&gt; [ 'label' =&gt; lng('ssl_certificates.certificate_for'), 'field' =&gt; 'domain', 'callback' =&gt; [sslcertificate::class, 'domainwithsan'], 'searchable' =&gt; false, ], 's.issuer' =&gt; [ 'label' =&gt; lng('ssl_certificates.issuer'), 'field' =&gt; 'issuer', ], 's.validfromdate' =&gt; [ 'label' =&gt; lng('ssl_certificates.valid_from'), 'field' =&gt; 'validfromdate', 'searchable' =&gt; false, ], 's.validtodate' =&gt; [ 'label' =&gt; lng('ssl_certificates.valid_until'), 'field' =&gt; 'validtodate', 'searchable' =&gt; false, ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('sslcertificates_list', [ 'd.domain', 'c.domain', 's.issuer', 's.validfromdate', 's.validtodate', ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'domains', 'page' =&gt; 'domainssleditor', 'action' =&gt; 'view', 'id' =&gt; ':domainid' ], 'visible' =&gt; [sslcertificate::class, 'caneditssl'] ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'domains', 'page' =&gt; 'sslcertificates', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], // let's encrypt certificates removed 'correctly' // disabling let's encrypt domain 'visible' =&gt; [sslcertificate::class, 'isnotletsencrypt'] ], ] ] ];</file><file name="lib/tablelisting/index.html" /><file name="lib/tablelisting/customer/tablelisting.domains.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\domain; use froxlor\ui\callbacks\style; use froxlor\ui\callbacks\text; use froxlor\ui\listing; return [ 'domain_list' =&gt; [ 'title' =&gt; lng('admin.domains'), 'icon' =&gt; 'fa-solid fa-globe', 'self_overview' =&gt; ['section' =&gt; 'domains', 'page' =&gt; 'domains'], 'default_sorting' =&gt; ['d.domain_ace' =&gt; 'asc'], 'columns' =&gt; [ 'd.domain_ace' =&gt; [ 'label' =&gt; lng('domains.domainname'), 'field' =&gt; 'domain_ace', 'callback' =&gt; [domain::class, 'domainexternallinkinfo'], ], 'ipsandports' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ipsandports'), 'field' =&gt; 'ipsandports', 'sortable' =&gt; false, 'callback' =&gt; [domain::class, 'listips'], 'searchable' =&gt; false, ], 'd.documentroot' =&gt; [ 'label' =&gt; lng('panel.path'), 'field' =&gt; 'documentroot', 'callback' =&gt; [domain::class, 'domaintarget'], ], 'd.isbinddomain' =&gt; [ 'label' =&gt; lng('domains.isbinddomain'), 'field' =&gt; 'isbinddomain', 'callback' =&gt; [text::class, 'boolean'], ], 'd.isemaildomain' =&gt; [ 'label' =&gt; lng('admin.emaildomain'), 'field' =&gt; 'isemaildomain', 'callback' =&gt; [text::class, 'boolean'], ], 'd.email_only' =&gt; [ 'label' =&gt; lng('admin.email_only'), 'field' =&gt; 'email_only', 'callback' =&gt; [text::class, 'boolean'], ], 'd.iswildcarddomain' =&gt; [ 'label' =&gt; lng('domains.serveraliasoption_wildcard'), 'field' =&gt; 'iswildcarddomain', 'callback' =&gt; [text::class, 'boolean'], ], 'd.letsencrypt' =&gt; [ 'label' =&gt; lng('panel.letsencrypt'), 'field' =&gt; 'letsencrypt', 'callback' =&gt; [text::class, 'boolean'], ], 'ad.id' =&gt; [ 'label' =&gt; lng('domains.aliasdomainid'), 'field' =&gt; 'aliasdomainid' ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('domain_list', [ 'd.domain_ace', 'd.documentroot' ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'domains', 'page' =&gt; 'domains', 'action' =&gt; 'edit', 'id' =&gt; ':id' ], 'visible' =&gt; [domain::class, 'canedit'] ], 'logfiles' =&gt; [ 'icon' =&gt; 'fa-solid fa-file', 'title' =&gt; lng('panel.viewlogs'), 'href' =&gt; [ 'section' =&gt; 'domains', 'page' =&gt; 'logfiles', 'domain_id' =&gt; ':id' ], 'visible' =&gt; [domain::class, 'canviewlogs'] ], 'domaindnseditor' =&gt; [ 'icon' =&gt; 'fa-solid fa-globe', 'title' =&gt; lng('dnseditor.edit'), 'href' =&gt; [ 'section' =&gt; 'domains', 'page' =&gt; 'domaindnseditor', 'domain_id' =&gt; ':id' ], 'visible' =&gt; [domain::class, 'caneditdns'] ], 'domainssleditor' =&gt; [ 'callback' =&gt; [domain::class, 'editsslbuttons'], ], 'letsencrypt' =&gt; [ 'icon' =&gt; 'fa-solid fa-shield', 'title' =&gt; lng('panel.letsencrypt'), 'visible' =&gt; [domain::class, 'hasletsencryptactivated'] ], 'haslias' =&gt; [ 'icon' =&gt; 'fa-solid fa-arrow-up-right-from-square', 'title' =&gt; lng('domains.hasaliasdomains'), 'href' =&gt; [ 'section' =&gt; 'domains', 'page' =&gt; 'domains', 'searchfield' =&gt; 'ad.id', 'searchtext' =&gt; ':id' ], 'visible' =&gt; [domain::class, 'caneditalias'] ], 'isassigned' =&gt; [ 'icon' =&gt; 'fa-solid fa-check-to-slot', 'title' =&gt; lng('domains.isassigneddomain'), 'visible' =&gt; [domain::class, 'isassigned'] ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'domains', 'page' =&gt; 'domains', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], 'visible' =&gt; [domain::class, 'candelete'] ] ], 'format_callback' =&gt; [ [style::class, 'resultdomainterminatedordeactivated'] ] ] ];</file><file name="lib/tablelisting/customer/tablelisting.htaccess.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\ftp; use froxlor\ui\callbacks\text; use froxlor\ui\listing; // used outside scope variables $cperlenabled = $cperlenabled ?? false; return [ 'htaccess_list' =&gt; [ 'title' =&gt; lng('menue.extras.pathoptions'), 'icon' =&gt; 'fa-solid fa-folder', 'self_overview' =&gt; ['section' =&gt; 'extras', 'page' =&gt; 'htaccess'], 'default_sorting' =&gt; ['path' =&gt; 'asc'], 'columns' =&gt; [ 'path' =&gt; [ 'label' =&gt; lng('panel.path'), 'field' =&gt; 'path', 'callback' =&gt; [ftp::class, 'pathrelative'] ], 'options_indexes' =&gt; [ 'label' =&gt; lng('extras.view_directory'), 'field' =&gt; 'options_indexes', 'callback' =&gt; [text::class, 'boolean'] ], 'error404path' =&gt; [ 'label' =&gt; lng('extras.error404path'), 'field' =&gt; 'error404path' ], 'error403path' =&gt; [ 'label' =&gt; lng('extras.error403path'), 'field' =&gt; 'error403path' ], 'error500path' =&gt; [ 'label' =&gt; lng('extras.error500path'), 'field' =&gt; 'error500path' ], 'options_cgi' =&gt; [ 'label' =&gt; lng('extras.execute_perl'), 'field' =&gt; 'options_cgi', 'callback' =&gt; [text::class, 'boolean'], 'visible' =&gt; $cperlenabled ] ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('htaccess_list', [ 'path', 'options_indexes', 'error404path', 'error403path', 'error500path', 'options_cgi' ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'extras', 'page' =&gt; 'htaccess', 'action' =&gt; 'edit', 'id' =&gt; ':id' ], ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'extras', 'page' =&gt; 'htaccess', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], ] ] ] ];</file><file name="lib/tablelisting/customer/tablelisting.emails_overview.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\impersonate; use froxlor\ui\callbacks\style; use froxlor\ui\callbacks\text; use froxlor\ui\listing; return [ 'emaildomain_list' =&gt; [ 'title' =&gt; lng('menue.email.emailsoverview'), 'icon' =&gt; 'fa-solid fa-envelope', 'self_overview' =&gt; ['section' =&gt; 'email', 'page' =&gt; 'overview'], 'default_sorting' =&gt; ['d.domain_ace' =&gt; 'asc'], 'columns' =&gt; [ 'd.domain_ace' =&gt; [ 'label' =&gt; 'domain', 'field' =&gt; 'domain', ], 'addresses' =&gt; [ 'label' =&gt; '# ' . lng('emails.emails'), 'field' =&gt; 'addresses', 'searchable' =&gt; false, ], 'accounts' =&gt; [ 'label' =&gt; '# ' . lng('emails.accounts'), 'field' =&gt; 'accounts', 'searchable' =&gt; false, ], 'forwarder' =&gt; [ 'label' =&gt; '# ' . lng('emails.forwarders'), 'field' =&gt; 'forwarder', 'searchable' =&gt; false, ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('emaildomain_list', [ 'd.domain_ace', 'addresses', 'accounts', 'forwarder', ]), 'actions' =&gt; [ 'show' =&gt; [ 'icon' =&gt; 'fa-solid fa-eye', 'title' =&gt; lng('apikeys.clicktoview'), 'href' =&gt; [ 'section' =&gt; 'email', 'page' =&gt; 'email_domain', 'domainid' =&gt; ':domainid' ], ], ], ] ];</file><file name="lib/tablelisting/customer/tablelisting.export.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\ftp; use froxlor\ui\callbacks\text; use froxlor\ui\listing; return [ 'export_list' =&gt; [ 'title' =&gt; lng('error.customerhasongoingexportjob'), 'icon' =&gt; 'fa-solid fa-server', 'self_overview' =&gt; ['section' =&gt; 'extras', 'page' =&gt; 'export'], 'default_sorting' =&gt; ['destdir' =&gt; 'asc'], 'columns' =&gt; [ 'destdir' =&gt; [ 'label' =&gt; lng('panel.path'), 'field' =&gt; 'data.destdir', 'callback' =&gt; [ftp::class, 'pathrelative'] ], 'pgp_public_key' =&gt; [ 'label' =&gt; lng('panel.pgp_public_key'), 'field' =&gt; 'data.pgp_public_key', 'callback' =&gt; [text::class, 'boolean'] ], 'dump_web' =&gt; [ 'label' =&gt; lng('extras.dump_web'), 'field' =&gt; 'data.dump_web', 'callback' =&gt; [text::class, 'boolean'], ], 'dump_mail' =&gt; [ 'label' =&gt; lng('extras.dump_mail'), 'field' =&gt; 'data.dump_mail', 'callback' =&gt; [text::class, 'boolean'], ], 'dump_dbs' =&gt; [ 'label' =&gt; lng('extras.dump_dbs'), 'field' =&gt; 'data.dump_dbs', 'callback' =&gt; [text::class, 'boolean'], ] ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('export_list', [ 'destdir', 'pgp_public_key', 'dump_web', 'dump_mail', 'dump_dbs' ]), 'actions' =&gt; [ 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.abort'), 'class' =&gt; 'btn-warning', 'href' =&gt; [ 'section' =&gt; 'extras', 'page' =&gt; 'export', 'action' =&gt; 'abort', 'id' =&gt; ':id' ], ] ] ] ];</file><file name="lib/tablelisting/customer/tablelisting.ftps.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; use froxlor\ui\callbacks\ftp; use froxlor\ui\callbacks\style; use froxlor\ui\callbacks\text; use froxlor\ui\listing; return [ 'ftp_list' =&gt; [ 'title' =&gt; lng('menue.ftp.accounts'), 'icon' =&gt; 'fa-solid fa-users', 'self_overview' =&gt; ['section' =&gt; 'ftp', 'page' =&gt; 'accounts'], 'default_sorting' =&gt; ['username' =&gt; 'asc'], 'columns' =&gt; [ 'username' =&gt; [ 'label' =&gt; lng('login.username'), 'field' =&gt; 'username', ], 'description' =&gt; [ 'label' =&gt; lng('panel.ftpdesc'), 'field' =&gt; 'description' ], 'homedir' =&gt; [ 'label' =&gt; lng('panel.path'), 'field' =&gt; 'homedir', 'callback' =&gt; [ftp::class, 'pathrelative'] ], 'shell' =&gt; [ 'label' =&gt; lng('panel.shell'), 'field' =&gt; 'shell', 'visible' =&gt; settings::get('system.allow_customer_shell') == '1' ], 'login_enabled' =&gt; [ 'label' =&gt; lng('panel.active'), 'field' =&gt; 'login_enabled', 'callback' =&gt; [text::class, 'yesno'], ] ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('ftp_list', [ 'username', 'description', 'homedir', 'shell', 'login_enabled', ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'ftp', 'page' =&gt; 'accounts', 'action' =&gt; 'edit', 'id' =&gt; ':id' ], ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'ftp', 'page' =&gt; 'accounts', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], ] ], 'format_callback' =&gt; [ [style::class, 'logindisabled'] ], ] ];</file><file name="lib/tablelisting/customer/tablelisting.htpasswd.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\ftp; use froxlor\ui\listing; return [ 'htpasswd_list' =&gt; [ 'title' =&gt; lng('menue.extras.directoryprotection'), 'icon' =&gt; 'fa-solid fa-lock', 'self_overview' =&gt; ['section' =&gt; 'extras', 'page' =&gt; 'htpasswds'], 'default_sorting' =&gt; ['path' =&gt; 'asc'], 'columns' =&gt; [ 'username' =&gt; [ 'label' =&gt; lng('login.username'), 'field' =&gt; 'username' ], 'path' =&gt; [ 'label' =&gt; lng('panel.path'), 'field' =&gt; 'path', 'callback' =&gt; [ftp::class, 'pathrelative'] ] ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('htpasswd_list', [ 'username', 'path' ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'extras', 'page' =&gt; 'htpasswds', 'action' =&gt; 'edit', 'id' =&gt; ':id' ], ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'extras', 'page' =&gt; 'htpasswds', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], ] ] ] ];</file><file name="lib/tablelisting/customer/tablelisting.emails.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; use froxlor\ui\callbacks\email; use froxlor\ui\callbacks\text; use froxlor\ui\listing; return [ 'email_list' =&gt; [ 'title' =&gt; lng('menue.email.emails'), 'icon' =&gt; 'fa-solid fa-envelope', 'self_overview' =&gt; ['section' =&gt; 'email', 'page' =&gt; 'email_domain'], 'default_sorting' =&gt; ['m.email_full' =&gt; 'asc'], 'columns' =&gt; [ 'm.email_full' =&gt; [ 'label' =&gt; lng('emails.emailaddress'), 'field' =&gt; 'email_full', ], 'm.destination' =&gt; [ 'label' =&gt; lng('emails.forwarders'), 'field' =&gt; 'destination', 'callback' =&gt; [email::class, 'forwarderlist'], ], 'm.popaccountid' =&gt; [ 'label' =&gt; lng('emails.account'), 'field' =&gt; 'popaccountid', 'callback' =&gt; [email::class, 'account'], ], 'm.spam_tag_level' =&gt; [ 'label' =&gt; lng('antispam.spam_tag_level.title'), 'field' =&gt; 'spam_tag_level', ], 'm.spam_kill_level' =&gt; [ 'label' =&gt; lng('antispam.spam_kill_level.title'), 'field' =&gt; 'spam_kill_level', ], 'm.bypass_spam' =&gt; [ 'label' =&gt; lng('antispam.bypass_spam.title'), 'field' =&gt; 'bypass_spam', 'callback' =&gt; [text::class, 'boolean'], ], 'm.policy_greylist' =&gt; [ 'label' =&gt; lng('antispam.policy_greylist.title'), 'field' =&gt; 'policy_greylist', 'callback' =&gt; [text::class, 'boolean'], ], 'm.iscatchall' =&gt; [ 'label' =&gt; lng('emails.catchall'), 'field' =&gt; 'iscatchall', 'callback' =&gt; [text::class, 'boolean'], 'visible' =&gt; settings::get('catchall.catchall_enabled') == '1' ], 'u.quota' =&gt; [ 'label' =&gt; lng('emails.quota'), 'field' =&gt; 'quota', 'visible' =&gt; settings::get('system.mail_quota_enabled') == '1' ] ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('email_list', [ 'm.email_full', 'm.destination', 'm.popaccountid', 'm.iscatchall', 'u.quota' ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'email', 'page' =&gt; 'email_domain', 'domainid' =&gt; ':domainid', 'action' =&gt; 'edit', 'id' =&gt; ':id' ], ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'email', 'page' =&gt; 'email_domain', 'domainid' =&gt; ':domainid', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], ] ] ] ];</file><file name="lib/tablelisting/customer/tablelisting.mysqls.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\mysql; use froxlor\ui\callbacks\text; use froxlor\ui\listing; // used outside scope variables $multiple_mysqlservers = $multiple_mysqlservers ?? false; return [ 'mysql_list' =&gt; [ 'title' =&gt; lng('menue.mysql.databases'), 'icon' =&gt; 'fa-solid fa-database', 'self_overview' =&gt; ['section' =&gt; 'mysql', 'page' =&gt; 'mysqls'], 'default_sorting' =&gt; ['databasename' =&gt; 'asc'], 'columns' =&gt; [ 'databasename' =&gt; [ 'label' =&gt; lng('mysql.databasename'), 'field' =&gt; 'databasename', ], 'description' =&gt; [ 'label' =&gt; lng('mysql.databasedescription'), 'field' =&gt; 'description' ], 'size' =&gt; [ 'label' =&gt; lng('mysql.size'), 'field' =&gt; 'size', 'callback' =&gt; [text::class, 'size'], 'searchable' =&gt; false ], 'dbserver' =&gt; [ 'label' =&gt; lng('mysql.mysql_server'), 'field' =&gt; 'dbserver', 'callback' =&gt; [mysql::class, 'dbserver'], 'visible' =&gt; $multiple_mysqlservers ] ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('mysql_list', [ 'databasename', 'description', 'size', 'dbserver' ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'mysql', 'page' =&gt; 'mysqls', 'action' =&gt; 'edit', 'id' =&gt; ':id' ], ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'mysql', 'page' =&gt; 'mysqls', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], ] ] ] ];</file><file name="lib/tablelisting/customer/index.html" /><file name="lib/tablelisting/admin/tablelisting.mysqlserver.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\admin; use froxlor\ui\listing; return [ 'mysqlserver_list' =&gt; [ 'title' =&gt; lng('admin.mysqlserver.mysqlserver'), 'icon' =&gt; 'fa-solid fa-server', 'self_overview' =&gt; ['section' =&gt; 'mysqlserver', 'page' =&gt; 'mysqlserver'], 'default_sorting' =&gt; ['caption' =&gt; 'asc'], 'columns' =&gt; [ 'id' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.dbserver'), 'field' =&gt; 'id', ], 'caption' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.caption'), 'field' =&gt; 'caption', 'isdefaultsearchfield' =&gt; true, ], 'host' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.host'), 'field' =&gt; 'host', ], 'port' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.port'), 'field' =&gt; 'port', 'class' =&gt; 'text-center', ], 'user' =&gt; [ 'label' =&gt; lng('admin.mysqlserver.user'), 'field' =&gt; 'user', 'visible' =&gt; [admin::class, 'canchangeserversettings'] ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('mysqlserver_list', [ 'caption', 'host', 'port', ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'mysqlserver', 'page' =&gt; 'mysqlserver', 'action' =&gt; 'edit', 'id' =&gt; ':id' ], 'visible' =&gt; [admin::class, 'canchangeserversettings'] ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'mysqlserver', 'page' =&gt; 'mysqlserver', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], 'visible' =&gt; [admin::class, 'canchangeserversettings'] ], ] ] ];</file><file name="lib/tablelisting/admin/tablelisting.domains.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; use froxlor\ui\callbacks\domain; use froxlor\ui\callbacks\impersonate; use froxlor\ui\callbacks\style; use froxlor\ui\callbacks\text; use froxlor\ui\listing; // used outside scope variables $customercollectioncount = !is_null($customercollection ?? null) ? $customercollection-&gt;count() : 0; return [ 'domain_list' =&gt; [ 'title' =&gt; lng('admin.domains'), 'icon' =&gt; 'fa-solid fa-globe', 'empty_msg' =&gt; $customercollectioncount == 0 ? lng('admin.domain_nocustomeraddingavailable') : '', 'self_overview' =&gt; ['section' =&gt; 'domains', 'page' =&gt; 'domains'], 'default_sorting' =&gt; ['d.domain_ace' =&gt; 'asc'], 'columns' =&gt; [ 'd.id' =&gt; [ 'label' =&gt; 'id', 'field' =&gt; 'id', 'sortable' =&gt; true, ], 'd.domain_ace' =&gt; [ 'label' =&gt; lng('domains.domainname'), 'field' =&gt; 'domain_ace', 'isdefaultsearchfield' =&gt; true, 'callback' =&gt; [domain::class, 'domaineditlink'], ], 'ipsandports' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ipsandports'), 'field' =&gt; 'ipsandports', 'sortable' =&gt; false, 'callback' =&gt; [domain::class, 'listips'], ], 'c.name' =&gt; [ 'label' =&gt; lng('customer.name'), 'field' =&gt; 'customer.name', 'callback' =&gt; [text::class, 'customerfullname'], ], 'c.loginname' =&gt; [ 'label' =&gt; lng('login.username'), 'field' =&gt; 'customer.loginname', 'callback' =&gt; [impersonate::class, 'customer'], ], 'd.aliasdomain' =&gt; [ 'label' =&gt; lng('domains.aliasdomain'), 'field' =&gt; 'aliasdomain', ], 'd.documentroot' =&gt; [ 'label' =&gt; lng('customer.documentroot'), 'field' =&gt; 'documentroot', ], 'd.isbinddomain' =&gt; [ 'label' =&gt; lng('domains.isbinddomain'), 'field' =&gt; 'isbinddomain', 'callback' =&gt; [text::class, 'boolean'], ], 'd.isemaildomain' =&gt; [ 'label' =&gt; lng('admin.emaildomain'), 'field' =&gt; 'isemaildomain', 'callback' =&gt; [text::class, 'boolean'], ], 'd.email_only' =&gt; [ 'label' =&gt; lng('admin.email_only'), 'field' =&gt; 'email_only', 'callback' =&gt; [text::class, 'boolean'], ], 'd.iswildcarddomain' =&gt; [ 'label' =&gt; lng('domains.serveraliasoption_wildcard'), 'field' =&gt; 'iswildcarddomain', 'callback' =&gt; [text::class, 'boolean'], ], 'd.subcanemaildomain' =&gt; [ 'label' =&gt; lng('admin.subdomainforemail'), 'field' =&gt; 'subcanemaildomain', 'callback' =&gt; [text::class, 'boolean'], ], 'd.caneditdomain' =&gt; [ 'label' =&gt; lng('admin.domain_editable.title'), 'field' =&gt; 'caneditdomain', 'callback' =&gt; [text::class, 'boolean'], ], 'd.dkim' =&gt; [ 'label' =&gt; lng('domains.dkimenabled'), 'field' =&gt; 'dkim', 'callback' =&gt; [text::class, 'boolean'], ], 'd.phpenabled' =&gt; [ 'label' =&gt; lng('admin.phpenabled'), 'field' =&gt; 'phpenabled', 'callback' =&gt; [text::class, 'boolean'], ], 'd.phpsettingid' =&gt; [ 'label' =&gt; lng('admin.phpsettings.title'), 'field' =&gt; 'phpsettingid', 'searchable' =&gt; false, 'callback' =&gt; [domain::class, 'getphpconfigname'], 'visible' =&gt; (int)settings::get('system.mod_fcgid') == 1 || (int)settings::get('phpfpm.enabled') == 1 ], 'd.openbasedir' =&gt; [ 'label' =&gt; lng('domains.openbasedirenabled'), 'field' =&gt; 'openbasedir', 'callback' =&gt; [text::class, 'boolean'], ], 'd.speciallogfile' =&gt; [ 'label' =&gt; lng('admin.speciallogfile.title'), 'field' =&gt; 'speciallogfile', 'callback' =&gt; [text::class, 'boolean'], ], 'd.hsts' =&gt; [ 'label' =&gt; lng('domains.hsts'), 'field' =&gt; 'hsts', 'callback' =&gt; [text::class, 'boolean'], ], 'd.http2' =&gt; [ 'label' =&gt; lng('admin.domain_http2.title'), 'field' =&gt; 'http2', 'callback' =&gt; [text::class, 'boolean'], ], 'd.letsencrypt' =&gt; [ 'label' =&gt; lng('panel.letsencrypt'), 'field' =&gt; 'letsencrypt', 'callback' =&gt; [text::class, 'boolean'], ], 'd.deactivated' =&gt; [ 'label' =&gt; lng('admin.deactivated'), 'field' =&gt; 'deactivated', 'callback' =&gt; [text::class, 'boolean'], ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('domain_list', [ 'd.domain_ace', 'c.name', 'c.loginname', 'd.aliasdomain', ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'domains', 'page' =&gt; 'domains', 'action' =&gt; 'edit', 'id' =&gt; ':id' ], ], 'duplicate' =&gt; [ 'icon' =&gt; 'fa-solid fa-clone', 'title' =&gt; lng('admin.domain_duplicate'), 'modal' =&gt; [text::class, 'domainduplicatemodal'], ], 'logfiles' =&gt; [ 'icon' =&gt; 'fa-solid fa-file', 'title' =&gt; lng('panel.viewlogs'), 'href' =&gt; [ 'section' =&gt; 'domains', 'page' =&gt; 'logfiles', 'domain_id' =&gt; ':id' ], 'visible' =&gt; [domain::class, 'canviewlogs'] ], 'domaindnseditor' =&gt; [ 'icon' =&gt; 'fa-solid fa-globe', 'title' =&gt; lng('dnseditor.edit'), 'href' =&gt; [ 'section' =&gt; 'domains', 'page' =&gt; 'domaindnseditor', 'domain_id' =&gt; ':id' ], 'visible' =&gt; [domain::class, 'admincaneditdns'] ], 'domainssleditor' =&gt; [ 'callback' =&gt; [domain::class, 'editsslbuttons'], ], 'letsencrypt' =&gt; [ 'icon' =&gt; 'fa-solid fa-shield', 'title' =&gt; lng('panel.letsencrypt'), 'visible' =&gt; [domain::class, 'hasletsencryptactivated'] ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'domains', 'page' =&gt; 'domains', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], 'visible' =&gt; [domain::class, 'admincandelete'] ] ], 'format_callback' =&gt; [ [style::class, 'resultdomainterminatedordeactivated'] ] ] ];</file><file name="lib/tablelisting/admin/tablelisting.ipsandports.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; use froxlor\ui\callbacks\text; use froxlor\ui\listing; return [ 'ipsandports_list' =&gt; [ 'title' =&gt; lng('admin.ipsandports.ipsandports'), 'icon' =&gt; 'fa-solid fa-ethernet', 'self_overview' =&gt; ['section' =&gt; 'ipsandports', 'page' =&gt; 'ipsandports'], 'default_sorting' =&gt; ['ip' =&gt; 'asc'], 'columns' =&gt; [ 'ip' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ip'), 'field' =&gt; 'ip', 'isdefaultsearchfield' =&gt; true, ], 'port' =&gt; [ 'label' =&gt; lng('admin.ipsandports.port'), 'field' =&gt; 'port', 'class' =&gt; 'text-center', ], 'listen' =&gt; [ 'label' =&gt; 'listen', 'field' =&gt; 'listen_statement', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'], 'visible' =&gt; settings::get('system.webserver') != 'nginx' ], 'namevirtualhost' =&gt; [ 'label' =&gt; 'namevirtualhost', 'field' =&gt; 'namevirtualhost_statement', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'], 'visible' =&gt; settings::get('system.webserver') == 'apache2' &amp;&amp; (int)settings::get('system.apache24') == 0 ], 'vhostcontainer' =&gt; [ 'label' =&gt; 'vhost-container', 'field' =&gt; 'vhostcontainer', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'] ], 'servername' =&gt; [ 'label' =&gt; lng('admin.ipsandports.create_vhostcontainer_servername_statement'), 'field' =&gt; 'vhostcontainer_servername_statement', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'], 'visible' =&gt; settings::get('system.webserver') == 'apache2' ], 'specialsettings' =&gt; [ 'label' =&gt; 'specialsettings', 'field' =&gt; 'specialsettings', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'] ], 'ssl' =&gt; [ 'label' =&gt; 'ssl', 'field' =&gt; 'ssl', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'] ], 'ssl_cert_file' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_cert_file'), 'field' =&gt; 'ssl_cert_file', 'class' =&gt; 'text-center', ], 'ssl_key_file' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_key_file'), 'field' =&gt; 'ssl_key_file', 'class' =&gt; 'text-center', ], 'ssl_ca_file' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_ca_file'), 'field' =&gt; 'ssl_ca_file', 'class' =&gt; 'text-center', ], 'ssl_cert_chainfile' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_cert_chainfile.title'), 'field' =&gt; 'ssl_cert_chainfile', 'class' =&gt; 'text-center', ], 'docroot' =&gt; [ 'label' =&gt; lng('admin.ipsandports.docroot.title'), 'field' =&gt; 'docroot', 'class' =&gt; 'text-center', ], 'ssl_specialsettings' =&gt; [ 'label' =&gt; 'ssl specialsettings', 'field' =&gt; 'ssl_specialsettings', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'] ], 'include_specialsettings' =&gt; [ 'label' =&gt; lng('serversettings.includedefault_sslvhostconf'), 'field' =&gt; 'include_specialsettings', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'] ], 'ssl_default_vhostconf_domain' =&gt; [ 'label' =&gt; lng('admin.ipsandports.ssl_default_vhostconf_domain'), 'field' =&gt; 'ssl_default_vhostconf_domain', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'] ], 'include_default_vhostconf_domain' =&gt; [ 'label' =&gt; '[domains] '. lng('serversettings.includedefault_sslvhostconf'), 'field' =&gt; 'include_default_vhostconf_domain', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'] ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('ipsandports_list', [ 'ip', 'port', 'vhostcontainer', 'specialsettings', 'servername', 'ssl' ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'ipsandports', 'page' =&gt; 'ipsandports', 'action' =&gt; 'edit', 'id' =&gt; ':id' ], ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'ipsandports', 'page' =&gt; 'ipsandports', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], ], ] ] ];</file><file name="lib/tablelisting/admin/tablelisting.admins.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\admin; use froxlor\ui\callbacks\customer; use froxlor\ui\callbacks\impersonate; use froxlor\ui\callbacks\progressbar; use froxlor\ui\callbacks\style; use froxlor\ui\callbacks\text; use froxlor\ui\listing; return [ 'admin_list' =&gt; [ 'title' =&gt; lng('admin.admin'), 'icon' =&gt; 'fa-solid fa-user', 'self_overview' =&gt; ['section' =&gt; 'admins', 'page' =&gt; 'admins'], 'default_sorting' =&gt; ['loginname' =&gt; 'asc'], 'columns' =&gt; [ 'adminid' =&gt; [ 'label' =&gt; 'id', 'field' =&gt; 'adminid', 'sortable' =&gt; true, ], 'loginname' =&gt; [ 'label' =&gt; lng('login.username'), 'field' =&gt; 'loginname', 'callback' =&gt; [impersonate::class, 'admin'], 'sortable' =&gt; true, 'isdefaultsearchfield' =&gt; true, ], 'name' =&gt; [ 'label' =&gt; lng('customer.name'), 'field' =&gt; 'name', ], 'email' =&gt; [ 'label' =&gt; lng('login.email'), 'field' =&gt; 'email', ], 'def_language' =&gt; [ 'label' =&gt; lng('login.profile_lng'), 'field' =&gt; 'def_language', ], 'customers_used' =&gt; [ 'label' =&gt; lng('admin.customers'), 'field' =&gt; 'customers_used', 'class' =&gt; 'text-center', ], 'diskspace' =&gt; [ 'label' =&gt; lng('customer.diskspace'), 'field' =&gt; 'diskspace', 'callback' =&gt; [progressbar::class, 'diskspace'], ], 'traffic' =&gt; [ 'label' =&gt; lng('customer.traffic'), 'field' =&gt; 'traffic', 'callback' =&gt; [progressbar::class, 'traffic_admins'], ], 'caneditphpsettings' =&gt; [ 'label' =&gt; lng('admin.caneditphpsettings'), 'field' =&gt; 'caneditphpsettings', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'], ], 'change_serversettings' =&gt; [ 'label' =&gt; lng('admin.change_serversettings'), 'field' =&gt; 'change_serversettings', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'], ], 'deactivated' =&gt; [ 'label' =&gt; lng('admin.deactivated'), 'field' =&gt; 'deactivated', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'], ], 'lastlogin_succ' =&gt; [ 'label' =&gt; lng('admin.lastlogin_succ'), 'field' =&gt; 'lastlogin_succ', 'callback' =&gt; [text::class, 'timestamp'], ], 'theme' =&gt; [ 'label' =&gt; lng('panel.theme'), 'field' =&gt; 'theme', ], 'api_allowed' =&gt; [ 'label' =&gt; lng('usersettings.api_allowed.title'), 'field' =&gt; 'api_allowed', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'], ], 'type_2fa' =&gt; [ 'label' =&gt; lng('2fa.type_2fa'), 'field' =&gt; 'type_2fa', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'type2fa'], ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('admin_list', [ 'loginname', 'name', 'customers_used', 'diskspace', 'traffic', 'deactivated', ]), 'actions' =&gt; [ 'show' =&gt; [ 'icon' =&gt; 'fa-solid fa-eye', 'title' =&gt; lng('usersettings.custom_notes.title'), 'modal' =&gt; [text::class, 'customernotedetailmodal'], 'visible' =&gt; [customer::class, 'hasnote'] ], 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'admins', 'page' =&gt; 'admins', 'action' =&gt; 'edit', 'id' =&gt; ':adminid' ], ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'admins', 'page' =&gt; 'admins', 'action' =&gt; 'delete', 'id' =&gt; ':adminid' ], 'visible' =&gt; [admin::class, 'isnotme'] ], ], 'format_callback' =&gt; [ [style::class, 'deactivated'], [style::class, 'diskspacewarning'], [style::class, 'trafficwarning'] ] ] ];</file><file name="lib/tablelisting/admin/tablelisting.plans.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\text; use froxlor\ui\listing; return [ 'plan_list' =&gt; [ 'title' =&gt; lng('admin.plans.plans'), 'icon' =&gt; 'fa-solid fa-clipboard-list', 'self_overview' =&gt; ['section' =&gt; 'plans', 'page' =&gt; 'overview'], 'default_sorting' =&gt; ['p.name' =&gt; 'asc'], 'columns' =&gt; [ 'p.id' =&gt; [ 'label' =&gt; 'id', 'field' =&gt; 'id', ], 'p.name' =&gt; [ 'label' =&gt; lng('admin.plans.name'), 'field' =&gt; 'name', 'isdefaultsearchfield' =&gt; true, ], 'p.description' =&gt; [ 'label' =&gt; lng('admin.plans.description'), 'field' =&gt; 'description', ], 'p.adminname' =&gt; [ 'label' =&gt; lng('admin.admin'), 'field' =&gt; 'adminname', ], 'p.ts' =&gt; [ 'label' =&gt; lng('admin.plans.last_update'), 'field' =&gt; 'ts', 'callback' =&gt; [text::class, 'timestamp'], ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('plan_list', [ 'p.name', 'p.description', 'p.adminname', 'p.ts', ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'plans', 'page' =&gt; 'overview', 'action' =&gt; 'edit', 'id' =&gt; ':id' ], ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'plans', 'page' =&gt; 'overview', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], ], ] ] ];</file><file name="lib/tablelisting/admin/tablelisting.cronjobs.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\text; use froxlor\ui\listing; return [ 'cron_list' =&gt; [ 'title' =&gt; lng('admin.cron.cronsettings'), 'icon' =&gt; 'fa-solid fa-clock-rotate-left', 'default_sorting' =&gt; ['c.id' =&gt; 'asc'], 'no_search' =&gt; true, 'columns' =&gt; [ 'c.desc_lng_key' =&gt; [ 'label' =&gt; lng('cron.description'), 'field' =&gt; 'desc_lng_key', 'callback' =&gt; [text::class, 'crondesc'] ], 'c.lastrun' =&gt; [ 'label' =&gt; lng('cron.lastrun'), 'field' =&gt; 'lastrun', 'callback' =&gt; [text::class, 'timestamp'] ], 'c.interval' =&gt; [ 'label' =&gt; lng('cron.interval'), 'field' =&gt; 'interval' ], 'c.isactive' =&gt; [ 'label' =&gt; lng('cron.isactive'), 'field' =&gt; 'isactive', 'callback' =&gt; [text::class, 'boolean'] ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('cron_list', [ 'c.desc_lng_key', 'c.lastrun', 'c.interval', 'c.isactive', ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'cronjobs', 'page' =&gt; 'overview', 'action' =&gt; 'edit', 'id' =&gt; ':id' ], ] ] ] ];</file><file name="lib/tablelisting/admin/tablelisting.phpconfigs.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\settings; use froxlor\ui\callbacks\admin; use froxlor\ui\callbacks\phpconf; use froxlor\ui\listing; return [ 'phpconf_list' =&gt; [ 'title' =&gt; lng('menue.phpsettings.maintitle'), 'icon' =&gt; 'fa-brands fa-php', 'self_overview' =&gt; ['section' =&gt; 'phpsettings', 'page' =&gt; 'overview'], 'default_sorting' =&gt; ['c.description' =&gt; 'asc'], 'columns' =&gt; [ 'c.id' =&gt; [ 'label' =&gt; 'id', 'field' =&gt; 'id', ], 'c.description' =&gt; [ 'label' =&gt; lng('admin.phpsettings.description'), 'field' =&gt; 'description', 'isdefaultsearchfield' =&gt; true, ], 'domains' =&gt; [ 'label' =&gt; lng('admin.phpsettings.activedomains'), 'field' =&gt; 'domains', 'callback' =&gt; [phpconf::class, 'domainlist'], 'searchable' =&gt; false, 'sortable' =&gt; false, ], 'fpmdesc' =&gt; [ 'label' =&gt; lng('admin.phpsettings.fpmdesc'), 'field' =&gt; 'fpmdesc', 'visible' =&gt; (bool)settings::get('phpfpm.enabled'), 'callback' =&gt; [phpconf::class, 'fpmconflink'] ], 'c.binary' =&gt; [ 'label' =&gt; lng('admin.phpsettings.binary'), 'field' =&gt; 'binary', 'visible' =&gt; !(bool)settings::get('phpfpm.enabled') ], 'c.file_extensions' =&gt; [ 'label' =&gt; lng('admin.phpsettings.file_extensions'), 'field' =&gt; 'file_extensions', ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('phpconf_list', [ 'c.description', 'domains', 'fpmdesc', 'c.binary', 'c.file_extensions' ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'phpsettings', 'page' =&gt; 'overview', 'action' =&gt; 'edit', 'id' =&gt; ':id' ], 'visible' =&gt; [admin::class, 'canchangeserversettings'] ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'phpsettings', 'page' =&gt; 'overview', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], 'visible' =&gt; [phpconf::class, 'isnotdefault'] ] ] ] ];</file><file name="lib/tablelisting/admin/tablelisting.integrity.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\style; use froxlor\ui\callbacks\text; use froxlor\ui\listing; return [ 'integrity_list' =&gt; [ 'title' =&gt; lng('admin.integritycheck'), 'icon' =&gt; 'fa-solid fa-circle-check', 'self_overview' =&gt; ['section' =&gt; 'settings', 'page' =&gt; 'integritycheck'], 'default_sorting' =&gt; ['displayid' =&gt; 'asc'], 'no_search' =&gt; true, 'columns' =&gt; [ 'displayid' =&gt; [ 'label' =&gt; 'id', 'field' =&gt; 'displayid' ], 'checkdesc' =&gt; [ 'label' =&gt; lng('admin.integrityname'), 'field' =&gt; 'checkdesc' ], 'result' =&gt; [ 'label' =&gt; lng('admin.integrityresult'), 'field' =&gt; 'result', 'callback' =&gt; [text::class, 'boolean'], 'searchable' =&gt; false, ] ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('integrity_list', [ 'displayid', 'checkdesc', 'result' ]), 'format_callback' =&gt; [ [style::class, 'resultintegritybad'] ] ] ];</file><file name="lib/tablelisting/admin/tablelisting.filetemplates.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\listing; return [ 'filetpl_list' =&gt; [ 'title' =&gt; lng('admin.templates.filetemplates'), 'icon' =&gt; 'fa-solid fa-file-lines', 'self_overview' =&gt; ['section' =&gt; 'templates', 'page' =&gt; 'email'], 'default_sorting' =&gt; ['template' =&gt; 'asc'], 'no_search' =&gt; true, 'columns' =&gt; [ 'template' =&gt; [ 'label' =&gt; lng('admin.templates.action'), 'field' =&gt; 'template' ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('filetpl_list', [ 'template' ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'templates', 'page' =&gt; $page, 'action' =&gt; 'editf', 'id' =&gt; ':id' ], ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'templates', 'page' =&gt; $page, 'action' =&gt; 'deletef', 'id' =&gt; ':id' ], ], ], ] ];</file><file name="lib/tablelisting/admin/index.html" /><file name="lib/tablelisting/admin/tablelisting.customers.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\customer; use froxlor\ui\callbacks\impersonate; use froxlor\ui\callbacks\progressbar; use froxlor\ui\callbacks\style; use froxlor\ui\callbacks\text; use froxlor\ui\listing; return [ 'customer_list' =&gt; [ 'title' =&gt; lng('admin.customers'), 'description' =&gt; lng('admin.customers_list_desc'), 'icon' =&gt; 'fa-solid fa-user', 'self_overview' =&gt; ['section' =&gt; 'customers', 'page' =&gt; 'customers'], 'default_sorting' =&gt; ['c.name' =&gt; 'asc'], 'columns' =&gt; [ 'c.customerid' =&gt; [ 'label' =&gt; 'id', 'field' =&gt; 'customerid', 'sortable' =&gt; true, ], 'c.name' =&gt; [ 'label' =&gt; lng('customer.name'), 'field' =&gt; 'name', 'callback' =&gt; [text::class, 'customerfullname'], ], 'c.loginname' =&gt; [ 'label' =&gt; lng('login.username'), 'field' =&gt; 'loginname', 'callback' =&gt; [impersonate::class, 'customer'], ], 'a.loginname' =&gt; [ 'label' =&gt; lng('admin.admin'), 'field' =&gt; 'adminname', 'callback' =&gt; [impersonate::class, 'admin'], ], 'c.email' =&gt; [ 'label' =&gt; lng('customer.email'), 'field' =&gt; 'email', ], 'c.street' =&gt; [ 'label' =&gt; lng('customer.street'), 'field' =&gt; 'street', ], 'c.zipcode' =&gt; [ 'label' =&gt; lng('customer.zipcode'), 'field' =&gt; 'zipcode', ], 'c.city' =&gt; [ 'label' =&gt; lng('customer.city'), 'field' =&gt; 'city', ], 'c.phone' =&gt; [ 'label' =&gt; lng('customer.phone'), 'field' =&gt; 'phone', ], 'c.fax' =&gt; [ 'label' =&gt; lng('customer.fax'), 'field' =&gt; 'fax', ], 'c.customernumber' =&gt; [ 'label' =&gt; lng('customer.customernumber'), 'field' =&gt; 'customernumber', ], 'c.def_language' =&gt; [ 'label' =&gt; lng('login.profile_lng'), 'field' =&gt; 'def_language', ], 'c.guid' =&gt; [ 'label' =&gt; 'guid', 'field' =&gt; 'guid', ], 'c.diskspace' =&gt; [ 'label' =&gt; lng('customer.diskspace'), 'field' =&gt; 'diskspace', 'callback' =&gt; [progressbar::class, 'diskspace'], ], 'c.traffic' =&gt; [ 'label' =&gt; lng('customer.traffic'), 'field' =&gt; 'traffic', 'callback' =&gt; [progressbar::class, 'traffic'], ], 'c.deactivated' =&gt; [ 'label' =&gt; lng('admin.deactivated'), 'field' =&gt; 'deactivated', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'], ], 'c.lastlogin_succ' =&gt; [ 'label' =&gt; lng('admin.lastlogin_succ'), 'field' =&gt; 'lastlogin_succ', 'callback' =&gt; [text::class, 'timestamp'], ], 'c.phpenabled' =&gt; [ 'label' =&gt; lng('admin.phpenabled'), 'field' =&gt; 'phpenabled', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'], ], 'c.perlenabled' =&gt; [ 'label' =&gt; lng('admin.perlenabled'), 'field' =&gt; 'perlenabled', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'], ], 'c.dnsenabled' =&gt; [ 'label' =&gt; lng('admin.dnsenabled'), 'field' =&gt; 'dnsenabled', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'], ], 'c.theme' =&gt; [ 'label' =&gt; lng('panel.theme'), 'field' =&gt; 'theme', ], 'c.logviewenabled' =&gt; [ 'label' =&gt; lng('admin.logviewenabled'), 'field' =&gt; 'logviewenabled', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'], ], 'c.api_allowed' =&gt; [ 'label' =&gt; lng('usersettings.api_allowed.title'), 'field' =&gt; 'api_allowed', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'boolean'], ], 'c.type_2fa' =&gt; [ 'label' =&gt; lng('2fa.type_2fa'), 'field' =&gt; 'type_2fa', 'class' =&gt; 'text-center', 'callback' =&gt; [text::class, 'type2fa'], ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('customer_list', [ 'c.name', 'c.loginname', 'a.loginname', 'c.email', 'c.diskspace', 'c.traffic', ]), 'actions' =&gt; [ 'show' =&gt; [ 'icon' =&gt; 'fa-solid fa-eye', 'title' =&gt; lng('usersettings.custom_notes.title'), 'modal' =&gt; [text::class, 'customernotedetailmodal'], 'visible' =&gt; [customer::class, 'hasnote'] ], 'unlock' =&gt; [ 'icon' =&gt; 'fa-solid fa-unlock', 'title' =&gt; lng('panel.unlock'), 'class' =&gt; 'btn-outline-secondary', 'href' =&gt; [ 'section' =&gt; 'customers', 'page' =&gt; 'customers', 'action' =&gt; 'unlock', 'id' =&gt; ':customerid' ], 'visible' =&gt; [customer::class, 'islocked'] ], 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'customers', 'page' =&gt; 'customers', 'action' =&gt; 'edit', 'id' =&gt; ':customerid' ], ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'customers', 'page' =&gt; 'customers', 'action' =&gt; 'delete', 'id' =&gt; ':customerid' ], ], ], 'format_callback' =&gt; [ [style::class, 'resultcustomerlockedordeactivated'] ] ] ];</file><file name="lib/tablelisting/admin/tablelisting.fpmconfigs.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\callbacks\admin; use froxlor\ui\callbacks\phpconf; use froxlor\ui\listing; return [ 'fpmconf_list' =&gt; [ 'title' =&gt; lng('menue.phpsettings.fpmdaemons'), 'icon' =&gt; 'fa-brands fa-php', 'self_overview' =&gt; ['section' =&gt; 'phpsettings', 'page' =&gt; 'fpmdaemons'], 'default_sorting' =&gt; ['description' =&gt; 'asc'], 'columns' =&gt; [ 'id' =&gt; [ 'label' =&gt; 'id', 'field' =&gt; 'id' ], 'description' =&gt; [ 'label' =&gt; lng('admin.phpsettings.description'), 'field' =&gt; 'description', 'isdefaultsearchfield' =&gt; true, ], 'configs' =&gt; [ 'label' =&gt; lng('admin.phpsettings.activephpconfigs'), 'callback' =&gt; [phpconf::class, 'configslist'], 'searchable' =&gt; false, ], 'reload_cmd' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.reload'), 'field' =&gt; 'reload_cmd' ], 'config_dir' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.configdir'), 'field' =&gt; 'config_dir' ], 'pm' =&gt; [ 'label' =&gt; lng('serversettings.phpfpm_settings.pm'), 'field' =&gt; 'pm', ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('fpmconf_list', [ 'description', 'configs', 'reload_cmd', 'config_dir', 'pm' ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'phpsettings', 'page' =&gt; 'fpmdaemons', 'action' =&gt; 'edit', 'id' =&gt; ':id' ], 'visible' =&gt; [admin::class, 'canchangeserversettings'] ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'phpsettings', 'page' =&gt; 'fpmdaemons', 'action' =&gt; 'delete', 'id' =&gt; ':id' ], 'visible' =&gt; [phpconf::class, 'isnotdefault'] ] ] ] ];</file><file name="lib/tablelisting/admin/tablelisting.mailtemplates.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\ui\listing; return [ 'mailtpl_list' =&gt; [ 'title' =&gt; lng('admin.templates.templates'), 'icon' =&gt; 'fa-solid fa-envelope', 'self_overview' =&gt; ['section' =&gt; 'templates', 'page' =&gt; 'email'], 'default_sorting' =&gt; ['template' =&gt; 'asc'], 'no_search' =&gt; true, 'columns' =&gt; [ 'language' =&gt; [ 'label' =&gt; lng('login.language'), 'field' =&gt; 'language' ], 'template' =&gt; [ 'label' =&gt; lng('admin.templates.action'), 'field' =&gt; 'template' ], ], 'visible_columns' =&gt; listing::getvisiblecolumnsforlisting('mailtpl_list', [ 'language', 'template' ]), 'actions' =&gt; [ 'edit' =&gt; [ 'icon' =&gt; 'fa-solid fa-edit', 'title' =&gt; lng('panel.edit'), 'href' =&gt; [ 'section' =&gt; 'templates', 'page' =&gt; $page, 'action' =&gt; 'edit', 'subjectid' =&gt; ':subjectid', 'mailbodyid' =&gt; ':mailbodyid' ], ], 'delete' =&gt; [ 'icon' =&gt; 'fa-solid fa-trash', 'title' =&gt; lng('panel.delete'), 'class' =&gt; 'btn-danger', 'href' =&gt; [ 'section' =&gt; 'templates', 'page' =&gt; $page, 'action' =&gt; 'delete', 'subjectid' =&gt; ':subjectid', 'mailbodyid' =&gt; ':mailbodyid' ], ], ], ] ];</file><file name=".github/ISSUE_TEMPLATE.md"># bug report vs. support request unsure whether problem bug configuration error * contact us via irc #froxlor irc.libera.chat * post thread forum https://forum.froxlor.org rule thumb: reporting issue * see [reported](https://github.com/froxlor/froxlor/issues) (and possibly already [fixed](https://github.com/froxlor/froxlor/issues?utf8=&amp;q=is:issue%20is:closed)) first * try git master # summary please provide concise summary problem experiencing... # system information * froxlor version: $version/$gitsha1 * web server: apache2/nginx/lighttpd * dns server: bind/powerdns (standalone)/powerdns (bind-backend) * pop/imap server: courier/dovecot * smtp server: postfix/exim * ftp server: proftpd/pureftpd * os/version: ... # steps reproduce 1. 2. 3. # expected behavior 1. 2. 3. # actual behavior 1. 2. 3. # log files/log entries syslog: &lt;pre&gt; example &lt;/pre&gt;</file><file name=".github/PULL_REQUEST_TEMPLATE.md"># description please include summary change issue fixed any. please also include relevant motivation context. list dependencies required change. fixes # (issue) ## type change please delete options relevant. - [ ] bug fix (non-breaking change fixes issue) - [ ] new feature (non-breaking change adds functionality) - [ ] breaking change (fix feature would cause existing functionality work expected) - [ ] change requires documentation update # tested? please describe tests ran verify changes. provide instructions reproduce. please also list relevant details test configuration - [ ] test - [ ] test b **test configuration**: * distribution: * webserver: * php: * etc.etc.: # checklist: - [ ] performed self-review code - [ ] commented code, particularly hard-to-understand areas - [ ] made corresponding changes documentation - [ ] changes generate new warnings - [ ] added tests prove fix effective feature works - [ ] new existing unit tests pass locally changes</file><file name=".github/CONTRIBUTING.md"># contribution start working pr, contact us via [discord](https://discord.froxlor.org) forum [https://forum.froxlor.org](https://forum.froxlor.org) get clue whether someone else already working want/need certain change. course, bugfixes always welcome. please always focus **main** branch [github repository](https://github.com/froxlor/froxlor). ## checklist general rules prs are: * please save us trouble unnecessary round-trips _testing_ changes. * re-write commit history provide clean history! * i.e. provide prs contain commit changes something, next changes back, third one changes again, little differently... thanks! ### service changes make changes functionality service configurations, please make sure implementation covers supported services distributions. ### l10n add new language strings, please make sure add english fallback strings `lng/en.php`. ### new settings database-layout changes add new settings implement database-changes, please make sure add * `install/froxlor.sql.php` * handle update (see [`install/updates/froxlor/update_2.x.inc.php`](https://github.com/froxlor/froxlor/blob/main/install/updates/froxlor/update_2.x.inc.php)) * question update-process works, please contact us</file><file name=".github/ISSUE_TEMPLATE/bug_report.md">--- name: bug report about: create report help us improve title: '' labels: '' assignees: '' --- **as rule thumb: reporting issue** * see [reported](https://github.com/froxlor/froxlor/issues) (and possibly already [fixed](https://github.com/froxlor/froxlor/issues?utf8=&amp;q=is:issue%20is:closed)) first * try git master **describe bug** clear concise description bug is. **system information** * froxlor version: $version/$gitsha1 * web server: apache2/nginx/lighttpd * dns server: bind/powerdns (standalone)/powerdns (bind-backend) * pop/imap server: courier/dovecot * smtp server: postfix/exim * ftp server: proftpd/pureftpd * os/version: ... **to reproduce** steps reproduce behavior: 1. go '...' 2. click '....' 3. scroll '....' 4. see error **expected behavior** clear concise description expected happen. **logfiles** applicable, add log-entries help explain problem. **additional context** add context problem here.</file><file name=".github/ISSUE_TEMPLATE/feature_request.md">--- name: feature request about: suggest idea project title: '' labels: '' assignees: '' --- **is feature request related problem? please describe.** clear concise description problem is. ex. i'm always frustrated [...] **describe solution like** clear concise description want happen. **describe alternatives considered** clear concise description alternative solutions features considered. **additional context** add context screenshots feature request here.</file><file name="doc/index.html" /><file name="doc/example/create_customer.php">&lt;?php // include froxlorapi helper class require __dir__ . '/froxlorapi.php'; // create object froxlorapi url, apikey apisecret $fapi = new froxlorapi('http://127.0.0.1/api.php', 'your-api-key', 'your-api-secret'); // customer data $data = [ 'new_loginname' =&gt; 'test', 'email' =&gt; 'test@froxlor.org', 'firstname' =&gt; 'test', 'name' =&gt; 'testman', 'customernumber' =&gt; 1337, 'new_customer_password' =&gt; 's0mecrypt1cpassword' . uniqid() ]; // send request $response = $fapi-&gt;request('customers.add', $data); // check error ($fapi-&gt;getlaststatuscode() != 200) { echo "http-status: " . $fapi-&gt;getlaststatuscode() . php_eol; echo "description: " . $response['message'] . php_eol; exit(); } // view response data var_dump($response); /* array(60) { ["customerid"]=&gt; string(1) "1" ["loginname"]=&gt; string(4) "test" ["password"]=&gt; string(63) "$5$asdasdasd.asdasd" ["adminid"]=&gt; string(1) "1" ["name"]=&gt; string(7) "testman" ["firstname"]=&gt; string(4) "test" [...] */</file><file name="doc/example/list_functions.php">&lt;?php // include froxlorapi helper class require __dir__ . '/froxlorapi.php'; // create object froxlorapi url, apikey apisecret $fapi = new froxlorapi('http://localhost/api.php', 'your-api-key', 'your-api-secret'); // send request $response = $fapi-&gt;request('froxlor.listfunctions'); // check error ($fapi-&gt;getlaststatuscode() != 200) { echo "http-status: " . $fapi-&gt;getlaststatuscode() . php_eol; echo "description: " . $response['message'] . php_eol; exit(); } // view response data var_dump($response);</file><file name="doc/example/index.html" /><file name="doc/example/FroxlorAPI.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ class froxlorapi { private string $url; private string $key; private string $secret; private ?array $lasterror = null; private ?string $laststatuscode = null; public function __construct($url, $key, $secret) { $this-&gt;url = $url; $this-&gt;key = $key; $this-&gt;secret = $secret; } public function request($command, array $data = []) { $payload = [ 'command' =&gt; $command, 'params' =&gt; $data ]; $ch = curl_init($this-&gt;url); curl_setopt($ch, curlopt_httpheader, ['content-type: application/json']); curl_setopt($ch, curlopt_header, 0); curl_setopt($ch, curlopt_userpwd, $this-&gt;key . ":" . $this-&gt;secret); curl_setopt($ch, curlopt_timeout, 30); curl_setopt($ch, curlopt_post, 1); curl_setopt($ch, curlopt_postfields, json_encode($payload)); curl_setopt($ch, curlopt_returntransfer, true); $result = curl_exec($ch); $this-&gt;laststatuscode = curl_getinfo($ch, curlinfo_http_code); return json_decode($result ?? curl_error($ch), true); } public function getlaststatuscode(): ?string { return $this-&gt;laststatuscode; } }</file><file name="templates/index.html" /><file name="templates/Froxlor/config.json">{ "global": { "css": [ "assets/scss/app.scss", "assets/css/custom.css" ], "js": [ "assets/js/app.js", "assets/js/apikey.js" ], "img": { "ui": "logo_white.png", "login": "logo.png" } }, "variants": { "default": { "color-scheme": "light", "description": "default (light)" }, "dark": { "color-scheme": "dark", "img": { "login": "logo_white.png" }, "description": "darkmode" } }, "author": "froxlor" }</file><file name="templates/Froxlor/index.html" /><file name="templates/Froxlor/settings/index.html" /><file name="templates/Froxlor/table/index.html" /><file name="templates/Froxlor/assets/index.html" /><file name="templates/Froxlor/assets/js/app.js">import '@fortawesome/fontawesome-free'; import './bootstrap'; // vue import {createapp} 'vue'; const app = createapp({}); // load jquery components object.entries(import.meta.glob('./jquery/*.js', {eager: true})).foreach(([path, definition]) =&gt; { definition.default(); }); app.mount('#app');</file><file name="templates/Froxlor/assets/js/bootstrap.js">import _ 'lodash'; window._ = _; // jquery import jquery 'jquery'; window.$ = jquery; import 'jquery-validation'; // bootstrap import * bootstrap 'bootstrap'; window.bootstrap = bootstrap; // chartjs import chart 'chart.js/auto'; window.chart = chart; // set default theme window.$theme = 'froxlor'; // axios import axios 'axios'; window.axios = axios; window.axios.defaults.headers.common['x-requested-with'] = 'xmlhttprequest'; window.axios.defaults.headers.common['x-csrf-token'] = document.queryselector('meta[name="csrf-token"]').getattribute('content');</file><file name="templates/Froxlor/assets/js/index.html" /><file name="templates/Froxlor/assets/js/jquery/configfiles.js">export default function () { $(function () { /* * config files - select recommended */ $('#selectrecommendedconfig').on('click', function () { $('input[data-recommended]').each(function () { ($(this).data('recommended') == 1) { $(this).prop('checked', true); } else { $(this).prop('checked', false); } }) }); /* * export/download json file (e.g. usage config-services) */ $('#downloadselectionasjson').on('click', function () { var formdata = $(this).closest('form').serialize(); window.location = "lib/ajax.php?action=getconfigjsonexport&amp;" + formdata; }); /* * open modal window show selected config-commands/files * selected daemon */ $('.show-config').on('click', function () { const distro = $(this).data('dist'); const section = $(this).data('section'); const daemon = $(this).data('daemon'); $.ajax({ url: "lib/ajax.php?action=getconfigdetails", type: "post", datatype: "json", data: {distro: distro, section: section, daemon: daemon}, success: function (data) { $('#configtplshowlabel').html(data.title); $('#configtplshow .modal-body').html(data.content); const mymodal = new bootstrap.modal(document.getelementbyid('configtplshow')); mymodal.show(); }, error: function (request, status, error) { $('#configtplshowlabel').html('error'); $('#configtplshow .modal-body').html('&lt;div class="alert alert-danger" role="alert"&gt;' + request.responsejson.message + '&lt;/div&gt;'); const mymodal = new bootstrap.modal(document.getelementbyid('configtplshow')); mymodal.show(); } }); }); }); }</file><file name="templates/Froxlor/assets/js/jquery/search.js">export default function () { $(function () { /* * search */ let search = $('#search') search.on('submit', function (e) { e.preventdefault(); }); search.find('input').on('keyup', function () { let query = $(this).val(); let dropdown = $('#search .search-results'); // hide search query empty (!query.length) { dropdown.html(''); dropdown.parent().hide(); return; } // show notification short search query (query.length &amp;&amp; query.length &lt; 3) { dropdown.html('&lt;li class="list-group-item text-body-secondary py-1"&gt;please enter 2 characters&lt;/li&gt;'); dropdown.parent().show(); return; } // search $.ajax({ url: "lib/ajax.php?action=searchglobal&amp;theme=" + window.$theme, type: "post", data: { searchtext: query }, datatype: "json", success: data =&gt; { // show notification got results (object.keys(data).length === 0) { dropdown.html('&lt;li class="list-group-item text-body-secondary py-1"&gt;nothing found!&lt;/li&gt;'); dropdown.parent().show(); return; } // clear dropdown show results dropdown.html(''); dropdown.parent().show(); object.keys(data).foreach(key =&gt; { dropdown.append('&lt;li class="list-group-item text-body-secondary text-capitalize fw-bold py-1 border-bottom"&gt;' + key + '&lt;/li&gt;'); data[key].foreach(item =&gt; { dropdown.append('&lt;li class="list-group-item mt-1"&gt;&lt;a href="' + item.href + '" tabindex="2" class="text-decoration-none"&gt;' + item.title + '&lt;/a&gt;&lt;/li&gt;'); }); }); }, error: function (a, b) { console.log(a, b); dropdown.html('&lt;li class="list-group-item text-body-secondary py-1"&gt;whoops got errors!&lt;/li&gt;'); dropdown.parent().show(); } }); }); }); }</file><file name="templates/Froxlor/assets/js/jquery/traffic.js">export default function () { $(function () { /* * traffic - display helptext content box according dns-record type selected */ $("select[name='range']").on('change', function () { var selval = $(this).val(); var baseref = $(this).data('baseref'); window.location.href = baseref + '?range=' + selval; }); }); }</file><file name="templates/Froxlor/assets/js/jquery/customer.js">export default function () { $(function () { // make inputs enabled unlimited checked disabled $("input[name$='_ul']").each(function () { var fieldname = $(this).attr("name").substring(0, $(this).attr("name").length - 3); $("input[name='" + fieldname + "']").prop({ readonly: $(this).is(":checked"), required: !$(this).is(":checked") }); }); // change state unlimited checkboxes clicked $("input[name$='_ul']").on('change', function () { var fieldname = $(this).attr("name").substring(0, $(this).attr("name").length - 3); $("input[name='" + fieldname + "']").prop({ readonly: $(this).is(":checked"), required: !$(this).is(":checked") }); (!$(this).is(":checked")) { $("input[name='" + fieldname + "']").focus() } }); // set values hosting plan adding/editing customer according plan's values $('#use_plan').on('change', function () { var pid = $(this).val(); (pid &gt; 0) { $.ajax({ url: "admin_plans.php?page=overview&amp;action=jqgetplanvalues", type: "post", data: { planid: pid }, datatype: "json", beforesend: function (request) { request.setrequestheader('x-csrf-token', document.queryselector('meta[name="csrf-token"]').getattribute('content')); }, success: function (json) { (var json) { (i == 'email_imap' || == 'email_pop3' || == 'perlenabled' || == 'phpenabled' || == 'dnsenabled' || == 'logviewenabled') { /** handle checkboxes **/ (json[i] == 1) { $("input[name='" + + "']").prop('checked', true); } else { $("input[name='" + + "']").prop('checked', false); } } else (i == 'allowed_phpconfigs') { /** handle array values **/ $("input[name='allowed_phpconfigs[]']").each(function (index) { $(this).prop('checked', false); (var j json[i]) { ($(this).val() == json[i][j]) { $(this).prop('checked', true); break; } } }); } else (json[i] == -1) { /** handle unlimited checkboxes **/ $("input[name='" + + "_ul']").attr('checked', 'checked'); $("input[name='" + + "']").prop({ readonly: true }); } else { /** handle normal value **/ $("input[name='" + + "']").val(json[i]); $("input[name='" + + "']").prop({ readonly: false }); $("input[name='" + + "_ul']").prop('checked', false); } } }, error: function (a, b) { console.log(a, b); } }); } }); }); }</file><file name="templates/Froxlor/assets/js/jquery/dnseditor.js">export default function () { $(function () { // display helptext content box according dns-record type selected $("select[name='dns_type']").on('change', function () { var selval = $(this).val(); $.ajax({ url: "lib/ajax.php?action=loadlanguagestring", type: "post", datatype: "json", data: {langid: 'dnseditor.notes.' + selval}, success: function (data) { $("#dns_content").next().html(data); }, error: function (request, status, error) { console.log(request, status, error) } }); }); }); }</file><file name="templates/Froxlor/assets/js/jquery/newsfeed.js">export default function () { $(function () { /* * newsfeed */ (document.getelementbyid('newsfeed')) { let role = ""; (typeof $("#newsfeed").data("role") !== "undefined") { role = "&amp;role=" + $("#newsfeed").data("role"); } $.ajax({ url: "lib/ajax.php?action=newsfeed" + role + "&amp;theme=" + window.$theme, type: "get", success: function (data) { $("#newsfeeditems").html(data); }, error: function (request, status, error) { console.log(request, status, error) $("#newsfeeditems").html('&lt;div class="list-group-item text-center"&gt;&lt;span class="badge bg-warning" role="alert"&gt;error loading newsfeed&lt;/span&gt;&lt;/div&gt;'); } }); } }); }</file><file name="templates/Froxlor/assets/js/jquery/install.js">export default function () { $(function () { /* * switch basic advanced installation mode */ $('#switchinstallmode').on('click', function () { var checked = $(this).prop('checked'); window.location = window.location.pathname + replacequeryparam('extended', +checked, window.location.search); }); function replacequeryparam(param, newval, search) { var regex = new regexp("([?;&amp;])" + param + "[^&amp;;]*[;&amp;]?"); (search.match(regex)) { search = search.replace(regex, "$1").replace(/&amp;$/, ''); } return search + '&amp;' + param + '=' + newval; } function checkconfigstate() { $.ajax({ url: window.location.href, type: "get", success: function (data, textstatus, request) { (request.status &gt;= 300) { window.location = "http://" + srvname; } }, error: function (request, textstatus, errorthrown) { // continue (request.status &gt;= 300) { window.location = "http://" + srvname; } } }); } var ctimer; /** * check manual-config switch */ $('#manual_config').on('click', function () { clearinterval(ctimer); var checked = $(this).prop('checked'); (checked) { // button zum login $('#submitauto').addclass('d-none'); $('#submitmanual').removeclass('d-none'); } else { ctimer = setinterval(checkconfigstate, 1000); // spinner frs warten $('#submitauto').removeclass('d-none'); $('#submitmanual').addclass('d-none'); } }); ($('#manual_config').length &gt; 0) { var srvname = $('#target_servername').val(); clearinterval(ctimer); ctimer = setinterval(checkconfigstate, 1000); } }); }</file><file name="templates/Froxlor/assets/js/jquery/tablecolumns.js">export default function () { $(function () { /* * table columns - manage columns modal */ $('.managecolumnsmodal form').on('submit', function (event) { $.ajax({ url: 'lib/ajax.php?action=updatetablelisting&amp;listing=' + $(this).data('listing') + '&amp;theme=' + window.$theme, type: 'post', datatype: 'json', data: $(this).serialize(), success: function () { window.location.href = ''; }, error: function (request) { alert(request.responsejson.message); } }); event.preventdefault(); }); $('.managecolumnsmodal form button[data-action="reset"]').on('click', function () { var form = $(this).parents('form:first'); $.ajax({ url: 'lib/ajax.php?action=resettablelisting&amp;listing=' + form.data('listing') + '&amp;theme=' + window.$theme, type: 'post', datatype: 'json', data: {}, success: function () { window.location.href = ''; }, error: function (request) { alert(request.responsejson.message); } }); }); $('.managecolumnsmodal form button[data-action="select-all"]').on('click', function () { $(this).parents('form:first').find('input:checkbox').prop('checked', true); }); $('.managecolumnsmodal form button[data-action="unselect-all"]').on('click', function () { $(this).parents('form:first').find('input:checkbox').prop('checked', false); }); }); }</file><file name="templates/Froxlor/assets/js/jquery/validation.js">export default function () { $(function () { /* * validation */ $('#customer_add,#customer_edit').each(function () { $(this).validate({ rules: { 'name': { required: function () { return $('#company').val().trim().length === 0 || $('#firstname').val().trim().length &gt; 0; } }, 'firstname': { required: function () { return $('#company').val().trim().length === 0 || $('#name').val().trim().length &gt; 0; } }, 'company': { required: function () { return $('#name').val().trim().length === 0 &amp;&amp; $('#firstname').val().trim().length === 0; } } }, }); }); $('#domain_add,#domain_edit').each(function () { $(this).validate({ rules: { 'ipandport[]': { required: true, minlength: 1 } }, errorplacement: function (error, element) { $(error).prependto($(element).parent().parent()); } }); }); }); }</file><file name="templates/Froxlor/assets/js/jquery/domains.js">export default function () { $(function () { /* * domains */ // disable unusable php-configuration customer settings $('#customerid').on('change', function () { var cid = $(this).val(); $.ajax({ url: "admin_domains.php?page=domains&amp;action=jqgetcustomerphpconfigs", type: "post", data: { customerid: cid }, datatype: "json", beforesend: function (request) { request.setrequestheader('x-csrf-token', document.queryselector('meta[name="csrf-token"]').getattribute('content')); }, success: function (json) { (json.length &gt; 0) { $('#phpsettingid option').each(function () { var pid = $(this).val(); $(this).attr("disabled", "disabled"); (var json) { (pid == json[i]) { $(this).removeattr("disabled"); } } }); } }, error: function (a, b) { console.log(a, b); } }); }); // show warning speciallogfile option toggled ($('input[name=speciallogverified]')) { $('input[name=speciallogfile]').on('click', function () { $('#speciallogfilenote').remove(); $('#speciallogfile').removeclass('is-invalid'); $('#speciallogverified').val(0); const cfilename = window.location.pathname.substring(window.location.pathname.lastindexof("/")+1); $.ajax({ url: cfilename + "?page=overview&amp;action=jqspeciallogfilenote", type: "post", data: { id: $('input[name=id]').val(), newval: +$('#speciallogfile').is(':checked') }, datatype: "json", async: false, beforesend: function (request) { request.setrequestheader('x-csrf-token', document.queryselector('meta[name="csrf-token"]').getattribute('content')); }, success: function (json) { (json.changed) { $('#speciallogfile').addclass('is-invalid'); $('#speciallogfile').parent().append(json.info); $('#speciallogverified').val(1); } }, error: function (a, b) { console.log(a, b); } }); }); } /** * email domain - hide unnecessary/unused sections */ ($('#id') &amp;&amp; $('#email_only').is(':checked')) { $('#section_b').hide(); $('#section_bssl').hide(); $('#section_c').hide(); } /** * toggle show/hide sections case email flag */ $('#email_only').on('click', function () { ($(this).is(':checked')) { // hide unnecessary sections $('#section_b').hide(); $('#section_bssl').hide(); $('#section_c').hide(); } else { // show sections $('#section_b').show(); $('#section_bssl').show(); $('#section_c').show(); } }) /** * ssl enabled domain - hide unnecessary/unused sections */ ($('#id') &amp;&amp; !$('#sslenabled').is(':checked')) { $('#section_bssl&gt;.formfields&gt;.row').not(":first").addclass("d-none"); } /** * toggle show/hide sections case ssl enabled flag */ $('#sslenabled').on('click', function () { ($(this).is(':checked')) { // show sections $('#section_bssl&gt;.formfields&gt;.row').removeclass("d-none"); } else { // hide unnecessary sections $('#section_bssl&gt;.formfields&gt;.row').not(":first").addclass("d-none"); } }) }); }</file><file name="templates/Froxlor/assets/js/jquery/ipsandports.js">export default function () { $(function () { /* * ipsandports - check internal ip output notice private-range ip given */ $('#ip').on('change', function () { var ipval = $(this).val(); (ipval.length &gt; 0) { $('#ipnote').remove(); $('#ip').removeclass('is-invalid'); $.ajax({ url: "admin_ipsandports.php?page=overview&amp;action=jqcheckip", type: "post", data: { ip: ipval }, datatype: "json", beforesend: function (request) { request.setrequestheader('x-csrf-token', document.queryselector('meta[name="csrf-token"]').getattribute('content')); }, success: function (json) { (json != 0) { $('#ip').addclass('is-invalid'); $('#ip').parent().append(json); } }, error: function (a, b) { console.log(a, b); } }); } }); }); }</file><file name="templates/Froxlor/assets/js/jquery/updatecheck.js">export default function () { $(function () { /* * updatecheck */ (document.getelementbyid('updatecheck')) { runcheck(); } function runcheck(force = 0) { $.ajax({ url: "lib/ajax.php?action=updatecheck&amp;theme=" + window.$theme + "&amp;force=" + force, type: "get", success: function (data) { $("#updatecheck").html(data); const po = new bootstrap.popover(document.getelementbyid('ucheck')); const mypopovertrigger = document.getelementbyid('ucheck') mypopovertrigger.addeventlistener('shown.bs.popover', () =&gt; { $('#forceupdatecheck').on('click', function () { runcheck(1); po.hide(); }); }) }, error: function (request, status, error) { console.log(request, status, error) let message = 'can\'t check version'; $("#updatecheck").html('&lt;span id="ucheck" class="text-decoration-none badge bg-warning mt-2 me-2" data-bs-toggle="tooltip" data-bs-placement="left" title="' + message + '"&gt;&lt;i class="fa-solid fa-exclamation-triangle"&gt;&lt;/i&gt; &lt;span class="d-md-none d-xl-inline"&gt;' + message + '&lt;/span&gt;&lt;/span&gt;'); new bootstrap.tooltip(document.getelementbyid('ucheck')); } }); } }); }</file><file name="templates/Froxlor/assets/js/jquery/global.js">export default function () { $(function () { /* * global */ $('#historyback').on('click', function (e) { e.preventdefault(); history.back(1); }) $('[data-bs-toggle="popover"]').each(function () { new bootstrap.popover($(this)); }) (!window.issecurecontext) { // hide copyclipboard buttons works secure context $('.copyclipboard').hide(); } $('.copyclipboard').on('click', function (e) { e.preventdefault(); const source_element = $(this).data('clipboard-source'); navigator.clipboard.writetext($('#' + source_element).text().trim()); }) }); }</file><file name="templates/Froxlor/assets/js/jquery/emails.js">export default function () { $(function () { /** * bypass spam - hide unnecessary/unused sections */ ($('#id') &amp;&amp; $('#bypass_spam').is(':checked')) { $('#spam_tag_level').closest('.row').addclass('d-none'); $('#spam_rewrite_subject').closest('.row').addclass('d-none'); $('#spam_kill_level').closest('.row').addclass('d-none'); $('#policy_greylist').closest('.row').addclass('d-none'); } /** * toggle show/hide sections case bypass spam flag */ $('#bypass_spam').on('click', function () { ($(this).is(':checked')) { // hide unnecessary sections $('#spam_tag_level').closest('.row').addclass('d-none'); $('#spam_rewrite_subject').closest('.row').addclass('d-none'); $('#spam_kill_level').closest('.row').addclass('d-none'); $('#policy_greylist').closest('.row').addclass('d-none'); } else { // show sections $('#spam_tag_level').closest('.row').removeclass('d-none'); $('#spam_rewrite_subject').closest('.row').removeclass('d-none'); $('#spam_kill_level').closest('.row').removeclass('d-none'); $('#policy_greylist').closest('.row').removeclass('d-none'); } }) }); }</file><file name="templates/Froxlor/assets/js/jquery/apikeys.js">export default function () { $(function () { var timer, delay = 650; $('div[data-action="apikeys"] #allowed_from').on('keyup change', function () { var _this = $(this); cleartimeout(timer); timer = settimeout(function () { var akid = _this.closest('div[data-action="apikeys"]').data('entry'); $.ajax({ url: "lib/ajax.php?action=editapikey", type: "post", datatype: "json", data: { id: akid, allowed_from: _this.val(), valid_until: $('div[data-entry="' + akid + '"] #valid_until').val() }, success: function (data) { (data.message) { _this.removeclass('is-valid'); _this.addclass('is-invalid'); } else { _this.removeclass('is-invalid'); _this.addclass('is-valid'); _this.val(data.allowed_from); } }, error: function (request, status, error) { _this.removeclass('is-valid'); _this.addclass('is-invalid'); } }); }, delay); }); $('div[data-action="apikeys"] #valid_until').on('keyup change', function () { var _this = $(this); cleartimeout(timer); timer = settimeout(function () { var akid = _this.closest('div[data-action="apikeys"]').data('entry'); $.ajax({ url: "lib/ajax.php?action=editapikey", type: "post", datatype: "json", data: { id: akid, valid_until: _this.val(), allowed_from: $('div[data-entry="' + akid + '"] #allowed_from').val() }, success: function (data) { (data.message) { _this.removeclass('is-valid'); _this.addclass('is-invalid'); } else { _this.removeclass('is-invalid'); _this.addclass('is-valid'); //_this.val(data.valid_until); } }, error: function (request, status, error) { _this.removeclass('is-valid'); _this.addclass('is-invalid'); } }); }, delay); }); }); }</file><file name="templates/Froxlor/assets/js/jquery/index.html" /><file name="templates/Froxlor/assets/scss/index.html" /><file name="templates/Froxlor/assets/scss/components/index.html" /><file name="templates/Froxlor/user/index.html" /><file name="templates/Froxlor/misc/index.html" /><file name="templates/Froxlor/form/index.html" /><file name="templates/Froxlor/install/index.html" /><file name="templates/Froxlor/login/index.html" /><file name="templates/misc/index.html" /><file name="templates/misc/awstats/index.html">&lt;!doctype html&gt; &lt;html&gt; &lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;title&gt;awstats {site_domain}&lt;/title&gt; &lt;/head&gt; &lt;frameset cols="*" rows="45,*" frameborder=0&gt; &lt;frame id="topframe" name="topframe" noresize="noresize" scrolling="no" src="nav.html" title="topframe"&gt; &lt;frame id="mainframe" name="mainframe" src="current/awstats.{site_domain}.html" title="mainframe"&gt; &lt;noframes&gt; &lt;body&gt; &lt;/body&gt; &lt;/noframes&gt; &lt;/frameset&gt; &lt;/html&gt;</file><file name="templates/misc/awstats/nav.html">&lt;!doctype html&gt; &lt;html&gt; &lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;title&gt;navigation&lt;/title&gt; &lt;style type="text/css"&gt; /* include froxlor theming */ html, body { margin: 0; height: 100%; font: 12px/18px 'lucida grande', 'lucida sans unicode', helvetica, arial, verdana, sans-serif; color: #444; text-align: center; background: none repeat scroll 0 0 rgba(240, 242, 244, 0.85); border-bottom: 1px solid #ddd; box-sizing: border-box; -webkit-font-smoothing: subpixel-antialiased; } select { padding: 6px 4px 7px 24px; color: #333; border: 1px solid #d9d9d9; margin: 5px 5px 5px 0; border-radius: 3px; background: url(data:image/png;base64,ivborw0kggoaaaansuheugaaaacaaaaecayaaabcxiv9aaaktwldq1bqag90b3nob3agsundihbyb2zpbguaabjtny93wfnpfsa/e296osveopdeq5uqqksekibfuijejeaoiyqeflsikqgoktiuquyfhhb0kdjwrlewidbsaziiqopgkkkiskh3wx1259mdnfep8/2e8533faaofofcuqasbec6scoj8/veo2niuxwpgaer4iatafxeljhogu84kmvfm4nmyyvav0eavlk9ewg4wfqlqvhw/0mzj5zi5w1c5gzpf2tx5jwn57qcqxgmpy5n+plugyyxmyyrlyhntrlo+skwn2u+spsm89nffdnp7czmp/nnufpom7jlajkjgxlozxykcur8u86gabj0ozzfznjtbdwsadcumbxuweuws42ckzlwmi6c5wbaocr9w0u+yalgqxtmke6gejlemjqsru15zqitkxmb9rpkpamkumyil5fklfbrtka6mctabscxmz9ljsvm1xp19+awbj1ylkadls34qv/6+rcvhrolfqfxoqcspxcj+2vuz+oyagbgtwcabp+aw1igqosgantufc0z7gdamq+alt5v7mhit0wtpvkxs7v1tk6olvdas+ilfzpnfxb8bx0zz2qmhcvwicvi2lnzol6crk4styqg+xqiviy0djkezrjzeqkuiwbjc9/0+nvgp9/dmkyqkjairhjhpfcqixqlozwmev8ofwaiukeilu/717bvovxn278pw279dltat4aebwwueuka+a0byghkgmttk/9a0tgx6oeaqgikcjg/uboj6qju1j9bqp/zfs6acvncpm8+tlg4ypnjsr/8ywycfpcaiqaddaaddiapyai74ahcgdvwbvnamaghmwax4ifkka4kiaesagtbpige28fuua6qqc2oa43ggggfj8e5cbfcbdfalxafdibh8aymgzdgcoigpesfaja6paszqraqhcsg5kleucaubsvacvasjijk0apopvqifupludvub/0anydoqzehpugunainqx9a72eepsb0wbs2hq1hnuwbb8dh8ci4cc6ec+e8ebtcctfar+aw+bx8fb4fd8dp4akeigsegeghtisncjbgjbzjrctikqqakufqkeakhelcbiadyhpkhqahowfqdbpjgvhdrgb4mezmkswwtdnmmkyf04m5grnejgm+yalylawf1hnrj43gjmfzspnyeuxbbdp2avywdhj7bofdmxamoeechy4gl4jbjtuc24trwp3f9eggcbn4pf4db4f3xqfjuxgpph9fhj+cp4o/jh/gvywqcboeo4ipizygiqwjlbdqcacj1wkjhcmietgi6ewmjvkjy4hfxfpio7gxoeyciimtteiuphbscmktqztuslpaekb6rsat9clo5fcyklygxeo+sr5ehis/o6hqzckcshxfrtlgouq5s7lleuwluo2p7tryqps6jvphpu99rh2rqfowuvbx4cusvqhqafg4rvbckahopoihufgxv7fe8bhir+jzjakssrjhiau0sqlc6yrsv9kemk3zvjlyov15i3k98mxlurw8irgktwpfju/lgmp5lseaqjogcwg82npale0cbzioo5vq/ekp9el69/qe+riqiups1ujvpaovqqdubxgiw5jhz0hjfdgomw4z3s/snuuxszbr86zgwddntappqrmrcdqk1jrubqm9v0fvvdvt1xeot6o/1mbomgueauro7no4opfck67posntlna8pnlpc9yy1wrtwq51qktba0jbr9txw6xdpn1e+7koq8ddj0vnl85pntfdmu5cxahult0zuk9rvdqdtunl0u50xe9lz09pplet16m3pw+ih6g/tr9j/6ebyybtkgiwy6ddynxq1zdicivhg+e9i6ir2yjzai9rl9gksylxlpfg41bjurm1e3+txjmgkwemvfm300ztgtobzjgztlmq2v6za+awuyn5snmfea8fbmgyefrsteizxfo6wyosayz7mrsmbzob2cactgjybvqts2q1emftab1rvco6y/qtjynnmk2tzx1bfdt5tuts223/sdo349lv2n20p9r72k+2b7n/odtitmd2vtl3hggoqq4bhtocpricwrjwi2vm0daxwbhssz9nz4ewt7avowgdpj1wo510eufmcpy6h3p+3yxpkups7zi6x2soye7tncfxfveua7xrwfx0bslc/xmh3ptcug41bo/dddz57gfdrzzmpfi8jni88ltxlhg2e05yndkrowe9ec9frwkvhm8v7wjvcu9hpvo+st4npuo+dr7lfc/6yf0c/hb49ftr+/p86/zh5znowzmvm4assccgpobxohmgjla9ca6af7qz6mf8o/mi+a3bing/egfwwxctkmyqn0jxosghfafpwmzdvor1laatif9qv+bnugd4ufj9cnmiwurhpgjkxgrd5gsuv1rx1ec0dftk6ksxgjhcmlzyfgxk7mhyiyxec3cvhi5zimupu73iznhsrzcxayxow3wqxjgeg388azsqlvcf8iebzk3htizxx1k5zjzh4e3hpeo783fxxwsugmlbskjrynhiajjr0s6ksws35jlk50kosfz4msuvpsplmju49vdqdfpuwlm6it0h/yrirzqq6szqyvia0se2eoelbzkdm3dnjkscjaezokxfww1sulqs7zazyjbibrpnzldkv82jzdm+vhmpagn3mvnlm5en5prkfrccs5y3vgof3oq1kwzxeqysxgwtwrkqy7xb6rzvw2t81xxes1qbuvbndtbrite9xh+1vj1po29n3tag3w0n+qr5kvz+js4bqzzhngk39wy231y2+vmbv+bkou1hseghlbwtv7babi3dor0tcvtpeato33bcdth22zvcdhwuvi7olr7agbszzre6q2dx693xuy+xzc6p2kpai9szubpy2lzmwla97en5cvmtcs+kpkqtys2vk3v5e6/vc9/xwkvdvvj1fr9w/51q3+qwguoakgo4a9khntrg1nz9x/6u7qdgwckdhw+jdg0cdjvcwedyv1evvv/uadfigsaoxb259r3x922nzmbqjkzt4vfwvhb06q8jp9w+fncs4zj7eooprj9wntoac1qglmut463jrqntmw19j+ad6gh3aw/+yeqnqyf1tlacuj1vdjp0ou/09jncmxnnxwefn0s6n9qr33h/fpt5m52hnt0xai5cuuhz8xyxr9ezs66xtl52vnzicvtk61xw1zzuh+7mnx1+bu5h9bt0ova2xxo61t43p+/0dbfr52543bh40//m1vvzb/xdjrh9pz+uf+ao/87o3bs7l+9l35u6v+yb9khbq6whjy+0htx8yvzl0wbr4nsg12d34wwp7w/xhp79mvxrh+g8j9qnjso6i3wjdqmnx3zgrj1d+ht4mfjz1pp835r/q3xh+ulh391/7x6phh9+kxk5/cewv+qvdr2e/bpjimti0zv0n1otbw/v3x5+x37x9t7q/chuzgf8h9kpzh/bpwv8ejcdpj39dwoy8/wro+xuaaaaigniuk0aaholaacagwaa+f8aaidpaab1maaa6maaadqyaaaxb5jfxuyaaaajcehzcwaacxmaaastaqcanbgaaaajsurbvbjty+jo6pipczmacqkckhigswwkqhwgmcsyagmygadwzd0hswpvywaaaabjru5erkjggg==) no-repeat 9px; min-width: 170px; text-indent: 0.01px; text-overflow: ''; -webkit-appearance: none; -moz-appearance: none; appearance: none; } &lt;/style&gt; &lt;script&gt; function change_page() { top.mainframe.location= document.periodform.periodselect.value + '/awstats.{site_domain}.html'; } &lt;/script&gt; &lt;/head&gt; &lt;body&gt; &lt;form action="#" id="periodform" method="get" name="periodform"&gt; &lt;b&gt;select period&lt;/b&gt; &lt;select name="periodselect" onchange="change_page()"&gt; &lt;option value="current"&gt;current&lt;/option&gt; {select_entries} &lt;/select&gt; &lt;/form&gt; &lt;/body&gt; &lt;/html&gt;</file><file name="templates/misc/deactivated/index.html">&lt;!doctype html&gt; &lt;html lang="en"&gt; &lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;meta name="robots" content="noindex, nofollow"&gt; &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt; &lt;title&gt;froxlor - deactivated page&lt;/title&gt; &lt;style&gt; :root{--primary:#1872a2;--fonts:ui-sans-serif,system-ui,-apple-system,blinkmacsystemfont,"segoe ui",roboto,"helvetica neue",arial,"noto sans",sans-serif,"apple color emoji","segoe ui emoji","segoe ui symbol","noto color emoji"} body{display:flex;flex-direction:column;background:#f8f9fa;color:#4b5563;align-items:center;justify-content:center;font-family:var(--fonts)} main{background:#fff;margin:10% auto 12px;max-width:540px;padding:2rem;box-shadow:4px 8px 16px 0 rgba(0,0,0,.07);border-radius:.375rem} main h2{margin:0} main p{margin-bottom:1.5rem} main p:last-child{margin-bottom:0} main ul{list-style:none;margin-left:-40px} main li{display:flex;align-items:center;margin-bottom:1rem} main .icon{min-width:24px;width:24px;stroke:var(--primary);margin-right:.75rem} code{background:#eee;padding:.1rem .25rem;border-radius:4px;color:rgba(0,0,0,.75)} hr{margin:2rem 0;border:none;border-bottom:solid 1px rgba(0,0,0,.1)} a,a:active,a:visited{color:var(--primary);text-decoration:none} a:hover{text-decoration:underline} footer{display:flex;align-items:center;margin-top:.5rem} footer .logo{margin-right:.35rem} @media (prefers-color-scheme: dark) { :root{--primary:#29a2d6} body{background:#212529;color:#f8f9fa} main{background:#343a40} hr{border-color:rgba(0,0,0,.2)} } &lt;/style&gt; &lt;/head&gt; &lt;body&gt; &lt;main&gt; &lt;h2&gt;domain deactivated&lt;/h2&gt; &lt;p&gt; domain managed using &lt;a href="https://froxlor.org" rel="external"&gt;froxlor server management panel&lt;/a&gt;. see page, domain deactivated administrator. &lt;/p&gt; &lt;ul&gt; &lt;li&gt; &lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="1.5" stroke="currentcolor" class="icon"&gt; &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021m21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008h12v8.25z" /&gt; &lt;/svg&gt; &lt;span&gt;please ask provider/hoster questions.&lt;/span&gt; &lt;/li&gt; &lt;/ul&gt; &lt;/main&gt; &lt;footer&gt; &lt;img class="logo" src="data:image/png;base64,ivborw0kggoaaaansuheugaaaegaaaaqcayaaac1mdndaaaacxbiwxmaaastaaaleweampwyaaakt2ldq1bqag90b3nob3agsundihbyb2zpbguaahjanvnnvfppfj333vrcs4ialetvuhuiifjci4auksyqiqkqsoghodkvucerruueg8igiaoojocmfvesdiok2afkiakog6oiisr74xuja9a89+bn/rxxpues852zzwfacaywsdnrnyamquieeecdx8tg4equqiekjhaaeaizzcfz/smbaph+pdwrisahvgabenmlcadatzvambyh/w/qqplcayceacb0kthlciauaeb6jkkmaebgaycdmcztakaeagdly2ljafataganf+btaicd+jl7aqbblcevaacracatzyheagg7akzpvopfafgwabrms8q5angtadbjv2zialc3amdoeauyaagmadbriiupaar7agdiiyn4aiszabrg8lc88suueocqaab4mbi8usq5ryfbcc1xb1dxlh4ozkkxkxq2yqjhmkauwnmzgtkbna/g88waakcrfrhgg/p9em4ors7ono62dl8t6r8g/yjiyup+5c+rceaaaof0fth+lc+zgoa7bobt/qil7groxgugdfelzripqluaoonav/nw+h48pewhklnz2exk5nhkxejbycpxff5nwl/av/1s+x48/pf14l7ijieyxyfhbpjgwsz0tkucz5ijhglc5o9h/lcl//wd0yleswk5wcou41escy5emozzmquiiukskcul0v9k4t8s+wm+3zuasgo+axurlahdywp2sycqwhta4vcaapk7b8hukagdggid4c93/+8//uegjqcazkmscqaaxkqklltksz/hcaaarkcbkrbbg/tbgczabhzbbdzbc/xgnorcjmtcqhbccmsahhjgkaycqiigzbadkmav1eadnmbraiatca4uwlw4dj1wd/phcj7bklybcqrbyagtyshaiafiilgjjggxmyx4icfibbkljcdjibrrikurnugxuopuifvihfi9cgi5h1xgupe7yaaygvygvecxligyut3udlvduag3gorgogvqzhqxmo8wojvqcrqapyw2oefqq2gp2o8+q8cwwogybzpebdauxsncstgscznjy7eirayrxhqwvqwdu4n1y8+xdwqsguxactyed0igyr5bsfhmwe7yskgghcq0edojnwkdhfhcjyktqeu0jror+cqyyjixh1hilcpweo8tlxb7iepenyqsiumyj7mqakmxpftsetjg0m5si+ksqzs0sbojk8nazguybzmulcaryixknetd5dpkg+qh8lsknwjacat4u+iouspqshnleou05qzlmdjbvaoaut2oovqrny9aqq2htlkvuyeoezr1mjnngxzjs6wtopxtgmgxapdpr+h0uhhdlr5ol9bx0svpr+ix6ap0dwwnhhwdx4hnkbmbgacyzxl3gk+ytkyz04szx1qwnzhrmoezd5lvvvgqtip8fzhkcpvklsavgyovvkmqpqreqgtv81xlvi+pxln9rkzvm1pjqqnulqtvqp1q61mbu2epo6ihqmeob1q/ph5z/ykgwcnmw09dpfggsv/jvmygc2mzs3gsiwsnq4z1gtxejrhn2xx2kruy/r27iz2qqae5qznkm1ezuvouzj8h45hx+jx0tgnnkkex836k3htvkeipg6y0tlkxzvxrqpaxllirsktrq0frvtau7aedpr1fu1n7gq5bx0onxcdhz4/obz3nu9lt3ackpxznptr1ri6qa6ubobted79up+6ynr5egj5mb6feeb3n+hx9l/1u/w36p/vhdfggswwkbtsmzhg8xtvxbzwdl8fb8vfdxcnaq6vhlwgx4ysrude8o9vgjuypjgngxomk423gbcajjgymiszltepn7ppstbmmkay7tdtmx83mzaln1pk1mz0x1zlnm+eb15vft2baefostqi2ugvjsuraplnutrxuhvo5wavyvvpds0atna0l1rutu6crp7lok06rntznw7dxtsm2qbczsoxybtuutm22fwfnyhdnt8wuw+6tvzn9un2n/t0hdyfzdqsdwh1+c7ryfdpwot6azpzup33f9jbpl2dyzxdp2dpjthplkcrpnvob00dnf2e5c4pziiujs4lllpc+lpsbxt3iverkdpvxxef60vwdm7obwu2o26/unu5p7ofcn8w0nymewtnz0mpiq+br5de/c5+vmgvfrh5pq0+bz7xniy9jl5fxrdewt6v3qvdh7xc+9j5yn+m+4zw33jlewv/mn8c3ylflt8nvnl+f30n/i/9k/3r/0qcngcubzwojgugbwwl7+hp8ib+opzrbzfay2e1bjkc5qrvbj4ktguxbrsfoyoyqrsh355jokc5pdovqfujw0adh5mglw34mj4whhvegp45wifga0tgxnxfr3enz30t6rjze3ptnmu85ry1knso+qi5qpno3ujs6p8yuzlnm1vidwelssxw5liqunm5svt/87foh4p3ic+n7f5gvyf1weahowvsfpxaplhisopzatihoojtwqraqqbamjfitdywocnnchcjnii/rntgi2enckh5o8kgqtxqs7jg8nxkkxtollow5hcepklxmduzdmzqefpp2ig0yptq9myoskzbxqqohtzo2z+pn5mz2y6xlhbl+xw6lty8elqfja7oqravzlqq2qqbovfoo1yohsmdlv2a/zynkozarnivn7cyzytuqn5zvn//tesis4zk2pyzlvy0dwoa9rgo5sjxxedsk4xufk4zwbqw8uiq2km3vt6vtv5eufr0mek1rgv7byolbtqfr6wtvcuwffevc1+1dt1gvwd+1yfqgnrs+fymkrhtbf5cvf9go3hjlg4dvyr+z3js0qaveuwtpztjm6ebelz5bdpaql+axdm4n2dq0dd9wto319kxbl5fnknu7g7zduao/pli8zafjzs07p1skvpru+lq27tldtwhx+g7r7ht7vpy07nxbw7z3/t7jvttvavvn1wbvzftj+7p3p66jqun4lvttxa1obxhtxwpsa/0hiw6217nu1r3spvrsj9yr60coxx++/p3vdy0nng1vjzzg4inwrhnk6fcj3/cedtradox7roeh0x92hwcdl2pcmvkarpttmvtbylu6t8w+0dbq3nr8r9sfd5w0pfl5svnuywna6yltk2fyz4ydlz19fi753gdborz752po32opb++6ehth0kx/i+c7vdvoxpk4dpky2+utv7hxmq86x23qdoo8/pptt8e7nluarrlca7nuer21e2b36ruen87d9l158rb/1tweot3dvfn6b/ff9/xfft1+cif9zsu72xcn7q28t7xf9edtqdld3yfvp1v+3njv3h9qwheg89hcr/cghypp/ph1jw9dby+zj8ugdybrnjg+otnip3l96fynq89kzyaef/6i/suufxyvfvjv69fo0zjrozfyl5o/bxyl/era6xmv28bcxh6+yxgzmv70vvvtwxfcdx3vo98pt+r8ih8o/2j5sfvt0kf7kxmtk/8ea5jz/gmzldsaaaagy0hstqaaeiuaaicdaad5/waagokaahuwaadqyaaaopgaabdvkl/frgaaay1jrefuenrs1muivluububnvqzkoswudkerzfog0kwt6wpn0wwcdmosgx4umvs/kovkhikylhrbjvv1o/5vljcmyemufyijabyhsrqvbve0znrbj/vzfna4ndn+wth/pgwhc/baa6+z97v3et/d0ww24sq8ij5mnl7tn6zbvdjwizoxdpp8b3ja5qaxpq0mtanom9jzbvqbsqhbsgsmfrqlv+kpuc47cqonlfxzpsnfjd/bubrdffhdwiddcazmohspjwfad+eqnl8xcl/wqogc+/fjyxcxvuhjivjx8hx2cwgeweo4fixokl10wg9o1hssxucl30v5p1jxnfuxp+m53i67cq5mywzexj2ylnarjbdl3be4ffpxdfofsownhx+uwgxxf1uz/024dpnxfhrwrieips74xnyiq3a8xion6qxivj0tx1vyb8x7cj/jrelfjrx/zgms0p2bcwzhzejaqtgmo35j+opinicv8glkerouzci24lasrh/yzcgjffmfdib/b/iped8bnojx8w1hpr+gcxpwtzsadagrgtegrazljxd4zc59l1jr2dzc91s8g+psxhfwgggxo4s6bd9gaqrkahdhsqhso/fczrwes56ezlmb1bgcb+dbcg67rwalsud+udaavvlrfw1oqco18jekbusvgnmqa/f153scpgegt+o7iwt8nwrzwksh5irbuudmfoxmquhv2ekrskiog54oufxst3sefpvi4dz77ieaw/8uh+vdpf6dkxgf+f9gyntrkxe4or8tqwnowrigbdeftefdzhbkckuby9blu0xkc1pi++pk+objy5q80/nexsdl9wrgndkaailyzcj5zh1fcb00jl07jd2lkfgbx+lwxe6xjp6pcmiuimg8/fmrd3geyhniz+h6wgzp/i+t7mzpjo5wkjyu2t01cwfjp6hh2wzn0advbm7kalas3weyftwzivgtihtxs8ytd6koyx2uqi8iikcsd6cdhxnni+ii+vxhwd3g83ths9l8k5jzzbfh2ul7x0jyelfljvzuhtoc0dwowbncoga25s6wrhdhg8+2i1j0you/awbuu7abhvm/zwaaaabjru5erkjggg==" alt="froxlor"/&gt; &lt;small&gt;&amp;copy; 2009-&lt;span id="year"&gt;&lt;/span&gt; &lt;a href="https://froxlor.org" rel="external"&gt;the froxlor team&lt;/a&gt;&lt;/small&gt; &lt;/footer&gt; &lt;script&gt; document.getelementbyid("year").innerhtml = new date().getfullyear(); &lt;/script&gt; &lt;/body&gt; &lt;/html&gt;</file><file name="templates/misc/php/default.ini.php">&lt;?php $phpini = &lt;&lt;&lt;eoini allow_url_fopen = allow_url_include = auto_append_file = auto_globals_jit = auto_prepend_file = bcmath.scale = 0 cli_server.color = default_charset = "utf-8" default_mimetype = "text/html" default_socket_timeout = 60 asp_tags = disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,curl_exec,curl_multi_exec,exec,parse_ini_file,passthru,popen,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,shell_exec,show_source,system display_errors = display_startup_errors = doc_root = enable_dl = error_reporting = e_all &amp; ~e_deprecated &amp; ~e_strict &amp; ~e_notice expose_php = file_uploads = html_errors = ignore_repeated_errors = ignore_repeated_source = include_path = ".:{pear_dir}" implicit_flush = ldap.max_links = -1 log_errors = log_errors_max_len = 1024 mail.add_x_header = max_execution_time = 30 max_file_uploads = 20 max_input_time = 60 memory_limit = 128m {open_basedir_c}open_basedir = "{open_basedir}" output_buffering = 4096 post_max_size = 16m precision = 14 register_argc_argv = report_memleaks = request_order = "gp" sendmail_path = "/usr/sbin/sendmail -t -i -f {customer_email}" serialize_precision = -1 session.auto_start = 0 session.cache_expire = 180 session.cache_limiter = nocache session.cookie_domain = session.cookie_httponly = session.cookie_lifetime = 0 session.cookie_path = / session.cookie_samesite = session.gc_divisor = 1000 session.gc_maxlifetime = 1440 session.gc_probability = 0 session.name = phpsessid session.referer_check = session.save_handler = files session.save_path = "{tmp_dir}" session.serialize_handler = php session.sid_bits_per_character = 5 session.sid_length = 26 session.trans_sid_tags = "a=href,area=href,frame=src,form=" session.use_cookies = 1 session.use_only_cookies = 1 session.use_strict_mode = 0 session.use_trans_sid = 0 short_open_tag = upload_max_filesize = 32m upload_tmp_dir = "{tmp_dir}" variables_order = "gpcs" opcache.restrict_api = "{document_root}" eoini;</file><file name="templates/misc/php/index.html" /><file name="templates/misc/standardcustomer/index.html">&lt;!doctype html&gt; &lt;html lang="en"&gt; &lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;meta name="robots" content="noindex, nofollow"&gt; &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt; &lt;title&gt;froxlor - default page&lt;/title&gt; &lt;style&gt; :root{--primary:#1872a2;--fonts:ui-sans-serif,system-ui,-apple-system,blinkmacsystemfont,"segoe ui",roboto,"helvetica neue",arial,"noto sans",sans-serif,"apple color emoji","segoe ui emoji","segoe ui symbol","noto color emoji"} body{display:flex;flex-direction:column;background:#f8f9fa;color:#4b5563;align-items:center;justify-content:center;font-family:var(--fonts)} main{background:#fff;margin:10% auto 12px;max-width:540px;padding:2rem;box-shadow:4px 8px 16px 0 rgba(0,0,0,.07);border-radius:.375rem} main h2{margin:0} main p{margin-bottom:1.5rem} main p:last-child{margin-bottom:0} main ul{list-style:none;margin-left:-40px} main li{display:flex;align-items:center;margin-bottom:1rem} main .icon{min-width:24px;width:24px;stroke:var(--primary);margin-right:.75rem} code{background:#eee;padding:.1rem .25rem;border-radius:4px;color:rgba(0,0,0,.75)} hr{margin:2rem 0;border:none;border-bottom:solid 1px rgba(0,0,0,.1)} a,a:active,a:visited{color:var(--primary);text-decoration:none} a:hover{text-decoration:underline} footer{display:flex;align-items:center;margin-top:.5rem} footer .logo{margin-right:.35rem} @media (prefers-color-scheme: dark) { :root{--primary:#29a2d6} body{background:#212529;color:#f8f9fa} main{background:#343a40} hr{border-color:rgba(0,0,0,.2)} } &lt;/style&gt; &lt;/head&gt; &lt;body&gt; &lt;main&gt; &lt;h2&gt;domain default page&lt;/h2&gt; &lt;p&gt; domain managed using &lt;a href="https://froxlor.org" rel="external"&gt;froxlor server management panel&lt;/a&gt;. see page, content domain yet. &lt;/p&gt; &lt;ul&gt; &lt;li&gt; &lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="1.5" stroke="currentcolor" class="icon"&gt; &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021m21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008h12v8.25z" /&gt; &lt;/svg&gt; &lt;span&gt;please ask provider/hoster credentials froxlor panel&lt;/span&gt; &lt;/li&gt; &lt;li&gt; &lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="1.5" stroke="currentcolor" class="icon"&gt; &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021m21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008h12v8.25z" /&gt; &lt;/svg&gt; &lt;span&gt;log ftp server credentials&lt;/span&gt; &lt;/li&gt; &lt;li&gt; &lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="1.5" stroke="currentcolor" class="icon"&gt; &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021m21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008h12v8.25z" /&gt; &lt;/svg&gt; &lt;span&gt;customize remove &lt;code&gt;index.html&lt;/code&gt; file&lt;/span&gt; &lt;/li&gt; &lt;/ul&gt; &lt;hr/&gt; &lt;p&gt;&lt;b&gt;want dig deeper froxlor?&lt;/b&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="https://docs.froxlor.org" rel="external"&gt;read docs &amp;rarr;&lt;/a&gt;&lt;/p&gt; &lt;/main&gt; &lt;footer&gt; &lt;img class="logo" src="data:image/png;base64,ivborw0kggoaaaansuheugaaaegaaaaqcayaaac1mdndaaaacxbiwxmaaastaaaleweampwyaaakt2ldq1bqag90b3nob3agsundihbyb2zpbguaahjanvnnvfppfj333vrcs4ialetvuhuiifjci4auksyqiqkqsoghodkvucerruueg8igiaoojocmfvesdiok2afkiakog6oiisr74xuja9a89+bn/rxxpues852zzwfacaywsdnrnyamquieeecdx8tg4equqiekjhaaeaizzcfz/smbaph+pdwrisahvgabenmlcadatzvambyh/w/qqplcayceacb0kthlciauaeb6jkkmaebgaycdmcztakaeagdly2ljafataganf+btaicd+jl7aqbblcevaacracatzyheagg7akzpvopfafgwabrms8q5angtadbjv2zialc3amdoeauyaagmadbriiupaar7agdiiyn4aiszabrg8lc88suueocqaab4mbi8usq5ryfbcc1xb1dxlh4ozkkxkxq2yqjhmkauwnmzgtkbna/g88waakcrfrhgg/p9em4ors7ono62dl8t6r8g/yjiyup+5c+rceaaaof0fth+lc+zgoa7bobt/qil7groxgugdfelzripqluaoonav/nw+h48pewhklnz2exk5nhkxejbycpxff5nwl/av/1s+x48/pf14l7ijieyxyfhbpjgwsz0tkucz5ijhglc5o9h/lcl//wd0yleswk5wcou41escy5emozzmquiiukskcul0v9k4t8s+wm+3zuasgo+axurlahdywp2sycqwhta4vcaapk7b8hukagdggid4c93/+8//uegjqcazkmscqaaxkqklltksz/hcaaarkcbkrbbg/tbgczabhzbbdzbc/xgnorcjmtcqhbccmsahhjgkaycqiigzbadkmav1eadnmbraiatca4uwlw4dj1wd/phcj7bklybcqrbyagtyshaiafiilgjjggxmyx4icfibbkljcdjibrrikurnugxuopuifvihfi9cgi5h1xgupe7yaaygvygvecxligyut3udlvduag3gorgogvqzhqxmo8wojvqcrqapyw2oefqq2gp2o8+q8cwwogybzpebdauxsncstgscznjy7eirayrxhqwvqwdu4n1y8+xdwqsguxactyed0igyr5bsfhmwe7yskgghcq0edojnwkdhfhcjyktqeu0jror+cqyyjixh1hilcpweo8tlxb7iepenyqsiumyj7mqakmxpftsetjg0m5si+ksqzs0sbojk8nazguybzmulcaryixknetd5dpkg+qh8lsknwjacat4u+iouspqshnleou05qzlmdjbvaoaut2oovqrny9aqq2htlkvuyeoezr1mjnngxzjs6wtopxtgmgxapdpr+h0uhhdlr5ol9bx0svpr+ix6ap0dwwnhhwdx4hnkbmbgacyzxl3gk+ytkyz04szx1qwnzhrmoezd5lvvvgqtip8fzhkcpvklsavgyovvkmqpqreqgtv81xlvi+pxln9rkzvm1pjqqnulqtvqp1q61mbu2epo6ihqmeob1q/ph5z/ykgwcnmw09dpfggsv/jvmygc2mzs3gsiwsnq4z1gtxejrhn2xx2kruy/r27iz2qqae5qznkm1ezuvouzj8h45hx+jx0tgnnkkex836k3htvkeipg6y0tlkxzvxrqpaxllirsktrq0frvtau7aedpr1fu1n7gq5bx0onxcdhz4/obz3nu9lt3ackpxznptr1ri6qa6ubobted79up+6ynr5egj5mb6feeb3n+hx9l/1u/w36p/vhdfggswwkbtsmzhg8xtvxbzwdl8fb8vfdxcnaq6vhlwgx4ysrude8o9vgjuypjgngxomk423gbcajjgymiszltepn7ppstbmmkay7tdtmx83mzaln1pk1mz0x1zlnm+eb15vft2baefostqi2ugvjsuraplnutrxuhvo5wavyvvpds0atna0l1rutu6crp7lok06rntznw7dxtsm2qbczsoxybtuutm22fwfnyhdnt8wuw+6tvzn9un2n/t0hdyfzdqsdwh1+c7ryfdpwot6azpzup33f9jbpl2dyzxdp2dpjthplkcrpnvob00dnf2e5c4pziiujs4lllpc+lpsbxt3iverkdpvxxef60vwdm7obwu2o26/unu5p7ofcn8w0nymewtnz0mpiq+br5de/c5+vmgvfrh5pq0+bz7xniy9jl5fxrdewt6v3qvdh7xc+9j5yn+m+4zw33jlewv/mn8c3ylflt8nvnl+f30n/i/9k/3r/0qcngcubzwojgugbwwl7+hp8ib+opzrbzfay2e1bjkc5qrvbj4ktguxbrsfoyoyqrsh355jokc5pdovqfujw0adh5mglw34mj4whhvegp45wifga0tgxnxfr3enz30t6rjze3ptnmu85ry1knso+qi5qpno3ujs6p8yuzlnm1vidwelssxw5liqunm5svt/87foh4p3ic+n7f5gvyf1weahowvsfpxaplhisopzatihoojtwqraqqbamjfitdywocnnchcjnii/rntgi2enckh5o8kgqtxqs7jg8nxkkxtollow5hcepklxmduzdmzqefpp2ig0yptq9myoskzbxqqohtzo2z+pn5mz2y6xlhbl+xw6lty8elqfja7oqravzlqq2qqbovfoo1yohsmdlv2a/zynkozarnivn7cyzytuqn5zvn//tesis4zk2pyzlvy0dwoa9rgo5sjxxedsk4xufk4zwbqw8uiq2km3vt6vtv5eufr0mek1rgv7byolbtqfr6wtvcuwffevc1+1dt1gvwd+1yfqgnrs+fymkrhtbf5cvf9go3hjlg4dvyr+z3js0qaveuwtpztjm6ebelz5bdpaql+axdm4n2dq0dd9wto319kxbl5fnknu7g7zduao/pli8zafjzs07p1skvpru+lq27tldtwhx+g7r7ht7vpy07nxbw7z3/t7jvttvavvn1wbvzftj+7p3p66jqun4lvttxa1obxhtxwpsa/0hiw6217nu1r3spvrsj9yr60coxx++/p3vdy0nng1vjzzg4inwrhnk6fcj3/cedtradox7roeh0x92hwcdl2pcmvkarpttmvtbylu6t8w+0dbq3nr8r9sfd5w0pfl5svnuywna6yltk2fyz4ydlz19fi753gdborz752po32opb++6ehth0kx/i+c7vdvoxpk4dpky2+utv7hxmq86x23qdoo8/pptt8e7nluarrlca7nuer21e2b36ruen87d9l158rb/1tweot3dvfn6b/ff9/xfft1+cif9zsu72xcn7q28t7xf9edtqdld3yfvp1v+3njv3h9qwheg89hcr/cghypp/ph1jw9dby+zj8ugdybrnjg+otnip3l96fynq89kzyaef/6i/suufxyvfvjv69fo0zjrozfyl5o/bxyl/era6xmv28bcxh6+yxgzmv70vvvtwxfcdx3vo98pt+r8ih8o/2j5sfvt0kf7kxmtk/8ea5jz/gmzldsaaaagy0hstqaaeiuaaicdaad5/waagokaahuwaadqyaaaopgaabdvkl/frgaaay1jrefuenrs1muivluububnvqzkoswudkerzfog0kwt6wpn0wwcdmosgx4umvs/kovkhikylhrbjvv1o/5vljcmyemufyijabyhsrqvbve0znrbj/vzfna4ndn+wth/pgwhc/baa6+z97v3et/d0ww24sq8ij5mnl7tn6zbvdjwizoxdpp8b3ja5qaxpq0mtanom9jzbvqbsqhbsgsmfrqlv+kpuc47cqonlfxzpsnfjd/bubrdffhdwiddcazmohspjwfad+eqnl8xcl/wqogc+/fjyxcxvuhjivjx8hx2cwgeweo4fixokl10wg9o1hssxucl30v5p1jxnfuxp+m53i67cq5mywzexj2ylnarjbdl3be4ffpxdfofsownhx+uwgxxf1uz/024dpnxfhrwrieips74xnyiq3a8xion6qxivj0tx1vyb8x7cj/jrelfjrx/zgms0p2bcwzhzejaqtgmo35j+opinicv8glkerouzci24lasrh/yzcgjffmfdib/b/iped8bnojx8w1hpr+gcxpwtzsadagrgtegrazljxd4zc59l1jr2dzc91s8g+psxhfwgggxo4s6bd9gaqrkahdhsqhso/fczrwes56ezlmb1bgcb+dbcg67rwalsud+udaavvlrfw1oqco18jekbusvgnmqa/f153scpgegt+o7iwt8nwrzwksh5irbuudmfoxmquhv2ekrskiog54oufxst3sefpvi4dz77ieaw/8uh+vdpf6dkxgf+f9gyntrkxe4or8tqwnowrigbdeftefdzhbkckuby9blu0xkc1pi++pk+objy5q80/nexsdl9wrgndkaailyzcj5zh1fcb00jl07jd2lkfgbx+lwxe6xjp6pcmiuimg8/fmrd3geyhniz+h6wgzp/i+t7mzpjo5wkjyu2t01cwfjp6hh2wzn0advbm7kalas3weyftwzivgtihtxs8ytd6koyx2uqi8iikcsd6cdhxnni+ii+vxhwd3g83ths9l8k5jzzbfh2ul7x0jyelfljvzuhtoc0dwowbncoga25s6wrhdhg8+2i1j0you/awbuu7abhvm/zwaaaabjru5erkjggg==" alt="froxlor"/&gt; &lt;small&gt;&amp;copy; 2009-&lt;span id="year"&gt;&lt;/span&gt; &lt;a href="https://froxlor.org" rel="external"&gt;the froxlor team&lt;/a&gt;&lt;/small&gt; &lt;/footer&gt; &lt;script&gt; document.getelementbyid("year").innerhtml = new date().getfullyear(); &lt;/script&gt; &lt;/body&gt; &lt;/html&gt;</file><file name="templates/misc/unconfigured/index.html">&lt;!doctype html&gt; &lt;html lang="en"&gt; &lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;meta name="robots" content="noindex, nofollow"&gt; &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt; &lt;title&gt;froxlor - domain configured&lt;/title&gt; &lt;style&gt; :root{--primary:#1872a2;--fonts:ui-sans-serif,system-ui,-apple-system,blinkmacsystemfont,"segoe ui",roboto,"helvetica neue",arial,"noto sans",sans-serif,"apple color emoji","segoe ui emoji","segoe ui symbol","noto color emoji"} body{display:flex;flex-direction:column;background:#f8f9fa;color:#4b5563;align-items:center;justify-content:center;font-family:var(--fonts)} main{background:#fff;margin:10% auto 12px;max-width:540px;padding:2rem;box-shadow:4px 8px 16px 0 rgba(0,0,0,.07);border-radius:.375rem} main h2{margin:0} main p{margin-bottom:1.5rem} main p:last-child{margin-bottom:0} main ul{list-style:none;margin-left:-40px} main li{display:flex;align-items:center;margin-bottom:1rem} main .icon{min-width:24px;width:24px;stroke:var(--primary);margin-right:.75rem} code{background:#eee;padding:.1rem .25rem;border-radius:4px;color:rgba(0,0,0,.75)} hr{margin:2rem 0;border:none;border-bottom:solid 1px rgba(0,0,0,.1)} a,a:active,a:visited{color:var(--primary);text-decoration:none} a:hover{text-decoration:underline} footer{display:flex;align-items:center;margin-top:.5rem} footer .logo{margin-right:.35rem} @media (prefers-color-scheme: dark) { :root{--primary:#29a2d6} body{background:#212529;color:#f8f9fa} main{background:#343a40} hr{border-color:rgba(0,0,0,.2)} } &lt;/style&gt; &lt;/head&gt; &lt;body&gt; &lt;main&gt; &lt;h2&gt;domain configured&lt;/h2&gt; &lt;p&gt; domain requires configuration via froxlor server management panel, currently assigned customer. &lt;/p&gt; &lt;ul&gt; &lt;li&gt; &lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="1.5" stroke="currentcolor" class="icon"&gt; &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021m21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008h12v8.25z" /&gt; &lt;/svg&gt; &lt;span&gt;please ask provider/hoster questions.&lt;/span&gt; &lt;/li&gt; &lt;/ul&gt; &lt;/main&gt; &lt;footer&gt; &lt;img class="logo" src="data:image/png;base64,ivborw0kggoaaaansuheugaaaegaaaaqcayaaac1mdndaaaacxbiwxmaaastaaaleweampwyaaakt2ldq1bqag90b3nob3agsundihbyb2zpbguaahjanvnnvfppfj333vrcs4ialetvuhuiifjci4auksyqiqkqsoghodkvucerruueg8igiaoojocmfvesdiok2afkiakog6oiisr74xuja9a89+bn/rxxpues852zzwfacaywsdnrnyamquieeecdx8tg4equqiekjhaaeaizzcfz/smbaph+pdwrisahvgabenmlcadatzvambyh/w/qqplcayceacb0kthlciauaeb6jkkmaebgaycdmcztakaeagdly2ljafataganf+btaicd+jl7aqbblcevaacracatzyheagg7akzpvopfafgwabrms8q5angtadbjv2zialc3amdoeauyaagmadbriiupaar7agdiiyn4aiszabrg8lc88suueocqaab4mbi8usq5ryfbcc1xb1dxlh4ozkkxkxq2yqjhmkauwnmzgtkbna/g88waakcrfrhgg/p9em4ors7ono62dl8t6r8g/yjiyup+5c+rceaaaof0fth+lc+zgoa7bobt/qil7groxgugdfelzripqluaoonav/nw+h48pewhklnz2exk5nhkxejbycpxff5nwl/av/1s+x48/pf14l7ijieyxyfhbpjgwsz0tkucz5ijhglc5o9h/lcl//wd0yleswk5wcou41escy5emozzmquiiukskcul0v9k4t8s+wm+3zuasgo+axurlahdywp2sycqwhta4vcaapk7b8hukagdggid4c93/+8//uegjqcazkmscqaaxkqklltksz/hcaaarkcbkrbbg/tbgczabhzbbdzbc/xgnorcjmtcqhbccmsahhjgkaycqiigzbadkmav1eadnmbraiatca4uwlw4dj1wd/phcj7bklybcqrbyagtyshaiafiilgjjggxmyx4icfibbkljcdjibrrikurnugxuopuifvihfi9cgi5h1xgupe7yaaygvygvecxligyut3udlvduag3gorgogvqzhqxmo8wojvqcrqapyw2oefqq2gp2o8+q8cwwogybzpebdauxsncstgscznjy7eirayrxhqwvqwdu4n1y8+xdwqsguxactyed0igyr5bsfhmwe7yskgghcq0edojnwkdhfhcjyktqeu0jror+cqyyjixh1hilcpweo8tlxb7iepenyqsiumyj7mqakmxpftsetjg0m5si+ksqzs0sbojk8nazguybzmulcaryixknetd5dpkg+qh8lsknwjacat4u+iouspqshnleou05qzlmdjbvaoaut2oovqrny9aqq2htlkvuyeoezr1mjnngxzjs6wtopxtgmgxapdpr+h0uhhdlr5ol9bx0svpr+ix6ap0dwwnhhwdx4hnkbmbgacyzxl3gk+ytkyz04szx1qwnzhrmoezd5lvvvgqtip8fzhkcpvklsavgyovvkmqpqreqgtv81xlvi+pxln9rkzvm1pjqqnulqtvqp1q61mbu2epo6ihqmeob1q/ph5z/ykgwcnmw09dpfggsv/jvmygc2mzs3gsiwsnq4z1gtxejrhn2xx2kruy/r27iz2qqae5qznkm1ezuvouzj8h45hx+jx0tgnnkkex836k3htvkeipg6y0tlkxzvxrqpaxllirsktrq0frvtau7aedpr1fu1n7gq5bx0onxcdhz4/obz3nu9lt3ackpxznptr1ri6qa6ubobted79up+6ynr5egj5mb6feeb3n+hx9l/1u/w36p/vhdfggswwkbtsmzhg8xtvxbzwdl8fb8vfdxcnaq6vhlwgx4ysrude8o9vgjuypjgngxomk423gbcajjgymiszltepn7ppstbmmkay7tdtmx83mzaln1pk1mz0x1zlnm+eb15vft2baefostqi2ugvjsuraplnutrxuhvo5wavyvvpds0atna0l1rutu6crp7lok06rntznw7dxtsm2qbczsoxybtuutm22fwfnyhdnt8wuw+6tvzn9un2n/t0hdyfzdqsdwh1+c7ryfdpwot6azpzup33f9jbpl2dyzxdp2dpjthplkcrpnvob00dnf2e5c4pziiujs4lllpc+lpsbxt3iverkdpvxxef60vwdm7obwu2o26/unu5p7ofcn8w0nymewtnz0mpiq+br5de/c5+vmgvfrh5pq0+bz7xniy9jl5fxrdewt6v3qvdh7xc+9j5yn+m+4zw33jlewv/mn8c3ylflt8nvnl+f30n/i/9k/3r/0qcngcubzwojgugbwwl7+hp8ib+opzrbzfay2e1bjkc5qrvbj4ktguxbrsfoyoyqrsh355jokc5pdovqfujw0adh5mglw34mj4whhvegp45wifga0tgxnxfr3enz30t6rjze3ptnmu85ry1knso+qi5qpno3ujs6p8yuzlnm1vidwelssxw5liqunm5svt/87foh4p3ic+n7f5gvyf1weahowvsfpxaplhisopzatihoojtwqraqqbamjfitdywocnnchcjnii/rntgi2enckh5o8kgqtxqs7jg8nxkkxtollow5hcepklxmduzdmzqefpp2ig0yptq9myoskzbxqqohtzo2z+pn5mz2y6xlhbl+xw6lty8elqfja7oqravzlqq2qqbovfoo1yohsmdlv2a/zynkozarnivn7cyzytuqn5zvn//tesis4zk2pyzlvy0dwoa9rgo5sjxxedsk4xufk4zwbqw8uiq2km3vt6vtv5eufr0mek1rgv7byolbtqfr6wtvcuwffevc1+1dt1gvwd+1yfqgnrs+fymkrhtbf5cvf9go3hjlg4dvyr+z3js0qaveuwtpztjm6ebelz5bdpaql+axdm4n2dq0dd9wto319kxbl5fnknu7g7zduao/pli8zafjzs07p1skvpru+lq27tldtwhx+g7r7ht7vpy07nxbw7z3/t7jvttvavvn1wbvzftj+7p3p66jqun4lvttxa1obxhtxwpsa/0hiw6217nu1r3spvrsj9yr60coxx++/p3vdy0nng1vjzzg4inwrhnk6fcj3/cedtradox7roeh0x92hwcdl2pcmvkarpttmvtbylu6t8w+0dbq3nr8r9sfd5w0pfl5svnuywna6yltk2fyz4ydlz19fi753gdborz752po32opb++6ehth0kx/i+c7vdvoxpk4dpky2+utv7hxmq86x23qdoo8/pptt8e7nluarrlca7nuer21e2b36ruen87d9l158rb/1tweot3dvfn6b/ff9/xfft1+cif9zsu72xcn7q28t7xf9edtqdld3yfvp1v+3njv3h9qwheg89hcr/cghypp/ph1jw9dby+zj8ugdybrnjg+otnip3l96fynq89kzyaef/6i/suufxyvfvjv69fo0zjrozfyl5o/bxyl/era6xmv28bcxh6+yxgzmv70vvvtwxfcdx3vo98pt+r8ih8o/2j5sfvt0kf7kxmtk/8ea5jz/gmzldsaaaagy0hstqaaeiuaaicdaad5/waagokaahuwaadqyaaaopgaabdvkl/frgaaay1jrefuenrs1muivluububnvqzkoswudkerzfog0kwt6wpn0wwcdmosgx4umvs/kovkhikylhrbjvv1o/5vljcmyemufyijabyhsrqvbve0znrbj/vzfna4ndn+wth/pgwhc/baa6+z97v3et/d0ww24sq8ij5mnl7tn6zbvdjwizoxdpp8b3ja5qaxpq0mtanom9jzbvqbsqhbsgsmfrqlv+kpuc47cqonlfxzpsnfjd/bubrdffhdwiddcazmohspjwfad+eqnl8xcl/wqogc+/fjyxcxvuhjivjx8hx2cwgeweo4fixokl10wg9o1hssxucl30v5p1jxnfuxp+m53i67cq5mywzexj2ylnarjbdl3be4ffpxdfofsownhx+uwgxxf1uz/024dpnxfhrwrieips74xnyiq3a8xion6qxivj0tx1vyb8x7cj/jrelfjrx/zgms0p2bcwzhzejaqtgmo35j+opinicv8glkerouzci24lasrh/yzcgjffmfdib/b/iped8bnojx8w1hpr+gcxpwtzsadagrgtegrazljxd4zc59l1jr2dzc91s8g+psxhfwgggxo4s6bd9gaqrkahdhsqhso/fczrwes56ezlmb1bgcb+dbcg67rwalsud+udaavvlrfw1oqco18jekbusvgnmqa/f153scpgegt+o7iwt8nwrzwksh5irbuudmfoxmquhv2ekrskiog54oufxst3sefpvi4dz77ieaw/8uh+vdpf6dkxgf+f9gyntrkxe4or8tqwnowrigbdeftefdzhbkckuby9blu0xkc1pi++pk+objy5q80/nexsdl9wrgndkaailyzcj5zh1fcb00jl07jd2lkfgbx+lwxe6xjp6pcmiuimg8/fmrd3geyhniz+h6wgzp/i+t7mzpjo5wkjyu2t01cwfjp6hh2wzn0advbm7kalas3weyftwzivgtihtxs8ytd6koyx2uqi8iikcsd6cdhxnni+ii+vxhwd3g83ths9l8k5jzzbfh2ul7x0jyelfljvzuhtoc0dwowbncoga25s6wrhdhg8+2i1j0you/awbuu7abhvm/zwaaaabjru5erkjggg==" alt="froxlor"/&gt; &lt;small&gt;&amp;copy; 2009-&lt;span id="year"&gt;&lt;/span&gt; &lt;a href="https://froxlor.org" rel="external"&gt;the froxlor team&lt;/a&gt;&lt;/small&gt; &lt;/footer&gt; &lt;script&gt; document.getelementbyid("year").innerhtml = new date().getfullyear(); &lt;/script&gt; &lt;/body&gt; &lt;/html&gt;</file><file name="logs/index.html" /><file name="lng/it.lng.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @author luca piona &lt;info@havanastudio.ch&gt; * @author luca longinotti &lt;chtekk@gentoo.org&gt; * @author emilien * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'admin' =&gt; [ 'overview' =&gt; 'generale', 'ressourcedetails' =&gt; 'risorse utilizzate', 'systemdetails' =&gt; 'dettagli sistema', 'froxlordetails' =&gt; 'dettagli froxlor', 'installedversion' =&gt; 'versione installata', 'latestversion' =&gt; 'ultima versione disponibile', 'lookfornewversion' =&gt; [ 'clickhere' =&gt; 'cerca sul web', 'error' =&gt; 'errore durante la lettura', ], 'resources' =&gt; 'risorse', 'customer' =&gt; 'cliente', 'customers' =&gt; 'clienti', 'customer_add' =&gt; 'crea cliente', 'customer_edit' =&gt; 'modifica cliente', 'domains' =&gt; 'domini', 'domain_add' =&gt; 'crea dominio', 'domain_edit' =&gt; 'modifica dominio', 'subdomainforemail' =&gt; 'sottodominio utilizzabile come dominio email', 'admin' =&gt; 'admin', 'admins' =&gt; 'admin', 'admin_add' =&gt; 'crea admin', 'admin_edit' =&gt; 'modifica admin', 'customers_see_all' =&gt; 'pu vedere tutti clienti?', 'change_serversettings' =&gt; 'pu cambiare le impostazioni del server?', 'server' =&gt; 'sistema', 'serversettings' =&gt; 'opzioni', 'rebuildconf' =&gt; 'rigenera configurazione', 'stdsubdomain' =&gt; 'sottodominio standard', 'stdsubdomain_add' =&gt; 'crea sottodominio standard', 'phpenabled' =&gt; 'php abilitato', 'deactivated' =&gt; 'disattiva', 'deactivated_user' =&gt; 'disattiva utente', 'sendpassword' =&gt; 'invia password', 'ownvhostsettings' =&gt; 'impostazioni vhost speciali', 'configfiles' =&gt; [ 'serverconfiguration' =&gt; 'configurazione servizi', 'overview' =&gt; 'panoramica', 'distribution' =&gt; 'distribuzione', 'service' =&gt; 'servizio', 'daemon' =&gt; 'demone', 'etc' =&gt; 'altro (sistema)', 'choosedistribution' =&gt; '-- scegli una distribuzione --', 'chooseservice' =&gt; '-- scegli un servizio --', 'choosedaemon' =&gt; '-- scegli un demone --', 'statistics' =&gt; 'statistiche', 'compactoverview' =&gt; 'visualizzazione-compatta', 'wizard' =&gt; 'wizard (assistente)', 'http' =&gt; 'server web (http)', 'dns' =&gt; 'nameserver (dns)', 'mail' =&gt; 'server di posta elettronica (imap/pop3)', 'smtp' =&gt; 'server di posta elettronica (smtp)', 'ftp' =&gt; 'server ftp', ], 'templates' =&gt; [ 'templates' =&gt; 'template', 'template_add' =&gt; 'aggiungi template', 'template_edit' =&gt; 'modifica template', 'action' =&gt; 'azione', 'email' =&gt; 'email', 'subject' =&gt; 'soggetto:', 'mailbody' =&gt; 'testo dell\'email', 'createcustomer' =&gt; 'email di benvenuto per nuovi clienti', 'pop_success' =&gt; 'benvenuto per ogni nuovo account email', 'template_replace_vars' =&gt; 'variabili da cambiare nel template:', 'firstname' =&gt; 'rimpiazzato con il nome del cliente.', 'name' =&gt; 'rimpiazzato con il cognome del cliente.', 'username' =&gt; 'rimpiazzato con il nome utente dell\'account.', 'password' =&gt; 'rimpiazzato con la password dell\'account.', 'email' =&gt; 'rimapiazzato con l\'indirizzo dell\'account.', 'traffic' =&gt; 'sostituito con il traffico che stato assegnato al cliente.', 'trafficused' =&gt; 'sostituito con il traffico che stato usato dal cliente.', 'pop_success_alternative' =&gt; 'email di benvenuto spedita all\'indirizzo alternativo per nuovi account email', 'email_password' =&gt; 'sostituito con la password dell\'account pop3/imap.', 'index_html' =&gt; 'file index per le nuove cartelle create dai clienti', 'servername' =&gt; 'sostituito con il nomeserver.', 'customer' =&gt; 'sostituito con il nome utente del cliente.', 'admin' =&gt; 'sostituito con il nome utente dell\'amministratore.', 'customer_email' =&gt; 'sostituito con l\'indirizzo e-mail del cliente.', 'admin_email' =&gt; 'sostituito con l\'indirizzo e-mail dell\'amministratore.', 'filetemplates' =&gt; 'file modelli', 'filecontent' =&gt; 'contenuto file', 'new_database_by_customer' =&gt; 'notifica al cliente quando un database stato creato', 'new_ftpaccount_by_customer' =&gt; 'notifica al cliente quando un utente ftp stato creato', 'newdatabase' =&gt; 'mail di notifica per nuovi database', 'newftpuser' =&gt; 'mail di notifica per nuovi utenti ftp', 'cust_name' =&gt; 'nome del cliente', 'db_name' =&gt; 'nome del database', 'db_pass' =&gt; 'password del database', 'db_desc' =&gt; 'descrizione del database', 'db_srv' =&gt; 'server del database', 'pma_uri' =&gt; 'url phpmyadmin (se presente)', 'usr_name' =&gt; 'nome utente ftp', 'usr_pass' =&gt; 'password ftp', 'usr_path' =&gt; 'cartella utente ftp (rispetto alla cartella docroot del cliente)', 'forgotpwd' =&gt; 'mail di notifica per il reset della password', 'password_reset' =&gt; 'notifica al cliente per il reset della password', 'trafficmaxpercent' =&gt; 'mail di notifica per clienti che hanno raggiunto il limite di traffico', 'max_percent' =&gt; 'sostituito con spazio/limite di traffico per l\'invio dei report precentuale.', 'usage_percent' =&gt; 'sostituito con l\'utilizzo del disco/limite di traffico, che stato esaurito da parte del cliente percentuale.', 'diskmaxpercent' =&gt; 'mail di notifica per clienti che hanno raggiunto il limite di spazio su disco', 'diskavailable' =&gt; 'sostituito con il spazio utilizzato mb, che stato assegnato al cliente.', 'diskused' =&gt; 'sostituito con il spazio utilizzato mb, che stato esaurito da parte del cliente.', 'salutation' =&gt; 'sostituito con un saluto corretto (nome azienda)', 'company' =&gt; 'sostituisce con il nome dell \'azienda del cliente', 'link' =&gt; 'sostituito con il link di azzeramento password cliente.', 'server_hostname' =&gt; 'sostituisce il nome host del sistema (url froxlor)', 'server_ip' =&gt; 'sostituisce l\'indrizzo ip predefinito del server', 'server_port' =&gt; 'sostituisce la porta predefinita del server', 'domainname' =&gt; 'sostituisce il sottodominio predefinito dei clienti (pu essere vuoto se non viene generato)', ], 'webserver' =&gt; 'webserver', 'ipsandports' =&gt; [ 'ipsandports' =&gt; 'ip e porte', 'add' =&gt; 'aggiungi ip/porta', 'edit' =&gt; 'modifica ip/porta', 'ipandport' =&gt; 'ip/porta', 'ip' =&gt; 'ip', 'port' =&gt; 'porta', 'create_listen_statement' =&gt; 'crea la direttiva listen', 'create_namevirtualhost_statement' =&gt; 'crea la direttiva namevirtualhost', 'create_vhostcontainer' =&gt; 'crea vhost-container', 'create_vhostcontainer_servername_statement' =&gt; 'crea la direttiva servername vhost-container', 'enable_ssl' =&gt; 'questa una porta ssl?', 'ssl_cert_file' =&gt; 'percorso del certificato ssl (ssl certificate)', 'webserverdefaultconfig' =&gt; 'configurazione predefinita webserver', 'webserverdomainconfig' =&gt; 'configurazione dominio webserver', 'webserverssldomainconfig' =&gt; 'configura ssl webserver', 'ssl_key_file' =&gt; 'percorso al keyfile ssl', 'ssl_ca_file' =&gt; 'percorso al ca certificate ssl', 'default_vhostconf_domain' =&gt; 'impostazioni predefinite vhost per ogni contenitore di dominio', 'docroot' =&gt; [ 'title' =&gt; 'imposta cartella principale (vuoto = va froxlor)', 'description' =&gt; 'qui puoi definire una tua cartella principale (la destinazione di una richiesta) per questa combinazione ip/porta.&lt;br /&gt;&lt;strong&gt;attenzione:&lt;/strong&gt; fai molta attenzione quello che scrivi qui!', ], 'ssl_cert_chainfile' =&gt; [ 'title' =&gt; 'percorso al file catena dei certificati ssl', 'description' =&gt; 'principalmente bundle ca, similare, presubilmente vuoi impostare questo se hai acquistato un certificato ssl.', ], 'ssl_paste_description' =&gt; 'incolla il contenuto completo del tuo certificato nella casella di testo', 'ssl_cert_file_content' =&gt; 'contenuto del certificato ssl', 'ssl_key_file_content' =&gt; 'contenuto del file di chiave (privata) ssl', 'ssl_ca_file_content' =&gt; 'contenuto del file ssl ca di autorit di certificazione (opzionale)', 'ssl_ca_file_content_desc' =&gt; '&lt;br /&gt;&lt;br /&gt;autenticazione client, imposta questo settaggio soltanto se sai di cosa si tratta.', 'ssl_cert_chainfile_content' =&gt; 'contenuto del file di catena di certificato (opzionale)', 'ssl_cert_chainfile_content_desc' =&gt; '&lt;br /&gt;&lt;br /&gt;abitualmente bundle ca similare, probabilmente vuoi impostare questo settaggio se hai acquistato un certificato ssl.', ], 'memorylimitdisabled' =&gt; 'disabilitato', 'valuemandatory' =&gt; 'questo valore obbligatorio', 'valuemandatorycompany' =&gt; 'o campi "nome" e "cognome" il capo "compagnia" devono essere riempiti', 'phpversion' =&gt; 'versione php', 'mysqlserverversion' =&gt; 'versione mysql server', 'webserverinterface' =&gt; 'interfaccia webserver', 'accountsettings' =&gt; 'impostazioni account', 'panelsettings' =&gt; 'impostazioni pannello', 'systemsettings' =&gt; 'impostazioni di sistema', 'webserversettings' =&gt; 'impostazioni server web', 'mailserversettings' =&gt; 'impostazioni server di posta', 'nameserversettings' =&gt; 'impostazioni nameserver', 'updatecounters' =&gt; 'ricalcolo risorse', 'subcanemaildomain' =&gt; [ 'never' =&gt; 'mai', 'choosableno' =&gt; 'selezionabile, predefinito no', 'choosableyes' =&gt; 'selezionabile, predefinito si', 'always' =&gt; 'sempre', ], 'webalizersettings' =&gt; 'impostazioni webalizer', 'webalizer' =&gt; [ 'normal' =&gt; 'normale', 'quiet' =&gt; 'modesto', 'veryquiet' =&gt; 'niente', ], 'domain_nocustomeraddingavailable' =&gt; 'adesso non possibile aggiungere un dominio. prima necessario aggiungere almeno un cliente.', 'loggersettings' =&gt; 'impostazioni log', 'logger' =&gt; [ 'normal' =&gt; 'normale', 'paranoid' =&gt; 'paranoico', ], 'emaildomain' =&gt; 'email dominio', 'email_only' =&gt; 'solo email?', 'wwwserveralias' =&gt; 'aggiungi "www." serveralias', 'subject' =&gt; 'oggetto', 'recipient' =&gt; 'destinatario', 'message' =&gt; 'scrivi un messaggio', 'text' =&gt; 'messaggio', 'sslsettings' =&gt; 'impostazioni ssl', 'dkimsettings' =&gt; 'impostazioni domainkey', 'caneditphpsettings' =&gt; ' possibile modificare le impostazioni di dominio relative php?', 'allips' =&gt; 'tutti gli ip', 'awstatssettings' =&gt; 'impostazioni awstats', 'domain_dns_settings' =&gt; 'impostazioni dominio dns', 'activated' =&gt; 'attivato', 'statisticsettings' =&gt; 'impostazioni statistiche', 'or' =&gt; 'o', 'sysload' =&gt; 'carico del sistema', 'noloadavailable' =&gt; 'non disponibile', 'nouptimeavailable' =&gt; 'non disponibile', 'nosubject' =&gt; '(nessun oggetto)', 'security_settings' =&gt; 'opzioni di sicurezza', 'know_what_youre_doing' =&gt; 'modifica solo, se sai quello che stai facendo!', 'show_version_login' =&gt; [ 'title' =&gt; 'mostra la versione di froxlor quando si effettua l\'accesso', 'description' =&gt; 'mostra la versione di froxlor fondo-pagina di accesso', ], 'show_version_footer' =&gt; [ 'title' =&gt; 'mostra la versione di froxlor fondo-pagina', 'description' =&gt; 'mostra la versione di froxlor fondo ad ogni pagina', ], 'froxlor_graphic' =&gt; [ 'title' =&gt; 'intestazione grafica per froxlor', 'description' =&gt; 'quale grafica vuoi mostrare nell\'intestazione?', ], 'phpsettings' =&gt; [ 'title' =&gt; 'configurazione php', 'description' =&gt; 'descrizione breve', 'actions' =&gt; 'azioni', 'activedomains' =&gt; 'in uso per dominio/i', 'notused' =&gt; 'configurazione non utilizzata', 'editsettings' =&gt; 'modific impostazioni php', 'addsettings' =&gt; 'crea una nuova impostazione php', 'viewsettings' =&gt; 'mostra impostazioni php', 'phpinisettings' =&gt; 'impostazioni php.ini', 'addnew' =&gt; 'crea nuove impostazioni', 'binary' =&gt; 'php binary', 'file_extensions' =&gt; 'estensioni file', 'file_extensions_note' =&gt; '(senza punto, separate da spazi)', 'enable_slowlog' =&gt; 'abilita slowlog (per dominio)', 'request_terminate_timeout' =&gt; 'richiedi terminate-timeout', 'request_slowlog_timeout' =&gt; 'richiedi slowlog-timeout', ], 'misc' =&gt; 'varie', 'phpconfig' =&gt; [ 'template_replace_vars' =&gt; 'variabili che saranno sostituite nei file di configurazione', 'pear_dir' =&gt; 'verr sostituito con le impostazioni globali per la cartella pear.', 'open_basedir_c' =&gt; 'inserir un ; (punto e virgola) per commentare/disabilitare open_basedir se impostato', 'open_basedir' =&gt; 'verr sostituito con l\'impostazione open_basedir del dominio.', 'tmp_dir' =&gt; 'verr sostituito con la cartella temporanea del dominio.', 'open_basedir_global' =&gt; 'verr sostituito con il valore globale del percorso che sar allegato al open_basedir', 'customer_email' =&gt; 'verr sostituito con l\'indirizzo email del cliente che possiede questo dominio.', 'admin_email' =&gt; 'verr sostituito con l\'indirizzo email dell\'amministratore di questo dominio.', 'domain' =&gt; 'verr sostituito con il dominio.', 'customer' =&gt; 'verr sostituito con il nome utente del cliente che possiede questo dominio.', 'admin' =&gt; 'verr sostituito con il nome utente dell\'amministratore che possiede questo dominio.', ], 'expert_settings' =&gt; 'impostazioni avanzate!', 'mod_fcgid_starter' =&gt; [ 'title' =&gt; 'processi php per questo dominio (vuoto per lasciare il valore predefinito)', ], 'phpserversettings' =&gt; 'impostazioni php', 'mod_fcgid_maxrequests' =&gt; [ 'title' =&gt; 'richieste php massime per questo dominio (vuoto per lasciare il valore predefinito)', ], 'spfsettings' =&gt; 'impostazioni dominio spf', 'specialsettingsforsubdomains' =&gt; 'applica le impostazioni speciali tutti sottodomini (*.esempio.com)', 'accountdata' =&gt; 'dati conto', 'contactdata' =&gt; 'dati contatto', 'servicedata' =&gt; 'dati di servizio', 'newerversionavailable' =&gt; ' disponibile una nuova versione di floxlor', 'cron' =&gt; [ 'cronsettings' =&gt; 'impostazioni cronjob', 'add' =&gt; 'aggiungi cronjob', ], 'cronjob_edit' =&gt; 'modifica cronjob', 'warning' =&gt; 'attenzione - leggi attentamente!', 'lastlogin_succ' =&gt; 'ultimo accesso', 'ftpserver' =&gt; 'server ftp', 'ftpserversettings' =&gt; 'impostazioni del server ftp', 'webserver_user' =&gt; 'utente webserver', 'webserver_group' =&gt; 'gruppo webserver', 'perlenabled' =&gt; 'perl abilitato', 'fcgid_settings' =&gt; 'fcgid', 'mod_fcgid_user' =&gt; 'utente locale per fcgid (froxlor vhost)', 'mod_fcgid_group' =&gt; 'gruppo locale per fcgid (froxlor vhost)', 'perl_settings' =&gt; 'perl/cgi', 'notgiven' =&gt; '[se presente]', 'phpfpm_settings' =&gt; 'php-fpm', 'traffic' =&gt; 'traffico', 'domaintraffic' =&gt; 'domimi', 'customertraffic' =&gt; 'clienti', 'serversoftware' =&gt; 'software per server', 'store_defaultindex' =&gt; 'archivio del file indice predefinito al percorso radice clienti', 'assignedmax' =&gt; 'assegnato / max', 'usedmax' =&gt; 'usato / max', 'used' =&gt; 'usato', 'speciallogwarning' =&gt; '&lt;div id="speciallogfilenote" class="invalid-feedback"&gt;avviso: cambiando questa impostazione perderai tutte le vecchie statistiche per questo dominio.&lt;/div&gt;', 'speciallogfile' =&gt; [ 'title' =&gt; 'file file log seperato', 'description' =&gt; 'spunta qui per un log di accesso separato per questo dominio', ], 'domain_editable' =&gt; [ 'title' =&gt; 'permetti la modifica del dominio', 'desc' =&gt; 'se settato si, il cliente abilitato modificare varie impostazioni del dominio.&lt;br /&gt;se settato su no, il cliente non pu modificare nulla.', ], 'phpfpm.ininote' =&gt; 'non tutti valori che potresti volere settare possono essere usati nella configurazione del pool php-fpm.', 'phpinfo' =&gt; 'phpinfo()', 'selectserveralias' =&gt; 'valore serveralias per il dominio', 'selectserveralias_desc' =&gt; 'scegli se froxlor deve creare un settaggio wildcard (*.dominio.tld), un alias www (www.dominio.tld) nessun alias', 'show_news_feed' =&gt; 'mostra il feed notizie sul cruscotto dell \'amministratore', 'cronsettings' =&gt; 'impostazioni cronjob', 'integritycheck' =&gt; 'validazione database', 'integrityid' =&gt; '#', 'integrityname' =&gt; 'nome', 'integrityresult' =&gt; 'risultato', 'integrityfix' =&gt; 'risolvi problemi automaticamente', 'customer_show_news_feed' =&gt; 'mostra feed di notizie personalizzati sul cruscotto dei clienti', 'customer_news_feed_url' =&gt; 'feed rss- per il feed di notizie personalizzato', 'movetoadmin' =&gt; 'trasferisci cliente', 'movecustomertoadmin' =&gt; 'trasferisci cliente all\'amministratore/rivenditore selezionato&lt;br /&gt;&lt;small&gt;lascia questo vuoto per nessuna modifica.&lt;br /&gt;se l\'amministratore desiderato non appare nella lista, il suo massimale di clienti e stato ragggiunto.&lt;/small&gt;', 'note' =&gt; 'nota', ], 'changepassword' =&gt; [ 'old_password' =&gt; 'vecchia password', 'new_password' =&gt; 'nuova password', 'new_password_confirm' =&gt; 'nuova password (verifica)', 'new_password_ifnotempty' =&gt; 'nuova password (vuota = non cambia)', 'also_change_ftp' =&gt; ' cambia la password dell\'account ftp principale?', 'also_change_stats' =&gt; ' modificare anche la password di statistic', ], 'country' =&gt; [ 'af' =&gt; 'afganistan', 'ax' =&gt; 'isole aland', 'al' =&gt; 'albania', 'dz' =&gt; 'algeria', 'as' =&gt; 'american samoa', 'ad' =&gt; 'andorra', 'ao' =&gt; 'angola', 'ai' =&gt; 'anguilla', 'aq' =&gt; 'antarctica', 'ag' =&gt; 'antigua barbuda', 'ar' =&gt; 'argentina', 'am' =&gt; 'armenia', 'aw' =&gt; 'aruba', 'au' =&gt; 'australia', 'at' =&gt; 'austria', 'az' =&gt; 'azerbaijan', 'bs' =&gt; 'bahamas', 'bh' =&gt; 'bahrain', 'bd' =&gt; 'bangladesh', 'bb' =&gt; 'barbados', 'by' =&gt; 'belarus', 'be' =&gt; 'belgium', 'bz' =&gt; 'belize', 'bj' =&gt; 'benin', 'bm' =&gt; 'bermuda', 'bt' =&gt; 'bhutan', 'bo' =&gt; 'bolivia, stato plurinazionale della', 'bq' =&gt; 'bonaire, saint eustatius e saba', 'ba' =&gt; 'bosnia e herzegovina', 'bw' =&gt; 'botswana', 'bv' =&gt; 'bouvet island', 'br' =&gt; 'brasile', 'io' =&gt; 'territorio britannico del oceano indiano', 'bn' =&gt; 'brunei darussalam', 'bg' =&gt; 'bulgaria', 'bf' =&gt; 'burkina faso', 'bi' =&gt; 'burundi', 'kh' =&gt; 'cambogia', 'cm' =&gt; 'camerun', 'ca' =&gt; 'canada', 'cv' =&gt; 'capo verde', 'ky' =&gt; 'isole cayman', 'cf' =&gt; 'repubblica dell\'africa centrale', 'td' =&gt; 'chad', 'cl' =&gt; 'chile', 'cn' =&gt; 'cina', 'cx' =&gt; 'isola di natale', 'cc' =&gt; 'isole cocos (keeling)', 'co' =&gt; 'colombia', 'km' =&gt; 'comoros', 'cg' =&gt; 'congo', 'cd' =&gt; 'congo, repubblica democratica del', 'ck' =&gt; 'isole cook', 'cr' =&gt; 'costa rica', 'ci' =&gt; 'costa d\'avorio', 'hr' =&gt; 'croazia', 'cu' =&gt; 'cuba', 'cw' =&gt; 'curacao', 'cy' =&gt; 'cipro', 'cz' =&gt; 'repubblica ceca', 'dk' =&gt; 'danimarca', 'dj' =&gt; 'djibouti', 'dm' =&gt; 'dominica', 'do' =&gt; 'repubblica dominicana', 'ec' =&gt; 'ecuador', 'eg' =&gt; 'egitto', 'sv' =&gt; 'el salvador', 'gq' =&gt; 'guinea equatoriale', 'er' =&gt; 'eritrea', 'ee' =&gt; 'estonia', 'et' =&gt; 'etiopia', 'fk' =&gt; 'isole falkland (malvinas)', 'fo' =&gt; 'isole faroe', 'fj' =&gt; 'fiji', 'fi' =&gt; 'finlandia', 'fr' =&gt; 'francia', 'gf' =&gt; 'guiana francese', 'pf' =&gt; 'polinesia francese', 'tf' =&gt; 'territori francesi del sud', 'ga' =&gt; 'gabon', 'gm' =&gt; 'gambia', 'ge' =&gt; 'georgia', 'de' =&gt; 'germania', 'gh' =&gt; 'ghana', 'gi' =&gt; 'gibilterra', 'gr' =&gt; 'grecia', 'gl' =&gt; 'groenlandia', 'gd' =&gt; 'grenada', 'gp' =&gt; 'guadeloupe', 'gu' =&gt; 'guam', 'gt' =&gt; 'guatemala', 'gg' =&gt; 'guernsey', 'gn' =&gt; 'guinea', 'gw' =&gt; 'guinea-bissau', 'gy' =&gt; 'guyana', 'ht' =&gt; 'haiti', 'hm' =&gt; 'isola heard e isola mcdonald', 'va' =&gt; 'stato del vaticano', 'hn' =&gt; 'honduras', 'hk' =&gt; 'hong kong', 'hu' =&gt; 'ungheria', 'is' =&gt; 'islanda', 'in' =&gt; 'india', 'id' =&gt; 'indonesia', 'ir' =&gt; 'iran, repubblica islamica del', 'iq' =&gt; 'iraq', 'ie' =&gt; 'irlanda', 'im' =&gt; 'isola man', 'il' =&gt; 'israele', 'it' =&gt; 'italia', 'jm' =&gt; 'giamaica', 'jp' =&gt; 'giappone', 'je' =&gt; 'jersey', 'jo' =&gt; 'giordania', 'kz' =&gt; 'kazakistan', 'ke' =&gt; 'kenya', 'ki' =&gt; 'kiribati', 'kp' =&gt; 'corea, repubblica popolare della', 'kr' =&gt; 'corea, repubblica della', 'kw' =&gt; 'kuwait', 'kg' =&gt; 'kyrgyzstan', 'la' =&gt; 'lao, repubblica popolare del', 'lv' =&gt; 'lettonia', 'lb' =&gt; 'libano', 'ls' =&gt; 'lesotho', 'lr' =&gt; 'liberia', 'ly' =&gt; 'libia', 'li' =&gt; 'liechtenstein', 'lt' =&gt; 'lituania', 'lu' =&gt; 'lussemburgo', 'mo' =&gt; 'macao', 'mk' =&gt; 'macedonia', 'mg' =&gt; 'madagascar', 'mw' =&gt; 'malawi', 'my' =&gt; 'malesia', 'mv' =&gt; 'maldive', 'ml' =&gt; 'mali', 'mt' =&gt; 'malta', 'mh' =&gt; 'isole marshall', 'mq' =&gt; 'martinique', 'mr' =&gt; 'mauritania', 'mu' =&gt; 'mauritius', 'yt' =&gt; 'mayotte', 'mx' =&gt; 'messico', 'fm' =&gt; 'micronesia, stati federali del', 'md' =&gt; 'moldavia', 'mc' =&gt; 'monaco', 'mn' =&gt; 'mongolia', 'me' =&gt; 'montenegro', 'ms' =&gt; 'montserrat', 'ma' =&gt; 'marocco', 'mz' =&gt; 'mozambico', 'mm' =&gt; 'myanmar', 'na' =&gt; 'namibia', 'nr' =&gt; 'nauru', 'np' =&gt; 'nepal', 'nl' =&gt; 'olanda', 'nc' =&gt; 'nuova caledonia', 'nz' =&gt; 'nuova zelanda', 'ni' =&gt; 'nicaragua', 'ne' =&gt; 'niger', 'ng' =&gt; 'nigeria', 'nu' =&gt; 'niue', 'nf' =&gt; 'isole norfolk', 'mp' =&gt; 'isole mariana settentrionali', 'no' =&gt; 'norvegia', 'om' =&gt; 'oman', 'pk' =&gt; 'pakistan', 'pw' =&gt; 'palau', 'ps' =&gt; 'territorio occupato della palestina', 'pa' =&gt; 'panama', 'pg' =&gt; 'papua nuova guinea', 'py' =&gt; 'paraguay', 'pe' =&gt; 'peru', 'ph' =&gt; 'filippine', 'pn' =&gt; 'pitcairn', 'pl' =&gt; 'polonia', 'pt' =&gt; 'portogallo', 'pr' =&gt; 'porto rico', 'qa' =&gt; 'qatar', 're' =&gt; 'reunion', 'ro' =&gt; 'romania', 'ru' =&gt; 'russia', 'rw' =&gt; 'ruanda', 'bl' =&gt; 'saint barthelemy', 'sh' =&gt; 'saint helena, ascension tristan da cunha', 'kn' =&gt; 'saint kitts nevis', 'lc' =&gt; 'saint lucia', 'mf' =&gt; 'saint martin (french part)', 'pm' =&gt; 'saint pierre miquelon', 'vc' =&gt; 'saint vincent grenadines', 'ws' =&gt; 'samoa', 'sm' =&gt; 'san marino', 'st' =&gt; 'sao tome principe', 'sa' =&gt; 'arabia saudita', 'sn' =&gt; 'senegal', 'rs' =&gt; 'serbia', 'sc' =&gt; 'seychelles', 'sl' =&gt; 'sierra leone', 'sg' =&gt; 'singapore', 'sx' =&gt; 'sint maarten (dutch part)', 'sk' =&gt; 'slovacchia', 'si' =&gt; 'slovenia', 'sb' =&gt; 'isole solomon', 'so' =&gt; 'somalia', 'za' =&gt; 'africa del sud', 'gs' =&gt; 'south georgia south sandwich islands', 'es' =&gt; 'spagna', 'lk' =&gt; 'sri lanka', 'sd' =&gt; 'sudan', 'sr' =&gt; 'suriname', 'sj' =&gt; 'svalbard jan mayen', 'sz' =&gt; 'swaziland', 'se' =&gt; 'svezia', 'ch' =&gt; 'svizzera', 'sy' =&gt; 'siria', 'tw' =&gt; 'taiwan, provincia della cina', 'tj' =&gt; 'tajikistan', 'tz' =&gt; 'tanzania', 'th' =&gt; 'tailandia', 'tl' =&gt; 'timor-leste', 'tg' =&gt; 'togo', 'tk' =&gt; 'tokelau', 'to' =&gt; 'tonga', 'tt' =&gt; 'trinidad tobago', 'tn' =&gt; 'tunisia', 'tr' =&gt; 'turchia', 'tm' =&gt; 'turkmenistan', 'tc' =&gt; 'turks caicos islands', 'tv' =&gt; 'tuvalu', 'ug' =&gt; 'uganda', 'ua' =&gt; 'ucraina', 'ae' =&gt; 'emirati arabi uniti', 'gb' =&gt; 'gran bretagna', 'us' =&gt; 'stati uniti d\'america', 'um' =&gt; 'stati uniti, isole minori', 'uy' =&gt; 'uruguay', 'uz' =&gt; 'uzbekistan', 'vu' =&gt; 'vanuatu', 've' =&gt; 'venezuela', 'vn' =&gt; 'vietnam', 'vg' =&gt; 'isole vergini brittaniche', 'vi' =&gt; 'isole vergini, u.s.', 'wf' =&gt; 'wallis futuna', 'eh' =&gt; 'sahara occidentale', 'ye' =&gt; 'yemen', 'zm' =&gt; 'zambia', 'zw' =&gt; 'zimbabue', ], 'cron' =&gt; [ 'cronname' =&gt; 'nome cronjob', 'lastrun' =&gt; 'ultima esecuzione', 'interval' =&gt; 'intervallo', 'isactive' =&gt; 'abilitato', 'description' =&gt; 'descrizione', 'changewarning' =&gt; 'la modifica di questi valori pu avere conseguenze negative nel comportamento di froxlor e dei suoi processi automatizzati&lt;br /&gt;per favore modifica questi valori solo se sei sicuro di quello che stai facendo!', ], 'crondesc' =&gt; [ 'cron_unknown_desc' =&gt; 'nessuna descrizione fornita', 'cron_tasks' =&gt; 'generazione del file di configurazione', 'cron_legacy' =&gt; 'legacy (vecchi) cronjob', 'cron_traffic' =&gt; 'calcolo del traffico', 'cron_usage_report' =&gt; 'invia report di utilizzo web e del traffico', 'cron_mailboxsize' =&gt; 'calcolo dimensioni caselle di posta', ], 'cronjob' =&gt; [ 'cronjobsettings' =&gt; 'impostazioni cronjob', 'cronjobinterval' =&gt; 'durata intervallo', 'cronjobintervalv' =&gt; 'valore di intervallo runtime', ], 'cronjobs' =&gt; [ 'notyetrun' =&gt; 'non ancora avviato', ], 'cronmgmt' =&gt; [ 'minutes' =&gt; 'minuti', 'hours' =&gt; 'ore', 'days' =&gt; 'giorni', 'weeks' =&gt; 'settimane', 'months' =&gt; 'mesi', ], 'customer' =&gt; [ 'documentroot' =&gt; 'cartella principale', 'name' =&gt; 'cognome', 'firstname' =&gt; 'nome', 'company' =&gt; 'ditta', 'street' =&gt; 'via', 'zipcode' =&gt; 'cap', 'city' =&gt; 'citt', 'phone' =&gt; 'telefono', 'fax' =&gt; 'fax', 'email' =&gt; 'email', 'customernumber' =&gt; 'id cliente', 'diskspace' =&gt; 'spazio web (mb)', 'traffic' =&gt; 'traffico (gb)', 'mysqls' =&gt; 'database mysql', 'emails' =&gt; 'indirizzi email', 'accounts' =&gt; 'account email', 'forwarders' =&gt; 'reindirizzamenti email', 'ftps' =&gt; 'account ftp', 'subdomains' =&gt; 'sottodomini', 'domains' =&gt; 'domini', 'title' =&gt; 'titolo', 'country' =&gt; 'paese', 'email_quota' =&gt; 'limite e-mail', 'email_imap' =&gt; 'e-mail imap', 'email_pop3' =&gt; 'e-mail pop3', 'mail_quota' =&gt; 'limite mail', 'sendinfomail' =&gt; 'inviami dati via email', 'generated_pwd' =&gt; 'password suggerita', 'usedmax' =&gt; 'usato / massimo', 'services' =&gt; 'servizi', ], 'diskquota' =&gt; 'quota', 'dns' =&gt; [ 'destinationip' =&gt; 'dominio ip', 'a_record' =&gt; 'a-record (ipv6 optionale)', 'mxrecords' =&gt; 'definisci mx records', 'txtrecords' =&gt; 'definisci txt records', 'txtexample' =&gt; 'esempio (spf-entry):&lt;br /&gt;v=spf1 ip4:xxx.xxx.xx.0/23 -all', 'standardip' =&gt; 'ip predefinito del server', 'cname_record' =&gt; 'record cname', 'standardmx' =&gt; 'record mx predefinito del server', 'mxconfig' =&gt; 'record mx personalizzati', 'priority10' =&gt; 'priorit 10', 'priority20' =&gt; 'priorit 20', ], 'domain' =&gt; [ 'openbasedirpath' =&gt; 'percorso openbasedir', 'docroot' =&gt; 'percorso del campo sopra', 'homedir' =&gt; 'cartella home', ], 'domains' =&gt; [ 'description' =&gt; 'qui puoi creare (sotto)domini e cambiare il loro percorso.&lt;br /&gt;il sistema, dopo ogni cambiamento, necessita di un po\' di tempo per applicare le nuove impostazioni.', 'domainsettings' =&gt; 'opzioni del dominio', 'domainname' =&gt; 'nome del dominio', 'subdomain_add' =&gt; 'crea sottodominio', 'subdomain_edit' =&gt; 'modifica il (sotto)dominio', 'wildcarddomain' =&gt; 'crea una wildcarddomain?', 'aliasdomain' =&gt; 'alias per questo dominio', 'noaliasdomain' =&gt; 'nessun alias per il dominio', 'hasaliasdomains' =&gt; 'ha domini alias', 'statstics' =&gt; 'statistiche d\'utilizzo', 'isassigneddomain' =&gt; ' dominio assegnato', 'add_date' =&gt; 'aggiunto froxlor', 'registration_date' =&gt; 'aggiunto al registro', 'topleveldomain' =&gt; 'dominio di primo livello (tld)', 'associated_with_domain' =&gt; 'associato', 'aliasdomains' =&gt; 'alias domini', 'redirectifpathisurl' =&gt; 'codice di redirezione (predefinito: vuoto)', 'redirectifpathisurlinfo' =&gt; ' necessario selezionare uno di questi se hai inserito un url come percorso', 'ipandport_multi' =&gt; [ 'title' =&gt; 'indirizzi ip', 'description' =&gt; 'specifica uno pi indirizzi ip per il dominio.&lt;br /&gt;&lt;br /&gt;&lt;div class="text-danger"&gt;nota: l\'indirizzo ip non pu essere modificato quando il dominio configurato come &lt;strong&gt;alias-domain&lt;/strong&gt; di un altro dominio.&lt;/div&gt;', ], 'ipandport_ssl_multi' =&gt; [ 'title' =&gt; 'indirizzi ip ssl', ], 'ssl_redirect' =&gt; [ 'title' =&gt; 'reindirizzamento ssl', 'description' =&gt; 'questa opzione crea un reindirizzamento per vhosts non-sll modo che tutte le richieste vengono reindirizzate ai ssl-vhost.&lt;br /&gt;&lt;br /&gt;praticamente una richiesta &lt;strong&gt;http&lt;/strong&gt;://dominio.tld/ ti reindirizzera &lt;strong&gt;https&lt;/strong&gt;://dominio.tld/', ], 'serveraliasoption_wildcard' =&gt; 'wildcard (*.dominio.tld)', 'serveraliasoption_www' =&gt; 'www (www.dominio.tld)', 'serveraliasoption_none' =&gt; 'nessun alias', 'domain_import' =&gt; 'importa dominii', 'import_separator' =&gt; 'separatore', 'import_offset' =&gt; 'offset', 'import_file' =&gt; 'file csv', 'import_description' =&gt; 'per ottenere informazioni dettagliate sulla struttura del file di importazione e su come importare con successo, visita &lt;a href="https://docs.froxlor.org/latest/admin-guide/domain-import/" target="_blank"&gt;https://docs.froxlor.org/latest/admin-guide/domain-import/&lt;/a&gt;', ], 'emails' =&gt; [ 'description' =&gt; 'qui puoi creare e cambiare tuoi indirizzi email.&lt;br /&gt;un account come la bucalettere davanti casa tua. se qualcuno ti manda un\'email, essa sar recapitata all\'interno del tuo account.&lt;br /&gt;&lt;br /&gt;per scaricare le tue email usa le seguenti impostazioni nel tuo programma di posta elettronica: (i dati scritti &lt;i&gt;corsivo&lt;/i&gt; vanno cambiati con tuoi!)&lt;br /&gt;hostname: &lt;b&gt;&lt;i&gt;nome del dominio&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;username: &lt;b&gt;&lt;i&gt;nome dell\'account / indirizzo email&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;password: &lt;b&gt;&lt;i&gt;la password scelta&lt;/i&gt;&lt;/b&gt;', 'emailaddress' =&gt; 'indirizzo email', 'emails_add' =&gt; 'crea indirizzo email', 'emails_edit' =&gt; 'modifica indirizzo email', 'catchall' =&gt; 'catch-all', 'iscatchall' =&gt; 'definisci come indirizzo catch-all?', 'account' =&gt; 'account', 'account_add' =&gt; 'crea account', 'account_delete' =&gt; 'cancella account', 'from' =&gt; 'da', 'to' =&gt; 'per', 'forwarders' =&gt; 'reindirizzamenti', 'forwarder_add' =&gt; 'crea reindirizzamento', 'alternative_emailaddress' =&gt; 'indirizzo email alternativo', 'quota' =&gt; 'limite', 'noquota' =&gt; 'nessun limite', 'updatequota' =&gt; 'aggiorna limite', 'quota_edit' =&gt; 'cambia limite e-mail', 'noemaildomainaddedyet' =&gt; 'non hai ancora un (email-)dominio nel tuo account.', 'back_to_overview' =&gt; 'torna indietro nel riepilogo', ], 'error' =&gt; [ 'error' =&gt; 'errore', 'directorymustexist' =&gt; 'la cartella %s deve esistere. per favore creala tramite il tuo client ftp.', 'filemustexist' =&gt; 'il file %s deve esistere.', 'allresourcesused' =&gt; 'hai gi usato tutte le tue risorse.', 'domains_cantdeletemaindomain' =&gt; 'non puoi cancellare un dominio usato come dominio email.', 'domains_canteditdomain' =&gt; 'non puoi modificare questo dominio. la funzione stata disabilitata dall\'admin.', 'domains_cantdeletedomainwithemail' =&gt; 'non puoi cancellare un dominio usato come dominio email. cancella prima tutti gli indirizzi email che lo utilizzano.', 'firstdeleteallsubdomains' =&gt; 'prima di creare un dominio wildcard, cancella tutti sottodomini presenti per quel dominio.', 'youhavealreadyacatchallforthisdomain' =&gt; 'hai gi definito un catchall per questo dominio.', 'ftp_cantdeletemainaccount' =&gt; 'non puoi cancellare il tuo account ftp principale.', 'login' =&gt; 'il nome utente la password da te immessi sono incorretti. per favore riprova!', 'login_blocked' =&gt; 'questo account stato sospeso per troppi tentativi di login falliti. &lt;br /&gt;riprovi tra %s secondi.', 'notallreqfieldsorerrors' =&gt; 'alcuni campi sono stati lasciati vuoti sono stati riempiti incorrettamente.', 'oldpasswordnotcorrect' =&gt; 'la vecchia password non corretta.', 'youcantallocatemorethanyouhave' =&gt; 'non puoi assegnare pi risorse di quante ne possieda tu stesso.', 'mustbeurl' =&gt; 'non hai inserito un\'indirizzo valido completo (per es. http://qualchedominio.com/errore404.htm).', 'invalidpath' =&gt; 'non hai scelto un\'indirizzo valido.', 'stringisempty' =&gt; 'manca il dato nel campo.', 'stringiswrong' =&gt; 'dato incorretto.', 'newpasswordconfirmerror' =&gt; 'la nuova password non corrisponde quella vecchia.', 'mydomain' =&gt; '\'dominio\'', 'mydocumentroot' =&gt; '\'documentroot\'', 'loginnameexists' =&gt; 'il login %s esiste gi.', 'emailiswrong' =&gt; 'l\'indirizzo email %s contiene caratteri invalidi incompleto.', 'loginnameiswrong' =&gt; 'il login %s contiene caratteri invalidi.', 'userpathcombinationdupe' =&gt; 'la combinazione tra nome utente e percorso esiste gi.', 'patherror' =&gt; 'errore! il percorso non pu essere vuoto.', 'errordocpathdupe' =&gt; 'le opzioni per la cartella %s esistono gi.', 'adduserfirst' =&gt; 'per favore crea prima un utente ...', 'domainalreadyexists' =&gt; 'il dominio %s gi assegnato ad un cliente.', 'nolanguageselect' =&gt; 'nessuna lingua selezionata.', 'nosubjectcreate' =&gt; 'devi definire un titolo per questo template email.', 'nomailbodycreate' =&gt; 'devi definiro un testo per questo template email.', 'templatenotfound' =&gt; 'il template non stato trovato.', 'alltemplatesdefined' =&gt; 'non puoi definire altri template, tutte le lingue sono gi definite.', 'wwwnotallowed' =&gt; 'www non ammesso come sottodominio.', 'subdomainiswrong' =&gt; 'il sottodominio %s contiene caratteri invalidi.', 'domaincantbeempty' =&gt; 'il nome dominio non pu essere vuoto.', 'domainexistalready' =&gt; 'il dominio %s esiste gi.', 'domainisaliasorothercustomer' =&gt; 'il dominio alias selezionato sua volta un dominio alias appartiene ad un altro cliente.', 'emailexistalready' =&gt; 'l\'indirizzo email %s esiste gi.', 'maindomainnonexist' =&gt; 'il dominio principale %s non esiste.', 'destinationnonexist' =&gt; 'per favore crea il tuo reindirizzamento nel campo \'destinazione\'.', 'destinationalreadyexistasmail' =&gt; 'il reindirizzamento %s esiste gi come indirizzo email attivo.', 'destinationalreadyexist' =&gt; 'hai gi definito un reindirizzamento per %s .', 'destinationiswrong' =&gt; 'il reindirizzamento %s contiene caratteri invalidi incompleto.', 'ipstillhasdomains' =&gt; 'la combinazione ip/porta che vuoi eliminare ha ancora dei domini assegnati, per favore riassegna questi domini ad altre combinazioni ip/porta prima di eliminare questa.', 'cantdeletedefaultip' =&gt; 'non puoi eliminare la combinazione ip/porta default dei rivenditori, per favore imposta un\'altra combinazione ip/porta come default dei rivenditori prima di eliminare questa.', 'cantdeletesystemip' =&gt; 'non puoi eliminare l\'ultima ip di sistema, crea un\'altra combinazione ip/porta per l\'ip di sistema cambia l\'ip di sistema.', 'myipaddress' =&gt; '\'ip\'', 'myport' =&gt; '\'porta\'', 'myipdefault' =&gt; 'devi selezionare una combinazione ip/porta che diventer default.', 'myipnotdouble' =&gt; 'questa combinazione ip/porta esiste gi.', 'admin_domain_emailsystemhostname' =&gt; 'spiacente, l\'hostname di sistema non pu essere usato come dominio di un cliente', 'cantchangesystemip' =&gt; 'non puoi cambiare l\'ultima ip di sistema, crea un\'altra combinazione ip/porta per l\'ip di sistema cambia l\'ip di sistema.', 'loginnameissystemaccount' =&gt; 'non puoi creare account che siano analoghi quelli di sistema (per esempio quelli che iniziano con "%s"). digita un\'altro nome account.', 'sessiontimeoutiswrong' =&gt; '"timeout sessione" deve essere un numero.', 'maxloginattemptsiswrong' =&gt; '"numero massimo tentativi login" deve essere un numero.', 'deactivatetimiswrong' =&gt; '"durata disattivamento" deve essere un numero.', 'accountprefixiswrong' =&gt; '&amp;quopt;prefisso utente" incorretto.', 'mysqlprefixiswrong' =&gt; '&amp;quopt;prefisso sql" incorretto.', 'ftpprefixiswrong' =&gt; '&amp;quopt;prefisso ftp" incorretto.', 'ipiswrong' =&gt; '"indirizzo ip" incorretto. permesso solo un indirizzo ip valido.', 'vmailuidiswrong' =&gt; '"uid email" incorretto. permessa solo una uid numerica.', 'vmailgidiswrong' =&gt; '"gid email" incorretto. permessa solo una gid numerica.', 'adminmailiswrong' =&gt; '"mittente" incorretto. permesso solo un indirizzo email valido.', 'pagingiswrong' =&gt; 'valore degli "elementi da visualizzare per pagina" incorretto. sono permessi solo numeri.', 'phpmyadminiswrong' =&gt; 'il link phpmyadmin invalido.', 'webmailiswrong' =&gt; 'il link alla webmail invalido.', 'webftpiswrong' =&gt; 'il link al webftp invalido.', 'stringformaterror' =&gt; 'il valore per il campo "%s" non nel formato atteso.', 'youcantdeleteyourself' =&gt; 'non puoi cancellare te stesso per motivi di sicurezza.', 'youcanteditallfieldsofyourself' =&gt; 'nota: non puoi modificare tutti campi del tuo account per motivi di sicurezza.', 'documentrootexists' =&gt; 'la cartella "%s" gi presente per questo cliente. cancella la cartella prima di aggiungere nuovamente il cliente.', 'formtokencompromised' =&gt; 'la richiesta sembra essere compromessa. per motivi di sicurezza sei stato disconnesso.', 'logerror' =&gt; 'errore log: %s', 'nomessagetosend' =&gt; 'non hai inserito un messaggio.', 'norecipientsgiven' =&gt; 'non hai specificato alcun destinatario', 'errorsendingmail' =&gt; 'il messaggio "%s" fallito', 'cannotreaddir' =&gt; 'impossibile leggere la cartella "%s"', 'invalidip' =&gt; 'indirizzo ip non valido: %s', 'invalidmysqlhost' =&gt; 'indirizzo mysql non valido: %s', 'cannotuseawstatsandwebalizeratonetime' =&gt; 'non possibile abilitare webalizer e awstats allo stesso tempo, si prega di sceglierne uno solo', 'cannotwritetologfile' =&gt; 'impossibile aprire il file di log %s scrittura', 'vmailquotawrong' =&gt; 'il limite deve essere un numero positivo.', 'allocatetoomuchquota' =&gt; 'si tentato di allocare %s mb limite, non c\' abbastanza spazio disponibile.', 'missingfields' =&gt; 'non tutti campi obbligatori sono stati compilati.', 'accountnotexisting' =&gt; 'l\'account di posta elettronica dato non esiste.', 'nopermissionsorinvalidid' =&gt; 'non hai permessi necessari per modificare le impostazioni stato fornito un id non valido.', 'phpsettingidwrong' =&gt; 'una configurazione php con questo id non esiste', 'descriptioninvalid' =&gt; 'la descrizione troppo corta, la descrizione troppo corta troppo lunga contiene caratteri non validi.', 'info' =&gt; 'info', 'filecontentnotset' =&gt; 'il file non pu essere vuoto!', 'index_file_extension' =&gt; 'l\'estensione file del file index deve essere compresa tra 1 e 6 caratteri. l\'estensione pu contenere solo caratteri a-z, a-z 0-9', 'customerdoesntexist' =&gt; 'il cliente che si selezionato non esiste.', 'admindoesntexist' =&gt; 'l\'amministratore che si selezionato non esiste.', 'ipportdoesntexist' =&gt; 'la combinazione ip/porta selezionata non esiste.', 'usernamealreadyexists' =&gt; 'esiste gi il nome utente: %s', 'plausibilitychecknotunderstood' =&gt; 'il controllo non ha capito la risposta di plausibilit', 'errorwhensaving' =&gt; 'verificato un errore durante il salvataggio del campo %s', 'hiddenfieldvaluechanged' =&gt; 'il valore per il campo nascosto "%s" cambiato durante la modifica delle impostazioni.&lt;br /&gt;&lt;br /&gt;questo non solitamente un grosso problema, le impostazioni potrebbe non essere salvate causa di questo.', 'notrequiredpasswordlength' =&gt; 'la password scritta troppo corta. si prega di scrivere una password lunga almeno %s caratteri.', 'overviewsettingoptionisnotavalidfield' =&gt; 'woops, un campo che dovrebbe essere mostrato come opzione impostazioni-principale non un tipo esclusivo. si possono rimproverare gli sviluppatori per questo. questo non deve accadere!', 'pathmaynotcontaincolon' =&gt; 'il percorso che hai inserito non dovrebbe contenere due punti (:). inserisci un percorso valido.', 'exception' =&gt; '%s', 'notrequiredpasswordcomplexity' =&gt; 'la complessita della password specificata non soddisfacente.&lt;br /&gt;si prega di contattare l\'amministratore se avete domande sulla complessit della password', 'stringerrordocumentnotvalidforlighty' =&gt; 'una stringa come errordocument non funziona lighttpd, si prega di specificare un percorso di un file', 'urlerrordocumentnotvalidforlighty' =&gt; 'un url come errordocument non funziona lighttpd, si prega di specificare un percorso di un file', 'intvaluetoolow' =&gt; 'il numero dato troppo basso (campo %s)', 'intvaluetoohigh' =&gt; 'il numero dato troppo alto (campo %s)', 'phpfpmstillenabled' =&gt; 'php-fpm attivo. si prega di disattivarlo prima di attivare fcgid', 'fcgidstillenabled' =&gt; 'fcgid attivo. si prega di disattivarlo prima di attivare php-fpm', 'domains_cantdeletedomainwithaliases' =&gt; 'non possibile cancellare un dominio che viene utilizzato per alias-domains. necessario eliminare prima gli alias.', 'user_banned' =&gt; 'il tuo account stato bannato. contatta l\'amministratore per maggiori informazioni.', 'loginnameiswrong2' =&gt; 'il nome utente contiente troppi caratteri. sono permessi soltanto %s caratteri.', 'session_timeout' =&gt; 'valore troppo basso', 'session_timeout_desc' =&gt; 'non dovresti settare il timeout della sessione ad un valore minore di 1 minuto.', 'invalidhostname' =&gt; 'il nome del host non pu essere vuoto contenere spazi', 'operationnotpermitted' =&gt; 'operazione non permessa!', 'featureisdisabled' =&gt; 'funzionalit %s disabilitata. perfavore contatta il tuo fornitore di servizi.', 'usercurrentlydeactivated' =&gt; 'l\'utente %s attualmente disabilitato', 'setlessthanalreadyused' =&gt; 'non puoi impostare dei limiti minori per \'%s\', di quanto questo utente abbia gi utilizzato&lt;br /&gt;', 'stringmustntbeempty' =&gt; 'il valore per il campo %s non pu essere vuoto', 'sslcertificateismissingprivatekey' =&gt; 'devi specificare una chiave privata per il tuo certificato', 'sslcertificatewrongdomain' =&gt; 'il certificato fornito non appartiene questo dominio', 'sslcertificateinvalidcert' =&gt; 'il contenuto del certificato fornito non sembra essere un certificato valido', 'sslcertificateinvalidcertkeypair' =&gt; 'la chiave privata fornita non sembra appartenere al certificato fornito', 'sslcertificateinvalidca' =&gt; 'il certificato ca fornito non sembra essere un certificato valido', 'sslcertificateinvalidchain' =&gt; 'i dati della catena di certificato non sembrano essere un certificato valido', 'givendirnotallowed' =&gt; 'la cartella fornita nel campo %s non permessa.', 'sslredirectonlypossiblewithsslipport' =&gt; 'l\'utilizzo del reindirizzamento ssl possibile soltanto quando il dominio ha almeno una combinazione ip/porta assegnata ed abilitata ssl.', 'fcgidstillenableddeadlock' =&gt; 'fcgid attualmente attivo.&lt;br /&gt;perfavore disattivalo prima di cambiare ad un server web diverso da apache2', 'send_report_title' =&gt; 'invia rapporto errori', 'send_report_desc' =&gt; 'grazie per aver communicato questo errore, aiutandoci migliorare froxlor.&lt;br /&gt;questa la mail che verr inviata agli svillupatori di froxlor:', 'send_report' =&gt; 'invia rapporto', 'send_report_error' =&gt; 'errore nell invio del rapporto: &lt;br /&gt;%s', 'notallowedtouseaccounts' =&gt; 'il tuo account non permette l\'utilizzo di imap/pop3. non puoi aggiungere account di posta elettronica.', 'cannotdeletehostnamephpconfig' =&gt; 'questa configurazione php utilizzata dal vhost froxlor e non pu essere eliminata.', 'cannotdeletedefaultphpconfig' =&gt; 'questa configurazione php impostata come predefinita e non pu essere eliminata.', 'passwordshouldnotbeusername' =&gt; 'la password deve essere diversa dal nome utente.', 'no_phpinfo' =&gt; 'ci dispiace, impossibile leggere phpinfo()', 'moveofcustomerfailed' =&gt; 'trasferimento del cliente all\'amministratore/rivenditore selezionato fallito. considera che tutte le altre modfiche al cliente sono state applicate con successo questa fase.&lt;br&gt;&lt;br&gt;messaggio d\'errore: %s', 'domain_import_error' =&gt; 'il seguente errore occorsonell \'importazione di dominii: %s', ], 'extras' =&gt; [ 'description' =&gt; 'qui puoi aggiungere alcune opzioni extra, per esempio impostare delle cartelle protette.&lt;br /&gt;il sistema, dopo ogni cambiamento, necessita di un po\' di tempo per applicare le nuove impostazioni.', 'directoryprotection_add' =&gt; 'aggiungi protezione cartella', 'view_directory' =&gt; 'mostra protezione cartella', 'pathoptions_add' =&gt; 'aggiungi opzioni cartella', 'directory_browsing' =&gt; 'visualizza file e cartelle', 'pathoptions_edit' =&gt; 'modifica opzioni cartella', 'errordocument404path' =&gt; 'url errordocument 404', 'errordocument403path' =&gt; 'url errordocument 403', 'errordocument500path' =&gt; 'url errordocument 500', 'errordocument401path' =&gt; 'url errordocument 401', 'execute_perl' =&gt; 'esegui perl/cgi', 'htpasswdauthname' =&gt; 'argomento di autenticazione (authname)', 'directoryprotection_edit' =&gt; 'modifica la protezione della directory', ], 'ftp' =&gt; [ 'description' =&gt; 'qui puoi creare e modificare tuoi account ftp.&lt;br /&gt;i cambiamenti sono effettuati tempo reale e gli account si possono usare immediatamente.', 'account_add' =&gt; 'crea account', 'account_edit' =&gt; 'modifica acocunt ftp', 'editpassdescription' =&gt; 'imposta una nuova password lascia vuoto per non cambiarla.', ], 'gender' =&gt; [ 'title' =&gt; 'titolo', 'male' =&gt; 'sig.', 'female' =&gt; 'sig.ra', 'undef' =&gt; '', ], 'index' =&gt; [ 'customerdetails' =&gt; 'dettagli cliente', 'accountdetails' =&gt; 'dettagli account', ], 'logger' =&gt; [ 'date' =&gt; 'data', 'type' =&gt; 'tipo', 'action' =&gt; 'azione', 'user' =&gt; 'utente', 'truncate' =&gt; 'log vuoto', 'reseller' =&gt; 'rivenditore', 'admin' =&gt; 'amministratore', 'cron' =&gt; 'cronjob', 'login' =&gt; 'login', 'intern' =&gt; 'interno', 'unknown' =&gt; 'sconosciuto', ], 'login' =&gt; [ 'username' =&gt; 'nome utente', 'password' =&gt; 'password', 'language' =&gt; 'lingua', 'login' =&gt; 'login', 'logout' =&gt; 'logout', 'profile_lng' =&gt; 'scegli la lingua', 'forgotpwd' =&gt; 'dimenticato la password?', 'presend' =&gt; 'reimposta la password', 'email' =&gt; 'indirizzo e-mail', 'remind' =&gt; 'reimposta la mia password', 'usernotfound' =&gt; 'utente non trovata!', 'backtologin' =&gt; 'torna al login', 'combination_not_found' =&gt; 'combinazione utente-indirizzo email non trovata.', ], 'mails' =&gt; [ 'pop_success' =&gt; [ 'mailbody' =&gt; 'salve,\\n\\nil tuo indirizzo email {email}\\n stato configurato con successo.\\n\\nquesta un\'email creata automaticamente,\\n per favore non rispondere!\\n\\ncordiali saluti, amministratore.', 'subject' =&gt; 'indirizzo email configurato con successo', ], 'createcustomer' =&gt; [ 'mailbody' =&gt; 'salve {firstname} {name},\\n\\nqueste sono le informazioni per il tuo account:\\n\\nnome utente: {username}\\npassword: {password}\\n\\ngrazie,\\namministratore.', 'subject' =&gt; 'informazioni account', ], 'pop_success_alternative' =&gt; [ 'mailbody' =&gt; 'salve,\\n\\nil tuo account email {email}\\n stato creato correttamente.\\nla tua password {password}.\\n\\nquesta un\'email creata automaticamente,\\n si prega di non rispondere questa email!\\n\\ncordiali saluti, amministratore.', 'subject' =&gt; 'account email creato correttamente', ], 'password_reset' =&gt; [ 'subject' =&gt; 'reimposta password', 'mailbody' =&gt; 'salve {username},\\n\\nla tua password froxlor stata reimpostata!\\nla nuova password : {link}\\n\\ngrazie,\\n team froxlor', ], 'new_database_by_customer' =&gt; [ 'subject' =&gt; '[froxlor] nuovo database creato', 'mailbody' =&gt; 'hello {cust_name}, hai appena aggiunto un nuovo database. ecco le informazioni inserite: nome database: {db_name} password: {db_pass} descrizione: {db_desc} db-hostname: {db_srv} {pma_uri} cordiali saluti, team froxlor', ], 'new_ftpaccount_by_customer' =&gt; [ 'subject' =&gt; 'nuovo utente ftp creato', 'mailbody' =&gt; 'salve {cust_name}, hai appena aggiunto un nuovo utente ftp. ecco le informazioni inserite: nome utente: {usr_name} password: {usr_pass} percorso: {usr_path} cordiali saluti, team froxlor', ], 'trafficmaxpercent' =&gt; [ 'mailbody' =&gt; 'salve {name},\\n\\nhai utilizzato {trafficused} mb di {traffic} mb traffico disponibile.\\nquesto pi del {max_percent}%%.\\n\\ncordiali saluti, il team froxlor', 'subject' =&gt; 'raggiunto il limite di traffico', ], 'diskmaxpercent' =&gt; [ 'mailbody' =&gt; 'salve {name},\\n\\nhai utilizzato {diskused} mb di {diskavailable} mb di spazio disponibile.\\nquesto pi del {max_percent}%%.\\n\\ncordiali saluti, il team froxlor', 'subject' =&gt; 'raggiungere il limite di spazio su disco', ], ], 'menu' =&gt; [ 'message' =&gt; 'messaggi', ], 'menue' =&gt; [ 'main' =&gt; [ 'main' =&gt; 'principale', 'changepassword' =&gt; 'cambia la password', 'changelanguage' =&gt; 'cambia la lingua', 'username' =&gt; 'utente: ', 'changetheme' =&gt; 'cambia tema', ], 'email' =&gt; [ 'email' =&gt; 'email', 'emails' =&gt; 'indirizzi', 'webmail' =&gt; 'webmail', ], 'mysql' =&gt; [ 'mysql' =&gt; 'mysql', 'databases' =&gt; 'database', 'phpmyadmin' =&gt; 'phpmyadmin', ], 'domains' =&gt; [ 'domains' =&gt; 'domini', 'settings' =&gt; 'opzioni', ], 'ftp' =&gt; [ 'ftp' =&gt; 'ftp', 'accounts' =&gt; 'account', 'webftp' =&gt; 'webftp', ], 'extras' =&gt; [ 'extras' =&gt; 'extra', 'directoryprotection' =&gt; 'cartelle protette', 'pathoptions' =&gt; 'opzioni cartelle', ], 'traffic' =&gt; [ 'traffic' =&gt; 'traffico', 'current' =&gt; 'mese corrente', 'table' =&gt; 'traffico', ], 'phpsettings' =&gt; [ 'maintitle' =&gt; 'configurazioni php', ], 'logger' =&gt; [ 'logger' =&gt; 'log di sistema', ], ], 'message' =&gt; [ 'norecipients' =&gt; 'nessuna e-mail stata inviata perch non ci sono destinatari nel database', 'success' =&gt; 'inviato correttamente il messaggio %s recipients', ], 'mysql' =&gt; [ 'description' =&gt; 'qui puoi creare e modificare il tuo database mysql&lt;br /&gt;le modifiche sono istantanee e puoi usare subito il database.&lt;br /&gt;nel men sinistra trovi phpmyadmin con cui puoi amministrare il tuo database.&lt;br /&gt;&lt;br /&gt;per usare database nei tuoi script php usa le seguenti impostazioni: (le parole &lt;i&gt;corsivo&lt;/i&gt; devono essere modificate con quello che hai scritto!)&lt;br /&gt;hostname: &lt;b&gt;&lt;sql_host&gt;&lt;/b&gt;&lt;br /&gt;utente: &lt;b&gt;&lt;i&gt;nome database&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;password: &lt;b&gt;&lt;i&gt;la password che hai scelto&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;database: &lt;b&gt;&lt;i&gt;nome database&lt;/i&gt;&lt;/b&gt;', 'databasename' =&gt; 'nome database', 'databasedescription' =&gt; 'descrizione database', 'database_create' =&gt; 'crea database', 'mysql_server' =&gt; 'server mysql', 'database_edit' =&gt; 'modifica database', 'size' =&gt; 'dimensione', ], 'panel' =&gt; [ 'edit' =&gt; 'modifica', 'delete' =&gt; 'cancella', 'create' =&gt; 'crea', 'save' =&gt; 'salva', 'yes' =&gt; 'si', 'no' =&gt; 'no', 'emptyfornochanges' =&gt; 'lasciare vuoto se non si vuole cambiare', 'emptyfordefault' =&gt; 'lasciare vuoto per l\'impostazione di default', 'path' =&gt; 'percorso', 'toggle' =&gt; 'cambia', 'next' =&gt; 'prossimo', 'dirsmissing' =&gt; 'la cartella fornita non stata trovata.', 'urloverridespath' =&gt; 'url (sovrascrive il percorso)', 'pathorurl' =&gt; 'percorso url', 'ascending' =&gt; 'ascendente', 'descending' =&gt; 'discendente', 'search' =&gt; 'cerca', 'used' =&gt; 'utilizzato', 'translator' =&gt; 'traduttore', 'reset' =&gt; 'annulla le modifiche', 'pathdescription' =&gt; 'se la cartella non esiste, viene creata automaticamente.', 'back' =&gt; 'indietro', 'reseller' =&gt; 'rivenditore', 'admin' =&gt; 'amministratore', 'customer' =&gt; 'cliente/i', 'send' =&gt; 'invia', 'nosslipsavailable' =&gt; 'attualmente non ci sono combinazioni ssl ip/porta per questo server', 'backtooverview' =&gt; 'ritorna alla pagina precedente', 'dateformat' =&gt; 'dd-mm-yyyy', 'dateformat_function' =&gt; 'd-m-y', 'timeformat_function' =&gt; 'h:i:s', 'default' =&gt; 'predefinito', 'never' =&gt; 'mai', 'active' =&gt; 'attivo', 'please_choose' =&gt; 'scegli', 'allow_modifications' =&gt; 'permetti modifiche', 'megabyte' =&gt; 'megabyte', 'not_supported' =&gt; 'non supportato in: ', 'view' =&gt; 'view', 'toomanydirs' =&gt; 'troppe sottocartelle. rifare tornando indietro nella selezione manuale della cartella.', 'abort' =&gt; 'termina', 'not_activated' =&gt; 'non attivato', 'off' =&gt; 'off', 'options' =&gt; 'opzioni', 'neverloggedin' =&gt; 'nessun login effettuato', 'descriptionerrordocument' =&gt; 'pu essere un url, un percorso ad un file solo una stringa con un " "&lt;br /&gt;lasciare vuoto per usare il valore di default del server.', 'unlock' =&gt; 'unlock', 'theme' =&gt; 'tema', 'variable' =&gt; 'variabile', 'description' =&gt; 'descrizione', 'pathdescriptionex' =&gt; '&lt;br /&gt;&lt;br /&gt;se vuoi redirezionare ad un altro dominio, questo valore deve iniziare con http:// https://.', 'pathdescriptionsubdomain' =&gt; 'se la cartella non esiste, viene creata automaticamente.&lt;br /&gt;&lt;br /&gt;se vuoi redirezionare ad un altro dominio, questo valore deve iniziare con http:// https://.&lt;br /&gt;&lt;br /&gt;se la url termina con / considerata una cartella, altrimenti verr trattata come un file.', 'cancel' =&gt; 'annulla', 'ssleditor' =&gt; 'impostazioni ssl per questo dominio', 'dashboard' =&gt; 'cruscotto', 'assigned' =&gt; 'assegnato', 'available' =&gt; 'disponibile', 'news' =&gt; 'notizie', 'ftpdesc' =&gt; 'descrizione ftp', ], 'phpfpm' =&gt; [ 'vhost_httpuser' =&gt; 'utente locale per php-fpm (froxlor vhost)', 'vhost_httpgroup' =&gt; 'gruppo locale per php-fpm (froxlor vhost)', 'ownvhost' =&gt; [ 'title' =&gt; 'abilita php-fpm per vhost froxlor', 'description' =&gt; 'se abilitato, froxlor potr essere avviato attraverso un utente locale', ], 'use_mod_proxy' =&gt; [ 'title' =&gt; 'usa mod_proxy / mod_proxy_fcgi', 'description' =&gt; 'attiva l\'utilizzo di php-fpm attraverso mod_proxy_fcgi. richiede almeno apache-2.4.9', ], ], 'pwdreminder' =&gt; [ 'success' =&gt; 'la password stata reimpostata con successo.&lt;br /&gt;a questo punto riceverai una email con la nuova password.', 'notallowed' =&gt; 'il reimposta password disabilitato', 'changed' =&gt; 'la tua password stata aggiornata con successo. puoi accedere con le tue nuove credenziali.', 'wrongcode' =&gt; 'ci dispiace, il tuo codice di attivazione non esiste gi scaduto.', 'choosenew' =&gt; 'setta la nuova password', ], 'question' =&gt; [ 'question' =&gt; 'domanda di sicurezza', 'admin_customer_reallydelete' =&gt; 'sei sicuro di voler cancellare il cliente %s? quest\'azione non potr essere annullata!', 'admin_domain_reallydelete' =&gt; 'sei sicuro di voler cancellare il dominio %s?', 'admin_domain_reallydisablesecuritysetting' =&gt; 'sei sicuro di voler disattivare queste opzioni di sicurezza (openbasedir)?', 'admin_admin_reallydelete' =&gt; 'sei sicuro di voler cancellare l\'admin %s? tutti clienti e domini saranno affidati all\'amministratore principale.', 'admin_template_reallydelete' =&gt; 'sei sicuro di voler cancellare il template \'%s\'?', 'domains_reallydelete' =&gt; 'sei sicuro di voler cancellare il dominio %s?', 'email_reallydelete' =&gt; 'sei sicuro di voler cancellare l\'indirizzo email %s?', 'email_reallydelete_account' =&gt; 'sei sicuro di voler cancellare l\'account email di %s?', 'email_reallydelete_forwarder' =&gt; 'sei sicuro di voler cancellare il reindirizzamento %s?', 'extras_reallydelete' =&gt; 'sei sicuro di voler cancellare la protezione per la cartella %s?', 'extras_reallydelete_pathoptions' =&gt; 'sei sicuro di voler cancellare le opzioni cartella per %s?', 'ftp_reallydelete' =&gt; 'sei sicuro di voler cancellare l\'account ftp %s?', 'mysql_reallydelete' =&gt; 'sei sicuro di voler cancellare il database %s? quest\'azione non potr essere annullata!', 'admin_configs_reallyrebuild' =&gt; 'sei sicuro di voler rigenerare file di configurazione per apache e bind?', 'admin_customer_alsoremovefiles' =&gt; 'cancellare anche file dell\'utente?', 'admin_ip_reallydelete' =&gt; 'vuoi veramente eliminare l\'indirizzo ip %s?', 'admin_domain_reallydocrootoutofcustomerroot' =&gt; 'sei sicuro di volere la cartella base dei dati web di questo dominio al di fuori della cartella base del cliente?', 'admin_counters_reallyupdate' =&gt; 'sei sicuro di voler ricacolare il consumo delle risorse?', 'admin_cleartextmailpws_reallywipe' =&gt; 'sei sicuro di voler cancellare tutte le password chiaro degli account email dalla tabella mail_users? attenzione non si pu tornare indietro!', 'logger_reallytruncate' =&gt; 'sei sicuro di voler troncare la tabella "%s"?', 'admin_quotas_reallywipe' =&gt; 'sei sicuro di voler cancellare tutti limiti dalla tabella mail_users? questa operazione non pu essere annullata!', 'admin_quotas_reallyenforce' =&gt; 'sei sicuro di voler impostare il limite predefinito tutti gli utenti? questa operazione non pu essere annullata!', 'phpsetting_reallydelete' =&gt; 'do really want delete settings? domains use settings currently changed default config.', 'customer_reallyunlock' =&gt; 'sei sicuro di voler sbloccare il cliente %s?', 'admin_customer_alsoremovemail' =&gt; 'eliminare completamente dati della posta elettronica dal filesystem??', 'admin_customer_alsoremoveftphomedir' =&gt; 'rimuovere anche la cartella homedir dell\'utente ftp?', 'admin_integritycheck_reallyfix' =&gt; 'vuoi veramente provare risolvere problemi di integrit del database automaticamente?', ], 'redirect_desc' =&gt; [ 'rc_default' =&gt; 'predefinito', 'rc_movedperm' =&gt; 'spostato modo permanente', 'rc_found' =&gt; 'trovato', 'rc_seeother' =&gt; 'vedi gli altri', 'rc_tempred' =&gt; 'reindirizzamento temporaneo', ], 'serversettings' =&gt; [ 'session_timeout' =&gt; [ 'title' =&gt; 'timeout della sessione', 'description' =&gt; 'quanto tempo un utente deve rimanere inattivo prima che la sessione diventi invalida (secondi)?', ], 'accountprefix' =&gt; [ 'title' =&gt; 'prefisso cliente', 'description' =&gt; 'che prefisso dovrebbero avere gli account dei clienti?', ], 'mysqlprefix' =&gt; [ 'title' =&gt; 'prefisso sql', 'description' =&gt; 'che prefisso dovrebbero avere database sql?', ], 'ftpprefix' =&gt; [ 'title' =&gt; 'prefisso ftp', 'description' =&gt; 'che prefisso vuoi che per gli account ftp?&lt;br/&gt;&lt;b&gt;se si modifica questo devi anche modificare il limite (quota) della query sql nel file di configurazione del server ftp nel caso cui venga usata!&lt;/b&gt; ', ], 'documentroot_prefix' =&gt; [ 'title' =&gt; 'cartella dati web', 'description' =&gt; 'dove devono essere immagazzinati tutti dati web?', ], 'logfiles_directory' =&gt; [ 'title' =&gt; 'cartella logfiles', 'description' =&gt; 'dove devono essere immagazzinati tutti log?', ], 'ipaddress' =&gt; [ 'title' =&gt; 'indirizzo ip', 'description' =&gt; 'qual\' l\'indirizzo ip di questo server?', ], 'hostname' =&gt; [ 'title' =&gt; 'hostname', 'description' =&gt; 'qual\' l\'hostname di questo server?', ], 'apachereload_command' =&gt; [ 'title' =&gt; 'comando riavvio apache', 'description' =&gt; 'qual\' il comando per riavviare apache?', ], 'bindconf_directory' =&gt; [ 'title' =&gt; 'cartella configurazione bind', 'description' =&gt; 'dove sono file di configurazione per bind?', ], 'bindreload_command' =&gt; [ 'title' =&gt; 'comando riavvio bind', 'description' =&gt; 'qual\' il comando per riavviare bind?', ], 'vmail_uid' =&gt; [ 'title' =&gt; 'uid email', 'description' =&gt; 'che userid dovrebbe avere l\'utente che gestisce le email?', ], 'vmail_gid' =&gt; [ 'title' =&gt; 'gid email', 'description' =&gt; 'che groupid dovrebbe avere l\'utente che gestisce le email?', ], 'vmail_homedir' =&gt; [ 'title' =&gt; 'cartella email', 'description' =&gt; 'dove devono essere immagazzinate tutte le email?', ], 'adminmail' =&gt; [ 'title' =&gt; 'mittente', 'description' =&gt; 'qual\' l\'indirizzo del mittente delle email provenienti dal pannello?', ], 'phpmyadmin_url' =&gt; [ 'title' =&gt; 'url phpmyadmin', 'description' =&gt; 'qual\' l\'url di phpmyadmin? (deve cominciare per http://)', ], 'webmail_url' =&gt; [ 'title' =&gt; 'url webmail', 'description' =&gt; 'qual\' l\'url della webmail? (deve cominciare per http://)', ], 'webftp_url' =&gt; [ 'title' =&gt; 'url webftp', 'description' =&gt; 'qual\' l\'url del webftp? (deve cominciare per http://)', ], 'language' =&gt; [ 'description' =&gt; 'qual\' la lingua standard del tuo server?', ], 'maxloginattempts' =&gt; [ 'title' =&gt; 'numero massimo tentativi login', 'description' =&gt; 'numero massimo di tentativi di login prima che l\'account sia disattivato.', ], 'deactivatetime' =&gt; [ 'title' =&gt; 'durata disattivamento', 'description' =&gt; 'tempo (sec.) di disattivazione dell\'account dopo troppi tentativi di login.', ], 'pathedit' =&gt; [ 'title' =&gt; 'modalit di scelta percorsi/cartelle', 'description' =&gt; 'un percorso/cartella andr scelto attraverso un menu tendina inserendolo mano?', ], 'nameservers' =&gt; [ 'title' =&gt; 'nameservers', 'description' =&gt; 'lista degli hostname (separati dalla virgola) di tutti nameserver. il primo della lista sar il impostato come primario.', ], 'mxservers' =&gt; [ 'title' =&gt; 'mx servers', 'description' =&gt; 'lista dei server mx (separati dalla virgola) numero spazio hostname (es. \'10 mx.example.com\').', ], 'paging' =&gt; [ 'title' =&gt; 'elementi da visualizzare per pagina', 'description' =&gt; 'quanti elementi dovrebbero essere visualizzati su una pagina? (0 = disattiva impaginazione)', ], 'defaultip' =&gt; [ 'title' =&gt; 'ip/porta default', 'description' =&gt; 'qual\' la combinazione ip/porta default?', ], 'phpappendopenbasedir' =&gt; [ 'title' =&gt; 'percoso da aggiungere openbasedir', 'description' =&gt; 'questi percorsi (separati da colonne) verranno aggiunti allo statement openbasedir ognuno vhost-container.', ], 'natsorting' =&gt; [ 'title' =&gt; 'usa l\'ordinamento naturale vista elenco', 'description' =&gt; 'disponi la lista come web1 -&gt; web2 -&gt; web11 al posto di web1 -&gt; web11 -&gt; web2.', ], 'deactivateddocroot' =&gt; [ 'title' =&gt; 'docroot per gli utenti disattivati', 'description' =&gt; 'quando un utente viene disattivato questo percorso viene usato come suo docroot. lascia vuoto per non creare un vhost tutti.', ], 'mailpwcleartext' =&gt; [ 'title' =&gt; 'salva le password chiaro degli account email nel database', 'description' =&gt; 'se impostato si, tutte le password saranno salvate chiaro (saranno leggibili chiunque abbia accesso al database) nella tabella mail_users. attiva questa opzione solo se necessaria!', 'removelink' =&gt; 'clicca qui per cancellare tutte le password chiaro dalla tabella.', ], 'ftpdomain' =&gt; [ 'title' =&gt; 'account ftp @domain', 'description' =&gt; 'i clienti possono creare account ftp utente@dominiocliente?', ], 'mod_fcgid' =&gt; [ 'title' =&gt; 'includi php via mod_fcgid/suexec', 'description' =&gt; 'usa mod_fcgid/suexec/libnss_mysql per avviare php con il corrispondente account-utente.&lt;br/&gt;&lt;b&gt;questo richiede una speciale configurazione del webserver. tutte le opzioni seguenti sono validi solo se il modulo abilitato.&lt;/b&gt;', 'configdir' =&gt; [ 'title' =&gt; 'cartella della configurazione', 'description' =&gt; 'dove vuoi che venga salvata la configurazione di fcgid? se non ti sei compilato suexec da solo, di solito questo percorso /var/www', ], 'tmpdir' =&gt; [ 'title' =&gt; 'cartella temp', 'description' =&gt; 'dove va salvata la cartella temp', ], 'starter' =&gt; [ 'title' =&gt; 'processi per dominio', 'description' =&gt; 'quanti processi dovrebbero essere avviati/permessi per ogni dominio? il valore 0 raccomandato poich php si autogestisce processi modo molto efficiente.', ], 'wrapper' =&gt; [ 'title' =&gt; 'wrapper vhosts', 'description' =&gt; 'come dovrebbe essere il wrapper incluso nel vhosts', ], 'peardir' =&gt; [ 'title' =&gt; 'cartella globale di pear', 'description' =&gt; 'quali sono le cartelle globali di pear che dovrebbero essere sostituite ogni configurazione php.ini? pi cartelle devono essere separate da : (due punti).', ], 'maxrequests' =&gt; [ 'title' =&gt; 'richieste massime per dominio', 'description' =&gt; 'quante richieste dovrebbero essere permesse per dominio?', ], 'defaultini' =&gt; 'configurazione di default di php per nuovi domini', 'defaultini_ownvhost' =&gt; 'configurazione di default di php per froxlor-vhost', 'idle_timeout' =&gt; [ 'title' =&gt; 'timeout inattivit', 'description' =&gt; 'impostazione timeout per il mod fastcgi.', ], ], 'sendalternativemail' =&gt; [ 'title' =&gt; 'usa un\'indirizzo email alternativo', 'description' =&gt; 'invia la password dell\'email un\'indirizzo diverso da quello creato', ], 'apacheconf_vhost' =&gt; [ 'title' =&gt; 'file/cartella della configurazione vhost del webserver', 'description' =&gt; 'dove vuoi che venga salvata la configurazione vhost? qui puoi scegliere un file (tutti vhosts un file) una cartella (ogni vhost avr il suo file).', ], 'apacheconf_diroptions' =&gt; [ 'title' =&gt; 'webserver diroptions configuration file/dirname', 'description' =&gt; 'dove vuoi che venga salvata la configurazione dir-options? qui puoi scegliere un file (tutti vhosts un file) una cartella (ogni vhost avr il suo file).', ], 'apacheconf_htpasswddir' =&gt; [ 'title' =&gt; 'cartella htpasswd del webserver', 'description' =&gt; 'dove vuoi che vengano salvati file htpasswd per la protezione delle cartelle?', ], 'mysql_access_host' =&gt; [ 'description' =&gt; 'lista degli host (separati da una virgola) cui gli utenti possono collegarsi al server mysql.', 'title' =&gt; 'hosts accesso mysql', ], 'webalizer_quiet' =&gt; [ 'description' =&gt; 'verbosit del programma webalizer', 'title' =&gt; 'webalizer output', ], 'logger' =&gt; [ 'enable' =&gt; 'abilita/disabilita log', 'severity' =&gt; 'livello log', 'types' =&gt; [ 'title' =&gt; 'tipo di log', 'description' =&gt; 'specificare tipo di log. per selezionare pi tipi, tenere premuto ctrl durante la selezione.&lt;br /&gt;tipi di log disponibili: syslog, file, mysql', ], 'logfile' =&gt; 'percorso completo e nome del file del log', 'logcron' =&gt; 'log cronjobs (one run)', ], 'ssl' =&gt; [ 'openssl_cnf' =&gt; 'defaults per la creazione del file cert', 'use_ssl' =&gt; [ 'title' =&gt; 'abilita utilizzo ssl', 'description' =&gt; 'spunta questo se vuoi usare ssl per il tuo server web', ], 'ssl_cert_file' =&gt; [ 'title' =&gt; 'percorso al certificato ssl', 'description' =&gt; 'specifica il percorso includendo il nome del file .crt .pem (certificato principale)', ], 'ssl_key_file' =&gt; [ 'title' =&gt; 'percorso al file di chiave ssl', 'description' =&gt; 'specifica il percorso includendo il nome del file per la chiave privata (abitualmente.key)', ], 'ssl_ca_file' =&gt; [ 'title' =&gt; 'percorso al certificato della ca (autorit certificatrice) ssl (opzionale)', 'description' =&gt; 'autenticazione client, da settare soltanto se desiderato.', ], 'ssl_cipher_list' =&gt; [ 'title' =&gt; 'configura le cifrature ssl permesse', 'description' =&gt; 'questa una lista di cifrature che vuoi (o non vuoi) usare nelle communicazioni ssl. per una lista delle cifrature e come includerle od escluderle, vedi le sezioni "cipher list format" e "cipher strings" sulla &lt;a href="https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html"&gt;man-page per le cifrature&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;il valore predefinito :&lt;/b&gt;&lt;pre&gt;ecdhe-rsa-aes128-sha256:aes128-gcm-sha256:rc4:high:!md5:!anull:!edh&lt;/pre&gt;', ], ], 'default_vhostconf' =&gt; [ 'title' =&gt; 'impostazioni default vhost', 'description' =&gt; 'il contenuto di questo campo sar incluso direttamente nel contenitore di dominio vhost. attenzione: il codice non sar controllato per eventuali errori. se contiene errori, il webserver non riavviarsi correttamente!', ], 'decimal_places' =&gt; 'numero di cifre decimali del traffico/spazio web uscita', 'webalizer_enabled' =&gt; 'abilita le statistiche webalizer', 'awstats_enabled' =&gt; 'abilita le statistiche awstats', 'selfdns' =&gt; [ 'title' =&gt; 'impostazioni dominio dns del cliente', ], 'selfdnscustomer' =&gt; [ 'title' =&gt; 'consenti ai clienti di modificare le impostazioni dns del dominio', ], 'unix_names' =&gt; [ 'title' =&gt; 'usa nomi utente unix compatibile', 'description' =&gt; 'consente di utilizzare &lt;strong&gt;-&lt;/strong&gt; e &lt;strong&gt;_&lt;/strong&gt; nei nomi utente se &lt;strong&gt;no&lt;/strong&gt;', ], 'allow_password_reset' =&gt; [ 'title' =&gt; 'consenti ai clienti di reimpostare la password', 'description' =&gt; 'i clienti possono reimpostare la propria password e una nuova password verr inviata al loro indirizzo e-mail', ], 'allow_password_reset_admin' =&gt; [ 'title' =&gt; 'consenti di reimpostare la password agli ammministratori', 'description' =&gt; 'amministratori/rivenditori possono reimpostare la propria password e una nuova password verr inviata al loro indirizzo e-mail', ], 'mail_quota' =&gt; [ 'title' =&gt; 'limite casella email', 'description' =&gt; 'limite predefinito per una nuova casella email creata (megabyte).', ], 'mail_quota_enabled' =&gt; [ 'title' =&gt; 'usa limiti per le caselle email dei clienti', 'description' =&gt; 'attiva per utilizzare limiti nelle caselle email. predefinito &lt;b&gt;no&lt;/b&gt; poich questo richiede una configurazione speciale.', 'removelink' =&gt; 'clicca qui per togliere tutti limiti dalle caselle email.', 'enforcelink' =&gt; 'clicca qui per applicare il limite predefinito tutte le caselle email degli utenti.', ], 'index_file_extension' =&gt; [ 'description' =&gt; 'quale estensione di file deve essere usata per il file index nelle cartelle del cliente appena creato? questa estensione di file sar utilizzata se lei uno dei vostri amministratori ha creato il proprio file modello di index.', 'title' =&gt; 'estensione file per il file index delle cartelle dei clienti appena creati', ], 'session_allow_multiple_login' =&gt; [ 'title' =&gt; 'permettere login multipli', 'description' =&gt; 'se attivato un utente pu accedere pi volte.', ], 'panel_allow_domain_change_admin' =&gt; [ 'title' =&gt; 'permettere di spostare domini tra gli amministratori', 'description' =&gt; 'se attivato si pu cambiare l\'amministratore di un dominio dalle impostazioni del dominio&lt;br /&gt;&lt;b&gt;attenzione:&lt;/b&gt; se un cliente non viene assegnato allo stesso amministratore e dominio, l\'amministratore pu vedere tutti gli altri domini di questo cliente!', ], 'panel_allow_domain_change_customer' =&gt; [ 'title' =&gt; 'permetti di spostare domini tra clienti', 'description' =&gt; 'se attivato si pu cambiare il cliente di un dominio dalle impostazioni del dominio.&lt;br /&gt;&lt;b&gt;attenzione:&lt;/b&gt; froxlor non cambier alcun percorso. ci potrebbe rendere inutilizzabile un dominio!', ], 'cron' =&gt; [ 'debug' =&gt; [ 'title' =&gt; 'debug cronscript', 'description' =&gt; 'attiva per mantenere il file lock dopo l\'avvio di cron, solo per debug&lt;br /&gt;&lt;b&gt;attenzione:&lt;/b&gt;mantenendo il file di lock al successivo avvio cron potrebbe non funzionare correttamente', ], ], 'specialsettingsforsubdomains' =&gt; [ 'description' =&gt; 'se si queste impostazioni personalizzate dei vhost saranno aggiunte tutti sottodomini; se le impostazioni speciali dei sottodomini verranno rimosse.', ], 'panel_password_min_length' =&gt; [ 'title' =&gt; 'lunghezza minima della password', 'description' =&gt; 'qui possibile impostare una lunghezza minima per le password.\'0\' significa: nessuna lunghezza minima richiesta.', ], 'system_store_index_file_subs' =&gt; [ 'title' =&gt; 'salva il file index predefinito anche nelle nuove sottocartelle', 'description' =&gt; 'se abilitato, il file index predefinito viene memorizzato per ogni cartella sottodominio appena creata (non se la cartella esiste gi!)', ], 'adminmail_return' =&gt; [ 'title' =&gt; 'indirizzo di risposta', 'description' =&gt; 'definire un indirizzo email come \'indirizzo di risposta\' per le email inviate dal pannello', ], 'adminmail_defname' =&gt; 'nome del mittente del pannello nell\'email', 'stdsubdomainhost' =&gt; [ 'title' =&gt; 'sottodominio standard cliente', 'description' =&gt; 'quale hostname dovrebbe essere usato per creare sottodomini standard per clienti. se vuoto, viene utilizzato l\'hostname del sistema.', ], 'awstats_path' =&gt; 'percorso awstats \'awstats_buildstaticpages.pl\'', 'awstats_conf' =&gt; 'cartella della configurazione di awstats', 'defaultttl' =&gt; 'dominio ttl per impegnare secondi (predefinito \'604800\' = 1 settimana)', 'defaultwebsrverrhandler_enabled' =&gt; 'abilita errordocuments automatico per tutti clienti', 'defaultwebsrverrhandler_err401' =&gt; [ 'title' =&gt; 'file/url per l\'errore 401', 'description' =&gt; '&lt;div class="text-danger"&gt;non supportato in: lighttpd&lt;/div&gt;', ], 'defaultwebsrverrhandler_err403' =&gt; [ 'title' =&gt; 'file/url per l\'errore 403', 'description' =&gt; '&lt;div class="text-danger"&gt;non supportato in: lighttpd&lt;/div&gt;', ], 'defaultwebsrverrhandler_err404' =&gt; 'file/url per l\'errore 404', 'defaultwebsrverrhandler_err500' =&gt; [ 'title' =&gt; 'file/url per l\'errore 500', 'description' =&gt; '&lt;div class="text-danger"&gt;non supportato in: lighttpd&lt;/div&gt;', ], 'ftpserver' =&gt; [ 'desc' =&gt; 'se pureftpd selezionato file .ftpquota per limiti dell\'utente sono creati e aggiornati giornalmente', ], 'customredirect_enabled' =&gt; [ 'title' =&gt; 'permetti ai clienti le redirezioni', 'description' =&gt; 'consente ai clienti di scegliere il codice di stato http per le redirezioni che verranno utilizzate', ], 'customredirect_default' =&gt; [ 'title' =&gt; 'redirezione predefinita', 'description' =&gt; 'imposta il codice della redirezione predefinito che dovrebbe essere usato se il cliente non lo imposta', ], 'mail_also_with_mxservers' =&gt; 'crea mail-, imap-, pop3- smtp-"a record" anche con mx-servers impostato', 'froxlordirectlyviahostname' =&gt; 'accedi direttamente froxlor via hostname', 'panel_password_regex' =&gt; [ 'title' =&gt; 'espressione per le password', 'description' =&gt; 'qui possibile impostare una espressione regolare per la complessit delle password.&lt;br /&gt;vuoto = nessun requisito specificato', ], 'perl_path' =&gt; [ 'title' =&gt; 'percorso perl', 'description' =&gt; 'rilevante solo se si utilizza lighttpd. predefinito /usr/bin/perl', ], 'mod_fcgid_ownvhost' =&gt; [ 'title' =&gt; 'abilita fcgid per vhost froxlor', 'description' =&gt; 'se attivato, froxlor verr eseguito con un utente locale&lt;br /&gt;&lt;strong&gt;attenzione:&lt;/strong&gt;questo richiede una configurazione manuale, vedi &lt;a target="_blank" href="https://docs.froxlor.org/latest/admin-guide/configuration/fcgid/"&gt;fcgid - handbook&lt;/a&gt;', ], 'perl' =&gt; [ 'suexecworkaround' =&gt; [ 'title' =&gt; 'abilita suexec workaround (solo con apache)', 'description' =&gt; 'abilita solo se la docroots del cliente non sono all\'interno del percorso suexec di apache&lt;br /&gt;se attivato, froxlor generer un link simbolico dalla cartella perl abilitata dei clienti + /cgi-bin/ al percorso specificato.&lt;br /&gt;nota: perl funziona solo nelle sottocartelle /cgi-bin/ e non nella cartella stessa (come farebbe normalmente senza questa correzione!)', ], 'suexeccgipath' =&gt; [ 'title' =&gt; 'percorso dei link simbolici della cartella abilitata perl del cliente', 'description' =&gt; 'imposta questo solo se la soluzione suexec abilitata.&lt;br /&gt;attenzione: assicurati che questo percorso sia all\'interno del percorso suexec oppure questa soluzione inutile', ], ], 'awstats_awstatspath' =&gt; 'percorso awstats \'awstats.pl\'', 'awstats_icons' =&gt; [ 'title' =&gt; 'percorso della cartella delle icone di awstats', 'description' =&gt; 'es. /usr/share/awstats/htdocs/icon/', ], 'login_domain_login' =&gt; 'permetti il login con domini', 'nginx_php_backend' =&gt; [ 'title' =&gt; 'nginx php backend', 'description' =&gt; 'questo dove ascolto il processo php per le richieste da nginx, pu essere un socket unix combinazione ip:porta', ], 'phpreload_command' =&gt; [ 'title' =&gt; 'comando riavvio php', 'description' =&gt; 'questo viene utilizzato per ricaricare il backend php se uso&lt;br /&gt;predefinito: vuoto', ], 'phpfpm_settings' =&gt; [ 'configdir' =&gt; 'cartella di configurazione php-fpm', 'reload' =&gt; 'comando di riavvio php-fpm', 'pm' =&gt; 'gestore processi (pm)', 'max_children' =&gt; [ 'title' =&gt; 'il numero di processi figli', 'description' =&gt; 'il numero di processi figli che vengono creati quando il pm impostato \'static\' e il numero massimo di processi figli che vengono creati quando il pm impostato \'dynamic\'&lt;br /&gt;equivalente php_fcgi_children', ], 'start_servers' =&gt; [ 'title' =&gt; 'il numero di processi figli creati all\'avvio', 'description' =&gt; 'nota: usato solo quando il pm impostato \'dynamic\'', ], 'min_spare_servers' =&gt; [ 'title' =&gt; 'il numero minimo di processi inattivi nel server', 'description' =&gt; 'nota: usato solo quando il pm impostato \'dynamic\'&lt;br /&gt;nota: obbligatorio quando il pm impostato \'dynamic\'', ], 'max_spare_servers' =&gt; [ 'title' =&gt; 'il numero massimo di processi inattivi nel server', 'description' =&gt; 'nota: usato solo quando il pm impostato \'dynamic\'&lt;br /&gt;nota: obbligatorio quando il pm impostato \'dynamic\'', ], 'max_requests' =&gt; [ 'title' =&gt; 'richieste per figli prima di rigenerare', 'description' =&gt; 'per le richieste senza fine specificare \'0\'. equivalente php_fcgi_max_requests.', ], 'aliasconfigdir' =&gt; 'configurazione cartella alias per php-fpm', 'idle_timeout' =&gt; [ 'title' =&gt; 'timeout inattivit', 'description' =&gt; 'impostazione timeout per php5 fpm fastcgi.', ], 'ipcdir' =&gt; [ 'title' =&gt; 'cartella fastcgi ipc', 'description' =&gt; 'la cartella nella quale verrano salvati socket php-fpm dal server web.&lt;br /&gt;questa cartella deve essere leggibile dal server web', ], ], 'report' =&gt; [ 'report' =&gt; 'abilita l\'invio dei report di utilizzo web e del traffico', 'webmax' =&gt; 'percentuale di avviso per lo spazio web', 'trafficmax' =&gt; 'percentuale di avviso per il traffico', ], 'dropdown' =&gt; 'dropdown', 'manual' =&gt; 'manuale', 'default_theme' =&gt; 'tema predefinito', 'validate_domain' =&gt; 'convalida dei domini', 'bindenable' =&gt; [ 'title' =&gt; 'abilita nameserver', 'description' =&gt; 'qui il nameserver pu essere abilitato e disabilitato globalmente.', ], 'default_vhostconf_domain' =&gt; [ 'description' =&gt; 'il contenuto di questo campo verr incluso direttamente nella configurazione del contenitore del dominio vhost. attenzione: non verrano verificati eventuali errori del codice contenuto. se conterr degli errori, vi il rischio che il server web non si avvii pi!', ], 'phpfpm' =&gt; [ 'title' =&gt; 'abilita php-fpm', 'description' =&gt; '&lt;b&gt;questa impostazione richiede una configurazione speciale del server web. vedi il &lt;a target="_blank" href="https://docs.froxlor.org/latest/admin-guide/configuration/php-fpm/"&gt;manuale php-fpm&lt;/a&gt;&lt;/b&gt;', ], 'diskquota_enabled' =&gt; 'quota attivita?', 'diskquota_repquota_path' =&gt; [ 'description' =&gt; 'percorso repquota', ], 'diskquota_quotatool_path' =&gt; [ 'description' =&gt; 'percorso al quotatool', ], 'diskquota_customer_partition' =&gt; [ 'description' =&gt; 'partizione, sulla quale sono salvati dati dei clienti', ], 'vmail_maildirname' =&gt; [ 'title' =&gt; 'nome maildir', 'description' =&gt; 'cartella maildir nell account utente. normalmente \'maildir\', alcune implementazioni \'.maildir\', e direttamente nella cartella utente se lasciato vuoto.', ], 'catchall_enabled' =&gt; [ 'title' =&gt; 'usa catchall', 'description' =&gt; 'vuoi offrire ai tuoi clienti la funzionalit di catchall?', ], 'apache_24' =&gt; [ 'title' =&gt; 'usa impostazioni per apache 2.4', 'description' =&gt; '&lt;strong class="text-danger"&gt;attenzione:&lt;/strong&gt; spunta soltanto se hai installato la versione 2.4 superiore di apache&lt;br /&gt;altrimenti il tuo server web non si avvier', ], 'nginx_fastcgiparams' =&gt; [ 'title' =&gt; 'percorso al file fastcgi_params', 'description' =&gt; 'specifica il percorso al file fastcgi_params di nginx includendo il nome del file', ], 'documentroot_use_default_value' =&gt; [ 'title' =&gt; 'usa il nome del dominio come valore predefinito per il percorso documentroot (radice dei documenti)', 'description' =&gt; 'se abilitato ed il percorso radice documentroot vuoto, il valore predefinito sar il nome del (sotto)dominio.&lt;br /&gt;&lt;br /&gt;esempio: &lt;br /&gt;/var/customers/nome_cliente/example.com/&lt;br /&gt;/var/customers/nome_cliente/sottodominio.example.com/', ], 'panel_phpconfigs_hidestdsubdomain' =&gt; [ 'title' =&gt; 'nascondi sottodominii predefiniti nel riepilogo di configurazione php', 'description' =&gt; 'se attivato sottodomini predefiniti dei clienti non saranno visualizzati nel riepilogo della configurazione php&lt;br /&gt;&lt;br /&gt;nota: questo solo visibile se avete abilitato fcgid php-fpm', ], 'passwordcryptfunc' =&gt; [ 'title' =&gt; 'scegli quale metodo crittografico deve essere usato per le password', ], 'systemdefault' =&gt; 'predefinito di sistema', 'panel_allow_theme_change_admin' =&gt; 'permetti agli amministratori di cambiare il tema', 'panel_allow_theme_change_customer' =&gt; 'permetti ai clienti di cambiare il tema', 'axfrservers' =&gt; [ 'title' =&gt; 'server axfr', 'description' =&gt; 'un elenco separato da virgole di indirizzi ip autorizzati trasferire zone dns (axfr).', ], 'customerssl_directory' =&gt; [ 'title' =&gt; 'cartella dei certificati ssl clienti del webserver', 'description' =&gt; 'dove devono esssere creati certificati ssl cliente?&lt;br /&gt;&lt;br /&gt;&lt;div class="text-danger"&gt;nota: il contenuto di questa cartella viene cancellato regolarmente, onde evitare il salvataggio manuale di dati essa.&lt;/div&gt;', ], 'allow_error_report_admin' =&gt; [ 'title' =&gt; 'permetti agli amministratori/rivenditori di inviare errori di database froxlor', 'description' =&gt; 'attenzione: non inviarci mai dati personali (dei clienti)!', ], 'allow_error_report_customer' =&gt; [ 'title' =&gt; 'permetti ai clienti di inviare errori di database froxlor', 'description' =&gt; 'attenzione: non inviarci mai dati personali (dei clienti)!', ], 'mailtraffic_enabled' =&gt; [ 'title' =&gt; 'analizza traffico posta', 'description' =&gt; 'abilita l\\\'analisi dei log del server di posta per calcolare il traffico', ], 'mdaserver' =&gt; [ 'title' =&gt; 'tipo mda', 'description' =&gt; 'tipo del server di consegna di posta', ], 'mdalog' =&gt; [ 'title' =&gt; 'log mda', 'description' =&gt; 'file log del server di consegna di posta', ], 'mtaserver' =&gt; [ 'title' =&gt; 'tipo mta', 'description' =&gt; 'tipo agente di trasferimento di posta', ], 'mtalog' =&gt; [ 'title' =&gt; 'log mta', 'description' =&gt; 'file log dell\\\'agente di trasferimento di posta', ], 'system_cronconfig' =&gt; [ 'title' =&gt; 'file di configurazione cron', 'description' =&gt; 'percorso al file di configurazione del servizio cron. questo file verr aggiornato regolarmente ed automaticamente da froxlor.&lt;br /&gt; nota: perfavore &lt;b&gt;sii sicuro&lt;/b&gt; di usare lo stesso nome di file come per il cronjob principale di froxlor (predefinito: /etc/cron.d/froxlor)!&lt;br&gt;&lt;br&gt;se usi &lt;b&gt;freebsd&lt;/b&gt;, qui specifica: &lt;i&gt;/etc/crontab&lt;/i&gt;!', ], 'system_crondreload' =&gt; [ 'title' =&gt; 'commando per riavviare il servizio cron', 'description' =&gt; 'specifica il commando da eseguire per riavviare il servizio cron del tuo sistema', ], 'system_croncmdline' =&gt; [ 'title' =&gt; 'commando di esecuzione cron (binario php)', 'description' =&gt; 'commando per eseguire nostri cronjob. modificalo soltanto se sai cosa stai facendo (predefinito: "/usr/bin/nice -n 5 /usr/bin/php -q")!', ], 'system_cron_allowautoupdate' =&gt; [ 'title' =&gt; 'permetti aggiornamenti automatici del database', 'description' =&gt; '&lt;div class="text-danger"&gt;&lt;b&gt;attenzione:&lt;/b&gt;&lt;/div&gt; questa impostazione permette al cronjob di bypassare la verifica di versione dei file e database di froxlors ed esegue gli aggiornamenti di database caso si verificasse un disallineamento di versione.&lt;br&gt;&lt;br&gt;&lt;div class="text-danger"&gt;l\'aggiornamento automatico imposter sempre valori predefiniti per nuove impostazioni modifiche. questo, non sempre potrebbe essere congruo ed adeguato per il vostro sistema. pensaci due volte prima di attivare questa opzione&lt;/div&gt;', ], 'dns_createhostnameentry' =&gt; 'crea la zone/config di bind per il nome host del sistema', 'panel_password_alpha_lower' =&gt; [ 'title' =&gt; 'caratteri minuscoli', 'description' =&gt; 'la password deve contenere almeno una lettera minuscola (a-z).', ], 'panel_password_alpha_upper' =&gt; [ 'title' =&gt; 'caratteri maiuscoli', 'description' =&gt; 'la password deve contenere almeno una lettere maiuscola (a-z).', ], 'panel_password_numeric' =&gt; [ 'title' =&gt; 'numeri', 'description' =&gt; 'la password deve contenere almeno un numero (0-9).', ], 'panel_password_special_char_required' =&gt; [ 'title' =&gt; 'caratteri speciali', 'description' =&gt; 'la password deve contenere almeno uno dei caratteri speciali definiti nel campo sottostante.', ], 'panel_password_special_char' =&gt; [ 'title' =&gt; 'lista dei caratteri speciali', 'description' =&gt; 'uno di questi caratteri richiesto se attivata l\'opzione soprastante.', ], ], 'spf' =&gt; [ 'use_spf' =&gt; 'attiva spf per domini?', 'spf_entry' =&gt; 'impostazioni spf per tutti domini', ], 'success' =&gt; [ 'success' =&gt; 'informazioni', 'clickheretocontinue' =&gt; 'clicca qui per continuare', 'settingssaved' =&gt; 'le impostazioni sono state salvate con successo.', 'rebuildingconfigs' =&gt; 'inseriti con successo lavori per la ricostruzione del file di configurazione', 'domain_import_successfully' =&gt; 'importato %s dominii con successo.', ], 'tasks' =&gt; [ 'outstanding_tasks' =&gt; 'processi cron sospeso', 'rebuild_vhost' =&gt; 'ricostruzione della configurazione del webserver', 'create_home' =&gt; 'aggiunto il nuovo cliente %s', 'rebuild_dns' =&gt; 'ricostruzione della configurazione di bind', 'create_ftp' =&gt; 'creazione delle cartelle per nuovi utenti ftp', 'delete_customer_files' =&gt; 'eliminazione dei file del cliente %s', 'noneoutstanding' =&gt; 'attualmente non ci sono processi sospeso per froxlor', 'create_quota' =&gt; 'setta quota al filesystem', 'delete_email_data' =&gt; 'elimina dati di posta elettronica del cliente.', 'delete_ftp_data' =&gt; 'elimina dati account-ftp del cliente.', 'rebuild_cron' =&gt; 'ricostruisci il file cron.d', ], 'traffic' =&gt; [ 'month' =&gt; 'mese', 'day' =&gt; 'giorno', 'months' =&gt; [ 1 =&gt; 'gennaio', 2 =&gt; 'febbraio', 3 =&gt; 'marzo', 4 =&gt; 'aprile', 5 =&gt; 'maggio', 6 =&gt; 'giugno', 7 =&gt; 'luglio', 8 =&gt; 'agosto', 9 =&gt; 'settembre', 10 =&gt; 'ottobre', 11 =&gt; 'novembre', 12 =&gt; 'dicembre', 'jan' =&gt; 'gen', 'feb' =&gt; 'feb', 'mar' =&gt; 'mar', 'apr' =&gt; 'apr', 'may' =&gt; 'mag', 'jun' =&gt; 'giu', 'jul' =&gt; 'lug', 'aug' =&gt; 'ago', 'sep' =&gt; 'set', 'oct' =&gt; 'ott', 'nov' =&gt; 'nov', 'dec' =&gt; 'dic', 'total' =&gt; 'totale', ], 'mb' =&gt; 'traffico (mb)', 'distribution' =&gt; '&lt;font color="#019522"&gt;ftp&lt;/font&gt; | &lt;font color="#0000ff"&gt;http&lt;/font&gt; | &lt;font color="#800000"&gt;mail&lt;/font&gt;', 'sumhttp' =&gt; 'sommatoria traffico ingresso http', 'sumftp' =&gt; 'sommatoria traffico ingresso ftp', 'summail' =&gt; 'sommatoria traffico ingresso mail', 'customer' =&gt; 'cliente', 'domain' =&gt; 'domini', 'trafficoverview' =&gt; 'riepilogo del traffico di', 'details' =&gt; 'dettagli', 'http' =&gt; 'http (mib)', 'ftp' =&gt; 'ftp (mib)', 'mail' =&gt; 'mail (mib)', ], 'translator' =&gt; 'luca longinotti, luca piona, emilien, christian munari', 'update' =&gt; [ 'updateinprogress_onlyadmincanlogin' =&gt; 'una nuova versione di froxlor stata installata non ancora impostata.&lt;br /&gt;solo l\'amministratore pu accedere e completare l\'aggiornamento.', 'update' =&gt; 'aggiorna froxlor', 'proceed' =&gt; 'procedi', 'update_information' =&gt; [ 'part_a' =&gt; 'i file di froxlor sono stati aggiornati alla versione &lt;strong&gt;%s&lt;/strong&gt;. la versione installata &lt;strong&gt;%s&lt;/strong&gt;.', 'part_b' =&gt; '&lt;br /&gt;&lt;br /&gt;i clienti non potranno accedere fino quando l\'aggiornamento non sar completato.&lt;br /&gt;&lt;strong&gt;procedere?&lt;/strong&gt;', ], 'noupdatesavail' =&gt; '&lt;strong&gt; gi presente l\'ultima versione di froxlor.&lt;/strong&gt;', ], 'usersettings' =&gt; [ 'custom_notes' =&gt; [ 'title' =&gt; 'note personali', 'description' =&gt; 'sentiti libero di inserire qualsi nota vuoi necessiti qui. apparirano nel riepilogo dell\'amministratore/cliente perl \'utente corrispondente.', 'show' =&gt; 'mostra le tue note nel cruscotto dell\'utente', ], ], ];</file><file name="lng/cz.lng.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'languages' =&gt; [ 'cz' =&gt; 'etina', 'de' =&gt; 'nmina', 'en' =&gt; 'anglitina', 'fr' =&gt; 'francouztina', 'it' =&gt; 'italtina', 'nl' =&gt; 'holandtina', 'pt' =&gt; 'portugaltina', 'se' =&gt; 'vdtina', 'es' =&gt; 'panltina', 'ca' =&gt; 'katalntina', ], '2fa' =&gt; [ '2fa' =&gt; 'monosti 2fa', '2fa_enabled' =&gt; 'aktivovat dvoufzov oven (2fa)', '2fa_removed' =&gt; '2fa spn odebrno', '2fa_added' =&gt; '2fa aktivovno spn&lt;br&gt;&lt;a class="alert-link" href="%s?page=2fa"&gt;zobrazit 2fa podrobnosti&lt;/a&gt;', '2fa_add' =&gt; 'aktivovat 2fa', '2fa_delete' =&gt; 'deaktivovat 2fa', '2fa_verify' =&gt; 'ovit kd', '2fa_overview_desc' =&gt; 'zde mete aktivovat dvoufaktorov ovovn vaeho tu.&lt;br&gt;&lt;br&gt;mete bu pout autentifiktor-aplikaci (jednorzov heslo / totp) nebo vm nechat froxlor po kadm spnm pihlen pomoc jednorzovho hesla poslat e-mail na vai e-mailovou adresu.', '2fa_email_desc' =&gt; 'v et je nastaven pro pouit jednorzovch hesel e-mailem. chcete-li deaktivovat, kliknte na "deaktivovat 2fa"', '2fa_ga_desc' =&gt; 'v et je nastaven tak, aby pouval jednorzov hesla zaloen na ase prostednictvm autentizan aplikace. naskenujte ne uveden qr kd pomoc poadovan autentizan aplikace pro vygenerovn kd. chcete-li deaktivovat, kliknte na "deaktivovat 2fa"', '2fa_not_activated' =&gt; 'dvoufzov ovovn nen povoleno', '2fa_not_activated_for_user' =&gt; 'dvoufaktorov oven nen pro aktulnho uivatele povoleno', 'type_2fa' =&gt; 'stav 2fa', ], 'admin' =&gt; [ 'overview' =&gt; 'pehled', 'ressourcedetails' =&gt; 'vyuijte zdroje', 'systemdetails' =&gt; 'podrobnosti systmu', 'froxlordetails' =&gt; 'podrobnosti froxloru', 'installedversion' =&gt; 'nainstalovan verze', 'latestversion' =&gt; 'nejnovj verze', 'lookfornewversion' =&gt; [ 'clickhere' =&gt; 'hledat prostednictvm webov sluby', 'error' =&gt; 'pi ten dolo k chyb', ], 'resources' =&gt; 'zdroje', 'customer' =&gt; 'zkaznk', 'customers' =&gt; 'zkaznci', 'customers_list_desc' =&gt; 'spravovat sv zkaznky', 'customer_add' =&gt; 'vytvoit zkaznka', 'customer_edit' =&gt; 'upravit zkaznka', 'username_default_msg' =&gt; 'ponechte przdn pro automaticky generovanou hodnotu', 'password_default_msg' =&gt; 'automaticky vygenerovno, pokud je przdn', 'domains' =&gt; 'domny', 'domain_add' =&gt; 'vytvoit domnu', 'domain_edit' =&gt; 'upravit domnu', 'subdomainforemail' =&gt; 'subdomny jako e-mailov domny', 'admin' =&gt; 'admin', 'admins' =&gt; 'administrtoi', 'admin_add' =&gt; 'vytvoit administrtora', 'admin_edit' =&gt; 'upravit administrtora', 'customers_see_all' =&gt; 'mete pistupovat k dalm sprvcm/prodejcm?', 'change_serversettings' =&gt; 'me zmnit nastaven serveru?', 'server' =&gt; 'systm', 'serversettings' =&gt; 'nastaven', 'serversettings_desc' =&gt; 'spravujte svj systm froxlor', 'rebuildconf' =&gt; 'znovu vytvoit konfiguran soubory', 'stdsubdomain' =&gt; 'standardn subdomna', 'stdsubdomain_add' =&gt; 'vytvoit standardn subdomnu', 'phpenabled' =&gt; 'php povoleno', 'deactivated' =&gt; 'deaktivovno', 'deactivated_user' =&gt; 'deaktivovat uivatele', 'sendpassword' =&gt; 'poslat heslo', 'ownvhostsettings' =&gt; 'vlastn nastaven vhost-serveru', 'configfiles' =&gt; [ 'serverconfiguration' =&gt; 'konfigurace', 'overview' =&gt; 'pehled', 'wizard' =&gt; 'prvodce', 'distribution' =&gt; 'distribuce', 'service' =&gt; 'sluba', 'daemon' =&gt; 'daemon', 'http' =&gt; 'webov server (http)', 'dns' =&gt; 'nameserver (dns)', 'mail' =&gt; 'potovn server (imap/pop3)', 'smtp' =&gt; 'mailov server (smtp)', 'ftp' =&gt; 'ftp-server', 'etc' =&gt; 'ostatn (systm)', 'choosedistribution' =&gt; '-- vyberte distribuci --', 'chooseservice' =&gt; '-- vyberte slubu --', 'choosedaemon' =&gt; '-- zvolte daemon --', 'statistics' =&gt; 'statistiky', 'compactoverview' =&gt; 'kompaktn pehled', 'legend' =&gt; '&lt;h3&gt;chystte se nakonfigurovat slubu/daemon&lt;/h3&gt;', 'commands' =&gt; '&lt;span class="text-danger"&gt;pkazy:&lt;/span&gt; tyto pkazy maj bt sputny po dku jako uivatel rootu v shellu. je bezpen zkoprovat cel blok vloit ho konzole.', 'files' =&gt; '&lt;span class="text-danger"&gt;konfiguran soubory:&lt;/span&gt; pkazy ped textovmi poli mly otevt editor clovm souborem. sta jen zkoprovat vloit obsah editoru uloit soubor.&lt;br&gt;&lt;span class="text-danger"&gt;upozornn:&lt;/span&gt; mysql heslo nebylo z bezpenostnch dvod nahrazeno. prosm nahrate "froxlor_mysql_password" samostatn nebo pouijte formul javascript ne k nahrazen na webu. pokud jste zapomnli heslo k mysql, najdete ho v "lib/userdata.inc.php"', 'importexport' =&gt; 'importovat/exportovat', 'finishnote' =&gt; 'soubor parametru byl spn vygenerovn. nyn spuste nsledujc pkaz jako root:', 'description' =&gt; 'konfigurace systmovch slueb', 'minihowto' =&gt; 'na tto strnce mete zobrazit rzn konfiguran ablony pro kadou slubu, (optovn)konfigurovat specifick sluby v ppad poteby nebo exportovat aktuln vbr json souboru pro pouit skriptech cli nebo na jinm serveru.&lt;br&gt;&lt;br&gt;&lt;b&gt;poznmka&lt;/b&gt;, e zvraznn sluby neodrej aktuln nastaven, ale ukazuj poadavky/doporuen z vaich aktulnch hodnot nastaven.', 'skipconfig' =&gt; 'ne(re)konfigurovat', 'recommendednote' =&gt; 'doporuen/poadovan sluby zaloen na aktulnm nastaven systmu', 'selectrecommended' =&gt; 'vybrat doporuen', 'downloadselected' =&gt; 'exportovat vybran', ], 'templates' =&gt; [ 'templates' =&gt; 'ablony e-mail', 'template_add' =&gt; 'pidat ablonu', 'template_fileadd' =&gt; 'pidat ablonu souboru', 'template_edit' =&gt; 'upravit ablonu', 'action' =&gt; 'akce', 'email' =&gt; 'e-mailov souborov ablony', 'subject' =&gt; 'pedmt', 'mailbody' =&gt; 'text e-mailu', 'createcustomer' =&gt; 'uvtac e-mail pro nov zkaznky', 'pop_success' =&gt; 'uvtac e-mail pro nov e-mailov ty', 'template_replace_vars' =&gt; 'promnn, kter maj bt nahrazeny v ablon:', 'salutation' =&gt; 'nahrazeno sprvnm oslovenm (jmno nebo nzev spolenosti)', 'firstname' =&gt; 'nahrazeno kestnm jmnem zkaznka.', 'name' =&gt; 'nahrazeno jmnem zkaznka.', 'company' =&gt; 'nahrazuje nzev firmy zkaznka', 'username' =&gt; 'nahrad uivatelskm jmnem zkaznka.', 'password' =&gt; 'nahrad heslem zkaznka.', 'email' =&gt; 'nahrazeno adresou tu pop3/imap.', 'customer_no' =&gt; 'nahrad slo zkaznka', 'traffic' =&gt; 'nahrazeno provozem, kter byl piazen zkaznkovi.', 'trafficused' =&gt; 'nahrazeno provozem, kter byl zkaznkem vyerpn.', 'pop_success_alternative' =&gt; 'uvtac e-mail pro nov e-mailov ty odeslan na alternativn adresu', 'email_password' =&gt; 'nahrad heslem tu pop3/imap.', 'index_html' =&gt; 'indexov soubor pro nov vytvoen adrese zkaznk', 'unconfigured_html' =&gt; 'soubor indexu pro nenastaven/neznm domny', 'unconfigured_content_fallback' =&gt; 'tato domna vyaduje konfiguraci prostednictvm panelu pro sprvu serveru froxlor, protoe v souasn dob nen piazena dnmu zkaznkovi.', 'file_extension' =&gt; [ 'description' =&gt; 'ppona souboru pro index mus bt v rozmez 1 6 znak. rozen obsahovat pouze znaky jako a-z, a-z 0-9&lt;br&gt;&lt;br&gt;vchoz: html', 'title' =&gt; 'ppona souboru pro ablonu souboru', ], 'servername' =&gt; 'nahrazeno jmnem serveru.', 'customer' =&gt; 'nahrazeno pihlaovacm jmnem zkaznka. pouze pro "indexov soubor pro nov vytvoen adrese zkaznk"', 'admin' =&gt; 'nahrazeno pihlaovacm jmnem sprvce. pouze pro "indexov soubor pro nov vytvoen adrese zkaznk"', 'customer_email' =&gt; 'nahrazeno e-mailovou adresou zkaznka. pouze pro "indexov soubor pro nov vytvoen adrese zkaznk"', 'admin_email' =&gt; 'nahrazeno e-mailovou adresou sprvce. pouze pro "indexov soubor pro nov vytvoen adrese zkaznk"', 'filetemplates' =&gt; 'ablony soubor', 'filecontent' =&gt; 'obsah souboru', 'new_database_by_customer' =&gt; 'upozornn zkaznka na vytvoen databze', 'new_ftpaccount_by_customer' =&gt; 'upozornn zkaznka na vytvoen ftp uivatele', 'newdatabase' =&gt; 'notifikan-maily novch databzch', 'newftpuser' =&gt; 'notifikan-maily novch ftp uivatelch', 'cust_name' =&gt; 'jmno zkaznka', 'db_name' =&gt; 'jmno databze', 'db_pass' =&gt; 'heslo databze', 'db_desc' =&gt; 'popis databze', 'db_srv' =&gt; 'databzov server', 'pma_uri' =&gt; 'url na phpmyadmin (pokud byl poskytnut)', 'usr_name' =&gt; 'ftp uivatelsk jmno', 'usr_pass' =&gt; 'ftp heslo', 'usr_path' =&gt; 'domovsk adres ftp (relativn k adresi customer-docroot)', 'forgotpwd' =&gt; 'notifikan-maily resetu hesla', 'password_reset' =&gt; 'upozornn pro zkaznka na resetovn hesla', 'trafficmaxpercent' =&gt; 'upozornn pro zkaznky pi vyerpn danho maximlnho procenta provozu', 'max_percent' =&gt; 'nahrazeno limitem vyuit disku/limitu provozu pro odesln zprv v procentech.', 'usage_percent' =&gt; 'nahrazeno vyuitm disku / provozem, kter byl zkaznkem vyerpn v procentech.', 'diskmaxpercent' =&gt; 'oznamovac e-mail pro zkaznky, pokud je vyerpno maximum procent z disku', 'diskavailable' =&gt; 'nahrazeno vyuitm disku, kter byl piazen zkaznkovi.', 'diskused' =&gt; 'nahrazeno vyuitm disku, kter byl zkaznkem vyerpn.', 'link' =&gt; 'nahrazeno odkazem na obnoven hesla zkaznka.', 'server_hostname' =&gt; 'nahrad nzev systmovho hostitele (url froxlor)', 'server_ip' =&gt; 'nahrad vchoz ip adresu serveru', 'server_port' =&gt; 'nahrad vchoz port serveru', 'domainname' =&gt; 'nahrazuje standardn subdomnu zkaznka (me bt przdn, pokud nen vygenerovna dn)', ], 'webserver' =&gt; 'webov server', 'createzonefile' =&gt; 'vytvoit znu dns pro domnu', 'custombindzone' =&gt; 'vlastn / nespravovan soubor zny', 'bindzonewarning' =&gt; 'pro vchoz nastaven&lt;br /&gt;&lt;strong class="text-danger"&gt;pozor:&lt;/strong&gt; pokud pouvte zonefile, budete muset run spravovat vechny poadovan zznamy pro vechny podzny.', 'ipsandports' =&gt; [ 'ipsandports' =&gt; 'ip aresy porty', 'add' =&gt; 'pidat ip/port', 'edit' =&gt; 'upravit ip/port', 'ipandport' =&gt; 'ip/port', 'ip' =&gt; 'ip', 'ipnote' =&gt; '&lt;div id="ipnote" class="invalid-feedback"&gt;poznmka: akoli jsou soukrom ip adresy povoleny, nkter funkce jako dns se nemus chovat sprvn.&lt;br&gt;pouvejte pouze soukrom ip adresy, pokud jste si jisti.&lt;/div&gt;', 'port' =&gt; 'port', 'create_listen_statement' =&gt; 'vytvoit listen statement', 'create_namevirtualhost_statement' =&gt; 'vytvoit vpis virtualhost', 'create_vhostcontainer' =&gt; 'vytvoit vhost-container', 'create_vhostcontainer_servername_statement' =&gt; 'vytvoit vpis servername v kontejneru vhost-container', 'enable_ssl' =&gt; 'je tohle ssl port?', 'ssl_cert_file' =&gt; 'cesta k certifiktu ssl', 'webserverdefaultconfig' =&gt; 'vchoz nastaven webserveru', 'webserverdomainconfig' =&gt; 'konfigurace domny webserveru', 'webserverssldomainconfig' =&gt; 'konfigurace webserveru ssl', 'ssl_key_file' =&gt; 'cesta k souboru kle ssl', 'ssl_ca_file' =&gt; 'cesta k ssl ca certifiktu', 'default_vhostconf_domain' =&gt; 'vchoz nastaven vhost pro kad kontejner domny', 'ssl_cert_chainfile' =&gt; [ 'title' =&gt; 'cesta k souboru ssl certificatechainfile', 'description' =&gt; 'vtinou ca_bundle, nebo podobn, pravdpodobn chcete nastavit, pokud jste si koupili ssl certifikt.', ], 'docroot' =&gt; [ 'title' =&gt; 'vlastn docroot (przdn = ukazuje na froxlor)', 'description' =&gt; 'zde mete definovat vlastn koenov adres dokumentu (cl poadavku) pro tuto kombinaci ip/port.&lt;br /&gt;&lt;strong&gt;pozor:&lt;/strong&gt; dvejte pozor, co zde zadvte!', ], 'ssl_paste_description' =&gt; 'vlote svj pln obsah certifiktu textovho pole', 'ssl_cert_file_content' =&gt; 'obsah certifiktu ssl', 'ssl_key_file_content' =&gt; 'obsah souboru ssl (soukromho) kle', 'ssl_ca_file_content' =&gt; 'obsah souboru ssl ca (nepovinn)', 'ssl_ca_file_content_desc' =&gt; '&lt;br /&gt;&lt;br /&gt;ovovn klienta, nastavte pouze pokud vte, co je.', 'ssl_cert_chainfile_content' =&gt; 'obsah souboru certifikanho etzce (nepovinn)', 'ssl_cert_chainfile_content_desc' =&gt; '&lt;br /&gt;&lt;br /&gt;nejastji ca_bundle nebo podobn, pravdpodobn jej budete chtt nastavit, pokud jste si zakoupili ssl certifikt.', 'ssl_default_vhostconf_domain' =&gt; 'vchoz nastaven ssl vhost pro kad kontejner domny', ], 'memorylimitdisabled' =&gt; 'zakzno', 'valuemandatory' =&gt; 'tato hodnota je povinn', 'valuemandatorycompany' =&gt; 'mus bt vyplnno bu "jmno" "kestn jmno" nebo "nzev spolenosti"', 'serversoftware' =&gt; 'software serveru', 'phpversion' =&gt; 'verze php', 'mysqlserverversion' =&gt; 'verze mysql serveru', 'webserverinterface' =&gt; 'rozhran webserveru', 'accountsettings' =&gt; 'nastaven tu', 'panelsettings' =&gt; 'nastaven panelu', 'systemsettings' =&gt; 'systemov nastaven', 'webserversettings' =&gt; 'nastaven webserveru', 'mailserversettings' =&gt; 'nastaven webserveru', 'nameserversettings' =&gt; 'nastaven nameserveru', 'updatecounters' =&gt; 'pepotat vyuit zdroj', 'subcanemaildomain' =&gt; [ 'never' =&gt; 'nikdy', 'choosableno' =&gt; 'voliteln, vchoz ne', 'choosableyes' =&gt; 'voliteln, vchoz ano', 'always' =&gt; 'vdy', ], 'wipecleartextmailpwd' =&gt; 'vymazat prost text hesla', 'webalizersettings' =&gt; 'nastaven webalizru', 'webalizer' =&gt; [ 'normal' =&gt; 'normln', 'quiet' =&gt; 'tich', 'veryquiet' =&gt; 'dn vstup', ], 'domain_nocustomeraddingavailable' =&gt; 'v souasn dob nen mon pidat domnu. nejprve muste pidat alespo jednoho zkaznka.', 'loggersettings' =&gt; 'nastaven logovn', 'logger' =&gt; [ 'normal' =&gt; 'normln', 'paranoid' =&gt; 'paranoid', ], 'emaildomain' =&gt; 'e-mailov domna', 'email_only' =&gt; 'pouze e-mail?', 'wwwserveralias' =&gt; 'pidat "www." serveralias', 'subject' =&gt; 'pedmt', 'recipient' =&gt; 'pjemce', 'message' =&gt; 'napsat zprvu', 'text' =&gt; 'zprva', 'sslsettings' =&gt; 'nastaven ssl', 'specialsettings_replacements' =&gt; 'mete pout nsledujc promnn:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt; &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt; &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (pipad-li v vahu)&lt;br/&gt;', 'antispam_settings' =&gt; 'nastaven antispamu', 'caneditphpsettings' =&gt; 'me zmnit php nastaven domny?', 'allips' =&gt; 'vechny ip adresy', 'awstatssettings' =&gt; 'nastaven awstatu', 'domain_dns_settings' =&gt; 'nastaven domnov dns', 'activated' =&gt; 'aktivovno', 'statisticsettings' =&gt; 'nastaven statistik', 'or' =&gt; 'nebo', 'sysload' =&gt; 'systmov zaten', 'noloadavailable' =&gt; 'neni k dispozici', 'nouptimeavailable' =&gt; 'neni k dispozici', 'nosubject' =&gt; '(bez pedmtu)', 'security_settings' =&gt; 'monosti zabezpeen', 'know_what_youre_doing' =&gt; 'zmte pouze, pokud vte, co dlte!', 'show_version_login' =&gt; [ 'title' =&gt; 'zobrazit froxlor verzi pi pihlen', 'description' =&gt; 'zobrazit froxlor verzi v zpat na pihlaovac strnce', ], 'show_version_footer' =&gt; [ 'title' =&gt; 'zobrazit froxlor verzi v zpat', 'description' =&gt; 'zobrazit froxlor verzi v zpat na ostatnch strnkch', ], 'froxlor_graphic' =&gt; [ 'title' =&gt; 'grafick zhlav pro froxlor', 'description' =&gt; 'jak grafika mla bt zobrazena v zhlav', ], 'phpsettings' =&gt; [ 'title' =&gt; 'php konfigurace', 'description' =&gt; 'strun popis', 'actions' =&gt; 'akce', 'activedomains' =&gt; 'pouv se pro domnu/y', 'notused' =&gt; 'konfigurace se nepouv', 'editsettings' =&gt; 'zmnit nastaven php', 'addsettings' =&gt; 'vytvoit nov nastaven php', 'viewsettings' =&gt; 'zobrazit nastaven php', 'phpinisettings' =&gt; 'php.ini nastaven', 'addnew' =&gt; 'vytvoit novou konfiguraci php', 'binary' =&gt; 'php binary', 'fpmdesc' =&gt; 'php-fpm konfigurace', 'file_extensions' =&gt; 'ppony soubor', 'file_extensions_note' =&gt; '(bez teky, oddlench mezerami)', 'enable_slowlog' =&gt; 'povolit slowlog (pro kadou domnu)', 'request_terminate_timeout' =&gt; 'asov limit ukonen poadavku', 'request_slowlog_timeout' =&gt; 'asov limit ukonen poadavku slowlogu', 'activephpconfigs' =&gt; 'pouv se pro php-config(y)', 'pass_authorizationheader' =&gt; 'pedvn hlaviek http auth basic/digest z apache php', ], 'misc' =&gt; 'ostatn', 'fpmsettings' =&gt; [ 'addnew' =&gt; 'vytvoit novou verzi php', 'edit' =&gt; 'zmnit verzi php' ], 'phpconfig' =&gt; [ 'template_replace_vars' =&gt; 'promnn, kter budou nahrazeny v konfiguraci', 'pear_dir' =&gt; 'bude nahrazeno globlnm nastavenm pro pearl adres.', 'open_basedir_c' =&gt; 'vlo ; (stednk) komente/vypne open_basedir po nastaven', 'open_basedir' =&gt; 'bude nahrazeno nastavenm domny open_basedir.', 'tmp_dir' =&gt; 'bude nahrazeno doasnm adresem domny.', 'open_basedir_global' =&gt; 'bude nahrazena globln hodnotou cesty, kter bude pipojena k open_basedir (viz nastaven webserveru).', 'customer_email' =&gt; 'bude nahrazeno e-mailovou adresou zkaznka, kter tuto domnu vlastn.', 'admin_email' =&gt; 'bude nahrazeno e-mailovou adresou sprvce, kter tuto domnu vlastn.', 'domain' =&gt; 'bude nahrazeno domnou.', 'customer' =&gt; 'bude nahrazeno pihlaovacm jmnem zkaznka, kter vlastn tuto domnu.', 'admin' =&gt; 'bude nahrazeno pihlaovacm jmnem sprvce, kter tuto domnu vlastn.', 'docroot' =&gt; 'bude nahrazeno koenovm textem domny.', 'homedir' =&gt; 'bude nahrazeno domovskm adresem zkaznka.', ], 'expert_settings' =&gt; 'pokroil nastaven!', 'mod_fcgid_starter' =&gt; [ 'title' =&gt; 'php procesy pro tuto domnu (przdn pro vchoz hodnotu)', ], 'phpserversettings' =&gt; 'nastaven php', 'mod_fcgid_maxrequests' =&gt; [ 'title' =&gt; 'maximln poet php poadavk pro tuto domnu (ponechte przdn pro vchoz hodnotu)', ], 'spfsettings' =&gt; 'nastaven spf domn', 'specialsettingsforsubdomains' =&gt; 'pout speciln nastaven pro vechny subdomny (*.example.com)', 'accountdata' =&gt; 'daje tu', 'contactdata' =&gt; 'kontaktn daje', 'servicedata' =&gt; 'daje slub', 'newerversionavailable' =&gt; 'k dispozici je novj verze froxloru.', 'newerversiondetails' =&gt; 'aktualizovat na verzi &lt;b&gt;%s&lt;/b&gt; nyn?&lt;br/&gt;(vae aktuln verze je: %s)', 'extractdownloadedzip' =&gt; 'extrahovat staen archiv "%s"?', 'cron' =&gt; [ 'cronsettings' =&gt; 'nastaven cronjobu', 'add' =&gt; 'pidat cronjob', ], 'cronjob_edit' =&gt; 'upravit cronjob', 'warning' =&gt; 'varovn - vezmte prosm na vdom!', 'lastlogin_succ' =&gt; 'posledn pihlen', 'ftpserver' =&gt; 'ftp server', 'ftpserversettings' =&gt; 'nastaven ftp serveru', 'webserver_user' =&gt; 'uivatelsk jmno webserveru', 'webserver_group' =&gt; 'nzev skupiny webserveru', 'perlenabled' =&gt; 'perl povolen', 'fcgid_settings' =&gt; 'fcgid', 'mod_fcgid_user' =&gt; 'mstn uivatel pro fcgid (froxlor vhost)', 'mod_fcgid_group' =&gt; 'mstn skupina k pouit pro fcgid (froxlor vhost)', 'perl_settings' =&gt; 'perl/cgi', 'notgiven' =&gt; '[neposkytnuto]', 'store_defaultindex' =&gt; 'uloit vchoz indexov soubor zkaznkm docroot', 'phpfpm_settings' =&gt; 'php-fpm', 'traffic' =&gt; 'provoz', 'traffic_sub' =&gt; 'podrobnosti vyuit provozu', 'domaintraffic' =&gt; 'domny', 'customertraffic' =&gt; 'zkaznci', 'assignedmax' =&gt; 'piazeno / max', 'usedmax' =&gt; 'pouito / max', 'used' =&gt; 'vyuito', 'speciallogwarning' =&gt; '&lt;div id=speciallogfilenote class=invalid-feedback&gt;pozor: zmnou tohoto nastaven ztratte vechny star statistiky pro tuto domnu.&lt;/div&gt;', 'speciallogfile' =&gt; [ 'title' =&gt; 'oddlit soubor logu', 'description' =&gt; 'povolenm tto monosti zskte pro tuto domnu samostatn soubor pstupovho protokolu', ], 'domain_editable' =&gt; [ 'title' =&gt; 'povolit pravy domny', 'desc' =&gt; 'pokud je nastaveno ano, zkaznk zmnit nkolik nastaven domny.&lt;br /&gt;pokud je nastaveno ne, neme zkaznk nic mnit.', ], 'writeaccesslog' =&gt; [ 'title' =&gt; 'zapisovat pstupov protokol', 'description' =&gt; 'povolenm tto monosti zskte soubor protokolu pstupu pro tuto domnu', ], 'writeerrorlog' =&gt; [ 'title' =&gt; 'zapsat protokol chyb', 'description' =&gt; 'povolenm tto funkce zskte soubor chybovm protokolem pro tuto domnu', ], 'phpfpm.ininote' =&gt; 'ne vechny hodnoty, kter chcete definovat, mohou bt pouity v konfiguraci php-fpm poolu', 'phpinfo' =&gt; 'phpinfo()', 'selectserveralias' =&gt; 'hodnota serveralias pro domnu', 'selectserveralias_desc' =&gt; 'vyberte, zda froxlor ml vytvoit wildcard-entry (*.domain.tld), www-alias (www.domain.tld) nebo vbec dn alias', 'show_news_feed' =&gt; [ 'title' =&gt; 'zobrazit novinky na admin nstnce', 'description' =&gt; 'povolenm zobrazte oficiln novinky froxlor (https://inside.froxlor.org/news/) na va nstnce nikdy nezmekejte dleit informace nebo oznmen vydn.', ], 'cronsettings' =&gt; 'nastaven cronjobu', 'integritycheck' =&gt; 'oven databze', 'integrityname' =&gt; 'nzev', 'integrityresult' =&gt; 'vsledek', 'integrityfix' =&gt; 'automaticky opravit problmy', 'customer_show_news_feed' =&gt; 'zobrazit novinky na dicm panelu zkaznka', 'customer_news_feed_url' =&gt; [ 'title' =&gt; 'pout vlastn rss-feed', 'description' =&gt; 'zadejte vlastn rss kanl, kter bude zobrazen vaim zkaznkm na jejich nstnce.&lt;br /&gt;&lt;small&gt;ponechte przdn pro pouit oficilnho froxlor newsfeed (https://inside.froxlor.org/news/).&lt;/small&gt;', ], 'movetoadmin' =&gt; 'pesunout zkaznka', 'movecustomertoadmin' =&gt; [ 'title' =&gt; 'pesunout zkaznka na vybranho administrtora/prodejce', 'description' =&gt; 'ponechte przdn pro dnou zmnu.&lt;br /&gt;pokud se poadovan administrtor nezobraz v seznamu, jeho zkaznick limit byl dosaen.', ], 'note' =&gt; 'poznmka', 'mod_fcgid_umask' =&gt; [ 'title' =&gt; 'umask (vchoz: 022)', ], 'apcuinfo' =&gt; 'apcu info', 'opcacheinfo' =&gt; 'opcache info', 'letsencrypt' =&gt; [ 'title' =&gt; 'pout let\'s encrypt', 'description' =&gt; 'zskejte zdarma certifikt od &lt;a href="https://letsencrypt.org"&gt;let\'s encrypt&lt;/a&gt;. certifikt bude vytvoen obnoven automaticky.&lt;br&gt;&lt;strong class="text-danger"&gt;poznmka:&lt;/strong&gt; pokud jsou povoleny wildcards, tato monost bude automaticky zakzna.', ], 'autoupdate' =&gt; 'automatick aktualizace', 'server_php' =&gt; 'php', 'dnsenabled' =&gt; 'povolit dns editor', 'froxlorvhost' =&gt; 'froxlor virtualhost nastaven', 'hostname' =&gt; 'nzev serveru', 'memory' =&gt; 'vyuit pamti', 'webserversettings_ssl' =&gt; 'nastaven ssl webserveru', 'domain_hsts_maxage' =&gt; [ 'title' =&gt; 'http strict transport security (hsts)', 'description' =&gt; 'zadejte hodnotu maximlnho vku pro zhlav strict-transport-security&lt;br&gt;hodnota &lt;i&gt;0&lt;/i&gt; zake hsts pro domnu. vtina uivatel nastavila hodnotu &lt;i&gt;31536000&lt;/i&gt; (jeden rok).', ], 'domain_hsts_incsub' =&gt; [ 'title' =&gt; 'zahrnout hsts pro jakoukoliv subdomnu', 'description' =&gt; 'voliteln direktiva includesubdomains, pokud je ptomna, signalizuje ua, e zsady hsts se vztahuj na tohoto hostitele hsts na vechny subdomny nzvu domny hostitele.', ], 'domain_hsts_preload' =&gt; [ 'title' =&gt; 'zahrnout domnu seznamu pednatench hsts', 'description' =&gt; 'pokud chcete, aby byla tato domna zahrnuta &lt;a href="https://hstspreload.org/" target="_blank"&gt;hsts preload listu&lt;/a&gt; spravovanho chrome (a pouvanho firefoxem safari), pot pouijte tuto aktivaci.&lt;br&gt;odesln preload direktivy z vaich strnek mt trval nsledky zabrnit uivatelm v pstupu na vae strnky vechny jejich poddomny.&lt;br&gt;ped odeslnm hlaviky "preload" si prosm pette podrobnosti na &lt;a href="https://hstspreload.org/#removal" target="_blank"&gt;https://hstspreload.org/#removal&lt;/a&gt;.', ], 'domain_ocsp_stapling' =&gt; [ 'title' =&gt; 'stapling ocsp', 'description' =&gt; 'podrobn vysvtlen stapling ocsp viz &lt;a target="_blank" href="https://en.wikipedia.org/wiki/ocsp_stapling"&gt;wikipedia&lt;/a&gt;', 'nginx_version_warning' =&gt; '&lt;br /&gt;&lt;strong class="text-danger"&gt;varovn:&lt;/strong&gt; nginx verze 1.3.7 nebo vy je vyadovna pro ocsp stapling. pokud je vae verze star, webov server nebude sprvn sputn, dokud je povoleno ocsp stapling!', ], 'domain_http2' =&gt; [ 'title' =&gt; 'http2 podpora', 'description' =&gt; 'podrobn vysvtlen http2 viz &lt;a target="_blank" href="https://en.wikipedia.org/wiki/http/2"&gt;wikipedia&lt;/a&gt;', ], 'testmail' =&gt; 'test smtp', 'phpsettingsforsubdomains' =&gt; 'pout php konfiguraci na vechny subdomny:', 'plans' =&gt; [ 'name' =&gt; 'nzev plnu', 'description' =&gt; 'popis', 'last_update' =&gt; 'naposledy aktualizovno', 'plans' =&gt; 'plny hostingu', 'plan_details' =&gt; 'detaily plnu', 'add' =&gt; 'pidat nov pln', 'edit' =&gt; 'upravit pln', 'use_plan' =&gt; 'pout pln', ], 'notryfiles' =&gt; [ 'title' =&gt; 'dn automatick generovn try_soubor', 'description' =&gt; 'zde zvolte ano, pokud chcete sepcilnm nastavcen zadat vlastn direktivu try_files (potebnou napklad pro nkter pluginy wordpressu).', ], 'logviewenabled' =&gt; 'povolit pstup k logm pstupu/chyb', 'novhostcontainer' =&gt; '&lt;br&gt;&lt;br&gt;&lt;small class="text-danger"&gt;dn z ip port nem povolenou monost "vytvoit vhost-container", mnoho nastaven zde nebude k dispozici&lt;/small&gt;', 'ownsslvhostsettings' =&gt; 'vlastn ssl vhost-nastaven', 'domain_override_tls' =&gt; 'pepsat nastaven systmovho tls', 'domain_override_tls_addinfo' =&gt; '&lt;br /&gt;&lt;span class="text-danger"&gt;pouv se pouze v ppad, e "pepsat nastaven tls systmu" je nastaveno na "ano"&lt;/span&gt;', 'domain_sslenabled' =&gt; 'povolit pouit ssl', 'domain_honorcipherorder' =&gt; 'dodrovat poad ifry (serveru), vchoz &lt;strong&gt;ne&lt;/strong&gt;', 'domain_sessiontickets' =&gt; 'povolit tls sessiontickety (rfc 5077), vchoz &lt;strong&gt;ano&lt;/strong&gt;', 'domain_sessionticketsenabled' =&gt; [ 'title' =&gt; 'povolit pouit tiket tls globln', 'description' =&gt; 'vchoz &lt;strong&gt;ano&lt;/strong&gt;&lt;br&gt;vyaduje apache-2.4.11+ nebo nginx-1.5.9+', ], 'domaindefaultalias' =&gt; 'vchoz hodnota serveralias pro nov domny', 'smtpsettings' =&gt; 'nastaven smtp', 'smtptestaddr' =&gt; 'odeslat testovac email na', 'smtptestnote' =&gt; 'ne uveden hodnoty odrej vae aktuln nastaven lze je upravit pouze zde (viz odkaz v pravm hornm rohu)', 'smtptestsend' =&gt; 'odeslat testovac e-mail', 'mysqlserver' =&gt; [ 'mysqlserver' =&gt; 'mysql server', 'dbserver' =&gt; 'server #', 'caption' =&gt; 'popis', 'host' =&gt; 'nzev serveru / ip', 'port' =&gt; 'port', 'user' =&gt; 'oprvnn uivatel', 'add' =&gt; 'pidat nov mysql server', 'edit' =&gt; 'upravit mysql server', 'password' =&gt; 'heslo oprvnnho uivatele', 'password_emptynochange' =&gt; 'nov heslo, ponechte przdn pro ponechn aktulnho', 'allowall' =&gt; [ 'title' =&gt; 'povolit pouit tohoto serveru vem aktuln existujcm zkaznkm', 'description' =&gt; 'nastavte tuto hodnotu na true, pokud chcete povolit pouvn tohoto databzovho serveru vem stvajcm zkaznkm, aby na nj mohli pidvat databze. toto nastaven nen trval, ale lze jej spustit vcekrt.', ], 'testconn' =&gt; 'otestovat pipojen pi ukldn', 'ssl' =&gt; 'pout ssl pro pipojen k databzovmu serveru', 'ssl_cert_file' =&gt; 'cesta k souboru k ssl certifikan autorit', 'verify_ca' =&gt; 'povolit oven serverovho ssl certifiktu', ], 'settings_importfile' =&gt; 'zvolit importovan soubor', 'documentation' =&gt; 'dokumentace', 'adminguide' =&gt; 'admin prvodce', 'userguide' =&gt; 'uivatelsk manul', 'apiguide' =&gt; 'prvodce api', 'domain_duplicate' =&gt; 'duplikovat domnu', 'domain_duplicate_named' =&gt; 'duplikovat %s', 'backups' =&gt; [ 'backups' =&gt; 'zlohy', ], ], 'apcuinfo' =&gt; [ 'clearcache' =&gt; 'vymazat apcu mezipam', 'generaltitle' =&gt; 'obecn informace cache', 'version' =&gt; 'apcu verze', 'phpversion' =&gt; 'verze php', 'host' =&gt; 'apcu hostitel', 'sharedmem' =&gt; 'sdlen pam', 'sharedmemval' =&gt; '%d segment(y) %s (%s pamti)', 'start' =&gt; 'as sputn', 'uptime' =&gt; 'doba provozu', 'upload' =&gt; 'podpora nahrvn soubor', 'cachetitle' =&gt; 'informace cache', 'cvar' =&gt; 'promnn v mezipamti', 'hit' =&gt; 'zsahy', 'miss' =&gt; 'nevyuito', 'reqrate' =&gt; 'mra poadavku (zsahy, nevyuit)', 'creqsec' =&gt; 'poadavky mezipamti za sekundu', 'hitrate' =&gt; 'rychlost zsahu', 'missrate' =&gt; 'nevyuit mra', 'insrate' =&gt; 'insert rate', 'cachefull' =&gt; 'pln poet vyrovnvac pamti', 'runtime' =&gt; 'nastaven sputn', 'memnote' =&gt; 'vyuit pamti', 'total' =&gt; 'celkem', 'free' =&gt; 'voln', 'used' =&gt; 'vyuito', 'hitmiss' =&gt; 'zsahy &amp; nevyuit', 'detailmem' =&gt; 'podrobn vyuit pamti fragmentace', 'fragment' =&gt; 'fragmentace', 'nofragment' =&gt; 'bez fragmentace', 'fragments' =&gt; 'fragmentace', ], 'apikeys' =&gt; [ 'no_api_keys' =&gt; 'nebyly nalezeny dn api kle', 'key_add' =&gt; 'pidat nov kl', 'apikey_removed' =&gt; 'api kl id #%s byl spn odstrann', 'apikey_added' =&gt; 'byl spn vygenerovn nov api kl', 'clicktoview' =&gt; 'kliknte pro zobrazen', 'allowed_from' =&gt; 'povoleno od', 'allowed_from_help' =&gt; 'rkami oddlen seznam ip adres / st.&lt;br&gt;vchoz nastaven je przdn (povolit od vech).', 'valid_until' =&gt; 'platn do', 'valid_until_help' =&gt; 'datum platnosti, formt rrrr-mm-ddth:mm', ], 'changepassword' =&gt; [ 'old_password' =&gt; 'star heslo', 'new_password' =&gt; 'nov heslo', 'new_password_confirm' =&gt; 'potvrdit heslo', 'new_password_ifnotempty' =&gt; 'nov heslo (przdn = dn zmna)', 'also_change_ftp' =&gt; ' tak zmnit heslo hlavnho ftp tu', 'also_change_stats' =&gt; ' tak zmnit heslo pro strnku se statistikou', 'also_change_global_mysql' =&gt; 'tak zmnit heslo pro globln mysql et', ], 'cron' =&gt; [ 'cronname' =&gt; 'nzev cronjobu', 'lastrun' =&gt; 'posledn sputn', 'interval' =&gt; 'interval', 'isactive' =&gt; 'povoleno', 'description' =&gt; 'popis', 'changewarning' =&gt; 'zmna tchto hodnot mt negativn pinu chovn froxlor jeho automatickch loh.&lt;br /&gt;zmte hodnoty zde pouze pokud jste si jisti, e vte, co dlte.', ], 'crondesc' =&gt; [ 'cron_unknown_desc' =&gt; 'nebyl zadn dn popis', 'cron_tasks' =&gt; 'generovn konfiguranch soubor', 'cron_legacy' =&gt; 'star (star) cronjob', 'cron_traffic' =&gt; 'vpoet datovho provozu', 'cron_usage_report' =&gt; 'hlen provozu webu', 'cron_mailboxsize' =&gt; 'vpoet velikosti schrnky', 'cron_letsencrypt' =&gt; 'aktualizace certifiktu let\'s encrypt', 'cron_export' =&gt; 'zpracovn loh exportu dat', 'cron_backup' =&gt; 'zpracovn loh zlohovn systmu zkaznk', ], 'cronjob' =&gt; [ 'cronjobsettings' =&gt; 'nastaven cronjobu', 'cronjobintervalv' =&gt; 'hodnota intervalu bhu', 'cronjobinterval' =&gt; 'interval bhu', ], 'cronjobs' =&gt; [ 'notyetrun' =&gt; 'jet nesputno', ], 'cronmgmt' =&gt; [ 'minutes' =&gt; 'minut', 'hours' =&gt; 'hodin', 'days' =&gt; 'dn', 'weeks' =&gt; 'tdn', 'months' =&gt; 'msc', ], 'customer' =&gt; [ 'documentroot' =&gt; 'domovsk adres', 'name' =&gt; 'nzev', 'firstname' =&gt; 'kestn jmno', 'lastname' =&gt; 'pjmen', 'company' =&gt; 'firma', 'nameorcompany_desc' =&gt; 'kestn jmno/pjmen nebo firma je povinn', 'street' =&gt; 'ulice', 'zipcode' =&gt; 'ps', 'city' =&gt; 'msto', 'phone' =&gt; 'mobil', 'fax' =&gt; 'fax', 'email' =&gt; 'email', 'customernumber' =&gt; 'id zkaznka', 'diskspace' =&gt; 'webov prostor', 'traffic' =&gt; 'provoz', 'mysqls' =&gt; 'databze mysql', 'emails' =&gt; 'e-mailov adresy', 'accounts' =&gt; 'e-mailov ty', 'forwarders' =&gt; 'e-mailov peposlai', 'ftps' =&gt; 'ftp ty', 'subdomains' =&gt; 'subdomny', 'domains' =&gt; 'domny', 'mib' =&gt; 'mib', 'gib' =&gt; 'gib', 'title' =&gt; 'nzev', 'country' =&gt; 'zem', 'email_quota' =&gt; 'kvta e-mailu', 'email_imap' =&gt; 'e-mail imap', 'email_pop3' =&gt; 'e-mail pop3', 'sendinfomail' =&gt; 'poslat mi data e-mailem', 'generated_pwd' =&gt; 'nvrh hesla', 'usedmax' =&gt; 'pouito / max', 'services' =&gt; 'sluby', 'letsencrypt' =&gt; [ 'title' =&gt; 'pout let\'s encrypt', 'description' =&gt; 'zskejte zdarma certifikt od &lt;a href="https://letsencrypt.org"&gt;let\'s encrypt&lt;/a&gt;. certifikt bude vytvoen obnoven automaticky.', ], 'selectserveralias_addinfo' =&gt; 'tuto monost lze nastavit pi prav domny. jej poten hodnota je zddna z rodiovsk domny.', 'total_diskspace' =&gt; 'celkov prostor na disku', 'mysqlserver' =&gt; 'pouiteln mysql-server', ], 'diskquota' =&gt; 'kvta', 'antispam' =&gt; [ 'config_file' =&gt; [ 'title' =&gt; 'soubor nastavenm antispamu', 'description' =&gt; 'zadejte nzev souboru pro pravidla e-mail-antispamu', ], 'reload_command' =&gt; [ 'title' =&gt; 'pkaz k restartu systmu milter', 'description' =&gt; 'zadejte pkaz restartu pro slubu rspamd', ], 'activated' =&gt; [ 'title' =&gt; 'aktivovat antispam?', 'description' =&gt; 'chcete pout rspamd jako antispam slubu?', ], 'dkim_keylength' =&gt; [ 'title' =&gt; 'dkim dlka kle', 'description' =&gt; 'upozornn: zmny se budou vztahovat pouze na nov kle&lt;br/&gt;&lt;br/&gt;vyaduje uritou poloku dns pro domnu. pokud nepouvte funkci nameserver, budete muset tyto poloky run spravovat.', ], 'spam_tag_level' =&gt; [ 'title' =&gt; 'rove spam tagu', 'description' =&gt; 'poet bod, kter je nutn k oznaen e-mailu jako spam&lt;br/&gt;vchoz: 7.0' ], 'spam_kill_level' =&gt; [ 'title' =&gt; 'rove likvidace spamu', 'description' =&gt; 'poet bod, kter je nutn k plnmu vyazen e-mailu&lt;br/&gt;vchoz: 14.0' ], 'bypass_spam' =&gt; [ 'title' =&gt; 'obejt spamfiltr', 'description' =&gt; 'aktivac obejdete/zakete filtrovn spamu pro tuto adresu.&lt;br/&gt;vchoz: ne' ], 'policy_greylist' =&gt; [ 'title' =&gt; 'pout greylisting', 'description' =&gt; 'pchoz e-maily budou chrnny &lt;a href="https://en.wikipedia.org/wiki/greylisting_(email)" target="_blank"&gt;greylisting&lt;/a&gt;.&lt;br/&gt;vchoz: ano' ], 'required_spf_dns' =&gt; 'poadovan spf dns zznam', 'required_dmarc_dns' =&gt; 'poadovan dmarc dns zznam', 'required_dkim_dns' =&gt; 'poadovan dkim dns zznam', ], 'dns' =&gt; [ 'destinationip' =&gt; 'ip domny(y)', 'standardip' =&gt; 'standardn ip adresa serveru', 'a_record' =&gt; 'a-zznam (voliteln ipv6)', 'cname_record' =&gt; 'zznam cname', 'mxrecords' =&gt; 'definovat mx zznamy', 'standardmx' =&gt; 'standardn mx zznam serveru', 'mxconfig' =&gt; 'vlastn mx zznamy', 'priority10' =&gt; 'priorita 10', 'priority20' =&gt; 'priorita 20', 'txtrecords' =&gt; 'definovat txt zznamy', 'txtexample' =&gt; 'pklad (spf-entry):&lt;br /&gt;v=spf1 ip4:xxx.xxx.xx.0/23 -all', 'howitworks' =&gt; 'zde mete spravovat dns poloky pro vai domnu. pamatujte, e froxlor automaticky vygeneruje ns/mx/a/aaaa zznamy pro vs. vlastn poloky jsou upednostovny, budou automaticky vygenerovny pouze chybjc poloky.', ], 'dnseditor' =&gt; [ 'edit' =&gt; 'upravit dns', 'records' =&gt; 'zznamy', 'notes' =&gt; [ 'a' =&gt; '32bitov adresa ipv4 pouvan k mapovn nzv hostitel na ip adresu hostitele.', 'aaaa' =&gt; '128-bitov ipv6 adresa, pouvan k mapovn jmen na ip adresu hostitele.', 'caa' =&gt; 'zznam zdroje caa umouje driteli jmna domny dns zadat jednu nebo vce certifikanch autorit (ca), kter jsou oprvnny vydvat certifikty pro tuto domnu.&lt;br&gt;struktura: &lt;code&gt;znaka tag[issue|issuewild|iodef|contactmail|contactphone] hodnota&lt;/code&gt;&lt;br&gt;pklad: &lt;code&gt;0 issue "ca.example.net"&lt;br&gt;0 iodef "mailto:security@example.com"&lt;/code&gt;', 'cname' =&gt; 'alias nzvu domny, hledn dns bude pokraovat opakovnm hledn novm nzvem. mon pouze pro subdomny!', 'dname' =&gt; 'vytvo alias pro cel podstrom stromu domny', 'loc' =&gt; 'informace geografickm umstn pro nzev domny.&lt;br&gt;struktura: &lt;code&gt;( d1 [m1 [s1]] {"n"|"s"} d2 [m2 [s2]] {"e"|"w"} alt["m"] [siz["m"] [hp["] [vp["m"]]]] )&lt;/code&gt;&lt;br&gt; &lt;code&gt;d1: [0 . 90] (stupn zempisn ky) d2: [0 .. 180] (stupnice zempisn dlky) m1, m2: [0 .. 59] (minuty zempisn ky/dlky) s1, s2: [0 .. 59. 99] (sekundy zempisn ky/dlky) [-100000.00 .. 42849672.95] . 1 (vka v metrech) velikost, hp, vp: [0 .. 90000000. 0] (velikost/pesnost v metrech)&lt;/code&gt;&lt;br&gt;pklad: &lt;code&gt;52 22 23.000 n 4 53 32.000 e -2,00m 000m 10000m&lt;/code&gt;', 'mx' =&gt; 'zznam vmn e-mail, namapuje domnu na mailserver pro tuto domnu.&lt;br&gt;pklad: &lt;code&gt;10 mail.example.com&lt;/code&gt;&lt;br&gt;poznmka: pro prioritu pouijte pole ve', 'ns' =&gt; 'deleguje znu dns, aby pouil dan autoritativn jmenn servery.', 'rp' =&gt; 'zznam odpovdn osoby&lt;br&gt;struktura: &lt;code&gt;mailbox[nahrate @ tekou] txt-record-name&lt;/code&gt;&lt;br&gt;pklad: &lt;code&gt;team.froxlor.org. froxlor.org.&lt;/code&gt;', 'srv' =&gt; 'zznam polohy sluby, pouit pro novj protokoly namsto vytven zznam specifickch pro protokol, jako je mx.&lt;br&gt;struktura: &lt;code&gt;prioritn vhov port cl&lt;/code&gt;&lt;br&gt;pklad: &lt;code&gt;0 5 5060 sipserver. xample.com.&lt;/code&gt;&lt;br&gt;poznmka: pro prioritu pouijte pole ve', 'sshfp' =&gt; 'zznam zdroje sshfp se pouv ke zveejnn otisk prst kle bezpenho shell (ssh) v dns.&lt;br&gt;struktura: &lt;code&gt;typ algoritmu&lt;/code&gt;&lt;br&gt;algoritmy: &lt;code&gt;0: vyhrazeno, 1: rsa, 2: dsa, 3: ecdsa, 4: ed25519, 6: typy ed448&lt;/code&gt;&lt;br&gt; &lt;code&gt;0: vyhrazen, 1: sha-1, 2: sha-256&lt;/code&gt;&lt;br&gt;pklad: &lt;code&gt;2 1 123456789abcdef67890123456789abcdef67890&lt;/code&gt;', 'tlsa' =&gt; 'tlsa (tls authentication) zznam slou ke zveejnn otisku prstu certifiktu tls/ssl. bn se pouv pro dane.&lt;br&gt;tlsa zznamy mohou bt dvryhodn, pouze pokud je dnssec povolena na va domn.&lt;br&gt;struktura: &lt;code&gt;typ otisku prstu&lt;/code&gt;&lt;br&gt;vyuit certifiktu: &lt;code&gt;0: pkix-t, 1: pkix-ee, 2: dane-ta, 3: dane-ee&lt;/code&gt;&lt;br&gt;selektor: &lt;code&gt;0: pouijte cel certifikt 1: pouvejte podzen veejn kl&lt;/code&gt;&lt;br&gt;odpovdajc typ: &lt;code&gt;0: bez hash, 1: sha-256 hash, 2:sha-512 hash&lt;/code&gt;&lt;br&gt;pklad: &lt;code&gt;3 1 123456789abcdef67890123456789abcdef123456789abcdef123456789abcde&lt;/code&gt;', 'txt' =&gt; 'voln definovan, popisn text.' ] ], 'domain' =&gt; [ 'openbasedirpath' =&gt; 'openbasedir-cesta', 'inherited' =&gt; 'stejn jako rodiovsk domna', 'docroot' =&gt; 'cesta z pole ve', 'homedir' =&gt; 'domovsk adres', 'docparent' =&gt; 'nadazen adres cesty z uvedenho pole', 'ssl_certificate_placeholder' =&gt; '---- begin certificate---' . php_eol . '[...]' . php_eol . '----end certificate----', 'ssl_key_placeholder' =&gt; '---- begin rsa private key-----' . php_eol . '[...]' . php_eol . '-----end rsa private key-----', ], 'domains' =&gt; [ 'description' =&gt; 'zde mete vytvoit (sub)domny zmnit jejich cesty.&lt;br /&gt;systm bude potebovat njak as, aby mohl po kad zmn pout nov nastaven.', 'domainsettings' =&gt; 'nastaven domny', 'domainname' =&gt; 'nzev domny', 'subdomain_add' =&gt; 'vytvoit subdomnu', 'subdomain_edit' =&gt; 'upravit (sub)domnu', 'wildcarddomain' =&gt; 'vytvoit jako wildcarddomain?', 'aliasdomain' =&gt; 'alias pro domnu', 'noaliasdomain' =&gt; 'dn alias domny', 'hasaliasdomains' =&gt; 'm alias domnu(y)', 'statstics' =&gt; 'statistiky vyuit', 'isassigneddomain' =&gt; 'je piazena domna', 'add_date' =&gt; 'pidno froxloru', 'registration_date' =&gt; 'pidno registru', 'topleveldomain' =&gt; 'top-level-domna', 'associated_with_domain' =&gt; 'pidruen', 'aliasdomains' =&gt; 'alias domn', 'redirectifpathisurl' =&gt; 'pesmrovac kd (vchoz: przdn)', 'redirectifpathisurlinfo' =&gt; 'muste vybrat pouze jednu z tchto poloek, pokud jste zadali adresu url jako cestu&lt;br/&gt;&lt;strong class="text-danger"&gt;poznmka:&lt;/strong&gt; zmny jsou aplikovny pouze v ppad, e dan cesta je url adresa.', 'ipandport_multi' =&gt; [ 'title' =&gt; 'ip adresa (adresy)', 'description' =&gt; 'zadejte jednu nebo vce ip adres domny.&lt;br /&gt;&lt;br /&gt;&lt;div class="text-danger"&gt;poznmka: ip adresy nelze zmnit, pokud je domna nakonfigurovna jako &lt;strong&gt;alias-domna&lt;/strong&gt; jin domny.&lt;/div&gt;', ], 'ipandport_ssl_multi' =&gt; [ 'title' =&gt; 'ssl ip adresa/y', ], 'ssl_redirect' =&gt; [ 'title' =&gt; 'pesmrovn ssl', 'description' =&gt; 'tato volba vytvo pesmrovn pro ne ssl vhosty, take vechny poadavky jsou pesmrovny na ssl-vhost.&lt;br /&gt;&lt;br /&gt;e.. poadavek na &lt;strong&gt;http&lt;/strong&gt;://domain.tld/ pesmruje vs na &lt;strong&gt;https&lt;/strong&gt;://domain.tld/', ], 'serveraliasoption_wildcard' =&gt; 'wildcard (*.domain.tld)', 'serveraliasoption_www' =&gt; 'www (www.domain.tld)', 'serveraliasoption_none' =&gt; 'bez aliasu', 'domain_import' =&gt; 'importovat domny', 'import_separator' =&gt; 'oddlova', 'import_offset' =&gt; 'odsazen', 'import_file' =&gt; 'soubor csv', 'import_description' =&gt; 'podrobn informace struktue importnho souboru spnm importu, navtivte prosm &lt;a href="https://docs.froxlor.org/latest/admin-guide/domain-import/" target="_blank" class="alert-link"&gt;https://docs.froxlor.org/latest/admin-guide/domain-import/&lt;/a&gt;', 'ssl_redirect_temporarilydisabled' =&gt; '&lt;br&gt;pesmrovn protokolu ssl je doasn deaktivovno, zatmco je generovn nov let\'s encrypt certifikt. bude znovu aktivovno po vygenerovn certifiktu.', 'termination_date' =&gt; 'datum ukonen', 'termination_date_overview' =&gt; 'ukoneno dne ', 'ssl_certificates' =&gt; 'ssl certifikty', 'ssl_certificate_removed' =&gt; 'certifikt id #%s byl spn odstrann', 'ssl_certificate_error' =&gt; 'chyba pi ten certifiktu pro domnu: %s', 'no_ssl_certificates' =&gt; 'neexistuj dn domny ssl certifiktem', 'isaliasdomainof' =&gt; 'je aliasdomna pro %s', 'isbinddomain' =&gt; 'vytvoit znu dns', 'dkimenabled' =&gt; 'dkim povoleno', 'openbasedirenabled' =&gt; 'openbasedir restrikce', 'hsts' =&gt; 'hsts povoleno', 'aliasdomainid' =&gt; 'id aliasov domny', 'nodomainsassignedbyadmin' =&gt; 'v et nem v souasn dob piazeny dn (aktivn) domny. pokud si myslte, e je patn, kontaktujte svho sprvce.', 'email_only' =&gt; 'jen emaily', ], 'emails' =&gt; [ 'description' =&gt; 'zde mete vytvet mnit sv e-mailov adresy.&lt;br /&gt;et je jako potovn schrnka ped vam domem. pokud vm nkdo pole e-mail, bude vyputn na et.&lt;br /&gt;&lt;br /&gt;chcete-li sthnout sv e-maily, pouijte nsledujc nastaven vaem potovnm programu: (data v &lt;i&gt;kurzv&lt;/i&gt; mus bt zmnna na ekvivalenty, kter jste zadali!&lt;br /&gt;hostitelsk jmno: &lt;b&gt;&lt;i&gt;domnov jmno&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;uivatelsk jmno: &lt;b&gt;&lt;i&gt;jmno tu / e-mailov adresa&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;heslo: &lt;b&gt;&lt;i&gt;heslo, kter jste zvolili&lt;/i&gt;&lt;/b&gt;', 'emailaddress' =&gt; 'e-mailov adresa', 'emails_add' =&gt; 'vytvoit e-mailovou adresu', 'emails_edit' =&gt; 'upravit e-mailovou adresu', 'catchall' =&gt; 'catchall', 'iscatchall' =&gt; 'definovat jako catchall-adresu?', 'account' =&gt; 'et', 'account_add' =&gt; 'vytvoit et', 'account_delete' =&gt; 'odstranit et', 'from' =&gt; 'zdroj', 'to' =&gt; 'destinace', 'forwarders' =&gt; 'pesmrovn', 'forwarder_add' =&gt; 'vytvoit peposlatele', 'alternative_emailaddress' =&gt; 'alternativn e-mailov adresa', 'quota' =&gt; 'kvta', 'noquota' =&gt; 'bez kvty', 'updatequota' =&gt; 'aktualizovat kvtu', 'quota_edit' =&gt; 'zmnit e-mail kvtu', 'noemaildomainaddedyet' =&gt; 've svm tu jet nemte (e-mailovou) domnu.', 'back_to_overview' =&gt; 'zpt na pehled domny', 'accounts' =&gt; 'ty', 'emails' =&gt; 'adresy', ], 'error' =&gt; [ 'error' =&gt; 'chyba', 'directorymustexist' =&gt; 'adres %s mus existovat. vytvote jej prosm pomoc vaeho ftp klienta.', 'filemustexist' =&gt; 'soubor %s mus existovat.', 'allresourcesused' =&gt; 'vechny sv zdroje jste ji vyuili.', 'domains_cantdeletemaindomain' =&gt; 'nemete odstranit piazenou domnu.', 'domains_canteditdomain' =&gt; 'tuto domnu nelze upravovat. byla zakzna administrtorem.', 'domains_cantdeletedomainwithemail' =&gt; 'nemete odstranit domnu, kter se pouv jako e-mailov domna. nejprve odstrate vechny e-mailov adresy.', 'firstdeleteallsubdomains' =&gt; 'nejdve muste odstranit vechny subdomny, ne budete moci vytvoit wildcard domnu.', 'youhavealreadyacatchallforthisdomain' =&gt; 'pro tuto domnu jste ji definovali catchall.', 'ftp_cantdeletemainaccount' =&gt; 'nemete odstranit svj hlavn ftp et', 'login' =&gt; 'zadan uivatelsk jmno nebo heslo je patn. zkuste prosm znovu!', 'login_blocked' =&gt; 'tento et byl pozastaven kvli pli mnoha chybm pihlen. &lt;br /&gt;zkuste prosm znovu za %s sekund.', 'notallreqfieldsorerrors' =&gt; 'nevyplnili jste vechna nebo jste nesprvn vyplnili nkter pole.', 'oldpasswordnotcorrect' =&gt; 'star heslo nen sprvn.', 'youcantallocatemorethanyouhave' =&gt; 'nemete pidlit vce zdroj ne pro sebe.', 'mustbeurl' =&gt; 'nezadal jsi platnou nebo plnou url (nap. http://somedomain.com/error404.htm)', 'invalidpath' =&gt; 'nezvolili jste platnou adresu url (mon problmy se seznamem adres?)', 'stringisempty' =&gt; 'chybjc vstup v poli', 'stringiswrong' =&gt; 'nesprvn vstup v poli', 'newpasswordconfirmerror' =&gt; 'nov heslo potvrzen hesla se neshoduj', 'mydomain' =&gt; '\'domna\'', 'mydocumentroot' =&gt; '\'documentroot\'', 'loginnameexists' =&gt; 'pihlaovac jmno %s ji existuje', 'emailiswrong' =&gt; 'emailov adresa %s obsahuje neplatn znaky nebo je nekompletn', 'alternativeemailiswrong' =&gt; 'zadan alternativn e-mailov adresa %s pro odesln pihlaovacch daj se zd bt neplatn', 'loginnameiswrong' =&gt; 'pihlaovac jmno "%s" obsahuje nepovolen znaky.', 'loginnameiswrong2' =&gt; 'pihlaovac jmno obsahuje pli mnoho znak. pouze %s znaky jsou povoleny.', 'userpathcombinationdupe' =&gt; 'kombinace uivatelskho jmna cesty ji existuje', 'patherror' =&gt; 'obecn chyba! cesta neme bt przdn', 'errordocpathdupe' =&gt; 'monost pro cestu %s ji existuj', 'adduserfirst' =&gt; 'nejprve prosm vytvote zkaznka', 'domainalreadyexists' =&gt; 'domna %s je ji piazena zkaznkovi', 'nolanguageselect' =&gt; 'nebyl vybrn dn jazyk.', 'nosubjectcreate' =&gt; 'muste definovat tma pro tuto ablonu e-mailu.', 'nomailbodycreate' =&gt; 'muste definovat text e-mailu pro tuto ablonu e-mailu.', 'templatenotfound' =&gt; 'ablona nebyla nalezena.', 'alltemplatesdefined' =&gt; 'nemete definovat vce ablon, vechny jazyky jsou ji podporovny.', 'wwwnotallowed' =&gt; 'www nen povoleno pro subdomny.', 'subdomainiswrong' =&gt; 'subdomna %s obsahuje neplatn znaky.', 'domaincantbeempty' =&gt; 'nzev domny neme bt przdn.', 'domainexistalready' =&gt; 'domna %s ji existuje.', 'domainisaliasorothercustomer' =&gt; 'vybran domna aliasu je sama sob domnou, jinou kombinaci ip/port nebo pat jinmu zkaznkovi.', 'emailexistalready' =&gt; 'e-mailov adresa %s ji existuje.', 'maindomainnonexist' =&gt; 'hlavn domna %s neexistuje.', 'maindomaindeactivated' =&gt; 'hlavn domna %s je deaktivovna.', 'destinationnonexist' =&gt; 'prosm vytvote pedavatele v poli "destination".', 'destinationalreadyexistasmail' =&gt; 'peposlatel %s ji existuje jako aktivn e-mailov adresa.', 'destinationalreadyexist' =&gt; 'ji jste definovali pesmrovn na "%s"', 'destinationiswrong' =&gt; 'peposlatel() %s obsahuje neplatn znaky nebo je nepln.', 'dumpfoldercannotbedocroot' =&gt; 'sloka pro datov vpisy neme bt v domovsk adres, zvolte prosm sloku svm domovskm adresi, nap. /dumps', 'templatelanguagecombodefined' =&gt; 'kombinace vybranho jazyka/ablony ji byla definovna.', 'templatelanguageinvalid' =&gt; 'vybran jazyk neexistuje', 'ipstillhasdomains' =&gt; 'kombinace ip/portu, kterou chcete odstranit, stle obsahuje piazen domny, ped smaznm tto kombinace ip/portu je prosm piate k jinm kombinacm ip/portu.', 'cantdeletedefaultip' =&gt; 'nelze odstranit vchoz kombinaci ip/portu, ped smaznm tto kombinace ip/portu prosm nastavte vchoz nastaven jin kombinace ip/portu.', 'cantdeletesystemip' =&gt; 'nelze odstranit posledn systmovou ip adresu ani vytvoit novou kombinaci ip/port pro systmovou ip adresu nebo zmnit systmovou ip adresu.', 'myipaddress' =&gt; '\'ip\'', 'myport' =&gt; '\'port\'', 'myipdefault' =&gt; 'muste vybrat kombinaci ip/port, kter mla bt vchoz.', 'myipnotdouble' =&gt; 'tato kombinace ip/portu ji existuje.', 'admin_domain_emailsystemhostname' =&gt; 'jmno serveru nelze pout jako domnu zkaznka.', 'cantchangesystemip' =&gt; 'nelze zmnit posledn systmovou ip adresu ani vytvoit novou kombinaci ip/port pro systmovou ip adresu nebo zmnit systmovou ip adresu.', 'sessiontimeoutiswrong' =&gt; 'je povolen pouze seln "asov limit relace".', 'maxloginattemptsiswrong' =&gt; 'jsou povoleny pouze seln "maximln pokusy pihlen".', 'deactivatetimiswrong' =&gt; 'jsou povoleny pouze seln "doby deaktivace".', 'accountprefixiswrong' =&gt; '"zkaznick prefix" je nesprvn.', 'mysqlprefixiswrong' =&gt; '"sql prefix" je nesprvn.', 'ftpprefixiswrong' =&gt; 'prefix ftp je patn.', 'ipiswrong' =&gt; '"ip-adresa" je patn. je povoleno pouze platn ip adresa.', 'vmailuidiswrong' =&gt; '"uid-mail" je nesprvn. je povoleno pouze seln uid.', 'vmailgidiswrong' =&gt; 'poloka mails-gid je chybn. povoleno je pouze seln gid.', 'adminmailiswrong' =&gt; '"odeslatelsk adresa" je chybn. povolena je pouze platn e-mailov adresa.', 'pagingiswrong' =&gt; 'hodnota "poloky na strnku" je patn. povoleny jsou pouze seln znaky.', 'phpmyadminiswrong' =&gt; 'phpmyadmin-link nen platn odkaz.', 'webmailiswrong' =&gt; 'odkaz na webmail nen platn odkaz.', 'webftpiswrong' =&gt; 'webftp odkaz nen platnm odkazem.', 'stringformaterror' =&gt; 'hodnota pro pole "%s" nen v oekvanm formtu.', 'loginnameisusingprefix' =&gt; 'nemete vytvoit ty, kter zanaj znakem %s, protoe tento prefix je nastaven na automatick pojmenovn tu. zadejte prosm jin nzev tu.', 'loginnameissystemaccount' =&gt; 'et "%s" ji v systmu existuje nelze jej pout. zadejte jin nzev tu.', 'loginnameisreservedname' =&gt; 'nzev tu %s je vyhrazen pro vnitn systm nelze jej pout.', 'youcantdeleteyourself' =&gt; 'z bezpenostnch dvod nelze odstranit sm sebe.', 'youcanteditallfieldsofyourself' =&gt; 'poznmka: z bezpenostnch dvod nelze upravovat vechna pole vlastnho tu.', 'documentrootexists' =&gt; 'adres "%s" ji pro tohoto zkaznka existuje. ped pidnm zkaznka jej odstrate.', 'norepymailiswrong' =&gt; 'poloka noreply-address je chybn. povolena je pouze platn e-mailov adresa.', 'logerror' =&gt; 'chyba logu: %s', 'nomessagetosend' =&gt; 'nezadali jste zprvu.', 'norecipientsgiven' =&gt; 'nezadali jste dnho pjemce', 'errorsendingmail' =&gt; 'zprva pro "%s" se nezdaila', 'errorsendingmailpub' =&gt; 'zprva na danou e-mailovou adresu se nezdaila', 'cannotreaddir' =&gt; 'nelze pest adres "%s"', 'invalidip' =&gt; 'neplatn ip adresa: %s', 'invalidmysqlhost' =&gt; 'neplatn adresa mysql hostitele: %s', 'cannotuseawstatsandwebalizeratonetime' =&gt; 'nemete povolit webalizer awstats zrove, zvolte si jeden z nich', 'cannotwritetologfile' =&gt; 'nelze otevt soubor protokolu %s pro zpis', 'vmailquotawrong' =&gt; 'kvta mus bt kladn slo.', 'allocatetoomuchquota' =&gt; 'pokusili jste se pidlit %s mb kvtu, ale ji vm nezbv dostatek.', 'missingfields' =&gt; 'ne vechna povinn pole byla vyplnna.', 'requiredfield' =&gt; 'toto pole je povinn.', 'accountnotexisting' =&gt; 'zadan e-mailov et neexistuje.', 'nopermissionsorinvalidid' =&gt; 'nemte dostaten oprvnn ke zmn tohoto nastaven nebo bylo udleno neplatn id.', 'phpsettingidwrong' =&gt; 'php konfigurace tmto id neexistuje', 'descriptioninvalid' =&gt; 'popis je pli krtk/pli dlouh nebo obsahuje nepovolen znaky.', 'info' =&gt; 'info', 'filecontentnotset' =&gt; 'soubor neme bt przdn!', 'customerdoesntexist' =&gt; 'zvolen zkaznk neexistuje.', 'admindoesntexist' =&gt; 'zvolen administrtor neexistuje.', 'ipportdoesntexist' =&gt; 'kombinace ip/portu, kterou jste zvolili, neexistuje.', 'usernamealreadyexists' =&gt; 'uivatelsk jmno %s ji existuje.', 'plausibilitychecknotunderstood' =&gt; 'odpov kontroly vrohodnosti nen srozumiteln.', 'errorwhensaving' =&gt; 'dolo k chyb pi ukldn pole %s', 'hiddenfieldvaluechanged' =&gt; 'hodnota skrytho pole "%s" se zmnila pi pravch nastaven.&lt;br /&gt;&lt;br /&gt;toto obvykle nen velk problm, ale z toho dvodu nelze uloit nastaven.', 'notrequiredpasswordlength' =&gt; 'zadan heslo je pli krtk. zadejte prosm alespo %s znaky.', 'overviewsettingoptionisnotavalidfield' =&gt; 'jejda, pole, kter mlo bt zobrazeno jako volba v pehledu nastaven, nen vjimen povolen typ. z toho mete vinit vvoje. nemlo se stt!', 'pathmaynotcontaincolon' =&gt; 'cesta, kterou jste zadali, nemla obsahovat dvojteku (":"). zadejte sprvnou hodnotu cesty.', 'exception' =&gt; '%s', 'notrequiredpasswordcomplexity' =&gt; 'sloitost zadanho hesla nebyla dostaten.&lt;br /&gt;pokud mte njak dotazy ohledn sloitosti', 'stringerrordocumentnotvalidforlighty' =&gt; 'etzec jako errordocument v lighttpd nefunguje, zadejte prosm cestu k souboru', 'urlerrordocumentnotvalidforlighty' =&gt; 'url adresa jako chybov dokument nefunguje v lighttp, zadejte prosm cestu k souboru', 'invaliderrordocumentvalue' =&gt; 'hodnota udan jako chybov dokument se nezd bt platnm souborem, url nebo etzcem.', 'intvaluetoolow' =&gt; 'zadan slo je pli nzk (pole %s)', 'intvaluetoohigh' =&gt; 'zadan slo je pli vysok (pole %s)', 'phpfpmstillenabled' =&gt; 'php-fpm je aktuln aktivn. ped aktivac fcgid jej deaktivujte', 'fcgidstillenabled' =&gt; 'fcgid je aktuln aktivn. prosm deaktivujte jej ped aktivac php-fpm', 'domains_cantdeletedomainwithaliases' =&gt; 'nemete odstranit domnu, kter se pouv pro alias-domny. nejdve muste aliasy odstranit.', 'user_banned' =&gt; 'v et byl uzamen. pro dal informace kontaktujte svho sprvce.', 'session_timeout' =&gt; 'hodnota je pli nzk', 'session_timeout_desc' =&gt; 'asov limit relace neml bt ni ne 1 minuta.', 'invalidhostname' =&gt; 'nzev hostitele mus bt platn domna. neme bt przdn ani nesm obsahovat pouze mezery', 'operationnotpermitted' =&gt; 'operace nen povolena!', 'featureisdisabled' =&gt; 'funkce %s je zakzna. obrate se na svho poskytovatele slueb.', 'usercurrentlydeactivated' =&gt; 'uivatel %s je momentln deaktivovn', 'setlessthanalreadyused' =&gt; 'nelze nastavit mn prostedk \'%s\', ne tento uivatel ji pouil&lt;br /&gt;', 'stringmustntbeempty' =&gt; 'hodnota pole %s nesm bt przdn', 'sslcertificateismissingprivatekey' =&gt; 'muste zadat soukrom kl k vaemu certifiktu', 'sslcertificatewrongdomain' =&gt; 'dan certifikt nepat k tto domn', 'sslcertificateinvalidcert' =&gt; 'dan obsah certifiktu se nezd bt platnm certifiktem', 'sslcertificateinvalidcertkeypair' =&gt; 'zadan soukrom kl nepat k danmu certifiktu', 'sslcertificateinvalidca' =&gt; 'dan daje certifikt ca se nezdaj bt platnm certifiktem', 'sslcertificateinvalidchain' =&gt; 'daje danho etzce certifikt se nezdaj bt platnm certifiktem', 'givendirnotallowed' =&gt; 'zadan adres v poli %s nen povolen.', 'sslredirectonlypossiblewithsslipport' =&gt; 'pouit let\'s encrypt je mon pouze v ppad, e domna piazenou alespo jednu ssl-povolenou kombinaci ip/port.', 'fcgidstillenableddeadlock' =&gt; 'fcgid je aktuln aktivn.&lt;br /&gt;prosm deaktivujte ho ped pepnutm na jin webov server ne apache2 nebo lighttpd', 'send_report_title' =&gt; 'odeslat zprvu chyb', 'send_report_desc' =&gt; 'dkujeme, e jste nahlsili tuto chybu pomohli nm vylepit froxlor.&lt;br /&gt;toto je e-mail, kter bude odesln froxlor vvoji:', 'send_report' =&gt; 'odeslat hlen', 'send_report_error' =&gt; 'chyba pi odesln hlen: &lt;br /&gt;%s', 'notallowedtouseaccounts' =&gt; 'v et neumouje pouvat imap/pop3. e-mailov ty nelze pidat.', 'cannotdeletehostnamephpconfig' =&gt; 'tato konfigurace php je pouvna froxlor-vhost nelze ji odstranit.', 'cannotdeletedefaultphpconfig' =&gt; 'tato konfigurace php je nastavena jako vchoz nelze ji odstranit.', 'passwordshouldnotbeusername' =&gt; 'heslo nemlo bt stejn jako uivatelsk jmno.', 'no_phpinfo' =&gt; 'je nm lto, phpinfo() nelze pest', 'moveofcustomerfailed' =&gt; 'pesun zkaznka vybranho administrtora/prodejce selhal. mjte na pamti, e vechny ostatn zmny zkaznka byly spn aplikovny v tto fzi.&lt;br&gt;&lt;br&gt;zprva chyb: %s', 'domain_import_error' =&gt; 'pi importu domn dolo k chyb: %s', 'fcgidandphpfpmnogoodtogether' =&gt; 'fcgid php-fpm nelze souasn aktivovat', 'no_apcuinfo' =&gt; 'dn informace cache nejsou k dispozici. apcu se nezd bt sputna.', 'no_opcacheinfo' =&gt; 'dn informace opcache nejsou k dispozici. opcache se nezd bt natena.', 'inactive_opcacheinfo' =&gt; 'opcache se zd bt nainstalovna, ale nen aktivovno.', 'nowildcardwithletsencrypt' =&gt; 'let\'s encrypt neum zpracovvat wildcard domny pomoc acme froxlor (vyaduje dns-challenge), omlouvme se. nastavte prosm serveralias na www nebo jej zcela zakate', 'customized_version' =&gt; 'vypad to, e vae instalace froxlor byla upravena, na pravy neposkytuijeme podporu, je nm lto.', 'autoupdate_0' =&gt; 'neznm chyba', 'autoupdate_1' =&gt; 'nastaven php allow_url_fopen je zakzno. autoupdate mus bt povolen v php.ini', 'autoupdate_2' =&gt; 'php zip rozen nebylo nalezeno, ujistte se, e je nainstalovno aktivovno', 'autoupdate_4' =&gt; 'archiv froxlor nemohl bt uloen na disk :(', 'autoupdate_5' =&gt; 'version.froxlor.org vrtil nepijateln hodnoty :(', 'autoupdate_6' =&gt; 'jejda, ke staen nebyla zadna dn (platn) verze :(', 'autoupdate_7' =&gt; 'staen archiv nebyl nalezen :(', 'autoupdate_8' =&gt; 'archiv nelze extrahovat :(', 'autoupdate_9' =&gt; 'staen soubor neproel kontrolou integrity. zkuste prosm aktualizovat znovu.', 'autoupdate_10' =&gt; 'minimln podporovan verze php je 7.4.0', 'autoupdate_11' =&gt; 'webupdate je zakzn', 'mailaccistobedeleted' =&gt; 'jin et se stejnm nzvem (%s) je v souasn dob smazn, proto jej nelze v tuto chvli pidat.', 'customerhasongoingexportjob' =&gt; 'na zpracovn ji ek loha exportu dat, bute prosm trpliv.', 'exportfunctionnotenabled' =&gt; 'funkce exportu nen povolena', 'dns_domain_nodns' =&gt; 'dns nen pro tuto domnu povoleno', 'dns_content_empty' =&gt; 'nebyl zadn dn obsah', 'dns_content_invalid' =&gt; 'neplatn obsah dns', 'dns_arec_noipv4' =&gt; 'neplatn ip adresa pro a-zznam', 'dns_aaaarec_noipv6' =&gt; 'neplatn ip adresa pro zadan zznam aaaa', 'dns_mx_prioempty' =&gt; 'byla zadna neplatn mx priorita', 'dns_mx_needdom' =&gt; 'hodnota mx obsahu mus bt platn nzev domny', 'dns_mx_noalias' =&gt; 'hodnota mx neme bt poloka cname.', 'dns_cname_invaliddom' =&gt; 'neplatn nzev domny pro zznam cname', 'dns_cname_nomorerr' =&gt; 'zznam zdroje se stejnm nzvem zznamu ji existuje. nelze jej pout jako cname.', 'dns_other_nomorerr' =&gt; 'zznam cname se stejnm nzvem zznamu ji existuje. nelze jej pout pro jin typ.', 'dns_ns_invaliddom' =&gt; 'neplatn nzev domny pro ns zznam', 'dns_srv_prioempty' =&gt; 'byla zadna neplatn srv priorita', 'dns_srv_invalidcontent' =&gt; 'neplatn obsah srv mus obsahovat vhu, port cl, nap.: 5 5060 sipserver.example.com.', 'dns_srv_needdom' =&gt; 'hodnota srv cle mus bt platn nzev domny', 'dns_srv_noalias' =&gt; 'hodnota srv cle neme bt poloka cname.', 'dns_duplicate_entry' =&gt; 'zznam ji existuje', 'dns_notfoundorallowed' =&gt; 'domna nebyla nalezena nebo nemte oprvnn', 'domain_nopunycode' =&gt; 'nesmte specifikovat punycode (idna). domna bude automaticky pevedena', 'domain_noipaddress' =&gt; 'nelze pidat ip adresu jako domnu', 'dns_record_toolong' =&gt; 'zznamy/popisky mohou mt pouze 63 znak', 'noipportgiven' =&gt; 'nen zadn dn ip/port', 'nosslippportgiven' =&gt; 'pi povolen ssl je teba zvolit ssl ip/port', 'jsonextensionnotfound' =&gt; 'tato funkce vyaduje rozen php-json.', 'cannotdeletesuperadmin' =&gt; 'prvnho sprvce nelze odstranit.', 'no_wwwcnamae_ifwwwalias' =&gt; 'nelze nastavit cname zznam pro "www" jako domnu pro generovn www-alias. zmte prosm nastaven bu na "no alias" nebo "wildcard alias"', 'local_group_exists' =&gt; 'tato skupina ji v systmu existuje.', 'local_group_invalid' =&gt; 'zadan nzev skupiny je neplatn', 'invaliddnsforletsencrypt' =&gt; 'dns domn neobsahuje dnou z vybranch ip adres. vytvoen let\'s encryp certifiktu nen mon.', 'notallowedphpconfigused' =&gt; 'pokus pouit php konfigurace, kter nen piazena zkaznkovi', 'pathmustberelative' =&gt; 'uivatel nem oprvnn specifikovat adrese mimo domovsk adres zkaznka. zadejte relativn cestu (bez vodnho /).', 'mysqlserverstillhasdbs' =&gt; 'databzov server nelze odstranit ze seznamu povolench zkaznk, protoe na nm stle existuj databze.', 'domaincannotbeedited' =&gt; 'nemte oprvnn upravovat domnu %s', 'invalidcronjobintervalvalue' =&gt; 'interval cronjobu mus bt jeden z: %s', 'phpgdextensionnotavailable' =&gt; 'rozen php gd nen dostupn. nelze ovit data obrzk', '2fa_wrongcode' =&gt; 'zadan kd nen platn', 'gnupgextensionnotavailable' =&gt; 'rozen php gnupg nen dostupn. nelze ovit pgp veejn kl', 'invalidpgppublickey' =&gt; 'pgp veejn kl nen platn', 'invalid_validtime' =&gt; 'platn v sekundch bt pouze mezi 10 120', 'customerphpenabledbutnoconfig' =&gt; 'zkaznk php aktivovn, ale nebyla vybrna dn konfigurace php.', ], 'extras' =&gt; [ 'description' =&gt; 'zde mete pidat nkter doplky, napklad ochranu adres.&lt;br /&gt;po kad zmn bude systm potebovat urit as, aby aplikoval nov nastaven.', 'directoryprotection_add' =&gt; 'pidat ochranu adrese', 'view_directory' =&gt; 'zobrazit obsah adrese', 'pathoptions_add' =&gt; 'pidat monosti cesty', 'directory_browsing' =&gt; 'prohlen obsahu adrese', 'pathoptions_edit' =&gt; 'upravit monosti cesty', 'error404path' =&gt; '404', 'error403path' =&gt; '403', 'error500path' =&gt; '500', 'error401path' =&gt; '401', 'errordocument404path' =&gt; 'errordocument 404', 'errordocument403path' =&gt; 'errordocument 403', 'errordocument500path' =&gt; 'errordocument 500', 'errordocument401path' =&gt; 'errordocument 401', 'execute_perl' =&gt; 'spustit perl/cgi', 'htpasswdauthname' =&gt; 'dvod oven (authname)', 'directoryprotection_edit' =&gt; 'upravit ochranu adrese', 'export' =&gt; 'vytvoit vpis dat', 'dump_web' =&gt; 'zahrnout webov data', 'dump_mail' =&gt; 'zahrnout e-mailov data', 'dump_dbs' =&gt; 'zahrnout databze', 'path_protection_label' =&gt; '&lt;strong class="text-danger"&gt;dleit&lt;/strong&gt;', 'path_protection_info' =&gt; 'drazn doporuujeme chrnit danou cestu, viz "extra" -&gt; "ochrana adres"', ], 'ftp' =&gt; [ 'description' =&gt; 'zde mete vytvoit zmnit sv ftp ty.&lt;br /&gt;zmny jsou provedeny okamit ty mohou bt pouity okamit.', 'account_add' =&gt; 'vytvoit et', 'account_edit' =&gt; 'upravit ftp et', 'editpassdescription' =&gt; 'nastavte nov heslo nebo ponechte przdn pro zanechn stvajcho.', ], 'gender' =&gt; [ 'title' =&gt; 'nzev', 'male' =&gt; 'pan', 'female' =&gt; 'pan', 'undef' =&gt; '', ], 'imprint' =&gt; 'prvn ustanoven', 'index' =&gt; [ 'customerdetails' =&gt; 'podrobnosti zkaznkovi', 'accountdetails' =&gt; 'nastaven tu', ], 'integrity_check' =&gt; [ 'databasecharset' =&gt; 'sada znak databze (mla bt utf-8)', 'domainiptable' =&gt; 'ip &amp;lt;&amp;dash;&amp;gt; reference domn', 'subdomainsslredirect' =&gt; 'falen pznak pesmrovn ssl pro non-ssl domny', 'froxlorlocalgroupmemberforfcgidphpfpm' =&gt; 'froxlor-uivatelve skupinch zkaznk (pro fcgid/php-fpm)', 'webservergroupmemberforfcgidphpfpm' =&gt; 'webov uivatel skupin zkaznk (pro fcgid/php-fpm)', 'subdomainletsencrypt' =&gt; 'hlavn domny bez ssl portu nemaj dn subdomny aktivnm pesmrovnm ssl', ], 'logger' =&gt; [ 'date' =&gt; 'datum', 'type' =&gt; 'typ', 'action' =&gt; 'akce', 'user' =&gt; 'uivatel', 'truncate' =&gt; 'vyprzdnit protokol', 'reseller' =&gt; 'pekupnk', 'admin' =&gt; 'administrtor', 'cron' =&gt; 'cronjob', 'login' =&gt; 'pihlen', 'intern' =&gt; 'intern', 'unknown' =&gt; 'neznm', ], 'login' =&gt; [ 'username' =&gt; 'uivatelsk jmno', 'password' =&gt; 'heslo', 'language' =&gt; 'jazyk', 'login' =&gt; 'pihlsit se', 'logout' =&gt; 'odhlsit se', 'profile_lng' =&gt; 'jazyk profilu', 'welcomemsg' =&gt; 'pro pstup k vaemu tu se pihlaste.', 'forgotpwd' =&gt; 'zapomnli jste heslo?', 'presend' =&gt; 'obnovit heslo', 'email' =&gt; 'e-mailov adresa', 'remind' =&gt; 'obnovit heslo', 'usernotfound' =&gt; 'uivatel nebyl nalezen!', 'backtologin' =&gt; 'zpt na pihlen', 'combination_not_found' =&gt; 'kombinace uivatele e-mailov adresy nenalezena.', '2fa' =&gt; 'dvoufzov oven (2fa)', '2facode' =&gt; 'zadejte prosm 2fa kd', '2faremember' =&gt; 'dvovat prohlei', ], 'mails' =&gt; [ 'pop_success' =&gt; [ 'mailbody' =&gt; 'dobr den,\\n\\nv e-mailov et {email}\\nbyl spn vytvoen.\\n\\ntoto je automaticky vytvoen\\ne-mail, prosm neodpovdejte na nj!\\n\\nv sprvce', 'subject' =&gt; 'e-mailov et byl spn nastaven', ], 'createcustomer' =&gt; [ 'mailbody' =&gt; 'dobr den {salutation},\\n\\nzde je v et:\\n\\nuivatelsk jmno: {username}\\nheslo: {password}\\n\\ndkujeme,\\nv sprvce', 'subject' =&gt; 'informace tu', ], 'pop_success_alternative' =&gt; [ 'mailbody' =&gt; 'dobr den {salutation},\\n\\nv e-mailov et {email}\\nbyl spn vytvoen.\\nvae heslo je {password}.\\n\\ntoto je automaticky vytvoen e-mail\\n, prosm neodpovdejte na to!\\n\\nyours upmn, v sprvce', 'subject' =&gt; 'e-mailov et byl spn nastaven', ], 'password_reset' =&gt; [ 'subject' =&gt; 'obnoven hesla', 'mailbody' =&gt; 'dobr den, {salutation},\\n\\nje zde v odkaz pro nastaven novho hesla. tento odkaz je platn po dobu nsledujcch 24 hodin.\\n\\n{link}\\n\\ndkujeme,\\nv sprvce', ], 'new_database_by_customer' =&gt; [ 'subject' =&gt; '[froxlor] byla vytvoena nov databze', 'mailbody' =&gt; 'dobr den {cust_name}, jste prv pidali novou databzi. zde jsou zadan informace: nzev databze: {db_name} heslo: {db_pass} popis: {db_desc} hostitel databze: {db_srv} phpmyadmin: {pma_uri} pozdravem v sprvce', ], 'new_ftpaccount_by_customer' =&gt; [ 'subject' =&gt; 'nov ftp uivatel vytvoen', 'mailbody' =&gt; 'dobr den {cust_name}, jste prv pidali novho ftp uivatele. zde jsou zadan informace: uivatelsk jmno: {usr_name} heslo: {usr_pass} cesta: {usr_path} ach upmn, v sprvce', ], 'trafficmaxpercent' =&gt; [ 'mailbody' =&gt; 'ven/ {salutation},\\n\\njste pouili {trafficused} z dostupnho provozu {traffic}.\\ntoto je vce ne {max_percent}%%.\\n\\nvae upmn sprvce', 'subject' =&gt; 'dosaen limitu provozu', ], 'diskmaxpercent' =&gt; [ 'mailbody' =&gt; 'ven/ {salutation},\\n\\njste pouili {diskused} ze svho dostupnho {diskavailable} disku.\\ntoto je vce ne {max_percent}%%.\\n\\nvae upmn sprvce', 'subject' =&gt; 'dosaen limitu na disku', ], '2fa' =&gt; [ 'mailbody' =&gt; 'dobr den,\\n\\nv 2fa pihlaovac kd je: {code}.\\n\\ntoto je automaticky vytvoen\\ne-mail, prosm neodpovdejte na to!\\n\\nv sprvce', 'subject' =&gt; 'froxlor - 2fa kd', ], ], 'menue' =&gt; [ 'main' =&gt; [ 'main' =&gt; 'hlavn', 'changepassword' =&gt; 'zmnit heslo', 'changelanguage' =&gt; 'zmnit jazyk', 'username' =&gt; 'pihlen jako: ', 'changetheme' =&gt; 'zmnit motiv', 'apihelp' =&gt; 'npovda api', 'apikeys' =&gt; 'api kle', ], 'email' =&gt; [ 'email' =&gt; 'email', 'emails' =&gt; 'adresy', 'webmail' =&gt; 'webmail', 'emailsoverview' =&gt; 'pehled e-mailovch domn', ], 'mysql' =&gt; [ 'mysql' =&gt; 'mysql', 'databases' =&gt; 'databze', 'phpmyadmin' =&gt; 'phpmyadmin', ], 'domains' =&gt; [ 'domains' =&gt; 'domny', 'settings' =&gt; 'pehled domn', ], 'ftp' =&gt; [ 'ftp' =&gt; 'ftp', 'accounts' =&gt; 'ty', 'webftp' =&gt; 'webftp', ], 'extras' =&gt; [ 'extras' =&gt; 'extra', 'directoryprotection' =&gt; 'ochrana adrese', 'pathoptions' =&gt; 'monosti cesty', 'export' =&gt; 'export dat', ], 'traffic' =&gt; [ 'traffic' =&gt; 'provoz', 'current' =&gt; 'aktuln msc', 'overview' =&gt; 'celkov provoz', ], 'phpsettings' =&gt; [ 'maintitle' =&gt; 'php konfigurace', 'fpmdaemons' =&gt; 'verze php-fpm', ], 'logger' =&gt; [ 'logger' =&gt; 'systmov protokol', ], ], 'message' =&gt; [ 'norecipients' =&gt; 'nebyl odesln dn e-mail, protoe v databzi nejsou dn pjemci', 'success' =&gt; 'zprva byla spn odeslna pjemcm %s', ], 'mysql' =&gt; [ 'databasename' =&gt; 'uivatel/jmno databze', 'databasedescription' =&gt; 'popis databze', 'database_create' =&gt; 'vytvoit databzi', 'description' =&gt; 'zde mete vytvoit zmnit databze mysql.&lt;br /&gt;zmny jsou provedeny okamit databze bt pouita okamit.&lt;br /&gt;v menu na lev stran najdete nstroj phpmyadmin, pomoc kterho mete snadno spravovat svou databzi.&lt;br /&gt;&lt;br /&gt;pro pouit vaich databz svch vlastnch php-skriptech pouijte nsledujc nastaven: (data &lt;i&gt;kurzvou&lt;/i&gt; je teba zmnit na ekvivalenty, kter jste zadali!&lt;br /&gt;nzev hostitele: &lt;b&gt;&lt;sql_host&gt;&lt;/b&gt;&lt;br /&gt;uivatelsk jmno: &lt;b&gt;&lt;i&gt;nzev databze&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;heslo: &lt;b&gt;&lt;i&gt;heslo, kter jste si vybrali&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;databze: &lt;b&gt;&lt;i&gt;databzov nzev&lt;/i&gt;&lt;/b&gt;', 'mysql_server' =&gt; 'server mysql', 'database_edit' =&gt; 'upravit databzi', 'size' =&gt; 'velikost', 'privileged_user' =&gt; 'oprvnn databzov uivatel', 'privileged_passwd' =&gt; 'heslo pro oprvnnho uivatele', 'unprivileged_passwd' =&gt; 'heslo pro neoprvnnho uivatele', 'mysql_ssl_ca_file' =&gt; 'certifikt ssl serveru', 'mysql_ssl_verify_server_certificate' =&gt; 'ovit certifikt ssl serveru', 'globaluserinfo' =&gt; 'pro pstup k databzm mete navc pout vae froxlor pihlen (uivatel: %s), kter automaticky pstup ke vem databzm.&lt;br /&gt;doporuujeme &lt;b&gt;ne&lt;/b&gt; pout pro aplikace, pouze pro sprvu (nap. pes phpmyadmin).', 'edit_global_user' =&gt; 'upravit administrtora', ], 'opcacheinfo' =&gt; [ 'generaltitle' =&gt; 'obecn informace', 'resetcache' =&gt; 'resetovat opcache', 'version' =&gt; 'verze opcache', 'phpversion' =&gt; 'verze php', 'runtimeconf' =&gt; 'spustiteln konfigurace', 'start' =&gt; 'as sputn', 'lastreset' =&gt; 'posledn restart', 'oomrestarts' =&gt; 'poet restart oom', 'hashrestarts' =&gt; 'poet restart hash', 'manualrestarts' =&gt; 'manuln poet restart', 'hitsc' =&gt; 'poet zsah', 'missc' =&gt; 'nevyuit poet', 'blmissc' =&gt; 'poet zmekanch zznam na ern listin', 'status' =&gt; 'stav', 'never' =&gt; 'nikdy', 'enabled' =&gt; 'opcache povoleno', 'cachefull' =&gt; 'mezipam je pln', 'restartpending' =&gt; 'ek na restart', 'restartinprogress' =&gt; 'probh restart', 'cachedscripts' =&gt; 'poet skript v mezipamti', 'memusage' =&gt; 'vyuit pamti', 'totalmem' =&gt; 'celkov pam', 'usedmem' =&gt; 'vyuit pam', 'freemem' =&gt; 'voln pam', 'wastedmem' =&gt; 'promarnn pam', 'maxkey' =&gt; 'maximln poet kl', 'usedkey' =&gt; 'pouit kle', 'wastedkey' =&gt; 'promarnn kle', 'strinterning' =&gt; 'string interning', 'strcount' =&gt; 'poet etzc', 'keystat' =&gt; 'statistika kl v mezipamti', 'used' =&gt; 'vyuito', 'free' =&gt; 'voln', 'blacklist' =&gt; 'ern listina', 'novalue' =&gt; '&lt;i&gt;dn hodnota&lt;/i&gt;', 'true' =&gt; '&lt;i&gt;true&lt;/i&gt;', 'false' =&gt; '&lt;i&gt;false&lt;/i&gt;', 'funcsavail' =&gt; 'dostupn funkce', ], 'panel' =&gt; [ 'edit' =&gt; 'upravit', 'delete' =&gt; 'smazat', 'create' =&gt; 'vytvoit', 'save' =&gt; 'uloit', 'yes' =&gt; 'ano', 'no' =&gt; 'ne', 'emptyfornochanges' =&gt; 'przdn pro dn zmny', 'emptyfordefault' =&gt; 'przdn pro vchoz nastaven', 'path' =&gt; 'cesta', 'toggle' =&gt; 'pepna', 'next' =&gt; 'dal', 'dirsmissing' =&gt; 'nelze najt nebo pest adres!', 'unlimited' =&gt; '', 'urloverridespath' =&gt; 'url (pepsn cesty)', 'pathorurl' =&gt; 'cesta nebo url', 'ascending' =&gt; 'vzestupn', 'descending' =&gt; 'sestupn', 'search' =&gt; 'vyhledat', 'used' =&gt; 'vyuito', 'translator' =&gt; 'peklada', 'reset' =&gt; 'zahodit zmny', 'pathdescription' =&gt; 'pokud sloka neexistuje, bude vytvoena automaticky.', 'pathdescriptionex' =&gt; '&lt;br /&gt;&lt;br /&gt;&lt;span class="text-danger"&gt;upozornn:&lt;/span&gt; cesta &lt;code&gt;/&lt;/code&gt; nen povolena z dvodu administrativnho nastaven, bude automaticky nastaveno na &lt;code&gt;/chosen.subdomain.tld/&lt;/code&gt; pokud nen nastaveno na jin adres.', 'pathdescriptionsubdomain' =&gt; 'pokud sloka neexistuje, bude vytvoena automaticky.&lt;br /&gt;&lt;br /&gt;pokud chcete pesmrovat na jinou domnu, mus tento zznam zat http:// nebo https://.&lt;br /&gt;&lt;br /&gt;pokud url kon / je povaovna za sloku, pokud ne, je povaovna za soubor.', 'back' =&gt; 'zpt', 'reseller' =&gt; 'pekupnk', 'admin' =&gt; 'admin', 'customer' =&gt; 'zkaznk/zkaznci', 'send' =&gt; 'odeslat', 'nosslipsavailable' =&gt; 'v souasn dob neexistuj dn kombinace ssl ip/port pro tento server', 'backtooverview' =&gt; 'zpt na pehled', 'dateformat' =&gt; 'rrrr-mm-dd', 'dateformat_function' =&gt; 'r-m-d', 'timeformat_function' =&gt; 'h:i:s', 'default' =&gt; 'vchoz', 'never' =&gt; 'nikdy', 'active' =&gt; 'aktivn', 'please_choose' =&gt; 'vyberte prosm', 'allow_modifications' =&gt; 'povolit zmny', 'megabyte' =&gt; 'megabyte', 'not_supported' =&gt; 'nepodporovno v: ', 'view' =&gt; 'zobrazen', 'toomanydirs' =&gt; 'pli mnoho podadres. vrate se zpt na manuln vbr cesty.', 'abort' =&gt; 'peruit', 'not_activated' =&gt; 'nen aktivovno', 'off' =&gt; 'vyp.', 'options' =&gt; 'monosti', 'neverloggedin' =&gt; 'dosud dn pihlen', 'descriptionerrordocument' =&gt; 'me bt adresa url, cesta k souboru nebo jen etzec zabalen kolem " "&lt;br /&gt;ponechte przdn pro pouit vchoz hodnoty serveru.', 'unlock' =&gt; 'odemknout', 'theme' =&gt; 'motiv', 'variable' =&gt; 'promnn', 'description' =&gt; 'popis', 'cancel' =&gt; 'zruit', 'ssleditor' =&gt; 'nastaven ssl pro tuto domnu', 'ssleditor_infoshared' =&gt; 'v souasn dob pouv certifikt rodiovsk domny', 'ssleditor_infoglobal' =&gt; 'v souasn dob pouv globln certifikt', 'dashboard' =&gt; 'nstnka', 'assigned' =&gt; 'piazeno', 'available' =&gt; 'k dispozici', 'news' =&gt; 'novinky', 'newsfeed_disabled' =&gt; 'novinky jsou zakzny. klepnutm na ikonu pravy pejdete nastaven.', 'ftpdesc' =&gt; 'popis ftp', 'letsencrypt' =&gt; 'pouv let\'s encrypt', 'set' =&gt; 'aplikovat', 'shell' =&gt; 'konzole', 'exportpath' =&gt; [ 'title' =&gt; 'clov cesta pro exportovan data', 'description' =&gt; 'toto je cesta, kde bude exporotovan archiv uloen. pokud jsou webov data zahrnuta, vechny soubory z domovskho adrese jsou uloeny mimo sloku zadanou zde.', ], 'export_pgp_public_key' =&gt; [ 'title' =&gt; 'veejn pgp kl pro ifrovn', 'description' =&gt; 'toto je veejn pgp kl, kter bude pouit k zaifrovn exportu. pokud nechte toto pole przdn, export nebude zaifrovn.', ], 'pgp_public_key' =&gt; 'veejn pgp kl', 'none_value' =&gt; 'dn', 'viewlogs' =&gt; 'zobrazit protokoly', 'not_configured' =&gt; 'systm jet nen nakonfigurovn. kliknte zde pro pechod konfigurace.', 'ihave_configured' =&gt; 'konfiguroval jsem sluby', 'system_is_configured' =&gt; '&lt;i class="fa-solid fa-circle-exclamation me-1"&gt;&lt;/i&gt;systm je ji nastaven jako konfigurovan', 'settings_before_configuration' =&gt; 'ujistte se, e jste upravili nastaven ped konfigurac slueb zde', 'image_field_delete' =&gt; 'odstranit stvajc obrzek', 'usage_statistics' =&gt; 'vyuit zdroj', 'security_question' =&gt; 'bezpenostn otzka', 'listing_empty' =&gt; 'nebyly nalezeny dn zznamy', 'unspecified' =&gt; 'nespecifikovno', 'settingsmode' =&gt; 'reim', 'settingsmodebasic' =&gt; 'zkladn', 'settingsmodeadvanced' =&gt; 'rozen', 'settingsmodetoggle' =&gt; 'reim pepnn', 'modalclose' =&gt; 'zavt', 'managetablecolumnsmodal' =&gt; [ 'title' =&gt; 'sprva sloupc tabulky', 'description' =&gt; 'zde si mete pizpsobit viditeln sloupce', ], 'mandatoryfield' =&gt; 'pole je povinn', 'select_all' =&gt; 'vybrat ve', 'unselect_all' =&gt; 'odznait ve', 'searchtablecolumnsmodal' =&gt; [ 'title' =&gt; 'hledat v polch', 'description' =&gt; 'vyberte pole, kterm chcete vyhledat' ], 'upload_import' =&gt; 'nahrt importovat', 'profile' =&gt; 'mj profil', 'use_checkbox_for_unlimited' =&gt; 'hodnota 0 deaktivuje tento prostedek. zakrtvac polko vpravo umouje neomezen pouit.', ], 'phpfpm' =&gt; [ 'vhost_httpuser' =&gt; 'mstn uivatel pro php-fpm (froxlor vhost)', 'vhost_httpgroup' =&gt; 'mstn skupina pro php-fpm (froxlor vhost)', 'ownvhost' =&gt; [ 'title' =&gt; 'povolit php-fpm pro froxlor vhost', 'description' =&gt; 'pokud je povoleno, bude froxlor sputn tak pod mstnm uivatelem', ], 'use_mod_proxy' =&gt; [ 'title' =&gt; 'pout mod_proxy / mod_proxy_fcgi', 'description' =&gt; '&lt;strong class="text-danger"&gt;pi pouvn debianu 9.x (stretch) nebo novjho&lt;/strong&gt;mus bt povoleno pouit php-fpm pes mod_proxy_fcgi. vyaduje alespo apache-2.4.9', ], 'ini_flags' =&gt; 'zadejte mon &lt;strong&gt;php_flag&lt;/strong&gt; pro php.ini. jeden zznam na dek', 'ini_values' =&gt; 'zadejte monou &lt;strong&gt;php_value&lt;/strong&gt; pro php.ini. jeden zznam na dek', 'ini_admin_flags' =&gt; 'zadejte mon &lt;strong&gt;php_admin_flag&lt;/strong&gt; pro php.ini. jeden zznam na dek', 'ini_admin_values' =&gt; 'zadejte monou &lt;strong&gt;php_value&lt;/strong&gt; pro php.ini. jeden zznam na dek', ], 'privacy' =&gt; 'zsady ochrany soukrom', 'pwdreminder' =&gt; [ 'success' =&gt; 'obnoven hesla bylo spn poadovno. postupujte podle pokyn v e-mailu, kter jste obdreli.', 'notallowed' =&gt; 'neznm uivatel nebo obnoven hesla je zakzno', 'changed' =&gt; 'vae heslo bylo spn aktualizovno. nyn se mete pihlsit pomoc novho hesla.', 'wrongcode' =&gt; 'je nm lto, v aktivan kd neexistuje nebo ji vyprel.', 'choosenew' =&gt; 'nastavit nov heslo', ], 'question' =&gt; [ 'question' =&gt; 'bezpenostn otzka', 'admin_customer_reallydelete' =&gt; 'opravdu chcete odstranit zkaznka %s? tuto akci nelze vrtit zpt!', 'admin_domain_reallydelete' =&gt; 'opravdu chcete odstranit domnu %s?&lt;br&gt;&lt;span class="text-danger"&gt;&lt;strong&gt;poznmka:&lt;/strong&gt; vechny subdomny, ftp-ty e-mailov adresy/ty spojen touto domnou budou odstranny!&lt;/span&gt;', 'admin_domain_reallydisablesecuritysetting' =&gt; 'opravdu chcete zakzat toto nastaven zabezpeen openbasedir?', 'admin_admin_reallydelete' =&gt; 'opravdu chcete odstranit sprvce %s? kad zkaznk domna budou znovu piazeny k vaemu tu.', 'admin_template_reallydelete' =&gt; 'opravdu chcete odstranit ablonu\'%s\'?', 'domains_reallydelete' =&gt; 'opravdu chcete odstranit domnu %s?', 'email_reallydelete' =&gt; 'opravdu chcete odstranit e-mailovou adresu %s?', 'email_reallydelete_account' =&gt; 'opravdu chcete smazat e-mailov et %s?', 'email_reallydelete_forwarder' =&gt; 'opravdu chcete odstranit peposlatele %s?', 'extras_reallydelete' =&gt; 'opravdu chcete odstranit ochranu adrese pro %s?', 'extras_reallydelete_pathoptions' =&gt; 'opravdu chcete odstranit monosti cesty pro %s?', 'extras_reallydelete_export' =&gt; 'opravdu chcete peruit plnovanou prci na exportu?', 'ftp_reallydelete' =&gt; 'opravdu chcete odstranit ftp et %s?', 'mysql_reallydelete' =&gt; 'opravdu chcete odstranit databzi %s? tuto akci nelze vrtit zpt!', 'admin_configs_reallyrebuild' =&gt; 'opravdu chcete znovu sestavit vechny konfiguran soubory?', 'admin_customer_alsoremovefiles' =&gt; 'odstranit tak uivatelsk soubory?', 'admin_customer_alsoremovemail' =&gt; 'zcela odstranit e-mailov data ze souborovho systmu?', 'admin_customer_alsoremoveftphomedir' =&gt; 'odebrat tak domovsk adres ftp uivatele?', 'admin_ip_reallydelete' =&gt; 'opravdu chcete odstranit ip adresu %s?', 'admin_domain_reallydocrootoutofcustomerroot' =&gt; 'jste si jisti, e chcete, aby koen dokumentu pro tuto domnu nebyl v rmci koene zkaznka?', 'admin_counters_reallyupdate' =&gt; 'opravdu chcete pepotat vyuit prostedk?', 'admin_cleartextmailpws_reallywipe' =&gt; 'opravdu chcete vymazat vechna neifrovan hesla e-mailovho tu z tabulky mail_users? tuto akci nelze vrtit zpt! nastaven neifrovanch e-mailovch hesel bude tak nastaveno na vypnut', 'logger_reallytruncate' =&gt; 'opravdu chcete zredukovat tabulku "%s"?', 'admin_quotas_reallywipe' =&gt; 'opravdu chcete vymazat vechny kvty v tabulce mail_users? toto nelze vrtit zpt!', 'admin_quotas_reallyenforce' =&gt; 'opravdu chcete vynutit vchoz kvtu pro vechny uivatele? toto nelze vrtit zpt!', 'phpsetting_reallydelete' =&gt; 'opravdu chcete odstranit tato nastaven? vechny domny, kter v souasn dob pouvaj tato nastaven, budou zmnny na vchoz nastaven.', 'fpmsetting_reallydelete' =&gt; 'opravdu chcete smazat tato nastaven php-fpm? vechny php konfigurace, kter v souasn dob pouvaj tato nastaven, budou zmnny na vchoz nastaven.', 'customer_reallyunlock' =&gt; 'opravdu chcete odemknout zkaznka %s?', 'admin_integritycheck_reallyfix' =&gt; 'opravdu chcete zkusit automaticky opravit vechny problmy integritou databze?', 'plan_reallydelete' =&gt; 'opravdu chcete odstranit pln hostovn %s?', 'apikey_reallydelete' =&gt; 'opravdu chcete odstranit tento api kl?', 'apikey_reallyadd' =&gt; 'opravdu chcete vytvoit nov api kl?', 'dnsentry_reallydelete' =&gt; 'opravdu chcete odstranit tento zznam zny?', 'certificate_reallydelete' =&gt; 'opravdu chcete odstranit tento certifikt?', 'cache_reallydelete' =&gt; 'opravdu chcete vymazat mezipam?', 'please_enter_otp' =&gt; 'zadejte prosm 2fa kd', 'admin_mysqlserver_reallydelete' =&gt; 'opravdu chcete smazat tento mysql-server?', ], 'redirect_desc' =&gt; [ 'rc_default' =&gt; 'vchoz', 'rc_movedperm' =&gt; 'trvale pesunuto', 'rc_found' =&gt; 'nalezeno', 'rc_seeother' =&gt; 'viz ostatn', 'rc_tempred' =&gt; 'doasn pesmrovn', ], 'serversettings' =&gt; [ 'session_timeout' =&gt; [ 'title' =&gt; 'vypren platnosti relace', 'description' =&gt; 'jak dlouho mus bt uivatel neaktivn, ne bude relace neplatn (sekundy)?', ], 'accountprefix' =&gt; [ 'title' =&gt; 'prefix zkaznka', 'description' =&gt; 'jak prefix mly mt zkaznick ty?', ], 'mysqlprefix' =&gt; [ 'title' =&gt; 'sql prefix', 'description' =&gt; 'jak prefix ml mt mysql ty?&lt;/br&gt;pouijte "random" jako hodnotu k zskn trojmstnho nhodnho prefixu&lt;/br&gt;pouijte "dbname" jako hodnotu, pole nzvu databze je pouito spolu nzvem zkaznka jako prefix.', ], 'ftpprefix' =&gt; [ 'title' =&gt; 'ftp prefix', 'description' =&gt; 'jak prefix mly mt ftp ty?&lt;br/&gt;&lt;b&gt;pokud toto zmnte, muste tak zmnit quota sql query v konfiguranm souboru ftp serveru, pokud jej pouvte!&lt;/b&gt; ', ], 'documentroot_prefix' =&gt; [ 'title' =&gt; 'domovsk adres', 'description' =&gt; 'kde mly bt uloeny vechny domovsk adrese?', ], 'logfiles_directory' =&gt; [ 'title' =&gt; 'adres soubor protokolu', 'description' =&gt; 'kde maj bt uloeny vechny soubory protokol?', ], 'logfiles_script' =&gt; [ 'title' =&gt; 'vlastn skript pro odesln soubor protokolu do', 'description' =&gt; 'zde mete zadat skript pout zstupn symboly &lt;strong&gt;{logfile}, {domain} {customer}&lt;/strong&gt; v ppad poteby. pokud jej chcete pout, budete muset aktivovat tak &lt;strong&gt;nastaven log webserveru&lt;/strong&gt;. nen zapoteb dn pedem stanoven pipe-znak.', ], 'logfiles_format' =&gt; [ 'title' =&gt; 'formt pstupovho protokolu', 'description' =&gt; 'zde zadejte vlastn formt logu podle specifikac webovch server, ponechte przdn pro vchoz. v zvislosti na vaem formtu mus bt etzec uveden.&lt;br/&gt;pokud je pouito nginx, bude vypadat jako &lt;i&gt;log_format frx_custom {configured_value}&lt;/i&gt;.&lt;br/&gt;pokud je pouito apache, bude vypadat jako &lt;i&gt;logformat {configured_value} frx_custom&lt;/i&gt;.&lt;br/&gt;&lt;strong&gt;pozornost&lt;/strong&gt;: kd nebude zkontrolovn pro dn chyby. pokud obsahuje chyby, webov server nemus znovu spustit!', ], 'logfiles_type' =&gt; [ 'title' =&gt; 'typ pstupovho protokolu', 'description' =&gt; 'zde si vyberte mezi &lt;strong&gt;combined&lt;/strong&gt; nebo &lt;strong&gt;vhost_combined&lt;/strong&gt;.', ], 'logfiles_piped' =&gt; [ 'title' =&gt; 'pesmrovn soubor protokolu webovho serveru zadanho skriptu (viz ve)', 'description' =&gt; 'pouvte-li vlastn skript pro logy, muste jej aktivovat, aby mohl bt sputn', ], 'ipaddress' =&gt; [ 'title' =&gt; 'ip adresa', 'description' =&gt; 'jak je hlavn ip adresa tohoto serveru?', ], 'hostname' =&gt; [ 'title' =&gt; 'nzev serveru', 'description' =&gt; 'jak je nzev hostitele tohoto serveru?', ], 'apachereload_command' =&gt; [ 'title' =&gt; 'pkaz pro optovn naten webovho serveru', 'description' =&gt; 'jak je pkaz webovho serveru pro optovn naten konfiguranch soubor?', ], 'bindenable' =&gt; [ 'title' =&gt; 'povolit nameserver', 'description' =&gt; 'zde lze globln povolit zakzat nameserver.', ], 'bindconf_directory' =&gt; [ 'title' =&gt; 'konfiguran adres serveru dns', 'description' =&gt; 'kde mly bt uloeny konfiguran soubory dns-serveru?', ], 'bindreload_command' =&gt; [ 'title' =&gt; 'pkaz pro optovn naten serveru dns', 'description' =&gt; 'jak je pkaz pro znovunaten dns serveru daemon?', ], 'vmail_uid' =&gt; [ 'title' =&gt; 'uid-mail', 'description' =&gt; 'kter uivatelsk id mly mt e-maily?', ], 'vmail_gid' =&gt; [ 'title' =&gt; 'mails-gid', 'description' =&gt; 'jak groupid mly mt e-maily?', ], 'vmail_homedir' =&gt; [ 'title' =&gt; 'domovsk adres pro emaily', 'description' =&gt; 'kde mly bt uloeny vechny emaily?', ], 'adminmail' =&gt; [ 'title' =&gt; 'odeslatel', 'description' =&gt; 'jak je adresa odeslatele pro e-maily odeslan z panelu?', ], 'phpmyadmin_url' =&gt; [ 'title' =&gt; 'phpmyadmin url', 'description' =&gt; 'jak je adresa url na phpmyadmin? (mus zat http(s)://)', ], 'webmail_url' =&gt; [ 'title' =&gt; 'webmail url', 'description' =&gt; 'jak je url adresa webov poty? (mus zat http(s)://)', ], 'webftp_url' =&gt; [ 'title' =&gt; 'webftp url', 'description' =&gt; 'jak je url adresa na webftp? (mus zat http(s)://)', ], 'language' =&gt; [ 'description' =&gt; 'jak je v standardn jazyk serveru?', ], 'maxloginattempts' =&gt; [ 'title' =&gt; 'maximln poet pokus pihlen', 'description' =&gt; 'maximln poet pokus pihlen, po kterch je et zakzn.', ], 'deactivatetime' =&gt; [ 'title' =&gt; 'as deaktivace', 'description' =&gt; 'as (sek.) je po pli mnoha pokusech pihlen deaktivovn et.', ], 'pathedit' =&gt; [ 'title' =&gt; 'typ vstupu cesty', 'description' =&gt; 'mla bt cesta vybrna v rozbalovacm menu nebo vstupnm poli?', ], 'nameservers' =&gt; [ 'title' =&gt; 'nameservery', 'description' =&gt; 'rkou oddlen seznam obsahujc jmna vech nameserver. prvn bude primrn.', ], 'mxservers' =&gt; [ 'title' =&gt; 'mx servery', 'description' =&gt; 'rkou oddlen seznam obsahujc dvojici sel nzvu hostitele oddlench mezerou (nap. \'10 mx.example.com\') obsahujc mx servery.', ], 'paging' =&gt; [ 'title' =&gt; 'poet poloek na strnku', 'description' =&gt; 'kolik zznam se zobraz na jedn strnce? (0 = zakzat strnkovn)', ], 'defaultip' =&gt; [ 'title' =&gt; 'vchoz ip/port', 'description' =&gt; 'vyberte vechny ip adresy, kter chcete pout jako vchoz pro nov domny', ], 'defaultsslip' =&gt; [ 'title' =&gt; 'vchoz ssl ip/port', 'description' =&gt; 'vyberte vechny ssl ip adresy, kter chcete pout jako vchoz pro nov domny', ], 'phpappendopenbasedir' =&gt; [ 'title' =&gt; 'cesty, kter se pipoj souboru openbasedir', 'description' =&gt; 'tyto cesty (oddlen dvojtekami) budou pidny pkazu openbasedir v kadm kontejneru vhost.', ], 'natsorting' =&gt; [ 'title' =&gt; 'pout pirozen lidsk tdn v zobrazen seznamu', 'description' =&gt; 'sead seznamy jako web1 -&gt; web2 -&gt; web11 msto web1 -&gt; web11 -&gt; web2.', ], 'deactivateddocroot' =&gt; [ 'title' =&gt; 'docroot pro deaktivovan uivatele', 'description' =&gt; 'pokud je uivatel deaktivovn, pouije se tato cesta jako docroot. ponechte przdn, pokud vbec nechcete vytvet vhost hostitele.', ], 'mailpwcleartext' =&gt; [ 'title' =&gt; 'tak ukldat neifrovan hesla e-mailovch databze', 'description' =&gt; 'pokud je toto nastaveno na ano, vechna hesla budou tak uloena v tabulce mail_users-table (neifrovan text, jednodue iteln pro vechny pstupem k databzi). aktivujte pouze pokud chcete pout sasl!', ], 'ftpdomain' =&gt; [ 'title' =&gt; 'ftp ty @domna', 'description' =&gt; 'zkaznci mohou vytvoit ftp ty uivatel@domnauivatele?', ], 'mod_fcgid' =&gt; [ 'title' =&gt; 'povolit fcgid', 'description' =&gt; 'pouijte pro sputn php odpovdajcm uivatelskm tem.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;toto vyaduje speciln konfiguraci webovho serveru pro apache, viz &lt;a target="_blank" href="https://docs.froxlor.org/latest/admin-guide/configuration/fcgid/"&gt;fcgid - pruka&lt;/a&gt;&lt;/b&gt;', 'configdir' =&gt; [ 'title' =&gt; 'adres konfigurace', 'description' =&gt; 'kde mly bt uloeny vechny fcgid konfiguran soubory? pokud nepouvte vlastn kompilovan suexec binrn, co je normln situace, tato cesta mus bt pod /var/www/&lt;br /&gt;&lt;br /&gt;&lt;div class="text-danger"&gt;poznmka: obsah tto sloky je pravideln smazn, aby se zabrnilo ukldn dat v n manuln.&lt;/div&gt;', ], 'tmpdir' =&gt; [ 'title' =&gt; 'doasn adres', 'description' =&gt; 'kde mly bt uloeny doasn adrese', ], 'starter' =&gt; [ 'title' =&gt; 'procesy na domnu', 'description' =&gt; 'kolik proces mlo bt sputno/povoleno v dan domn? hodnota 0 je doporuen pinou php pak bude velmi efektivn spravovat samotn poet proces.', ], 'wrapper' =&gt; [ 'title' =&gt; 'wrapper v hostitelch vhosts', 'description' =&gt; 'jak ml bt wrapper zahrnut vhosts', ], 'peardir' =&gt; [ 'title' =&gt; 'globln adrese pear', 'description' =&gt; 'kter globln adrese pear mly bt nahrazeny v kadm konfiguranm souboru php.ini? rzn adrese mus bt oddleny dvojtekou.', ], 'maxrequests' =&gt; [ 'title' =&gt; 'maximln poet poadavk na domnu', 'description' =&gt; 'kolik poadavk mlo bt povoleno na domnu?', ], 'defaultini' =&gt; 'vchoz konfigurace php pro nov domny', 'defaultini_ownvhost' =&gt; 'vchoz konfigurace php pro froxlor-vhost', 'idle_timeout' =&gt; [ 'title' =&gt; 'asov limit neinnosti', 'description' =&gt; 'asov limit nastaven mod fastcgi.', ], ], 'sendalternativemail' =&gt; [ 'title' =&gt; 'pout alternativn e-mailovou adresu', 'description' =&gt; 'poslat heslo na jinou adresu pi vytven e-mailu', ], 'apacheconf_vhost' =&gt; [ 'title' =&gt; 'konfiguran soubor/adres webserveru', 'description' =&gt; 'kde bt uloena konfigurace vhost? zde mete zadat bu soubor (vechny vhosty v jednom souboru), nebo adres (kad vhost vlastnm souboru).', ], 'apacheconf_diroptions' =&gt; [ 'title' =&gt; 'konfiguran soubor/nzev adrese webovho serveru diroptions', 'description' =&gt; 'kde bt uloena konfigurace diroptions? zde mete zadat bu soubor (vechny dioptrie v jednom souboru), nebo adres (kad dioptrie vlastnm souboru).', ], 'apacheconf_htpasswddir' =&gt; [ 'title' =&gt; 'webserver htpasswd dirname', 'description' =&gt; 'kde maj bt soubory htpasswd pro ochranu adrese uloeny?', ], 'mysql_access_host' =&gt; [ 'title' =&gt; 'mysql-access-hosts', 'description' =&gt; 'rkami oddlen seznam hostitel, od kterch mli mt uivatel monost se pipojit k serveru mysql-server. pro povolen podst je platn sov maska nebo cidr.', ], 'webalizer_quiet' =&gt; [ 'title' =&gt; 'vstup webaliztoru', 'description' =&gt; 'verbosita webalizru', ], 'logger' =&gt; [ 'enable' =&gt; 'logovn povoleno/zakzno', 'severity' =&gt; 'rove protokolovn', 'types' =&gt; [ 'title' =&gt; 'typ (typy) log', 'description' =&gt; 'zadejte typy log. chcete-li vybrat vce typ, podrte ctrl pi vbru.&lt;br /&gt;dostupn typy log jsou: syslog, soubor, mysql', ], 'logfile' =&gt; [ 'title' =&gt; 'nzev souboru pro log', 'description' =&gt; 'pouv se pouze v ppad, e typ logu obsahuje "soubor". tento soubor bude vytvoen v froxlor/logs/. tato sloka je chrnna ped veejnm pstupem.', ], 'logcron' =&gt; 'zaznamenvat cronjoby', 'logcronoption' =&gt; [ 'never' =&gt; 'nikdy', 'once' =&gt; 'jednou', 'always' =&gt; 'vdy', ], ], 'ssl' =&gt; [ 'use_ssl' =&gt; [ 'title' =&gt; 'povolit vyuit ssl', 'description' =&gt; 'zakrtnte, pokud chcete pout ssl pro v webov server', ], 'ssl_cert_file' =&gt; [ 'title' =&gt; 'cesta k ssl certifiktu', 'description' =&gt; 'zadejte cestu vetn nzvu souboru .crt nebo .pem (hlavn certifikt)', ], 'openssl_cnf' =&gt; 'vchoz nastaven pro vytvoen cert souboru', 'ssl_key_file' =&gt; [ 'title' =&gt; 'cesta k souboru kle ssl', 'description' =&gt; 'zadejte cestu vetn nzvu souboru pro soukrom kl (z vtiny.key)', ], 'ssl_ca_file' =&gt; [ 'title' =&gt; 'cesta k ssl ca certifiktu (voliteln)', 'description' =&gt; 'ovovn klienta, nastavte pouze pokud vte, co je.', ], 'ssl_cipher_list' =&gt; [ 'title' =&gt; 'konfigurovat povolen ssl ifry', 'description' =&gt; 'toto je seznam ifer, kter chcete (nebo nechcete) pout pi komunikaci ssl. pro seznam ifer zpsob, jak je zahrnout/vylouit viz oddly "cipher list format" "cipher strings" na &lt;a href="https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html"&gt;man-strnce pro ifry&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;vchoz hodnota je:&lt;/b&gt;&lt;pre&gt;ecdh+aesgcm:ecdh+aes256:!anull:!md5:!dss:!dh:!aes128&lt;/pre&gt;', ], 'apache24_ocsp_cache_path' =&gt; [ 'title' =&gt; 'apache 2.4: cesta k ocsp stapling cache', 'description' =&gt; 'konfiguruje mezipam pouitou k ukldn odpovd ocsp, kter jsou zahrnuty tls handshakes.', ], 'ssl_protocols' =&gt; [ 'title' =&gt; 'konfigurace verze protokolu tls', 'description' =&gt; 'toto je seznam ssl protokol, kter chcete (nebo nechcete) pout pi pouit ssl. &lt;b&gt;upozornn:&lt;/b&gt; nkter star prohlee nemus podporovat nejnovj verze protokolu.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;vchoz hodnota je:&lt;/b&gt;&lt;pre&gt;tlsv1.2&lt;/pre&gt;', ], 'tlsv13_cipher_list' =&gt; [ 'title' =&gt; 'nakonfigurujte explicitn tlsv1.3 ifry, pokud jsou pouity', 'description' =&gt; 'toto je seznam ifr, kter chcete (nebo nechcete) pout pi komunikaci tlsv1.3. seznam ifr jak je zahrnovat/vylouit, viz &lt;a href="https://wiki.openssl.org/index.php/tls1.3"&gt;dokumentace pro tlsv1.&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;vchoz hodnota je przdn&lt;/b&gt;', ], ], 'default_vhostconf' =&gt; [ 'title' =&gt; 'vchoz nastaven vhost-serveru', 'description' =&gt; 'obsah tohoto pole bude pmo zahrnut tohoto kontejneru ip/portem. mete pout nsledujc promnn:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt; &lt;code&gt;{fpmsocket}&lt;/code&gt; (pokud existuje)&lt;br/&gt; upozornn: kd nebude zkontrolovn na vskyt chyb. pokud obsahuje chyby, webov server nemus znovu spustit!', ], 'apache_globaldiropt' =&gt; [ 'title' =&gt; 'monosti adrese pro prefix zkaznka', 'description' =&gt; 'obsah tohoto pole bude zahrnut 05_froxlor_dirfix_nofcgid.conf apache config. je-li przdn, pouije se vchoz hodnota:&lt;br&gt;&lt;br&gt;apache &gt;=2.&lt;br&gt;&lt;code&gt;require granted&lt;br&gt;allowoverride all&lt;/code&gt;&lt;br&gt;&lt;br&gt;apache &lt;=2.&lt;br&gt;&lt;code&gt;order allow,deny&lt;br&gt;allow all&lt;/code&gt;', ], 'default_vhostconf_domain' =&gt; [ 'description' =&gt; 'obsah tohoto pole bude pmo zahrnut vhhost kontejneru. mete pout nsledujc promnn:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt; &lt;code&gt;{fpmsocket}&lt;/code&gt; (pokud existuje)&lt;br/&gt; upozornn: kd nebude zkontrolovn na obsah chyb. pokud obsahuje chyby, webov server nemus znovu spustit!', ], 'decimal_places' =&gt; 'poet desetinnch mst vstupu provozu/webovho prostoru', 'selfdns' =&gt; [ 'title' =&gt; 'nastaven dns domny zkaznka', ], 'selfdnscustomer' =&gt; [ 'title' =&gt; 'umonit zkaznkm upravit nastaven dns domny', ], 'unix_names' =&gt; [ 'title' =&gt; 'pout uivatelsk jmna kompatibiln unix', 'description' =&gt; 'umouje pouvat &lt;strong&gt;-&lt;/strong&gt; &lt;strong&gt;_&lt;/strong&gt; v uivatelskch jmnech, pokud &lt;strong&gt;ne&lt;/strong&gt;', ], 'allow_password_reset' =&gt; [ 'title' =&gt; 'povolit obnoven hesla zkaznkem', 'description' =&gt; 'zkaznci mohou obnovit sv heslo aktivan odkaz bude odesln na jejich e-mailovou adresu', ], 'allow_password_reset_admin' =&gt; [ 'title' =&gt; 'povolit obnoven hesla administrtorem', 'description' =&gt; 'sprvci/prodejci mohou obnovit sv heslo na jejich e-mailovou adresu bude zasln aktivan odkaz', ], 'mail_quota' =&gt; [ 'title' =&gt; 'kvta pro potovn schrnku', 'description' =&gt; 'vchoz kvta pro nov vytvoen potovn schrnky (megabyte).', ], 'mail_quota_enabled' =&gt; [ 'title' =&gt; 'pout kvty pro potovn schrnku pro zkaznky', 'description' =&gt; 'aktivujte pro pouit kvt na mailboxech. vchoz hodnota je &lt;b&gt;ne&lt;/b&gt;, protoe vyaduje speciln nastaven.', 'removelink' =&gt; 'kliknte zde pro vymazn vech kvt pro e-mailov ty.', 'enforcelink' =&gt; 'kliknte zde pro vynucen vchoz kvty na vechny uivatelsk e-mailov ty.', ], 'session_allow_multiple_login' =&gt; [ 'title' =&gt; 'povolit vcensobn pihlen', 'description' =&gt; 'pokud je uivatel aktivovn, se pihlsit vcekrt.', ], 'panel_allow_domain_change_admin' =&gt; [ 'title' =&gt; 'povolit pesouvn domn mezi sprvci', 'description' =&gt; 'pokud je aktivovno, mete zmnit administrtora domny v nastaven domny.&lt;br /&gt;&lt;b&gt;upozornn:&lt;/b&gt; pokud zkaznk nen piazen stejnmu sprvci jako domna, administrtor vidt vechny ostatn domny tohoto zkaznka!', ], 'panel_allow_domain_change_customer' =&gt; [ 'title' =&gt; 'povolit pesouvn domn mezi zkaznky', 'description' =&gt; 'pokud je aktivovno, mete zmnit zkaznka domny v nastaven domny.&lt;br /&gt;&lt;b&gt;upozornn:&lt;/b&gt; froxlor zmn koenov adres dokumentu na vchoz domovsk adres novho zkaznka (+ domnov sloka, pokud je aktivovna)', ], 'specialsettingsforsubdomains' =&gt; [ 'description' =&gt; 'pokud je zvoleno ano, budou tato vlastn nastaven vhost pidna ke vem subdomnm; pokud ne, budou zvltn nastaven subdomny odstranna.', ], 'panel_password_min_length' =&gt; [ 'title' =&gt; 'minimln dlka hesla', 'description' =&gt; 'zde mete nastavit minimln dlku hesla. "0" znamen, e nen vyadovna dn minimln dlka.', ], 'system_store_index_file_subs' =&gt; [ 'title' =&gt; 'uloit vchoz soubor indexu tak novch podsloek', 'description' =&gt; 'pokud je povoleno, vchoz indexov soubor se ukld kad nov vytvoen subdomnov cesty (ne pokud sloka ji existuje!)', ], 'adminmail_return' =&gt; [ 'title' =&gt; 'odpovdt na adresu', 'description' =&gt; 'definujte e-mailovou adresu jako odpov na adresu pro emaily odeslan panelem.', ], 'adminmail_defname' =&gt; 'jmno odeslatele e-mailu v panelu', 'stdsubdomainhost' =&gt; [ 'title' =&gt; 'zkaznick standardn subdomna', 'description' =&gt; 'jak nzev hostitele ml bt pouit pro vytvoen standardnch subdomn pro zkaznka. pokud je przdn, pouije se systmov nzev hostitele.', ], 'awstats_path' =&gt; 'cesta k awstats \'awstats_buildstaticpages.pl\'', 'awstats_conf' =&gt; 'cesta k konfiguraci awstats', 'defaultttl' =&gt; 'ttl domny pro navzn v sekundch (vchoz \'604800\' = 1 tden)', 'defaultwebsrverrhandler_enabled' =&gt; 'povolit vchoz chybov dokumenty pro vechny zkaznky', 'defaultwebsrverrhandler_err401' =&gt; [ 'title' =&gt; 'soubor/url pro chybu 401', 'description' =&gt; '&lt;div class="text-danger"&gt;nen podporovno v: lighttpd&lt;/div&gt;', ], 'defaultwebsrverrhandler_err403' =&gt; [ 'title' =&gt; 'soubor/url pro chybu 403', 'description' =&gt; '&lt;div class="text-danger"&gt;nen podporovno v: lighttpd&lt;/div&gt;', ], 'defaultwebsrverrhandler_err404' =&gt; 'soubor/url pro chybu 404', 'defaultwebsrverrhandler_err500' =&gt; [ 'title' =&gt; 'soubor/url pro chybu 500', 'description' =&gt; '&lt;div class="text-danger"&gt;nen podporovno v: lighttpd&lt;/div&gt;', ], 'ftpserver' =&gt; [ 'desc' =&gt; 'pokud je zvolen pureftpd, soubory .ftpquota pro uivatelsk kvty jsou vytveny denn aktualizovny', ], 'customredirect_enabled' =&gt; [ 'title' =&gt; 'povolit pesmrovn zkaznk', 'description' =&gt; 'umonit zkaznkm vybrat kd pro http-status pesmrovn, kter budou pouity', ], 'customredirect_default' =&gt; [ 'title' =&gt; 'vchoz pesmrovn', 'description' =&gt; 'nastavte vchoz kd pesmrovn, kter se ml pout, pokud jej zkaznk nenastav sm', ], 'mail_also_with_mxservers' =&gt; 'vytvoit mail-, imap-, pop3- smtp-"a record" tak nastavenm mx-server', 'froxlordirectlyviahostname' =&gt; 'pstup k froxlor pmo prostednictvm nzvu hostitele', 'panel_password_regex' =&gt; [ 'title' =&gt; 'regulrn vraz pro hesla', 'description' =&gt; 'zde mete nastavit regulrn vraz pro sloitost hesel.&lt;br /&gt;przdn = dn specifick poadavky', ], 'perl_path' =&gt; [ 'title' =&gt; 'cesta k perl', 'description' =&gt; 'vchoz je /usr/bin/perl', ], 'mod_fcgid_ownvhost' =&gt; [ 'title' =&gt; 'povolit fcgid pro froxlor vhost', 'description' =&gt; 'pokud je povoleno, bude froxlor sputn tak pod mstnm uivatelem', ], 'perl' =&gt; [ 'suexecworkaround' =&gt; [ 'title' =&gt; 'povolit suexec workaround', 'description' =&gt; 'povolit pouze v ppad, e zkaznick docrooty nejsou v apache suexec cest.&lt;br /&gt;pokud je povoleno, froxlor vygeneruje symbolick odkaz od zkaznk perl-enabled adrese + /cgi-bin/ k dan cest.&lt;br /&gt;vimnte si, e perl bude fungovat pouze v podadresi sloek /cgi-bin/ ne sloce samotn (jako dl bez tto opravy!)', ], 'suexeccgipath' =&gt; [ 'title' =&gt; 'cesta pro symlinky adres zkaznka povolenm perlem', 'description' =&gt; 'toto je teba nastavit pouze pokud je povolena suexec-workaround.&lt;br /&gt;pozor: ujistte se, e tato cesta je v rmci hlavn cesty, nebo jinak je toto een zbyten', ], ], 'awstats_awstatspath' =&gt; 'cesta k awstats \'awstats.pl\'', 'awstats_icons' =&gt; [ 'title' =&gt; 'cesta ke sloce ikon awstats', 'description' =&gt; 'nap. /usr/share/awstats/htdocs/icon/', ], 'login_domain_login' =&gt; 'povolit pihlen pomoc domn', 'perl_server' =&gt; [ 'title' =&gt; 'umstn soketu perl serveru', 'description' =&gt; 'jednoduch nvod najdete na: &lt;a target="blank" href="https://www.nginx.com/resources/wiki/start/topics/examples/fcgiwrap/"&gt;nginx.com&lt;/a&gt;', ], 'nginx_php_backend' =&gt; [ 'title' =&gt; 'nginx php backend', 'description' =&gt; 'zde proces php naslouch poadavkm z nginxu, bt unixov soket kombinac ip:port&lt;br /&gt;*nepouv se php-fpm', ], 'phpreload_command' =&gt; [ 'title' =&gt; 'pkaz pro optovn naten php', 'description' =&gt; 'toto se pouv k obnoven php backendu, pokud je pouit&lt;br /&gt;vchoz: przdn&lt;br /&gt;*nen pouito php-fpm', ], 'phpfpm' =&gt; [ 'title' =&gt; 'povolit php-fpm', 'description' =&gt; '&lt;b&gt;to vyaduje speciln konfiguraci webserveru viz &lt;a target="_blank" href="https://docs.froxlor.org/latest/admin-guide/configuration/php-fpm/"&gt;php-fpm pruka&lt;/a&gt;&lt;/b&gt;', ], 'phpfpm_settings' =&gt; [ 'configdir' =&gt; 'adres konfigurace php-fpm', 'aliasconfigdir' =&gt; 'konfigurace adrese aliasu php-fpm', 'reload' =&gt; 'php-fpm restart pkaz', 'pm' =&gt; 'zen sprvce procesu (pm)', 'max_children' =&gt; [ 'title' =&gt; 'poet podzench proces', 'description' =&gt; 'poet podzench proces, kter maj bt vytvoeny, kdy je hodnota pm nastavena na \'static\' maximln poet podzench proces, kter maj bt vytvoeny, kdy je hodnota pm nastavena na \'dynamic/ondemand\'&lt;br /&gt;ekvivalent hodnoty php_fcgi_children', ], 'start_servers' =&gt; [ 'title' =&gt; 'poet podzench proces vytvoench pi sputn', 'description' =&gt; 'poznmka: pouv se pouze v ppad, e je pm nastaven na \'dynamick\'', ], 'min_spare_servers' =&gt; [ 'title' =&gt; 'poadovan minimln poet proces serveru v neinnosti', 'description' =&gt; 'poznmka: pouv se pouze pi nastaven pm na \'dynamic\'&lt;br /&gt;poznmka: povinn pi nastaven pm na \'dynamic\'', ], 'max_spare_servers' =&gt; [ 'title' =&gt; 'poadovan maximln poet proces serveru v neinnosti', 'description' =&gt; 'poznmka: pouv se pouze v ppad, e je pm nastaven na \'dynamick\'&lt;br /&gt;poznmka: povinn, kdy je pm nastaven na \'dynamick\'', ], 'max_requests' =&gt; [ 'title' =&gt; 'poadavky na proces ped znovu objevenm', 'description' =&gt; 'pro nekonen zpracovn poadavk zadejte \'0\'. ekvivalentn php_fcgi_max_requests.', ], 'idle_timeout' =&gt; [ 'title' =&gt; 'asov limit neinnosti', 'description' =&gt; 'nastaven asovho limitu pro php fastcgi.', ], 'ipcdir' =&gt; [ 'title' =&gt; 'fastcgi adres ipc', 'description' =&gt; 'adres, kam bude webov server ukldat sockety php-fpm.&lt;br /&gt;tento adres mus bt pro webov server iteln', ], 'limit_extensions' =&gt; [ 'title' =&gt; 'povolen ppony', 'description' =&gt; 'omezuje rozen hlavnho skriptu, kter fpm dovol analyzovat. zabrnit chybm v konfiguraci na stran webovho serveru. mli byste omezit fpm pouze na ppony .php, abyste zabrnili kodlivm uivatelm pouvat jin ppony ke sputn kdu php. vchoz hodnota: .php', ], 'envpath' =&gt; 'cesty, kter se pidaj prosted path. nechte przdn, pokud promnn prosted path neexistuje', 'override_fpmconfig' =&gt; 'pepsat nastaven fpm-daemon (pm, max_children atd.)', 'override_fpmconfig_addinfo' =&gt; '&lt;br /&gt;&lt;span class="text-danger"&gt;pouv se pouze v ppad, e "pepsat nastaven fpm-daemon" je nastaveno na "ano"&lt;/span&gt;', 'restart_note' =&gt; 'upozornn: konfigurace nebude zkontrolovna na vskyt chyb. pokud obsahuje chyby, php-fpm nemus znovu spustit!', 'custom_config' =&gt; [ 'title' =&gt; 'vlastn konfigurace', 'description' =&gt; 'pidejte vlastn konfiguraci pro kadou instanci php-fpm verze, napklad &lt;i&gt;pm.status_path = /status&lt;/i&gt; pro monitorovn. promnn ne lze pout zde. &lt;strong&gt;upozornn: konfigurace nebude zkontrolovna pro dn chyby. pokud obsahuje chyby, php-fpm nemus znovu spustit!&lt;/strong&gt;', ], 'allow_all_customers' =&gt; [ 'title' =&gt; 'piadit tuto konfiguraci vem aktuln existujcm zkaznkm', 'description' =&gt; 'nastavte tuto hodnotu na true, pokud chcete tuto konfiguraci piadit vem aktuln existujcm zkaznkm, aby ji mohli pouvat. toto nastaven nen trval, ale lze jej spustit vcekrt.', ], ], 'report' =&gt; [ 'report' =&gt; 'povolit odesln hlen pouvn webu provozu', 'webmax' =&gt; [ 'title' =&gt; 'rove varovn v procentech pro webov prostor', 'description' =&gt; 'platn hodnoty jsou 0 150. nastavenm tto hodnoty na 0 zake tuto zprvu.', ], 'trafficmax' =&gt; [ 'title' =&gt; 'rove varovn v procentech pro provoz', 'description' =&gt; 'platn hodnoty jsou 0 150. nastavenm tto hodnoty na 0 zake tuto zprvu.', ], ], 'dropdown' =&gt; 'rozevrac nabdka', 'manual' =&gt; 'manuln', 'default_theme' =&gt; 'vchoz ablona', 'validate_domain' =&gt; 'ovit nzvy domn', 'diskquota_enabled' =&gt; 'kvta aktivovna?', 'diskquota_repquota_path' =&gt; [ 'description' =&gt; 'cesta k repquota', ], 'diskquota_quotatool_path' =&gt; [ 'description' =&gt; 'cesta k quotatool', ], 'diskquota_customer_partition' =&gt; [ 'description' =&gt; 'oddl, na kterm jsou uloeny zkaznick soubory', ], 'vmail_maildirname' =&gt; [ 'title' =&gt; 'nzev maildir', 'description' =&gt; 'maildir adres uivatelskho tu. obvykle \'maildir\', v nkterch implementacch \'.maildir\' pmo adrese uivatele, pokud zstane przdn.', ], 'catchall_enabled' =&gt; [ 'title' =&gt; 'pout catchall', 'description' =&gt; 'chcete svm zkaznkm poskytnout funkci catchall?', ], 'apache_24' =&gt; [ 'title' =&gt; 'pout pravy pro apache 2.4', 'description' =&gt; '&lt;strong class="text-danger"&gt;pozor:&lt;/strong&gt; pouijte, pouze pokud mte nainstalovanou apache verzi 2.4 nebo vy&lt;br /&gt;jinak nebude v webserver moci spustit', ], 'nginx_fastcgiparams' =&gt; [ 'title' =&gt; 'cesta k souboru fastcgi_params', 'description' =&gt; 'zadejte cestu k souboru fastcgi_params nginx vetn nzvu souboru', ], 'documentroot_use_default_value' =&gt; [ 'title' =&gt; 'pout nzev domny jako vchoz hodnotu pro cestu koenovho adrese dokumentu', 'description' =&gt; 'pokud je povoleno cesta documentroot je przdn, vchoz hodnotou bude nzev (sub)domny.&lt;br /&gt;&lt;br /&gt;pklady: &lt;br /&gt;/var/customers/webs/customer_name/example.com/&lt;br /&gt;/var/customers/webs/customer_name/subdomain.example.com/', ], 'panel_phpconfigs_hidesubdomains' =&gt; [ 'title' =&gt; 'skrt subdomny v php-konfiguranm pehledu', 'description' =&gt; 'pokud je aktivovno, subdomny zkaznk nebudou zobrazeny v pehledu php-konfigurac, zobraz se pouze poet subdomn.&lt;br /&gt;&lt;br /&gt;poznmka: toto je viditeln pouze v ppad, e jste povolili fcgid nebo php-fpm', ], 'panel_phpconfigs_hidestdsubdomain' =&gt; [ 'title' =&gt; 'skrt standardn subdomny v pehledu konfigurace php-', 'description' =&gt; 'pokud je aktivovno, standardn subdomny pro zkaznky se nebudou zobrazovat v pehledu php-konfigurac&lt;br /&gt;&lt;br /&gt;poznmka: toto je viditeln pouze v ppad, e jste povolili fcgid nebo php-fpm', ], 'passwordcryptfunc' =&gt; [ 'title' =&gt; 'vyberte, kter metoda ifrovn hesla bt pouita', 'description' =&gt; 'vyberte, kter metoda ifrovn heslem bt pouita. pokud toto nastaven zmnte, budou ifrovna pouze nov hesla novou metodou. stvajc hesla se nezmn.', ], 'systemdefault' =&gt; 'vchoz systmov nastaven', 'panel_allow_theme_change_admin' =&gt; 'povolit administrtorm zmnit motiv', 'panel_allow_theme_change_customer' =&gt; 'umonit zkaznkm zmnu motivu', 'axfrservers' =&gt; [ 'title' =&gt; 'servery axfr', 'description' =&gt; 'rkami oddlen seznam ip adres, kter mohou penet (axfr) zny.', ], 'powerdns_mode' =&gt; [ 'title' =&gt; 'operan reim powerdns', 'description' =&gt; 'vyberte reim powedns: nativn pro dnou replikaci (vchoz) / master, pokud je poteba dns replikace.', ], 'customerssl_directory' =&gt; [ 'title' =&gt; 'adres zkaznickch certifikt webovch server', 'description' =&gt; 'kde mly bt vytvoeny ssl-certifikty zadan zkaznkem?&lt;br /&gt;&lt;br /&gt;&lt;div class="text-danger"&gt;poznmka: obsah tto sloky je pravideln smazn, aby se zabrnilo ukldn dat tto sloky run.&lt;/div&gt;', ], 'allow_error_report_admin' =&gt; [ 'title' =&gt; 'povolit sprvcm/prodejcm nahlsit chyby databze froxlor', 'description' =&gt; 'upozornn: nikdy nm neposlejte dn osobn (zkaznick)daje!', ], 'allow_error_report_customer' =&gt; [ 'title' =&gt; 'umonit zkaznkm nahlsit chyby databze froxlor', 'description' =&gt; 'upozornn: nikdy nm neposlejte dn osobn (zkaznick)daje!', ], 'mailtraffic_enabled' =&gt; [ 'title' =&gt; 'analyzovat penos poty', 'description' =&gt; 'povolit analzu protokol mailserveru pro vpoet provozu', ], 'mdaserver' =&gt; [ 'title' =&gt; 'mda typ', 'description' =&gt; 'typ potovnho serveru', ], 'mdalog' =&gt; [ 'title' =&gt; 'protokol mda', 'description' =&gt; 'soubor protokolu serveru pro doruovn poty', ], 'mtaserver' =&gt; [ 'title' =&gt; 'mta typ', 'description' =&gt; 'typ zprostedkovatele pro penos poty', ], 'mtalog' =&gt; [ 'title' =&gt; 'protokol mta', 'description' =&gt; 'soubor protokolu agenta pro penos poty', ], 'system_cronconfig' =&gt; [ 'title' =&gt; 'konfiguran soubor cronu', 'description' =&gt; 'cesta ke konfiguranmu souboru cron-service. tento soubor bude pravideln automaticky aktualizovn froxlorem.&lt;br /&gt;poznmka: &lt;b&gt;ujistte se&lt;/b&gt;, e pouvte stejn nzev souboru jako pro hlavn froxlor cronjob (vchoz: /etc/cron.d/froxlor)!&lt;br&gt;&lt;br&gt;pokud pouvte &lt;b&gt;freebsd&lt;/b&gt;, zadejte zde &lt;i&gt;/etc/crontab&lt;/i&gt;!', ], 'system_crondreload' =&gt; [ 'title' =&gt; 'pkaz pro optovn naten cron-daemona', 'description' =&gt; 'urete pkaz, kter bt proveden, aby bylo mon znovu nast systmy cron-daemon', ], 'system_croncmdline' =&gt; [ 'title' =&gt; 'pkaz pro proveden cronu (php-binary)', 'description' =&gt; 'pkaz k proveden naich cronjob. zmte pouze pokud vte, co dlte (vchoz: "/usr/bin/nice -n 5 /usr/bin/php -q")!', ], 'system_cron_allowautoupdate' =&gt; [ 'title' =&gt; 'povolit automatick aktualizace databze', 'description' =&gt; '&lt;div class="text-danger"&gt;&lt;b&gt;pozor:&lt;/b&gt;&lt;/div&gt; toto nastaven umouje cronjob obejt kontrolu verz froxlor soubor databze spustit aktualizace databze v ppad, e dojde k nesouladu verz.&lt;br&gt;&lt;br&gt;&lt;div class="text-danger"&gt;automatick aktualizace vdy nastav vchoz hodnoty pro nov nastaven nebo zmny. toto nemus vdy vyhovovat vaemu systmu. ped aktivac tto monosti&lt;/div&gt; prosm dvakrt rozmyslete', ], 'dns_createhostnameentry' =&gt; 'vytvote bind-zone/config pro nzev hostitele systmu', 'panel_password_alpha_lower' =&gt; [ 'title' =&gt; 'mal psmo', 'description' =&gt; 'heslo mus obsahovat alespo jedno mal psmeno (a-z).', ], 'panel_password_alpha_upper' =&gt; [ 'title' =&gt; 'velk psmeno', 'description' =&gt; 'heslo mus obsahovat alespo jedno velk psmeno (a-z).', ], 'panel_password_numeric' =&gt; [ 'title' =&gt; 'sla', 'description' =&gt; 'heslo mus obsahovat alespo jedno slo (0-9).', ], 'panel_password_special_char_required' =&gt; [ 'title' =&gt; 'speciln znak', 'description' =&gt; 'heslo mus obsahovat alespo jeden z ne uvedench znak.', ], 'panel_password_special_char' =&gt; [ 'title' =&gt; 'seznam specilnch znak', 'description' =&gt; 'jeden z tchto znak je vyadovn, pokud je nastavena uveden volba.', ], 'apache_itksupport' =&gt; [ 'title' =&gt; 'pout pravy itk-mpm apache', 'description' =&gt; '&lt;strong class="text-danger"&gt;pozor:&lt;/strong&gt; pouijte, pouze pokud mte opravdu povoleno apache itk-mpm&lt;br /&gt;jinak v webserver nebude moci spustit', ], 'letsencryptca' =&gt; [ 'title' =&gt; 'acme prosted', 'description' =&gt; 'prosted, kter se pout pro certifikty let\'s encrypt / zerossl.', ], 'letsencryptchallengepath' =&gt; [ 'title' =&gt; 'cesta k vzvm let\'s encrypt', 'description' =&gt; 'adres, ze kterho mly bt nabzeny vzvy let\'s encrypt prostednictvm globlnho aliasu.', ], 'letsencryptkeysize' =&gt; [ 'title' =&gt; 'velikost kle pro nov let\'s encrypt certifikty', 'description' =&gt; 'velikost kle v bitech pro nov let\'s encrypt certifikty.', ], 'letsencryptreuseold' =&gt; [ 'title' =&gt; 'znovu pout let\'s encrypt kl', 'description' =&gt; 'pokud je aktivovn, bude pi kadm obnoven pouit stejn kl, jinak bude pokad vygenerovn nov kl.', ], 'leenabled' =&gt; [ 'title' =&gt; 'pout let\'s encrypt', 'description' =&gt; 'pokud je aktivovno, zkaznci mohou nechat froxlor automaticky generovat obnovit ifrovac certifikty domn ssl ip/portem.&lt;br /&gt;&lt;br /&gt;nezapomete, e muste prochzet konfigurac webserveru, pokud je povoleno, protoe tato funkce vyaduje speciln konfiguraci.', ], 'caa_entry' =&gt; [ 'title' =&gt; 'generovat caa dns zznamy', 'description' =&gt; 'automaticky generuje caa zznamy pro domny podporou ssl, kter pouvaj let\'s encrypt', ], 'caa_entry_custom' =&gt; [ 'title' =&gt; 'dal zznamy caa dns', 'description' =&gt; 'dns certification authority autorizace (caa) je mechanismus politiky bezpenosti internetu, kter dritelm domnovch jmen umouje certifikovat autorit&lt;br&gt;, zda jsou oprvnni vydvat digitln certifikty pro urit nzev domny. dl pomoc novho zdrojovho zznamu domnovho systmu "caa" (dns).&lt;br&gt;&lt;br&gt;obsah tohoto pole bude zahrnut dns zny pmo (kad dek vyst v caa zznam).&lt;br&gt;pokud je pro tuto domnu povoleno ifrovn, tato poloka bude vdy pidna automaticky nemus bt pidna run:&lt;br&gt;&lt;code&gt;0 problm "letsencrypt". rg"&lt;/code&gt; (pokud domna je domna zstupnch znak, bude msto toho pouita vydn).&lt;br&gt;chcete-li povolit hlen incident, mete pidat zznam &lt;code&gt;iodef&lt;/code&gt;. pklad pro odesln zprvy na &lt;code&gt;me@example. om&lt;/code&gt; bude:&lt;br&gt;&lt;code&gt;0 iodef "mailto:me@example. om"&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;strong&gt;upozornn:&lt;/strong&gt; kd nebude zkontrolovn z dvodu chyb. pokud obsahuje chyby, vae caa zznamy nemus fungovat!', ], 'exportenabled' =&gt; [ 'title' =&gt; 'povolit export dat pro zkaznky', 'description' =&gt; 'pokud je aktivovno, zkaznk bude moci naplnovat lohy pro export dat (cron-export), kter generuj archiv svm docrootu (podadres vybran zkaznkem)', ], 'dnseditorenable' =&gt; [ 'title' =&gt; 'povolit dns editor', 'description' =&gt; 'umouje administrtorm zkaznkovi spravovat dns zznamy domn', ], 'dns_server' =&gt; [ 'title' =&gt; 'daemon dns serveru', 'description' =&gt; 'nezapomete, e "daemons" je teba konfigurovat pomoc konfiguranch ablon froxloru', ], 'panel_customer_hide_options' =&gt; [ 'title' =&gt; 'skryt poloek nabdek graf nvtvnosti v zkaznickm panelu', 'description' =&gt; 'vyberte poloky, kter chcete skrt v panelu zkaznka. chcete-li vybrat vce monost, podrte ctrl pi vbru.', ], 'allow_allow_customer_shell' =&gt; [ 'title' =&gt; 'umonit zkaznkm povolit pstup pes shell pro uivatele ftp', 'description' =&gt; '&lt;strong class="text-danger"&gt;upozornn: pstup k shell umouje uivateli spustit rzn binrn soubory vaem systmu. pouvejte extrmn opatrnost. aktivujte prosm pouze pokud vte, co dlte!!!&lt;/strong&gt;', ], 'available_shells' =&gt; [ 'title' =&gt; 'seznam dostupnch pkaz', 'description' =&gt; 'rkami oddlen seznam shell, z nich si zkaznk vybrat pro sv ftp uivatele.&lt;br&gt;&lt;br&gt;vimnte si, e vchoz shell &lt;strong&gt;/bin/false&lt;/strong&gt; bude vdy na vbr (pokud je povolen), kdy je toto nastaven przdn. v kadm ppad je vchoz hodnota proftp uivatele', ], 'le_froxlor_enabled' =&gt; [ 'title' =&gt; 'povolit let\'s encrypt pro hostitele froxlor', 'description' =&gt; 'pokud je aktivovno, bude vhost froxloru automaticky zabezpeen pomoc let\'s encrypt certifiktu.', ], 'le_froxlor_redirect' =&gt; [ 'title' =&gt; 'povolit pesmrovn ssl pro vhost froxloru', 'description' =&gt; 'pokud je aktivovno, vechny poadavky http na v froxlor budou pesmrovny na pslun server ssl.', ], 'option_unavailable_websrv' =&gt; '&lt;br&gt;&lt;em class="text-danger"&gt;k dispozici pouze pro: %s&lt;/em&gt;', 'option_unavailable' =&gt; '&lt;br&gt;&lt;em class="text-danger"&gt;monost nen dostupn kvli jinm nastavenm.&lt;/em&gt;', 'letsencryptacmeconf' =&gt; [ 'title' =&gt; 'cesta k snippetu acme.conf', 'description' =&gt; 'nzev souboru v konfiguranm textovm bloku, kter umouje webovmu serveru obsluhovat vzvu acme.', ], 'mail_use_smtp' =&gt; 'nastavte e-mail pro pouit smtp', 'mail_smtp_host' =&gt; 'zadejte smtp server', 'mail_smtp_usetls' =&gt; 'povolit ifrovn tls', 'mail_smtp_auth' =&gt; 'povolit ovovn smtp', 'mail_smtp_port' =&gt; 'tcp port pro pipojen k', 'mail_smtp_user' =&gt; 'smtp uivatelsk jmno', 'mail_smtp_passwd' =&gt; 'smtp heslo', 'http2_support' =&gt; [ 'title' =&gt; 'http2 podpora', 'description' =&gt; 'povolit podporu http2 pro ssl.&lt;br&gt;&lt;em class="text-danger"&gt;povolte pouze pokud v server tuto funkci podporuje (nginx verze 1.9.5+, apache2 verze 2.4.17+)&lt;/em&gt;', ], 'nssextrausers' =&gt; [ 'title' =&gt; 'pout libnss-extrauser msto libnss-mysql', 'description' =&gt; 'nest uivatele z databze, ale ze soubor. aktivujte se, prosm, pouze pokud jste ji proli poadovanmi kroky konfigurace (system -&gt; libnss-extrausers).&lt;br&gt;&lt;strong class="text-danger"&gt;pouze pro debian/ubuntu (nebo pokud jste sami zkompilovali libnss-extrauser!)&lt;/strong&gt;', ], 'le_domain_dnscheck' =&gt; [ 'title' =&gt; 'ovit dns domn pi pouit let\'s encrypt', 'description' =&gt; 'pokud je aktivovno, froxlor ov, zda se domna, kter certifikt, smuje alespo na jednu ze ip adres systmu.', ], 'le_domain_dnscheck_resolver' =&gt; [ 'title' =&gt; 'pout extern nameserver pro oven dns', 'description' =&gt; 'je-li nastaveno, froxlor pouije tuto dns k oven dns domn pi pouit let\'s encrypt. pokud je przdn, bude pouit vchoz peklada dns systmu.', ], 'phpsettingsforsubdomains' =&gt; [ 'description' =&gt; 'pokud ano, zvolen php-config bude aktualizovn na vechny subdomny', ], 'leapiversion' =&gt; [ 'title' =&gt; 'zvolte si implementaci acme pro let\'s encrypt', 'description' =&gt; 'v souasn dob je podporovna pouze implementace acme v2 pro let\'s encrypt.', ], 'enable_api' =&gt; [ 'title' =&gt; 'povolit extern pouit api', 'description' =&gt; 'chcete-li pouvat froxlor api, muste aktivovat tuto monost. podrobnj informace naleznete v &lt;a href="https://docs.froxlor.org/latest/api-guide/" target="_new"&gt;https://docs.froxlor.org/&lt;/a&gt;', ], 'api_customer_default' =&gt; '"povolit pstup k api" pro nov zkaznky', 'dhparams_file' =&gt; [ 'title' =&gt; 'soubor dhparams (vmna kl diffie-hellman)', 'description' =&gt; 'pokud je zde zadn soubor dhparams.pem, bude zahrnut konfigurace webserveru. ponechte przdn pro vypnut.&lt;br&gt;pklad: /etc/ssl/webserver/dhparams.&lt;br&gt;&lt;br&gt;pokud soubor neexistuje, bude vytvoen automaticky nsledujcm pkazem: &lt;code&gt;openssl dhparam -out /etc/ssl/webserver/dhparams. em 4096&lt;/code&gt;. ped zadnm souboru je doporueno vytvoit soubor, protoe vytvoen trv docela dlouho blokuje cronjob.', ], 'errorlog_level' =&gt; [ 'title' =&gt; 'rove protokol chyb', 'description' =&gt; 'zadejte rove protokolu chyb. vchoz hodnota je "warn" pro apache-user "error" pro nginx-usery.', ], 'letsencryptecc' =&gt; [ 'title' =&gt; 'vystavit certifikt esc / certifikt ecdsa', 'description' =&gt; 'je-li nastaveno na platnou velikost kle, vystaven certifikt bude pouvat ecc / ecdsa', ], 'froxloraliases' =&gt; [ 'title' =&gt; 'aliasy domn pro froxlor vhost', 'description' =&gt; 'rkami oddlen seznam domn, kter maj bt pidny jako serverov alias froxlor vhost', ], 'default_sslvhostconf' =&gt; [ 'title' =&gt; 'vchoz nastaven ssl vhost-serveru', 'description' =&gt; 'obsah tohoto pole bude pmo zahrnut tohoto kontejneru ip/portem. mete pout nsledujc promnn:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt; &lt;code&gt;{fpmsocket}&lt;/code&gt; (pokud existuje)&lt;br/&gt; upozornn: kd nebude zkontrolovn na vskyt chyb. pokud obsahuje chyby, webov server nemus znovu spustit!', ], 'includedefault_sslvhostconf' =&gt; 'zahrnout ne-ssl vhost-nastaven v ssl-vhost', 'apply_specialsettings_default' =&gt; 'vchoz hodnota pro "pout speciln nastaven pro vechny subdomny (*.example.com)" pi prav domny', 'apply_phpconfigs_default' =&gt; 'vchoz hodnota pro nastaven "pout php konfiguraci na vechny subdomny" pi prav domny', 'awstats' =&gt; [ 'logformat' =&gt; [ 'title' =&gt; 'nastaven logformat', 'description' =&gt; 'pokud pouvte vlastn logformat pro svj webov server, muste tak zmnit awstats logformat.&lt;br/&gt;vchoz je 1. pro vce informac zkontrolujte dokumentaci &lt;a target="_blank" href="https://awstats.sourceforge.io/docs/awstats_config.html#logformat"&gt;zde&lt;/a&gt;.', ], ], 'hide_incompatible_settings' =&gt; 'skrt nekompatibiln nastaven', 'soaemail' =&gt; 'e-mailov adresa pro pouit v soa zznamech (vchoz adresa odeslatele z nastaven panelu, pokud je przdn)', 'imprint_url' =&gt; [ 'title' =&gt; 'adresa url k prvnm poznmkm / otisku', 'description' =&gt; 'zadejte adresu url svch prvnch poznmek / strnek otisky. odkaz bude viditeln na pihlaovac obrazovce v zpat po pihlen.', ], 'terms_url' =&gt; [ 'title' =&gt; 'url k podmnkm pouit', 'description' =&gt; 'zadejte adresu url k podmnkm pouvn. odkaz bude viditeln na pihlaovac obrazovce v zpat pi pihlen.', ], 'privacy_url' =&gt; [ 'title' =&gt; 'url k zsadm ochrany osobnch daj', 'description' =&gt; 'zadejte adresu url sv strnky se zsadami ochrany osobnch daj / strnky otisky. odkaz bude viditeln na pihlaovac obrazovce v zpat po pihlen.', ], 'logo_image_header' =&gt; [ 'title' =&gt; 'obrzek loga (zhlav)', 'description' =&gt; 'nahrajte vlastn obrzek loga, kter se zobraz v zhlav po pihlen (doporuen vka 30px)', ], 'logo_image_login' =&gt; [ 'title' =&gt; 'obrzek loga (pihlaovac obrazovka)', 'description' =&gt; 'nahrajte vlastn obrzek loga, kter se zobraz bhem pihlen', ], 'logo_overridetheme' =&gt; [ 'title' =&gt; 'pepe logo definovan v motivu pomoc "logo image" (hlavika pihlaovac strnka, viz ne)', 'description' =&gt; 'toto mus bt nastaveno na "true", pokud mte v myslu pout nahran logo_custom. alternativn mete stle pouvat "logo custom. ng" "logo_custom_login.png".', ], 'logo_overridecustom' =&gt; [ 'title' =&gt; 'pepsat vlastn logo (logo_custom.png logo_custom_login.png) definovan v ablon "obrzek loga" (hlavika pihlen, viz ne)', 'description' =&gt; 'nastavte na "true" pokud chcete ignorovat vlastn loga pro zhlav pihlen pout "logo image"', ], 'createstdsubdom_default' =&gt; [ 'title' =&gt; 'pedvolen hodnota pro "vytvoit standardn subdomnu" pi vytven zkaznka', 'description' =&gt; '', ], 'froxlorusergroup' =&gt; [ 'title' =&gt; 'vlastn systmov skupina pro vechny zkaznky', 'description' =&gt; 'pouit libnss-extrauser (systmovho nastaven) je vyadovno. vytven przdnch hodnot pesko nebo odstran existujc skupinu.', ], 'acmeshpath' =&gt; [ 'title' =&gt; 'cesta k acme.sh', 'description' =&gt; 'nastavte na msto, kde je acme.sh nainstalovn, vetn skriptu acme.sh&lt;br&gt;vchoz je &lt;b&gt;/root/.acme.sh/acme.sh&lt;/b&gt;', ], 'update_channel' =&gt; [ 'title' =&gt; 'froxlor aktualizan-kanl', 'description' =&gt; 'vyberte aktualizan kanl froxlor. vchoz hodnota je "stabiln"', ], 'uc_stable' =&gt; 'stabiln', 'uc_testing' =&gt; 'testovac', 'uc_nightly' =&gt; 'nightly', 'traffictool' =&gt; [ 'toolselect' =&gt; 'analyztor provozu', 'webalizer' =&gt; 'webalizer', 'awstats' =&gt; 'awstats', 'goaccess' =&gt; 'goaccess' ], 'requires_reconfiguration' =&gt; 'zmna tohoto nastaven vyadovat zmnu konfigurace nsledujcch slueb:&lt;br&gt;&lt;strong&gt;%s&lt;/strong&gt;', 'req_limit_per_interval' =&gt; [ 'title' =&gt; 'poet http poadavk na interval', 'description' =&gt; 'omezit poet http poadavk na interval (viz ne) pro froxlor, vchoz hodnota je "60"', ], 'req_limit_interval' =&gt; [ 'title' =&gt; 'interval omezen rychlosti', 'description' =&gt; 'zadejte v sekundch pro poet http poadavk. vchoz hodnota je "60"', ], 'option_requires_otp' =&gt; 'toto nastaven vyaduje oven pes otp', 'panel_menu_collapsed' =&gt; [ 'title' =&gt; 'sbalit sekce menu', 'description' =&gt; 'pokud dojde k deaktivaci, lev sti menu budou vdy rozeny.', ], 'le_renew_services' =&gt; [ 'title' =&gt; 'pro tyto sluby pouijte certifikt froxloru let\'s encrypt', 'description' =&gt; 'pokud je nastavena hodnota none (nebo je ne uveden pkaz renew-hook przdn), nebudou u vybranch slueb provedeny dn pravy konfigurace tkajc se ssl.&lt;br&gt;&lt;br&gt;pkaz reload-command pro vybran sluby ml bt pidn pkazu renew-hook, jinak se zmny konfigurace nebo obnoven certifikty nemus sprvn pout.', ], 'le_renew_hook' =&gt; [ 'title' =&gt; 'pkaz renew-hook programu let\'s encrypt', 'description' =&gt; 'nastavte pkaz, kter restartuje vybran sluby, aby sluba mohla obnoven certifikty sprvn pouvat.', ], ], 'spf' =&gt; [ 'use_spf' =&gt; [ 'title' =&gt; 'aktivovat spf pro domny?', 'description' =&gt; 'vyaduje pro domnu uritou poloku dns. pokud nepouvte funkci nameserver, budete muset tyto poloky run spravovat.', ], 'spf_entry' =&gt; 'spf poloka pro vechny domny', ], 'dmarc' =&gt; [ 'use_dmarc' =&gt; [ 'title' =&gt; 'aktivovat dmarc pro domny?', 'description' =&gt; 'vyaduje pro domnu uritou poloku dns. pokud nepouvte funkci nameserver, budete muset tyto poloky run spravovat.', ], 'dmarc_entry' =&gt; 'dmarc zznam pro vechny domny', ], 'ssl_certificates' =&gt; [ 'certificate_for' =&gt; 'certifikt pro', 'valid_from' =&gt; 'platn od', 'valid_until' =&gt; 'platn do', 'issuer' =&gt; 'vydavatel', ], 'success' =&gt; [ 'success' =&gt; 'informace', 'clickheretocontinue' =&gt; 'kliknte zde pro pokraovn', 'settingssaved' =&gt; 'nastaven bylo spn uloeno.', 'rebuildingconfigs' =&gt; 'spn vloen koly pro obnoven konfiguranch soubor', 'domain_import_successfully' =&gt; 'spn importovno %s domn.', 'exportscheduled' =&gt; 'vae exportn loha byla naplnovna. pokejte prosm na jej zpracovn', 'exportaborted' =&gt; 'v plnovan export byl zruen', 'dns_record_added' =&gt; 'zznam byl spn pidn', 'dns_record_deleted' =&gt; 'zznam byl spn odstrann', 'testmailsent' =&gt; 'testovac e-mail byl spn odesln', 'settingsimported' =&gt; 'nastaven bylo spn importovno', 'sent_error_report' =&gt; 'hlen chybch bylo spn odeslno. dkujeme za v pspvek.', ], 'tasks' =&gt; [ 'outstanding_tasks' =&gt; 'nevyzen lohy', 'rebuild_vhost' =&gt; 'obnoven konfigurace webserveru', 'create_home' =&gt; 'pidvn novho zkaznka %s', 'rebuild_dns' =&gt; 'obnoven bind konfigurace', 'create_ftp' =&gt; 'vytven adrese pro novho uivatele ftp-user', 'delete_customer_files' =&gt; 'mazn zkaznickch soubor %s', 'noneoutstanding' =&gt; 'v souasn dob nejsou dn nevyzen koly pro froxlor', 'delete_email_data' =&gt; 'odstranit e-mailov data zkaznka.', 'delete_ftp_data' =&gt; 'odstranit data ftp tu.', 'rebuild_rspamd' =&gt; 'obnoven konfigurace antispamu.', 'create_quota' =&gt; 'nastavit kvtu na souborovm systmu', 'rebuild_cron' =&gt; 'obnoven cron.d-souboru', 'create_customer_datadump' =&gt; 'loha pro export dat pro zkaznka %s', 'delete_domain_pdns' =&gt; 'odstranit domnu %s z databze powerdns', 'delete_domain_ssl' =&gt; 'odstranit ssl soubory domny %s', ], 'terms' =&gt; 'podmnky pouit', 'traffic' =&gt; [ 'month' =&gt; 'msc', 'day' =&gt; 'den', 'months' =&gt; [ 1 =&gt; 'leden', 2 =&gt; 'nor', 3 =&gt; 'bezen', 4 =&gt; 'duben', 5 =&gt; 'kvten', 6 =&gt; 'erven', 7 =&gt; 'ervenec', 8 =&gt; 'srpen', 9 =&gt; 'z', 10 =&gt; 'jen', 11 =&gt; 'listopad', 12 =&gt; 'prosinec', 'jan' =&gt; 'led', 'feb' =&gt; 'n', 'mar' =&gt; 'be', 'apr' =&gt; 'dub', 'may' =&gt; 'kv', 'jun' =&gt; 'vn', 'jul' =&gt; 'vc', 'aug' =&gt; 'srp', 'sep' =&gt; 'z', 'oct' =&gt; 'j', 'nov' =&gt; 'lis', 'dec' =&gt; 'pro', 'total' =&gt; 'celkem', ], 'mb' =&gt; 'provoz', 'sumtotal' =&gt; 'celkov provoz', 'sumhttp' =&gt; 'http provoz', 'sumftp' =&gt; 'ftp provoz', 'summail' =&gt; 'penos e-mail', 'customer' =&gt; 'zkaznk', 'domain' =&gt; 'domna', 'trafficoverview' =&gt; 'shrnut provozu', 'bycustomers' =&gt; 'provoz podle zkaznk', 'details' =&gt; 'podrobnosti', 'http' =&gt; 'http', 'ftp' =&gt; 'ftp', 'mail' =&gt; 'mail', 'nocustomers' =&gt; 'potebujete alespo jednoho zkaznka pro zobrazen statistik provozu.', 'top5customers' =&gt; 'top 5 zkaznk', 'nodata' =&gt; 'pro dan rozsah nebyla nalezena dn data.', 'ranges' =&gt; [ 'last24h' =&gt; 'poslednch 24 hodin', 'last7d' =&gt; 'poslednch 7 dn', 'last30d' =&gt; 'poslednch 30 dn', 'cm' =&gt; 'aktuln msc', 'last3m' =&gt; 'posledn 3 msce', 'last6m' =&gt; 'poslednch 6 msc', 'last12m' =&gt; 'poslednch 12 msc', 'cy' =&gt; 'aktuln rok', ], 'byrange' =&gt; 'ureno podle rozsahu', ], 'translator' =&gt; '', 'update' =&gt; [ 'updateinprogress_onlyadmincanlogin' =&gt; 'byla nainstalovna novj verze froxloru, ale jet nebyla nastavena.&lt;br /&gt;pouze sprvce se pihlsit dokonit aktualizaci.', 'update' =&gt; 'aktualizace froxloru', 'proceed' =&gt; 'pokraovat', 'update_information' =&gt; [ 'part_a' =&gt; 'froxlor soubory byly aktualizovny na verzi &lt;strong&gt;%s&lt;/strong&gt;. nainstalovan verze je &lt;strong&gt;%s&lt;/strong&gt;.', 'part_b' =&gt; '&lt;br /&gt;&lt;br /&gt;zkaznci se nebudou moci pihlsit, dokud nebude aktualizace dokonena.&lt;br /&gt;&lt;strong&gt;pokraovat?&lt;/strong&gt;', ], 'noupdatesavail' =&gt; 'ji mte nejnovj verzi %sfroxlor nainstalovanou.', 'description' =&gt; 'probh aktualizace databze pro vai instalaci froxlor', 'uc_newinfo' =&gt; 'k dispozici je novj verze %s: "%s" (vae aktuln verze je: %s)', 'notify_subject' =&gt; 'k dispozici je nov aktualizace', 'dbupdate_required' =&gt; 'froxlor soubory byly aktualizovny, je vyadovna aktualizace databze', ], 'usersettings' =&gt; [ 'custom_notes' =&gt; [ 'title' =&gt; 'vlastn poznmky', 'description' =&gt; 'nebojte se zde vloit jakkoliv poznmky, kter chcete/potebujete. zobraz se v pehledu sprvce/zkaznka pro pslunho uivatele.&lt;br&gt;markdown je podporovn, html bude odstranno.', 'show' =&gt; 'zobrazit sv poznmky na nstnce uivatele', ], 'api_allowed' =&gt; [ 'title' =&gt; 'povolit pstup k api', 'description' =&gt; 'pokud je povoleno v nastaven, tento uivatel vytvoit api kle pistupovat k froxlor api', 'notice' =&gt; 'pstup k api nen povolen pro v et.', ], 'gui_access' =&gt; [ 'title' =&gt; 'povolit pihlen webui', 'description' =&gt; 'pokud je zakzno, uivatel se neme pihlsit froxlor web-ui, ale vechny sluby (web, ftp, mail, databze, api-pstup atd.) budou fungovat normln.', ], ], 'install' =&gt; [ 'slogan' =&gt; 'panel pro sprvu serveru froxlor', 'preflight' =&gt; 'kontrola systmu', 'critical_error' =&gt; 'kritick chyba', 'suggestions' =&gt; 'nen vyadovno, ale doporuuje se', 'phpinfosuccess' =&gt; 'v systm b php %s', 'phpinfowarn' =&gt; 'v systm b na ni verzi ne php %s', 'phpinfoupdate' =&gt; 'aktualizujte vai aktuln verzi php z %s na %s nebo vy', 'start_installation' =&gt; 'spustit instalaci', 'check_again' =&gt; 'znovu natte zkontrolujte', 'switchmode_advanced' =&gt; 'zobrazit rozen monosti', 'switchmode_basic' =&gt; 'skrt rozen monosti', 'dependency_check' =&gt; [ 'title' =&gt; 'vtejte froxloru', 'description' =&gt; 'zkontrolujeme zvislost systmu, abychom zajistili, e budou povolena vechna poadovan php rozen moduly, aby froxlor bel sprvn.', ], 'database' =&gt; [ 'top' =&gt; 'databze', 'title' =&gt; 'vytvoit databzi uivatele', 'description' =&gt; 'froxlor vyaduje databzi navc &lt;a href="https://docs.froxlor.org/latest/general/installation/tarball.html#_3-create-privileged-database-user" target="_blank"&gt;privilegovanho uivatele&lt;/a&gt;, aby mohl vytvet uivatele databze (volba grant). dan databze neprivilegovan databzov uivatel bude vytvoen v tomto procesu. oprvnn uivatel mus existovat.', 'user' =&gt; 'neoprvnn databzov uivatel', 'dbname' =&gt; 'nzev databze', 'force_create' =&gt; 'zlohovat pepsat databzi, pokud existuje?', ], 'admin' =&gt; [ 'top' =&gt; 'admin uivatel', 'title' =&gt; 'pojme vytvoit hlavnho administrtora.', 'description' =&gt; 'tomuto uivateli budou udlena vechna oprvnn pro pravu nastaven pidvn/aktualizace/mazn zdroj, jako jsou zkaznci, domny, atd.', 'use_admin_email_as_sender' =&gt; 'pouijte uvedenou e-mailovou adresu jako adresu odeslatele. pokud nen zakrtnuto, zadejte prosm ne uvedenou adresu odeslatele.', 'use_autogenerated_email_as_sender' =&gt; 'ponechte przdn pro vchoz: admin@nzevserveru', ], 'system' =&gt; [ 'top' =&gt; 'systmov nastaven', 'title' =&gt; 'podrobnosti vaem serveru', 'description' =&gt; 'nastavte si sv prosted stejn jako data monosti souvisejc se serverem, aby se froxlor mohl dozvdt vaem systmu. tyto hodnoty jsou klov pro konfiguraci fungovn systmu.', 'ipv4' =&gt; 'primrn ipv4 adresa (pouije-li se)', 'ipv6' =&gt; 'primrn ipv6 adresa (pouije-li se)', 'servername' =&gt; 'nzev serveru (fqdn, dn ip-adresa)', 'phpbackend' =&gt; 'php backend', 'activate_newsfeed' =&gt; 'povolit oficiln novinky&lt;br&gt;&lt;small&gt;(extern zdroj: https://inside.froxlor.org/news/)&lt;/small&gt;', ], 'install' =&gt; [ 'top' =&gt; 'dokonit nastaven', 'title' =&gt; 'posledn krok...', 'description' =&gt; 'ne uveden pkaz sthne, nainstaluje nakonfiguruje poadovan sluby vaem systmu podle daj, kter jste zadali v tomto instalanm procesu.&lt;br&gt;&lt;br&gt;&lt;span class="text-danger"&gt;nezapomete spustit nsledujc pkaz jako &lt;b&gt;root&lt;/b&gt; na shell/terminl serveru &lt;b&gt;uvdomte si&lt;/b&gt;, e tento pkaz &lt;b&gt;pepe&lt;/b&gt; jakoukoli existujc konfiguraci pro pouit sluby (budou vytvoeny zlohy)!.&lt;br&gt;pokud nechcete pepsat dn konfigurace, vyberte monost &lt;i&gt;nakonfiguruji sluby run&lt;/i&gt; v doln sti tto strnky!&lt;/span&gt;', 'runcmd' =&gt; 'spuste nsledujc pkaz pro dokonen instalace:', 'manual_config' =&gt; 'sluby nakonfiguruji run, sta pesmrovat k pihlen', 'waitforconfig' =&gt; 'ekn na konfiguraci slueb...', ], 'errors' =&gt; [ 'wrong_ownership' =&gt; 'ujistte se, e soubory froxlor jsou vlastnny %s:%s', 'missing_extensions' =&gt; 'nsledujc php rozen jsou vyadovna nejsou nainstalovna', 'suggestedextensions' =&gt; 'nsledujc php rozen se nepodailo najt, ale jsou doporueny', 'databaseexists' =&gt; 'databze ji existuje, prosm nastavte monost pepsn pro obnovu nebo zvolte jin nzev', 'unabletocreatedb' =&gt; 'nelze vytvoit testovac databzi', 'unabletodropdb' =&gt; 'nelze zruit zkuebn databzi', 'mysqlusernameexists' =&gt; 'uivatel uren pro uivatele bez oprvnn ji existuje. pouijte prosm jin uivatelsk jmno, nebo jej odstrate.', 'unabletocreateuser' =&gt; 'nelze vytvoit testovacho uivatele', 'unabletodropuser' =&gt; 'nelze zruit testovac uivatele', 'unabletoflushprivs' =&gt; 'zadan privilegovan uivatel neme vymazat oprvnn', 'nov4andnov6ip' =&gt; 'mus bt zadna adresa ipv4 nebo ipv6', 'servernameneedstobevalid' =&gt; 'zadan nzev serveru se nezd bt fqdn nebo hostname', 'websrvuserdoesnotexist' =&gt; 'zd se, e uivatel webovho serveru v systmu neexistuje', 'websrvgrpdoesnotexist' =&gt; 'zd se, e dan webserverov skupina v systmu neexistuje', 'notyetconfigured' =&gt; 'zd se, e sluby jet nebyly nakonfigurovny (spn). provete prosm pkaz ne nebo zakrtnte polko pro pozdj zpracovn.', 'mandatory_field_not_set' =&gt; 'povinn pole "%s" nen nastaveno!', 'unexpected_database_error' =&gt; 'dolo k neoekvan vjimce databze. %s', 'sql_import_failed' =&gt; 'nepodailo se importovat sql data!', 'unprivileged_sql_connection_failed' =&gt; 'nepodailo se inicializovat neprivilegovan sql pipojen!', 'privileged_sql_connection_failed' =&gt; 'nepodailo se inicializovat privilegovan sql pipojen!', 'mysqldump_backup_failed' =&gt; 'nelze vytvoit zlohu databze, dolo k chyb mysqldump.', 'sql_backup_file_missing' =&gt; 'nelze vytvoit zlohu databze, zlon soubor neexistuje.', 'backup_binary_missing' =&gt; 'nelze vytvoit zlohu databze, ujistte se, e jste nainstalovali mysqldump.', 'creating_configfile_failed' =&gt; 'nelze vytvoit konfiguran soubory, nelze zapisovat souboru.', 'database_already_exiting' =&gt; 'nali jsme databzi nebylo mon ji pepsat!' ] ], 'welcome' =&gt; [ 'title' =&gt; 'vtejte froxloru!', 'config_note' =&gt; 'aby mohl froxlor sprvn komunikovat se zlohou, muste ji nakonfigurovat.', 'config_now' =&gt; 'nastavit nyn' ], ];</file><file name="lng/ca.lng.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'languages' =&gt; [ 'cz' =&gt; 'txec', 'de' =&gt; 'alemany', 'en' =&gt; 'angles', 'fr' =&gt; 'frances', 'it' =&gt; 'italia', 'nl' =&gt; 'holandes', 'pt' =&gt; 'portugues', 'se' =&gt; 'suec', 'es' =&gt; 'espanyol', 'ca' =&gt; 'catala', ], '2fa' =&gt; [ '2fa' =&gt; 'opcions 2fa', '2fa_enabled' =&gt; 'activar l\'autenticaci de dos factors (2fa)', '2fa_removed' =&gt; '2fa eliminat correctament', '2fa_added' =&gt; '2fa activat correctament&lt;br /&gt;&lt;a class="alert-link" href="%s?page=2fa"&gt;veure detalls de 2fa&lt;/a&gt;', '2fa_add' =&gt; 'activar 2fa', '2fa_delete' =&gt; 'desactivar 2fa', '2fa_verify' =&gt; 'verificar codi', '2fa_overview_desc' =&gt; 'aqu podeu activar una autenticaci de dos factors per al vostre compte.&lt;br/&gt;&lt;br/&gt;podeu utilitzar una aplicaci d\'autenticaci (contrasenya d\'un sol basada en el temps / totp) deixar que froxlor us envi un correu electrnic l\'adrea del vostre compte desprs de cada inici de sessi correcte amb una contrasenya d\'un sol s.', '2fa_email_desc' =&gt; 'el vostre compte est configurat per utilitzar contrasenyes d\'un sol per cada correu electrnic. per desactivar-la, feu clic "desactivar 2fa".', '2fa_ga_desc' =&gt; 'el vostre compte est configurat per utilitzar contrasenyes d\'un sol basades en el temps mitjanant una aplicaci d\'autenticaci. escanegeu el codi qr que apareix continuaci amb l\'aplicaci d\'autenticaci que vulgueu per generar els codis. per desactivar, feu clic "desactivar 2fa".' ], 'admin' =&gt; [ 'overview' =&gt; 'visi general', 'ressourcedetails' =&gt; 'recursos utilitzats', 'systemdetails' =&gt; 'detalls del sistema', 'froxlordetails' =&gt; 'detalls de froxlor', 'installedversion' =&gt; 'versi installada', 'latestversion' =&gt; 'ltima versi', 'lookfornewversion' =&gt; [ 'clickhere' =&gt; 'cerca mitjanant el servei web', 'error' =&gt; 'error de lectura' ], 'resources' =&gt; 'recursos', 'customer' =&gt; 'client', 'customers' =&gt; 'clients', 'customers_list_desc' =&gt; 'gestioni els seus clients', 'customer_add' =&gt; 'crear client', 'customer_edit' =&gt; 'editar client', 'username_default_msg' =&gt; 'deixar buit per al valor autogenerat', 'domains' =&gt; 'dominis', 'domain_add' =&gt; 'crear domini', 'domain_edit' =&gt; 'editar domini', 'subdomainforemail' =&gt; 'subdominis com dominis de correu electrnic', 'admin' =&gt; 'administrador', 'admins' =&gt; 'administradors', 'admin_add' =&gt; 'crear administrador', 'admin_edit' =&gt; 'editar administrador', 'customers_see_all' =&gt; 'pot accedir als recursos d\'altres administradors/revenedors?', 'change_serversettings' =&gt; 'pot canviar la configuraci del servidor?', 'server' =&gt; 'sistema', 'serversettings' =&gt; 'ajustos', 'serversettings_desc' =&gt; 'administrar el sistema froxlor', 'rebuildconf' =&gt; 'reconstruir arxius de configuraci', 'stdsubdomain' =&gt; 'subdomini estndard', 'stdsubdomain_add' =&gt; 'crear subdomini estndard', 'phpenabled' =&gt; 'php habilitat', 'deactivated' =&gt; 'desactivat', 'deactivated_user' =&gt; 'desactivar usuari', 'sendpassword' =&gt; 'enviar contrasenya', 'ownvhostsettings' =&gt; 'configuraci vhost prpia', 'configfiles' =&gt; [ 'serverconfiguration' =&gt; 'configuraci', 'overview' =&gt; 'visi general', 'wizard' =&gt; 'assistent', 'distribution' =&gt; 'distribuci', 'service' =&gt; 'servei', 'daemon' =&gt; 'dimoni', 'http' =&gt; 'servidor web (http)', 'dns' =&gt; 'servidor de noms (dns)', 'mail' =&gt; 'servidor de correu (imap/pop3)', 'smtp' =&gt; 'servidor de correu (smtp)', 'ftp' =&gt; 'servidor ftp', 'etc' =&gt; 'altres (sistema)', 'choosedistribution' =&gt; '-- esculli una distribuci --', 'chooseservice' =&gt; '-- esculli un servei --', 'choosedaemon' =&gt; '-- esculli un dimoni --', 'statistics' =&gt; 'estadstiques', 'compactoverview' =&gt; 'vista general compacta', 'legend' =&gt; '&lt;h3&gt;est punt de configurar un servei/dimoni&lt;/h3&gt;', 'commands' =&gt; '&lt;span class="text-danger"&gt;ordres:&lt;/span&gt; aquestes ordres han de ser executades lnia per lnia com usuari root en una shell. segur copiar tot el bloc enganxar-lo l\'intrpret d\'ordres.', 'files' =&gt; '&lt;span class="text-danger"&gt;fitxers de configuraci:&lt;/span&gt; les ordres abans dels camps de text han d\'obrir un editor amb el fitxer de dest. noms de copiar enganxar el contingut l\'editor desar el fitxer.&lt;br /&gt;&lt;span class="text-danger"&gt;nota:&lt;/span&gt; la contrasenya mysql ha estat reemplaada per raons de seguretat. si us plau, reemplaa "froxlor_mysql_password" pel teu compte fes servir el formulari javascript de sota per reemplaar-la situ. si oblidat la teva contrasenya mysql la trobars "lib/userdata.inc.php".', 'importexport' =&gt; 'importar/exportar', 'finishnote' =&gt; 'fitxer de parmetres generat correctament. ara executeu la segent ordre com root:', 'description' =&gt; 'configurar els serveis del sistema', 'minihowto' =&gt; 'en aquesta pgina podeu veure les diferents plantilles de configuraci per cada servei, (re)configurar serveis especfics si cal exportar la selecci actual un fitxer json per utilitzar-lo als scripts cli en un altre servidor.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;tingui en compte&lt;/b&gt; que els serveis ressaltats reflecteixen la configuraci actual, sin que mostren requisits/recomanacions dels seus valors de configuraci actuals.', 'skipconfig' =&gt; 'no (re)configurar', 'recommendednote' =&gt; 'serveis recomanats/requerits segons la configuraci actual del sistema', 'selectrecommended' =&gt; 'seleccionar recomanats', 'downloadselected' =&gt; 'exportar seleccionat' ], 'templates' =&gt; [ 'templates' =&gt; 'plantilles de correu electrnic', 'template_add' =&gt; 'afegir plantilla', 'template_fileadd' =&gt; 'afegir plantilla de fitxer', 'template_edit' =&gt; 'editar plantilla', 'action' =&gt; 'acci', 'email' =&gt; 'plantilles de correu electrnic fitxers', 'subject' =&gt; 'assumpte', 'mailbody' =&gt; 'cos del correu', 'createcustomer' =&gt; 'correu de benvinguda per nous clients', 'pop_success' =&gt; 'correu de benvinguda per nous comptes de correu electrnic', 'template_replace_vars' =&gt; 'variables substituir la plantilla:', 'salutation' =&gt; 'substitut per una correcta salutaci (nom empresa)', 'firstname' =&gt; 'substitut pel nom del client.', 'name' =&gt; 'substitut pel nom complet del client.', 'company' =&gt; 'substitut pel nom de l\'empresa del client.', 'username' =&gt; 'substitut pel nom d\'usuari del compte del client.', 'password' =&gt; 'substitut per la contrasenya del compte del client.', 'email' =&gt; 'substitut per l\'adrea de correu electrnic del compte pop3/imap.', 'customer_no' =&gt; 'substitut pel nmero de client.', 'traffic' =&gt; 'substitut pel trnsit assignat al client.', 'trafficused' =&gt; 'substitut pel trnsit, que ha sigut esgotat pel client.', 'pop_success_alternative' =&gt; 'correu de benvinguda per nous comptes de correu electrnic enviats l\'adrea alternativa.', 'email_password' =&gt; 'substitut per la contrasenya del compte pop3/imap.', 'index_html' =&gt; 'arxiu d\'ndex per directoris de clients acabats de crear', 'servername' =&gt; 'substitut pel nom del servidor.', 'customer' =&gt; 'substitut pel nom d\'usuari del client.', 'admin' =&gt; 'substitut pel nom d\'usuari de l\'administrador.', 'customer_email' =&gt; 'substitut per l\'adrea de correu electrnic del client.', 'admin_email' =&gt; 'substitut per l\'adrea de correu electrnic de l\'administrador.', 'filetemplates' =&gt; 'plantilles de fitxers', 'filecontent' =&gt; 'contingut del fitxer', 'new_database_by_customer' =&gt; 'notificaci al client de la creaci d\'una base de dades', 'new_ftpaccount_by_customer' =&gt; 'notificaci al client de la creaci d\'un usuari ftp', 'newdatabase' =&gt; 'correus de notificaci per noves bases de dades', 'newftpuser' =&gt; 'correus de notificaci per nous usuaris ftp', 'cust_name' =&gt; 'nom del client', 'db_name' =&gt; 'nom de la base de dades', 'db_pass' =&gt; 'contrasenya de la base de dades', 'db_desc' =&gt; 'descripci de la base de dades', 'db_srv' =&gt; 'servidor de base de dades', 'pma_uri' =&gt; 'url de phpmyadmin (si s\'indica)', 'usr_name' =&gt; 'nom d\'usuari ftp', 'usr_pass' =&gt; 'contrasenya ftp', 'usr_path' =&gt; 'directori home de l\'ftp (relatiu customer-docroot)', 'forgotpwd' =&gt; 'correus de notificaci de restabliment de contrasenya', 'password_reset' =&gt; 'notificaci al client de restabliment de contrasenya', 'trafficmaxpercent' =&gt; 'correu de notificaci per als clients quan s\'esgota un determinat percentatge mxim de trnsit', 'max_percent' =&gt; 'substitut pel lmit de l\'s del disc/trnsit per l\'enviament d\'informes en percentatge.', 'usage_percent' =&gt; 'substitut amb l\'s del disc/trnsit esgotat pel client en percentatge.', 'diskmaxpercent' =&gt; 'correu de notificaci als clients quan s\'esgota el percentatge mxim d\'espai al disc.', 'diskavailable' =&gt; 'substitut per l\'s de disc assignat al client.', 'diskused' =&gt; 'substitut per l\'s de disc, que ha sigut esgotat pel client.', 'link' =&gt; 'substitut per l\'enlla de restabliment de contrasenya del client.', 'server_hostname' =&gt; 'reemplaa el nom del sistema (url froxlor)', 'server_ip' =&gt; 'reemplaa l\'adrea ip per defecte del servidor ', 'server_port' =&gt; 'reemplaa el port per defecte del servidor', 'domainname' =&gt; 'reemplaa el subdomini estndard del client (pot estar buit si se\'n genera cap)' ], 'webserver' =&gt; 'servidor web', 'createzonefile' =&gt; 'crear zona dns pel domini', 'custombindzone' =&gt; 'arxiu de zona personalitzatada / gestionada', 'bindzonewarning' =&gt; 'buit per defecte&lt;br /&gt;&lt;strong class="text-danger"&gt;atenci:&lt;/strong&gt; si utilitza un fitxer de zones, haur de gestionar tamb manualment tots els registres necessaris per totes les subzones.', 'ipsandports' =&gt; [ 'ipsandports' =&gt; 'ips ports', 'add' =&gt; 'afegir ip/port', 'edit' =&gt; 'editar ip/port', 'ipandport' =&gt; 'ip/port', 'ip' =&gt; 'ip', 'ipnote' =&gt; '&lt;div id="ipnote" class="invalid-feedback"&gt;nota: tot que les adreces ip privades estan permeses, algunes caracterstiques com dns podrien comportar-se correctament.&lt;br /&gt;noms utilitzi adreces ip privades si est segur.&lt;/div&gt;', 'port' =&gt; 'port', 'create_listen_statement' =&gt; 'crear sentncia listen', 'create_namevirtualhost_statement' =&gt; 'crear sentncia namevirtualhost', 'create_vhostcontainer' =&gt; 'crear vhost-container', 'create_vhostcontainer_servername_statement' =&gt; 'crear sentncia servername vhost-container', 'enable_ssl' =&gt; 'es tracta d\'un port ssl?', 'ssl_cert_file' =&gt; 'ruta del certificat ssl', 'webserverdefaultconfig' =&gt; 'configuraci per defecte del servidor web', 'webserverdomainconfig' =&gt; 'configuraci de domini del servidor web', 'webserverssldomainconfig' =&gt; 'configuraci ssl del servidor web', 'ssl_key_file' =&gt; 'ruta del fitxer de claus ssl', 'ssl_ca_file' =&gt; 'ruta del certificat ssl ca', 'default_vhostconf_domain' =&gt; 'configuraci vhost per defecte per cada contenidor de domini', 'ssl_cert_chainfile' =&gt; [ 'title' =&gt; 'ruta del fitxer ssl certificatechainfile', 'description' =&gt; 'normalment ca_bundle, similar, probablement vols configurar aix si comprat un certificat ssl.' ], 'docroot' =&gt; [ 'title' =&gt; 'docroot personalizat (buit = apunta froxlor)', 'description' =&gt; 'aqu podeu definir un document-root personalitzat (el dest d\'una petici) per aquesta combinaci ip/port.&lt;br/&gt;&lt;strong&gt;atenci:&lt;/strong&gt; si us plau, vs amb compte amb el que introdueixes aqu!' ], 'ssl_paste_description' =&gt; 'enganxi el contingut complet del vostre certificat al quadre de text', 'ssl_cert_file_content' =&gt; 'contingut del certificat ssl', 'ssl_key_file_content' =&gt; 'contingut del fitxer de la clau ssl (privada)', 'ssl_ca_file_content' =&gt; 'contingut del fitxer ssl ca (opcional)', 'ssl_ca_file_content_desc' =&gt; '&lt;br/&gt;&lt;br/&gt;autenticaci del client, configuri aix noms si sap el que s.', 'ssl_cert_chainfile_content' =&gt; 'contingut del fitxer de cadena de certificats (opcional)', 'ssl_cert_chainfile_content_desc' =&gt; '&lt;br/&gt;&lt;br/&gt;normalment ca_bundle, similar, probablement vols configurar aix si comprat un certificat ssl.', 'ssl_default_vhostconf_domain' =&gt; 'configuraci ssl vhost per defecte per cada contenidor de domini' ], 'memorylimitdisabled' =&gt; 'desactivat', 'valuemandatory' =&gt; 'aquest valor obligatori', 'valuemandatorycompany' =&gt; 'o b "nom" "nom complet" "empresa" ha de ser omplert', 'serversoftware' =&gt; 'programari del servidor', 'phpversion' =&gt; 'versi php', 'mysqlserverversion' =&gt; 'versi del servidor mysql', 'webserverinterface' =&gt; 'interfcie del servidor web', 'accountsettings' =&gt; 'configuraci del compte', 'panelsettings' =&gt; 'configuraci del panell', 'systemsettings' =&gt; 'configuraci del sistema', 'webserversettings' =&gt; 'configuraci del servidor web', 'mailserversettings' =&gt; 'configuraci del servidor de correu', 'nameserversettings' =&gt; 'configuraci del servidor de noms', 'updatecounters' =&gt; 'recalcular l\'s de recursos', 'subcanemaildomain' =&gt; [ 'never' =&gt; 'mai', 'choosableno' =&gt; 'seleccionable, per defecte no', 'choosableyes' =&gt; 'seleccionable, per defecte s', 'always' =&gt; 'sempre' ], 'wipecleartextmailpwd' =&gt; 'esborrar contrasenyes en text pla', 'webalizersettings' =&gt; 'configuraci de webalizer', 'webalizer' =&gt; [ 'normal' =&gt; 'normal', 'quiet' =&gt; 'silencis', 'veryquiet' =&gt; 'no mostra res' ], 'domain_nocustomeraddingavailable' =&gt; 'actualment possible afegir un domini. primer ha d\'afegir almenys un client.', 'loggersettings' =&gt; 'configuraci del registre', 'logger' =&gt; [ 'normal' =&gt; 'normal', 'paranoid' =&gt; 'paranoic' ], 'emaildomain' =&gt; 'correu de domini', 'email_only' =&gt; 'noms correu electrnic?', 'wwwserveralias' =&gt; 'afageix un "www." serveralias', 'subject' =&gt; 'assumpte', 'recipient' =&gt; 'destinatari', 'message' =&gt; 'escriure un missatge', 'text' =&gt; 'missatge', 'sslsettings' =&gt; 'configuraci ssl', 'specialsettings_replacements' =&gt; 'pot utilitzar les segents variables:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (si escau)&lt;br/&gt;', 'dkimsettings' =&gt; 'configuraci de dkim', 'caneditphpsettings' =&gt; 'pot canviar els parmetres de domini relacionats amb php?', 'allips' =&gt; 'totes les ip', 'awstatssettings' =&gt; 'configuraci de awstats', 'domain_dns_settings' =&gt; 'configuraci dns del domini', 'activated' =&gt; 'activat', 'statisticsettings' =&gt; 'configuraci d\'estadstiques', 'or' =&gt; 'o', 'sysload' =&gt; 'crrega del sistema', 'noloadavailable' =&gt; 'no disponible', 'nouptimeavailable' =&gt; 'no disponible', 'nosubject' =&gt; '(sense assumpte)', 'security_settings' =&gt; 'opcions de seguretat', 'know_what_youre_doing' =&gt; 'canviar noms si sap el que fa!', 'show_version_login' =&gt; [ 'title' =&gt; 'mostra la versi de froxlor l\'inici de sessi', 'description' =&gt; 'mostrar la versi de froxlor al peu de pgina la pgina d\'inici de sessi' ], 'show_version_footer' =&gt; [ 'title' =&gt; 'mostrar la versi de froxlor al peu de pgina', 'description' =&gt; 'mostrar la versi de froxlor al peu de pgina de la resta de pgines' ], 'froxlor_graphic' =&gt; [ 'title' =&gt; 'grfic de capalera per froxlor', 'description' =&gt; 'quin grfic s\'ha de mostrar la capalera' ], 'phpsettings' =&gt; [ 'title' =&gt; 'configuraci php', 'description' =&gt; 'breu descripci', 'actions' =&gt; 'accions', 'activedomains' =&gt; 'en per domini(s)', 'notused' =&gt; 'configuraci en s', 'editsettings' =&gt; 'canviar configuraci php', 'addsettings' =&gt; 'crear nova configuraci php', 'viewsettings' =&gt; 'veure la configuraci php', 'phpinisettings' =&gt; 'configuraci php.ini', 'addnew' =&gt; 'crear nova configuraci php', 'binary' =&gt; 'php binari', 'fpmdesc' =&gt; 'configuraci php-fpm', 'file_extensions' =&gt; 'extensions de fitxers', 'file_extensions_note' =&gt; '(sense punt, separades per espais)', 'enable_slowlog' =&gt; 'activar slowlog (per domini)', 'request_terminate_timeout' =&gt; 'sollicitar terminate-timeout', 'request_slowlog_timeout' =&gt; 'sollicitar slowlog-timeout', 'activephpconfigs' =&gt; 'en per php-config(s)', 'pass_authorizationheader' =&gt; 'afegeix les capaleres http auth basic/digest de l\'apache cap al php' ], 'misc' =&gt; 'varis', 'fpmsettings' =&gt; [ 'addnew' =&gt; 'crear nova versi php', 'edit' =&gt; 'canviar versi php' ], 'phpconfig' =&gt; [ 'template_replace_vars' =&gt; 'variables que seran reemplaades les configs', 'pear_dir' =&gt; 'ser reemplaada amb la configuraci global per al directori pear.', 'open_basedir_c' =&gt; 's\'inserir un ; (punt coma) per comentar/desactivar open_basedir quan s\'estableixi', 'open_basedir' =&gt; 'es substituir per la configuraci open_basedir del domini.', 'tmp_dir' =&gt; 'ser reemplaat pel directori temporal del domini.', 'open_basedir_global' =&gt; 'es substituir pel valor global de la ruta que s\'adjuntar open_basedir (veure configuraci del servidor web).', 'customer_email' =&gt; 'es substituir per l\'adrea de correu electrnic del client propietari del domini.', 'admin_email' =&gt; 'es substituir per l\'adrea de correu electrnic de l\'administrador propietari del domini.', 'domain' =&gt; 'es substituir pel domini.', 'customer' =&gt; 'es substituir pel nom d\'usuari del client propietari del domini.', 'admin' =&gt; 'es substituir pel nom d\'usuari de l\'administrador propietari del domini.', 'docroot' =&gt; 'es substituir per l\'arrel del document del domini.', 'homedir' =&gt; 'es substituir pel directori arrel del client.' ], 'expert_settings' =&gt; 'configuraci experta!', 'mod_fcgid_starter' =&gt; [ 'title' =&gt; 'processos php per aquest domini (buit per defecte)' ], 'phpserversettings' =&gt; 'configuracions de php', 'mod_fcgid_maxrequests' =&gt; [ 'title' =&gt; 'peticions php mximes per aquest domini (buit per defecte)' ], 'spfsettings' =&gt; 'configuraci spf del domini', 'specialsettingsforsubdomains' =&gt; 'aplicar configuraci especial tots els subdominis (*.exemple.com)', 'accountdata' =&gt; 'dades del compte', 'contactdata' =&gt; 'dades de contacte', 'servicedata' =&gt; 'dades de servei', 'newerversionavailable' =&gt; 'hi ha una nova versi de froxlor disponible.', 'newerversiondetails' =&gt; 'actualitzi ara la versi &lt;b&gt;%s&lt;/b&gt;?&lt;br/&gt;(la seva versi actual s: %s)', 'extractdownloadedzip' =&gt; 'extreure el fitxer descarregat "%s"?', 'cron' =&gt; [ 'cronsettings' =&gt; 'configuraci de tasques de cron', 'add' =&gt; 'afegir tasca cron' ], 'cronjob_edit' =&gt; 'editar tasques de cron', 'warning' =&gt; 'avs - tingueu en compte!', 'lastlogin_succ' =&gt; 'darrer inici de sessi', 'ftpserver' =&gt; 'servidor ftp', 'ftpserversettings' =&gt; 'configuraci del servidor ftp', 'webserver_user' =&gt; 'nom d\'usuari del servidor web', 'webserver_group' =&gt; 'nom de grup del servidor web', 'perlenabled' =&gt; 'perl activat', 'fcgid_settings' =&gt; 'fcgid', 'mod_fcgid_user' =&gt; 'usuari local utilitzar per fcgid (froxlor vhost)', 'mod_fcgid_group' =&gt; 'grup local utilitzar per fcgid (froxlor vhost)', 'perl_settings' =&gt; 'perl/cgi', 'notgiven' =&gt; '[no indicat]', 'store_defaultindex' =&gt; 'emmagatzemar el fitxer d\'ndex per defecte al docroot del client', 'phpfpm_settings' =&gt; 'php-fpm', 'traffic' =&gt; 'trnsit', 'traffic_sub' =&gt; 'detalls sobre l\'s del trnsit', 'domaintraffic' =&gt; 'dominis', 'customertraffic' =&gt; 'clients', 'assignedmax' =&gt; 'assignat / mxim', 'usedmax' =&gt; 'utilitzat / mxim', 'used' =&gt; 'utilitzat', 'speciallogwarning' =&gt; '&lt;div id="speciallogfilenote" class="invalid-feedback"&gt;avs: en canviar aquesta configuraci perdr totes les antigues estadstiques per aquest domini.&lt;/div&gt;', 'speciallogfile' =&gt; [ 'title' =&gt; 'fitxer de registre separat', 'description' =&gt; 'activi aquesta opci per obtenir un fitxer de registre d\'accs independent per aquest domini.' ], 'domain_editable' =&gt; [ 'title' =&gt; 'permetre editar el domini', 'desc' =&gt; 'si s\'estableix en "si", el client pot canviar diversos parmetres del domini.&lt;br/&gt;si s\'estableix en "no", el client pot canviar res.' ], 'writeaccesslog' =&gt; [ 'title' =&gt; 'escriure un registre d\'accs', 'description' =&gt; 'activi aquesta opci per obtenir un fitxer de registre d\'accs per aquest domini.' ], 'writeerrorlog' =&gt; [ 'title' =&gt; 'escriure un registre d\'errors', 'description' =&gt; 'activi aquesta opci per obtenir un fitxer de registre \'errors per aquest domini.' ], 'phpfpm.ininote' =&gt; 'no tots els valors que voleu definir poden ser utilitzats en la configuraci del pool php-fpm', 'phpinfo' =&gt; 'phpinfo()', 'selectserveralias' =&gt; 'valor serveralias per al domini', 'selectserveralias_desc' =&gt; 'tri si froxlor ha de crear una entrada comod (*.domini.tld), un lies www (www.domini.tld) cap lies.', 'show_news_feed' =&gt; [ 'title' =&gt; 'mostrar notcies al panell d\'administraci', 'description' =&gt; 'activi aquesta opci per mostrar les notcies oficials de froxlor (https://inside.froxlor.org/news/) al teu tauler de control perdre\'t mai informaci important anuncis de llanaments.' ], 'cronsettings' =&gt; 'configuraci de tasques de cron', 'integritycheck' =&gt; 'validaci de la base de dades', 'integrityname' =&gt; 'nom', 'integrityresult' =&gt; 'resultat', 'integrityfix' =&gt; 'soluci automtica de problemes', 'customer_show_news_feed' =&gt; 'mostrar notcies al panell del client', 'customer_news_feed_url' =&gt; [ 'title' =&gt; 'utilitzar un canal rss personalitzat', 'description' =&gt; 'especifiqui un canal rss personalitzat que es mostrar als vostres clients en el vostre tauler de control.&lt;br/&gt;&lt;small&gt;deixi aquest camp buit per utilitzar el canal de notcies oficial de froxlor (https://inside.froxlor.org/news/).&lt;/small&gt;' ], 'movetoadmin' =&gt; 'moure client', 'movecustomertoadmin' =&gt; 'mou el client l\'administrador/revenedor seleccionat&lt;br/&gt;&lt;small&gt;deixa aix buit per fer canvis.&lt;br/&gt;si l\'administrador desitjat apareix la llista, el seu lmit de clients ha estat assolit.&lt;/small&gt;', 'note' =&gt; 'nota', 'mod_fcgid_umask' =&gt; [ 'title' =&gt; 'mscara (per defecte: 022)' ], 'apcuinfo' =&gt; 'informaci apcu', 'opcacheinfo' =&gt; 'informaci opcache', 'letsencrypt' =&gt; [ 'title' =&gt; 'utilitzar let\'s encrypt', 'description' =&gt; 'obtingui un certificat gratut de &lt;a href="https://letsencrypt.org"&gt;let\'s encrypt&lt;/a&gt;. el certificat es crear renovar automticament.&lt;br /&gt;&lt;strong class="text-danger"&gt;atenci:&lt;/strong&gt; si els comodins estan activats, aquesta opci es desactivar automticament.' ], 'autoupdate' =&gt; 'actualitza automticament', 'server_php' =&gt; 'php', 'dnsenabled' =&gt; 'habilitar editor dns', 'froxlorvhost' =&gt; 'configuraci virtualhost de froxlor ', 'hostname' =&gt; 'nom de host', 'memory' =&gt; 'memria en s', 'webserversettings_ssl' =&gt; 'configuraci ssl del servidor web', 'domain_hsts_maxage' =&gt; [ 'title' =&gt; 'seguretat estricta de transport http (hsts)', 'description' =&gt; 'especifiqui el valor d\'edat mxima per la capalera strict-transport-security (sts)&lt;br/&gt;el valor &lt;i&gt;0&lt;/i&gt; desactivar hsts per al domini. la majoria dels usuaris estableixen un valor de &lt;i&gt;31536000&lt;/i&gt; (un any).' ], 'domain_hsts_incsub' =&gt; [ 'title' =&gt; 'incloure hsts per qualsevol subdomini', 'description' =&gt; 'la directiva opcional "includesubdomains", si present, indica la ua que la poltica hsts s\'aplica aquest host hsts aix com qualsevol subdomini del nom de domini del host.' ], 'domain_hsts_preload' =&gt; [ 'title' =&gt; 'incloure domini la &lt;a href="https://hstspreload.org/" target="_blank"&gt;llista de precrrega hsts&lt;/a&gt;', 'description' =&gt; 'si vol que aquest domini s\'inclogui la llista de precrrega hsts mantinguda per chrome (i utilitzada per firefox safari), activeu aquesta opci.&lt;br /&gt;l\'enviament de la directiva de precrrega des del vostre lloc pot tenir conseqncies permanents impedir que els usuaris accedeixin al seu lloc qualsevol dels seus subdominis.&lt;br /&gt;si us plau, llegiu els detalls &lt;a href="https://hstspreload.org/#removal" target="_blank"&gt;https://hstspreload .org/#removal&lt;/a&gt; abans d\'enviar la capalera amb "preload".' ], 'domain_ocsp_stapling' =&gt; [ 'title' =&gt; 'ocsp stapling', 'description' =&gt; 'consulti &lt;a target="_blank" href="https://en.wikipedia.org/wiki/ocsp_stapling"&gt;wikipedia&lt;/a&gt; per una explicaci detallada del grapat ocsp', 'nginx_version_warning' =&gt; '&lt;br /&gt;&lt;strong class="text-danger"&gt;avs:&lt;/strong&gt; es requereix la versi 1.3.7 superior de nginx per al ocsp stapling. si la vostra versi anterior, el servidor web s\'iniciar correctament mentre el grapat ocsp estigui activat!' ], 'domain_http2' =&gt; [ 'title' =&gt; 'suport http2', 'description' =&gt; 'consulti &lt;a target="_blank" href="https://en.wikipedia.org/wiki/http/2"&gt;wikipedia&lt;/a&gt; per una explicaci detallada de http2' ], 'testmail' =&gt; 'prova smtp', 'phpsettingsforsubdomains' =&gt; 'aplicar php-config tots els subdominis:', 'plans' =&gt; [ 'name' =&gt; 'nom del pla', 'description' =&gt; 'descripci', 'last_update' =&gt; 'ltima actualitzaci', 'plans' =&gt; 'plans d\'allotjament', 'plan_details' =&gt; 'detalls del pla', 'add' =&gt; 'afegir nou pla', 'edit' =&gt; 'editar pla', 'use_plan' =&gt; 'aplicar pla' ], 'notryfiles' =&gt; [ 'title' =&gt; 'no s\'autogeneren try_files', 'description' =&gt; 'digui "s" aqu si vol especificar una directiva try_files personalitzada en specialsettings (necessria per alguns plugins de wordpress).' ], 'logviewenabled' =&gt; 'habilitar accs als logs d\'accss/error', 'novhostcontainer' =&gt; '&lt;br /&gt;&lt;br /&gt;&lt;small class="text-danger"&gt;cap de les ips ports activada l\'opci "crear vhost-container", molts ajustaments aqu estaran disponibles&lt;/small&gt;', 'ownsslvhostsettings' =&gt; 'configuraci prpia de ssl vhost', 'domain_override_tls' =&gt; 'anullar la configuraci tls del sistema', 'domain_override_tls_addinfo' =&gt; '&lt;br /&gt;&lt;span class="text-danger"&gt;noms s\'utilitza si l\'opci "override system tls settings" est configurada com "s".&lt;/span&gt;', 'domain_sslenabled' =&gt; 'habilitar l\'s de ssl', 'domain_honorcipherorder' =&gt; 'respecteu l\'ordre de xifrat (servidor), per defecte &lt;strong&gt;no&lt;/strong&gt;', 'domain_sessiontickets' =&gt; 'habilitar tls sessiontickets (rfc 5077), per defecte &lt;strong&gt;s&lt;/strong&gt;', 'domain_sessionticketsenabled' =&gt; [ 'title' =&gt; 'habilitar l\'s de tls sessiontickets globalment', 'description' =&gt; 'per defecte &lt;strong&gt;s&lt;/strong&gt;&lt;br/&gt;requereix apache-2.4.11+ nginx-1.5.9+' ], 'domaindefaultalias' =&gt; 'valor per defecte de serveralias per nous dominis', 'smtpsettings' =&gt; 'configuraci smtp', 'smtptestaddr' =&gt; 'enviar correu de prova a', 'smtptestnote' =&gt; 'tingueu en compte que els valors segents reflecteixen la configuraci actual noms es poden ajustar (vegeu l\'enlla la cantonada superior dreta)', 'smtptestsend' =&gt; 'enviar correu de prova', 'mysqlserver' =&gt; [ 'mysqlserver' =&gt; 'servidor mysql', 'dbserver' =&gt; 'servidor #', 'caption' =&gt; 'descripci', 'host' =&gt; 'nom de host / ip', 'port' =&gt; 'port', 'user' =&gt; 'usuari privilegiat', 'add' =&gt; 'afegir nou servidor mysql', 'edit' =&gt; 'editar servidor mysql', 'password' =&gt; 'contrasenya d\'usuari privilegiat', 'password_emptynochange' =&gt; 'nova contrasenya, deixar buit per cap canvi', 'allowall' =&gt; [ 'title' =&gt; 'permetre l\'s d\'aquest servidor tots els clients existents actualment', 'description' =&gt; 'estableix aquesta opci "cert" si voleu permetre l\'s d\'aquest servidor de base de dades tots els clients existents perqu hi puguin afegir bases de dades. aquesta configuraci permanent, per es pot executar diverses vegades.' ], 'testconn' =&gt; 'provar la connexi en desar', 'ssl' =&gt; 'utilitzar ssl per la connexi al servidor de base de dades', 'ssl_cert_file' =&gt; 'la ruta del fitxer l\'autoritat del certificat ssl', 'verify_ca' =&gt; 'habilitar la verificaci del certificat ssl del servidor' ], 'settings_importfile' =&gt; 'escollir fitxer d\'importaci', 'documentation' =&gt; 'documentaci', 'adminguide' =&gt; 'guia de l\'administrador', 'userguide' =&gt; 'guia de l\'usuari', 'apiguide' =&gt; 'guia de la api' ], 'apcuinfo' =&gt; [ 'clearcache' =&gt; 'esborrar memria cau d\'apcu', 'generaltitle' =&gt; 'informaci general sobre la memria cau', 'version' =&gt; 'versi d\'apcu', 'phpversion' =&gt; 'versi php', 'host' =&gt; 'host apcu', 'sharedmem' =&gt; 'memria compartida', 'sharedmemval' =&gt; '%d segment(s) amb %s (%s memria)', 'start' =&gt; 'hora d\'inici', 'uptime' =&gt; 'temps d\'activitat', 'upload' =&gt; 'suport de crrega de fitxers', 'cachetitle' =&gt; 'informaci de la memria cau', 'cvar' =&gt; 'variables en memria cau', 'hit' =&gt; 'encerts', 'miss' =&gt; 'errors', 'reqrate' =&gt; 'taxa de peticions (encerts, errors)', 'creqsec' =&gt; 'peticions de memria cau/segon', 'hitrate' =&gt; 'taxa d\'encerts', 'missrate' =&gt; 'percentatge d\'errors', 'insrate' =&gt; 'taxa d\'insercions', 'cachefull' =&gt; 'recompte de memria cau plena', 'runtime' =&gt; 'configuraci de temps d\'execuci', 'memnote' =&gt; 's de memria', 'total' =&gt; 'total', 'free' =&gt; 'lliure', 'used' =&gt; 'utilitzat', 'hitmiss' =&gt; 'encerts errors', 'detailmem' =&gt; 's detallat de memria fragmentaci', 'fragment' =&gt; 'fragmentaci', 'nofragment' =&gt; 'sense fragmentaci', 'fragments' =&gt; 'fragments' ], 'apikeys' =&gt; [ 'no_api_keys' =&gt; 'no s\'han trobat claus api', 'key_add' =&gt; 'afegir una nova clau', 'apikey_removed' =&gt; 'la clau api amb l\'id #%s ha estat eliminada amb xit', 'apikey_added' =&gt; 's\'ha generat correctament una nova clau api', 'clicktoview' =&gt; 'faci clic per veure', 'allowed_from' =&gt; 'perms des de', 'allowed_from_help' =&gt; 'llista separada per comes d\'adreces ip / xarxes.&lt;br /&gt;per defecte buit (permetre des de tots).', 'valid_until' =&gt; 'vlid fins', 'valid_until_help' =&gt; 'data fins la qual vlid, format aaaa-mm-ddthh:mm' ], 'changepassword' =&gt; [ 'old_password' =&gt; 'contrasenya antiga', 'new_password' =&gt; 'nova contrasenya', 'new_password_confirm' =&gt; 'confirmi la contrasenya', 'new_password_ifnotempty' =&gt; 'nova contrasenya (buida = sense canvis)', 'also_change_ftp' =&gt; ' canvi tamb la contrasenya del compte ftp principal', 'also_change_stats' =&gt; ' canvi tamb la contrasenya de la pgina d\'estadstiques' ], 'cron' =&gt; [ 'cronname' =&gt; 'nom de la tasca cron', 'lastrun' =&gt; 'ltima execuci', 'interval' =&gt; 'interval', 'isactive' =&gt; 'activat', 'description' =&gt; 'descripci', 'changewarning' =&gt; 'canviar aquests valors pot tenir una causa negativa en el comportament de froxlor les tasques automatitzades.&lt;br/&gt;si us plau, noms canvi els valors aqu, si est segur del que est fent.' ], 'crondesc' =&gt; [ 'cron_unknown_desc' =&gt; 'cap descripci especificada', 'cron_tasks' =&gt; 'generaci d\'arxius de configuraci', 'cron_legacy' =&gt; 'tasca cron heretadada (antic)', 'cron_traffic' =&gt; 'clcul de trnsit', 'cron_usage_report' =&gt; 'informes web de trnsit', 'cron_mailboxsize' =&gt; 'clcul de la mida de la bstia', 'cron_letsencrypt' =&gt; 'actualitzaci de certificats let\'s encrypt', 'cron_backup' =&gt; 'processar tasques de cpia de seguretat' ], 'cronjob' =&gt; [ 'cronjobsettings' =&gt; 'configuraci de tasques cron', 'cronjobintervalv' =&gt; 'valor de l\'interval de temps d\'execuci', 'cronjobinterval' =&gt; 'interval d\'execuci' ], 'cronjobs' =&gt; [ 'notyetrun' =&gt; 'encara executat' ], 'cronmgmt' =&gt; [ 'minutes' =&gt; 'minuts', 'hours' =&gt; 'hores', 'days' =&gt; 'dies', 'weeks' =&gt; 'setmanes', 'months' =&gt; 'mesos' ], 'customer' =&gt; [ 'documentroot' =&gt; 'directori d\'inici', 'name' =&gt; 'nom complet', 'firstname' =&gt; 'nom', 'lastname' =&gt; 'cognoms', 'company' =&gt; 'empresa', 'nameorcompany_desc' =&gt; 'es requereix nom/cognom empresa', 'street' =&gt; 'carrer', 'zipcode' =&gt; 'codi postal', 'city' =&gt; 'ciutat', 'phone' =&gt; 'telfon', 'fax' =&gt; 'fax', 'email' =&gt; 'correu electrnic', 'customernumber' =&gt; 'id de client', 'diskspace' =&gt; 'espai web', 'traffic' =&gt; 'trnsit', 'mysqls' =&gt; 'bases de dades mysql', 'emails' =&gt; 'adreces de correu electrnic', 'accounts' =&gt; 'comptes de correu electrnic', 'forwarders' =&gt; 'remitents de correu electrnic', 'ftps' =&gt; 'comptes ftp', 'subdomains' =&gt; 'subdominis', 'domains' =&gt; 'dominis', 'mib' =&gt; 'mib', 'gib' =&gt; 'gib', 'title' =&gt; 'ttol', 'country' =&gt; 'pas', 'email_quota' =&gt; 'quota de correu electrnic', 'email_imap' =&gt; 'correu imap', 'email_pop3' =&gt; 'correu electrnic pop3', 'sendinfomail' =&gt; 'enviar dades per correu electrnic', 'generated_pwd' =&gt; 'suggeriment de contrasenya', 'usedmax' =&gt; 'utilitzat / mxim', 'services' =&gt; 'serveis', 'letsencrypt' =&gt; [ 'title' =&gt; 'utilitzar let\'s encrypt', 'description' =&gt; 'obtingui un certificat gratut de &lt;a href="https://letsencrypt.org"&gt;let\'s encrypt&lt;/a&gt;. el certificat es crear renovar automticament.' ], 'selectserveralias_addinfo' =&gt; 'aquesta opci es pot configurar en editar el domini. el seu valor inicial s\'hereta del domini pare.', 'total_diskspace' =&gt; 'espai total en disc', 'mysqlserver' =&gt; 'servidor mysql utilitzable' ], 'diskquota' =&gt; 'quota', 'dns' =&gt; [ 'destinationip' =&gt; 'ip(s) del domini', 'standardip' =&gt; 'ip estndard del servidor', 'a_record' =&gt; 'registre (ipv6 opcional)', 'cname_record' =&gt; 'registre cname', 'mxrecords' =&gt; 'definir registres mx', 'standardmx' =&gt; 'registre mx estndard del servidor', 'mxconfig' =&gt; 'registres mx personalitzats', 'priority10' =&gt; 'prioritat 10', 'priority20' =&gt; 'prioritat 20', 'txtrecords' =&gt; 'definir registres txt', 'txtexample' =&gt; 'exemple (entrada spf):&lt;br/&gt;v=spf1 ip4:xxx.xxx.xx.0/23 -all', 'howitworks' =&gt; 'aqu podeu gestionar les entrades dns per al vostre domini. tingueu en compte que froxlor generar automticament els registres ns/mx/a/aaaa per tu. les entrades personalitzades sn preferibles, noms les entrades que faltin seran generades automticament.' ], 'dnseditor' =&gt; [ 'edit' =&gt; 'editar dns', 'records' =&gt; 'registres', 'notes' =&gt; [ 'a' =&gt; 'adrea ipv4 de 32 bits, utilitzada per mapejar noms de host una adrea ip del host.', 'aaaa' =&gt; 'adrea ipv6 de 128 bits, utilitzada per mapejar noms de host una adrea ip del host.', 'caa' =&gt; 'el registre de recursos caa permet al titular d\'un nom de domini dns especificar una diverses autoritats de certificaci (ca) autoritzades emetre certificats per aquest domini.&lt;br/&gt;estructura: &lt;code&gt;flag tag[issue|issuewild|iodef|contactmail|contactphone] value&lt;/code&gt;&lt;br/&gt;exemple: &lt;code&gt;0 issue "ca.example.net"&lt;br/&gt;&lt;/code&gt; 0 &lt;code&gt;iodef "mailto:security@example.com"&lt; /code&gt;', 'cname' =&gt; 'lies del nom de domini, la cerca dns continuar reintentant la cerca amb el nou nom. noms possible per subdominis.', 'dname' =&gt; 'crea un lies per tot un subarbre de l\'arbre de noms de domini', 'loc' =&gt; 'informaci sobre la ubicaci geogrfica d\'un nom de domini.&lt;br/&gt;estructura: &lt;code&gt;( d1 [m1 [s1]] { d2 [m2 [s2]] { alt["m"] [siz["m"] [hp["m"] [vp["m"]]]] )&lt;/code&gt;&lt;br/&gt;descripci: &lt;code&gt;d1&lt;/code&gt;: [0 . &lt;code&gt;. 90] (graus de latitud) d2: [0 .. 180] (graus de longitud) m1, m2: [0 .. 59] (minuts latitud/longitud) s1, s2: [0 .. 59,999] (segons latitud/longitud) alt: [-100000.00 .. 42849672.95] por .01 (altitud en metres) siz, hp, vp: [0 .. 90000000.00] (mida/precisi en metres)&lt;/code&gt;&lt;br/&gt;exemple: &lt;code&gt;52 22 23.000 n 4 53 32.000 e -2.00m 0.00m 10000m 10m&lt;/code&gt;', 'mx' =&gt; 'registre d\'intercanvi de correu, assigna un nom de domini un servidor de correu per aquest domini.&lt;br/&gt;exemple: &lt;code&gt;10 mail.example.com&lt;/code&gt;&lt;br/&gt;nota : per la prioritat, utilitzeu el camp anterior.', 'ns' =&gt; 'delega una zona dns perqu utilitzi els servidors de noms autoritatius indicats.', 'rp' =&gt; 'registre de persona responsable&lt;br/&gt;estructura: &lt;code&gt;mailbox[substituir @ per un punt] txt-record-name&lt;/code&gt;&lt;br/&gt;exemple: &lt;code&gt;team.froxlor.org . froxlor.org.&lt;/code&gt;', 'srv' =&gt; 'registre d\'ubicaci de servei, utilitzat per protocols ms recents en lloc de crear registres especfics de protocol com mx.&lt;br/&gt;estructura: &lt;code&gt;priority weight port target&lt;/code&gt;&lt;br/&gt;exemple : &lt;code&gt;0 5 5060 sipserver.example.com.&lt;/code&gt;&lt;br/&gt;nota: per la prioritat, utilitzeu el camp anterior.', 'sshfp' =&gt; 'el registre de recursos sshfp s\'utilitza per publicar empremtes digitals de claus d\'intrpret d\'ordres segur (ssh) al dns.&lt;br/&gt;estructura: &lt;code&gt;tipus d\'algorisme empremta digital&lt;/code&gt;&lt;br/ &gt;algorismes: 0: reservat &lt;code&gt;, 1: rsa, 2: dsa, 3: ecdsa, 4: ed25519, 6: ed448&lt;/code&gt;&lt;br/&gt;tipus: 0 &lt;code&gt;: reservat, 1: sha- 1, 2: sha-256&lt;/code&gt;&lt;br/&gt;exemple: &lt;code&gt;2 1 123456789abcdef67890123456789abcdef67890&lt;/code&gt;', 'txt' =&gt; 'text descriptiu de lliure definici.' ] ], 'domain' =&gt; [ 'openbasedirpath' =&gt; 'ruta openbasedir', 'docroot' =&gt; 'ruta del camp anterior', 'homedir' =&gt; 'directori d\'inici', 'docparent' =&gt; 'directori pare de la ruta del camp anterior', 'ssl_certificate_placeholder' =&gt; '---- begin certificate---' . php_eol . '[...]' . php_eol . '----end certificate----', 'ssl_key_placeholder' =&gt; '---- begin rsa private key-----' . php_eol . '[...]' . php_eol . '-----end rsa private key-----', ], 'domains' =&gt; [ 'description' =&gt; 'aqu pot crear (sub)dominis canviar les seves rutes.&lt;br/&gt;el sistema necessitar algun temps per aplicar la nova configuraci desprs de cada canvi.', 'domainsettings' =&gt; 'configuraci del domini', 'domainname' =&gt; 'nom de domini', 'subdomain_add' =&gt; 'crear subdomini', 'subdomain_edit' =&gt; 'editar (sub)domini', 'wildcarddomain' =&gt; 'crear com domini comod?', 'aliasdomain' =&gt; 'lies per domini', 'noaliasdomain' =&gt; 'sense lies de domini', 'hasaliasdomains' =&gt; 't domini(s) lies', 'statstics' =&gt; 'estadstiques d\'s', 'isassigneddomain' =&gt; 'domini assignat', 'add_date' =&gt; 'afegit froxlor', 'registration_date' =&gt; 'afegit al registre', 'topleveldomain' =&gt; 'domini top-level', 'associated_with_domain' =&gt; 'associat', 'aliasdomains' =&gt; 'dominis d\'lies', 'redirectifpathisurl' =&gt; 'codi de redirecci (per defecte: buit)', 'redirectifpathisurlinfo' =&gt; 'noms ha de seleccionar una d\'aquestes opcions si heu introdut un url com ruta&lt;br/&gt;&lt;strong class="text-danger"&gt;nota:&lt;/strong&gt; els canvis noms s\'apliquen si la ruta indicada una url.', 'issubof' =&gt; 'aquest domini un subdomini d\'un altre domini', 'issubofinfo' =&gt; 'si vol afegir un subdomini com domini complet, haureu d\'establir-lo al domini correcte (per exemple, si voleu afegir "www.domini.tld", haureu de seleccionar "domini.tld").', 'nosubtomaindomain' =&gt; 'no subdomini d\'un domini complet', 'ipandport_multi' =&gt; [ 'title' =&gt; 'adreces ip', 'description' =&gt; 'especifica una ms adreces ip per al domini.&lt;br/&gt;&lt;br/&gt;&lt;div class="text-danger"&gt;nota: les adreces ip es poden canviar quan el domini est configurat com &lt;strong&gt;lies-domini&lt;/ strong&gt; d\'un altre domini.&lt;/div&gt;' ], 'ipandport_ssl_multi' =&gt; [ 'title' =&gt; 'adrea(es) ip ssl' ], 'ssl_redirect' =&gt; [ 'title' =&gt; 'redirecci ssl', 'description' =&gt; 'aquesta opci crea redireccionaments per vhosts ssl de manera que totes les peticions sn redirigides al vhost ssl.&lt;br/&gt;&lt;br/&gt;p.e. una petici &lt;strong&gt;http://domini.tld/&lt;/strong&gt; us redirigir &lt;strong&gt;https://domini.tld/&lt;/strong&gt;' ], 'serveraliasoption_wildcard' =&gt; 'comod (*.domini.tld)', 'serveraliasoption_www' =&gt; 'www (www.domini.tld)', 'serveraliasoption_none' =&gt; 'sense lies', 'domain_import' =&gt; 'importar dominis', 'import_separator' =&gt; 'separador', 'import_offset' =&gt; 'desplaament', 'import_file' =&gt; 'arxiu csv', 'import_description' =&gt; 'per obtenir informaci detallada sobre l\'estructura del fitxer d\'importaci sobre com fer la importaci correctament, visiti &lt;a href="https://docs.froxlor.org/latest/admin-guide/domain-import/" target="_blank" class="alert-link"&gt;https://docs.froxlor.org/latest/admin-guide/domain-import/&lt;/a&gt;.', 'ssl_redirect_temporarilydisabled' =&gt; '&lt;br/&gt;la redirecci ssl es desactiva temporalment mentre es genera un certificat let\'s encrypt nou. es tornar activar un cop generat el certificat.', 'termination_date' =&gt; 'data de terminaci', 'termination_date_overview' =&gt; 'acabat partir de ', 'ssl_certificates' =&gt; 'certificats ssl', 'ssl_certificate_removed' =&gt; 'el certificat amb l\'id #%s s\'ha eliminat amb xit', 'ssl_certificate_error' =&gt; 'error en llegir el certificat per al domini: %s', 'no_ssl_certificates' =&gt; 'no hi ha dominis amb certificat ssl', 'isaliasdomainof' =&gt; 's lies de domini per %s', 'isbinddomain' =&gt; 'crear zona dns', 'dkimenabled' =&gt; 'dkim activat', 'openbasedirenabled' =&gt; 'restricci de openbasedir', 'hsts' =&gt; 'hsts habilitat', 'aliasdomainid' =&gt; 'id de lies de domini' ], 'emails' =&gt; [ 'description' =&gt; 'aqu pots crear modificar les teves adreces de correu electrnic.&lt;br/&gt;un compte com la bstia que tens davant de casa. si alg us envia un correu electrnic, aquest caur al compte.&lt;br/&gt;&lt;br/&gt;per descarregar els vostres correus electrnics utilitzeu la segent configuraci al vostre programa de correu: (les dades en &lt;i&gt;cursiva&lt;/i&gt; s\'han de canviar pels equivalents que heu escrit!)&lt;br/&gt;hostname: &lt;b&gt;&lt;i&gt;nom del domini&lt;/i&gt;&lt;/b&gt;&lt;br/&gt;username: &lt;b&gt;&lt;i&gt;nom del compte / adrea de correu electrnic&lt;/i&gt;&lt;/b&gt;&lt;br/&gt;password: &lt;b&gt;&lt;i&gt;la contrasenya que heu triat&lt;/i&gt;&lt;/b&gt;', 'emailaddress' =&gt; 'adrea de correu electrnic', 'emails_add' =&gt; 'crear adrea de correu electrnic', 'emails_edit' =&gt; 'editar adrea de correu electrnic', 'catchall' =&gt; 'catchall', 'iscatchall' =&gt; 'definir com adrea "catchall"?', 'account' =&gt; 'compte', 'account_add' =&gt; 'crear compte', 'account_delete' =&gt; 'eliminar compte', 'from' =&gt; 'origen', 'to' =&gt; 'dest', 'forwarders' =&gt; 'transitaris', 'forwarder_add' =&gt; 'crear expedidor', 'alternative_emailaddress' =&gt; 'adrea de correu electrnic alternativa', 'quota' =&gt; 'quota', 'noquota' =&gt; 'sense quota', 'updatequota' =&gt; 'actualitzar quota', 'quota_edit' =&gt; 'modificar quota de correu electrnic', 'noemaildomainaddedyet' =&gt; 'encara un domini (de correu electrnic) al vostre compte.', 'back_to_overview' =&gt; 'tornar la vista general de dominis', 'accounts' =&gt; 'comptes', 'emails' =&gt; 'adreces' ], 'error' =&gt; [ 'error' =&gt; 'error', 'directorymustexist' =&gt; 'el directori %s ha d\'existir. si us plau, crea\'l amb el teu client ftp.', 'filemustexist' =&gt; 'el fitxer %s ha d\'existir.', 'allresourcesused' =&gt; 'ja ha utilitzat tots els seus recursos.', 'domains_cantdeletemaindomain' =&gt; 'no pot suprimir un domini assignat.', 'domains_canteditdomain' =&gt; 'no pot editar aquest domini. ha estat desactivat per l\'administrador.', 'domains_cantdeletedomainwithemail' =&gt; 'no pot suprimir un domini que s\'utilitza com domini de correu electrnic. elimineu primer totes les adreces de correu electrnic.', 'firstdeleteallsubdomains' =&gt; 'abans de crear un domini comod, heu d\'eliminar tots els subdominis.', 'youhavealreadyacatchallforthisdomain' =&gt; 'ja ha definit un domini comod per aquest domini.', 'ftp_cantdeletemainaccount' =&gt; 'no pot suprimir el vostre compte ftp principal', 'login' =&gt; 'el nom d\'usuari la contrasenya que heu introdut sn incorrectes. intenta-ho de nou.', 'login_blocked' =&gt; 'aquest compte ha estat susps causa de masses errors d\'inici de sessi. &lt;br/&gt;intenteu-ho de nou en %s segons.', 'notallreqfieldsorerrors' =&gt; 'no ha emplenat tots els camps n\'ha omplert alguns incorrectament.', 'oldpasswordnotcorrect' =&gt; 'la contrasenya antiga correcta.', 'youcantallocatemorethanyouhave' =&gt; 'no es pot assignar ms recursos dels que t.', 'mustbeurl' =&gt; 'no heu escrit una url vlida completa (per exemple http://algundomini.com/error404.htm)', 'invalidpath' =&gt; 'no ha triat una url vlida (potser problemes amb la llista d\'adreces?)', 'stringisempty' =&gt; 'falta informaci al camp', 'stringiswrong' =&gt; 'camp incorrecte', 'newpasswordconfirmerror' =&gt; 'la nova contrasenya la de confirmaci coincideixen', 'mydomain' =&gt; 'domini', 'mydocumentroot' =&gt; 'documentroot', 'loginnameexists' =&gt; 'el nom d\'usuari %s ja existeix', 'emailiswrong' =&gt; 'l\'adrea de correu %s cont carcters vlids est incomplet', 'alternativeemailiswrong' =&gt; 'les %s adreces de correu electrnic alternatives donades per enviar les credencials semblen ser vlides', 'loginnameiswrong' =&gt; 'el nom d\'usuari "%s" cont carcters illegals.', 'loginnameiswrong2' =&gt; 'el nom d\'usuari cont massa carcters. noms es permeten %s carcters.', 'userpathcombinationdupe' =&gt; 'la combinaci de nom d\'usuari ruta ja existeix', 'patherror' =&gt; 'error general. la ruta pot estar buida', 'errordocpathdupe' =&gt; 'l\'opci per la ruta %s ja existeix', 'adduserfirst' =&gt; 'si us plau, cre primer un client', 'domainalreadyexists' =&gt; 'el domini %s ja est assignat un client', 'nolanguageselect' =&gt; 'no s\'ha seleccionat cap idioma.', 'nosubjectcreate' =&gt; 'ha de definir un tema per aquesta plantilla de correu.', 'nomailbodycreate' =&gt; 'ha de definir un text de correu per aquesta plantilla de correu.', 'templatenotfound' =&gt; 'la plantilla s\'ha trobat.', 'alltemplatesdefined' =&gt; 'no pot definir ms plantilles, tots els idiomes ja estan suportats.', 'wwwnotallowed' =&gt; 'www est perms per subdominis.', 'subdomainiswrong' =&gt; 'el subdomini %s cont carcters vlids.', 'domaincantbeempty' =&gt; 'el nom de domini pot estar buit.', 'domainexistalready' =&gt; 'el domini %s ja existeix.', 'domainisaliasorothercustomer' =&gt; 'l\'lies de domini seleccionat en ell mateix un lies de domini, una combinaci ip/port diferent pertany un altre client.', 'emailexistalready' =&gt; 'l\'adrea de correu electrnic %s ja existeix.', 'maindomainnonexist' =&gt; 'el domini principal %s existeix.', 'destinationnonexist' =&gt; 'si us plau, creeu el vostre redireccionador al camp "dest".', 'destinationalreadyexistasmail' =&gt; 'el remitent %s ja existeix com adrea de correu electrnic activa.', 'destinationalreadyexist' =&gt; 'ja ha definit un reenviador per "%s".', 'destinationiswrong' =&gt; 'la redirecci %s cont carcters vlids est incompleta.', 'backupfoldercannotbedocroot' =&gt; 'la carpeta per les cpies de seguretat pot ser la vostra carpeta d\'inici, escolliu una carpeta dins de la vostra carpeta d\'inici, per exemple, /backups.', 'templatelanguagecombodefined' =&gt; 'la combinaci idioma/plantilla seleccionada ja ha estat definida.', 'templatelanguageinvalid' =&gt; 'l\'idioma seleccionat existeix.', 'ipstillhasdomains' =&gt; 'la combinaci ip/port que vol eliminar encara dominis assignats, si us plau reassigneu-los altres combinacions ip/port abans d\'eliminar aquesta combinaci ip/port.', 'cantdeletedefaultip' =&gt; 'no pot esborrar la combinaci ip/port per defecte, si us plau fes una altra combinaci ip/port per defecte abans d\'esborrar aquesta combinaci ip/port.', 'cantdeletesystemip' =&gt; 'no pot suprimir la ltima ip del sistema, creeu una nova combinaci ip/port per la ip del sistema canvieu la ip del sistema.', 'myipaddress' =&gt; 'ip', 'myport' =&gt; 'port', 'myipdefault' =&gt; 'ha de seleccionar una combinaci ip/port que es converteixi en predeterminada.', 'myipnotdouble' =&gt; 'aquesta combinaci ip/port ja existeix.', 'admin_domain_emailsystemhostname' =&gt; 'el nom de host del servidor es pot utilitzar com domini del client.', 'cantchangesystemip' =&gt; 'no pot canviar la ltima ip del sistema, creeu una nova combinaci ip/port per la ip del sistema canvieu la ip del sistema.', 'sessiontimeoutiswrong' =&gt; 'noms es permet un temps d\'espera de sessi numric.', 'maxloginattemptsiswrong' =&gt; 'noms es permeten "intents d\'inici de sessi mxims" numrics.', 'deactivatetimiswrong' =&gt; 'noms es permet "temps de desactivaci" numric.', 'accountprefixiswrong' =&gt; 'el "prefix del client" incorrecte.', 'mysqlprefixiswrong' =&gt; 'el "prefix sql" incorrecte.', 'ftpprefixiswrong' =&gt; 'el "prefix ftp" incorrecte.', 'ipiswrong' =&gt; 'l\'"adrea ip" incorrecte. noms es permet una adrea ip vlida.', 'vmailuidiswrong' =&gt; 'el "mails-uid" incorrecte. noms es permet un uid numric.', 'vmailgidiswrong' =&gt; 'el "mails-gid" incorrecte. noms es permet un gid numric.', 'adminmailiswrong' =&gt; 'la direcci del remitent incorrecte. noms es permet una adrea de correu electrnic vlida.', 'pagingiswrong' =&gt; 'el valor "entries per page" incorrecte. noms es permeten carcters numrics.', 'phpmyadminiswrong' =&gt; 'l\'enlla phpmyadmin un enlla vlid.', 'webmailiswrong' =&gt; 'l\'enlla webmail un enlla vlid.', 'webftpiswrong' =&gt; 'l\'enlla webftp un enlla vlid.', 'stringformaterror' =&gt; 'el valor del camp "%s" el format esperat.', 'loginnameisusingprefix' =&gt; 'no pot crear comptes que comencen per "%s", ja que aquest prefix est configurat per ser utilitzat l\'assignaci automtica de noms de compte. introduu un altre nom de compte.', 'loginnameissystemaccount' =&gt; 'el compte "%s" ja existeix al sistema es pot utilitzar. si us plau, introduu un altre nom de compte.', 'youcantdeleteyourself' =&gt; 'no es pot esborrar per raons de seguretat.', 'youcanteditallfieldsofyourself' =&gt; 'nota: pot editar tots els camps del vostre compte per raons de seguretat.', 'documentrootexists' =&gt; 'el directori "%s" ja existeix per aquest client. si us plau, elimineu-lo abans d\'afegir el client de nou.', 'norepymailiswrong' =&gt; 'l\'adrea "noreply-address" incorrecta. noms es permet una adrea de correu electrnic vlida.', 'logerror' =&gt; 'registre d\'error: %s', 'nomessagetosend' =&gt; 'no ha introdut cap missatge.', 'norecipientsgiven' =&gt; 'no ha especificat cap destinatari', 'errorsendingmail' =&gt; 'el missatge "%s" ha fallat', 'errorsendingmailpub' =&gt; 'el missatge l\'adrea de correu electrnic indicada ha fallat', 'cannotreaddir' =&gt; 'no s\'ha pogut llegir el directori "%s".', 'invalidip' =&gt; 'adrea ip vlida: %s', 'invalidmysqlhost' =&gt; 'adrea de host mysql vlida: %s', 'cannotuseawstatsandwebalizeratonetime' =&gt; 'no pot activar webalizer awstats al mateix temps, si us plau escolliu un d\'ells.', 'cannotwritetologfile' =&gt; 'no es pot obrir el fitxer de registre %s per escriure', 'vmailquotawrong' =&gt; 'la mida de la quota ha de ser un nmero positiu.', 'allocatetoomuchquota' =&gt; 'ha intentat assignar %s mb de quota, per en suficients.', 'missingfields' =&gt; 'no s\'han omplert tots els camps obligatoris.', 'requiredfield' =&gt; 'aquest camp obligatori.', 'accountnotexisting' =&gt; 'el compte de correu electrnic indicat existeix.', 'nopermissionsorinvalidid' =&gt; 'no permisos suficients per canviar aquesta configuraci s\'ha introdut un identificador vlid.', 'phpsettingidwrong' =&gt; 'no hi ha una configuraci php amb aquest id.', 'descriptioninvalid' =&gt; 'la descripci massa curta, massa llarga cont carcters illegals.', 'info' =&gt; 'informaci', 'filecontentnotset' =&gt; 'el fitxer pot estar buit.', 'index_file_extension' =&gt; 'l\'extensi del fitxer ndex ha de tenir entre 1 6 carcters. l\'extensi noms pot contenir carcters com a-z, a-z 0-9', 'customerdoesntexist' =&gt; 'el client seleccionat existeix.', 'admindoesntexist' =&gt; 'l\'administrador escollit existeix.', 'ipportdoesntexist' =&gt; 'la combinaci ip/port que ha triat existeix.', 'usernamealreadyexists' =&gt; 'el nom d\'usuari %s ja existeix.', 'plausibilitychecknotunderstood' =&gt; 'no s\'ha ents la resposta de la comprovaci de plausibilitat.', 'errorwhensaving' =&gt; 's\'ha produt un error en desar els %s camps', 'hiddenfieldvaluechanged' =&gt; 'el valor del camp ocult "%s" ha canviat en editar la configuraci.&lt;br/&gt;&lt;br/&gt;aix sol ser un gran problema, per la configuraci s\'ha pogut desar per aquest motiu.', 'notrequiredpasswordlength' =&gt; 'la contrasenya introduda massa curta. si us plau, introduu almenys %s carcters.', 'overviewsettingoptionisnotavalidfield' =&gt; 'ups, un camp que s\'hauria de mostrar com una opci la vista de configuraci un tipus exceptuat. pots culpar els desenvolupadors per aix. aix hauria de passar.', 'pathmaynotcontaincolon' =&gt; 'la ruta introduda ha de contenir dos punts (":"). introduu un valor de ruta correcte.', 'exception' =&gt; '%s', 'notrequiredpasswordcomplexity' =&gt; 'la complexitat de la contrasenya especificada s\'ha complert.&lt;br/&gt;poseu-vos en contacte amb el vostre administrador si teniu algun dubte sobre la complexitat especificada.', 'stringerrordocumentnotvalidforlighty' =&gt; 'una cadena com errordocument funciona amb lighttpd, si us plau especifica una ruta un fitxer.', 'urlerrordocumentnotvalidforlighty' =&gt; 'una url com errordocument funciona amb lighttpd, si us plau especifica una ruta un fitxer', 'invaliderrordocumentvalue' =&gt; 'el valor donat com errordocument sembla ser un fitxer, url cadena vlids.', 'intvaluetoolow' =&gt; 'el nmero donat massa baix (camp %s))', 'intvaluetoohigh' =&gt; 'el nmero donat massa alt (camp %s)', 'phpfpmstillenabled' =&gt; 'php-fpm est actualment actiu. desactiveu-lo abans d\'activar fcgid.', 'fcgidstillenabled' =&gt; 'fcgid est actualment actiu. desactiveu-lo abans d\'activar php-fpm.', 'domains_cantdeletedomainwithaliases' =&gt; 'no es pot suprimir un domini que s\'utilitza per lies. primer heu d\'eliminar els lies.', 'user_banned' =&gt; 'el vostre compte ha estat bloquejat. si us plau, contacteu amb el vostre administrador per ms informaci.', 'session_timeout' =&gt; 'valor massa baix', 'session_timeout_desc' =&gt; 'el temps d\'espera de la sessi ha de ser inferior 1 minut.', 'invalidhostname' =&gt; 'el nom de host ha de ser un domini vlid. pot estar buit ni estar format noms per espais en blanc.', 'operationnotpermitted' =&gt; 'operaci permesa', 'featureisdisabled' =&gt; 'la funci %s est desactivada. poseu-vos en contacte amb el vostre provedor de serveis.', 'usercurrentlydeactivated' =&gt; 'l\'usuari %s est desactivat actualment', 'setlessthanalreadyused' =&gt; 'no pot establir menys recursos de \'%s\' dels que aquest usuari ja ha utilitzat&lt;br/&gt;', 'stringmustntbeempty' =&gt; 'el valor del camp %s ha d\'estar buit', 'sslcertificateismissingprivatekey' =&gt; 'necessita especificar una clau privada per al vostre certificat', 'sslcertificatewrongdomain' =&gt; 'el certificat indicat pertany aquest domini', 'sslcertificateinvalidcert' =&gt; 'el contingut del certificat indicat sembla un certificat vlid.', 'sslcertificateinvalidcertkeypair' =&gt; 'la clau privada indicada pertany al certificat en qesti.', 'sslcertificateinvalidca' =&gt; 'les dades del certificat de la ca semblen ser un certificat vlid.', 'sslcertificateinvalidchain' =&gt; 'les dades de la cadena del certificat semblen ser un certificat vlid.', 'givendirnotallowed' =&gt; 'el directori indicat al camp %s est perms.', 'sslredirectonlypossiblewithsslipport' =&gt; 'l\'s de let\'s encrypt noms possible quan el domini assignada almenys una combinaci ip/port habilitada per ssl.', 'fcgidstillenableddeadlock' =&gt; 'fcgid est actualment actiu.&lt;br/&gt;si us plau, desactiveu-lo abans de canviar un altre servidor web que sigui apache2 lighttpd', 'send_report_title' =&gt; 'enviar informe d\'error', 'send_report_desc' =&gt; 'grcies per informar d\'aquest error ajudar-nos millorar froxlor.&lt;br/&gt;aquest el correu electrnic que s\'enviar l\'equip de desenvolupadors de froxlor:', 'send_report' =&gt; 'enviar informe', 'send_report_error' =&gt; 'error en enviar l\'informe: &lt;br/&gt;%s', 'notallowedtouseaccounts' =&gt; 'el vostre compte permet utilitzar imap/pop3. podeu afegir comptes de correu.', 'cannotdeletehostnamephpconfig' =&gt; 'aquesta configuraci php utilitzada pel froxlor-vhost pot ser esborrada.', 'cannotdeletedefaultphpconfig' =&gt; 'aquesta configuraci php est establerta per defecte es pot esborrar.', 'passwordshouldnotbeusername' =&gt; 'la contrasenya pot ser la mateixa que el nom dusuari.', 'no_phpinfo' =&gt; 'ho sentim, puc llegir phpinfo()', 'moveofcustomerfailed' =&gt; 'el canvi del client l\'administrador/revenedor seleccionat ha fallat. tingui en compte que tots els altres canvis en el client s\'han aplicat amb xit en aquesta etapa.&lt;br/&gt;&lt;br/&gt;missatge d\'error: %s', 'domain_import_error' =&gt; 's\'ha produt el segent error en importar dominis: %s', 'fcgidandphpfpmnogoodtogether' =&gt; 'fcgid php-fpm poden estar activats alhora', 'no_apcuinfo' =&gt; 'no hi ha informaci de memria cau disponible. apcu sembla que s\'est executant.', 'no_opcacheinfo' =&gt; 'no hi ha informaci de memria cau disponible. opcache sembla que s\'est executant.', 'nowildcardwithletsencrypt' =&gt; 'let\'s encrypt pot manejar dominis comod usant acme froxlor (requereix dns-challenge), ho sento. si us plau, establiu el serveralias www desactiveu-lo completament.', 'customized_version' =&gt; 'sembla que la teva installaci de froxlor ha estat modificada, hi ha suport, ho sentim.', 'autoupdate_0' =&gt; 'error desconegut', 'autoupdate_1' =&gt; 'el parmetre de php allow_url_fopen est desactivat. autoupdate necessita que aquest parmetre estigui habilitat php.ini', 'autoupdate_2' =&gt; 'extensi php zip trobada, si us plau assegureu-vos que est installada activada', 'autoupdate_4' =&gt; 'el fitxer froxlor ha pogut ser emmagatzemat al disc :(', 'autoupdate_5' =&gt; 'version.froxlor.org ha tornat valors inacceptables :(', 'autoupdate_6' =&gt; 'whoops, hi havia una versi (vlida) donada per descarregar :(', 'autoupdate_7' =&gt; 'no s\'ha pogut trobar el fitxer descarregat :(', 'autoupdate_8' =&gt; 'no s\'ha pogut extreure el fitxer :(', 'autoupdate_9' =&gt; 'el fitxer descarregat ha passat la comprovaci de la integritat. si us plau, intenteu tornar actualitzar.', 'autoupdate_10' =&gt; 'la versi mnima suportada de php 7.4.0', 'autoupdate_11' =&gt; 'webupdate est desactivat', 'mailaccistobedeleted' =&gt; 'un altre compte amb el mateix nom (%s) est sent eliminat per tant es pot afegir en aquest moment.', 'customerhasongoingbackupjob' =&gt; 'ja hi ha un treball de cpia de seguretat esperant ser processat, si us plau sigui pacient.', 'backupfunctionnotenabled' =&gt; 'la funci de cpia de seguretat est habilitada', 'dns_domain_nodns' =&gt; 'dns est habilitat per aquest domini', 'dns_content_empty' =&gt; 'no hi ha contingut', 'dns_content_invalid' =&gt; 'el contingut dns vlid', 'dns_arec_noipv4' =&gt; 'no s\'ha proporcionat cap adrea ip vlida per al registre a.', 'dns_aaaarec_noipv6' =&gt; 'no s\'ha indicat una adrea ip vlida per al registre aaaa', 'dns_mx_prioempty' =&gt; 'prioritat mx vlida', 'dns_mx_needdom' =&gt; 'el valor de contingut mx ha de ser un nom de domini vlid.', 'dns_mx_noalias' =&gt; 'el valor de contingut mx pot ser una entrada cname.', 'dns_cname_invaliddom' =&gt; 'nom de domini vlid per al registre cname', 'dns_cname_nomorerr' =&gt; 'ja hi ha un resource-record amb el mateix nom de registre. es pot utilitzar com cname.', 'dns_other_nomorerr' =&gt; 'ja hi ha un registre cname amb el mateix nom de registre. es pot utilitzar per cap altre tipus.', 'dns_ns_invaliddom' =&gt; 'nom de domini vlid per al registre ns', 'dns_srv_prioempty' =&gt; 'prioritat srv vlida', 'dns_srv_invalidcontent' =&gt; 'contingut srv vlid, ha de contenir els camps weight, port target, p.ex: 5 5060 servidorsip.exemple.com.', 'dns_srv_needdom' =&gt; 'el valor srv target ha de ser un nom de domini vlid', 'dns_srv_noalias' =&gt; 'el valor srv-target pot ser una entrada cname.', 'dns_duplicate_entry' =&gt; 'el registre ja existeix', 'dns_notfoundorallowed' =&gt; 'domini trobat sense perms', 'domain_nopunycode' =&gt; 'no heu d\'especificar punycode (idna). el domini es convertir automticament', 'dns_record_toolong' =&gt; 'els registres/etiquetes noms poden tenir un mxim de 63 carcters', 'noipportgiven' =&gt; 'no s\'ha especificat ip/port', 'jsonextensionnotfound' =&gt; 'aquesta funci requereix una extensi php json.', 'cannotdeletesuperadmin' =&gt; 'el primer administrador es pot eliminar.', 'no_wwwcnamae_ifwwwalias' =&gt; 'no es pot establir un registre cname per "www" perqu el domini est configurat per generar un lies www. canvieu la configuraci "sense lies" "lies comod".', 'local_group_exists' =&gt; 'el grup indicat ja existeix al sistema.', 'local_group_invalid' =&gt; 'el nom del grup vlid', 'invaliddnsforletsencrypt' =&gt; 'el dns del domini inclou cap de les adreces ip seleccionades. la generaci del certificat let\'s encrypt possible.', 'notallowedphpconfigused' =&gt; 'intentant utilitzar php-config que est assignat al client', 'pathmustberelative' =&gt; 'l\'usuari perms per especificar directoris fora del directori personal del client. si us plau, especifiqueu una ruta relativa (sense /).', 'mysqlserverstillhasdbs' =&gt; 'no es pot eliminar el servidor de base de dades de la llista de clients permesos, ja que encara hi ha bases de dades.', 'domaincannotbeedited' =&gt; 'no se us permet editar la %s domini.', 'invalidcronjobintervalvalue' =&gt; 'l\'interval de la tasca cron ha de ser un dels segents: %s' ], 'extras' =&gt; [ 'description' =&gt; 'aqu podeu afegir alguns extres, per exemple protecci de directoris.&lt;br/&gt;el sistema necessitar algun temps per aplicar la nova configuraci desprs de cada canvi.', 'directoryprotection_add' =&gt; 'afegir protecci de directori', 'view_directory' =&gt; 'mostra el contingut del directori', 'pathoptions_add' =&gt; 'afegir opcions de ruta', 'directory_browsing' =&gt; 'exploraci del contingut del directori', 'pathoptions_edit' =&gt; 'editar opcions de ruta', 'error404path' =&gt; '404', 'error403path' =&gt; '403', 'error500path' =&gt; '500', 'error401path' =&gt; '401', 'errordocument404path' =&gt; 'documenterror 404', 'errordocument403path' =&gt; 'documenterror 403', 'errordocument500path' =&gt; 'documenterror 500', 'errordocument401path' =&gt; 'documenterror 401', 'execute_perl' =&gt; 'executar perl/cgi', 'htpasswdauthname' =&gt; 'ra d\'autenticaci (authname)', 'directoryprotection_edit' =&gt; 'editar protecci de directori', 'backup' =&gt; 'crear cpia de seguretat', 'backup_web' =&gt; 'cpia de seguretat de dades web', 'backup_mail' =&gt; 'cpia de seguretat de les dades de correu', 'backup_dbs' =&gt; 'cpia de seguretat de bases de dades', 'path_protection_label' =&gt; '&lt;strong class="text-danger"&gt;important&lt;/strong&gt;', 'path_protection_info' =&gt; 'us recomanem encaridament que protegeixi la ruta indicada, consulteu "extres" -&gt; "protecci de directoris".' ], 'ftp' =&gt; [ 'description' =&gt; 'aqu podeu crear modificar els vostres comptes ftp.&lt;br/&gt;els canvis es fan l\'instant els comptes es poden utilitzar immediatament.', 'account_add' =&gt; 'crear compte', 'account_edit' =&gt; 'editar compte ftp', 'editpassdescription' =&gt; 'estableixi una nova contrasenya deixeu-la en blanc per canviar-la.' ], 'gender' =&gt; [ 'title' =&gt; 'ttol', 'male' =&gt; 'sr.', 'female' =&gt; 'sra.', 'undef' =&gt; '' ], 'imprint' =&gt; 'avs legal', 'index' =&gt; [ 'customerdetails' =&gt; 'dades del client', 'accountdetails' =&gt; 'dades del compte' ], 'integrity_check' =&gt; [ 'databasecharset' =&gt; 'joc de carcters de la base de dades (ha de ser utf-8)', 'domainiptable' =&gt; 'referncies ip &lt;-&gt; domini', 'subdomainsslredirect' =&gt; 'bandera falsa ssl-redirect per dominis ssl', 'froxlorlocalgroupmemberforfcgidphpfpm' =&gt; 'usuari froxlor als grups de clients (per fcgid/php-fpm)', 'webservergroupmemberforfcgidphpfpm' =&gt; 'usuari webserver als grups de clients (per fcgid/php-fpm)', 'subdomainletsencrypt' =&gt; 'els dominis principals sense port ssl assignat tenen subdominis amb redirecci ssl activa' ], 'logger' =&gt; [ 'date' =&gt; 'data', 'type' =&gt; 'tipus', 'action' =&gt; 'acci', 'user' =&gt; 'usuari', 'truncate' =&gt; 'registre buit', 'reseller' =&gt; 'revenedor', 'admin' =&gt; 'administrador', 'cron' =&gt; 'tasca cron', 'login' =&gt; 'inici de sessi', 'intern' =&gt; 'intern', 'unknown' =&gt; 'desconegut' ], 'login' =&gt; [ 'username' =&gt; 'nom d\'usuari', 'password' =&gt; 'contrasenya', 'language' =&gt; 'idioma', 'login' =&gt; 'inici de sessi', 'logout' =&gt; 'finalitzar sessi', 'profile_lng' =&gt; 'idioma del perfil', 'welcomemsg' =&gt; 'inici sessi per accedir al vostre compte.', 'forgotpwd' =&gt; 'heu oblidat la contrasenya?', 'presend' =&gt; 'restablir contrasenya', 'email' =&gt; 'correu electrnic', 'remind' =&gt; 'restablir la contrasenya', 'usernotfound' =&gt; 'no s\'ha trobat l\'usuari', 'backtologin' =&gt; 'tornar l\'inici de sessi', 'combination_not_found' =&gt; 'no s\'ha trobat cap combinaci d\'usuari adrea electrnica.', '2fa' =&gt; 'autenticaci de dos factors (2fa)', '2facode' =&gt; 'introdueixi el codi 2fa' ], 'mails' =&gt; [ 'pop_success' =&gt; [ 'mailbody' =&gt; 'hola,\\nel vostre compte de correu {email} s\'ha configurat correctament.\\naquest un correu creat \\nautomticament, si us plau contesteu!\\natentament, el vostre administrador', 'subject' =&gt; 'compte de correu configurat correctament' ], 'createcustomer' =&gt; [ 'mailbody' =&gt; 'hola {salutation}, aqu hi ha les dades del vostre compte: nom d\'usuari: {username}: {password}, el seu administrador.', 'subject' =&gt; 'informaci del compte' ], 'pop_success_alternative' =&gt; [ 'mailbody' =&gt; 'hola {salutation}, el vostre compte de correu {email} s\'ha configurat correctament. la contrasenya {password}. aquest un correu creat automticament, si us plau el contesteu. atentament, el vostre administrador.', 'subject' =&gt; 'compte de correu configurat correctament' ], 'password_reset' =&gt; [ 'subject' =&gt; 'restablir contrasenya', 'mailbody' =&gt; 'hola {salutation}, aqu est el vostre enlla per establir una nova contrasenya. aquest enlla vlid durant les segents 24 hores. {link}, el vostre administrador.' ], 'new_database_by_customer' =&gt; [ 'subject' =&gt; '[froxlor] nova base de dades creada', 'mailbody' =&gt; 'hola {cust_name}, acabes d\'afegir una nova base de dades. aqu hi ha la informaci introduda: nom de la base de dades: {db_name} contrasenya: {db_pass} descripci: {db_desc} nom de host de la base de dades: {db_srv} phpmyadmin: {pma_uri} atentament, el vostre administrador' ], 'new_ftpaccount_by_customer' =&gt; [ 'subject' =&gt; 'nou usuari ftp creat', 'mailbody' =&gt; 'hola {cust_name} acabes d\'afegir un nou usuari ftp. aqu hi ha la informaci introduda: nom d\'usuari: {usr_name} contrasenya: {usr_pass} ruta: {usr_path} atentament, el vostre administrador' ], 'trafficmaxpercent' =&gt; [ 'mailbody' =&gt; 'estimat {salutation}, ha utilitzat el {trafficused} del seu {traffic} disponible de trnsit. aix ms del {max_percent}%%', 'subject' =&gt; 'arribant al lmit de trnsit' ], 'diskmaxpercent' =&gt; [ 'mailbody' =&gt; 'estimat {salutation}, ha utilitzat el {diskused} de su {diskavailable} disponible d\'espai en disc. aix ms del {max_percent}.', 'subject' =&gt; 'arribant al lmit d\'espai de disc' ], '2fa' =&gt; [ 'mailbody' =&gt; 'hola, el vostre codi d\'accs 2fa s..: {code}. aquest un correu creat automticament, si us plau el respongui. atentament, el vostre administrador.', 'subject' =&gt; 'froxlor - codi 2fa' ] ], 'menue' =&gt; [ 'main' =&gt; [ 'main' =&gt; 'principal', 'changepassword' =&gt; 'canviar contrasenya', 'changelanguage' =&gt; 'canviar idioma', 'username' =&gt; 'iniciar sessi com ', 'changetheme' =&gt; 'canviar tema', 'apihelp' =&gt; 'ajuda d\'api', 'apikeys' =&gt; 'claus d\'api' ], 'email' =&gt; [ 'email' =&gt; 'correu electrnic', 'emails' =&gt; 'adreces', 'webmail' =&gt; 'correu web', 'emailsoverview' =&gt; 'vista general de dominis de correu electrnic' ], 'mysql' =&gt; [ 'mysql' =&gt; 'mysql', 'databases' =&gt; 'bases de dades', 'phpmyadmin' =&gt; 'phpmyadmin' ], 'domains' =&gt; [ 'domains' =&gt; 'dominis', 'settings' =&gt; 'vista general de dominis' ], 'ftp' =&gt; [ 'ftp' =&gt; 'ftp', 'accounts' =&gt; 'comptes', 'webftp' =&gt; 'webftp' ], 'extras' =&gt; [ 'extras' =&gt; 'extres', 'directoryprotection' =&gt; 'protecci de directoris', 'pathoptions' =&gt; 'opcions de ruta', 'backup' =&gt; 'cpia de seguretat' ], 'traffic' =&gt; [ 'traffic' =&gt; 'trnsit', 'current' =&gt; 'mes en curs', 'overview' =&gt; 'trnsit total' ], 'phpsettings' =&gt; [ 'maintitle' =&gt; 'configuracions php', 'fpmdaemons' =&gt; 'versions de php-fpm' ], 'logger' =&gt; [ 'logger' =&gt; 'registre del sistema' ] ], 'message' =&gt; [ 'norecipients' =&gt; 'no s\'ha enviat cap correu electrnic perqu hi ha destinataris la base de dades', 'success' =&gt; 'missatge enviat correctament als destinataris de %s', ], 'mysql' =&gt; [ 'databasename' =&gt; 'usuari/nom de la base de dades', 'databasedescription' =&gt; 'descripci de la base de dades', 'database_create' =&gt; 'crear base de dades', 'description' =&gt; 'aqu podeu crear modificar les vostres bases de dades mysql.&lt;br/&gt;els canvis es realitzen l\'instant la base de dades es pot utilitzar immediatament.&lt;br/&gt;al men de l\'esquerra trobareu l\'eina phpmyadmin amb la qual podeu administrar fcilment la vostra base de dades.&lt;br/&gt;&lt;br/&gt;per utilitzar les vostres bases de dades en els vostres propis scripts php utilitzeu els segents ajustaments: (les dades en &lt;i&gt;cursiva&lt;/i&gt; s\'han de canviar pels equivalents que hagi escrit!)&lt;br/&gt;nom de host: &lt;b&gt;&lt;sql_host/&gt;&lt;/b&gt;&lt;br/&gt;nom d\'usuari: &lt;b&gt;&lt;i&gt;databasename&lt;/i&gt;&lt;/b&gt;&lt;br/&gt; contrasenya: &lt;b&gt;&lt;i&gt;la contrasenya que heu triat&lt;/i&gt;&lt;/b&gt;&lt;br/&gt;base de dades: &lt;b&gt;&lt;i&gt;databasename&lt;/i&gt;&lt;/b&gt;', 'mysql_server' =&gt; 'servidor mysql', 'database_edit' =&gt; 'editar base de dades', 'size' =&gt; 'mida', 'privileged_user' =&gt; 'usuari privilegiat de la base de dades', 'privileged_passwd' =&gt; 'contrasenya per usuari privilegiat', 'unprivileged_passwd' =&gt; 'contrasenya per usuari sense privilegis', 'mysql_ssl_ca_file' =&gt; 'certificat del servidor ssl', 'mysql_ssl_verify_server_certificate' =&gt; 'verificar certificat de servidor ssl' ], 'opcacheinfo' =&gt; [ 'generaltitle' =&gt; 'informaci general', 'resetcache' =&gt; 'restablir opcache', 'version' =&gt; 'versi de opcache', 'phpversion' =&gt; 'versi de php', 'runtimeconf' =&gt; 'configuraci de temps d\'execuci', 'start' =&gt; 'hora d\'inici', 'lastreset' =&gt; 'ltim reinici', 'oomrestarts' =&gt; 'recompte de reinicis oom', 'hashrestarts' =&gt; 'recompte de reinicis hash', 'manualrestarts' =&gt; 'recompte de reinicis manuals', 'hitsc' =&gt; 'nombre d\'encerts', 'missc' =&gt; 'nombre de faltes', 'blmissc' =&gt; 'llista negra del nombre de faltes', 'status' =&gt; 'estat', 'never' =&gt; 'mai', 'enabled' =&gt; 'opcache activat', 'cachefull' =&gt; 'memria cau plena', 'restartpending' =&gt; 'reinici pendent', 'restartinprogress' =&gt; 'reinici en curs', 'cachedscripts' =&gt; 'recompte d\'scripts en memria cau', 'memusage' =&gt; 's de memria', 'totalmem' =&gt; 'memria total', 'usedmem' =&gt; 'memria utilitzada', 'freemem' =&gt; 'memria lliure', 'wastedmem' =&gt; 'memria desaprofitada', 'maxkey' =&gt; 'tecles mximes', 'usedkey' =&gt; 'tecles utilitzades', 'wastedkey' =&gt; 'tecles desaprofitades', 'strinterning' =&gt; 'intercalaci de cadenes', 'strcount' =&gt; 'recompte de cadenes', 'keystat' =&gt; 'estadstica de claus en memria cau', 'used' =&gt; 'utilitzat', 'free' =&gt; 'lliure', 'blacklist' =&gt; 'llista negra', 'novalue' =&gt; '&lt;i&gt;sense valor&lt;/i&gt;', 'true' =&gt; '&lt;i&gt;cert&lt;/i&gt;', 'false' =&gt; '&lt;i&gt;fals&lt;/i&gt;', 'funcsavail' =&gt; 'funcions disponibles' ], 'panel' =&gt; [ 'edit' =&gt; 'editar', 'delete' =&gt; 'eliminar', 'create' =&gt; 'crear', 'save' =&gt; 'desar', 'yes' =&gt; 's', 'no' =&gt; 'no', 'emptyfornochanges' =&gt; 'buit per cap canvi', 'emptyfordefault' =&gt; 'buit per valors per defecte', 'path' =&gt; 'ruta', 'toggle' =&gt; 'commutar', 'next' =&gt; 'segent', 'dirsmissing' =&gt; 'no es pot trobar llegir el directori!', 'unlimited' =&gt; '', 'urloverridespath' =&gt; 'url (anulla la ruta)', 'pathorurl' =&gt; 'ruta url', 'ascending' =&gt; 'ascendent', 'descending' =&gt; 'descendent', 'search' =&gt; 'cercar', 'used' =&gt; 'utilitzada', 'translator' =&gt; 'traductor', 'reset' =&gt; 'descartar canvis', 'pathdescription' =&gt; 'si el directori existeix, es crear automticament.', 'pathdescriptionex' =&gt; '&lt;br/&gt;&lt;br/&gt;&lt;span class="text-danger"&gt;nota:&lt;/span&gt; la ruta &lt;code&gt;/&lt;/code&gt; est permesa causa de la configuraci administrativa, s\'establir automticament &lt;code&gt;/elegit.subdomini.tld/&lt;/code&gt; si s\'estableix en un altre directori.', 'pathdescriptionsubdomain' =&gt; 'si el directori existeix, es crear automticament.&lt;br/&gt;&lt;br/&gt;si voleu una redirecci un altre domini, aquesta entrada ha de comenar per http:// https://.&lt;br/&gt;&lt;br/&gt;si la url acaba en / es considera una carpeta, si no, es tracta com fitxer.', 'back' =&gt; 'tornar', 'reseller' =&gt; 'revenedor', 'admin' =&gt; 'administrador', 'customer' =&gt; 'client/s', 'send' =&gt; 'enviar', 'nosslipsavailable' =&gt; 'actualment hi ha combinacions ip/port ssl per aquest servidor', 'backtooverview' =&gt; 'tornar la vista general', 'dateformat' =&gt; 'aaaa-mm-dd', 'dateformat_function' =&gt; 'a-m-d', 'timeformat_function' =&gt; 'h:i:s', 'default' =&gt; 'per defecte', 'never' =&gt; 'mai', 'active' =&gt; 'actiu', 'please_choose' =&gt; 'seleccioni una opci', 'allow_modifications' =&gt; 'permetre modificacions', 'megabyte' =&gt; 'megabyte', 'not_supported' =&gt; 'no suportat en: ', 'view' =&gt; 'veure', 'toomanydirs' =&gt; 'massa subdirectoris. tornar la selecci manual de ruta.', 'abort' =&gt; 'avortar', 'not_activated' =&gt; 'no activat', 'off' =&gt; 'desactivat', 'options' =&gt; 'opcions', 'neverloggedin' =&gt; 'encara s\'ha iniciat sessi', 'descriptionerrordocument' =&gt; 'pot ser una url, la ruta un fitxer simplement una cadena envoltada de ""&lt;br/&gt;deixeu-lo buit per utilitzar el valor predeterminat del servidor.', 'unlock' =&gt; 'desbloquejar', 'theme' =&gt; 'tema', 'variable' =&gt; 'variable', 'description' =&gt; 'descripci', 'cancel' =&gt; 'cancellar', 'ssleditor' =&gt; 'configuraci ssl per aquest domini', 'ssleditor_infoshared' =&gt; 'actualment utilitzant el certificat del domini pare', 'ssleditor_infoglobal' =&gt; 'actualment utilitzant el certificat global', 'dashboard' =&gt; 'panell de control', 'assigned' =&gt; 'assignat', 'available' =&gt; 'disponible', 'news' =&gt; 'notcies', 'newsfeed_disabled' =&gt; 'la font de notcies est desactivada. feu clic la icona d\'edici per anar la configuraci.', 'ftpdesc' =&gt; 'descripci d\'ftp', 'letsencrypt' =&gt; 'utilitzant let\'s encrypt', 'set' =&gt; 'aplicar', 'shell' =&gt; 'shell', 'backuppath' =&gt; [ 'title' =&gt; 'ruta de dest de la cpia de seguretat', 'description' =&gt; 'aquesta la ruta s\'emmagatzemaran les cpies de seguretat. si seleccioneu la cpia de seguretat de les dades web, tots els fitxers de la carpeta d\'inici s\'emmagatzemen excloent-hi la carpeta de cpia de seguretat especificada aqu.' ], 'none_value' =&gt; 'cap', 'viewlogs' =&gt; 'veure fitxers de registre', 'not_configured' =&gt; 'el sistema encara est configurat. feu clic aqu per anar la configuraci.', 'ihave_configured' =&gt; 'he configurat els serveis', 'system_is_configured' =&gt; '&lt;i class="fa-solid fa-circle-exclamation me-1"/&gt;el sistema ja est configurat', 'settings_before_configuration' =&gt; 'assegureu-vos d\'ajustar la configuraci abans de configurar els serveis aqu', 'image_field_delete' =&gt; 'esborrar la imatge actual existent', 'usage_statistics' =&gt; 's de recursos', 'security_question' =&gt; 'pregunta de seguretat', 'listing_empty' =&gt; 'no s\'han trobat entrades', 'unspecified' =&gt; 'sense especificar', 'settingsmode' =&gt; 'mode', 'settingsmodebasic' =&gt; 'bsic', 'settingsmodeadvanced' =&gt; 'avanat', 'settingsmodetoggle' =&gt; 'faci clic per canviar el mode', 'modalclose' =&gt; 'tancar', 'managetablecolumnsmodal' =&gt; [ 'title' =&gt; 'administrar columnes de la taula', 'description' =&gt; 'aqu pot personalitzar les columnes visibles' ], 'mandatoryfield' =&gt; 'camp obligatori', 'select_all' =&gt; 'selecciona-ho tot', 'unselect_all' =&gt; 'desselecciona-ho tot', 'searchtablecolumnsmodal' =&gt; [ 'title' =&gt; 'cerca en els camps', 'description' =&gt; 'seleccioni el camp vol cercar' ], 'upload_import' =&gt; 'carregar e importar' ], 'phpfpm' =&gt; [ 'vhost_httpuser' =&gt; 'usuari local utilitzar per php-fpm (froxlor vhost)', 'vhost_httpgroup' =&gt; 'grup local utilitzar per php-fpm (froxlor vhost)', 'ownvhost' =&gt; [ 'title' =&gt; 'habilitar php-fpm per al vhost de froxlor', 'description' =&gt; 'si est habilitat, froxlor tamb s\'executar sota un usuari local' ], 'use_mod_proxy' =&gt; [ 'title' =&gt; 'utilitzar mod_proxy / mod_proxy_fcgi', 'description' =&gt; '&lt;strong class="text-danger"&gt;s\'ha d\'activar quan utilitzeu debian 9.x (stretch) posterior&lt;/strong&gt;. activar per utilitzar php-fpm via mod_proxy_fcgi. com mnim es requereix apache-2.4.9' ], 'ini_flags' =&gt; 'introdueixi possibles &lt;strong&gt;php_flags&lt;/strong&gt;per php.ini. una entrada per lnia', 'ini_values' =&gt; 'introdueixi possibles &lt;strong&gt;php_values&lt;/strong&gt;per php.ini. una entrada per lnia', 'ini_admin_flags' =&gt; 'introdueixi possibles &lt;strong&gt;php_admin_flags&lt;/strong&gt;per php.ini. una entrada per lnia', 'ini_admin_values' =&gt; 'introdueixi possibles &lt;strong&gt;php_admin_values&lt;/strong&gt;per php.ini. una entrada per lnia' ], 'privacy' =&gt; 'poltica de privadesa', 'pwdreminder' =&gt; [ 'success' =&gt; 'restabliment de contrasenya sollicitat amb xit. seguiu les instruccions del correu electrnic que heu rebut.', 'notallowed' =&gt; 'usuari desconegut el restabliment de contrasenya est desactivat', 'changed' =&gt; 'la vostra contrasenya s\'ha actualitzat correctament. ja podeu iniciar sessi amb la nova contrasenya.', 'wrongcode' =&gt; 'ho sentim, el vostre codi d\'activaci existeix ja ha caducat.', 'choosenew' =&gt; 'establir nova contrasenya' ], 'question' =&gt; [ 'question' =&gt; 'pregunta de seguretat', 'admin_customer_reallydelete' =&gt; 'realment vol eliminar el client %s? es podr desfer.', 'admin_domain_reallydelete' =&gt; 'realment vol esborrar el domini %s?', 'admin_domain_reallydisablesecuritysetting' =&gt; 'realment vol desactivar aquesta configuraci de seguretat openbasedir?', 'admin_admin_reallydelete' =&gt; 'realment vol esborrar l\'admin %s? tots els clients dominis seran reassignats al vostre compte.', 'admin_template_reallydelete' =&gt; 'realment vol esborrar la plantilla \'%s\'?', 'domains_reallydelete' =&gt; 'realment vol esborrar el domini %s?', 'email_reallydelete' =&gt; 'realment vol esborrar l\'adrea de correu electrnic %s?', 'email_reallydelete_account' =&gt; 'realment vol esborrar el compte de correu de %s?', 'email_reallydelete_forwarder' =&gt; 'realment vol esborrar el forwarder %s?', 'extras_reallydelete' =&gt; 'realment vol esborrar la protecci de directori de %s?', 'extras_reallydelete_pathoptions' =&gt; 'realment vol esborrar les opcions de ruta de %s?', 'extras_reallydelete_backup' =&gt; 'realment vol avortar el treball de la cpia de seguretat planificat?', 'ftp_reallydelete' =&gt; 'realment vol esborrar el compte ftp %s?', 'mysql_reallydelete' =&gt; 'realment vol esborrar la base de dades %s? es podr desfer.', 'admin_configs_reallyrebuild' =&gt; 'realment vol reconstruir tots els fitxers de configuraci?', 'admin_customer_alsoremovefiles' =&gt; 'treure tamb els fitxers d\'usuari?', 'admin_customer_alsoremovemail' =&gt; 'eliminar completament les dades de correu electrnic del sistema de fitxers?', 'admin_customer_alsoremoveftphomedir' =&gt; 'treure tamb el directori de l\'usuari ftp?', 'admin_ip_reallydelete' =&gt; 'realment vol esborrar l\'adrea ip %s?', 'admin_domain_reallydocrootoutofcustomerroot' =&gt; 'ests segur que vol que l\'arrel del document per aquest domini estigui dins l\'arrel del client?', 'admin_counters_reallyupdate' =&gt; 'realment vol recalcular l\'s de recursos?', 'admin_cleartextmailpws_reallywipe' =&gt; 'realment vol esborrar totes les contrasenyes encriptades dels comptes de correu de la taula mail_users? aix es pot revertir. l\'opci d\'emmagatzemar les contrasenyes de correu electrnic sense xifrar tamb es desactivar.', 'logger_reallytruncate' =&gt; 'realment vol truncar la taula "%s"?', 'admin_quotas_reallywipe' =&gt; 'realment vol esborrar totes les quotes de la taula mail_users? aix es pot revertir.', 'admin_quotas_reallyenforce' =&gt; 'realment vol aplicar la quota per defecte tots els usuaris? aix es pot revertir.', 'phpsetting_reallydelete' =&gt; 'realment vol suprimir aquesta configuraci? tots els dominis que utilitzen aquesta configuraci seran canviats la configuraci per defecte.', 'fpmsetting_reallydelete' =&gt; 'realment vol eliminar aquesta configuraci de php-fpm? totes les configuracions de php que utilitzin aquests parmetres es canviaran la configuraci per defecte.', 'remove_subbutmain_domains' =&gt; 'treure tamb els dominis que s\'afegeixen com dominis complets per que sn subdominis d\'aquest domini?', 'customer_reallyunlock' =&gt; 'realment vol desbloquejar el client %s?', 'admin_integritycheck_reallyfix' =&gt; 'realment vol intentar arreglar tots els problemes d\'integritat de la base de dades automticament?', 'plan_reallydelete' =&gt; 'realment vol eliminar el pla d\'allotjament %s?', 'apikey_reallydelete' =&gt; 'realment vol esborrar aquesta api-key?', 'apikey_reallyadd' =&gt; 'realment vol crear una nova api-key?', 'dnsentry_reallydelete' =&gt; 'realment vol suprimir aquesta entrada dns?', 'certificate_reallydelete' =&gt; 'realment vol esborrar aquest certificat?', 'cache_reallydelete' =&gt; 'realment vol esborrar la memria cau?' ], 'redirect_desc' =&gt; [ 'rc_default' =&gt; 'per defecte', 'rc_movedperm' =&gt; 'mogut permanentment', 'rc_found' =&gt; 'trobat', 'rc_seeother' =&gt; 'veure\'n un altre', 'rc_tempred' =&gt; 'redirecci temporal' ], 'serversettings' =&gt; [ 'session_timeout' =&gt; [ 'title' =&gt; 'temps d\'espera de la sessi', 'description' =&gt; 'quant de temps ha d\'estar inactiu un usuari perqu s\'invalidi la sessi (segons)?' ], 'accountprefix' =&gt; [ 'title' =&gt; 'prefix de client', 'description' =&gt; 'quin prefix han de tenir els comptes de client?' ], 'mysqlprefix' =&gt; [ 'title' =&gt; 'prefix sql', 'description' =&gt; 'quin prefix han de tenir els comptes mysql?&lt;br/&gt;utilitzeu "random" com valor per obtenir un prefix aleatori de 3 dgits&lt;br/&gt;utilitzeu "dbname" com valor, s\'utilitza un camp de nom de base de dades juntament amb el nom del client com prefix.' ], 'ftpprefix' =&gt; [ 'title' =&gt; 'prefix ftp', 'description' =&gt; 'quin prefix han de tenir els comptes ftp?&lt;br/&gt;&lt;b&gt;si canvies aix, tamb haurs de canviar la consulta sql quota al fitxer de configuraci del servidor ftp en cas que l\'utilitzis&lt;/b&gt;. ' ], 'documentroot_prefix' =&gt; [ 'title' =&gt; 'directori d\'inici', 'description' =&gt; 'on s\'han d\'emmagatzemar tots els directoris d\'inici?' ], 'logfiles_directory' =&gt; [ 'title' =&gt; 'directori logfiles', 'description' =&gt; 'on s\'han d\'emmagatzemar tots els fitxers de registre?' ], 'logfiles_script' =&gt; [ 'title' =&gt; 'script personalitzat per enviar els fitxers de registre', 'description' =&gt; 'pot especificar un script aqu utilitzar els marcadors de posici &lt;strong&gt;{logfile}, {domain} {customer}&lt;/strong&gt; si cal. en cas que vulgui utilitzar-lo, ha d\'activar tamb l\'opci &lt;strong&gt;pipe webserver logfiles&lt;/strong&gt;. cal el prefix pipe.' ], 'logfiles_format' =&gt; [ 'title' =&gt; 'format de registre d\'accs', 'description' =&gt; 'introduu aqu un format de registre personalitzat d\'acord amb les especificacions del vostre servidor web, deixi buit per defecte. depenent del seu format, la cadena ha d\'estar entre cometes.&lt;br/&gt;si s\'utilitza amb nginx, es veur com &lt;i&gt;log_format&lt;/i&gt; &lt;i&gt;frx_custom&lt;/i&gt; &lt;i&gt; {configured_value}&lt;/i &gt;.&lt;br/&gt;si s\'utilitza amb apache, es veur com &lt;i&gt;logformat {configured_value} frx_custom&lt;/i&gt;.&lt;br/&gt;&lt;strong&gt;atenci&lt;/strong&gt;: es comprovar si el codi cont errors. si cont errors, el servidor web podria tornar arrencar!' ], 'logfiles_type' =&gt; [ 'title' =&gt; 'tipus de registre d\'accs', 'description' =&gt; 'trieu aqu entre &lt;strong&gt;combinat&lt;/strong&gt; &lt;strong&gt;vhost_combinat&lt;/strong&gt;.' ], 'logfiles_piped' =&gt; [ 'title' =&gt; 'canalitzar els fitxers de registre del servidor web l\'script especificat (veure dalt)', 'description' =&gt; 'si utilitzeu un script personalitzat per als fitxers de registre, haureu d\'activar-lo perqu s\'executi.' ], 'ipaddress' =&gt; [ 'title' =&gt; 'adrea ip', 'description' =&gt; 'quina l\'adrea ip principal d\'aquest servidor?' ], 'hostname' =&gt; [ 'title' =&gt; 'nom de host', 'description' =&gt; 'quin el nom de host d\'aquest servidor?' ], 'apachereload_command' =&gt; [ 'title' =&gt; 'ordre de recrrega del servidor web', 'description' =&gt; 'quina l\'ordre del servidor web per recarregar els fitxers de configuraci?' ], 'bindenable' =&gt; [ 'title' =&gt; 'habilitar servidor de noms', 'description' =&gt; 'aqu es pot habilitar deshabilitar globalment el servidor de noms.' ], 'bindconf_directory' =&gt; [ 'title' =&gt; 'directori de configuraci del servidor dns', 'description' =&gt; 'on s\'han de desar els fitxers de configuraci del servidor dns?' ], 'bindreload_command' =&gt; [ 'title' =&gt; 'ordre de recrrega del servidor dns', 'description' =&gt; 'quina la comanda per recarregar el dimoni del servidor dns?' ], 'vmail_uid' =&gt; [ 'title' =&gt; 'mails-uid', 'description' =&gt; 'quin userid han de tenir els correus?' ], 'vmail_gid' =&gt; [ 'title' =&gt; 'mails-gid', 'description' =&gt; 'quin groupid ha de tenir mails?' ], 'vmail_homedir' =&gt; [ 'title' =&gt; 'mails-homedir', 'description' =&gt; 'on s\'haurien d\'emmagatzemar tots els correus?' ], 'adminmail' =&gt; [ 'title' =&gt; 'remitent', 'description' =&gt; 'quina l\'adrea del remitent per als correus electrnics enviats des del panell?' ], 'phpmyadmin_url' =&gt; [ 'title' =&gt; 'url de phpmyadmin', 'description' =&gt; 'quina la url de phpmyadmin? (ha de comenar per http(s)://)' ], 'webmail_url' =&gt; [ 'title' =&gt; 'url de webmail', 'description' =&gt; 'quina la url de webmail? (ha de comenar per http(s)://)' ], 'webftp_url' =&gt; [ 'title' =&gt; 'url de webftp', 'description' =&gt; 'quina la url de webftp? (ha de comenar per http(s)://)' ], 'language' =&gt; [ 'description' =&gt; 'quin el llenguatge estndard del vostre servidor?' ], 'maxloginattempts' =&gt; [ 'title' =&gt; 'nombre mxim d\'intents d\'inici de sessi', 'description' =&gt; 'nombre mxim d\'intents d\'inici de sessi desprs dels quals es desactiva el compte.' ], 'deactivatetime' =&gt; [ 'title' =&gt; 'temps de desactivaci', 'description' =&gt; 'temps (segons) que es desactiva un compte desprs de massa intents d\'inici de sessi.' ], 'pathedit' =&gt; [ 'title' =&gt; 'tipus d\'entrada de ruta', 'description' =&gt; 's\'ha de seleccionar una ruta amb un men desplegable amb un camp d\'entrada?' ], 'nameservers' =&gt; [ 'title' =&gt; 'servidors de noms', 'description' =&gt; 'una llista separada per comes que cont els noms de host de tots els servidors de noms. el primer ser el principal.' ], 'mxservers' =&gt; [ 'title' =&gt; 'servidors mx', 'description' =&gt; 'una llista separada per comes que cont un parell d\'un nombre un nom de sistema principal separats per espais en blanc (per exemple, \'10 mx.exemple.com\') que cont els servidors mx.' ], 'paging' =&gt; [ 'title' =&gt; 'entrades per pgina', 'description' =&gt; 'quantes entrades es mostraran una pgina? (0 = desactivar la paginaci)' ], 'defaultip' =&gt; [ 'title' =&gt; 'ip/port per defecte', 'description' =&gt; 'seleccioni totes les adreces ip que voleu utilitzar com predeterminades per als nous dominis.' ], 'defaultsslip' =&gt; [ 'title' =&gt; 'ip/port ssl per defecte', 'description' =&gt; 'seleccioni totes les adreces ip amb ssl habilitat que voleu utilitzar per defecte per als nous dominis' ], 'phpappendopenbasedir' =&gt; [ 'title' =&gt; 'rutes afegir openbasedir', 'description' =&gt; 'aquestes rutes (separades per dos punts) s\'afegiran la declaraci openbasedir cada contenidor vhost.' ], 'natsorting' =&gt; [ 'title' =&gt; 'utilitzar ordenaci humana natural la vista de llista', 'description' =&gt; 'ordena les llistes com web1 -&gt; web2 -&gt; web11 en lloc de web1 -&gt; web11 -&gt; web2.' ], 'deactivateddocroot' =&gt; [ 'title' =&gt; 'docroot per usuaris desactivats', 'description' =&gt; 'quan un usuari desactivat aquesta ruta utilitzada com el seu docroot. deixar buit per crear cap vhost.' ], 'mailpwcleartext' =&gt; [ 'title' =&gt; 'desar tamb les contrasenyes dels comptes de correu sense xifrar la base de dades', 'description' =&gt; 'si aquesta opci est activada, totes les contrasenyes seran guardades sense encriptar (text clar, llegible per qualsevol amb accs la base de dades) la taula mail_users. activeu aquesta opci noms si voleu utilitzar sasl.' ], 'ftpdomain' =&gt; [ 'title' =&gt; 'comptes ftp @domini', 'description' =&gt; 'els clients poden crear comptes ftp user@customerdomain?' ], 'mod_fcgid' =&gt; [ 'title' =&gt; 'activar fcgid', 'description' =&gt; 'utilitzi aix per executar php amb el compte d\'usuari corresponent.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;aix necessita una configuraci especial del servidor web per apache, vegeu &lt;a target="_blank" href="https://docs.froxlor.org/latest/admin-guide/configuration/fcgid/"&gt;fcgid - manual&lt;/a&gt;&lt;/b&gt;', 'configdir' =&gt; [ 'title' =&gt; 'directori de configuraci', 'description' =&gt; 'on s\'han de desar tots els fitxers de configuraci fcgid? si utilitzeu un binari suexec autocompilat, que la situaci normal, aquesta ruta ha d\'estar sota /var/www/&lt;br/&gt;&lt;br/&gt;&lt;div class="text-danger"&gt;nota: el contingut d\'aquesta carpeta s\'esborra regularment, aix que eviteu emmagatzemar dades manualment.&lt;/div&gt;' ], 'tmpdir' =&gt; [ 'title' =&gt; 'directori temporal', 'description' =&gt; 'on s\'han d\'emmagatzemar els directoris temporals' ], 'starter' =&gt; [ 'title' =&gt; 'processos per domini', 'description' =&gt; 'quants processos s\'haurien d\'iniciar/permetre per domini? es recomana el valor 0 perqu php gestionar llavors la quantitat de processos per si mateix de forma molt eficient.' ], 'wrapper' =&gt; [ 'title' =&gt; 'wrapper en vhosts', 'description' =&gt; 'com s\'ha d\'incloure el wrapper als vhosts' ], 'peardir' =&gt; [ 'title' =&gt; 'directoris globals de pear', 'description' =&gt; 'quins directoris globals de pear han de ser reemplaats cada configuraci php.ini? els directoris diferents han d\'estar separats per dos punts.' ], 'maxrequests' =&gt; [ 'title' =&gt; 'nombre mxim de peticions per domini', 'description' =&gt; 'quantes peticions cal permetre per domini?' ], 'defaultini' =&gt; 'configuraci php per defecte per nous dominis', 'defaultini_ownvhost' =&gt; 'configuraci php per defecte per froxlor-vhost', 'idle_timeout' =&gt; [ 'title' =&gt; 'temps d\'espera', 'description' =&gt; 'configuraci de temps d\'espera per fastcgi mod.' ] ], 'sendalternativemail' =&gt; [ 'title' =&gt; 'utilitzar una adrea de correu electrnic alternativa', 'description' =&gt; 'enviar la contrasenya una adrea diferent durant la creaci del compte de correu electrnic.' ], 'apacheconf_vhost' =&gt; [ 'title' =&gt; 'fitxer/nom de directori de configuraci del servidor web vhost', 'description' =&gt; 'on s\'ha de desar la configuraci del vhost? podeu especificar aqu un fitxer (tots els vhosts en un fitxer) un directori (cada vhost al vostre propi fitxer).' ], 'apacheconf_diroptions' =&gt; [ 'title' =&gt; 'fitxer/nom de directori de configuraci de diroptions del servidor web', 'description' =&gt; 'on s\'ha d\'emmagatzemar la configuraci de diroptions? podeu especificar un fitxer (totes les diroptions en un fitxer) directori (cada diroption en el vostre propi fitxer) aqu.' ], 'apacheconf_htpasswddir' =&gt; [ 'title' =&gt; 'nom de directori per htpasswd webserver', 'description' =&gt; 'on s\'han de desar els fitxers htpasswd per la protecci de directoris?' ], 'mysql_access_host' =&gt; [ 'title' =&gt; 'mysql-access-hosts', 'description' =&gt; 'una llista separada per comes dels hosts des dels quals s\'ha de permetre als usuaris connectar-se al servidor mysql. per permetre una subxarxa vlida la sintaxi netmask cidr.' ], 'webalizer_quiet' =&gt; [ 'title' =&gt; 'sortida de webalizer', 'description' =&gt; 'verbositat del programa webalizer' ], 'logger' =&gt; [ 'enable' =&gt; 'registre activat/desactivat', 'severity' =&gt; 'nivell de registre', 'types' =&gt; [ 'title' =&gt; 'tipus de registre', 'description' =&gt; 'especifiqueu els tipus de registre. per seleccionar diversos tipus, mantingueu premuda la tecla ctrl mentre selecciona.&lt;br/&gt;els tipus de registre disponibles sn: syslog, file, mysql' ], 'logfile' =&gt; [ 'title' =&gt; 'nom del fitxer de registre', 'description' =&gt; 'noms s\'utilitza si el log-type inclou "file". aquest fitxer es crear froxlor/logs/. aquesta carpeta est protegida contra l\'accs pblic.' ], 'logcron' =&gt; 'log cronjobs', 'logcronoption' =&gt; [ 'never' =&gt; 'mai', 'once' =&gt; 'un cop', 'always' =&gt; 'sempre' ] ], 'ssl' =&gt; [ 'use_ssl' =&gt; [ 'title' =&gt; 'activar de ssl', 'description' =&gt; 'marqui aquesta opci si vol utilitzar ssl per al seu servidor web' ], 'ssl_cert_file' =&gt; [ 'title' =&gt; 'ruta al certificat ssl', 'description' =&gt; 'especifiqui la ruta incloent el nom del fitxer .crt .pem (certificat principal)' ], 'openssl_cnf' =&gt; 'valors predeterminats per crear el fitxer cert', 'ssl_key_file' =&gt; [ 'title' =&gt; 'ruta al fitxer de claus ssl', 'description' =&gt; 'especifiqui la ruta incloent el nom de fitxer per al fitxer de clau privada (.key principalment)' ], 'ssl_ca_file' =&gt; [ 'title' =&gt; 'ruta al certificat ssl ca (opcional)', 'description' =&gt; 'autenticaci del client, configuri aix noms si sap el que s.' ], 'ssl_cipher_list' =&gt; [ 'title' =&gt; 'configuri els xifrats ssl permesos', 'description' =&gt; 'aquesta una llista de xifradors que vol (o vol) utilitzar quan parli ssl. per una llista de xifradors com incloure\'ls/excloure\'ls, vegeu les seccions "cipher list format" "cipher strings" &lt;a href="https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html"&gt;la pgina man de xifradors&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;el valor per defecte s:&lt;/b&gt;&lt;pre&gt;ecdh+aesgcm:ecdh+aes256:!anull:!md5:!dss:!dh:!aes128&lt;/pre&gt;' ], 'apache24_ocsp_cache_path' =&gt; [ 'title' =&gt; 'apache 2.4: ruta la memria cau de grapat ocsp', 'description' =&gt; 'configura la memria cau utilitzada per emmagatzemar les respostes ocsp que s\'inclouen als handshakes tls.' ], 'ssl_protocols' =&gt; [ 'title' =&gt; 'configurar la versi del protocol tls', 'description' =&gt; 'aquesta una llista de protocols ssl que vol (o vol) utilitzar quan utilitzeu ssl. &lt;b&gt;nota:&lt;/b&gt; possible que alguns navegadors antics admetin les versions de protocol ms recents.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;el valor per defecte s:&lt;/b&gt;&lt;pre&gt;tlsv1.2&lt;/pre&gt;' ], 'tlsv13_cipher_list' =&gt; [ 'title' =&gt; 'configurar xifrats explcits tlsv1.3 si es fan servir', 'description' =&gt; 'aquesta una llista de xifradors que voleu (o voleu) utilitzar quan parleu tlsv1.3. per una llista de xifradors com incloure\'ls/excloure\'ls, vegeu &lt;a href="https://wiki.openssl.org/index.php/tls1.3"&gt;els documents per tlsv1.3&lt;/a&gt;.&lt;br/ &gt;&lt;br/&gt;&lt;b&gt;el valor per defecte buit&lt;/b&gt;' ] ], 'default_vhostconf' =&gt; [ 'title' =&gt; 'configuraci vhost per defecte', 'description' =&gt; 'el contingut d\'aquest camp s\'inclour directament en aquest contenidor ip/port vhost. podeu utilitzar les variables segents:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt; /code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (si escau)&lt;br/&gt; atenci: es comprovar si el codi cont errors. si cont errors, el servidor web podria tornar arrencar!' ], 'apache_globaldiropt' =&gt; [ 'title' =&gt; 'opcions de directori per customer-prefix', 'description' =&gt; 'el contingut d\'aquest camp s\'inclour la configuraci d\'apache 05_froxlor_dirfix_nofcgid.conf. si est buit, es far servir el valor per defecte:&lt;br/&gt;&lt;br/&gt;apache &gt;=2.4&lt;br/&gt;&lt;code&gt;require granted&lt;br/&gt;allowoverride all&lt;/code&gt;&lt;br/&gt;&lt;br/&gt;apache &lt;=2.2&lt;br/&gt;&lt;code&gt;order allow,deny&lt;br/&gt;allow all&lt;/code&gt;' ], 'default_vhostconf_domain' =&gt; [ 'description' =&gt; 'el contingut d\'aquest camp s\'inclou directament al contenidor vhost del domini. podeu utilitzar les variables segents:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt; /code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (si escau)&lt;br/&gt; atenci: es comprovar si el codi cont errors. si cont errors, el servidor web podria tornar arrencar!' ], 'decimal_places' =&gt; 'nombre de decimals la sortida de trnsit/espai web', 'selfdns' =&gt; [ 'title' =&gt; 'configuraci dns del domini del client' ], 'selfdnscustomer' =&gt; [ 'title' =&gt; 'permetre als clients editar la configuraci dns del domini' ], 'unix_names' =&gt; [ 'title' =&gt; 'utilitzar noms d\'usuari compatibles amb unix', 'description' =&gt; 'permet utilitzar &lt;strong&gt;-&lt;/strong&gt; &lt;strong&gt;_&lt;/strong&gt; als noms d\'usuari si &lt;strong&gt;no&lt;/strong&gt;' ], 'allow_password_reset' =&gt; [ 'title' =&gt; 'permetre que els clients restableixin la contrasenya', 'description' =&gt; 'els clients poden restablir la contrasenya se\'ls enviar un enlla d\'activaci la seva adrea de correu electrnic.' ], 'allow_password_reset_admin' =&gt; [ 'title' =&gt; 'permetre que els administradors restableixin la contrasenya', 'description' =&gt; 'els administradors/revenedors poden restablir la contrasenya se\'ls enviar un enlla d\'activaci la seva adrea de correu electrnic.' ], 'mail_quota' =&gt; [ 'title' =&gt; 'quota de bstia', 'description' =&gt; 'la quota per defecte per les noves bsties creades (megabyte).' ], 'mail_quota_enabled' =&gt; [ 'title' =&gt; 'utilitzar mailbox-quota per clients', 'description' =&gt; 'activar per utilitzar quotes les bsties de correu. per defecte &lt;b&gt;no&lt;/b&gt; ja que aix requereix una configuraci especial.', 'removelink' =&gt; 'faci clic aqu per esborrar totes les quotes dels comptes de correu.', 'enforcelink' =&gt; 'faci clic aqu per aplicar la quota per defecte tots els comptes de correu dels usuaris.' ], 'index_file_extension' =&gt; [ 'description' =&gt; 'quina extensi de fitxer s\'ha d\'utilitzar per al fitxer d\'ndex als directoris de clients acabats de crear? aquesta extensi de fitxer s\'utilitzar si vost un dels seus administradors ha creat la seva prpia plantilla de fitxer d\'ndex.', 'title' =&gt; 'extensi de fitxer per al fitxer d\'ndex en directoris de clients acabats de crear' ], 'session_allow_multiple_login' =&gt; [ 'title' =&gt; 'permetre l\'inici de sessi mltiple', 'description' =&gt; 'si s\'activa, un usuari pot iniciar sessi diverses vegades.' ], 'panel_allow_domain_change_admin' =&gt; [ 'title' =&gt; 'permetre moure dominis entre administradors', 'description' =&gt; 'si est activat pot canviar l\'admin d\'un domini domainsettings.&lt;br/&gt;&lt;b&gt;atenci:&lt;/b&gt; si un client est assignat al mateix administrador que el domini, l\'administrador pot veure tots els altres dominis d\'aquest client!' ], 'panel_allow_domain_change_customer' =&gt; [ 'title' =&gt; 'permetre moure dominis entre clients', 'description' =&gt; 'si est activat pots canviar el client d\'un domini domainsettings.&lt;br/&gt;&lt;b&gt;atenci:&lt;/b&gt; froxlor canvia el documentroot al homedir per defecte del nou client (+ carpeta de domini si est activat)' ], 'specialsettingsforsubdomains' =&gt; [ 'description' =&gt; 'en cas afirmatiu, aquests parmetres personalitzats de vhost s\'afegiran tots els subdominis; en cas negatiu, s\'eliminaran els ajustaments especials de subdomini.' ], 'panel_password_min_length' =&gt; [ 'title' =&gt; 'longitud mnima de contrasenya', 'description' =&gt; 'aqu pot establir una longitud mnima per les contrasenyes. 0\' vol dir que es requereix longitud mnima.' ], 'system_store_index_file_subs' =&gt; [ 'title' =&gt; 'emmagatzemar el fitxer ndex per defecte tamb les noves subcarpetes', 'description' =&gt; 'si s\'activa, el fitxer d\'ndex per defecte s\'emmagatzema cada ruta de subdomini creada recentment (no si la carpeta ja existeix).' ], 'adminmail_return' =&gt; [ 'title' =&gt; 'adrea de resposta', 'description' =&gt; 'defineix una adrea de correu electrnic com adrea de resposta per als correus electrnics enviats pel panell.' ], 'adminmail_defname' =&gt; 'nom del remitent del correu electrnic del panell', 'stdsubdomainhost' =&gt; [ 'title' =&gt; 'subdomini estndard del client', 'description' =&gt; 'quin nom de host s\'ha de fer servir per crear subdominis estndard per al client. si est buit, s\'utilitza el nom de sistema principal del sistema.' ], 'awstats_path' =&gt; 'ruta awstats \'awstats_buildstaticpages.pl\'', 'awstats_conf' =&gt; 'ruta de configuraci d\'awstats', 'defaultttl' =&gt; 'ttl de domini per bind en segons (per defecte \'604800\' = 1 setmana)', 'defaultwebsrverrhandler_enabled' =&gt; 'habilitar documents d\'error per defecte per tots els clients', 'defaultwebsrverrhandler_err401' =&gt; [ 'title' =&gt; 'fitxer/url per l\'error 401', 'description' =&gt; '&lt;div class="text-danger"&gt;no suportat a: lighttpd&lt;/div&gt;' ], 'defaultwebsrverrhandler_err403' =&gt; [ 'title' =&gt; 'fitxer/url per l\'error 403', 'description' =&gt; '&lt;div class="text-danger"&gt;no suportat a: lighttpd&lt;/div&gt;' ], 'defaultwebsrverrhandler_err404' =&gt; 'fitxer/url per l\'error 404', 'defaultwebsrverrhandler_err500' =&gt; [ 'title' =&gt; 'fitxer/url per l\'error 500', 'description' =&gt; '&lt;div class="text-danger"&gt;no suportat a: lighttpd&lt;/div&gt;' ], 'ftpserver' =&gt; [ 'desc' =&gt; 'si seleccioneu pureftpd, els fitxers .ftpquota per quotes d\'usuari es creen s\'actualitzen diriament' ], 'customredirect_enabled' =&gt; [ 'title' =&gt; 'permetre redireccionaments de clients', 'description' =&gt; 'permetre als clients triar el codi http-status per les redireccions que es faran servir' ], 'customredirect_default' =&gt; [ 'title' =&gt; 'redirecci per defecte', 'description' =&gt; 'estableix el codi de redirecci per defecte que s\'utilitzar si el client ho estableix per si mateix' ], 'mail_also_with_mxservers' =&gt; 'crear mail-, imap-, pop3- smtp-"a record" tamb amb mx-servers set', 'froxlordirectlyviahostname' =&gt; 'accedir froxlor directament travs del nom de host', 'panel_password_regex' =&gt; [ 'title' =&gt; 'expressi regular per contrasenyes', 'description' =&gt; 'aqu pot establir una expressi regular per la complexitat de les contrasenyes.&lt;br/&gt;buit = cap requeriment' ], 'perl_path' =&gt; [ 'title' =&gt; 'ruta perl', 'description' =&gt; 'per defecte /usr/bin/perl' ], 'mod_fcgid_ownvhost' =&gt; [ 'title' =&gt; 'habilita fcgid per al vhost de froxlor', 'description' =&gt; 'si est habilitat, froxlor tamb s\'executar sota un usuari local' ], 'perl' =&gt; [ 'suexecworkaround' =&gt; [ 'title' =&gt; 'habilitar soluci suexec', 'description' =&gt; 'habilitar noms si els directoris del client estan dins de la ruta apache suexec.&lt;br/&gt;si est habilitat, froxlor generar un enlla simblic des del directori del client habilitat per perl + /cgi-bin/ la ruta donada.&lt;br /&gt;tingueu en compte que perl noms funcionar al subdirectori de carpetes /cgi-bin/ la carpeta en si (com ho fa sense aquesta soluci!)' ], 'suexeccgipath' =&gt; [ 'title' =&gt; 'ruta per als enllaos simblics de directori habilitats per perl del client', 'description' =&gt; 'noms heu de configurar aix si la soluci de suexec est activada.&lt;br/&gt;atenci: assegureu-vos que aquesta ruta est dins de la ruta de suexec en cas contrari aquesta soluci intil.' ] ], 'awstats_awstatspath' =&gt; 'ruta awstats \'awstats.pl\'.', 'awstats_icons' =&gt; [ 'title' =&gt; 'ruta la carpeta d\'icones d\'awstats', 'description' =&gt; 'exemple: /usr/share/awstats/htdocs/icon/' ], 'login_domain_login' =&gt; 'permetre login amb dominis', 'perl_server' =&gt; [ 'title' =&gt; 'ubicaci del socket del servidor perl', 'description' =&gt; 'pot trobar una guia senzilla a: &lt;a target="blank" href="https://www.nginx.com/resources/wiki/start/topics/examples/fcgiwrap/"&gt;nginx.com&lt;/a&gt;' ], 'nginx_php_backend' =&gt; [ 'title' =&gt; 'nginx php backend', 'description' =&gt; 'aqu el procs php est escoltant peticions de nginx, pot ser un socket unix de combinaci ip:port&lt;br/&gt;*no s\'utilitza amb php-fpm' ], 'phpreload_command' =&gt; [ 'title' =&gt; 'ordre de reinici de php', 'description' =&gt; 's\'utilitza per recarregar el backend php si se n\'utilitza algun&lt;br/&gt;per defecte: en blanc&lt;br/&gt;*no s\'utilitza amb php-fpm' ], 'phpfpm' =&gt; [ 'title' =&gt; 'habilitar php-fpm', 'description' =&gt; '&lt;b&gt;aix necessita una configuraci especial del servidor web veure &lt;a target="_blank" href="https://docs.froxlor.org/latest/admin-guide/configuration/php-fpm/"&gt;manual php-fpm&lt;/a&gt;&lt;/b&gt;' ], 'phpfpm_settings' =&gt; [ 'configdir' =&gt; 'directori de configuraci de php-fpm', 'aliasconfigdir' =&gt; 'directori lies de configuraci de php-fpm', 'reload' =&gt; 'ordre de reinici de php-fpm', 'pm' =&gt; 'control del gestor de processos (pm)', 'max_children' =&gt; [ 'title' =&gt; 'nombre de processos fill', 'description' =&gt; 'el nombre de processos fill ser creats quan pm est en \'static\' el nombre mxim de processos fill ser creats quan pm est en \'dynamic/ondemand\'&lt;br/&gt;equivalent php_fcgi_children' ], 'start_servers' =&gt; [ 'title' =&gt; 'el nombre de processos fill creats l\'inici', 'description' =&gt; 'nota: noms es fa servir quan pm est configurat com \'dynamic' ], 'min_spare_servers' =&gt; [ 'title' =&gt; 'el nombre mnim desitjat de processos de servidor inactius', 'description' =&gt; 'nota: noms es fa servir quan pm \'dynamic\'&lt;br/&gt;nota: obligatori quan pm \'dynamic' ], 'max_spare_servers' =&gt; [ 'title' =&gt; 'el nombre mxim desitjat de processos inactius de servidor', 'description' =&gt; 'nota: noms s\'utilitza quan pm el valor "dynamic".&lt;br/&gt;nota: obligatori quan pm el valor "dynamic".' ], 'max_requests' =&gt; [ 'title' =&gt; 'peticions per fill abans de respawning', 'description' =&gt; 'per un processament infinit de peticions especifiqueu \'0\'. equivalent php_fcgi_max_requests.' ], 'idle_timeout' =&gt; [ 'title' =&gt; 'temps d\'espera', 'description' =&gt; 'configuraci de temps d\'espera per php fpm fastcgi.' ], 'ipcdir' =&gt; [ 'title' =&gt; 'directori ipc fastcgi', 'description' =&gt; 'el directori els sockets php-fpm seran emmagatzemats pel servidor web.&lt;br/&gt;aquest directori ha de ser llegible per al servidor web.' ], 'limit_extensions' =&gt; [ 'title' =&gt; 'extensions permeses', 'description' =&gt; 'limita les extensions de l\'script principal que fpm permetr analitzar. aix pot evitar errors de configuraci al servidor web. noms heu de limitar fpm extensions .php per evitar que usuaris maliciosos utilitzin altres extensions per executar codi php. valor per defecte: .php' ], 'envpath' =&gt; 'rutes per afegir l\'entorn path. deixeu-lo buit per cap variable d\'entorn path', 'override_fpmconfig' =&gt; 'anullar la configuraci de fpm-daemon (pm, max_children, etc.)', 'override_fpmconfig_addinfo' =&gt; '&lt;br/&gt;&lt;span class="text-danger"&gt;noms es fa servir si "override fpm-daemon settings" est en "s"&lt;/span&gt;', 'restart_note' =&gt; 'atenci: la configuraci ser revisada per errors. si cont errors, php-fpm podria tornar arrencar.', 'custom_config' =&gt; [ 'title' =&gt; 'configuraci personalitzada', 'description' =&gt; 'afegeix configuraci personalitzada cada instncia de versi de php-fpm, per exemple &lt;i&gt;pm.status_path = /status&lt;/i&gt; per monitoratge. les variables de sota poden ser utilitzades aqu. &lt;strong&gt;atenci: la configuraci ser revisada per errors. si cont errors, php-fpm podria tornar arrencar!&lt;/strong&gt;' ], 'allow_all_customers' =&gt; [ 'title' =&gt; 'assigneu aquesta configuraci tots els clients existents', 'description' =&gt; 'establiu-lo "cert" si voleu assignar aquesta configuraci tots els clients existents perqu puguin utilitzar-la. aquesta configuraci permanent, per es pot executar diverses vegades.' ] ], 'report' =&gt; [ 'report' =&gt; 'habilitar l\'enviament d\'informes sobre l\'s de la web el trnsit', 'webmax' =&gt; [ 'title' =&gt; 'nivell d\'advertncia en percentatge per l\'espai web', 'description' =&gt; 'els valors vlids sn 0-150. establir aquest valor 0 desactiva aquest informe.' ], 'trafficmax' =&gt; [ 'title' =&gt; 'nivell d\'advertncia en percentatge per al trnsit', 'description' =&gt; 'els valors vlids sn de 0 150. el valor 0 desactiva aquest informe.' ] ], 'dropdown' =&gt; 'desplegable', 'manual' =&gt; 'manual', 'default_theme' =&gt; 'tema per defecte', 'validate_domain' =&gt; 'validar noms de domini', 'diskquota_enabled' =&gt; 'quota activada?', 'diskquota_repquota_path' =&gt; [ 'description' =&gt; 'ruta repquota' ], 'diskquota_quotatool_path' =&gt; [ 'description' =&gt; 'ruta quotatool' ], 'diskquota_customer_partition' =&gt; [ 'description' =&gt; 'partici en qu s\'emmagatzemen els fitxers del client' ], 'vmail_maildirname' =&gt; [ 'title' =&gt; 'nom del maildir', 'description' =&gt; 'directori maildir al compte de l\'usuari. normalment \'maildir\', en algunes implementacions \'.maildir\', directament al directori de l\'usuari si es deixa en blanc.' ], 'catchall_enabled' =&gt; [ 'title' =&gt; 'utilitzar catchall', 'description' =&gt; 'vol proporcionar als seus clients la funci catchall?' ], 'apache_24' =&gt; [ 'title' =&gt; 'utilitzi les modificacions per apache 2.4', 'description' =&gt; '&lt;strong class="text-danger"&gt;atenci:&lt;/strong&gt; utilitzeu-lo noms si teniu installada la versi 2.4 superior d\'apache&lt;br/&gt;en cas contrari el vostre servidor web podr arrencar' ], 'nginx_fastcgiparams' =&gt; [ 'title' =&gt; 'ruta al fitxer fastcgi_params', 'description' =&gt; 'especifiqui la ruta al fitxer fastcgi_params de nginx incloent el nom de fitxer' ], 'documentroot_use_default_value' =&gt; [ 'title' =&gt; 'utilitzar el nom de domini com valor per defecte per la ruta documentroot', 'description' =&gt; 'si est habilitat la ruta documentroot buida, el valor per defecte ser el (sub)nom de domini.&lt;br/&gt;&lt;br/&gt;exemples: &lt;br/&gt;/var/clients/nom_client/exemple.com/&lt;br /&gt;/var/clients/nom_client/subdomini.exemple.com/' ], 'panel_phpconfigs_hidesubdomains' =&gt; [ 'title' =&gt; 'amagar subdominis la vista general de configuraci php', 'description' =&gt; 'si s\'activa, els subdominis dels clients es mostraran la vista general de configuracions php, noms es mostrar el nmero de subdominis.&lt;br/&gt;&lt;br/&gt;nota: aix noms ser visible si heu activat fcgid php-fpm .' ], 'panel_phpconfigs_hidestdsubdomain' =&gt; [ 'title' =&gt; 'amagar subdominis estndard la vista general de configuracions php', 'description' =&gt; 'si s\'activa, els subdominis estndard dels clients es mostraran la vista general de configuracions php&lt;br/&gt;&lt;br/&gt;nota: aix noms ser visible si heu activat fcgid php-fpm.' ], 'passwordcryptfunc' =&gt; [ 'title' =&gt; 'tri el mtode de xifratge de contrasenyes utilitzar' ], 'systemdefault' =&gt; 'sistema per defecte', 'panel_allow_theme_change_admin' =&gt; 'permetre als administradors canviar el tema', 'panel_allow_theme_change_customer' =&gt; 'permetre als clients canviar el tema', 'axfrservers' =&gt; [ 'title' =&gt; 'servidors axfr', 'description' =&gt; 'una llista separada per comes d\'adreces ip permeses per transferir (axfr) zones dns.' ], 'powerdns_mode' =&gt; [ 'title' =&gt; 'mode de funcionament powerdns', 'description' =&gt; 'seleccioni el mode powedns: natiu si es necessita replicaci dns (predeterminat) / mestre si es necessita replicaci dns.' ], 'customerssl_directory' =&gt; [ 'title' =&gt; 'webserver customer-ssl certificates-directory', 'description' =&gt; 'on s\'han de crear els certificats ssl especificats pel client?&lt;br/&gt;&lt;br/&gt;&lt;div class="text-danger"&gt;nota: el contingut d\'aquesta carpeta s\'esborra amb regularitat, aix que eviteu emmagatzemar dades manualment. &lt;/div&gt;' ], 'allow_error_report_admin' =&gt; [ 'title' =&gt; 'permetre als administradors/revenedors informar d\'errors la base de dades froxlor', 'description' =&gt; 'nota: mai ens envis dades personals (de clients)!' ], 'allow_error_report_customer' =&gt; [ 'title' =&gt; 'permetre als clients informar d\'errors la base de dades froxlor', 'description' =&gt; 'nota: mai ens envis dades personals (de clients)!' ], 'mailtraffic_enabled' =&gt; [ 'title' =&gt; 'analitzar el trnsit de correu', 'description' =&gt; 'permetre l\'anlisi dels registres del servidor de correu per calcular el trnsit' ], 'mdaserver' =&gt; [ 'title' =&gt; 'tipus de mda', 'description' =&gt; 'tipus de servidor de lliurament de correu' ], 'mdalog' =&gt; [ 'title' =&gt; 'registre mda', 'description' =&gt; 'fitxer de registre del mail delivery server' ], 'mtaserver' =&gt; [ 'title' =&gt; 'tipus de mta', 'description' =&gt; 'tipus d\'agent de transferncia de correu' ], 'mtalog' =&gt; [ 'title' =&gt; 'registre mta', 'description' =&gt; 'fitxer de registre de l\'agent de transferncia de correu' ], 'system_cronconfig' =&gt; [ 'title' =&gt; 'fitxer de configuraci de cron', 'description' =&gt; 'ruta al fitxer de configuraci del servei cron. aquest fitxer ser actualitzat regularment automticament per froxlor.&lt;br/&gt;nota: si us plau &lt;b&gt;assegureu-vos&lt;/b&gt; d\'utilitzar el mateix nom de fitxer que per al froxlor cronjob principal (per defecte: /etc/cron.d/froxlor)!&lt;br/&gt;&lt;br/&gt;si utilitzeu &lt;b&gt;freebsd&lt;/b&gt;, si us plau especifiqueu &lt;i&gt;/etc/crontab&lt;/i&gt; aqu!' ], 'system_crondreload' =&gt; [ 'title' =&gt; 'ordre de recrrega pel domini cron', 'description' =&gt; 'especifiqui l\'ordre executar per recarregar el dimoni cron del vostre sistema' ], 'system_croncmdline' =&gt; [ 'title' =&gt; 'ordre d\'execuci de cron (php-binari)', 'description' =&gt; 'ordre per executar les nostres tasques cron. canvieu-ho noms si sabeu el que esteu fent (per defecte: "/usr/bin/nice -n 5 /usr/bin/php -q").' ], 'system_cron_allowautoupdate' =&gt; [ 'title' =&gt; 'permetre actualitzar automticament la base de dades', 'description' =&gt; '&lt;div class="text-danger"&gt;&lt;b&gt;atenci:&lt;/b&gt;&lt;/div&gt; aquesta configuraci permet al cronjob saltar-se la comprovaci de versi dels fitxers froxlors la base de dades executa l\'actualitzaci de la base de dades en cas que passi un desajust de versi.&lt;br/&gt;&lt;br/&gt;&lt;div class= "text-danger"&gt;auto-update sempre establir valors per defecte per noves configuracions canvis. aix pot ser sempre adequat per al vostre sistema. si us plau, penseu-ho dues vegades abans d\'activar aquesta opci&lt;/div&gt;' ], 'dns_createhostnameentry' =&gt; 'crear bind-zone/config per al nom de host del sistema', 'panel_password_alpha_lower' =&gt; [ 'title' =&gt; 'minscules', 'description' =&gt; 'la contrasenya ha de contenir com mnim una lletra minscula (a-z).' ], 'panel_password_alpha_upper' =&gt; [ 'title' =&gt; 'majscules', 'description' =&gt; 'la contrasenya ha de contenir com mnim una lletra majscula (a-z).' ], 'panel_password_numeric' =&gt; [ 'title' =&gt; 'nmeros', 'description' =&gt; 'la contrasenya ha de contenir almenys un nmero (0-9).' ], 'panel_password_special_char_required' =&gt; [ 'title' =&gt; 'carcter especial', 'description' =&gt; 'la contrasenya ha de contenir com mnim un dels carcters definits continuaci.' ], 'panel_password_special_char' =&gt; [ 'title' =&gt; 'llista de carcters especials', 'description' =&gt; 'es requereix un d\'aquests carcters si s\'estableix l\'opci anterior.' ], 'apache_itksupport' =&gt; [ 'title' =&gt; 'modificacions d\'s per apache itk-mpm', 'description' =&gt; '&lt;strong class="text-danger"&gt;atenci:&lt;/strong&gt; utilitzeu-la noms si teniu apache itk-mpm habilitat&lt;br/&gt;, altrament el vostre servidor web es podr iniciar.' ], 'letsencryptca' =&gt; [ 'title' =&gt; 'entorn acme', 'description' =&gt; 'entorn que s\'utilitzar per als certificats let\'s encrypt / zerossl.' ], 'letsencryptchallengepath' =&gt; [ 'title' =&gt; 'ruta per als desafiaments let\'s encrypt', 'description' =&gt; 'directori des del qual s\'oferiran els reptes let\'s encrypt travs d\'un lies global.' ], 'letsencryptkeysize' =&gt; [ 'title' =&gt; 'mida de la clau per nous certificats let\'s encrypt', 'description' =&gt; 'mida de la clau en bits per nous certificats let\'s encrypt.' ], 'letsencryptreuseold' =&gt; [ 'title' =&gt; 'reutilitzar clau let\'s encrypt', 'description' =&gt; 'si s\'activa, s\'utilitzar la mateixa clau per cada renovaci, altrament es generar una clau nova cada vegada.' ], 'leenabled' =&gt; [ 'title' =&gt; 'activar let\'s encrypt', 'description' =&gt; 'si s\'activa, els clients poden deixar que automticament froxlor generi renovi certificats ssl let\'s encrypt per dominis amb una ip/port ssl.&lt;br/&gt;&lt;br/&gt;si us plau recorda que necessites anar travs de la configuraci del servidor web quan s\'activa perqu aquesta caracterstica necessita una configuraci especial.' ], 'caa_entry' =&gt; [ 'title' =&gt; 'generar registres dns caa', 'description' =&gt; 'genera automticament registres caa per dominis habilitats per ssl que utilitzen let\'s encrypt.' ], 'caa_entry_custom' =&gt; [ 'title' =&gt; 'registres dns caa addicionals', 'description' =&gt; 'dns certification authority authorization (caa) un mecanisme de poltica de seguretat internet que permet als titulars de noms de domini indicar les autoritats de certificaci&lt;br/&gt;si estan autoritzades emetre certificats digitals per un nom de domini concret. ho fa mitjanant un nou registre de recursos del sistema de noms de domini (dns) "caa".&lt;br/&gt;&lt;br/&gt;el contingut d\'aquest camp s\'inclour la zona dns directament (cada lnia dna lloc un registre caa ).&lt;br/&gt;si let\'s encrypt est habilitat per aquest domini, aquesta entrada sempre s\'afegir automticament caldr afegir-la manualment:&lt;br/&gt; 0&lt;code&gt;issue "letsencrypt.org"&lt;/code&gt; ( si el domini un domini comod, s\'utilitzar issuewild al seu lloc).&lt;br/&gt;per habilitar l\'informe d\'incidents, podeu afegir un registre &lt;code&gt;iodef&lt;/code&gt;. un exemple per enviar aquest informe &lt;code&gt;me@example.com&lt;/code&gt; seria:&lt;br/&gt; 0&lt;code&gt;iodef "mailto:me@example.com"&lt;/code&gt;&lt;br/&gt;&lt;br/ &gt;&lt;strong&gt;atenci:&lt;/strong&gt; es comprovar si el codi cont errors. si cont errors, possible que els vostres registres caa funcionin!' ], 'backupenabled' =&gt; [ 'title' =&gt; 'activar cpia de seguretat per clients', 'description' =&gt; 'si s\'activa, el client podr programar treballs de cpia de seguretat (cron-backup) que generen un fitxer dins del seu docroot (subdirectori elecci del client)' ], 'dnseditorenable' =&gt; [ 'title' =&gt; 'habilitar editor dns', 'description' =&gt; 'permet als administradors als clients gestionar les entrades dns del domini' ], 'dns_server' =&gt; [ 'title' =&gt; 'dimoni del servidor dns', 'description' =&gt; 'recordi que els dimonis han de ser configurats usant les plantilles de configuraci de froxlors' ], 'panel_customer_hide_options' =&gt; [ 'title' =&gt; 'amagar elements de men grfics de trnsit al panell de client', 'description' =&gt; 'seleccioni els elements que vol amagar al panell de client. per seleccionar diverses opcions, mantingueu premuda la tecla ctrl mentre seleccioneu.' ], 'allow_allow_customer_shell' =&gt; [ 'title' =&gt; 'permetre als clients habilitar l\'accs shell per usuaris ftp', 'description' =&gt; '&lt;strong class="text-danger"&gt;atenci: l\'accs shell permet l\'usuari executar diversos binaris al vostre sistema. utilitzeu-lo amb extrema precauci. si us plau, activeu aix noms si realment sap el que est fent!!!&lt;/strong&gt;' ], 'available_shells' =&gt; [ 'title' =&gt; 'llista de shells disponibles', 'description' =&gt; 'llista separada per comes dels intrprets d\'ordres disponibles perqu el client esculli per als seus usuaris ftp.&lt;br/&gt;&lt;br/&gt;tingueu en compte que l\'intrpret d\'ordres predeterminat &lt;strong&gt;/bin/false&lt;/strong&gt; sempre ser una opci (si est habilitat), fins tot si aquesta configuraci buida. el valor per defecte per als usuaris ftp en qualsevol cas.' ], 'le_froxlor_enabled' =&gt; [ 'title' =&gt; 'activar let\'s encrypt per al froxlor vhost', 'description' =&gt; 'si s\'activa, el froxlor vhost s\'assegurar automticament utilitzant un certificat let\'s encrypt.' ], 'le_froxlor_redirect' =&gt; [ 'title' =&gt; 'activar ssl-redirect per froxlor vhost', 'description' =&gt; 'si s\'activa, totes les peticions http al vostre froxlor seran redirigides al lloc ssl corresponent.' ], 'option_unavailable_websrv' =&gt; '&lt;br/&gt;&lt;em class="text-danger"&gt;disponible noms per a: %s&lt;/em&gt;', 'option_unavailable' =&gt; '&lt;br/&gt;&lt;em class="text-danger"&gt;opci disponible degut altres parmetres.&lt;/em&gt;', 'letsencryptacmeconf' =&gt; [ 'title' =&gt; 'ruta al fragment acme.conf', 'description' =&gt; 'nom de fitxer del fragment de configuraci que permet al servidor web utilitzar el desafiament acme.' ], 'mail_use_smtp' =&gt; 'configurar mailer per utilitzar smtp', 'mail_smtp_host' =&gt; 'especifiqui el servidor smtp', 'mail_smtp_usetls' =&gt; 'activar el xifratge tls', 'mail_smtp_auth' =&gt; 'activar l\'autenticaci smtp', 'mail_smtp_port' =&gt; 'port tcp al qual connectar-se', 'mail_smtp_user' =&gt; 'nom d\'usuari smtp', 'mail_smtp_passwd' =&gt; 'contrasenya smtp', 'http2_support' =&gt; [ 'title' =&gt; 'suport http2', 'description' =&gt; 'habiliti el suport http2 per ssl.&lt;br/&gt;&lt;em class="text-danger"&gt;habilitar noms si el seu webserver suporta aquesta caracterstica (nginx versi 1.9.5+, apache2 versi 2.4.17+)&lt;/em&gt;' ], 'nssextrausers' =&gt; [ 'title' =&gt; 'utilitzar libnss-extrausers en lloc de libnss-mysql', 'description' =&gt; 'no llegir usuaris de la base de dades sin de fitxers. si us plau, activa-ho noms si ja realitzat els passos de configuraci necessaris (system -&gt;&lt;strong class="text-danger"&gt;libnss-extrausers).&lt;/strong&gt;&lt;br/&gt;&lt;strong class="text-danger" &gt;noms per debian/ubuntu (o si ha compilat libnss-extrausers vost mateix!)&lt;/strong&gt;' ], 'le_domain_dnscheck' =&gt; [ 'title' =&gt; 'validar dns de dominis en utilitzar let\'s encrypt', 'description' =&gt; 'si est activat, froxlor validar si el domini que sollicita un certificat let\'s encrypt resol almenys una de les adreces ip del sistema.' ], 'le_domain_dnscheck_resolver' =&gt; [ 'title' =&gt; 'utilitzar un servidor de noms extern per la validaci dns', 'description' =&gt; 'si s\'estableix, froxlor utilitzar aquest dns per validar els dns dels dominis quan utilitzeu let\'s encrypt. si est buit, s\'utilitzar el solucionador dns per defecte del sistema.' ], 'phpsettingsforsubdomains' =&gt; [ 'description' =&gt; 'en cas afirmatiu s\'actualitzar el php-config triat tots els subdominis' ], 'leapiversion' =&gt; [ 'title' =&gt; 'escollir la implementaci acme de let\'s encrypt', 'description' =&gt; 'actualment noms es suporta la implementaci acme v2 per let\'s encrypt.' ], 'enable_api' =&gt; [ 'title' =&gt; 'habilitar d\'api externa', 'description' =&gt; 'per utilitzar la api froxlor cal activar aquesta opci. per obtenir informaci ms detallada, vegeu &lt;a href="https://docs.froxlor.org/latest/api-guide/" target="_new"&gt;https://docs.froxlor.org/&lt;/a&gt;' ], 'api_customer_default' =&gt; '"permetre accs la api" valor per defecte per nous clients', 'dhparams_file' =&gt; [ 'title' =&gt; 'fitxer dhparams (intercanvi de claus diffie-hellman)', 'description' =&gt; 'si s\'especifica aqu un fitxer dhparams.pem, s\'inclour la configuraci del servidor web. deixeu-lo buit per desactivar-lo.&lt;br/&gt;exemple: &lt;code&gt;/etc/ssl/webserver/dhparams&lt;/code&gt;.pem&lt;br/&gt;&lt;br/&gt;si el fitxer existeix, es crear automticament amb la segent ordre: &lt;code&gt;openssl dhparam -out /etc/ssl/webserver/dhparams.pem 4096&lt;/code&gt;. es recomana crear el fitxer abans d\'especificar-lo aqu, ja que la creaci triga fora bloqueja el cronjob.' ], 'errorlog_level' =&gt; [ 'title' =&gt; 'nivell de registre d\'errors', 'description' =&gt; 'especifiqui el nivell de registre d\'errors. per defecte "warn" per usuaris apache "error" per usuaris nginx.' ], 'letsencryptecc' =&gt; [ 'title' =&gt; 'emetre certificat ecc / ecdsa', 'description' =&gt; 'si s\'estableix una mida de clau vlida, el certificat ems utilitzar ecc/ecdsa.' ], 'froxloraliases' =&gt; [ 'title' =&gt; 'lies de domini per froxlor vhost', 'description' =&gt; 'llista separada per comes de dominis per afegir com lies de servidor al froxlor vhost' ], 'default_sslvhostconf' =&gt; [ 'title' =&gt; 'ssl per defecte vhost-settings', 'description' =&gt; 'el contingut d\'aquest camp s\'inclour directament en aquest contenidor ip/port vhost. podeu utilitzar les variables segents:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt; /code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (si escau)&lt;br/&gt; atenci: es comprovar si el codi cont errors. si cont errors, el servidor web podria tornar arrencar!' ], 'includedefault_sslvhostconf' =&gt; 'incloure configuraci de vhost ssl ssl-vhost', 'apply_specialsettings_default' =&gt; [ 'title' =&gt; 'valor per defecte per "aplicar configuracions especials tots els subdominis (*.exemple.com)\' en editar un domini' ], 'apply_phpconfigs_default' =&gt; [ 'title' =&gt; 'valor per defecte per "aplicar php-config tots els subdominis:\' en editar un domini' ], 'awstats' =&gt; [ 'logformat' =&gt; [ 'title' =&gt; 'configuraci de logformat', 'description' =&gt; 'si utilitzeu un format de registre personalitzat per al vostre servidor web, necessiteu canviar tamb l\'awstats logformat.&lt;br/&gt;per defecte 1. per ms informaci consulta la documentaci &lt;a target="_blank" href="https://awstats.sourceforge.io/docs/awstats_config.html#logformat"&gt;aqu&lt;/a&gt;.' ] ], 'hide_incompatible_settings' =&gt; 'amagar configuracions incompatibles', 'soaemail' =&gt; 'adrea de correu utilitzar en registres soa (per defecte l\'adrea del remitent de la configuraci del panell si buida)', 'imprint_url' =&gt; [ 'title' =&gt; 'url notes legals / impressi', 'description' =&gt; 'especifiqui una url al vostre lloc de notes legals / impressi. l\'enlla ser visible la pantalla d\'inici de sessi al peu de pgina un cop iniciada la sessi.' ], 'terms_url' =&gt; [ 'title' =&gt; 'url les condicions d\'s', 'description' =&gt; 'especifiqui una url al vostre lloc de condicions d\'s. l\'enlla ser visible la pantalla d\'inici de sessi al peu de pgina en iniciar sessi.' ], 'privacy_url' =&gt; [ 'title' =&gt; 'url la poltica de privadesa', 'description' =&gt; 'especifiqui una url al vostre lloc de poltica de privadesa / lloc d\'impressi. l\'enlla ser visible la pantalla d\'inici de sessi al peu de pgina en iniciar sessi.' ], 'logo_image_header' =&gt; [ 'title' =&gt; 'imatge de logotip (capalera)', 'description' =&gt; 'carregui la vostra prpia imatge de logotip perqu es mostri la capalera desprs de l\'inici de sessi (alada recomanada 30px)' ], 'logo_image_login' =&gt; [ 'title' =&gt; 'imatge del logotip (inici de sessi)', 'description' =&gt; 'carregui la vostra prpia imatge de logotip perqu es mostri durant l\'inici de sessi' ], 'logo_overridetheme' =&gt; [ 'title' =&gt; 'sobreescriu el logotip definit en el tema per "logo image" (capalera login, veure ms avall)', 'description' =&gt; 'aquesta opci s\'ha d\'establir com "cert" si vol utilitzar el logotip que ha carregat; com alternativa, pot continuar utilitzant les possibilitats basades en el tema "logo_custom.png" "logo_custom_login.png".' ], 'logo_overridecustom' =&gt; [ 'title' =&gt; 'sobreescriure el logotip personalitzat (logo_custom.png logo_custom_login.png) definit al tema per "imatge del logotip" (capalera inici de sessi, veure ms avall).', 'description' =&gt; 'estableixi aquest valor "cert" si vol ignorar els logotips personalitzats especfics del tema per la capalera l\'inici de sessi utilitzar "logo image".' ], 'createstdsubdom_default' =&gt; [ 'title' =&gt; 'valor preseleccionat per "crear subdomini estndard" en crear un client', 'description' =&gt; '' ], 'froxlorusergroup' =&gt; [ 'title' =&gt; 'grup de sistema personalitzat per tots els usuaris del client', 'description' =&gt; 'cal utilitzar libnss-extrausers (system-settings) perqu aix tingui efecte. un valor buit omet la creaci elimina el grup existent.' ], 'acmeshpath' =&gt; [ 'title' =&gt; 'ruta acme.sh', 'description' =&gt; 'establiu-lo s\'installa acme.sh, incloent l\'script acme.sh&lt;br/&gt;per defecte &lt;b&gt;/root/.acme.sh/acme.sh&lt;/b&gt;' ], 'update_channel' =&gt; [ 'title' =&gt; 'actualitzar canal froxlor', 'description' =&gt; 'seleccioni el canal d\'actualitzaci de froxlor. per defecte "estable"' ], 'uc_stable' =&gt; 'estable', 'uc_testing' =&gt; 'tests', 'traffictool' =&gt; [ 'toolselect' =&gt; 'analitzador de trnsit', 'webalizer' =&gt; 'webalizer', 'awstats' =&gt; 'awstats', 'goaccess' =&gt; 'goacccess' ], 'requires_reconfiguration' =&gt; 'el canvi d\'aquesta configuraci podria requerir una reconfiguraci dels serveis segents:&lt;br/&gt;&lt;strong&gt;%s&lt;/strong&gt;' ], 'spf' =&gt; [ 'use_spf' =&gt; 'activar spf per dominis?', 'spf_entry' =&gt; 'entrada spf per tots els dominis' ], 'ssl_certificates' =&gt; [ 'certificate_for' =&gt; 'certificat per a', 'valid_from' =&gt; 'vlid des de', 'valid_until' =&gt; 'vlid fins a', 'issuer' =&gt; 'emissor' ], 'success' =&gt; [ 'success' =&gt; 'informaci', 'clickheretocontinue' =&gt; 'feu clic aqu per continuar', 'settingssaved' =&gt; 'la configuraci s\'ha guardat correctament.', 'rebuildingconfigs' =&gt; 'tasques inserides amb xit per reconstruir fitxers de configuraci', 'domain_import_successfully' =&gt; 's\'han importat correctament els dominis %s.', 'backupscheduled' =&gt; 's\'ha programat la vostra tasca de cpia de seguretat. espereu que es processi.', 'backupaborted' =&gt; 'la seva cpia de seguretat programada ha estat cancellada', 'dns_record_added' =&gt; 'registre dns afegit correctament', 'dns_record_deleted' =&gt; 'registre dns eliminat correctament', 'testmailsent' =&gt; 'correu de prova enviat correctament', 'settingsimported' =&gt; 'configuraci importada correctament', 'sent_error_report' =&gt; 'informe d\'error enviat correctament. grcies per la vostra contribuci.' ], 'tasks' =&gt; [ 'outstanding_tasks' =&gt; 'tasques cron pendents', 'rebuild_vhost' =&gt; 'reconstrucci de la configuraci del servidor web', 'create_home' =&gt; 'afegeix nova %s client', 'rebuild_dns' =&gt; 'reconstrucci de la configuraci bind', 'create_ftp' =&gt; 'crear directori per un nou usuari ftp', 'delete_customer_files' =&gt; 'esborrar fitxers de client %s', 'noneoutstanding' =&gt; 'actualment hi ha tasques pendents per froxlor', 'create_quota' =&gt; 'establir quota al sistema de fitxers', 'delete_email_data' =&gt; 'esborrar dades de correu electrnic del client.', 'delete_ftp_data' =&gt; 'esborrar les dades del compte ftp del client.', 'rebuild_cron' =&gt; 'reconstruir el fitxer cron.d', 'create_customer_backup' =&gt; 'treball de cpia de seguretat per al client %s', 'delete_domain_pdns' =&gt; 'esborrar domini %s de la base de dades powerdns', 'delete_domain_ssl' =&gt; 'esborrar fitxers ssl de domini %s' ], 'terms' =&gt; 'condicions d\'s', 'traffic' =&gt; [ 'month' =&gt; 'mes', 'day' =&gt; 'dia', 'months' =&gt; [ '1' =&gt; 'gener', '2' =&gt; 'febrer', '3' =&gt; 'mar', '4' =&gt; 'abril', '5' =&gt; 'maig', '6' =&gt; 'juny', '7' =&gt; 'juliol', '8' =&gt; 'agost', '9' =&gt; 'setembre', '10' =&gt; 'octubre', '11' =&gt; 'novembre', '12' =&gt; 'desembre', 'jan' =&gt; 'gener', 'feb' =&gt; 'febrer', 'mar' =&gt; 'mar', 'apr' =&gt; 'abril', 'may' =&gt; 'maig', 'jun' =&gt; 'juny', 'jul' =&gt; 'juliol', 'aug' =&gt; 'agost', 'sep' =&gt; 'setembre', 'oct' =&gt; 'octubre', 'nov' =&gt; 'novembre', 'dec' =&gt; 'desembre', 'total' =&gt; 'total' ], 'mb' =&gt; 'trnsit', 'sumtotal' =&gt; 'trnsit total', 'sumhttp' =&gt; 'trnsit http', 'sumftp' =&gt; 'trnsit ftp', 'summail' =&gt; 'trnsit de correu', 'customer' =&gt; 'client', 'domain' =&gt; 'domini', 'trafficoverview' =&gt; 'resum del trnsit', 'bycustomers' =&gt; 'trnsit per clients', 'details' =&gt; 'detalls', 'http' =&gt; 'http', 'ftp' =&gt; 'ftp', 'mail' =&gt; 'correu', 'nocustomers' =&gt; 'necessita com mnim un client per veure els informes de trnsit.', 'top5customers' =&gt; 'top 5 clients', 'nodata' =&gt; 'no s\'han trobat dades per l\'interval donat.', 'ranges' =&gt; [ 'last24h' =&gt; 'ltimes 24 hores', 'last7d' =&gt; 'ltims 7 dies', 'last30d' =&gt; 'ltims 30 dies', 'cm' =&gt; 'mes actual', 'last3m' =&gt; 'ltims 3 mesos', 'last6m' =&gt; 'ltims 6 mesos', 'last12m' =&gt; 'ltims 12 meses', 'cy' =&gt; 'any en curs' ], 'byrange' =&gt; 'especificat per rang' ], 'translator' =&gt; '', 'update' =&gt; [ 'updateinprogress_onlyadmincanlogin' =&gt; 's\'ha installat una versi ms recent del froxlor per encara s\'ha configurat.&lt;br/&gt;noms l\'administrador pot iniciar sessi finalitzar l\'actualitzaci.', 'update' =&gt; 'actualitzaci de froxlor', 'proceed' =&gt; 'procedir', 'update_information' =&gt; [ 'part_a' =&gt; 'els fitxers froxlor han estat actualitzats la versi &lt;strong&gt;%s&lt;/strong&gt;. la versi installada &lt;strong&gt;%s&lt;/strong&gt;.', 'part_b' =&gt; '&lt;br/&gt;&lt;br/&gt;els clients es poden connectar fins que l\'actualitzaci hagi finalitzat.&lt;br/&gt;&lt;strong&gt;procedir?&lt;/strong&gt;' ], 'noupdatesavail' =&gt; 'ja installada la darrera %sversion de froxlor.', 'description' =&gt; 'executant actualitzacions de la base de dades per la installaci de froxlor', 'uc_newinfo' =&gt; 'hi ha una versi ms recent disponible: "%s" (la vostra versi actual s: %s)', 'notify_subject' =&gt; 'nova actualitzaci disponible' ], 'usersettings' =&gt; [ 'custom_notes' =&gt; [ 'title' =&gt; 'notes personalitzades', 'description' =&gt; 'sigues lliure de posar les notes que vulguis/necessitis aqu. es mostraran la vista general de l\'administrador/client per l\'usuari corresponent.', 'show' =&gt; 'mostrar les teves notes al tauler de control de l\'usuari' ], 'api_allowed' =&gt; [ 'title' =&gt; 'permet accedir la api', 'description' =&gt; 'quan est habilitat la configuraci, aquest usuari pot crear claus api accedir la api froxlor', 'notice' =&gt; 'l\'accs la api est perms per al vostre compte.' ] ], 'install' =&gt; [ 'slogan' =&gt; 'panell de gesti del servidor froxlor', 'preflight' =&gt; 'comprovaci del sistema', 'critical_error' =&gt; 'error crtic', 'suggestions' =&gt; 'no requerit per recomanat', 'phpinfosuccess' =&gt; 'el seu sistema funciona amb php %s', 'phpinfowarn' =&gt; 'el seu sistema est executant una versi inferior php %s', 'phpinfoupdate' =&gt; 'actualitzi la seva versi php actual de %s %s superior', 'start_installation' =&gt; 'inicieu la installaci', 'check_again' =&gt; 'recarregar per comprovar de nou', 'switchmode_advanced' =&gt; 'mostrar opcions avanades', 'switchmode_basic' =&gt; 'ocultar opcions avanades', 'dependency_check' =&gt; [ 'title' =&gt; 'benvingut froxlor', 'description' =&gt; 'comprovem les dependncies del sistema per assegurar-nos que totes les extensions mduls php necessaris estan habilitats perqu froxlor funcioni correctament.' ], 'database' =&gt; [ 'top' =&gt; 'base de dades', 'title' =&gt; 'crear base de dades usuari', 'description' =&gt; 'froxlor requereix una base de dades addicionalment un usuari privilegiat per poder crear usuaris bases de dades (opci grant). la base de dades l\'usuari privilegiat es crearan en aquest procs. l\'usuari privilegiat ha d\'existir.', 'user' =&gt; 'usuari privilegiat de la base de dades', 'dbname' =&gt; 'nom de la base de dades', 'force_create' =&gt; 'fer cpia de seguretat sobreescriure la base de dades si existeix?' ], 'admin' =&gt; [ 'top' =&gt; 'usuari administrador', 'title' =&gt; 'crearem l\'usuari administrador principal.', 'description' =&gt; 'aquest usuari tindr tots els privilegis per ajustar la configuraci afegir/actualitzar/eliminar recursos com clients, dominis, etc.' ], 'system' =&gt; [ 'top' =&gt; 'configuraci del sistema', 'title' =&gt; 'detalls sobre el vostre servidor', 'description' =&gt; 'establiu el vostre entorn aix com les dades opcions rellevants del servidor aqu perqu froxlor conegui el vostre sistema. aquests valors sn crucials per la configuraci el funcionament del sistema.', 'ipv4' =&gt; 'adrea ipv4 primria (si escau)', 'ipv6' =&gt; 'adrea ipv6 primria (si escau)', 'servername' =&gt; 'nom del servidor (fqdn, sense adrea ip)', 'phpbackend' =&gt; 'php backend', 'activate_newsfeed' =&gt; 'habilitar la font oficial de notcies&lt;br/&gt;&lt;small&gt;(font externa: https://inside.froxlor.org/news/)&lt;/small&gt;' ], 'install' =&gt; [ 'top' =&gt; 'finalitzar la configuraci', 'title' =&gt; 'un ltim pas...', 'description' =&gt; 'l\'ordre segent descarregar, installar configurar els serveis necessaris al vostre sistema d\'acord amb les dades que heu facilitat en aquest procs d\'installaci.', 'runcmd' =&gt; 'executeu la segent ordre com usuari root al vostre intrpret d\'ordres en aquest servidor:', 'manual_config' =&gt; 'configurar manualment els serveis, porta\'m l\'inici de sessi', 'waitforconfig' =&gt; 'esperant que es configurin els serveis...' ], 'errors' =&gt; [ 'wrong_ownership' =&gt; 'assegureu-vos que els fitxers froxlor sn propietat de %s:%s', 'missing_extensions' =&gt; 'les segents extensions de php sn necessries estan installades', 'suggestedextensions' =&gt; 'no s\'han trobat les segents extensions de php per es recomanen', 'databaseexists' =&gt; 'la base de dades ja existeix, si us plau establiu l\'opci override per reconstruir trieu un altre nom', 'unabletocreatedb' =&gt; 'no s\'ha pogut crear la base de dades de prova', 'unabletodropdb' =&gt; 'no s\'ha pogut suprimir la base de dades de prova', 'mysqlusernameexists' =&gt; 'l\'usuari especificat per l\'usuari sense privilegis ja existeix. si us plau, utilitzeu un altre nom d\'usuari elimineu-lo primer.', 'unabletocreateuser' =&gt; 'no s\'ha pogut crear l\'usuari de prova', 'unabletodropuser' =&gt; 'l\'usuari de prova s\'ha pogut eliminar.', 'unabletoflushprivs' =&gt; 'l\'usuari privilegiat pot eliminar privilegis.', 'nov4andnov6ip' =&gt; 'cal indicar una adrea ipv4 ipv6.', 'servernameneedstobevalid' =&gt; 'el nom de servidor indicat sembla que sigui un fqdn un nom de host.', 'websrvuserdoesnotexist' =&gt; 'sembla que l\'usuari del servidor web existeix al sistema.', 'websrvgrpdoesnotexist' =&gt; 'el webserver-group indicat sembla existir al sistema.', 'notyetconfigured' =&gt; 'els serveis encara s\'han configurat (correctament). si us plau, executeu l\'ordre que es mostra continuaci marqueu la casella per fer-ho ms tard.', 'mandatory_field_not_set' =&gt; 'el camp obligatori "%s" est configurat.', 'unexpected_database_error' =&gt; 's\'ha produt una excepci inesperada la base de dades. %s', 'sql_import_failed' =&gt; 'error en importar dades sql.', 'unprivileged_sql_connection_failed' =&gt; 'error en inicialitzar una connexi sql sense privilegis.', 'privileged_sql_connection_failed' =&gt; 'error en inicialitzar la connexi sql privilegiada.', 'mysqldump_backup_failed' =&gt; 'no es pot crear una cpia de seguretat de la base de dades, tenim un error de mysqldump.', 'sql_backup_file_missing' =&gt; 'no es pot crear una cpia de seguretat de la base de dades, el fitxer de cpia de seguretat existeix.', 'backup_binary_missing' =&gt; 'no es pot crear una cpia de seguretat de la base de dades, assegureu-vos que heu installat mysqldump.', 'creating_configfile_failed' =&gt; 'no es poden crear fitxers de configuraci, es pot escriure el fitxer.', 'database_already_exiting' =&gt; 'hem trobat una base de dades se\'ns ha perms sobreescriure-la!' ] ], 'welcome' =&gt; [ 'title' =&gt; 'benvingut froxlor!', 'config_note' =&gt; 'perqu froxlor pugui comunicar-se correctament amb el backend, de configurar-lo.', 'config_now' =&gt; 'configurar ara' ], ];</file><file name="lng/nl.lng.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @author sander klein &lt;roedie@roedie.nl&gt; * @author frits letteboer &lt;f.letteboer@radiotwenterand.nl&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'admin' =&gt; [ 'overview' =&gt; 'overzicht', 'ressourcedetails' =&gt; 'gebruikte resources', 'systemdetails' =&gt; 'systeem details', 'installedversion' =&gt; 'genstalleerde versie', 'latestversion' =&gt; 'laatste versie', 'lookfornewversion' =&gt; [ 'clickhere' =&gt; 'zoeken via webservice', 'error' =&gt; 'fout tijdens lezen', ], 'customer' =&gt; 'klant', 'customers' =&gt; 'klanten', 'customer_add' =&gt; 'maak klant', 'customer_edit' =&gt; 'bewerk klant', 'domains' =&gt; 'domeinen', 'domain_add' =&gt; 'maak domein', 'domain_edit' =&gt; 'bewerk domein', 'subdomainforemail' =&gt; 'subdomein als emaildomein', 'admin' =&gt; 'beheerder', 'admins' =&gt; 'beheerders', 'admin_add' =&gt; 'maak beheerder', 'admin_edit' =&gt; 'bewerk beheerder', 'customers_see_all' =&gt; 'kan alle klanten zien?', 'change_serversettings' =&gt; 'kan server instellingen aanpassen?', 'serversettings' =&gt; 'instellingen', 'rebuildconf' =&gt; 'configuratie bestanden opnieuw aanmaken', 'stdsubdomain' =&gt; 'standaard subdomein', 'stdsubdomain_add' =&gt; 'maak standard subdomein', 'deactivated' =&gt; 'gedeactiveerd', 'deactivated_user' =&gt; 'gebruiker deactiveren', 'sendpassword' =&gt; 'verstuur wachtwoord', 'ownvhostsettings' =&gt; 'eigen vhost-instellingen', 'configfiles' =&gt; [ 'serverconfiguration' =&gt; 'configuratie', 'overview' =&gt; 'overzicht', 'wizard' =&gt; 'wizard', 'distribution' =&gt; 'distributie', 'service' =&gt; 'dienst', 'etc' =&gt; 'overigen (systeem)', 'choosedistribution' =&gt; '-- kies een distributie --', 'chooseservice' =&gt; '-- kies een dienst --', 'choosedaemon' =&gt; '-- kies een daemon --', 'statistics' =&gt; 'statistieken', 'compactoverview' =&gt; 'compacte weergave', ], 'templates' =&gt; [ 'templates' =&gt; 'sjablonen', 'template_add' =&gt; 'maak sjabloon', 'template_edit' =&gt; 'bewerk sjabloon', 'action' =&gt; 'actie', 'email' =&gt; 'e-mail', 'subject' =&gt; 'onderwerp', 'mailbody' =&gt; 'mail inhoud', 'createcustomer' =&gt; 'welkomst bericht voor nieuwe klanten', 'pop_success' =&gt; 'welkomst bericht voor e-mail nieuw account', 'template_replace_vars' =&gt; 'variabelen die aangepast worden het sjabloon:', 'firstname' =&gt; 'vervangen door de voornaam van de klant.', 'name' =&gt; 'vervangen door de naam van de klant.', 'username' =&gt; 'vervangen door de gebruikersnaam van de klant.', 'password' =&gt; 'vervangen door het wachtwoord van de klant.', 'email' =&gt; 'vervangen door het adres van het pop3/imap account.', 'traffic' =&gt; 'wordt vervangen door aan klant toegewezen dataverkeer.', 'trafficused' =&gt; 'wordt vervangen door het verbruikte dataverkeer.', 'pop_success_alternative' =&gt; 'welkomstmail voor nieuwe emailaccounts, gestuurd naar een alternatief emailadres', 'email_password' =&gt; 'vervangen door het pop3/imap-wachtwoord.', 'index_html' =&gt; 'standaardpagina voor nieuwe mappen/domeinen', 'servername' =&gt; 'wordt vervangen door de naam van de server.', 'customer' =&gt; 'wordt vervangen door de inlognaam van de klant.', 'admin' =&gt; 'wordt vervangen door de inlognaam van de beheerder.', 'customer_email' =&gt; 'wordt vervangen door het e-mailadres van de klant.', 'admin_email' =&gt; 'wordt vervangen door het e-mailadres van de beheerder.', 'filetemplates' =&gt; 'bestandssjablonen', 'filecontent' =&gt; 'bestandsinhoud', 'new_database_by_customer' =&gt; 'klantnotificatie wanneer een database aangemaakt', 'new_ftpaccount_by_customer' =&gt; 'klantnotificatie wanneer een ftp-gebruiker aangemaakt', 'newdatabase' =&gt; 'notificatie mails voor nieuwe databases', 'newftpuser' =&gt; 'notificatie mails voor nieuwe ftp-gebruikers', 'cust_name' =&gt; 'naam klant', 'db_name' =&gt; 'naam database', 'db_pass' =&gt; 'wachtwoord database', 'db_desc' =&gt; 'beschrijving database', 'db_srv' =&gt; 'database server', 'pma_uri' =&gt; 'url naar phpmyadmin (indien opgegeven)', 'usr_name' =&gt; 'gebruikersnaam ftp', 'usr_pass' =&gt; 'wachtwoord ftp', 'usr_path' =&gt; 'map ftp (relatief aan docroot van klant)', 'forgotpwd' =&gt; 'notificatie mails voor opnieuw instellen wachtwoord', 'password_reset' =&gt; 'klantnotificatie voor opnieuw instellen wachtwoord', ], 'ipsandports' =&gt; [ 'ipsandports' =&gt; 'ip-adressen en poorten', 'add' =&gt; 'maak ip/poort', 'edit' =&gt; 'bewerk ip/poort', 'ipandport' =&gt; 'ip/poort', 'ip' =&gt; 'ip', 'port' =&gt; 'poort', 'create_listen_statement' =&gt; '\'listen\'-regel genereren', 'create_namevirtualhost_statement' =&gt; '\'namevirtualhost\'-regel genereren', 'create_vhostcontainer' =&gt; 'vhost-container genereren', 'create_vhostcontainer_servername_statement' =&gt; '\'servername\'-regel vhost-container genereren', 'enable_ssl' =&gt; 'is dit een ssl-poort?', 'ssl_cert_file' =&gt; 'pad naar ssl-certificaat', 'webserverdefaultconfig' =&gt; 'standaarconfiguratie webserver', 'webserverdomainconfig' =&gt; 'domeinconfiguratie webserver', 'webserverssldomainconfig' =&gt; 'ssl-configuratie webserver', 'ssl_key_file' =&gt; 'pad naar ssl keyfile', 'ssl_ca_file' =&gt; 'pad naar ssl ca certificaat', 'default_vhostconf_domain' =&gt; 'standaard vhost-instellingen voor iedere domeincontainer', 'docroot' =&gt; [ 'title' =&gt; 'aangepaste docroot (leeg = verwijzing naar froxlor)', 'description' =&gt; 'u kunt voor deze ip/poortcombinatie een aangepaste document-root opgeven.&lt;br /&gt;&lt;strong&gt;let op:&lt;/strong&gt; pas op wat u hier neerzet!', ], ], 'memorylimitdisabled' =&gt; 'gedeactiveerd', 'valuemandatory' =&gt; 'deze waarde verplicht', 'valuemandatorycompany' =&gt; 'de waarde "naam" en "voornaam" "bedrijf" moet ingevoerd worden', 'phpversion' =&gt; 'php-versie', 'phpmemorylimit' =&gt; 'php-geheugen-limiet', 'mysqlserverversion' =&gt; 'mysql server versie', 'mysqlclientversion' =&gt; 'mysql client versie', 'accountsettings' =&gt; 'account-instellingen', 'panelsettings' =&gt; 'paneel-instellingen', 'systemsettings' =&gt; 'systeem-instellingen', 'webserversettings' =&gt; 'webserver-instellingen', 'mailserversettings' =&gt; 'mailserver-instellingen', 'nameserversettings' =&gt; 'nameserver-instellingen', 'updatecounters' =&gt; 'gebruikte bronnen herberekenen', 'subcanemaildomain' =&gt; [ 'never' =&gt; 'nooit', 'choosableno' =&gt; 'kiesbaar, standaard nee', 'choosableyes' =&gt; 'kiesbaar, standaard ja', 'always' =&gt; 'altijd', ], 'webalizersettings' =&gt; 'instellingen voor webalizer', 'webalizer' =&gt; [ 'normal' =&gt; 'normaal', 'quiet' =&gt; 'stil', 'veryquiet' =&gt; 'geen uitvoer', ], 'domain_nocustomeraddingavailable' =&gt; 'het niet mogelijk een domein toe te voegen. u dient tenminste een klant aan te maken.', 'loggersettings' =&gt; 'instellingen voor logs', 'logger' =&gt; [ 'normal' =&gt; 'normaal', 'paranoid' =&gt; 'paranoide', ], 'emaildomain' =&gt; 'emaildomein', 'email_only' =&gt; 'alleen email?', 'wwwserveralias' =&gt; 'voeg een "www." serveralias toe', 'subject' =&gt; 'onderwerp', 'recipient' =&gt; 'ontvanger', 'message' =&gt; 'bericht schrijven', 'text' =&gt; 'bericht', 'sslsettings' =&gt; 'instellingen voor ssl', 'dkimsettings' =&gt; 'instellingen voor domainkeys', 'allips' =&gt; 'alle ip\'s', 'awstatssettings' =&gt; 'instellingen voor awstats', 'domain_dns_settings' =&gt; 'dns-instellingen voor domein', 'activated' =&gt; 'geactiveerd', 'statisticsettings' =&gt; 'instellingen voor statistieken', 'or' =&gt; 'of', 'sysload' =&gt; 'systeembelasting', 'noloadavailable' =&gt; 'niet beschikbaar', 'nouptimeavailable' =&gt; 'niet beschikbaar', 'nosubject' =&gt; '(geen onderwerp)', 'security_settings' =&gt; 'beveiliging', 'know_what_youre_doing' =&gt; 'verander dit alleen wanneer u zeker weet wat u doet!', 'show_version_login' =&gt; [ 'title' =&gt; 'toon versie van froxlor bij het inloggen', 'description' =&gt; 'toont de versie van froxlor de voettekst van de inlogpagina', ], 'show_version_footer' =&gt; [ 'title' =&gt; 'toon versie van froxlor de voettekst', 'description' =&gt; 'toont de versie van froxlor de voettekst op de rest van de pagina\'s', ], 'froxlor_graphic' =&gt; [ 'title' =&gt; 'kopgrafiek voor froxlor', 'description' =&gt; 'afbeelding die getoond wordt de kop', ], 'phpsettings' =&gt; [ 'title' =&gt; 'php configuratie', 'description' =&gt; 'korte omschrijven', 'actions' =&gt; 'actie\'s', 'activedomains' =&gt; 'wordt gebruikt door domein(en)', 'notused' =&gt; 'configuratie niet gebruik', 'editsettings' =&gt; 'instellingen voor php aanpassen', 'addsettings' =&gt; 'nieuwe instellingen voor php aanmaken', 'viewsettings' =&gt; 'instellingen voor php weergeven', 'phpinisettings' =&gt; 'instellingen php.ini', 'addnew' =&gt; 'nieuwe instellingen aanmaken', 'binary' =&gt; 'php uitvoerbaar bestand', 'file_extensions' =&gt; 'bestandsextensies', 'file_extensions_note' =&gt; '(zonder punt, gescheiden door spaties)', ], 'misc' =&gt; 'diversen', 'phpconfig' =&gt; [ 'template_replace_vars' =&gt; 'variabelen die worden vervangen de instellingen', 'pear_dir' =&gt; 'wordt vervangen door de globale pear-map.', 'open_basedir_c' =&gt; 'voegt een ; (puntkomma) toe om open_basedir in- uit te schakelen', 'open_basedir' =&gt; 'wordt vervangen door de open_basedir-instellingen voor het domein.', 'tmp_dir' =&gt; 'wordt vervangen door de tijdelijke map voor dit domein', 'open_basedir_global' =&gt; 'wordt vervangen door de globale waarde van het pad dat wordt toegevoegd aan de open_basedir.', 'customer_email' =&gt; 'wordt vervangen door het e-mailadres van de klant van het domein.', 'admin_email' =&gt; 'wordt vervangen door het e-mailadres van de beheerder van het domein.', 'domain' =&gt; 'wordt vervangen door het domein.', 'customer' =&gt; 'wordt vervangen door de loginnaam van de eigenaar van het domein.', 'admin' =&gt; 'wordt vervangen door de loginnaam van de beheerder van het domein.', ], 'expert_settings' =&gt; 'instellingen voor experts!', 'mod_fcgid_starter' =&gt; [ 'title' =&gt; 'aantal php-processen voor dit domein. (leeg betekent standaardinstellingen.)', ], 'phpserversettings' =&gt; 'php instellingen', 'mod_fcgid_maxrequests' =&gt; [ 'title' =&gt; 'maximaal aantal php verzoeken voor dit domein (leeg geldt als standaardwaarde)', ], 'spfsettings' =&gt; 'spf-instellingen domein', 'specialsettingsforsubdomains' =&gt; 'speciale instellingen toepassen op alle subdomeinen (*.example.com)', 'accountdata' =&gt; 'accountgegevens', 'contactdata' =&gt; 'contactgegevens', 'servicedata' =&gt; 'ondersteuningsgegevens', 'newerversionavailable' =&gt; 'er een nieuwe versie van froxlor beschikbaar', 'cron' =&gt; [ 'cronsettings' =&gt; 'instellingen cron-taken', 'add' =&gt; 'cron-taak toevoegen', ], 'cronjob_edit' =&gt; 'cron-taak aanpassen', 'warning' =&gt; 'waarschuwing - let op!', 'lastlogin_succ' =&gt; 'laatste login', 'ftpserver' =&gt; 'ftp server', 'ftpserversettings' =&gt; 'instellingen ftp-server', 'webserver_user' =&gt; 'gebruikersnaam webserver', 'webserver_group' =&gt; 'groepnaam webserver', 'perlenabled' =&gt; 'perl ingeschakeld', 'fcgid_settings' =&gt; 'fcgid', 'mod_fcgid_user' =&gt; 'lokale gebruiker voor fcgid (froxlor vhost)', 'mod_fcgid_group' =&gt; 'lokale groep voor fcgid (froxlor vhost)', 'perl_settings' =&gt; 'perl/cgi', 'notgiven' =&gt; '[niet opgegeven]', 'store_defaultindex' =&gt; 'standaard indexbestand opslaan map klant', 'phpfpm_settings' =&gt; 'php-fpm', ], 'changepassword' =&gt; [ 'old_password' =&gt; 'oud wachtwoord', 'new_password' =&gt; 'nieuw wachtwoord', 'new_password_confirm' =&gt; 'nieuw wachtwoord (bevestigen)', 'new_password_ifnotempty' =&gt; 'nieuw wachtwoord (leeg = niet veranderen)', 'also_change_ftp' =&gt; ' wijzig ook het wachtwoord van het hoofd ftp account', 'also_change_stats' =&gt; ' wijzig ook het wachtwoord van de statistieken', ], 'cron' =&gt; [ 'cronname' =&gt; 'naam cron-taak', 'lastrun' =&gt; 'laatst uitgevoerd', 'interval' =&gt; 'interval', 'isactive' =&gt; 'actief', 'description' =&gt; 'beschrijving', 'changewarning' =&gt; 'het aanpassen van de ze waarden kunnen van negatieve invloed zijn op het gedrag van froxlor en haar geautomatiseerde taken.&lt;br /&gt;pas deze waarden alleen aan wanneer u *zeer zeker* bent van wat u doet.', ], 'crondesc' =&gt; [ 'cron_unknown_desc' =&gt; 'geen beschrijving opgegeven', 'cron_tasks' =&gt; 'aanmaken configuratiebestanden', 'cron_legacy' =&gt; 'oude cron-taak', 'cron_traffic' =&gt; 'berekenen verkeersgegevens', ], 'cronjob' =&gt; [ 'cronjobsettings' =&gt; 'instellingen cron-taak', 'cronjobinterval' =&gt; 'interval uitvoeren', ], 'cronjobs' =&gt; [ 'notyetrun' =&gt; 'nog niet uitgevoerd', ], 'cronmgmt' =&gt; [ 'seconds' =&gt; 'seconden', 'minutes' =&gt; 'minuten', 'hours' =&gt; 'uren', 'days' =&gt; 'days', 'weeks' =&gt; 'weken', 'months' =&gt; 'maanden', ], 'customer' =&gt; [ 'name' =&gt; 'naam', 'firstname' =&gt; 'voornaam', 'company' =&gt; 'bedrijfsnaam', 'street' =&gt; 'straat', 'zipcode' =&gt; 'postcode', 'city' =&gt; 'plaats', 'phone' =&gt; 'telefoonnummer', 'fax' =&gt; 'faxnummer', 'email' =&gt; 'email', 'customernumber' =&gt; 'klant id', 'diskspace' =&gt; 'webruimte (mb)', 'traffic' =&gt; 'verkeer (gb)', 'emails' =&gt; 'e-mail-adressen', 'subdomains' =&gt; 'sub-domein(en)', 'domains' =&gt; 'domein(en)', 'title' =&gt; 'titel', 'country' =&gt; 'land', 'email_quota' =&gt; 'quotem voor e-mail', 'email_imap' =&gt; 'e-mail imap', 'email_pop3' =&gt; 'e-mail pop3', 'mail_quota' =&gt; 'mailquotum', 'sendinfomail' =&gt; 'stuur gegevens naar mij via e-mail', ], 'dns' =&gt; [ 'destinationip' =&gt; 'ip domein', 'standardip' =&gt; 'standaard server ip', 'a_record' =&gt; 'a-record (ipv6 optioneel)', 'cname_record' =&gt; 'cname-record', 'mxrecords' =&gt; 'mx-records', 'standardmx' =&gt; 'standaard server mx-record', 'mxconfig' =&gt; 'aangepaste mx-records', 'priority10' =&gt; 'prioriteit 10', 'priority20' =&gt; 'prioriteit 20', 'txtrecords' =&gt; 'txt-records', 'txtexample' =&gt; 'voorbeeld (spf-regel):&lt;br /&gt;v=spf1 ip4:xxx.xxx.xx.0/23 -all', ], 'domain' =&gt; [ 'openbasedirpath' =&gt; 'openbasedir-pad', 'docroot' =&gt; 'pad van bovenstaand veld', 'homedir' =&gt; 'home directory', ], 'domains' =&gt; [ 'description' =&gt; 'hier kunt u nieuwe (sub-) domeinen maken en de paden aanpassen.&lt;br /&gt;het systeem heeft een paar minuten nodig om de wijzigingen door te voeren na iedere varandering.', 'domainsettings' =&gt; 'domein instellingen', 'domainname' =&gt; 'domeinnaam', 'subdomain_add' =&gt; 'maak subdomein', 'subdomain_edit' =&gt; 'bewerk (sub)domein', 'wildcarddomain' =&gt; 'maak als wildcarddomein?', 'aliasdomain' =&gt; 'alias voor domein', 'noaliasdomain' =&gt; 'geen alias domein', 'hasaliasdomains' =&gt; 'heeft alias domein(en)', 'statstics' =&gt; 'gebruiksstatistieken', 'isassigneddomain' =&gt; 'is toegewezen domein', 'add_date' =&gt; 'toegevoegd aan froxlor', 'registration_date' =&gt; 'toegevoegd aan register', 'topleveldomain' =&gt; 'top-level-domein', 'associated_with_domain' =&gt; 'toegekend', 'aliasdomains' =&gt; 'alternatieve domeinnamen', 'redirectifpathisurl' =&gt; 'doorverwijzingscode (standaard: leegt)', 'redirectifpathisurlinfo' =&gt; 'u dient deze alleen op te geven indien u een url als pad hebt opgegeven', ], 'emails' =&gt; [ 'description' =&gt; 'hier kunt u e-mail adressen maken en wijzigen.&lt;br /&gt;een account net als een brievenbus voor uw huis. als iemand u mail stuurt wordt dit op uw account bezorgd.&lt;br /&gt;&lt;br /&gt;om uw emails te downloaden moet u het volgende instellen uw mailprogramma: (de &lt;i&gt;schuingedrukte&lt;/i&gt; gegevens moeten gewijzigd worden wat u ingegeven heeft!)&lt;br /&gt;servernaam: &lt;b&gt;&lt;i&gt;domeinnaam&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;gebruikersnaam: &lt;b&gt;&lt;i&gt;account naam / e-mailadres&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;wachtwoord: &lt;b&gt;&lt;i&gt;het door u ingegeven wachtwoord&lt;/i&gt;&lt;/b&gt;', 'emailaddress' =&gt; 'e-mailadres', 'emails_add' =&gt; 'maak nieuw e-mailadres', 'emails_edit' =&gt; 'bewerk e-mailadres', 'catchall' =&gt; 'catchall', 'iscatchall' =&gt; 'definieer als catchall-adres?', 'account_add' =&gt; 'maak nieuw account', 'account_delete' =&gt; 'verwijder account', 'from' =&gt; 'van', 'to' =&gt; 'aan', 'forwarder_add' =&gt; 'maak forwarder', 'alternative_emailaddress' =&gt; 'alternatief emailadres', 'quota' =&gt; 'quotum', 'noquota' =&gt; 'geen quotum', 'updatequota' =&gt; 'quotum aanpassen', 'quota_edit' =&gt; 'e-mailquotum aanpassen', 'noemaildomainaddedyet' =&gt; 'u hebt nog geen (email-)domein gekoppeld aan uw account.', ], 'error' =&gt; [ 'error' =&gt; 'fout', 'directorymustexist' =&gt; 'de map %s bestaat niet. maak hem eerst aan met uw ftp client.', 'filemustexist' =&gt; 'het bestand %s bestaat niet.', 'allresourcesused' =&gt; 'u heeft al uw resources al gebruikt.', 'domains_cantdeletemaindomain' =&gt; 'u kunt een domein dat gebruikt wordt als email-domein niet verwijderen.', 'domains_canteditdomain' =&gt; 'u kunt dit domein niet aanpassen. dit door de admin onbruikbaar gemaakt.', 'domains_cantdeletedomainwithemail' =&gt; 'u kunt een domein dat gebruikt wordt als email-domein niet verwijderen. verwijder eerst alle e-mail adressen.', 'firstdeleteallsubdomains' =&gt; 'u moet eerst alle subdomeinen verwijderen voor u een wildcard domein kunt maken.', 'youhavealreadyacatchallforthisdomain' =&gt; 'u heeft al een catchall voor dit domein aangemaakt.', 'ftp_cantdeletemainaccount' =&gt; 'u kunt uw hoofd ftp account niet verwijderen', 'login' =&gt; 'de door u ingegeven gebruikersnaam en wachtwoord zijn verkeerd. probeer opnieuw!', 'login_blocked' =&gt; 'dit account inactief vanwege teveel login fouten. &lt;br /&gt;probeer het nog eens %s seconden.', 'notallreqfieldsorerrors' =&gt; 'u heeft niet alle velden goed, helemaal niet ingevuld.', 'oldpasswordnotcorrect' =&gt; 'het oude wachtwoord niet correct.', 'youcantallocatemorethanyouhave' =&gt; 'u kunt niet meer resources gebruiken dan die u bezit.', 'mustbeurl' =&gt; 'u heeft geen goed compleet url ingegeven (bijv. http://eenserver.com/error404.htm)', 'invalidpath' =&gt; 'u heeft geen goed url ingegeven (misschien een probleem met dirlisting?)', 'stringisempty' =&gt; 'geen waarde invoerveld', 'stringiswrong' =&gt; 'verkeerde waarde invoerveld', 'newpasswordconfirmerror' =&gt; 'het nieuwe wachtwoord en de bevestiging zijn niet gelijk', 'loginnameexists' =&gt; 'loginnaam %s bestaat al', 'emailiswrong' =&gt; 'e-mailadres %s bevat illegale karakters niet compleet', 'loginnameiswrong' =&gt; 'loginnaam %s bevat illegale karakters', 'userpathcombinationdupe' =&gt; 'combinatie van gebruikersnaam en pad bestaat reeds', 'patherror' =&gt; 'generale fou! pad kan niet leeg zijn', 'errordocpathdupe' =&gt; 'optie voor pad %s bestaat reeds', 'adduserfirst' =&gt; 'maak klant eerst aan, aub', 'domainalreadyexists' =&gt; 'het domein %s al aan een klant toegewezen', 'nolanguageselect' =&gt; 'geen taal geselecteerd.', 'nosubjectcreate' =&gt; 'u moet een onderwerp ingeven voor dit e-mail sjabloon.', 'nomailbodycreate' =&gt; 'u moet een tekst ingeven voor dit e-mail sjabloon.', 'templatenotfound' =&gt; 'sjabloon niet gevonden.', 'alltemplatesdefined' =&gt; 'u kunt niet meer sjablonen definiren, alle talen worden al ondersteund.', 'wwwnotallowed' =&gt; 'www niet toegestaan voor subdomeinen.', 'subdomainiswrong' =&gt; 'het subdomein %s bevat illegale karakters.', 'domaincantbeempty' =&gt; 'de domeinnaam kan niet leeg zijn.', 'domainexistalready' =&gt; 'het domein %s bestaat reeds.', 'domainisaliasorothercustomer' =&gt; 'het geselecteerde alias domein verwijst naar zichzelf van een andere gebruiker.', 'emailexistalready' =&gt; 'het e-mail adres %s bestaat reeds.', 'maindomainnonexist' =&gt; 'het hoofd-domein %s bestaat niet.', 'destinationnonexist' =&gt; 'maak uw forwarder het veld \'destination\' alstublieft.', 'destinationalreadyexistasmail' =&gt; 'de forwarder naar %s bestaat reeds als actief e-mail adres.', 'destinationalreadyexist' =&gt; 'u heeft al een forwarder die verwijst naar %s .', 'destinationiswrong' =&gt; 'de forwarder naar %s bevat illegale karakter(s) niet compleet.', 'ipstillhasdomains' =&gt; 'de ip/port combinatie die u verwijderen wilt heeft nog domeinen toegewezen, wijs deze opnieuw aan andere ip/poort combinaties voordat u deze ip/poort combinatie verwijderd.', 'cantdeletedefaultip' =&gt; 'u kunt de standaard reseller ip/poort combinatie niet verwijderen, maak eerst een andere ip/port combinatie standaard voor reseller voor dat u deze ip/port combinatie verwijderd.', 'cantdeletesystemip' =&gt; 'u kunt het laatste ip/poort combinatie van het systeem niet verwijderen, maak eerste een andere ip/port combinatie aan voor het systeem wijzig het ip-adres van het systeem.', 'myipaddress' =&gt; '\'ip\'', 'myport' =&gt; '\'poort\'', 'myipdefault' =&gt; 'u moet een ip/poort combinatie selecteren die standaard moet worden.', 'myipnotdouble' =&gt; 'deze ip/poort combinatie bestaat reeds.', 'cantchangesystemip' =&gt; 'u kunt het laatste system ip niet wijzigen, maak eerst een nieuwe ip/poort combinatie aan wijzig het ip-adres van het systeem.', 'sessiontimeoutiswrong' =&gt; 'alleen numerieke "session timeout" zijn toegestaan.', 'maxloginattemptsiswrong' =&gt; 'alleen numerieke "maximaal aantal inlogpogingen" zijn toegestaan.', 'deactivatetimiswrong' =&gt; 'alleen numerieke "deactiveringstijd" zijn toegestaan.', 'accountprefixiswrong' =&gt; 'het "klant voorvoegsel" verkeerd.', 'mysqlprefixiswrong' =&gt; 'het "sql voorvoegsel" verkeerd.', 'ftpprefixiswrong' =&gt; 'het "ftp voorvoegsel" verkeerd.', 'ipiswrong' =&gt; 'het "ip-adres" verkeerd. alleen een geldig ip-adres toegestaan.', 'vmailuidiswrong' =&gt; 'het "mails-uid" verkeerd. alleen een numeriek uid toegestaan.', 'vmailgidiswrong' =&gt; 'het "mails-gid" verkeerd. alleen een numeriek gid toegestaan.', 'adminmailiswrong' =&gt; 'het "afzender-adres" verkeerd. alleen geldige e-mail adressen zijn toegestaan.', 'pagingiswrong' =&gt; 'het aantal "vermeldingen per pagina" verkeerd. alleen numerieke karakters zijn toegestaan.', 'phpmyadminiswrong' =&gt; 'de phpmyadmin-link niet een geldige link.', 'webmailiswrong' =&gt; 'de webmail-link niet een geldige link.', 'webftpiswrong' =&gt; 'de webftp-link niet een geldige link.', 'stringformaterror' =&gt; 'de waarde voor het veld "%s" niet het verwachte formaat.', 'loginnameissystemaccount' =&gt; 'u kunt geen accounts aanmaken die gelijk zijn aan systeem accounts (bijvoorbeeld beginnend met "%s"). kies een andere accountnaam aub.', 'youcantdeleteyourself' =&gt; 'u kunt uw eigen account, omwille van veiligheidsredenen, niet verwijderen.', 'youcanteditallfieldsofyourself' =&gt; 'opmerking: u kunt, om veiligheidsredenen, niet alle velden van uw account aanpassen.', 'documentrootexists' =&gt; 'de map "%s" voor deze klant bestaat reeds. verwijder deze map alvorens het account aan te maken.', 'formtokencompromised' =&gt; 'het verzoek lijkt te zijn gecompromitteerd. u bent veiligheidshalve uitgelogd.', 'logerror' =&gt; 'log-fout: %s', 'nomessagetosend' =&gt; 'u hebt geen bericht opgegeven.', 'norecipientsgiven' =&gt; 'u hebt geen ontvanger opgegeven', 'errorsendingmail' =&gt; 'het versturen van het bericht naar "%s" mislukt', 'cannotreaddir' =&gt; 'de map "%s" kan niet gelezen worden', 'invalidip' =&gt; '%s een ongeldig ip-adres', 'invalidmysqlhost' =&gt; 'ongeldig adres voor mysql-host: %s', 'cannotuseawstatsandwebalizeratonetime' =&gt; 'u kunt webalizer en awstats niet tegelijkertijd gebruiken. kies een van de twee.', 'cannotwritetologfile' =&gt; 'kan logbestand %s niet openen om naartoe te schrijven', 'vmailquotawrong' =&gt; 'het quotum dient een positief getal te zijn.', 'allocatetoomuchquota' =&gt; 'u probeerde %s mb quotum toe te kennen, maar u heeft niet voldoende over.', 'missingfields' =&gt; 'niet alle vereiste velden zijn ingevuld.', 'accountnotexisting' =&gt; 'het opgegeven e-mailaccount bestaat niet.', 'nopermissionsorinvalidid' =&gt; 'u hebt geen toestemming om deze instellingen te wijzigen, u hebt een ongeldig id opgegeven.', 'phpsettingidwrong' =&gt; 'een configuratie voor php met dit id bestaat niet', 'descriptioninvalid' =&gt; 'de omschrijving te kort, te lang bevat ongeldige karakters.', 'info' =&gt; 'informatie', 'filecontentnotset' =&gt; 'het bestand mag niet leeg zijn!', 'index_file_extension' =&gt; 'het achtervoegsel dient tussen de 1 en 6 tekens lang te zijn. het mag alleen tekens zal a-z, a-z en 0-9 bevatten.', 'customerdoesntexist' =&gt; 'de gekozen klant bestaat niet.', 'admindoesntexist' =&gt; 'de gekozen beheerder bestaat niet.', 'ipportdoesntexist' =&gt; 'de kozen combinatie poort/ip-adres bestaat niet.', 'admin_domain_emailsystemhostname' =&gt; 'de naam van de server kan niet gebruikt worden als domein voor e-mail.', 'usernamealreadyexists' =&gt; 'de gebruikersnaam %s reeds gebruik.', 'errorwhensaving' =&gt; 'fout tijdens opslaan veld %s', 'hiddenfieldvaluechanged' =&gt; 'de waarde van het verborgen veld "%s" gewijzigd tijdens het aanpassen van de instellingen.&lt;br /&gt;&lt;br /&gt;dit normaliter geen groot probleem maar heeft wel verhinderd dat de instellingen niet zijn opgeslagen.', 'notrequiredpasswordlength' =&gt; 'het opgegeven wachtwoord te kort. geef tenminste %s tekens op.', 'overviewsettingoptionisnotavalidfield' =&gt; 'woops, field displayed option settings-overview excepted type. blame developers this. happen!', 'pathmaynotcontaincolon' =&gt; 'het opgegeven pad mag geen dubbele punt (":") bevatten. geef een correct pad op.', 'exception' =&gt; '%s', 'notrequiredpasswordcomplexity' =&gt; 'er niet voldaan aan de complexiteit voor het wachtwoord (regex: %s)', 'stringerrordocumentnotvalidforlighty' =&gt; 'een tekenreeks als errordocument werkt niet lighttpd. geef een pad naar een bestand', 'urlerrordocumentnotvalidforlighty' =&gt; 'een tekenreeks als errordocument werkt niet lighttpd. geef een pad naar een bestand', 'intvaluetoolow' =&gt; 'het opgegeven nummer te laag (veld %s)', 'intvaluetoohigh' =&gt; 'het opgegeven nummer te hoog (veld %s)', 'phpfpmstillenabled' =&gt; 'php-fpm op dit moment actief. schakel dit eerst uit voordat u fcgid inschakelt', 'fcgidstillenabled' =&gt; 'fcgid op dit moment actief. schakel dit eerst uit voordat u php-fpm inschakelt', ], 'extras' =&gt; [ 'description' =&gt; 'hier kunt u wat extra instellingen doen zoals map beveiliging.&lt;br /&gt;het systeem heeft enkele minuten nodig om elke wijziging door te voeren.', 'directoryprotection_add' =&gt; 'map beveiliging toevoegen', 'view_directory' =&gt; 'map inhoud laten zien', 'pathoptions_add' =&gt; 'pad opties toevoegen', 'directory_browsing' =&gt; 'map inhoud browsen', 'pathoptions_edit' =&gt; 'pad opties bewerken', 'errordocument404path' =&gt; 'url naar foutdocument 404', 'errordocument403path' =&gt; 'url naar foutdocument 403', 'errordocument500path' =&gt; 'url naar foutdocument 500', 'errordocument401path' =&gt; 'url naar foutducument 401', 'execute_perl' =&gt; 'perl/cgi uitvoeren', 'htpasswdauthname' =&gt; 'reden voor authenticatie (authname)', 'directoryprotection_edit' =&gt; 'mapbeveiliging aanpassen', ], 'ftp' =&gt; [ 'description' =&gt; 'hier kunt u nieuwe ftp accounts maken bestaande accounts wijzigen.&lt;br /&gt;de wijzigingen worden direct doorgevoerd en het account kan direct gebruikt worden.', 'account_add' =&gt; 'maak nieuw account', 'account_edit' =&gt; 'ftp account aanpassen', 'editpassdescription' =&gt; 'nieuw wachtwoord leeg voor het oude wachtwoord.', ], 'index' =&gt; [ 'customerdetails' =&gt; 'klant details', 'accountdetails' =&gt; 'account details', ], 'logger' =&gt; [ 'date' =&gt; 'datum', 'type' =&gt; 'type', 'action' =&gt; 'actie', 'user' =&gt; 'gebruiker', 'truncate' =&gt; 'log legen', ], 'login' =&gt; [ 'username' =&gt; 'gebruikersnaam', 'password' =&gt; 'wachtwoord', 'language' =&gt; 'taal', 'login' =&gt; 'inloggen', 'logout' =&gt; 'uitloggen', 'profile_lng' =&gt; 'profiel taal', 'forgotpwd' =&gt; 'wachtwoord vergeten?', 'presend' =&gt; 'wachtwoord opnieuw instellen', 'email' =&gt; 'e-mailadres', 'remind' =&gt; 'mijn wachtwoord opnieuw instellen', 'usernotfound' =&gt; 'gebruiker niet gevonden!', 'backtologin' =&gt; 'terug naar inlogpagina', ], 'mails' =&gt; [ 'pop_success' =&gt; [ 'mailbody' =&gt; 'hallo,\\n\\nuw mail account {email}\\nis succesvol aangemaakt.\\n\\ndit een automatisch verstuurde\\ne-mail, beantwoord deze niet aub!\\n\\nmet vriendelijke groet, uw beheerder', 'subject' =&gt; 'mail account succesvol aangemaakt', ], 'createcustomer' =&gt; [ 'mailbody' =&gt; 'hallo {firstname} {name},\\n\\nhierbij uw account informatie:\\n\\ngebruikersnaam: {username}\\nwachtwoord: {password}\\n\\nmet vriendelijke groet,\\nuw beheerder', 'subject' =&gt; 'account informatie', ], 'pop_success_alternative' =&gt; [ 'mailbody' =&gt; 'hallo,\\n\\nuw mailaccount {email}\\nis met succes opgezet.\\nuw wachtwoord {password}.\\n\\ndit een automatisch gegenereerde\\ne-mail, u kunt hierop niet antwoorden!\\n\\nmet vriendelijk groet, uw beheerder', 'subject' =&gt; 'mailaccount actief gemaakt', ], 'password_reset' =&gt; [ 'subject' =&gt; 'wachtwoord opnieuw instellen', 'mailbody' =&gt; 'hallo {username},\\n\\nuw wachtwoord voor froxlor opnieuw ingesteld!\\nhet nieuwe wachtwoord is: {link}\\n\\nmet vriendelijke groet,\\nuw beheerder', ], 'new_database_by_customer' =&gt; [ 'subject' =&gt; '[froxlor] nieuwe database aangemaakt', 'mailbody' =&gt; 'geachte {cust_name}, u hebt zojuist een nieuwe database aangemaakt. hier zijn nogmaals de ingevoerde gegevens: naam database: {db_name} wachtwoord: {db_pass} beschrijving: {db_desc} hostnaam database: {db_srv} phpmyadmin: {pma_uri} met vriendelijke groet, uw beheerder', ], 'new_ftpaccount_by_customer' =&gt; [ 'subject' =&gt; 'nieuwe ftp-gebruiker aangemaakt', 'mailbody' =&gt; 'geachte {cust_name}, u hebt zojuist een nieuwe ftp-gebruiker aangemaakt. hier de opgegeven informatie: gebruikersnaam: {usr_name} wachtwoord: {usr_pass} pad: {usr_path} met vriendelijke groet, uw beheerder', ], ], 'menu' =&gt; [ 'message' =&gt; 'berichten', ], 'menue' =&gt; [ 'main' =&gt; [ 'main' =&gt; 'main', 'changepassword' =&gt; 'wijzig wachtwoord', 'changelanguage' =&gt; 'wijzig taal', 'username' =&gt; 'ingelogd als: ', ], 'email' =&gt; [ 'emails' =&gt; 'adressen', ], 'domains' =&gt; [ 'domains' =&gt; 'domeinen', 'settings' =&gt; 'instellingen', ], 'extras' =&gt; [ 'directoryprotection' =&gt; 'map beveiliging', 'pathoptions' =&gt; 'pad opties', ], 'traffic' =&gt; [ 'traffic' =&gt; 'dataverkeer', 'current' =&gt; 'deze maand', ], 'phpsettings' =&gt; [ 'maintitle' =&gt; 'php configuratie\'s', ], 'logger' =&gt; [ 'logger' =&gt; 'systeemlog', ], ], 'message' =&gt; [ 'norecipients' =&gt; 'er geen email verstuurd omdat er geen ontvangers de database zijn', 'success' =&gt; 'bericht verzonden naar ontvangers %s', ], 'mysql' =&gt; [ 'databasename' =&gt; 'gebruiker/database naam', 'databasedescription' =&gt; 'database omschrijving', 'database_create' =&gt; 'maak database', 'description' =&gt; 'hier kunt u mysql-databases maken en wijzigen.&lt;br /&gt;de wijzigingen worden direct gemaakt en de database kan direkt gebruikt worden.&lt;br /&gt;in het menu dat links staat vind u de tool phpmyadmin welke u kunt gebruiken om uw database makkelijk te beheren.&lt;br /&gt;&lt;br /&gt;om gebruikt te maken van uw database uw eigen php programmas kunt u de volgende instellingen gebruiken: (de gegeven &lt;i&gt;italics&lt;/i&gt; moeten aangepast worden wat u ingevoerd heeft!)&lt;br /&gt;hostnaam: &lt;b&gt;&lt;sql_host&gt;&lt;/b&gt;&lt;br /&gt;gebruikersnaam: &lt;b&gt;&lt;i&gt;databasenaam&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;wachtwoord: &lt;b&gt;&lt;i&gt;het wachtwoord dat u gekozen heeft&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;database: &lt;b&gt;&lt;i&gt;databasenaam&lt;/i&gt;&lt;/b&gt;', ], 'panel' =&gt; [ 'edit' =&gt; 'bewerken', 'delete' =&gt; 'verwijderen', 'create' =&gt; 'nieuw', 'save' =&gt; 'opslaan', 'yes' =&gt; 'ja', 'no' =&gt; 'nee', 'emptyfornochanges' =&gt; 'leeg laten voor huidige instelling', 'emptyfordefault' =&gt; 'leeg laten voor de standaard instellingen', 'path' =&gt; 'pad', 'toggle' =&gt; 'in- uitschalen', 'next' =&gt; 'volgende', 'dirsmissing' =&gt; 'de opgegeven map bestaat niet.', 'urloverridespath' =&gt; 'url (vervangt path)', 'pathorurl' =&gt; 'pad url', 'ascending' =&gt; 'oplopend', 'descending' =&gt; 'aflopend', 'search' =&gt; 'zoeken', 'used' =&gt; 'gebruikt', 'translator' =&gt; 'vertaler', 'reset' =&gt; 'wijzigingen verwerpen', 'pathdescription' =&gt; 'indien de map niet bestaat wordt deze automatisch aangemaakt.&lt;br /&gt;&lt;br /&gt;indien u wilt doorverwijzen naar een ander domein dient deze te beginnen met http:// https://', 'back' =&gt; 'back', 'reseller' =&gt; 'wederverkoper', 'admin' =&gt; 'beheerder', 'customer' =&gt; 'klant(en)', 'send' =&gt; 'verzenden', 'nosslipsavailable' =&gt; 'er zijn op dit moment geen ssl ip/poorten beschikbaar', 'backtooverview' =&gt; 'terug naar overzicht', 'dateformat' =&gt; 'yyyy-mm-dd', 'dateformat_function' =&gt; 'y-m-d', 'timeformat_function' =&gt; 'h:i:s', 'default' =&gt; 'standaard', 'never' =&gt; 'nooit', 'active' =&gt; 'actief', 'please_choose' =&gt; 'maak een keuze', 'allow_modifications' =&gt; 'aanpassingen toestaan', 'megabyte' =&gt; 'megabyte', 'not_supported' =&gt; 'wordt niet ondersteund in: ', 'view' =&gt; 'weergeven', 'toomanydirs' =&gt; 'teveel submappen. er wordt teruggevallen op handmatige invoer.', 'abort' =&gt; 'afbreken', 'not_activated' =&gt; 'niet actief', 'off' =&gt; 'uit', 'options' =&gt; 'opties', 'neverloggedin' =&gt; 'nog niet ingelogd', 'descriptionerrordocument' =&gt; 'kan een url, pad naar een bestand een tekenreeks zijn die omsloten door " "&lt;br /&gt;laat leeg voor de standaardwaarde.', 'unlock' =&gt; 'ontgrendelen', ], 'pwdreminder' =&gt; [ 'success' =&gt; 'wachtwoord opnieuw ingesteld.&lt;br /&gt;u ontvangt spoedig een e-mail met uw nieuwe wachtwoord.', 'notallowed' =&gt; 'het opnieuw instellen van wachtwoorden uitgeschakeld', ], 'question' =&gt; [ 'question' =&gt; 'beveiligingsvraag', 'admin_customer_reallydelete' =&gt; 'weet u zeker dat u de klant %s wilt verwijderen? dit kan niet ongedaan worden gemaakt!', 'admin_domain_reallydelete' =&gt; 'weet u zeker dat u het domein %s wilt verwijderen?', 'admin_domain_reallydisablesecuritysetting' =&gt; 'weet u echt heel zeker dat deze beveiligingsinstellingen wilt deactiveren (openbasedir)?', 'admin_admin_reallydelete' =&gt; 'weet u zeker dat u de admin %s verwijderen wilt? iedere klant en domein zal worden toegewezen aan de hoofd administrator.', 'admin_template_reallydelete' =&gt; 'weet u zeker dat u het sjabloon \'%s\' verwijderen wilt?', 'domains_reallydelete' =&gt; 'weet u zeker dat u het domein %s verwijderen wilt?', 'email_reallydelete' =&gt; 'weet u zeker dat u het e-mail adres %s verwijderen wilt?', 'email_reallydelete_account' =&gt; 'weet u zeker dat het e-mail account van %s verwijderen wilt?', 'email_reallydelete_forwarder' =&gt; 'weet u zeker dat u de forwarder %s verwijderen wilt?', 'extras_reallydelete' =&gt; 'weet u zeker dat u de map beveiliging voor de map %s verwijderen wilt?', 'extras_reallydelete_pathoptions' =&gt; 'weet u zeker dat u de pad-opties voor %s verwijderen wilt?', 'ftp_reallydelete' =&gt; 'weet u zeker dat u het ftp account %s verwijderen wilt?', 'mysql_reallydelete' =&gt; 'weet u zeker dat u de database %s verwijderen wilt? dit kan niet ongedaan gemaakt worden!', 'admin_configs_reallyrebuild' =&gt; 'weet u zeker dat u de configuratie bestanden voor apache en bind opnieuw wilt opbouwen?', 'admin_ip_reallydelete' =&gt; 'weet u zeker dat u het ip adres %s verwijderen wilt?', 'admin_domain_reallydocrootoutofcustomerroot' =&gt; 'weet u zeker dat u de document root voor dit domein niet de klant-root van de klant wil hebben?', 'admin_counters_reallyupdate' =&gt; 'weet u zeker dat u gebruikte bronnen wilt herberekenen?', 'admin_cleartextmailpws_reallywipe' =&gt; 'weet u zeker dat u alle onversleutelde wachtwoorden wilt verwijderen? deze opdracht niet terug te draaien!', 'logger_reallytruncate' =&gt; 'weet u zeker dat u de tabel "%s" wilt legen?', 'admin_quotas_reallywipe' =&gt; 'weet u zeker dat u alle quota wilt verwijderen? dit niet terug te draaien!', 'admin_quotas_reallyenforce' =&gt; 'weet u zeker dat u quota wilt afdwingen? dit niet terug te draaien!', 'phpsetting_reallydelete' =&gt; 'weet u zeker dat u deze instellingen wilt verwijderen? alle domeinen die deze configuratie gebruiken zullen terugvallen op de standaardinstellingen.', 'customer_reallyunlock' =&gt; 'weet u zeker dat u klant %s? wilt ontgrendelen', ], 'serversettings' =&gt; [ 'session_timeout' =&gt; [ 'title' =&gt; 'sessie timeout', 'description' =&gt; 'hoe lang moet een gebruiker inactief zijn voor dat de sessie ongeldig wordt (seconden)?', ], 'accountprefix' =&gt; [ 'title' =&gt; 'klant voorvoegsel', 'description' =&gt; 'welk voorvoegsel moet een klant account hebben?', ], 'mysqlprefix' =&gt; [ 'title' =&gt; 'sql voorvoegsel', 'description' =&gt; 'welk voorvoegsel moet een mysql account hebben?', ], 'ftpprefix' =&gt; [ 'title' =&gt; 'ftp voorvoegsel', 'description' =&gt; 'welk voorvoegsel dienen nieuwe ftp-accounts te krijgen?&lt;br/&gt;&lt;b&gt;indien u dit wijzigt, dient ook de query voor quota het configuratiebestand van de ftp-server aan te passen!&lt;/b&gt; ', ], 'documentroot_prefix' =&gt; [ 'title' =&gt; 'document map', 'description' =&gt; 'waar zullen alle gegeven opgeslagen worden?', ], 'logfiles_directory' =&gt; [ 'title' =&gt; 'logfiles map', 'description' =&gt; 'waar zullen alle log-file opgeslagen worden?', ], 'ipaddress' =&gt; [ 'title' =&gt; 'ip-adres', 'description' =&gt; 'wat het ip-adres van deze server?', ], 'hostname' =&gt; [ 'title' =&gt; 'hostnaam', 'description' =&gt; 'wat de hostnaam van deze server?', ], 'apachereload_command' =&gt; [ 'title' =&gt; 'apache reload commando', 'description' =&gt; 'wat het commando op apache te herladen?', ], 'bindconf_directory' =&gt; [ 'title' =&gt; 'bind configuratie map', 'description' =&gt; 'waar staan de bind configuratie bestanden?', ], 'bindreload_command' =&gt; [ 'title' =&gt; 'bind reload commando', 'description' =&gt; 'wat het command om bind te herladen?', ], 'vmail_uid' =&gt; [ 'title' =&gt; 'mails-uid', 'description' =&gt; 'welk userid moeten de e-mails hebben?', ], 'vmail_gid' =&gt; [ 'title' =&gt; 'mails-gid', 'description' =&gt; 'welke groupid moeten e-mails hebben?', ], 'vmail_homedir' =&gt; [ 'title' =&gt; 'mails-homedir', 'description' =&gt; 'waar moeten alle e-mail opgeslagen worden?', ], 'adminmail' =&gt; [ 'title' =&gt; 'afzender', 'description' =&gt; 'wat de afzender voor e-mail verstuurd vanuit het panel?', ], 'phpmyadmin_url' =&gt; [ 'title' =&gt; 'phpmyadmin url', 'description' =&gt; 'wat de url die verwijst naar phpmyadmin? (moet beginnen met http://)', ], 'webmail_url' =&gt; [ 'title' =&gt; 'webmail url', 'description' =&gt; 'wat de url die verwijst naar webmail? (moet beginnen met http://)', ], 'webftp_url' =&gt; [ 'title' =&gt; 'webftp url', 'description' =&gt; 'wat de url die verwijst naar webftp? (moet beginnen met http://)', ], 'language' =&gt; [ 'description' =&gt; 'wat uw standaard server taal?', ], 'maxloginattempts' =&gt; [ 'title' =&gt; 'maximaal aantal inlog pogingen', 'description' =&gt; 'maximaal aantal inlog pogingen voor het account gedeactiveerd wordt.', ], 'deactivatetime' =&gt; [ 'title' =&gt; 'deactiveringstijd', 'description' =&gt; 'tijd (in seconden) dat een account gedeactiveerd wordt na te veel inlogpogingen.', ], 'pathedit' =&gt; [ 'title' =&gt; 'manier van pad ingeven', 'description' =&gt; 'moet het pad geselecteerd worden met een \'dropdown\' menu met een invoerveld?', ], 'paging' =&gt; [ 'title' =&gt; 'vermeldingen per pagina', 'description' =&gt; 'hoeveel vermeldingen er getoond moeten worden per pagina? (0 = alles laten zien)', ], 'defaultip' =&gt; [ 'title' =&gt; 'standaard ip/poort', 'description' =&gt; 'wat de standaard ip/poort combinatie?', ], 'phpappendopenbasedir' =&gt; [ 'title' =&gt; 'pad dat toegevoegd wordt aan openbasedir', 'description' =&gt; 'deze paden (gescheiden door dubbele punten) zullen worden toegevoegd aan het openbasedir-statement iedere vhost-container.', ], 'natsorting' =&gt; [ 'title' =&gt; 'gebruik een natuurlijke manier van sorteren', 'description' =&gt; 'lijsten worden gesorteerd zoals web1 -&gt; web2 -&gt; web11 plaats van web1 -&gt; web11 -&gt; web2.', ], 'deactivateddocroot' =&gt; [ 'title' =&gt; 'pad naar webinhoud voor gedeactiveerde gebruikers', 'description' =&gt; 'wanneer een gebruiker geactiveerd is, wordt dit pad gebruikt voor zijn/haar webinhoud.', ], 'mailpwcleartext' =&gt; [ 'title' =&gt; 'sla het wachtwoord ook onversleuteld op de database', 'description' =&gt; 'indien ingesteld op ja worden wachtwoorden klare tekst opgeslagen de database (zichtbaar voor iedereen die toegang heeft tot de tabel mail_users). activeer dit alleen wanneer u gebruik gaat maken van sasl!', 'removelink' =&gt; 'klik hier om alle onversleutelde wachtwoorden uit de database te verwijderen', ], 'ftpdomain' =&gt; [ 'title' =&gt; 'ftp accounts @domein', 'description' =&gt; 'kunnen klanten ftp-accounts de vorm gebruiker@domein aanmaken?', ], 'mod_fcgid' =&gt; [ 'title' =&gt; 'php insluiten via mod_fcgid/suexec', 'description' =&gt; 'gebruik mod_fcgid/suexec/libnss_mysql om php uit te voeren onder het gebruikersaccount.&lt;br/&gt;&lt;b&gt;dit vereist een aangepaste configuratie van de webserver. alle volgende optie\'s zijn alleen geldig wanneer deze module actief is.&lt;/b&gt;', 'configdir' =&gt; [ 'title' =&gt; 'configuratiemap', 'description' =&gt; 'waar dienen alle configuratiebestanden voor fcgid te worden opgeslagen? indien u geen aangepaste versie van suexec gebruikt, zoals gebruikelijk is, dient dit pad onder /var/www/ te liggen', ], 'tmpdir' =&gt; [ 'title' =&gt; 'map voor tijdelijke bestanden', 'description' =&gt; 'waar dienen de tijdelijke mappen te worden opgeslagen?', ], 'starter' =&gt; [ 'title' =&gt; 'processen per domein', 'description' =&gt; 'hoeveel processen moeten gestart/toegestaan worden per domein? de waarde 0 wordt aangeraden, aangezien php zelf het aantal processen goed kan inschatten.', ], 'wrapper' =&gt; [ 'title' =&gt; 'wrapper vhosts', 'description' =&gt; 'hoe moet de wrapper ingesloten worden vhosts?', ], 'peardir' =&gt; [ 'title' =&gt; 'globale pear-mappen', 'description' =&gt; 'welke pear-mappen dienen te worden ingesloten elke php.ini? bij meerdere mappen dienen deze te worden gescheiden door dubbele punten.', ], 'maxrequests' =&gt; [ 'title' =&gt; 'maximaal aantal verzoeken per domein', 'description' =&gt; 'toegestane aantal verzoeken per domein', ], 'defaultini' =&gt; 'standaard php-configuratie voor nieuwe domeinen', 'defaultini_ownvhost' =&gt; 'standaard configuratie voor froxlor-vhost', ], 'sendalternativemail' =&gt; [ 'title' =&gt; 'gebruik alternatief emailadres', 'description' =&gt; 'stuur het wachtwoord naar een ander adres dan het adres dat opgegeven werd tijdens het aanmaken van het emailadres.', ], 'apacheconf_vhost' =&gt; [ 'title' =&gt; 'bestands-/mapnaam voor vhost-configuratie webserver', 'description' =&gt; 'waar dient het vhost-configuratiebestand opgeslagen te worden? u kunt hier zowel een bestand (alle configuratie\'s 1 bestand) een map (apart bestand voor iedere configuratie) opgeven.', ], 'apacheconf_diroptions' =&gt; [ 'title' =&gt; 'bestands-/mapnaam voor diroptions-configuratie webserver', 'description' =&gt; 'waar dient het diroptions-configuratiebestand opgeslagen te worden? u kunt hier zowel een bestand (alle configuratie\'s 1 bestand) een map (apart bestand voor iedere configuratie) opgeven.', ], 'apacheconf_htpasswddir' =&gt; [ 'title' =&gt; 'mapnaam htpasswd-bestanden webserver', 'description' =&gt; 'waar dienen de htpasswd-bestanden, voor beveiligde toegang, opgeslagen te worden?', ], 'mysql_access_host' =&gt; [ 'title' =&gt; 'toegangshosts voor mysql', 'description' =&gt; 'een door komma\'s gescheiden lijst met hosts waarvandaan gebruikers verbinding mogen maken met de mysql-server.', ], 'webalizer_quiet' =&gt; [ 'title' =&gt; 'uitvoer webalizer', 'description' =&gt; 'informatieniveau van webalizer', ], 'logger' =&gt; [ 'enable' =&gt; 'logs in-/uitgeschakeld', 'severity' =&gt; 'logniveau', 'types' =&gt; [ 'title' =&gt; 'log-type(s)', 'description' =&gt; 'om meerdere types te selecteren, houd u ctrl ingedrukt terwijl u selecteert.&lt;br /&gt;beschikbare types zijn: syslog, bestand, mysql', ], 'logfile' =&gt; 'pad naar logfile, inclusief bestandsnaam', 'logcron' =&gt; 'cronjobs loggen', 'logcronoption' =&gt; [ 'never' =&gt; 'nooit', 'once' =&gt; 'eenmalig', 'always' =&gt; 'altijd', ], ], 'ssl' =&gt; [ 'openssl_cnf' =&gt; 'standaardinstellingen certificaat', ], 'default_vhostconf' =&gt; [ 'title' =&gt; 'standaard vhost-instellingen', 'description' =&gt; 'de inhoud van dit veld wordt rechtstreeks de vhost-container geplaatst. n.b.: deze code wordt niet op fouten gecontroleerd. geval van fouten kan het zijn dat de webserver niet meer start!', ], 'decimal_places' =&gt; 'aantal getallen achter de komma uitvoer dataverkeer', 'webalizer_enabled' =&gt; 'webalizer activeren', 'awstats_enabled' =&gt; 'awstats activeren', 'selfdns' =&gt; [ 'title' =&gt; 'instellingen voor klantdomein', ], 'selfdnscustomer' =&gt; [ 'title' =&gt; 'klanten toestaan de dns-instellingen van het domein te wijzigen', ], 'unix_names' =&gt; [ 'title' =&gt; 'gebruik gebruikersnamen die compatible zijn met unix', 'description' =&gt; 'staat het gebruik van &lt;strong&gt;-&lt;/strong&gt; en &lt;strong&gt;_&lt;/strong&gt; gebruikersnaam toe, indien ingesteld op &lt;strong&gt;nee&lt;/strong&gt;', ], 'allow_password_reset' =&gt; [ 'title' =&gt; 'klanten toestaan hun wachtwoord opnieuw te stellen', 'description' =&gt; 'klanten kunnen hun wachtwoorden opnieuw instellen. het nieuwe wachtwoord wordt hen per e-mail toegestuurd.', ], 'allow_password_reset_admin' =&gt; [ 'title' =&gt; 'beheerders/wederverkopers toestaan hun wachtwoorden opnieuw te stellen.', 'description' =&gt; 'beheerders/wederverkopers kunnen hun wachtwoorden opnieuw instellen. het nieuwe wachtwoord wordt hen per e-mail toegestuurd.', ], 'mail_quota' =&gt; [ 'title' =&gt; 'quotum voor mailbox', 'description' =&gt; 'het standaard quotum voor nieuwe mailboxen (megabyte).', ], 'mail_quota_enabled' =&gt; [ 'title' =&gt; 'gebruik mailbox-quota voor mailboxen', 'description' =&gt; 'activeert het gebruik van quota voor mailboxen. standaard &lt;b&gt;nee&lt;/b&gt;, aangezien dit verdere configuratie vereist.', 'removelink' =&gt; 'klik hier om alle quota van mailbox te verwijderen.', 'enforcelink' =&gt; 'klik hier om het standaard quotum af te dwingen voor alle accounts.', ], 'index_file_extension' =&gt; [ 'description' =&gt; 'welk achtervoegsel moet gebruikt worden voor het indexbestand? dit achtervoegsel wordt gebruikt wanneer een van de beheerders een eigen indexsjabloon heeft gemaakt.', 'title' =&gt; 'achtervoegsel van het indexbestand nieuwe mappen voor klanten.', ], 'session_allow_multiple_login' =&gt; [ 'title' =&gt; 'meerdere logins toestaan', 'description' =&gt; 'indien dit ingeschakeld kan een klant meerdere malen tegelijkertijd inloggen.', ], 'panel_allow_domain_change_admin' =&gt; [ 'title' =&gt; 'het verplaatsen van domeinen tussen beheerders toestaan', 'description' =&gt; 'indien actief, kunt u een domein toewijzen aan een andere beheerder.&lt;br /&gt;&lt;b&gt;let op:&lt;/b&gt; indien een klant niet toegewezen aan de beheerder van het domein, kan de betreffende beheerde alle domeinen van deze klant zien!', ], 'panel_allow_domain_change_customer' =&gt; [ 'title' =&gt; 'het verplaatsen van domeinen tussen klanten toestaan', 'description' =&gt; 'indien actief, kunt u de klant van een domein veranderen.&lt;br /&gt;&lt;b&gt;let op:&lt;/b&gt; froxlor zal niet het pad aanpassen. dit kan ervoor zorgen dat het domein onbruikbaar wordt!', ], 'cron' =&gt; [ 'debug' =&gt; [ 'title' =&gt; 'foutopsporing cronscript', 'description' =&gt; 'activeer dit om het lockbestand te bewaren nadat de cron-taak afgehandeld, zodat het gerbuikt kan worden voor het opsporen van fouten.&lt;br /&gt;&lt;b&gt;let op:&lt;/b&gt;het vastzetten van het lockbestand kan ervoor zorgen dat de volgende cron-taak niet naar behoren functioneert.', ], ], 'specialsettingsforsubdomains' =&gt; [ 'description' =&gt; 'indien "ja" zullen deze aangepaste vhost-instellingen worden toegepast op alle subdomeinen.', ], 'panel_password_min_length' =&gt; [ 'title' =&gt; 'minimumlengte wachtwoord', 'description' =&gt; 'hier kunt u een minimumlengte voor wachtwoorden opgeven. \'0\' betekent geen minimumlengte.', ], 'system_store_index_file_subs' =&gt; [ 'title' =&gt; 'standaard indexbestand ook plaatsen nieuwe submappen', 'description' =&gt; 'indien actief wordt dit bestand automatisch geplaatst nieuw aangemaakte submappen (indien deze nog niet bestaat).', ], 'adminmail_return' =&gt; [ 'title' =&gt; 'reply-to adres', 'description' =&gt; 'geef een e-mailadres dat gebruikt wordt als antwoord-aan adres voor mails die verzonden worden door het paneel.', ], 'adminmail_defname' =&gt; 'panel e-mail sender name', 'stdsubdomainhost' =&gt; [ 'title' =&gt; 'standaarddomein voor klanten', 'description' =&gt; 'welke hostnaam dient gebruikt te worden voor standaard subdomeinen voor klanten. indien leeg zal de naam van het systeem gebruikt worden.', ], 'awstats_path' =&gt; 'pad naar \'awstats_buildstaticpages.pl\' van awstats', 'awstats_conf' =&gt; 'awstats configuratiepad', 'defaultttl' =&gt; 'standaard ttl voor domeinen seconden (standaard \'604800\' = 1 week)', 'defaultwebsrverrhandler_enabled' =&gt; 'standaard foutdocumenten voor alle klanten activeren', 'defaultwebsrverrhandler_err401' =&gt; [ 'title' =&gt; 'bestand/url voor foutcode 401', 'description' =&gt; '&lt;div class="text-danger"&gt;wordt niet ondersteund in: lighttpd&lt;/div&gt;', ], 'defaultwebsrverrhandler_err403' =&gt; [ 'title' =&gt; 'bestand/url voor foutcode 403', 'description' =&gt; '&lt;div class="text-danger"&gt;wordt niet ondersteund in: lighttpd&lt;/div&gt;', ], 'defaultwebsrverrhandler_err404' =&gt; 'bestand/url voor foutcode 404', 'defaultwebsrverrhandler_err500' =&gt; [ 'title' =&gt; 'bestand/url voor foutcode 500', 'description' =&gt; '&lt;div class="text-danger"&gt;wordt niet ondersteund in: lighttpd&lt;/div&gt;', ], 'ftpserver' =&gt; [ 'desc' =&gt; 'indien pureftpd geselecteerd is, worden .ftpquota bestanden dagelijks aangemaakt en/of bijgewerkt', ], 'customredirect_enabled' =&gt; [ 'title' =&gt; 'klanten toestaan doorverwijzingen te maken', 'description' =&gt; 'klanten toestaan de http-statuscode aan te passen die voor doorverwijzingen gebruikt worden', ], 'customredirect_default' =&gt; [ 'title' =&gt; 'standaard doorverwijzing', 'description' =&gt; 'kies de standaard doorverwijzingscode indien de klant dit zelf niet gedaan heeft', ], 'mail_also_with_mxservers' =&gt; 'maak mail-, imap-, pop3- en smtp-"a record" ook wanneer mx-servers zijn ingesteld', 'froxlordirectlyviahostname' =&gt; 'froxlor direct toegankelijk via hostnaam', 'panel_password_regex' =&gt; [ 'title' =&gt; 'reguliere expressie voor wachtwoorden', 'description' =&gt; 'hier kunt u een reguliere expressie opgeven voor de complexiteit van wachtwoorden.&lt;br /&gt;leeg betekent geen speciale complexiteit', ], 'perl_path' =&gt; [ 'title' =&gt; 'pad naar perl', 'description' =&gt; 'alleen relevant voor lighttpd. standaard /usr/bin/perl', ], 'mod_fcgid_ownvhost' =&gt; [ 'title' =&gt; 'fcgid inschakelen voor de vhost voor froxlor', 'description' =&gt; 'indien ingeschakeld wordt froxlor ook uitgevoerd onder een lokale gebruiker&lt;br /&gt;&lt;strong&gt;let op:&lt;/strong&gt;dit vereist handmatige configuratie, zie &lt;a target="_blank" href="https://docs.froxlor.org/latest/admin-guide/configuration/fcgid/"&gt;fcgid - handbook&lt;/a&gt;', ], 'perl' =&gt; [ 'suexecworkaround' =&gt; [ 'title' =&gt; 'om suexec heenwerken (geldt alleen voor apache)', 'description' =&gt; 'schakel dit alleen indien de documentmappen van klanten niet het pad van apache suexec vallen.&lt;br /&gt;indien ingeschakeld zal froxlor een symbolische link maken voor het pad waarvoor perl actief + /cgi-bin/.&lt;br /&gt;merk op dat perl dan alleen werkt de submap /cgi-bin/ en niet de map zelf (zoals het werkt zonder deze oplossing!)', ], 'suexeccgipath' =&gt; [ 'title' =&gt; 'pad naar symbolische links naar perl-mappen van klanten', 'description' =&gt; 'u dient dit alleen op te geven indien "om suexec heenwerken" actief is.&lt;br /&gt;let op: zorg ervoor dat deze map onder het pad van suexec valt, anders deze oplossing waardeloos', ], ], 'awstats_awstatspath' =&gt; 'pad naar awstats \'awstats.pl\'', 'awstats_icons' =&gt; [ 'title' =&gt; 'pad naar iconen awstats icons', 'description' =&gt; 'bijvoorbeeld /usr/share/awstats/htdocs/icon/', ], 'login_domain_login' =&gt; 'login met domeinen toestaan', 'nginx_php_backend' =&gt; [ 'title' =&gt; 'nginx php backend', 'description' =&gt; 'dit waar het php-proces luistert naar verzoeken van nginx, kan een unix socket van ip:poort combinatie zijn', ], 'phpreload_command' =&gt; [ 'title' =&gt; 'commando voor het herladen van php', 'description' =&gt; 'wordt gebruikt om de php backend opnieuw te laden, indien actief&lt;br /&gt;standaard: leeg', ], 'phpfpm' =&gt; 'php-fpm inschakelen', 'phpfpm_settings' =&gt; [ 'configdir' =&gt; 'configuratiemap van php-fpm', 'reload' =&gt; 'commando voor het herstarten van php-fpm', 'pm' =&gt; 'process manager control (pm)', 'max_children' =&gt; [ 'title' =&gt; 'het aantal subprocessen', 'description' =&gt; 'het aantal subprocessen dat gestart wordt indien pm ingesteld op \'statisch\' en het maximum aantal subprocessen wanneer pm ingesteld op \'dynamisch\'&lt;br /&gt;gelijk aan php_fcgi_children', ], 'start_servers' =&gt; [ 'title' =&gt; 'het aantal subprocessen bij het starten', 'description' =&gt; 'noot: wordt alleen gebruikt indien pm ingesteld op \'dynamisch\'', ], 'min_spare_servers' =&gt; [ 'title' =&gt; 'het gewenste minimum aantal vrije subprocessen', 'description' =&gt; 'noot: wordt alleen gebruikt indien pm ingesteld op \'dynamisch\'&lt;br /&gt;noot: verplicht wanneer pm ingesteld op \'dynamisch\'', ], 'max_spare_servers' =&gt; [ 'title' =&gt; 'thet gewenste minimum aantal vrije subprocessen', 'description' =&gt; 'noot: wordt alleen gebruikt indien pm ingesteld op \'dynamisch\'&lt;br /&gt;noot: verplicht wanneer pm ingesteld op \'dynamisch\'', ], 'max_requests' =&gt; [ 'title' =&gt; 'verzoeken voor subproces voordat het opnieuw gestart wordt', 'description' =&gt; 'voor het eindeloos verwerken kunt u deze waarde instellen op \'0\'. gelijk aan php_fcgi_max_requests.', ], ], ], 'spf' =&gt; [ 'use_spf' =&gt; 'spf voor domeinen activeren?', 'spf_entry' =&gt; 'spf regel voor alle domeinen', ], 'success' =&gt; [ 'success' =&gt; 'informatie', 'clickheretocontinue' =&gt; 'klik hier om verder te gaan', 'settingssaved' =&gt; 'de instellingen zijn opgeslagen.', ], 'tasks' =&gt; [ 'outstanding_tasks' =&gt; 'uitstaande cron-taken', 'rebuild_vhost' =&gt; 'bezig met opnieuw opbouwen van de configuratie van de webserver', 'create_home' =&gt; 'klant met naam %s wordt toegevoegd', 'rebuild_dns' =&gt; 'opnieuw opbouwen bind-configuratie', 'create_ftp' =&gt; 'map aanmaken voor nieuwe ftp-gebruiker', 'delete_customer_files' =&gt; 'verwijderen klantbestanden van %s', 'noneoutstanding' =&gt; 'er zijn op dit moment geen uitstaande taken voor froxlor', ], 'traffic' =&gt; [ 'month' =&gt; 'maand', 'day' =&gt; 'dag', 'months' =&gt; [ 1 =&gt; 'januari', 2 =&gt; 'februari', 3 =&gt; 'maart', 4 =&gt; 'april', 5 =&gt; 'mei', 6 =&gt; 'juni', 7 =&gt; 'juli', 8 =&gt; 'augustus', 9 =&gt; 'september', 10 =&gt; 'oktober', 11 =&gt; 'november', 12 =&gt; 'december', ], 'mb' =&gt; 'datavekeer (mb)', 'distribution' =&gt; '&lt;font color="#019522"&gt;ftp&lt;/font&gt; | &lt;font color="#0000ff"&gt;http&lt;/font&gt; | &lt;font color="#800000"&gt;mail&lt;/font&gt;', 'sumhttp' =&gt; 'samenvatting http-verkeer in', 'sumftp' =&gt; 'samenvatting ftp-verkeer in', 'summail' =&gt; 'samenvatting mail-verkeer in', ], 'translator' =&gt; 'sander klein/frits letteboer', 'update' =&gt; [ 'updateinprogress_onlyadmincanlogin' =&gt; 'een nieuwere versie van froxlor geinstalleerd maar nog niet geconfigureerd.&lt;br /&gt;alleen de beheerder kan inloggen en de update voltooien.', 'update' =&gt; 'froxlor update', 'proceed' =&gt; 'verdergaan', 'update_information' =&gt; [ 'part_a' =&gt; 'de bestanden van froxlor zijn bijgewerkt naar versie &lt;strong&gt;%s&lt;/strong&gt;. de geinstalleerde versie &lt;strong&gt;%s&lt;/strong&gt;.', 'part_b' =&gt; '&lt;br /&gt;&lt;br /&gt;klanten kunnen niet inloggen totdat de update voltooid is.&lt;br /&gt;&lt;strong&gt;verdergaan?&lt;/strong&gt;', ], 'noupdatesavail' =&gt; '&lt;strong&gt;u gebruikt reeds de meest recente versie van froxlor.&lt;/strong&gt;', ], ];</file><file name="lng/se.lng.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @author staffan starberg &lt;staff@starberg.com&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'admin' =&gt; [ 'overview' =&gt; 'versikt', 'ressourcedetails' =&gt; 'anvnda resurser', 'systemdetails' =&gt; 'system detaljer', 'froxlordetails' =&gt; 'froxlor detaljer', 'installedversion' =&gt; 'installerad version av froxlor', 'latestversion' =&gt; 'senaste version av froxlor', 'lookfornewversion' =&gt; [ 'clickhere' =&gt; '[sk senaste verison av froxlor via internet]', 'error' =&gt; 'fel vid lsning, kontrollera uppkopplingen mot froxlor', ], 'resources' =&gt; 'resurser', 'customer' =&gt; 'kunder', 'customers' =&gt; 'kunder', 'customer_add' =&gt; '[skapa en ny kund]', 'customer_edit' =&gt; 'ndra ny kund', 'domains' =&gt; 'domner', 'domain_add' =&gt; '[skapa en ny domn]', 'domain_edit' =&gt; 'tillt ndring av domnen', 'subdomainforemail' =&gt; 'sub-domn som e-postdomn (subdomains emaildomains)', 'admin' =&gt; 'admin', 'admins' =&gt; 'admins', 'admin_add' =&gt; '[skapa en ny admin]', 'admin_edit' =&gt; 'ndra admin', 'customers_see_all' =&gt; 'kan se alla kunder?', 'change_serversettings' =&gt; 'kan ndra serverinstllningar?', 'server' =&gt; 'systemet', 'serversettings' =&gt; 'instllningar', 'rebuildconf' =&gt; 'uppdatera konfig filer', 'stdsubdomain' =&gt; 'standard subdomn', 'stdsubdomain_add' =&gt; '[skapa en ny standard subdomn]', 'phpenabled' =&gt; 'php pslagen', 'deactivated' =&gt; 'inaktiv', 'deactivated_user' =&gt; 'avaktivera anvndare', 'sendpassword' =&gt; 'skicka lsenord', 'ownvhostsettings' =&gt; 'egna vhost-instllningar', 'configfiles' =&gt; [ 'serverconfiguration' =&gt; 'konfiguration', 'overview' =&gt; 'versikt', 'wizard' =&gt; 'guide', 'mail' =&gt; 'e-postserver (pop3/imap)', 'smtp' =&gt; 'e-postserver (smtp)', ], 'templates' =&gt; [ 'templates' =&gt; 'mallar', 'template_add' =&gt; '[lgg till en ny mall]', 'template_edit' =&gt; 'ndra en befintlig mall', 'action' =&gt; 'action', 'email' =&gt; 'e-post', 'subject' =&gt; 'rubrik (subjekt)', 'mailbody' =&gt; 'e-postinnehll (mail body)', 'createcustomer' =&gt; 'e-post till nya kunder (vlkommen)', 'pop_success' =&gt; 'e-post fr nya konton (vlkommen)', 'template_replace_vars' =&gt; 'variabler som kan ndras mallen:', 'firstname' =&gt; 'ndra till kundens frnamn.', 'name' =&gt; 'ndra till kundens efternamn.', 'username' =&gt; 'ndra till kundens kontonamns anvndarnamn.', 'password' =&gt; 'ndra till kundens kontonamns lsenord.', 'email' =&gt; 'ndra till adressen fr pop3/imap kontot.', 'traffic' =&gt; 'ersatt med trafikbegrnsningen som var tilldelad till kunden.', 'trafficused' =&gt; 'ersatt med trafikbegrnsningen som var verskriden av kunden.', 'pop_success_alternative' =&gt; 'vlkommstmeddelande fr nya e-post konton som skickas till den alternativa adressen', 'email_password' =&gt; 'ersatt med pop3/imap kontots lsenord.', ], 'ipsandports' =&gt; [ 'ipsandports' =&gt; 'ips ports', 'add' =&gt; '[lgg till ip/port]', 'edit' =&gt; 'ndra ip/port', 'create_listen_statement' =&gt; 'skapa "listen statement"', 'create_namevirtualhost_statement' =&gt; 'skapa namevirtualhost statement', 'create_vhostcontainer' =&gt; 'skapa vhost-container', 'create_vhostcontainer_servername_statement' =&gt; 'skapa servername statement vhost-container', ], 'memorylimitdisabled' =&gt; 'avstngd', 'valuemandatory' =&gt; 'denna ruta mste fyllas i', 'valuemandatorycompany' =&gt; 'fyll &amp;quot;frnamn&amp;quot; och &amp;quot;efternamn&amp;quot; eller &amp;quot;fretagsnamn&amp;quot;', 'serversoftware' =&gt; 'webserver version', 'phpversion' =&gt; 'php-version', 'phpmemorylimit' =&gt; 'php-minnesgrns', 'mysqlserverversion' =&gt; 'mysql server version', 'mysqlclientversion' =&gt; 'mysql klient version', 'webserverinterface' =&gt; 'webserver interface', 'accountsettings' =&gt; 'kontoinstllningar', 'panelsettings' =&gt; 'panelinstllningar', 'systemsettings' =&gt; 'systeminstllningar', 'webserversettings' =&gt; 'webserverinstllningar', 'mailserversettings' =&gt; 'e-postserverinstllningar', 'nameserversettings' =&gt; 'namnserverinstllningar', 'updatecounters' =&gt; 'uppdatera status', 'subcanemaildomain' =&gt; [ 'never' =&gt; 'aldrig', 'choosableno' =&gt; 'valbar, standardvrdet r nej', 'choosableyes' =&gt; 'valbar, standardvrdet r ja', 'always' =&gt; 'alltid', ], 'webalizersettings' =&gt; 'webalizer instllningar', 'webalizer' =&gt; [ 'normal' =&gt; 'normal', 'quiet' =&gt; 'tyst', 'veryquiet' =&gt; 'vldigt tyst', ], 'domain_nocustomeraddingavailable' =&gt; 'det gr inte att skapa en ny domn innan det finns mins en upplagd kund.', ], 'changepassword' =&gt; [ 'old_password' =&gt; 'gammalt lsenord', 'new_password' =&gt; 'nytt lsenord', 'new_password_confirm' =&gt; 'nytt lsenord (verifiera)', 'new_password_ifnotempty' =&gt; 'nytt lsenord (tomt fltet = inga ndringar)', 'also_change_ftp' =&gt; ' ndra ven lsenord fr huvud ftp kontot', 'also_change_stats' =&gt; ' ndra ven lsenord fr statistik', ], 'customer' =&gt; [ 'documentroot' =&gt; 'hemkatalog', 'name' =&gt; 'efternamn', 'firstname' =&gt; 'frnamn', 'company' =&gt; 'fretag', 'street' =&gt; 'postadress', 'zipcode' =&gt; 'postnummer', 'city' =&gt; 'postort', 'phone' =&gt; 'telefon', 'fax' =&gt; 'fax', 'email' =&gt; 'e-post', 'customernumber' =&gt; 'kundnummer', 'diskspace' =&gt; 'webb (mb)', 'traffic' =&gt; 'trafik (gb)', 'mysqls' =&gt; 'sql_dbas', 'emails' =&gt; 'e-post_adresser', 'accounts' =&gt; 'e-post_konton', 'forwarders' =&gt; 'e-post_skicka_vidare', 'ftps' =&gt; 'ftp_kto', 'subdomains' =&gt; 'sub-domner', 'domains' =&gt; 'domner', ], 'domain' =&gt; [ 'openbasedirpath' =&gt; 'openbasedir-path', 'docroot' =&gt; 'skvgen frn ovanstende flt', 'homedir' =&gt; 'hemkatalog', ], 'domains' =&gt; [ 'description' =&gt; 'hr kan du skapa (sub-)domner och ndra dem.&lt;br /&gt;systemet behver dock lite tid p sig att genomfra ndringarna.', 'domainsettings' =&gt; 'domninstllningar', 'domainname' =&gt; 'domnnamn', 'subdomain_add' =&gt; '[skapa en ny subdomn]', 'subdomain_edit' =&gt; 'ndra (sub)domn', 'wildcarddomain' =&gt; 'skapa som ospecificerad domn (create wildcarddomain?)', 'aliasdomain' =&gt; 'alias domn', 'noaliasdomain' =&gt; '(inget alias)', 'hasaliasdomains' =&gt; 'domnen har redan alias', 'statstics' =&gt; 'anvndarstatistik', 'isassigneddomain' =&gt; 'tilldelad domn ', ], 'emails' =&gt; [ 'description' =&gt; 'hr kan du skapa eller ndra dina e-postadresser.&lt;br /&gt;ett konto r som en brevlda utanfr huset. om ngon skickar dig e-post kommer det att hamna din brevlda (ditt konto).&lt;br /&gt;&lt;br /&gt;fr att hmta din e-post skall du anvnda fljande instllningar ditt e-postprogram: (text kursiv stil &lt;i&gt;italics&lt;/i&gt; mste ndras till det som motsvaras av det du knappade tidigare!)&lt;br /&gt;servernamn (hostname): &lt;b&gt;&lt;i&gt;domnnamn (domainname)&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;anvndarnamn (username): &lt;b&gt;&lt;i&gt;konto namn (account name) / e-postadress&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;lsenord (password): &lt;b&gt;&lt;i&gt;lsenordet som du valde&lt;/i&gt;&lt;/b&gt;', 'emailaddress' =&gt; 'e-postadress', 'emails_add' =&gt; '[skapa en e-postadress]', 'emails_edit' =&gt; 'ndra e-postadressen', 'catchall' =&gt; 'maildump', 'iscatchall' =&gt; 'skapa en maildump?', 'account' =&gt; 'konto', 'account_add' =&gt; 'skapa konto', 'account_delete' =&gt; 'radera konto', 'from' =&gt; 'frn', 'to' =&gt; 'till', 'forwarders' =&gt; 'skicka vidare:', 'forwarder_add' =&gt; '[skapa ny "skicka vidare"]', 'alternative_emailaddress' =&gt; 'alternative e-mail-address', ], 'error' =&gt; [ 'error' =&gt; 'fljande fel har uppsttt', 'directorymustexist' =&gt; 'katalogen %s mste finnas. skapa den med ditt ftp program.', 'filemustexist' =&gt; 'filen %s mste existera.', 'allresourcesused' =&gt; 'du har redan skapt mnga konton som du har tillstnd till.', 'domains_cantdeletemaindomain' =&gt; 'du kan inte radera en domn som anvndes fr e-post.', 'domains_canteditdomain' =&gt; 'endast administratrer kan ndra denna domn.', 'domains_cantdeletedomainwithemail' =&gt; 'du kan inte radera en domn som anvndes fr e-post. radera alla e-postadresser frst', 'firstdeleteallsubdomains' =&gt; 'du mste radera alla sub-domner innan du kan skapa en maildump (wildcard domain).', 'youhavealreadyacatchallforthisdomain' =&gt; 'du har redan skapat en maildump fr denna domn.', 'ftp_cantdeletemainaccount' =&gt; 'det gr inte att radera huvud ftp kontot fr domnen', 'login' =&gt; 'anvndarnamnet eller lsenordet var felaktigt, frsk igen!', 'login_blocked' =&gt; 'kontot har blivit avstngt p grund av fr mnga felaktiga inloggningsfrsk. &lt;br /&gt;frsk igen om %s sekunder.', 'notallreqfieldsorerrors' =&gt; 'du har inte fyllt alla flt eller har du skrivit ngot som inte accepteras.', 'oldpasswordnotcorrect' =&gt; 'det gamla lsenordet r fel.', 'youcantallocatemorethanyouhave' =&gt; 'du kan inte skapa fler resurser n du ger sjlv (you cannot allocate resources yourself).', 'mustbeurl' =&gt; 'du har inte skrivit en korrekt url (e.g. http://somedomain.com/error404.htm)', 'invalidpath' =&gt; 'du har inte valt en korrekt url (kanske har du lagt till en katalogskerhet att katalogerna inte kan visas?)', 'stringisempty' =&gt; 'du mste skriva ngot fltet', 'stringiswrong' =&gt; 'fel inatningsflt', 'newpasswordconfirmerror' =&gt; 'new password confirmation match', 'mydomain' =&gt; '\'domain\'', 'mydocumentroot' =&gt; '\'documentroot\'', 'loginnameexists' =&gt; 'login-name %s r upptaget', 'emailiswrong' =&gt; 'e-post-adressen "%s" innehller ogiltiga tecken eller r den inte komplett', 'loginnameiswrong' =&gt; 'login-namnet %s innehller ogiltiga tecken', 'userpathcombinationdupe' =&gt; 'anvndarnamnet och skvgen tillsammans finns redan', 'patherror' =&gt; 'generellt fel! skvgen till katalogen kan inte vara tom', 'errordocpathdupe' =&gt; 'option fr skvgen %s finns redan', 'adduserfirst' =&gt; 'skapa anvndaren frst', 'domainalreadyexists' =&gt; 'domnen %s gs redan av en kund', 'nolanguageselect' =&gt; 'inget sprk r valt.', 'nosubjectcreate' =&gt; 'du mste ha ett rubrik fr denna e-postmall.', 'nomailbodycreate' =&gt; 'du mste ha skrivit en e-post text fr denna mall.', 'templatenotfound' =&gt; 'e-postmallen hittades inte.', 'alltemplatesdefined' =&gt; 'du kan inte skapa flera mallar, alla sprk finns redan.', 'wwwnotallowed' =&gt; 'www r inte tilltet att anvnda fr subdomner.', 'subdomainiswrong' =&gt; 'subdomnen %s innehller ogiltiga tecken.', 'domaincantbeempty' =&gt; 'fltet fr domnnamn fr inte vara tommt.', 'domainexistalready' =&gt; 'domnen %s finns redan.', 'domainisaliasorothercustomer' =&gt; 'den valda domnen r antingen en aliasdomn eller gs den redan av en annan kund.', 'emailexistalready' =&gt; 'e-postadressen %s finns redan.', 'maindomainnonexist' =&gt; 'huvuddomnen %s finns inte.', 'destinationnonexist' =&gt; 'skapa en forwarder fltet \'destination\'.', 'destinationalreadyexistasmail' =&gt; 'denna forwarder %s, finns redan som aktiv e-postadress.', 'destinationalreadyexist' =&gt; 'du har redan skapat en forwarder till %s .', 'destinationiswrong' =&gt; 'denna forwarder: %s innehller ogiltiga tecken eller r den inte komplett adress.', 'ipstillhasdomains' =&gt; 'ip/port kombinationen som du vill radera har fortfarande domner anslutna till sig, flytta dessa till ngon annan ip/port kombination innan du raderar denna ip/port kombination.', 'cantdeletedefaultip' =&gt; 'det gr inte att ta bort den frvalda terfrsljarens ip/port kombination, vlj en annan ip/port kombination som frval fr terfrsljare innan du raderar denna ip/port kombination.', 'cantdeletesystemip' =&gt; 'det gr inte att radera den sista system ip:n, antingen skapar man en ny ip/port kombination fr system ip eller ndrar man system ip:n.', 'myipaddress' =&gt; '\'ip\'', 'myport' =&gt; '\'port\'', 'myipdefault' =&gt; 'man mste vlja en ip/port kombination som skall bli standardvrdet.', 'myipnotdouble' =&gt; 'denna ip/port kombination finns redan.', 'cantchangesystemip' =&gt; 'man kan inte ndra den senaste system ip-adressen. skapa en helt ny ip/port kombination fr system ip:n eller ndra system ip-adressen.', 'sessiontimeoutiswrong' =&gt; 'bara siffror &amp;quot;session timeout&amp;quot; r tilltna.', 'maxloginattemptsiswrong' =&gt; 'bara siffror &amp;quot;max login attempts&amp;quot; r tilltna.', 'deactivatetimiswrong' =&gt; 'bara siffror &amp;quot;deactivate time&amp;quot; r tilltna.', 'accountprefixiswrong' =&gt; 'det hr &amp;quot;customerprefix&amp;quot; r fel.', 'mysqlprefixiswrong' =&gt; 'det hr &amp;quot;sql prefix&amp;quot; r fel.', 'ftpprefixiswrong' =&gt; 'det hr &amp;quot;ftp prefix&amp;quot; r fel.', 'ipiswrong' =&gt; 'den hr &amp;quot;ip-address&amp;quot; r fel. endast en giltig ip-adress r tillten.', 'vmailuidiswrong' =&gt; 'den hr &amp;quot;mails-uid&amp;quot; r fel. endast numerisk uid r tilltenis allowed.', 'vmailgidiswrong' =&gt; 'den hr &amp;quot;mails-gid&amp;quot; r fel. endast numerisk gid r tilltenis allowed.', 'adminmailiswrong' =&gt; 'den hr &amp;quot;sender-address&amp;quot; r fel. endast en giltig e-postadress r tillten.', 'pagingiswrong' =&gt; 'den hr &amp;quot;entries per page&amp;quot;-vrdet r fel. endast siffror r tilltna.', 'phpmyadminiswrong' =&gt; 'den hr phpmyadmin-link r inte en giltig lnk.', 'webmailiswrong' =&gt; 'den hr webmail-link r inte en giltig lnk.', 'webftpiswrong' =&gt; 'den hr webftp-link r inte en giltig lnk.', 'stringformaterror' =&gt; 'vrdet fr fltet &amp;quot;%s&amp;quot; har inte rtt format.', 'loginnameissystemaccount' =&gt; 'det gr inte att skapa ett konto som liknar ett systemkonto (om det till exempel brjar med &amp;quot;%s&amp;quot;). vlj ett annat kontonamn.', 'youcantdeleteyourself' =&gt; 'av skerhetsskl gr inte att redera ditt eget konto.', 'youcanteditallfieldsofyourself' =&gt; 'notera: av skerhetsskl gr det inte att ndra ditt eget konto.', 'documentrootexists' =&gt; 'katalogen &amp;quot;%s&amp;quot; finns redan hos den hr kunden. radera detta frst innan kunden skapas igen.', 'formtokencompromised' =&gt; 'den skra anslutningen till froxlor har avslutats och du har av skerhetsskl automatiskt loggats ur.', ], 'extras' =&gt; [ 'description' =&gt; 'hr kan du ndra vriga saker ssom katalogskydd mm.&lt;br /&gt;systemet behver dock lite tid p sig att genomfra ndringarna.', 'directoryprotection_add' =&gt; '[skapa ett nytt katalogskydd]', 'view_directory' =&gt; 'visa kataloginnehll', 'pathoptions_add' =&gt; '[skapa ny regel fr skvgar]', 'directory_browsing' =&gt; 'visning av katalogstruktur', 'pathoptions_edit' =&gt; 'ndra skvgsinstllningar', ], 'ftp' =&gt; [ 'description' =&gt; 'hr kan du skapa eller nra dina ftp konton.&lt;br /&gt;ndringen genomfrs omedelbart man kan anvnda det nya/ndrade kontot direkt.', 'account_add' =&gt; '[skapa ett nytt ftp konto]', ], 'index' =&gt; [ 'customerdetails' =&gt; 'kunddetaljer', 'accountdetails' =&gt; 'kontodetaljer', ], 'login' =&gt; [ 'username' =&gt; 'anvndarnamn', 'password' =&gt; 'lsenord', 'language' =&gt; 'sprk', 'login' =&gt; 'logga in', 'logout' =&gt; 'logga ut', 'profile_lng' =&gt; 'profilsprk', ], 'mails' =&gt; [ 'pop_success' =&gt; [ 'mailbody' =&gt; 'hej,\\n\\nditt e-postkonto {email}\\nhar nu skapats.\\n\\ndetta r ett automatgenererat e-post meddelande\\n, det gr drfr inte att svara p detta meddelande!\\n', 'subject' =&gt; 'e-postkontot r nu skapat', ], 'createcustomer' =&gt; [ 'mailbody' =&gt; 'hej {firstname} {name},\\n\\nhr kommer kontoinformationen fr ditt konto:\\n\\nanvndarnamn (username): {username}\\nlsenord (password): {password}\\n\\n', 'subject' =&gt; 'kontoinformation', ], 'pop_success_alternative' =&gt; [ 'mailbody' =&gt; 'hej,\\n\\nditt e-postkonto {email}\\nhar ny skapats.\\nditt lsenord r {password}.\\n\\ndetta r ett automatgenererat e-postmeddelande som det inte gr att svara p!\\n\\nlycka till nskar, froxlor', 'subject' =&gt; 'e-postkontot r nu skapat', ], ], 'menue' =&gt; [ 'main' =&gt; [ 'main' =&gt; 'huvudsidan', 'changepassword' =&gt; 'ndra lsenord', 'changelanguage' =&gt; 'ndra sprk', 'username' =&gt; 'inloggad som: ', ], 'email' =&gt; [ 'email' =&gt; 'e-post', 'emails' =&gt; 'e-post', 'webmail' =&gt; 'webmail', ], 'mysql' =&gt; [ 'mysql' =&gt; 'mysql', 'databases' =&gt; 'databaser', 'phpmyadmin' =&gt; 'phpmyadmin', ], 'domains' =&gt; [ 'domains' =&gt; 'domner', 'settings' =&gt; 'instllningar', ], 'ftp' =&gt; [ 'ftp' =&gt; 'ftp', 'accounts' =&gt; 'konton', 'webftp' =&gt; 'webftp', ], 'extras' =&gt; [ 'extras' =&gt; 'extras', 'directoryprotection' =&gt; 'katalog skerhet', 'pathoptions' =&gt; 'instllningar skvg', ], 'traffic' =&gt; [ 'traffic' =&gt; 'trafik', 'current' =&gt; 'nuvarande mnad', ], ], 'mysql' =&gt; [ 'databasename' =&gt; 'anvndare/databasnamn', 'databasedescription' =&gt; 'beskrivning av databasen', 'database_create' =&gt; '[skapa en ny databas]', 'description' =&gt; 'hr ndras eller skapas mysql-databaser.&lt;br /&gt;ndringen sker omedelbart och databasen kan anvndas direkt.&lt;br /&gt;i menyn p vnster sida finns verktyget phpmyadmin med vilket man enkelt kan ndra sin databas.&lt;br /&gt;&lt;br /&gt;fr att anvnda databasen dina egna php-scripts anvnd fljande instllningar: (data med kursiv stil &lt;i&gt;italics&lt;/i&gt; mste ndras till det du matat in!)&lt;br /&gt;servernamn (hostname): &lt;b&gt;&lt;sql_host&gt;&lt;/b&gt;&lt;br /&gt;anvndarnamn (username): &lt;b&gt;&lt;i&gt;databsnamn (databasename)&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;lsenord (password): &lt;b&gt;&lt;i&gt;lsenordet som du har valt&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;databas (database): &lt;b&gt;&lt;i&gt;databasnamn (databasename)&lt;/i&gt;&lt;/b&gt;', ], 'panel' =&gt; [ 'edit' =&gt; 'ndra', 'delete' =&gt; 'radera', 'create' =&gt; 'skapa', 'save' =&gt; 'spara', 'yes' =&gt; 'ja', 'no' =&gt; 'nej', 'emptyfornochanges' =&gt; 'tomt flt = ingen ndring', 'emptyfordefault' =&gt; 'frvalt vrde anvnds om fltet lmnas tommt', 'path' =&gt; 'skvg (path)', 'toggle' =&gt; 'vxla (toggle)', 'next' =&gt; 'nsta', 'dirsmissing' =&gt; 'kan inte hitta eller lsa katalogen!', 'urloverridespath' =&gt; 'url (skriver ver skvgen)', 'pathorurl' =&gt; 'skvg eller url', 'ascending' =&gt; 'stigande', 'descending' =&gt; 'fallande', 'search' =&gt; 'sk', 'used' =&gt; 'anvnd', 'translator' =&gt; 'versttare', 'reset' =&gt; 'avbryt ndringarna', 'pathdescription' =&gt; 'katalogen kommer att skapas om den inte redan finns.', 'back' =&gt; 'tillbaka', ], 'question' =&gt; [ 'question' =&gt; 'skerhetsfrga', 'admin_customer_reallydelete' =&gt; 'r du sker p att du vill radera kunden %s? om du vljer att radera gr det inte att ngra sig eftert!', 'admin_domain_reallydelete' =&gt; 'r du riktigt sker p att du vill radera domnen %s?', 'admin_domain_reallydisablesecuritysetting' =&gt; 'r du riktigt sker p att du vill avaktivera skerhetsinstllningarna (openbasedir and/or safemode)?', 'admin_admin_reallydelete' =&gt; 'r du riktigt sker p att du vill radera adminkontot %s? alla kunder och domner kommer att flyttas till ditt konto istllet.', 'admin_template_reallydelete' =&gt; 'r du riktigt sker p att du vill radera mallen \'%s\'?', 'domains_reallydelete' =&gt; 'r du riktigt sker p att du vill radera domnen %s?', 'email_reallydelete' =&gt; 'r du riktigt sker p att du vill radera e-postadressen %s?', 'email_reallydelete_account' =&gt; 'r du riktigt sker p att du vill radera e-postkontot %s?', 'email_reallydelete_forwarder' =&gt; 'r du riktigt sker p att du vill radera forwardern till %s?', 'extras_reallydelete' =&gt; 'r du riktigt sker p att du vill radera katalogskerheten (directory protection) fr %s?', 'extras_reallydelete_pathoptions' =&gt; 'r du riktigt sker p att du vill radera katalogalternativen (path options) fr %s?', 'ftp_reallydelete' =&gt; 'r du riktigt sker p att du vill radera ftp kontot %s?', 'mysql_reallydelete' =&gt; 'r du riktigt sker p att du vill radera databasen %s? om du vljer att radera gr det inte att ngra sig eftert!', 'admin_configs_reallyrebuild' =&gt; 'r du riktigt sker p att du vill skapa nya konfigurationsfiler fr apache och bind?', 'admin_ip_reallydelete' =&gt; 'r du sker p att du vill radera ip addressen %s?', 'admin_domain_reallydocrootoutofcustomerroot' =&gt; 'dokumentkatalogen fr denna domn inte kommer att ligga kundkatalogen, r du sker p att du vill ndra detta?', 'admin_counters_reallyupdate' =&gt; 'vill du uppdatera alla statusberkningar fr kunder och admins?', 'admin_cleartextmailpws_reallywipe' =&gt; 'r du sker p att du vill radera alla okrupterade lsenord frn tabellen mail_users? du kan inte ndra dig eftert!', ], 'serversettings' =&gt; [ 'session_timeout' =&gt; [ 'title' =&gt; 'sessionen har avslutats fr att den tog fr lng tid att utfra (session timeout)', 'description' =&gt; 'tiden (i sekunder) som anvndaren fr vara inaktiv innan han mste logga igen r (seconds)?', ], 'accountprefix' =&gt; [ 'title' =&gt; 'kund id (customer prefix)', 'description' =&gt; 'vilket prefix skall anvndas till ett kundkonto?', ], 'mysqlprefix' =&gt; [ 'title' =&gt; 'sql id (sql prefix)', 'description' =&gt; 'vilket prefix skall anvndas till mysql?', ], 'ftpprefix' =&gt; [ 'title' =&gt; 'ftp id (ftp prefix)', 'description' =&gt; 'vilket prefix skall anvndas till ftp?', ], 'documentroot_prefix' =&gt; [ 'title' =&gt; 'hemkatalog', 'description' =&gt; 'vilken skvg skall det vara till hemkatalogen?', ], 'logfiles_directory' =&gt; [ 'title' =&gt; 'loggfilernas hemkatalog (logfiles directory)', 'description' =&gt; 'vilken skvg skall det vara till loggfilernas hemkatalog?', ], 'ipaddress' =&gt; [ 'title' =&gt; 'ip-adress', 'description' =&gt; 'vilken ip-adress har denna server?', ], 'hostname' =&gt; [ 'title' =&gt; 'datornamn (hostname)', 'description' =&gt; 'villket datornamn (hostname) har denna server?', ], 'apachereload_command' =&gt; [ 'title' =&gt; 'ladda om apache kommandot (apache reload)', 'description' =&gt; 'ange skvgen till programmet som laddar om apache (reload apache) konfigurationsfiler?', ], 'bindconf_directory' =&gt; [ 'title' =&gt; 'bind konfigurationskatalog (bind config directory)', 'description' =&gt; 'vilken skvg skall det vara till bind:s konfigurationsfiler?', ], 'bindreload_command' =&gt; [ 'title' =&gt; 'ange skvgen till programmet som laddar om bind (reload bind) konfigurationsfiler?', 'description' =&gt; 'ange skvgen till programmet som laddar om bind (reload bind) konfigurationsfiler?', ], 'vmail_uid' =&gt; [ 'title' =&gt; 'mails-uid', 'description' =&gt; 'vilket anvndarid (userid) ska e-posten ha?', ], 'vmail_gid' =&gt; [ 'title' =&gt; 'mails-gid', 'description' =&gt; 'vilket gruppid (groupid) ska e-posten ha?', ], 'vmail_homedir' =&gt; [ 'title' =&gt; 'e-post hemkatalog', 'description' =&gt; 'i vilken katalog skall e-posten sparas?', ], 'adminmail' =&gt; [ 'title' =&gt; 'avsndare', 'description' =&gt; 'vilken avsndaradress skall e-post frn admin panelen ha?', ], 'phpmyadmin_url' =&gt; [ 'title' =&gt; 'phpmyadmin url', 'description' =&gt; 'vilken url r det till phpmyadmin? (mste brja med http(s)://)', ], 'webmail_url' =&gt; [ 'title' =&gt; 'webmail url', 'description' =&gt; 'vilken url r det till webmail? (mste brja med http(s)://)', ], 'webftp_url' =&gt; [ 'title' =&gt; 'webftp url', 'description' =&gt; 'vilken url r det till webftp? (mste brja med http(s)://)', ], 'language' =&gt; [ 'description' =&gt; 'vilket sprk skall anvndas som standardsprk?', ], 'maxloginattempts' =&gt; [ 'title' =&gt; 'max antal login frsk', 'description' =&gt; 'maximalt antal inloggningsfrsk innan kontot stngs av.', ], 'deactivatetime' =&gt; [ 'title' =&gt; 'avstngningstid', 'description' =&gt; 'tid (sec.) som kontot stngs av efter fr mnga felaktiga frsk.', ], 'pathedit' =&gt; [ 'title' =&gt; 'typ av (path input)', 'description' =&gt; 'skall en skvg vljas en rullist eller matas fr hand?', ], 'nameservers' =&gt; [ 'title' =&gt; 'nameservers', 'description' =&gt; 'en kommaseparerad lista med namnet (hostname) p alla dns:er. den frsta blir den frsta som sks (primary).', ], 'mxservers' =&gt; [ 'title' =&gt; 'mx servers', 'description' =&gt; 'en kommaseparerad lista med nummer och namn separerade men mellanslag (ex. \'10 mx.example.com\') innehller mx servrarna.', ], 'paging' =&gt; [ 'title' =&gt; 'antal rader per sida', 'description' =&gt; 'hur mnga rader skall det vara p en sida? (0 = stng av sidbrytning)', ], 'defaultip' =&gt; [ 'title' =&gt; 'frvald ip/port', 'description' =&gt; 'vilken r den frvalda ip/port kombinationen?', ], 'phpappendopenbasedir' =&gt; [ 'title' =&gt; 'skvg att lgga till openbasedir', 'description' =&gt; 'dessa skvgar (separerade med kolon) kommer att lggas till openbasedir-statement alla vhost-container.', ], 'natsorting' =&gt; [ 'title' =&gt; 'anvnd mnsklig sortertering listvisning', 'description' =&gt; 'sorterar listan hr web1 -&gt; web2 -&gt; web11 istllet fr web1 -&gt; web11 -&gt; web2.', ], 'deactivateddocroot' =&gt; [ 'title' =&gt; 'dokumentroot fr avstngda anvndare', 'description' =&gt; 'nr en anvndare r avstngd kommer denna skvg att anvndas som dokumentroot. lmna fltet tommt om du inte vill skapa ngon vhost.', ], 'mailpwcleartext' =&gt; [ 'title' =&gt; 'spara ven lsenord till e-postkonton okrypterade databassen', 'description' =&gt; 'om du valt ja kommer alla lsenord att sparas okrypterade (klartext, fullt lsbara fr alla som har rttigheter till databasen) tabellen mail_users-table. aktivera detta endast om du r sker p vad du gr!', 'removelink' =&gt; 'klicka hr fr att radera alla okrypterade lsenord frn tabellen.', ], 'ftpdomain' =&gt; [ 'title' =&gt; 'ftp konton @domain', 'description' =&gt; 'kunder kan skapa ftp accounts user@customerdomain?', ], 'mod_fcgid' =&gt; [ 'title' =&gt; 'inkludera php via mod_fcgid/suexec', 'description' =&gt; 'anvnd mod_fcgid/suexec/libnss_mysql fr att kra php med tillhrande anvndarkonto.&lt;br/&gt;&lt;b&gt;denna instllning behver en speciell apache-konfiguration!&lt;/b&gt;', 'configdir' =&gt; [ 'title' =&gt; 'fcgi konfigurationskatalog', 'description' =&gt; 'i vilken katalog skall alla fcgi-konfigurationfiler lagras?', ], 'tmpdir' =&gt; [ 'title' =&gt; 'fcgi temporrkatalog', ], ], 'sendalternativemail' =&gt; [ 'title' =&gt; 'anvnd en alternativ e-postadress', 'description' =&gt; 'skicka lsenord med e-post till adressen email-account-creation', ], 'apacheconf_vhost' =&gt; [ 'title' =&gt; 'apache vhost konfiguration fil/katalognamn', 'description' =&gt; 'var skall vhost konfigurationen sparas? det gr att specificera alla vhost en fil eller en katalog dr alla filerna ligger (varje vhost sin egen fil).', ], 'apacheconf_diroptions' =&gt; [ 'title' =&gt; 'apache diroptions konfiguration fil/katalognamn', 'description' =&gt; 'var skall diroptions konfigurationen sparas? det gr att specificera alla diroptions en fil eller en katalog dr alla filerna ligger (varje diroptions sin egen fil).', ], 'apacheconf_htpasswddir' =&gt; [ 'title' =&gt; 'apache htpasswd katalognamn', 'description' =&gt; 'var skall htpasswd konfigurationen fr katalogskerheten?', ], 'mysql_access_host' =&gt; [ 'description' =&gt; 'en kommaseparerad lista med datornamn som tillts att kontakta mysql servern.', ], ], 'traffic' =&gt; [ 'month' =&gt; 'mnad', 'day' =&gt; 'dag', 'months' =&gt; [ 1 =&gt; 'januari', 2 =&gt; 'februari', 3 =&gt; 'mars', 4 =&gt; 'april', 5 =&gt; 'maj', 6 =&gt; 'juni', 7 =&gt; 'juli', 8 =&gt; 'augusti', 9 =&gt; 'september', 10 =&gt; 'oktober', 11 =&gt; 'november', 12 =&gt; 'december', ], 'mb' =&gt; 'trafik (mb)', 'distribution' =&gt; '&lt;font color="#019522"&gt;ftp&lt;/font&gt; | &lt;font color="#0000ff"&gt;http&lt;/font&gt; | &lt;font color="#800000"&gt;mail&lt;/font&gt;', 'sumhttp' =&gt; 'summa http-trafik i', 'sumftp' =&gt; 'summa ftp-trafik i', 'summail' =&gt; 'summa e-posttrafik i', ], 'translator' =&gt; 'staffan starberg', ];</file><file name="lng/de.lng.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'languages' =&gt; [ 'cz' =&gt; 'tschechisch', 'de' =&gt; 'deutsch', 'en' =&gt; 'englisch', 'fr' =&gt; 'franzsisch', 'it' =&gt; 'italienisch', 'nl' =&gt; 'niederlndisch', 'pt' =&gt; 'portugiesisch', 'se' =&gt; 'schwedisch', 'es' =&gt; 'spanisch', ], '2fa' =&gt; [ '2fa' =&gt; '2fa optionen', '2fa_enabled' =&gt; 'aktiviere zwei-faktor authentifizierung (2fa)', '2fa_removed' =&gt; '2fa erfolgreich gelscht', '2fa_added' =&gt; '2fa erfolgreich aktiviert&lt;br&gt;&lt;a class="alert-link" href="%s?page=2fa"&gt;2fa details ffnen&lt;/a&gt;', '2fa_add' =&gt; '2fa aktivieren', '2fa_delete' =&gt; '2fa deaktivieren', '2fa_verify' =&gt; 'code verifizieren', '2fa_overview_desc' =&gt; 'hier kann fr das konto eine zwei-faktor-authentisierung aktiviert werden.&lt;br&gt;&lt;br&gt;es kann entweder eine authenticator-app (time-based one-time password / totp) genutzt werden oder ein einmalpasswort, welches nach erfolgreichem login die hinterlegte e-mail adresse gesendet wird.', '2fa_email_desc' =&gt; 'das konto ist eingerichtet, um einmalpasswrter per e-mail zu erhalten. zum deaktivieren, klicke auf "2fa deaktivieren"', '2fa_ga_desc' =&gt; 'das konto ist eingerichtet, um zeitbasierte einmalpasswrter via authenticator-app zu erhalten. um die gewnschte authenticator-app einzurichten, scanne bitte den untenstehenden qr-code. zum deaktivieren, klicke auf "2fa deaktivieren"', '2fa_not_activated' =&gt; 'zwei-faktor authentifizierung ist nicht aktiviert', '2fa_not_activated_for_user' =&gt; 'zwei-faktor authentifizierung ist fr den aktuellen benutzer nicht aktiviert', 'type_2fa' =&gt; '2fa status', ], 'admin' =&gt; [ 'overview' =&gt; 'bersicht', 'ressourcedetails' =&gt; 'verbrauchte ressourcen', 'systemdetails' =&gt; 'systemdetails', 'froxlordetails' =&gt; 'froxlor-details', 'installedversion' =&gt; 'installierte version', 'latestversion' =&gt; 'neueste version', 'lookfornewversion' =&gt; [ 'clickhere' =&gt; 'per webservice abfragen - hier klicken', 'error' =&gt; 'fehler bei abfrage', ], 'resources' =&gt; 'ressourcen', 'customer' =&gt; 'kunde', 'customers' =&gt; 'kunden', 'customers_list_desc' =&gt; 'kundenverwaltung', 'customer_add' =&gt; 'kunden anlegen', 'customer_edit' =&gt; 'kunden bearbeiten', 'username_default_msg' =&gt; 'leer lassen fr automatische benutzername-vergabe', 'password_default_msg' =&gt; 'leer lassen fr passwortgenerierung', 'domains' =&gt; 'domains', 'domain_add' =&gt; 'domain anlegen', 'domain_edit' =&gt; 'domain bearbeiten', 'subdomainforemail' =&gt; 'subdomains als e-mail-domains erlauben', 'admin' =&gt; 'admin', 'admins' =&gt; 'admins', 'admin_add' =&gt; 'admin anlegen', 'admin_edit' =&gt; 'admin bearbeiten', 'customers_see_all' =&gt; 'zugriff auf resourcen anderer admins/reseller?', 'change_serversettings' =&gt; 'kann servereinstellungen bearbeiten?', 'serversettings' =&gt; 'einstellungen', 'serversettings_desc' =&gt; 'verwalte dein froxlor system', 'rebuildconf' =&gt; 'configs neu schreiben', 'stdsubdomain' =&gt; 'standardsubdomain', 'stdsubdomain_add' =&gt; 'standardsubdomain anlegen', 'phpenabled' =&gt; 'php verfgbar', 'deactivated' =&gt; 'gesperrt', 'deactivated_user' =&gt; 'benutzer sperren', 'sendpassword' =&gt; 'passwort zusenden', 'ownvhostsettings' =&gt; 'eigene vhost-einstellungen', 'configfiles' =&gt; [ 'serverconfiguration' =&gt; 'konfiguration', 'overview' =&gt; 'bersicht', 'wizard' =&gt; 'assistent', 'distribution' =&gt; 'distribution', 'service' =&gt; 'service', 'daemon' =&gt; 'daemon', 'http' =&gt; 'webserver (http)', 'dns' =&gt; 'nameserver (dns)', 'mail' =&gt; 'mailserver (imap/pop3)', 'smtp' =&gt; 'mailserver (smtp)', 'ftp' =&gt; 'ftp-server', 'etc' =&gt; 'sonstige (system)', 'choosedistribution' =&gt; '-- distribution whlen --', 'chooseservice' =&gt; '-- service whlen --', 'choosedaemon' =&gt; '-- daemon whlen --', 'statistics' =&gt; 'statistik', 'compactoverview' =&gt; 'kompakt-bersicht', 'legend' =&gt; '&lt;h3&gt;sie konfigurieren nun einen service/daemon.&lt;/h3&gt;', 'commands' =&gt; '&lt;span class="text-danger"&gt;kommandos:&lt;/span&gt; die angezeigten befehle mssen als benutzer root einer shell ausgefhrt werden. es kann auch problemlos der ganze block kopiert und die shell eingefgt werden.', 'files' =&gt; '&lt;span class="text-danger"&gt;konfigurationsdateien:&lt;/span&gt; der befehl direkt vor dem textfeld sollte einen editor mit der zieldatei ffnen. der inhalt kann nun einfach kopiert und den editor eingefgt und die datei gespeichert werden.&lt;br&gt;&lt;span class="text-danger"&gt;bitte beachten:&lt;/span&gt; das mysql-passwort wurde aus sicherheitsgrnden nicht ersetzt. bitte ersetzen sie "froxlor_mysql_password" manuell oder nutzen sie das folgende formular, um es temporr auf dieser seite zu setzen. falls das passwort vergessen wurde, findet es sich der datei "lib/userdata.inc.php".', 'finishnote' =&gt; 'parameter datei erfolgreich erstellt. folgende befehle mssen als root ausgefhrt werden:', 'description' =&gt; 'system-dienste konfigurieren', 'minihowto' =&gt; 'auf dieser seite knnen die verschiedenen konfigurationsvorlagen fr jeden dienst angezeigt werden, bestimmte dienste bei bedarf (erneut) konfiguriert oder die aktuelle auswahl eine json-datei exportiert werden, um sie den cli-skripten oder auf einem anderen server zu verwenden.&lt;br&gt;&lt;br&gt;&lt;b&gt;beachte&lt;/b&gt;, dass die hervorgehobenen dienste nicht die auf dem server genutzten dienste widerspiegeln, sondern anforderungen/empfehlungen aus den aktuellen einstellungswerten zeigen.', 'skipconfig' =&gt; 'nicht (erneut) konfigurieren', 'recommendednote' =&gt; 'empfohlene/bentigte dienste anhand der aktuellen systemeinstellungen', 'selectrecommended' =&gt; 'empfohlene whlen', 'downloadselected' =&gt; 'auswahl exportieren', ], 'templates' =&gt; [ 'templates' =&gt; 'e-mail-vorlagen', 'template_add' =&gt; 'vorlage hinzufgen', 'template_fileadd' =&gt; 'dateivorlage hinzufgen', 'template_edit' =&gt; 'vorlage bearbeiten', 'action' =&gt; 'aktion', 'email' =&gt; 'e-mail- &amp; dateivorlagen', 'subject' =&gt; 'betreff', 'mailbody' =&gt; 'mailtext', 'createcustomer' =&gt; 'willkommensmail fr neue kunden', 'pop_success' =&gt; 'willkommensmail fr neue e-mail-konten', 'template_replace_vars' =&gt; 'variablen, die den vorlagen ersetzt werden:', 'salutation' =&gt; 'wird mit einer korrekten anrede des kunden ersetzt.', 'firstname' =&gt; 'wird mit dem vornamen des kunden ersetzt.', 'name' =&gt; 'wird mit dem namen des kunden ersetzt.', 'company' =&gt; 'wird mit dem firmennamen des kunden ersetzt.', 'username' =&gt; 'wird mit dem benutzernamen des neuen kundenkontos ersetzt.', 'password' =&gt; 'wird mit dem passwort des neuen kundenkontos ersetzt.', 'email' =&gt; 'wird mit der adresse des neuen e-mail-kontos ersetzt.', 'customer_no' =&gt; 'wir mit der kunden-nummer ersetzt', 'traffic' =&gt; 'wird mit traffic, der dem kunden zugewiesen wurde, ersetzt.', 'trafficused' =&gt; 'wird mit traffic, der vom kunden bereits verbraucht wurde, ersetzt.', 'pop_success_alternative' =&gt; 'willkommensmail fr neue e-mail-konten fr die alternative e-mail-adresse', 'email_password' =&gt; 'wird mit dem passwort des neuen pop3/imap kontos ersetzt.', 'index_html' =&gt; 'index datei fr neu erzeugte kundenverzeichnisse', 'unconfigured_html' =&gt; 'index datei fr unkonfigurierte/unbekannte domains', 'unconfigured_content_fallback' =&gt; 'diese domain muss ber das froxlor-serververwaltungspanel konfiguriert werden, da sie derzeit keinem kunden zugewiesen ist.', 'file_extension' =&gt; [ 'description' =&gt; 'die dateiendung fr die index datei muss zwischen 1 und 6 zeichen lang sein und darf nur aus den zeichen a-z, a-z und 0-9 bestehen&lt;br&gt;&lt;br&gt;standard: html', 'title' =&gt; 'dateiendung fr datei vorlage', ], 'servername' =&gt; 'wird mit dem servernamen ersetzt.', 'customer' =&gt; 'wird mit dem loginnamen des kunden ersetzt. nur fr "index datei fr neu erzeugte kundenverzeichnisse".', 'admin' =&gt; 'wird mit dem loginnamen des admins ersetzt. nur fr "index datei fr neu erzeugte kundenverzeichnisse".', 'customer_email' =&gt; 'wird mit der e-mail-adresse des kunden ersetzt. nur fr "index datei fr neu erzeugte kundenverzeichnisse".', 'admin_email' =&gt; 'wird mit der e-mail-adresse des admin ersetzt. nur fr "index datei fr neu erzeugte kundenverzeichnisse".', 'filetemplates' =&gt; 'dateivorlagen', 'filecontent' =&gt; 'dateiinhalt', 'new_database_by_customer' =&gt; 'kunden-benachrichtigungs nach erstellung einer neuen datenbank', 'new_ftpaccount_by_customer' =&gt; 'kunden-benachrichtigung nach erstellung eines neuen ftp-benutzers', 'newdatabase' =&gt; 'benachrichtigungs-mails fr neue datenbank', 'newftpuser' =&gt; 'benachrichtigungs-mails fr neuen ftp-benutzer', 'cust_name' =&gt; 'kundenname', 'db_name' =&gt; 'datenbankname', 'db_pass' =&gt; 'datenbankpasswort', 'db_desc' =&gt; 'datenbankbeschreibung', 'db_srv' =&gt; 'datenbankserver', 'pma_uri' =&gt; 'url zu phpmyadmin (wenn angegeben)', 'usr_name' =&gt; 'ftp-benutzername', 'usr_pass' =&gt; 'ftp-passwort', 'usr_path' =&gt; 'ftp-heimatverzeichnis (relativ zum kunden-heimatverzeichnis)', 'forgotpwd' =&gt; 'benachrichtigungs-mails bei zurcksetzen des passworts', 'password_reset' =&gt; 'kunden-benachrichtigung nach zurcksetzen des passworts', 'trafficmaxpercent' =&gt; 'hinweismail fr kunden, wenn sie die angegebenen prozent des traffics verbraucht haben', 'max_percent' =&gt; 'wird mit dem webspace/traffic-limit, welches dem kunden zugewiesen wurde, ersetzt.', 'usage_percent' =&gt; 'wird mit dem webspace/traffic, welcher vom kunden bereits verbraucht wurde, ersetzt.', 'diskmaxpercent' =&gt; 'hinweismail fr kunden, wenn sie die angegebenen prozent des webspaces verbraucht haben', 'diskavailable' =&gt; 'wird mit dem webspace, der dem kunden zugewiesen wurde, ersetzt.', 'diskused' =&gt; 'wird mit dem webspace, welcher vom kunden bereits verbraucht wurde, ersetzt.', 'link' =&gt; 'wird mit dem link zum zurcksetzen des passworts ersetzt.', 'server_hostname' =&gt; 'wird mit dem system-hostname (url zu froxlor) ersetzt', 'server_ip' =&gt; 'wird mit der standard-system-ip-adresse ersetzt', 'server_port' =&gt; 'wird mit dem standard-port ersetzt', 'domainname' =&gt; 'wird mit der standardsubdomain des kunden ersetzt (kann leer sein, wenn keine erstellt werden soll)', ], 'createzonefile' =&gt; 'dns zone fr domain erstellen', 'custombindzone' =&gt; 'eigene / manuelle zone', 'bindzonewarning' =&gt; 'leer fr standardeinstellung.&lt;br /&gt;&lt;strong class="text-danger"&gt;warnung:&lt;/strong&gt; bei der verwendung einer zonendatei mssen alle bentigten records aller subdomains ebenfalls manuell verwaltet werden.', 'ipsandports' =&gt; [ 'ipsandports' =&gt; 'ips und ports', 'add' =&gt; 'ip-adresse/port hinzufgen', 'edit' =&gt; 'ip-adresse/port bearbeiten', 'ipandport' =&gt; 'ip-adresse/port', 'ip' =&gt; 'ip-adresse', 'ipnote' =&gt; '&lt;div id="ipnote" class="invalid-feedback"&gt;hinweis: obwohl private ip adressen erlaubt sind, kann es bei manchen features wie dns zu ungewolltem verhalten kommen.&lt;br&gt;verwende private adressen nur wenn du sicher bist.&lt;/div&gt;', 'port' =&gt; 'port', 'create_listen_statement' =&gt; 'erstelle listen-eintrag', 'create_namevirtualhost_statement' =&gt; 'erstelle namevirtualhost-eintrag', 'create_vhostcontainer' =&gt; 'erstelle vhost-container', 'create_vhostcontainer_servername_statement' =&gt; 'erstelle servername-eintrag im vhost-container', 'enable_ssl' =&gt; 'ist dies ein ssl-port?', 'ssl_cert_file' =&gt; 'pfad zum zertifikat', 'webserverdefaultconfig' =&gt; 'webserver-standard-konfiguration', 'webserverdomainconfig' =&gt; 'webserver-domain-konfiguration', 'webserverssldomainconfig' =&gt; 'webserver-ssl-konfiguration', 'ssl_key_file' =&gt; 'pfad zum ssl-private-key', 'ssl_ca_file' =&gt; 'pfad zum ssl-ca-zertifikat (optional)', 'default_vhostconf_domain' =&gt; 'standard vhost-einstellungen fr jeden domain-container', 'ssl_cert_chainfile' =&gt; [ 'title' =&gt; 'pfad zu dem ssl-certificatechainfile (optional)', 'description' =&gt; 'meist ca_bundle, o. . dies ist das feld, das gesetzt werden sollte, wenn ein gekauftes ssl-zertifikat vorliegt.', ], 'docroot' =&gt; [ 'title' =&gt; 'benutzerdefinierter docroot (wenn leer, zeige auf froxlor)', 'description' =&gt; 'hier kann ein benutzerdefinierter document-root (der zielordner fr einen zugriff) fr diese ip/port kombination gesetzt werden.&lt;br /&gt;&lt;strong&gt;achtung:&lt;/strong&gt; bitte berlege vorher, welchen pfad du hier angibst!', ], 'ssl_paste_description' =&gt; 'bitte den inhalt der zertifikatsdatei das textfeld kopieren.', 'ssl_cert_file_content' =&gt; 'inhalt des ssl-zertifikats (certificate)', 'ssl_key_file_content' =&gt; 'inhalt der key-datei (private-key)', 'ssl_ca_file_content' =&gt; 'inhalt der ssl-ca-datei (optional)', 'ssl_ca_file_content_desc' =&gt; '&lt;br /&gt;&lt;br /&gt;client authentifizierung, dieses feld sollte nur gesetzt werden, wenn es wirklich gebraucht wird.', 'ssl_cert_chainfile_content' =&gt; 'inhalt des ssl-certificatechainfile (optional)', 'ssl_cert_chainfile_content_desc' =&gt; '&lt;br /&gt;&lt;br /&gt;meist ca_bundle, o. . dies ist das feld, das gesetzt werden sollte, wenn ein gekauftes ssl-zertifikat vorliegt.', 'ssl_default_vhostconf_domain' =&gt; 'standard ssl vhost-einstellungen fr jeden domain-container', ], 'memorylimitdisabled' =&gt; 'deaktiviert', 'valuemandatory' =&gt; 'dieses feld muss ausgefllt werden.', 'valuemandatorycompany' =&gt; 'entweder "name" und "vorname" oder "firma" muss ausgefllt werden.', 'serversoftware' =&gt; 'webserver', 'phpversion' =&gt; 'php-version', 'mysqlserverversion' =&gt; 'mysql-server-version', 'webserverinterface' =&gt; 'webserver-interface', 'accountsettings' =&gt; 'konteneinstellungen', 'panelsettings' =&gt; 'panel-einstellungen', 'systemsettings' =&gt; 'systemeinstellungen', 'webserversettings' =&gt; 'webserver-einstellungen', 'mailserversettings' =&gt; 'mailserver-einstellungen', 'nameserversettings' =&gt; 'nameserver-einstellungen', 'updatecounters' =&gt; 'ressourcenverbrauch', 'subcanemaildomain' =&gt; [ 'never' =&gt; 'nie', 'choosableno' =&gt; 'whlbar, standardwert: nein', 'choosableyes' =&gt; 'whlbar, standardwert: ja', 'always' =&gt; 'immer', ], 'wipecleartextmailpwd' =&gt; 'klartext-passwrter leeren', 'webalizersettings' =&gt; 'webalizereinstellungen', 'webalizer' =&gt; [ 'normal' =&gt; 'normal', 'quiet' =&gt; 'leise', 'veryquiet' =&gt; 'keine ausgaben', ], 'domain_nocustomeraddingavailable' =&gt; 'es knnen derzeit keine domains angelegt werden. sie mssen zuerst einen kunden anlegen', 'loggersettings' =&gt; 'log-einstellungen', 'logger' =&gt; [ 'normal' =&gt; 'normal', 'paranoid' =&gt; 'paranoid', ], 'emaildomain' =&gt; 'e-mail-domain', 'email_only' =&gt; 'nur als e-mail-domain verwenden?', 'wwwserveralias' =&gt; 'einen "www." serveralias hinzufgen', 'subject' =&gt; 'betreff', 'recipient' =&gt; 'empfnger', 'message' =&gt; 'rundmail senden', 'text' =&gt; 'nachricht', 'sslsettings' =&gt; 'ssl-einstellungen', 'specialsettings_replacements' =&gt; 'die folgenden variablen knnen verwendet werden:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (wenn zutreffend)&lt;br/&gt;', 'antispam_settings' =&gt; 'antispam-einstellungen', 'caneditphpsettings' =&gt; 'kann php-bezogene domaineinstellungen vornehmen?', 'allips' =&gt; 'alle ip-adressen', 'awstatssettings' =&gt; 'awstats-einstellungen', 'domain_dns_settings' =&gt; 'domain-dns-einstellungen', 'activated' =&gt; 'aktiviert', 'statisticsettings' =&gt; 'statistik-einstellungen', 'or' =&gt; 'oder', 'sysload' =&gt; 'system-auslastung', 'noloadavailable' =&gt; 'nicht verfgbar', 'nouptimeavailable' =&gt; 'nicht verfgbar', 'nosubject' =&gt; '(kein betreff)', 'show_version_login' =&gt; [ 'title' =&gt; 'zeige froxlor version beim login', 'description' =&gt; 'zeige froxlor version der fuzeile der loginseite', ], 'show_version_footer' =&gt; [ 'title' =&gt; 'zeige froxlor version fuzeile', 'description' =&gt; 'zeige froxlor version der fuzeile aller anderen seiten', ], 'froxlor_graphic' =&gt; [ 'title' =&gt; 'grafik im kopfbereich des panels', 'description' =&gt; 'welche grafik soll im kopfbereich des panels anstatt des froxlor logos angezeigt werden?', ], 'phpsettings' =&gt; [ 'title' =&gt; 'php-konfiguration', 'description' =&gt; 'kurzbeschreibung', 'actions' =&gt; 'aktionen', 'activedomains' =&gt; 'in verwendung fr domain(s)', 'notused' =&gt; 'konfiguration wird nicht verwendet', 'editsettings' =&gt; 'php-konfiguration bearbeiten', 'addsettings' =&gt; 'php-konfiguration erstellen', 'viewsettings' =&gt; 'php-konfiguration ansehen', 'phpinisettings' =&gt; 'php.ini-einstellungen', 'addnew' =&gt; 'neue php konfiguration erstellen', 'binary' =&gt; 'php-binary', 'fpmdesc' =&gt; 'php-fpm config', 'file_extensions' =&gt; 'dateiendungen', 'file_extensions_note' =&gt; '(ohne punkt, durch leerzeichen getrennt)', 'enable_slowlog' =&gt; 'fpm-slowlog pro domain aktivieren', 'request_terminate_timeout' =&gt; 'request_terminate_timeout', 'request_slowlog_timeout' =&gt; 'request_slowlog_timeout', 'activephpconfigs' =&gt; 'in verwendung fr php-konfiguration(en)', 'pass_authorizationheader' =&gt; 'bergeben von http auth basic/digest-headern von apache php', ], 'misc' =&gt; 'sonstiges', 'fpmsettings' =&gt; [ 'addnew' =&gt; 'neue php version erstellen', 'edit' =&gt; 'php version bearbeiten', ], 'phpconfig' =&gt; [ 'template_replace_vars' =&gt; 'variablen, die den konfigurationen ersetzt werden', 'pear_dir' =&gt; 'wird mit dem globalen wert fr das include verzeichnis ersetzt.', 'open_basedir_c' =&gt; 'wird mit einem ; (semikolon) ersetzt, um open_basedir auszukommentieren/deaktivieren, wenn eingestellt.', 'open_basedir' =&gt; 'wird mit der open_basedir-einstellung der domain ersetzt.', 'tmp_dir' =&gt; 'wird mit der einstellung fr das temporre verzeichnis der domain ersetzt.', 'open_basedir_global' =&gt; 'wird mit der globalen einstellung des pfades ersetzt, der dem open_basedir hinzugefgt wird (siehe webserver einstellungen).', 'customer_email' =&gt; 'wird mit der e-mail-adresse des kunden ersetzt, dem die domain gehrt.', 'admin_email' =&gt; 'wird mit der e-mail-adresse des admins ersetzt, dem die domain gehrt.', 'domain' =&gt; 'wird mit der domain ersetzt.', 'customer' =&gt; 'wird mit dem loginnamen des kunden ersetzt, dem die domain gehrt.', 'admin' =&gt; 'wird mit dem loginnamen des admins ersetzt, dem die domain gehrt.', 'docroot' =&gt; 'wird mit dem heimatverzeichnis der domain ersetzt.', 'homedir' =&gt; 'wird mit dem heimatverzeichnis des kunden ersetzt.', ], 'know_what_youre_doing' =&gt; 'ndern sie diese einstellungen nur, wenn sie wissen sie tun!', 'security_settings' =&gt; 'sicherheitseinstellungen', 'expert_settings' =&gt; 'experteneinstellungen!', 'mod_fcgid_starter' =&gt; [ 'title' =&gt; 'php-prozesse fr diese domain (leer fr standardwert)', ], 'phpserversettings' =&gt; 'php-einstellungen', 'mod_fcgid_maxrequests' =&gt; [ 'title' =&gt; 'maximale php-requests fr diese domain (leer fr standardwert)', ], 'webserver' =&gt; 'webserver', 'spfsettings' =&gt; 'domain-spf-einstellungen', 'specialsettingsforsubdomains' =&gt; 'bernehme einstellungen fr alle subdomains (*.beispiel.de)', 'accountdata' =&gt; 'benutzerdaten', 'contactdata' =&gt; 'kontaktdaten', 'servicedata' =&gt; 'dienstleistungsdaten', 'newerversionavailable' =&gt; 'eine neuere version von froxlor wurde verffentlicht.', 'newerversiondetails' =&gt; 'jetzt auf version &lt;b&gt;%s&lt;/b&gt; aktualisieren?&lt;br/&gt;(aktuelle version ist: %s)', 'extractdownloadedzip' =&gt; 'heruntergeladenes archiv "%s" entpacken?', 'cron' =&gt; [ 'cronsettings' =&gt; 'cronjob-einstellungen', 'add' =&gt; 'cronjob hinzufgen', ], 'cronjob_edit' =&gt; 'cronjob bearbeiten', 'warning' =&gt; 'achtung - wichtiger hinweis!', 'lastlogin_succ' =&gt; 'letzte anmeldung', 'ftpserver' =&gt; 'ftp-server', 'ftpserversettings' =&gt; 'ftp-server-einstellungen', 'webserver_user' =&gt; 'benutzername webserver', 'webserver_group' =&gt; 'gruppenname webserver', 'perlenabled' =&gt; 'perl verfgbar', 'fcgid_settings' =&gt; 'fcgid', 'mod_fcgid_user' =&gt; 'lokaler benutzer fr fcgid (froxlor vhost)', 'mod_fcgid_group' =&gt; 'lokale gruppe fr fcgid (froxlor vhost)', 'perl_settings' =&gt; 'perl/cgi', 'notgiven' =&gt; '[nicht angegeben]', 'store_defaultindex' =&gt; 'standard-index-datei im kundenordner erstellen', 'phpfpm_settings' =&gt; 'php-fpm', 'traffic' =&gt; 'traffic', 'traffic_sub' =&gt; 'details der traffic-nutzung', 'customertraffic' =&gt; 'kunden', 'assignedmax' =&gt; 'zugewiesen / max.', 'usedmax' =&gt; 'benutzt / max.', 'used' =&gt; 'benutzt', 'speciallogwarning' =&gt; '&lt;div id="speciallogfilenote" class="invalid-feedback"&gt;achtung: durch diese einstellungen werden sie alle bisherige statistiken dieser domain verlieren.&lt;/div&gt;', 'speciallogfile' =&gt; [ 'title' =&gt; 'eigene log-datei', 'description' =&gt; 'aktivieren sie diese option, um fr diese domain eine eigene access-log datei zu erhalten', ], 'domain_editable' =&gt; [ 'title' =&gt; 'erlaube bearbeiten der domain', 'desc' =&gt; 'wenn ja, darf der kunde verschiedene einstellungen anpassen.&lt;br /&gt;wenn nein, darf nichts durch den kunden gendert werden.', ], 'writeaccesslog' =&gt; [ 'title' =&gt; 'zugriffslog schreiben', 'description' =&gt; 'aktiviere diese option, um fr diese domain eine access-log datei zu erhalten', ], 'writeerrorlog' =&gt; [ 'title' =&gt; 'fehlerlog schreiben', 'description' =&gt; 'aktiviere diese option, um fr diese domain eine error-log datei zu erhalten', ], 'phpfpm.ininote' =&gt; 'nicht alle gewnschten werte knnen der php-fpm-pool-konfiguration verwendet werden.', 'selectserveralias' =&gt; 'serveralias-angabe fr domain', 'selectserveralias_desc' =&gt; 'whlen sie hier, ob fr diese domain ein wildcard-eintrag (*.domain.tld), ein www-alias (www.domain.tld) oder gar kein alias angelegt werden soll.', 'show_news_feed' =&gt; [ 'title' =&gt; 'zeige newsfeed im admin-dashboard', 'description' =&gt; 'aktivieren sie diese option, um das offizielle froxlor newsfeed (https://inside.froxlor.org/news/) auf deinem dashboard anzuzeigen und verpasse keine wichtigen informationen oder release-announcements.', ], 'cronsettings' =&gt; 'cronjob-einstellungen', 'integritycheck' =&gt; 'datenbankprfung', 'integrityname' =&gt; 'name', 'integrityresult' =&gt; 'ergebnis', 'integrityfix' =&gt; 'probleme automatisch beheben', 'customer_show_news_feed' =&gt; 'zeige newsfeed im kunden-dashboard', 'customer_news_feed_url' =&gt; [ 'title' =&gt; 'benutzerdefiniertes rss-feed', 'description' =&gt; 'hier kann ein eigenes rss-feed angegeben werden, welches den kunden auf dem dashboard angezeigt wird.&lt;br /&gt;&lt;small&gt;leerlassen um das offizielle froxlor newsfeed (https://inside.froxlor.org/news/) zu verwenden.&lt;/small&gt;', ], 'movetoadmin' =&gt; 'kunde verschieben', 'movecustomertoadmin' =&gt; [ 'title' =&gt; 'verschiebe den kunden zum angegebenen admin/reseller', 'description' =&gt; 'leerlassen fr keine nderung.&lt;br /&gt;wird der gewnschte admin/reseller hier nicht aufgelistet, hat er sein kunden-kontigent erreicht.', ], 'note' =&gt; 'hinweis', 'mod_fcgid_umask' =&gt; [ 'title' =&gt; 'umask (standard: 022)', ], 'letsencrypt' =&gt; [ 'title' =&gt; 'ssl zertifikat erstellen (let\'s encrypt)', 'description' =&gt; 'holt ein kostenloses zertifikat von &lt;a href="https://letsencrypt.org"&gt;let\'s encrypt&lt;/a&gt;. das zertifikat wird automatisch erstellt und verlngert.&lt;br&gt;&lt;strong class="text-danger"&gt;achtung:&lt;/strong&gt; wenn wildcards aktiviert sind, wird diese option automatisch deaktiviert.', ], 'autoupdate' =&gt; 'auto-update', 'dnsenabled' =&gt; 'zugriff auf dns editor', 'froxlorvhost' =&gt; 'froxlor virtualhost einstellungen', 'hostname' =&gt; 'hostname', 'memory' =&gt; 'speicherauslastung', 'webserversettings_ssl' =&gt; 'webserver ssl-einstellungen', 'domain_hsts_maxage' =&gt; [ 'title' =&gt; 'http strict transport security (hsts)', 'description' =&gt; '"max-age" wert fr den strict-transport-security header&lt;br&gt;der wert &lt;i&gt;0&lt;/i&gt; deaktiviert hsts fr diese domain. meist wird der wert &lt;i&gt;31536000&lt;/i&gt; gerne genutzt (ein jahr).', ], 'domain_hsts_incsub' =&gt; [ 'title' =&gt; 'inkludiere hsts fr jede subdomain', 'description' =&gt; 'die optionale "includesubdomains" direktive, wenn vorhanden, signalisiert dem ua, dass die hsts regel fr diese domain und auch jede subdomain dieser gilt.', ], 'domain_hsts_preload' =&gt; [ 'title' =&gt; 'fge domain die hsts preload liste hinzu', 'description' =&gt; 'wenn die domain die &lt;a href="https://hstspreload.org/" target="_blank"&gt;hsts preload liste&lt;/a&gt;, verwaltet von chrome (und genutzt von firefox und safari), hinzugefgt werden soll, dann aktivieren sie diese einstellung.&lt;br&gt;die preload-direktive zu senden kann permantente konsequenzen haben und dazu fhren, dass benutzer auf diese domain und auch subdomains nicht zugreifen knnen.&lt;br&gt;beachten sie die details unter &lt;a href="https://hstspreload.org/#removal" target="_blank"&gt;https://hstspreload.org/#removal&lt;/a&gt; bevor ein header mit "preload" gesendet wird.', ], 'domain_ocsp_stapling' =&gt; [ 'title' =&gt; 'ocsp stapling', 'description' =&gt; 'siehe &lt;a target="_blank" href="https://de.wikipedia.org/wiki/online_certificate_status_protocol_stapling"&gt;wikipedia&lt;/a&gt; fr eine ausfhrliche beschreibung von ocsp-stapling', 'nginx_version_warning' =&gt; '&lt;br /&gt;&lt;strong class="text-danger"&gt;warnung:&lt;/strong&gt; nginx untersttzt ocsp-stapling erst ab version 1.3.7. wenn ihre version lter ist, wird der webserver bei aktiviertem ocsp-stapling nicht korrekt starten.', ], 'domain_http2' =&gt; [ 'title' =&gt; 'http2 untersttzung', 'description' =&gt; 'siehe &lt;a target="_blank" href="https://de.wikipedia.org/wiki/hypertext_transfer_protocol#http.2f2"&gt;wikipedia&lt;/a&gt; fr eine ausfhrliche beschreibung von http2', ], 'testmail' =&gt; 'smtp test', 'phpsettingsforsubdomains' =&gt; 'php-config fr alle subdomains bernehmen:', 'plans' =&gt; [ 'name' =&gt; 'plan name', 'description' =&gt; 'beschreibung', 'last_update' =&gt; 'zuletzt aktualisiert', 'plans' =&gt; 'hosting plne', 'plan_details' =&gt; 'plan details', 'add' =&gt; 'neuen plan anlegen', 'edit' =&gt; 'plan editieren', 'use_plan' =&gt; 'plan bernehmen', ], 'notryfiles' =&gt; [ 'title' =&gt; 'keine generierte try_files anweisung', 'description' =&gt; 'whlen sie "ja", wenn eine eigene try_files direktive den "eigenen vhost einstellungen" angegeben werden soll (z.b. ntig fr manche wordpress plugins).', ], 'logviewenabled' =&gt; 'zugriff auf access/error-logdateien', 'novhostcontainer' =&gt; '&lt;br&gt;&lt;br&gt;&lt;small class="text-danger"&gt;keine der ips und ports hat die option "erstelle vhost-container" aktiviert, einige einstellungen sind daher nicht verfgbar.&lt;/small&gt;', 'ownsslvhostsettings' =&gt; 'eigene ssl vhost-einstellungen', 'domain_override_tls' =&gt; 'berschreibe system tls einstellungen', 'domain_override_tls_addinfo' =&gt; '&lt;br /&gt;&lt;span class="text-danger"&gt;nur verwendet wenn "berschreibe system tls einstellungen" auf "ja" gestellt ist&lt;/span&gt;', 'domain_sslenabled' =&gt; 'aktiviere nutzung von ssl', 'domain_honorcipherorder' =&gt; 'bevorzuge die serverseitige cipher reihenfolge, standardwert &lt;strong&gt;nein&lt;/strong&gt;', 'domain_sessiontickets' =&gt; 'aktiviere tls sessiontickets (rfc 5077), standardwert &lt;strong&gt;ja&lt;/strong&gt;', 'domain_sessionticketsenabled' =&gt; [ 'title' =&gt; 'aktiviere nutzung von tls sessiontickets systemweit', 'description' =&gt; 'standardwert &lt;strong&gt;yes&lt;/strong&gt;&lt;br&gt;erfordert apache-2.4.11+ oder nginx-1.5.9+', ], 'domaindefaultalias' =&gt; 'standard serveralias-angabe fr neue domains', 'smtpsettings' =&gt; 'smtp einstellungen', 'smtptestaddr' =&gt; 'test-email senden an', 'smtptestnote' =&gt; 'bitte beachten: die untenstehenden werte reflektieren die aktuellen einstellungen und knnen auch nur dort angepasst werden (siehe link der oberen rechten ecke)', 'smtptestsend' =&gt; 'test-email senden', 'mysqlserver' =&gt; [ 'caption' =&gt; 'beschreibung', 'user' =&gt; 'privilegierter benutzer', 'add' =&gt; 'mysql server hinzufgen', 'edit' =&gt; 'mysql server bearbeiten', 'password' =&gt; 'passwort privilegierter benutzer', 'password_emptynochange' =&gt; 'neues passwort, leer fr keine nderung', 'allowall' =&gt; [ 'title' =&gt; 'nutzung fr aktuelle kunden automatisch erlauben', 'description' =&gt; 'ist diese einstellung aktiv, wird die verwendung dieses datenbank-servers automatisch allen aktuell existierenden kunden-accounts erlaubt. diese einstellung ist nicht permanent, kann aber mehrfach / nach bedarf ausgefhrt werden.', ], 'testconn' =&gt; 'teste verbindung beim speichern', 'ssl' =&gt; 'verwende ssl fr die verbindung zum datenbank-server', 'ssl_cert_file' =&gt; 'dateipfad zur ssl certificate authority', 'verify_ca' =&gt; 'aktiviere ssl zertifikats-verifikation', ], 'settings_importfile' =&gt; 'whle import-datei', 'documentation' =&gt; 'dokumentation', 'adminguide' =&gt; 'admin guide', 'userguide' =&gt; 'user guide', 'apiguide' =&gt; 'api guide', 'domain_duplicate' =&gt; 'domain duplizieren', 'domain_duplicate_named' =&gt; '%s duplizieren', 'emaildomainwarning' =&gt; '&lt;div id="emaildomainnote" class="invalid-feedback"&gt;achtung: durch die nderung dieser einstellung lschen sie alle bestehenden e-mail-adressen und -konten unwiderruflich.&lt;/div&gt;', ], 'apikeys' =&gt; [ 'no_api_keys' =&gt; 'keine api keys gefunden', 'key_add' =&gt; 'api key hinzufgen', 'apikey_removed' =&gt; 'der api key mit der id #%s wurde erfolgreich gelscht.', 'apikey_added' =&gt; 'der neue api key wurde erfolgreich angelegt.', 'clicktoview' =&gt; 'details anzeigen', 'allowed_from' =&gt; 'erlaube zugriff von', 'allowed_from_help' =&gt; 'komma getrennte liste von ips oder netzen.&lt;br&gt;standard ist leer (von berall erlaubt).', 'valid_until' =&gt; 'gltig bis', 'valid_until_help' =&gt; 'datum gltigkeitsende, format yyyy-mm-ddthh:mm', ], 'changepassword' =&gt; [ 'old_password' =&gt; 'altes passwort', 'new_password' =&gt; 'neues passwort', 'new_password_confirm' =&gt; 'neues passwort besttigen', 'new_password_ifnotempty' =&gt; 'neues passwort (leer fr keine nderung)', 'also_change_ftp' =&gt; 'auch passwort des haupt-ftp-zugangs ndern', 'also_change_stats' =&gt; ' auch passwort der statistikseite ndern', 'also_change_global_mysql' =&gt; 'auch passwort des globalen mysql-zugangs ndern', ], 'cron' =&gt; [ 'cronname' =&gt; 'cronjob-name', 'lastrun' =&gt; 'zuletzt gestartet', 'interval' =&gt; 'intervall', 'isactive' =&gt; 'aktiv', 'description' =&gt; 'beschreibung', 'changewarning' =&gt; 'nderungen diesen werten knnen einen negativen effekt auf das verhalten von froxlor und seinen automatisierten aufgaben haben.&lt;br /&gt;ndern sie hier bitte nur etwas, wenn sie sich ber die folgen im klaren sind.', ], 'crondesc' =&gt; [ 'cron_unknown_desc' =&gt; 'keine beschreibung angegeben', 'cron_tasks' =&gt; 'erstellen von konfigurationsdateien', 'cron_legacy' =&gt; 'legacy (alter) cronjob', 'cron_traffic' =&gt; 'traffic-berechnung', 'cron_usage_report' =&gt; 'webspace- und trafficreport', 'cron_mailboxsize' =&gt; 'berechnung der mailbox-gren', 'cron_letsencrypt' =&gt; 'aktualisierung der let\'s encrypt zertifikate', 'cron_export' =&gt; 'ausstehende datenexporte erstellen', 'cron_backup' =&gt; 'system- und kunden-sicherungen erstellen', ], 'cronjob' =&gt; [ 'cronjobsettings' =&gt; 'cronjob-einstellungen', 'cronjobintervalv' =&gt; 'laufzeit-intervall wert', 'cronjobinterval' =&gt; 'laufzeit-intervall', ], 'cronjobs' =&gt; [ 'notyetrun' =&gt; 'bisher nicht gestartet', ], 'cronmgmt' =&gt; [ 'minutes' =&gt; 'minuten', 'hours' =&gt; 'stunden', 'days' =&gt; 'tage', 'weeks' =&gt; 'wochen', 'months' =&gt; 'monate', ], 'customer' =&gt; [ 'documentroot' =&gt; 'heimatverzeichnis', 'name' =&gt; 'name', 'firstname' =&gt; 'vorname', 'lastname' =&gt; 'nachname', 'company' =&gt; 'firma', 'nameorcompany_desc' =&gt; 'entweder vorname/name oder firma ist erforderlich', 'street' =&gt; 'strae', 'zipcode' =&gt; 'plz', 'city' =&gt; 'ort', 'phone' =&gt; 'telefon', 'fax' =&gt; 'fax', 'email' =&gt; 'e-mail-adresse', 'customernumber' =&gt; 'kundennummer', 'diskspace' =&gt; 'webspace', 'traffic' =&gt; 'traffic', 'mysqls' =&gt; 'mysql-datenbanken', 'emails' =&gt; 'e-mail-adressen', 'accounts' =&gt; 'e-mail-konten', 'forwarders' =&gt; 'e-mail-weiterleitungen', 'ftps' =&gt; 'ftp-konten', 'subdomains' =&gt; 'subdomain(s)', 'domains' =&gt; 'domain(s)', 'title' =&gt; 'titel', 'country' =&gt; 'land', 'email_quota' =&gt; 'e-mail-kontingent', 'email_imap' =&gt; 'imap', 'email_pop3' =&gt; 'pop3', 'sendinfomail' =&gt; 'daten per e-mail mich senden', 'generated_pwd' =&gt; 'passwortvorschlag', 'usedmax' =&gt; 'benutzt / max.', 'services' =&gt; 'dienste', 'letsencrypt' =&gt; [ 'title' =&gt; 'ssl zertifikat erstellen (let\'s encrypt)', 'description' =&gt; 'holt ein kostenloses zertifikat von &lt;a href="https://letsencrypt.org"&gt;let\'s encrypt&lt;/a&gt;. das zertifikat wird automatisch erstellt und verlngert.', ], 'selectserveralias_addinfo' =&gt; 'diese option steht beim bearbeiten der domain zur verfgung. als initial-wert wird die einstellung der hauptdomain vererbt.', 'total_diskspace' =&gt; 'gesamtspeicherplatz', 'mysqlserver' =&gt; 'erlaubte mysql-server', ], 'diskquota' =&gt; 'quota', 'antispam' =&gt; [ 'config_file' =&gt; [ 'title' =&gt; 'antispam konfigurationsdatei', 'description' =&gt; 'pfad + dateiname der antispam-regel konfigurationsdatei', ], 'reload_command' =&gt; [ 'title' =&gt; 'milter-restart-befehl', 'description' =&gt; 'wie lautet der befehl zum neustarten des rspamd-dienstes?', ], 'activated' =&gt; [ 'title' =&gt; 'antispam aktivieren?', 'description' =&gt; 'aktivieren, um rspamd als antispam dienst zu verwenden.', ], 'dkim_keylength' =&gt; [ 'title' =&gt; 'dkim schlssel-lnge', 'description' =&gt; 'achtung: nderungen sind nur fr neue schlssel gltig.&lt;br/&gt;&lt;br/&gt;erfordert einen speziellen dns eintrag fr die domain. wenn das nameserver-feature nicht genutzt wird, muss dieser eintrag manuell verwaltet werden.', ], 'spam_tag_level' =&gt; [ 'title' =&gt; 'spam level', 'description' =&gt; 'erforderliche punktzahl zum markieren einer e-mail als spam&lt;br/&gt;standard: 7.0' ], 'rewrite_subject' =&gt; [ 'title' =&gt; 'betreff ndern', 'description' =&gt; 'dem e-mail betreff &lt;strong&gt;***spam***&lt;/strong&gt; hinzufgen, sofern zutreffend', ], 'spam_kill_level' =&gt; [ 'title' =&gt; 'ablehnungs level', 'description' =&gt; 'erforderliche punktzahl fr das ablehnen einer e-mail&lt;br/&gt;standard: 14.0' ], 'bypass_spam' =&gt; [ 'title' =&gt; 'spamfilter umgehen', 'description' =&gt; 'aktivieren, um den spamfilter fr diese adresse zu umgehen/deaktivieren.&lt;br/&gt;standard: nein' ], 'policy_greylist' =&gt; [ 'title' =&gt; 'verwende greylisting', 'description' =&gt; 'eingehende e-mails mittels &lt;a href="https://de.wikipedia.org/wiki/greylisting" target="_blank"&gt;greylisting&lt;/a&gt; schtzen.&lt;br/&gt;standard: ja' ], 'required_spf_dns' =&gt; 'erforderlicher spf dns eintrag', 'required_dmarc_dns' =&gt; 'erforderlicher dmarc dns eintrag', 'required_dkim_dns' =&gt; 'erforderlicher dkim dns eintrag', 'default_select' =&gt; [ 'on_changeable' =&gt; 'aktiviert, einstellbar', 'off_changeable' =&gt; 'deaktiviert, einstellbar', 'on_unchangeable' =&gt; 'aktiviert, nicht einstellbar', 'off_unchangeable' =&gt; 'deaktiviert, nicht einstellbar', ], 'default_bypass_spam' =&gt; [ 'title' =&gt; 'standardwert: spamfilter umgehen', 'description' =&gt; 'whlen, ob bei neuen e-mail-konten "spamfilter umgehen" standardmig aktiviert ist und ob diese einstellung vom kunden angepasst werden kann.&lt;br/&gt;standard: deaktiviert, einstellbar' ], 'default_spam_rewrite_subject' =&gt; [ 'title' =&gt; 'standardwert: betreff ndern', 'description' =&gt; 'whlen, ob bei neuen e-mail-konten "betreff ndern" standardmig aktiviert ist und ob diese einstellung vom kunden angepasst werden kann.&lt;br/&gt;standard: aktiviert, einstellbar' ], 'default_policy_greylist' =&gt; [ 'title' =&gt; 'standardwert: verwende greylisting', 'description' =&gt; 'whlen, ob bei neuen e-mail-konten "verwende greylisting" standardmig aktiviert ist und ob diese einstellung vom kunden angepasst werden kann.&lt;br/&gt;standard: aktiviert, einstellbar' ], ], 'dns' =&gt; [ 'destinationip' =&gt; 'domain-ip-adresse(n)', 'standardip' =&gt; 'server-standard-ip-adresse', 'a_record' =&gt; 'a-eintrag (ipv6 optional)', 'cname_record' =&gt; 'cname-eintrag', 'mxrecords' =&gt; 'mx eintrge definieren', 'standardmx' =&gt; 'server standard mx eintrag', 'mxconfig' =&gt; 'eigene mx eintrge', 'priority10' =&gt; 'prioritt 10', 'priority20' =&gt; 'prioritt 20', 'txtrecords' =&gt; 'txt-eintrge definieren', 'txtexample' =&gt; 'beispiel (spf-eintrag):&lt;br /&gt;v=spf1 ip4:xxx.xxx.xx.0/23 -all', 'howitworks' =&gt; 'hier knnen dns eintrge fr die domain verwaltet werden. beachten sie, dass froxlor automatisch ns/mx/a/aaaa eintrge generiert. die benutzerdefinierten eintrge werden bevorzugt, nur fehlende eintrge werden automatisch generiert.', ], 'dnseditor' =&gt; [ 'edit' =&gt; 'dns editieren', 'records' =&gt; 'eintrge', ], 'domain' =&gt; [ 'openbasedirpath' =&gt; 'openbasedir-pfad', 'inherited' =&gt; 'gleich wie elterndomain', 'docroot' =&gt; 'oben angegebener pfad', 'homedir' =&gt; 'heimverzeichnis', 'docparent' =&gt; 'elternverzeichnis des oben angegebenen pfads', ], 'domains' =&gt; [ 'description' =&gt; 'hier knnen sie (sub-)domains erstellen und deren pfade ndern.&lt;br /&gt;nach jeder nderung braucht das system etwas zeit, um die konfiguration neu einzulesen.', 'domainsettings' =&gt; 'domaineinstellungen', 'domainname' =&gt; 'domainname', 'subdomain_add' =&gt; 'subdomain anlegen', 'subdomain_edit' =&gt; '(sub-)domain bearbeiten', 'wildcarddomain' =&gt; 'als wildcarddomain eintragen?', 'aliasdomain' =&gt; 'alias fr domain', 'noaliasdomain' =&gt; 'keine aliasdomain', 'hasaliasdomains' =&gt; 'hat aliasdomain(s)', 'statstics' =&gt; 'statistiken', 'isassigneddomain' =&gt; 'zugewiesene domain', 'add_date' =&gt; 'zu froxlor hinzugefgt', 'registration_date' =&gt; 'registriert am', 'topleveldomain' =&gt; 'top-level-domain', 'associated_with_domain' =&gt; 'verbunden mit', 'aliasdomains' =&gt; 'aliasdomains', 'redirectifpathisurl' =&gt; 'redirect-code (standard: leer)', 'redirectifpathisurlinfo' =&gt; 'der redirect-code kann gewhlt werden, wenn der eingegebene pfad eine url ist.&lt;br/&gt;&lt;strong class="text-danger"&gt;hinweis:&lt;/strong&gt; nderungen werden nur wirksam wenn der pfad eine url ist.', 'ipandport_multi' =&gt; [ 'title' =&gt; 'ip-adresse(n)', 'description' =&gt; 'definieren sie eine oder mehrere ip-adresse(n) fr diese domain.&lt;br /&gt;&lt;br /&gt;&lt;div class="text-danger"&gt;hinweis: die ip-adressen knnen nicht gendert werden, sollte die domain als &lt;strong&gt;alias-domain&lt;/strong&gt; fr eine andere domain konfiguriert worden sein.&lt;/div&gt;', ], 'ipandport_ssl_multi' =&gt; [ 'title' =&gt; 'ssl-ip-adresse(n)', ], 'ssl_redirect' =&gt; [ 'title' =&gt; 'ssl-weiterleitung', 'description' =&gt; 'diese option erstellt fr alle nicht-ssl-vhosts eine weiterleitung (redirect), dass alle anfragen den ssl-vhost bermittelt werden (z. b. wrde eine anfrage &lt;strong&gt;http&lt;/strong&gt;://domain.tld/ weitergeleitet werden zu &lt;strong&gt;https&lt;/strong&gt;://domain.tld/).', ], 'serveraliasoption_wildcard' =&gt; 'wildcard (*.domain.tld)', 'serveraliasoption_www' =&gt; 'www (www.domain.tld)', 'serveraliasoption_none' =&gt; 'kein alias', 'domain_import' =&gt; 'domains importieren', 'import_separator' =&gt; 'trennzeichen', 'import_offset' =&gt; 'versatz (offset)', 'import_file' =&gt; 'csv-datei', 'import_description' =&gt; 'detaillierte informationen ber den aufbau der importdatei und einen erfolgreichen import gibt es hier: &lt;a href="https://docs.froxlor.org/latest/admin-guide/domain-import/" target="_blank" class="alert-link"&gt;https://docs.froxlor.org/latest/admin-guide/domain-import/&lt;/a&gt; (englisch)', 'ssl_redirect_temporarilydisabled' =&gt; '&lt;br&gt;die ssl-umleitung ist, whrend ein neues let\'s encrypt - zertifikat erstellt wird, temporr deaktiviert. die umleitung wird nach der zertifikatserstellung wieder aktiviert.', 'termination_date' =&gt; 'kndigungsdatum', 'termination_date_overview' =&gt; 'gekndigt zum ', 'ssl_certificates' =&gt; 'ssl zertifikate', 'ssl_certificate_removed' =&gt; 'das zertifikat mit der id #%s wurde erfolgreich gelscht.', 'ssl_certificate_error' =&gt; 'fehler beim lesen des zertifikats fr die domain: %s', 'no_ssl_certificates' =&gt; 'es wurden keine ssl-zertifikate gefunden', 'isaliasdomainof' =&gt; 'ist aliasdomain fr %s', 'isbinddomain' =&gt; 'erstelle dns-zone', 'dkimenabled' =&gt; 'dkim aktiviert', 'openbasedirenabled' =&gt; 'openbasedir einschrnkung', 'hsts' =&gt; 'hsts aktiviert', 'aliasdomainid' =&gt; 'id der alias-domain', 'nodomainsassignedbyadmin' =&gt; 'diesem account wurde noch keine (aktive) domain zugewiesen. bitte kontaktiere deinen administrator, wenn du der meinung bist, das ist nicht korrekt.', 'email_only' =&gt; 'nur e-mail', ], 'emails' =&gt; [ 'description' =&gt; 'hier knnen sie ihre e-mail-adressen einrichten.&lt;br /&gt;ein konto ist wie ihr briefkasten vor der haustr. wenn jemand eine e-mail sie schreibt, wird diese dieses konto gelegt.&lt;br /&gt;&lt;br /&gt;die zugangsdaten lauten wie folgt: (die angaben &lt;i&gt;kursiver&lt;/i&gt; schrift sind durch die jeweiligen eintrge zu ersetzen)&lt;br /&gt;&lt;br /&gt;hostname: &lt;b&gt;&lt;i&gt;domainname&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;benutzername: &lt;b&gt;&lt;i&gt;kontoname / e-mail-adresse&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;passwort: &lt;b&gt;&lt;i&gt;das gewhlte passwort&lt;/i&gt;&lt;/b&gt;', 'emailaddress' =&gt; 'e-mail-adresse', 'emails_add' =&gt; 'e-mail-adresse anlegen', 'emails_edit' =&gt; 'e-mail-adresse ndern', 'catchall' =&gt; 'catchall', 'iscatchall' =&gt; 'als catchall-adresse definieren?', 'account' =&gt; 'konto', 'account_add' =&gt; 'konto anlegen', 'account_delete' =&gt; 'konto lschen', 'from' =&gt; 'von', 'to' =&gt; 'nach', 'forwarders' =&gt; 'weiterleitungen', 'forwarder_add' =&gt; 'weiterleitung hinzufgen', 'alternative_emailaddress' =&gt; 'alternative e-mail-adresse', 'quota' =&gt; 'kontingent', 'noquota' =&gt; 'kein kontingent', 'updatequota' =&gt; 'update kontingent', 'quota_edit' =&gt; 'e-mail-kontingent ndern', 'noemaildomainaddedyet' =&gt; 'sie haben bisher noch keine (e-mail-)domain ihrem konto.', 'back_to_overview' =&gt; 'zurck zur domain-bersicht', 'accounts' =&gt; 'konten', 'emails' =&gt; 'adressen', ], 'error' =&gt; [ 'error' =&gt; 'fehlermeldung', 'directorymustexist' =&gt; 'das verzeichnis "%s" muss existieren. legen sie es bitte mit ihrem ftp-programm an.', 'filemustexist' =&gt; 'die datei "%s" muss existieren.', 'allresourcesused' =&gt; 'sie haben bereits alle ihnen zur verfgung stehenden ressourcen verbraucht.', 'domains_cantdeletemaindomain' =&gt; 'sie knnen keine zugewiesene domain lschen. ', 'domains_canteditdomain' =&gt; 'sie knnen diese domain nicht bearbeiten. dies wurde durch den admin verweigert.', 'domains_cantdeletedomainwithemail' =&gt; 'sie knnen keine domain lschen, die noch als e-mail-domain verwendet wird. lschen sie zuerst alle e-mail-adressen dieser domain.', 'firstdeleteallsubdomains' =&gt; 'sie mssen zuerst alle subdomains lschen, bevor sie eine wildcarddomain anlegen knnen.', 'youhavealreadyacatchallforthisdomain' =&gt; 'sie haben bereits eine e-mail-adresse als catchall fr diese domain definiert.', 'ftp_cantdeletemainaccount' =&gt; 'sie knnen ihren hauptaccount nicht lschen.', 'login' =&gt; 'die kombination aus benutzername und passwort ist ungltig.', 'login_blocked' =&gt; 'dieser account wurde aufgrund zu vieler fehlversuche vorbergehend geschlossen.&lt;br /&gt;bitte versuchen sie es "%s" sekunden erneut.', 'notallreqfieldsorerrors' =&gt; 'sie haben nicht alle felder bzw. ein feld mit fehlerhaften angaben ausgefllt.', 'oldpasswordnotcorrect' =&gt; 'das alte passwort ist nicht korrekt.', 'youcantallocatemorethanyouhave' =&gt; 'sie knnen nicht mehr ressourcen verteilen als ihnen noch zur verfgung stehen.', 'mustbeurl' =&gt; 'sie mssen eine vollstndige url angeben (z. b. http://domain.de/error404.htm).', 'invalidpath' =&gt; 'sie haben keine gltige url angegeben (evtl. probleme beim verzeichnislisting?).', 'stringisempty' =&gt; 'fehlende eingabe im feld', 'stringiswrong' =&gt; 'falsche eingabe im feld', 'newpasswordconfirmerror' =&gt; 'das neue passwort und dessen besttigung sind nicht identisch.', 'mydomain' =&gt; '\'domain\'', 'mydocumentroot' =&gt; '\'documentroot\'', 'loginnameexists' =&gt; 'der login-name "%s" existiert bereits.', 'emailiswrong' =&gt; 'die e-mail-adresse "%s" enthlt ungltige zeichen oder ist nicht vollstndig.', 'emailexists' =&gt; 'die e-mail-adresse "%s" wird bereits von einem anderen admin verwendet', 'emailexistsanon' =&gt; 'die e-mail-adresse "%s" wird bereits verwendet', 'alternativeemailiswrong' =&gt; 'die angegebene alternative e-mail adresse "%s", welche die zugangsdaten geschickt werden soll, scheint ungltig zu sein.', 'loginnameiswrong' =&gt; 'der login-name "%s" enthlt ungltige zeichen.', 'loginnameiswrong2' =&gt; 'der login-name enthlt zu viele zeichen, es sind maximal %s zeichen erlaubt.', 'userpathcombinationdupe' =&gt; 'die kombination aus benutzername und pfad existiert bereits.', 'patherror' =&gt; 'allgemeiner fehler! pfad darf nicht leer sein.', 'errordocpathdupe' =&gt; 'option fr pfad "%s" existiert bereits.', 'adduserfirst' =&gt; 'sie mssen zuerst einen kunden anlegen.', 'domainalreadyexists' =&gt; 'die domain "%s" wurde bereits einem kunden zugeordnet.', 'nolanguageselect' =&gt; 'es wurde keine sprache ausgewhlt.', 'nosubjectcreate' =&gt; 'sie mssen einen betreff angeben.', 'nomailbodycreate' =&gt; 'sie mssen einen e-mail-text eingeben.', 'templatenotfound' =&gt; 'vorlage wurde nicht gefunden.', 'alltemplatesdefined' =&gt; 'sie knnen keine weiteren vorlagen anlegen, da bereits fr alle sprachen eine vorlage existiert.', 'wwwnotallowed' =&gt; 'ihre subdomain darf nicht \'www\' heien.', 'subdomainiswrong' =&gt; 'die subdomain "%s" enthlt ungltige zeichen.', 'domaincantbeempty' =&gt; 'der domainname darf nicht leer sein.', 'domainexistalready' =&gt; 'die domain "%s" existiert bereits.', 'domainisaliasorothercustomer' =&gt; 'die ausgewhlte aliasdomain ist entweder selbst eine aliasdomain, hat nicht die gleiche ip/port-kombination oder gehrt einem anderen kunden.', 'emailexistalready' =&gt; 'die e-mail-adresse "%s" existiert bereits.', 'maindomainnonexist' =&gt; 'die hauptdomain "%s" existiert nicht.', 'maindomaindeactivated' =&gt; 'die hauptdomain "%s" ist deaktiviert.', 'destinationnonexist' =&gt; 'bitte geben sie ihre weiterleitungsadresse im feld \'nach\' ein.', 'destinationalreadyexistasmail' =&gt; 'die weiterleitung zu "%s" existiert bereits als aktive e-mail-adresse.', 'destinationalreadyexist' =&gt; 'es existiert bereits eine weiterleitung nach "%s".', 'destinationiswrong' =&gt; 'die weiterleitungsadresse "%s" enthlt ungltige zeichen oder ist nicht vollstndig.', 'dumpfoldercannotbedocroot' =&gt; 'der ordner fr daten-export darf nicht das heimatverzeichnis sein, whlen sie einen ordner unterhalb des heimatverzeichnisses, z.b. /dumps', 'templatelanguagecombodefined' =&gt; 'die gewhlte kombination aus sprache und vorlage ist bereits definiert.', 'templatelanguageinvalid' =&gt; 'die gewhlte sprache existiert nicht', 'ipstillhasdomains' =&gt; 'die ip/port-kombination, die sie lschen wollen, ist noch bei einer oder mehreren domains eingetragen. bitte ndern sie die domains vorher auf eine andere ip/port-kombination, um diese lschen zu knnen.', 'cantdeletedefaultip' =&gt; 'sie knnen die standard-ip/port-kombination fr reseller nicht lschen. bitte setzen sie eine andere ip/port-kombination als standard, um diese lschen zu knnen.', 'cantdeletesystemip' =&gt; 'sie knnen die letzte system-ip-adresse nicht lschen. entweder legen sie eine neue ip/port-kombination oder sie ndern die system-ip-adresse.', 'myipaddress' =&gt; '\'ip-adresse\'', 'myport' =&gt; '\'port\'', 'myipdefault' =&gt; 'sie mssen eine ip/port-kombination auswhlen, die den standard definieren soll.', 'myipnotdouble' =&gt; 'diese kombination aus ip-adresse und port existiert bereits.', 'cantchangesystemip' =&gt; 'sie knnen die letzte system-ip-adresse nicht lschen. entweder legen sie eine neue ip/port-kombination oder sie ndern die system-ip-adresse.', 'sessiontimeoutiswrong' =&gt; '"session-timeout" muss ein numerischer wert sein.', 'maxloginattemptsiswrong' =&gt; '"maximale loginversuche" muss ein numerischer wert sein.', 'deactivatetimiswrong' =&gt; '"lnge der deaktivierung" muss numerisch sein.', 'accountprefixiswrong' =&gt; 'das "kundenprfix" ist falsch.', 'mysqlprefixiswrong' =&gt; 'das "mysql-prfix" ist falsch.', 'ftpprefixiswrong' =&gt; 'das "ftp-prfix" ist falsch.', 'ipiswrong' =&gt; 'die "ip-adresse" ist falsch. bitte geben sie eine gltige ip-adresse an.', 'vmailuidiswrong' =&gt; 'die "mail-uid" ist falsch. es ist nur eine numerische uid erlaubt.', 'vmailgidiswrong' =&gt; 'die "mail-gid" ist falsch. es ist nur eine numerische gid erlaubt.', 'adminmailiswrong' =&gt; 'die "absenderadresse" ist fehlerhaft. bitte geben sie eine gltige e-mail-adresse an.', 'pagingiswrong' =&gt; 'die "eintrge pro seite"-einstellung ist falsch. es sind nur numerische zeichen erlaubt.', 'phpmyadminiswrong' =&gt; 'die "phpmyadmin-url" ist keine gltige url.', 'webmailiswrong' =&gt; 'die "webmail-url" ist keine gltige url.', 'webftpiswrong' =&gt; 'die "webftp-url" ist keine gltige url.', 'stringformaterror' =&gt; 'der wert des feldes "%s" hat nicht das erwartete format.', 'loginnameisusingprefix' =&gt; 'sie knnen keinen account anlegen, der mit "%s" beginnt, da dieser prefix fr die automatische namensvergabe eingestellt ist. bitte whlen sie einen anderen accountnamen.', 'loginnameissystemaccount' =&gt; 'der account "%s" existiert bereits auf dem system und kann daher nicht verwendet werden. bitte whlen sie einen anderen accountnamen.', 'loginnameisreservedname' =&gt; 'der account-name "%s" ist systemseitig reserviert und kann nicht verwenden werden.', 'youcantdeleteyourself' =&gt; 'aus sicherheitsgrnden knnen sie sich nicht selbst lschen.', 'youcanteditallfieldsofyourself' =&gt; 'hinweis: aus sicherheitsgrnden knnen sie nicht alle felder ihres eigenen accounts bearbeiten.', 'documentrootexists' =&gt; 'es existiert noch ein verzeichnis "%s" fr diesen kunden. bitte lschen sie dieses vorher.', 'norepymailiswrong' =&gt; 'die "noreply-adresse" ist ungltig. nur eine valide e-mail adresse kann akzeptiert werden.', 'logerror' =&gt; 'log-fehler: "%s"', 'nomessagetosend' =&gt; 'keine nachricht angegeben', 'norecipientsgiven' =&gt; 'keine empfnger angegeben', 'errorsendingmail' =&gt; 'das versenden der nachricht "%s" schlug fehl.', 'errorsendingmailpub' =&gt; 'das versenden der nachricht die angegebene e-mail adresse schlug fehl.', 'cannotreaddir' =&gt; 'der ordner "%s" kann nicht gelesen werden', 'invalidip' =&gt; 'ungltige ip-adresse: "%s"', 'invalidmysqlhost' =&gt; 'ungltige mysql-host-adresse: "%s"', 'cannotuseawstatsandwebalizeratonetime' =&gt; 'webalizer und awstats knnen nicht zur gleichen zeit aktiviert werden, bitte whlen sie eines aus.', 'cannotwritetologfile' =&gt; 'logdatei "%s" konnte nicht fr schreiboperationen geffnet werden.', 'vmailquotawrong' =&gt; 'die kontingent-gre muss positiv sein.', 'allocatetoomuchquota' =&gt; 'sie versuchen "%s" mb kontingent zu zuweisen, haben aber nicht genug brig.', 'missingfields' =&gt; 'es wurden nicht alle felder augefllt.', 'requiredfield' =&gt; 'dieses feld ist ein pflichtfeld.', 'accountnotexisting' =&gt; 'der angegebene e-mail-account existiert nicht.', 'nopermissionsorinvalidid' =&gt; 'entweder fehlen ihnen die ntigen rechte diese einstellung zu ndern oder es wurde eine ungltige id bergeben', 'phpsettingidwrong' =&gt; 'eine php-konfiguration mit dieser id existiert nicht', 'descriptioninvalid' =&gt; 'der beschreibungstext ist zu kurz, zu lang oder enthlt ungltige zeichen', 'info' =&gt; 'info', 'filecontentnotset' =&gt; 'diese datei darf nicht leer sein!', 'customerdoesntexist' =&gt; 'der ausgewhlte kunde existiert nicht.', 'admindoesntexist' =&gt; 'der ausgewhlte admin existiert nicht.', 'ipportdoesntexist' =&gt; 'die gewhlte ip/port-kombination existiert nicht.', 'hiddenfieldvaluechanged' =&gt; 'der wert des verborgenen feldes "%s" hat sich whrend dem ndern der einstellungen gendert.&lt;br /&gt;&lt;br /&gt;dies ist im grunde kein schwerwiegendes problem, allerdings konnten die einstellungen nicht gespeichert werden.', 'notrequiredpasswordlength' =&gt; 'das passwort ist zu kurz. bitte geben sie mindestens "%s" zeichen an.', 'overviewsettingoptionisnotavalidfield' =&gt; 'hoppla, ein feld, das als option der konfigurationsbersicht angezeigt werden soll, hat nicht den erwarteten wert. sie knnen den entwicklern die schuld geben. dies sollte nicht passieren!', 'usernamealreadyexists' =&gt; 'der benutzername "%s" existiert bereits.', 'plausibilitychecknotunderstood' =&gt; 'die antwort des plausibilittschecks wurde nicht verstanden', 'errorwhensaving' =&gt; 'bei dem speichern des feldes "%s" trat ein fehler auf', 'pathmaynotcontaincolon' =&gt; 'der eingegebene pfad sollte keinen doppelpunkt (":") enthalten. bitte geben sie einen korrekten wert fr den pfad ein.', 'notrequiredpasswordcomplexity' =&gt; 'die vorgegebene passwort-komplexitt wurde nicht erfllt.&lt;br /&gt;bitte kontaktieren sie ihren administrator, wenn sie fragen zur komplexitts-vorgabe haben.', 'stringerrordocumentnotvalidforlighty' =&gt; 'ein text als fehlerdokument funktioniert leider lighttpd nicht, bitte geben sie einen pfad zu einer datei an', 'urlerrordocumentnotvalidforlighty' =&gt; 'eine url als fehlerdokument funktioniert leider lighttpd nicht, bitte geben sie einen pfad zu einer datei an', 'invaliderrordocumentvalue' =&gt; 'der angegebene wert fr das fehlederdokument ist keine gltige datei, url oder text-zeile.', 'intvaluetoolow' =&gt; 'die angegebene zahl ist zu klein (feld "%s")', 'intvaluetoohigh' =&gt; 'die angegebene zahl ist zu gro (feld "%s")', 'phpfpmstillenabled' =&gt; 'php-fpm ist derzeit aktiviert. bitte deaktivieren sie es, um fcgid zu aktivieren', 'fcgidstillenabled' =&gt; 'fcgid ist derzeit aktiviert. bitte deaktivieren sie es, um php-fpm zu aktivieren', 'domains_cantdeletedomainwithaliases' =&gt; 'sie knnen keine domain lschen, die noch von alias-domains verwendet wird. lschen sie zuerst alle alias-domains dieser domain.', 'user_banned' =&gt; 'ihr benutzerkonto wurde gesperrt. bitte kontaktieren sie ihren administrator fr weitere informationen.', 'admin_domain_emailsystemhostname' =&gt; 'der system-hostname kann nicht als kundendomain verwendet werden.', 'session_timeout' =&gt; 'wert zu niedrig', 'session_timeout_desc' =&gt; 'der wert der session-timeout sollte nicht unter einer minute liegen.', 'invalidhostname' =&gt; 'hostname muss eine gltige domain sein. er darf weder leer sein noch nur aus leerzeichen bestehen', 'operationnotpermitted' =&gt; 'diese aktion ist nicht erlaubt!', 'featureisdisabled' =&gt; 'die funktion "%s" wurde deaktiviert. kontaktieren sie bitte ihren dienstleister.', 'usercurrentlydeactivated' =&gt; 'der benutzer "%s" ist derzeit deaktiviert', 'setlessthanalreadyused' =&gt; 'es knnen nicht weniger resourcen von "%s" gesetzt werden, als der benutzer bereits vergeben hat&lt;br /&gt;', 'stringmustntbeempty' =&gt; 'der wert fr das feld "%s" darf nicht leer sein', 'sslcertificateismissingprivatekey' =&gt; 'fr das zertifikat muss eine key-datei (private-key) angegeben werden.', 'sslcertificatewrongdomain' =&gt; 'das angegebene zertifikat gilt nicht fr die gewhlte domain.', 'sslcertificateinvalidcert' =&gt; 'der angegebene zertifikatsinhalt scheint kein gltiges zertifikat zu sein.', 'sslcertificateinvalidcertkeypair' =&gt; 'der angegebene key (private-key) gehrt nicht zum angegebenen zertifikat.', 'sslcertificateinvalidca' =&gt; 'das angegebene ca-zertifikat scheint nicht gltig zu sein.', 'sslcertificateinvalidchain' =&gt; 'das angegebene certificatechainfile scheint nicht gltig zu sein.', 'givendirnotallowed' =&gt; 'das angegebene verzeichnis im feld %s ist nicht erlaubt.', 'sslredirectonlypossiblewithsslipport' =&gt; 'die nutzung von let\'s encrypt ist nur mglich, wenn die domain mindestens eine ip/port - kombination mit aktiviertem ssl zugewiesen hat.', 'fcgidstillenableddeadlock' =&gt; 'fcgid ist derzeit aktiviert.&lt;br /&gt;bitte deaktiviere es, um einen anderen webserver als apache2 oder lighttpd auswhlen zu knnen.', 'send_report_title' =&gt; 'fehler melden', 'send_report_desc' =&gt; 'danke, dass sie uns diesen fehler melden und damit helfen froxlor zu verbessern.&lt;br /&gt;folgender bericht wird per mail das froxlor entwickler team gesendet.', 'send_report' =&gt; 'fehlerbericht senden', 'send_report_error' =&gt; 'fehler beim senden des berichts: &lt;br /&gt;%s', 'notallowedtouseaccounts' =&gt; 'ihrem konto ist die nutzung von imap/pop3 nicht erlaubt, daher knnen keine e-mail-konten angelegt werden', 'cannotdeletehostnamephpconfig' =&gt; 'diese php-konfiguration ist dem froxlor-vhost zugewiesen und kann daher nicht gelscht werden.', 'cannotdeletedefaultphpconfig' =&gt; 'diese php-konfiguration ist als standard hinterlegt und kann daher nicht gelscht werden.', 'passwordshouldnotbeusername' =&gt; 'das passwort sollte nicht mit dem benutzernamen bereinstimmen.', 'no_phpinfo' =&gt; 'entschuldigung, es ist nicht mglich die phpinfo() auszulesen.', 'moveofcustomerfailed' =&gt; 'das verschieben des kunden ist fehlgeschlagen. alle brigen nderungen wurden durchgefhrt und gespeichert.&lt;br&gt;&lt;br&gt;fehlermeldung: %s', 'domain_import_error' =&gt; 'der folgende fehler trat beim importieren der domains auf: %s', 'fcgidandphpfpmnogoodtogether' =&gt; 'fcgid und php-fpm knnen nicht gleichzeitig aktiviert werden.', 'no_apcuinfo' =&gt; 'keine apcu cache informationen verfgbar. apcu scheint nicht installiert zu sein.', 'no_opcacheinfo' =&gt; 'keine opcache informationen verfgbar. opcache scheint nicht installiert zu sein.', 'inactive_opcacheinfo' =&gt; 'opcache ist installiert, aber nicht aktiviert.', 'nowildcardwithletsencrypt' =&gt; 'let\'s encrypt kann mittels acme wildcard-domains nur via dns validieren, sorry. bitte den serveralias auf www setzen oder deaktivieren', 'customized_version' =&gt; 'es scheint als wre die froxlor installation angepasst worden. kein support, sorry.', 'autoupdate_0' =&gt; 'unbekannter fehler', 'autoupdate_1' =&gt; 'php einstellung allow_url_fopen ist deaktiviert. autoupdate bentigt diese option, bitte der php.ini aktivieren.', 'autoupdate_2' =&gt; 'php zip erweiterung nicht gefunden, bitte prfen, ob diese installiert und aktiviert ist.', 'autoupdate_4' =&gt; 'das froxlor archiv konnte nicht auf der festplatte gespeichert werden :(', 'autoupdate_5' =&gt; 'version.froxlor.org gab ungltige werte zurck :(', 'autoupdate_6' =&gt; 'woops, keine (gltige) version angegeben fr den download :(', 'autoupdate_7' =&gt; 'das heruntergeladene archiv konnte nicht gefunden werden :(', 'autoupdate_8' =&gt; 'das archiv konnte nicht entpackt werden :(', 'autoupdate_9' =&gt; 'die heruntergeladene datei konnte nicht verifiziert werden. bitte erneut versuchen zu aktualisieren.', 'autoupdate_10' =&gt; 'minimum untersttzte version von php ist 7.4.0', 'autoupdate_11' =&gt; 'webupdate ist deaktiviert', 'mailaccistobedeleted' =&gt; 'ein vorheriges konto mit dem gleichen namen (%s) wird aktuell noch gelscht und kann daher derzeit nicht angelegt werden', 'customerhasongoingexportjob' =&gt; 'es gibt noch einen austehenden daten-export. bitte haben sie etwas geduld.', 'exportfunctionnotenabled' =&gt; 'die datenexport-funktion nicht aktiviert', 'dns_domain_nodns' =&gt; 'dns ist fr diese domain nicht aktiviert', 'dns_content_empty' =&gt; 'keinen inhalt angegeben', 'dns_content_invalid' =&gt; 'dns eintrag ungltig', 'dns_arec_noipv4' =&gt; 'keine gltige ip-adresse fr a-eintrag angegeben', 'dns_aaaarec_noipv6' =&gt; 'keine gltige ip-adresse fr aaaa-eintrag angegeben', 'dns_mx_prioempty' =&gt; 'ungltige mx prioritt angegeben', 'dns_mx_needdom' =&gt; 'der wert des mx eintrags muss ein gltiger domainname sein', 'dns_mx_noalias' =&gt; 'der mx eintrag darf kein cname eintrag sein.', 'dns_cname_invaliddom' =&gt; 'ungltiger domain-name fr cname eintrag', 'dns_cname_nomorerr' =&gt; 'es existiert bereits ein eintrag mit dem gleichen namen. dieser eintrag kann daher nicht fr cname genutzt werden.', 'dns_other_nomorerr' =&gt; 'es existiert bereits ein cname eintrag mit dem gleichen namen. dieser eintrag kann daher nicht fr einen anderen genutzt werden.', 'dns_ns_invaliddom' =&gt; 'ungltiger domain-name fr ns eintrag', 'dns_srv_prioempty' =&gt; 'ungltige srv prioritt angegeben', 'dns_srv_invalidcontent' =&gt; 'ungltiger wert des srv eintrags, dieser muss aus den feldern weight, port und target, bestehen. bsp.: 5 5060 sipserver.example.com.', 'dns_srv_needdom' =&gt; 'der wert des srv eintrags muss ein gltiger domainname sein', 'dns_srv_noalias' =&gt; 'der srv eintrag darf kein cname eintrag sein.', 'dns_duplicate_entry' =&gt; 'eintrag existiert bereits', 'dns_notfoundorallowed' =&gt; 'domain nicht gefunden oder keine berechtigung', 'domain_nopunycode' =&gt; 'die eingabe von punycode (idna) ist nicht notwendig. die domain wird automatisch konvertiert.', 'domain_noipaddress' =&gt; 'eine ip-adresse kann nicht als domain angelegt werden', 'dns_record_toolong' =&gt; 'records/labels knnen maximal 63 zeichen lang sein', 'noipportgiven' =&gt; 'keine ip/port angegeben', 'nosslippportgiven' =&gt; 'wenn ssl aktiviert ist, muss eine ssl ip/port angegeben werden', 'jsonextensionnotfound' =&gt; 'diese funktion bentigt die php json-erweiterung.', 'cannotdeletesuperadmin' =&gt; 'der erste administrator kann nicht gelscht werden.', 'no_wwwcnamae_ifwwwalias' =&gt; 'es kann kein cname eintrag fr "www" angelegt werden, da die domain einen www-alias aktiviert hat. ndere diese einstellung auf "kein alias" oder "wildcard alias"', 'local_group_exists' =&gt; 'die angegebene gruppe existiert bereits auf dem system', 'local_group_invalid' =&gt; 'der angegebene gruppen-name ist nicht gltig', 'invaliddnsforletsencrypt' =&gt; 'die dns-eintrge der domain enthalten keine der gewhlten ip adressen. let\'s encrypt zertifikats-erstellung ist nicht mglich.', 'notallowedphpconfigused' =&gt; 'nutzung einer php-konfiguration welche nicht dem kunden zugeordnet ist', 'pathmustberelative' =&gt; 'der benutzer hat nicht die bentigten berechtigungen, um pfade auerhalb des kunden-heimatverzeichnisses anzugeben. bitte einen relativen pfad angeben (kein fhrendes /).', 'mysqlserverstillhasdbs' =&gt; 'datenbank-server kann fr den kunden nicht entfernt werden, da sich dort noch datenbanken befinden.', 'domaincannotbeedited' =&gt; 'keine berechtigung, um die domain %s zu bearbeiten', 'invalidcronjobintervalvalue' =&gt; 'cronjob intervall muss einer der folgenden werte sein: %s', 'phpgdextensionnotavailable' =&gt; 'die php gd extension ist nicht verfgbar. bild-daten knnen nicht validiert werden.', '2fa_wrongcode' =&gt; 'der angegebene code ist nicht korrekt', 'gnupgextensionnotavailable' =&gt; 'die php gnupg extension ist nicht verfgbar. pgp schlssel knnen nicht validiert werden.', 'invalidpgppublickey' =&gt; 'der angegebene pgp public key ist ungltig', 'invalid_validtime' =&gt; 'wert der valid_time sekunden muss zwischen 10 und 120 liegen.', 'customerphpenabledbutnoconfig' =&gt; 'kunde hat php aktiviert aber keine php-konfiguration wurde gewhlt.', 'emaildomainstillhasaddresses' =&gt; 'maildomain-flag kann nicht deaktiviert werden, da fr diese domain noch e-mail-adressen vorhanden sind.', ], 'extras' =&gt; [ 'description' =&gt; 'hier knnen sie zustzliche extras einrichten, wie zum beispiel einen verzeichnisschutz.&lt;br /&gt;die nderungen sind erst nach einer kurzen zeit wirksam.', 'directoryprotection_add' =&gt; 'verzeichnisschutz anlegen', 'view_directory' =&gt; 'verzeichnis anzeigen', 'pathoptions_add' =&gt; 'pfadoptionen hinzufgen', 'directory_browsing' =&gt; 'verzeichnisinhalt anzeigen', 'pathoptions_edit' =&gt; 'pfadoptionen bearbeiten', 'error404path' =&gt; '404', 'error403path' =&gt; '403', 'error500path' =&gt; '500', 'error401path' =&gt; '401', 'errordocument404path' =&gt; 'fehlerdokument 404', 'errordocument403path' =&gt; 'fehlerdokument 403', 'errordocument500path' =&gt; 'fehlerdokument 500', 'errordocument401path' =&gt; 'fehlerdokument 401', 'execute_perl' =&gt; 'perl/cgi ausfhren', 'htpasswdauthname' =&gt; 'grund der authentifizierung (authname)', 'directoryprotection_edit' =&gt; 'verzeichnisschutz bearbeiten', 'export' =&gt; 'datenexport erstellen', 'dump_web' =&gt; 'web-daten hinzufgen', 'dump_mail' =&gt; 'e-mail daten hinzufgen', 'dump_dbs' =&gt; 'datenbanken hinzufgen', 'path_protection_label' =&gt; '&lt;strong class="text-danger"&gt;wichtig&lt;/strong&gt;', 'path_protection_info' =&gt; 'wir raten dringend dazu den angegebenen pfad zu schtzen, siehe "extras" -&gt; "verzeichnisschutz"', ], 'ftp' =&gt; [ 'description' =&gt; 'hier knnen sie zustzliche ftp-konten einrichten.&lt;br /&gt;die nderungen sind sofort wirksam und die ftp-konten sofort benutzbar.', 'account_add' =&gt; 'benutzerkonto anlegen', 'account_edit' =&gt; 'ftp-konto bearbeiten', 'editpassdescription' =&gt; 'neues passwort setzen oder leer fr keine nderung.', ], 'gender' =&gt; [ 'title' =&gt; 'anrede', 'male' =&gt; 'herr', 'female' =&gt; 'frau', 'undef' =&gt; '', ], 'imprint' =&gt; 'impressum', 'index' =&gt; [ 'customerdetails' =&gt; 'kundendaten', 'accountdetails' =&gt; 'kontodaten', ], 'integrity_check' =&gt; [ 'databasecharset' =&gt; 'characterset der datenbank (sollte utf-8 sein)', 'domainiptable' =&gt; 'ip &amp;lt;&amp;dash;&amp;gt; domain verkn&amp;uuml;pfung', 'subdomainsslredirect' =&gt; 'falsches ssl-redirect flag bei nicht-ssl domains', 'froxlorlocalgroupmemberforfcgidphpfpm' =&gt; 'froxlor-benutzer kunden-gruppen (f&amp;uuml;r fcgid/php-fpm)', 'webservergroupmemberforfcgidphpfpm' =&gt; 'webserver-benutzer kunden-gruppen (f&amp;uuml;r fcgid/php-fpm)', 'subdomainletsencrypt' =&gt; 'hauptdomains ohne zugewiesenen ssl-port haben keine subdomain mit aktiviertem ssl-redirect', ], 'logger' =&gt; [ 'date' =&gt; 'datum', 'type' =&gt; 'typ', 'action' =&gt; 'aktion', 'user' =&gt; 'benutzer', 'truncate' =&gt; 'log leeren', 'reseller' =&gt; 'reseller', 'admin' =&gt; 'administrator', 'cron' =&gt; 'cronjob', 'login' =&gt; 'login', 'intern' =&gt; 'intern', 'unknown' =&gt; 'unbekannt', ], 'login' =&gt; [ 'username' =&gt; 'benutzername', 'password' =&gt; 'passwort', 'language' =&gt; 'sprache', 'login' =&gt; 'anmelden', 'logout' =&gt; 'abmelden', 'profile_lng' =&gt; 'profilsprache', 'welcomemsg' =&gt; 'bitte melden sie sich an, um auf ihr konto zuzugreifen.', 'forgotpwd' =&gt; 'passwort vergessen?', 'presend' =&gt; 'passwort zurcksetzen', 'email' =&gt; 'e-mail-adresse', 'remind' =&gt; 'passwort zurcksetzen', 'usernotfound' =&gt; 'fehler: unbekannter benutzer!', 'backtologin' =&gt; 'zurck zum login', 'combination_not_found' =&gt; 'kombination aus benutzername und e-mail adresse stimmen nicht berein.', '2fa' =&gt; 'zwei-faktor authentifizierung (2fa)', '2facode' =&gt; 'bitte 2fa code angeben', '2faremember' =&gt; 'browser vertrauen', ], 'mails' =&gt; [ 'pop_success' =&gt; [ 'mailbody' =&gt; 'hallo,\\n\\nihr e-mail-konto {username}\\nwurde erfolgreich eingerichtet.\\n\\ndies ist eine automatisch generierte\\ne-mail, bitte antworten sie nicht auf\\ndiese mitteilung.\\n\\nihr administrator', 'subject' =&gt; 'e-mail-konto erfolgreich eingerichtet', ], 'createcustomer' =&gt; [ 'mailbody' =&gt; 'hallo {salutation},\\n\\nhier ihre accountinformationen:\\n\\nbenutzername: {username}\\npasswort: {password}\\n\\nvielen dank,\\nihr administrator', 'subject' =&gt; 'kontoinformationen', ], 'pop_success_alternative' =&gt; [ 'mailbody' =&gt; 'hallo {salutation},\\n\\nihr e-mail-konto {username}\\nwurde erfolgreich eingerichtet.\\nihr passwort lautet {password}.\\n\\ndies ist eine automatisch generierte\\nemail, bitte antworten sie nicht auf\\ndiese mitteilung.\\n\\nihr administrator', 'subject' =&gt; 'e-mail-konto erfolgreich eingerichtet', ], 'password_reset' =&gt; [ 'subject' =&gt; 'passwort zurckgesetzt', 'mailbody' =&gt; 'hallo {salutation},\\n\\nhiermit erhalten sie den link, um ein neues passwort zu setzen. dieser link ist fr die nchsten 24 stunden gltig.\\n\\n{link}\\n\\nvielen dank,\\nihr administrator', ], 'new_database_by_customer' =&gt; [ 'subject' =&gt; '[froxlor] neue datenbank erstellt', 'mailbody' =&gt; 'hallo {cust_name}, du hast gerade eine neue datenbank angelegt. hier die angegebenen informationen: datenbankname: {db_name} passwort: {db_pass} beschreibung: {db_desc} datenbank-server: {db_srv} phpmyadmin: {pma_uri} vielen dank, ihr administrator', ], 'new_ftpaccount_by_customer' =&gt; [ 'subject' =&gt; 'neuer ftp-benutzer erstellt', 'mailbody' =&gt; 'hallo {cust_name}, du hast gerade einen neuen ftp-benutzer angelegt. hier die angegebenen informationen: benutzername: {usr_name} passwort: {usr_pass} pfad: {usr_path} vielen dank, ihr administrator', ], 'trafficmaxpercent' =&gt; [ 'mailbody' =&gt; 'hallo {salutation},\\n\\nsie haben bereits {trafficused} von ihren insgesamt {traffic} traffic verbraucht.\\ndies sind mehr als {max_percent}%%.\\n\\nvielen dank,\\nihr administrator', 'subject' =&gt; 'sie erreichen bald ihr traffic-limit', ], 'diskmaxpercent' =&gt; [ 'mailbody' =&gt; 'hallo {salutation},\\n\\nsie haben bereits {diskused} von ihren insgesamt {diskavailable} speicherplatz verbraucht.\\ndies sind mehr als {max_percent}%%.\\n\\nvielen dank,\\nihr administrator', 'subject' =&gt; 'sie erreichen bald ihr speicherplatz-limit', ], '2fa' =&gt; [ 'mailbody' =&gt; 'hallo,\\n\\nihr 2fa-login code lautet: {code}\\n\\ndies ist eine automatisch generierte\\nemail, bitte antworten sie nicht auf\\ndiese mitteilung.\\n\\nihr administrator', 'subject' =&gt; 'froxlor - 2fa code', ], ], 'menue' =&gt; [ 'main' =&gt; [ 'main' =&gt; 'allgemein', 'changepassword' =&gt; 'passwort ndern', 'changelanguage' =&gt; 'sprache ndern', 'username' =&gt; 'angemeldet als ', 'changetheme' =&gt; 'theme wechseln', 'apihelp' =&gt; 'api hilfe', 'apikeys' =&gt; 'api keys', ], 'email' =&gt; [ 'email' =&gt; 'e-mail', 'emails' =&gt; 'adressen', 'webmail' =&gt; 'webmail', 'emailsoverview' =&gt; 'e-mail domain bersicht', ], 'mysql' =&gt; [ 'mysql' =&gt; 'mysql', 'databases' =&gt; 'datenbanken', 'phpmyadmin' =&gt; 'phpmyadmin', ], 'domains' =&gt; [ 'domains' =&gt; 'domains', 'settings' =&gt; 'bersicht domains', ], 'ftp' =&gt; [ 'ftp' =&gt; 'ftp', 'accounts' =&gt; 'benutzerkonten', 'webftp' =&gt; 'webftp', ], 'extras' =&gt; [ 'extras' =&gt; 'extras', 'directoryprotection' =&gt; 'verzeichnisschutz', 'pathoptions' =&gt; 'pfadoptionen', 'export' =&gt; 'datenexport', ], 'traffic' =&gt; [ 'traffic' =&gt; 'traffic', 'current' =&gt; 'aktueller monat', 'overview' =&gt; 'bersicht', ], 'phpsettings' =&gt; [ 'maintitle' =&gt; 'php-konfigurationen', 'fpmdaemons' =&gt; 'php-fpm versionen', ], 'logger' =&gt; [ 'logger' =&gt; 'system-log', ], ], 'message' =&gt; [ 'norecipients' =&gt; 'es wurde keine e-mail versendet, da sich keine empfnger der datenbank befinden', 'success' =&gt; 'nachricht erfolgreich "%s" empfnger gesendet', ], 'mysql' =&gt; [ 'databasename' =&gt; 'benutzer-/datenbankname', 'databasedescription' =&gt; 'datenbankbeschreibung', 'database_create' =&gt; 'datenbank anlegen', 'description' =&gt; 'hier knnen sie mysql-datenbanken anlegen und lschen.&lt;br /&gt;die nderungen werden sofort wirksam und die datenbanken sind sofort benutzbar.&lt;br /&gt;im men finden sie einen link zu phpmyadmin, mit dem sie ihre datenbankinhalte komfortabel bearbeiten knnen.&lt;br /&gt;&lt;br /&gt;die zugangsdaten sind wie folgt: (die angaben &lt;i&gt;kursiver&lt;/i&gt; schrift sind durch die jeweiligen eintrge zu ersetzen)&lt;br /&gt;hostname: &lt;b&gt;&lt;sql_host&gt;&lt;/b&gt;&lt;br /&gt;benutzername: &lt;b&gt;&lt;i&gt;datenbankname&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;passwort: &lt;b&gt;&lt;i&gt;das gewhlte passwort&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;datenbank: &lt;b&gt;&lt;i&gt;datenbankname&lt;/i&gt;&lt;/b&gt;', 'mysql_server' =&gt; 'mysql-server', 'database_edit' =&gt; 'datenbank bearbeiten', 'size' =&gt; 'datenbankgre', 'privileged_user' =&gt; 'privilegierter datenbankbenutzer', 'privileged_passwd' =&gt; 'passwort fr privilegierten benutzer', 'unprivileged_passwd' =&gt; 'passwort fr nicht privilegierten benutzer', 'mysql_ssl_ca_file' =&gt; 'ssl-serverzertifikat', 'mysql_ssl_verify_server_certificate' =&gt; 'verifizieren des ssl-serverzertifikats', 'globaluserinfo' =&gt; 'um auf datenbanken zuzugreifen, kann zustzlich der froxlor-login (benutzer: %s) verwendet werden, dieser hat automatisch zugriff auf alle datenbanken.&lt;br /&gt;es wird empfohlen diesen &lt;b&gt;nicht&lt;/b&gt; fr applikationen zu nutzen, lediglich zur administration (z.b. via phpmyadmin).', 'edit_global_user' =&gt; 'admin benutzer bearbeiten', ], 'panel' =&gt; [ 'edit' =&gt; 'bearbeiten', 'delete' =&gt; 'lschen', 'create' =&gt; 'anlegen', 'save' =&gt; 'speichern', 'yes' =&gt; 'ja', 'no' =&gt; 'nein', 'emptyfornochanges' =&gt; 'leer fr keine nderung', 'emptyfordefault' =&gt; 'leer fr standardeinstellung.', 'path' =&gt; 'pfad', 'toggle' =&gt; 'umschalten', 'next' =&gt; 'weiter', 'dirsmissing' =&gt; 'das angegebene verzeichnis konnte nicht gefunden werden.', 'urloverridespath' =&gt; 'url (berschreibt pfad)', 'pathorurl' =&gt; 'pfad oder url', 'ascending' =&gt; 'aufsteigend', 'descending' =&gt; 'absteigend', 'search' =&gt; 'suche', 'used' =&gt; 'genutzt', 'translator' =&gt; 'bersetzung', 'reset' =&gt; 'nderungen verwerfen', 'pathdescription' =&gt; 'sollte das verzeichnis nicht existieren, wird es automatisch erstellt.', 'pathdescriptionex' =&gt; '&lt;br /&gt;&lt;br /&gt;&lt;span class="text-danger"&gt;bitte beachten:&lt;/span&gt; der pfad &lt;code&gt;/&lt;/code&gt; ist nicht erlaubt aufgrund administrativer einstellungen, er wird automatisch auf &lt;code&gt;/gewaehlte.subdomain.tld/&lt;/code&gt; gesetzt, sofern nicht ein anderer ordner angegeben wird.', 'pathdescriptionsubdomain' =&gt; 'sollte das verzeichnis nicht existieren, wird es automatisch erstellt.&lt;br /&gt;sollte eine weiterleitung auf eine andere domain gewnscht sein, muss der eintrag mit http:// oder https:// beginnen.&lt;br /&gt;endet die url mit einem / (slash) geht froxlor von einem ordner aus, wenn nicht, wird es wie eine datei behandelt.', 'back' =&gt; 'zurck', 'reseller' =&gt; 'reseller', 'admin' =&gt; 'administrator', 'customer' =&gt; 'kunde/n', 'send' =&gt; 'versenden', 'nosslipsavailable' =&gt; 'fr diesen server wurden noch keine ssl ip/port kombinationen eingetragen', 'backtooverview' =&gt; 'zurck zur bersicht', 'dateformat' =&gt; 'tt.mm.jjjj', 'dateformat_function' =&gt; 'd.m.y', 'timeformat_function' =&gt; 'h:i:s', 'default' =&gt; 'standard', 'never' =&gt; 'nie', 'active' =&gt; 'aktiv', 'please_choose' =&gt; 'bitte auswhlen', 'allow_modifications' =&gt; 'nderungen zulassen', 'megabyte' =&gt; 'megabyte', 'not_supported' =&gt; 'nicht untersttzt in: ', 'view' =&gt; 'ansehen', 'toomanydirs' =&gt; 'zu viele unterverzeichnisse. weiche auf manuelle verzeichniseingabe aus.', 'abort' =&gt; 'abbrechen', 'not_activated' =&gt; 'nicht aktiviert', 'off' =&gt; 'aus', 'options' =&gt; 'optionen', 'neverloggedin' =&gt; 'keine anmeldung bisher', 'descriptionerrordocument' =&gt; 'mgliche werte sind: url, pfad zu einer datei oder ein text, umgeben von anfhrungszeichen (" ").&lt;br /&gt;leer fr server-standardwert.', 'unlock' =&gt; 'entsperren', 'theme' =&gt; 'theme', 'variable' =&gt; 'variable', 'description' =&gt; 'beschreibung', 'ssleditor' =&gt; 'ssl-einstellungen fr diese domain', 'ssleditor_infoshared' =&gt; 'aktuell zertifikat der elterndomain genutzt', 'ssleditor_infoglobal' =&gt; 'aktuell globales zertifikat genutzt', 'dashboard' =&gt; 'dashboard', 'assigned' =&gt; 'zugewiesen', 'available' =&gt; 'verfgbar', 'news' =&gt; 'neuigkeiten', 'newsfeed_disabled' =&gt; 'das newsfeed ist deaktiviert. klicken sie auf das editier-icon, um zu den einstellungen zu gelangen.', 'ftpdesc' =&gt; 'ftp-beschreibung', 'letsencrypt' =&gt; 'benutzt let\'s encrypt', 'set' =&gt; 'setzen', 'exportpath' =&gt; [ 'title' =&gt; 'pfad zur ablage des exports', 'description' =&gt; 'in diesem ordner werden die export-archive abgelegt. wenn web-daten exportiert werden, werden alle dateien aus dem heimatverzeichnis gesichert, exklusive des hier angegebenen ordners.', ], 'export_pgp_public_key' =&gt; [ 'title' =&gt; 'ffentlicher pgp-schlssel', 'description' =&gt; 'der ffentliche pgp-schlssel, mit dem die exporte verschlsselt werden sollen. wenn kein schlssel angegeben ist, werden die exporte nicht verschlsselt.', ], 'pgp_public_key' =&gt; 'ffentlicher pgp-schlssel', 'none_value' =&gt; 'keine', 'viewlogs' =&gt; 'logdateien einsehen', 'not_configured' =&gt; 'das system wurde noch nicht konfiguriert. klicke auf den button um die installation zu starten.', 'ihave_configured' =&gt; 'ich habe die dienste konfiguriert', 'system_is_configured' =&gt; '&lt;i class="fa-solid fa-circle-exclamation me-1"&gt;&lt;/i&gt;das system ist bereits konfiguriert', 'settings_before_configuration' =&gt; 'stelle sicher, dass die einstellungen angepasst wurden bevor die dienste konfiguriert werden.', 'image_field_delete' =&gt; 'das momentan vorhandene bild lschen', 'usage_statistics' =&gt; 'resourcen-verbrauch', 'security_question' =&gt; 'sicherheitsabfrage', 'listing_empty' =&gt; 'keine eintrge gefunden', 'unspecified' =&gt; 'keine angabe', 'settingsmode' =&gt; 'modus', 'settingsmodebasic' =&gt; 'einfach', 'settingsmodeadvanced' =&gt; 'erweitert', 'settingsmodetoggle' =&gt; 'modus umschalten', 'modalclose' =&gt; 'schlieen', 'managetablecolumnsmodal' =&gt; [ 'title' =&gt; 'tabellenspalten verwalten', 'description' =&gt; 'hier knnen die angezeigten tabellenspalten angepasst werden', ], 'mandatoryfield' =&gt; 'pflichtfeld', 'select_all' =&gt; 'alle auswhlen', 'unselect_all' =&gt; 'alle abwhlen', 'searchtablecolumnsmodal' =&gt; [ 'title' =&gt; 'feld-suche', 'description' =&gt; 'whle das zu durchsuchende feld aus' ], 'upload_import' =&gt; 'hochladen und importieren', 'profile' =&gt; 'mein profil', 'use_checkbox_for_unlimited' =&gt; 'der wert "0" deaktiviert die resource. die checkbox rechts erlaubt "unlimitierte" nutzung.', 'use_checkbox_to_disable' =&gt; 'zum deaktivieren, klicke die checkbox auf der rechten seite des eingabefeldes', ], 'phpfpm' =&gt; [ 'vhost_httpuser' =&gt; 'lokaler benutzer fr php-fpm (froxlor-vhost)', 'vhost_httpgroup' =&gt; 'lokale gruppe fr php-fpm (froxlor-vhost)', 'ownvhost' =&gt; [ 'title' =&gt; 'verwende php-fpm im froxlor-vhost', 'description' =&gt; 'wenn verwendet, wird froxlor selbst unter einem lokalen benutzer ausgefhrt', ], 'use_mod_proxy' =&gt; [ 'title' =&gt; 'verwende mod_proxy / mod_proxy_fcgi', 'description' =&gt; '&lt;strong class="text-danger"&gt;muss gesetzt sein bei debian 9.x (stretch) oder neuer&lt;/strong&gt;. diese option kann aktiviert werden, um php-fpm via mod_proxy_fcgi einzubinden. dies setzt mindestens apache-2.4.9 voraus', ], 'ini_flags' =&gt; 'mgliche &lt;strong&gt;php_flag&lt;/strong&gt;s fr die php.ini. pro zeile eine direktive', 'ini_values' =&gt; 'mgliche &lt;strong&gt;php_value&lt;/strong&gt;s fr die php.ini. pro zeile eine direktive', 'ini_admin_flags' =&gt; 'mgliche &lt;strong&gt;php_admin_flag&lt;/strong&gt;s fr die php.ini. pro zeile eine direktive', 'ini_admin_values' =&gt; 'mgliche &lt;strong&gt;php_admin_value&lt;/strong&gt;s fr die php.ini. pro zeile eine direktive', ], 'privacy' =&gt; 'datenschutzerklrung', 'pwdreminder' =&gt; [ 'success' =&gt; 'das zurcksetzen des passworts wurde erfolgreich angefordert. sie sollten nun eine e-mail mit weiteren anweisungen erhalten.', 'notallowed' =&gt; 'unbekannter benutzer oder zurcksetzen des passworts ist deaktiviert.', 'changed' =&gt; 'ihr passwort wurde erfolgreich gendert. sie knnen sich nun damit anmelden.', 'wrongcode' =&gt; 'der verwendete aktivierungscode ist entweder nicht gltig oder bereits abgelaufen.', 'choosenew' =&gt; 'neues passwort auswhlen', ], 'question' =&gt; [ 'question' =&gt; 'sicherheitsabfrage', 'admin_customer_reallydelete' =&gt; 'wollen sie den kunden "%s" wirklich lschen?&lt;br /&gt;achtung! alle daten gehen unwiderruflich verloren! nach dem vorgang mssen die daten manuell aus dem dateisystem entfernt werden.', 'admin_domain_reallydelete' =&gt; 'wollen sie die domain "%s" wirklich lschen?&lt;br&gt;&lt;span class="text-danger"&gt;&lt;strong&gt;achtung:&lt;/strong&gt; alle subdomains, ftp-konten und e-mail adressen/konten, welche mit dieser domain verbunden sind, werden gelscht!&lt;/span&gt;', 'admin_domain_reallydisablesecuritysetting' =&gt; 'wollen sie die wichtige sicherheitseinstellung \'openbasedir\' wirklich deaktivieren?', 'admin_admin_reallydelete' =&gt; 'wollen sie den admin "%s" wirklich lschen?&lt;br /&gt;alle kunden und domains dieses admins werden ihnen zugeteilt.', 'admin_template_reallydelete' =&gt; 'wollen sie die vorlage "%s" wirklich lschen?', 'domains_reallydelete' =&gt; 'wollen sie die domain "%s" wirklich lschen?', 'email_reallydelete' =&gt; 'wollen sie die e-mail-adresse "%s" wirklich lschen?', 'email_reallydelete_account' =&gt; 'wollen sie das konto von "%s" wirklich lschen?', 'email_reallydelete_forwarder' =&gt; 'wollen sie die weiterleitung "%s" wirklich lschen?', 'extras_reallydelete' =&gt; 'wollen sie den verzeichnisschutz fr "%s" wirklich lschen?', 'extras_reallydelete_pathoptions' =&gt; 'wollen sie die optionen fr den pfad "%s" wirklich lschen?', 'extras_reallydelete_export' =&gt; 'wollen sie den geplanten daten-export wirklich lschen?', 'ftp_reallydelete' =&gt; 'wollen sie das ftp-benutzerkonto "%s" wirklich lschen?', 'mysql_reallydelete' =&gt; 'wollen sie die datenbank "%s" wirklich lschen?&lt;br /&gt;achtung! alle daten gehen unwiderruflich verloren!', 'admin_configs_reallyrebuild' =&gt; 'wollen sie wirklich alle konfigurationsdateien neu erstellen lassen?', 'admin_customer_alsoremovefiles' =&gt; 'kundendaten lschen?', 'admin_customer_alsoremovemail' =&gt; 'e-mail-daten auf dem dateisystem lschen?', 'admin_customer_alsoremoveftphomedir' =&gt; 'heimatverzeichnis des ftp-benutzers lschen?', 'admin_ip_reallydelete' =&gt; 'wollen sie wirklich die ip-adresse "%s" lschen?', 'admin_domain_reallydocrootoutofcustomerroot' =&gt; 'sind sie sicher, dass der documentroot dieser domain auerhalb des heimatverzeichnisses des kunden liegen soll?', 'admin_counters_reallyupdate' =&gt; 'wollen sie den ressourcenverbrauch neu berechnen?', 'admin_cleartextmailpws_reallywipe' =&gt; 'wollen sie wirklich alle unverschlsselten passwrter aus der tabelle mail_users entfernen? dieser schritt kann nicht rckgngig gemacht werden! die einstellung fr das speichern der e-mail-konten-passwrter klartext wird hierbei ebenfalls deaktiviert.', 'logger_reallytruncate' =&gt; 'wollen sie die tabelle "%s" wirklich leeren?', 'admin_quotas_reallywipe' =&gt; 'sind sie sicher, dass alle e-mail-kontingente aus der tabelle mail_users entfernt werden sollen? dieser schritt kann nicht rckgngig gemacht werden!', 'admin_quotas_reallyenforce' =&gt; 'sind sie sicher, dass sie allen benutzern das default-quota zuweisen wollen? dies kann nicht rckgngig gemacht werden!', 'phpsetting_reallydelete' =&gt; 'wollen sie diese php-einstellungen wirklich lschen? alle domains die diese einstellungen bis jetzt verwendet haben, werden dann auf die standardeinstellungen umgestellt.', 'fpmsetting_reallydelete' =&gt; 'wollen sie diese php-fpm einstellungen wirklich lschen? alle php konfigurationen die diese einstellungen bis jetzt verwendet haben, werden dann auf die standardeinstellungen umgestellt.', 'customer_reallyunlock' =&gt; 'wollen sie den kunden "%s" wirklich entsperren?', 'admin_integritycheck_reallyfix' =&gt; 'm&amp;ouml;chten sie wirklich versuchen s&amp;auml;mtliche datenbank-integrit&amp;auml;tsprobleme automatisch zu beheben?', 'plan_reallydelete' =&gt; 'wollen sie den hostingplan %s wirklich lschen?', 'apikey_reallydelete' =&gt; 'wollen sie den api-key wirklich lschen?', 'apikey_reallyadd' =&gt; 'einen neuen api-key erstellen?', 'dnsentry_reallydelete' =&gt; 'wollen sie den dns-eintrag wirklich lschen?', 'certificate_reallydelete' =&gt; 'wollen sie diese zertifikat wirklich lschen?', 'cache_reallydelete' =&gt; 'wollen sie den cache wirklich leeren?', 'please_enter_otp' =&gt; 'bitte 2fa code eingeben', 'admin_mysqlserver_reallydelete' =&gt; 'wollen sie wirklich diesen mysql-server lschen?', ], 'serversettings' =&gt; [ 'session_timeout' =&gt; [ 'title' =&gt; 'session-timeout', 'description' =&gt; 'wie lange muss ein benutzer inaktiv sein, damit die session ungltig wird? (in sekunden)', ], 'accountprefix' =&gt; [ 'title' =&gt; 'kundenprfix', 'description' =&gt; 'welchen prfix sollen die kundenaccounts haben?', ], 'mysqlprefix' =&gt; [ 'title' =&gt; 'mysql-prfix', 'description' =&gt; 'welchen prfix sollen die mysql-benutzerkonten haben?&lt;/br&gt;mit "random" als wert wird ein 3-stelliger zufallswert als prfix verwendet.&lt;/br&gt;mit "dbname" als wert wird ein feld databankname zusammen mit dem kundennamen als prfix genutzt.', ], 'ftpprefix' =&gt; [ 'title' =&gt; 'ftp-prfix', 'description' =&gt; 'welchen prfix sollen die ftp-benutzerkonten haben?&lt;br/&gt;&lt;b&gt;falls ftp-quoatas verwendet werden, ist es notwendig das quota-sql-query der ftp-server-config ebenfalls zu ndern!&lt;/b&gt;', ], 'documentroot_prefix' =&gt; [ 'title' =&gt; 'heimatverzeichnis', 'description' =&gt; 'wo sollen die heimatverzeichnisse der kunden liegen?', ], 'logfiles_directory' =&gt; [ 'title' =&gt; 'webserver-logdateien-verzeichnis', 'description' =&gt; 'wo sollen die logdateien des webservers liegen?', ], 'logfiles_script' =&gt; [ 'title' =&gt; 'eigenes script zu dem log-files bergeben werden', 'description' =&gt; 'hier kann ein script das die loginhalte bergeben werden hinterlegt und die platzhalter &lt;strong&gt;{logfile}, {domain} und {customer}&lt;/strong&gt; genutzt werden, sofern ntig. falls ein script angegeben wird, muss die option &lt;strong&gt;webserver logdateien umleiten&lt;/strong&gt; gesetzt werden', ], 'logfiles_format' =&gt; [ 'title' =&gt; 'access-log format', 'description' =&gt; 'hier kann ein angepasstes log-format entsprechend der webserver-dokumentation angegeben werden, leer lassen fr standard. abhngig vom logformat muss die angabe unter anfhrungszeichen stehen.&lt;br/&gt;wenn verwendet mit nginx, kann es wie folgt aussehen: &lt;i&gt;log_format frx_custom {eingestelltes_format}&lt;/i&gt;.&lt;br/&gt;wenn verwendet mit apache, kann es wie folgt aussehen: &lt;i&gt;logformat {eingestelltes_format} frx_custom&lt;/i&gt;.&lt;br /&gt;&lt;strong&gt;achtung:&lt;/strong&gt; der code wird nicht auf fehler geprft. etwaige fehler werden auch bernommen und der webserver knnte nicht mehr starten!', ], 'logfiles_type' =&gt; [ 'title' =&gt; 'access-log typ', 'description' =&gt; 'whle zwischen &lt;strong&gt;combined&lt;/strong&gt; oder &lt;strong&gt;vhost_combined&lt;/strong&gt;.', ], 'logfiles_piped' =&gt; [ 'title' =&gt; 'webserver logdateien zu eigenem script umleiten (siehe oben)', 'description' =&gt; 'wenn ein script fr die logdateien verwendet wird, muss diese option aktiviert werden, damit der webserver die ausgabe das script weitergibt.', ], 'ipaddress' =&gt; [ 'title' =&gt; 'ip-adresse', 'description' =&gt; 'welche haupt-ip-adresse hat der server?', ], 'hostname' =&gt; [ 'title' =&gt; 'hostname', 'description' =&gt; 'welchen hostnamen hat der server?', ], 'apachereload_command' =&gt; [ 'title' =&gt; 'webserver-reload-befehl', 'description' =&gt; 'wie heit das skript zum neuladen der webserver-konfigurationsdateien?', ], 'bindenable' =&gt; [ 'title' =&gt; 'nameserver aktivieren', 'description' =&gt; 'hier knnen sie den nameserver global aktivieren bzw. deaktivieren.', ], 'bindconf_directory' =&gt; [ 'title' =&gt; 'dns-server konfigurationsordner', 'description' =&gt; 'wo liegen die dns-server konfigurationsdateien?', ], 'bindreload_command' =&gt; [ 'title' =&gt; 'dns-server reload-befehl', 'description' =&gt; 'wie heit das skript zum neuladen der dns-server konfigurationsdateien?', ], 'vmail_uid' =&gt; [ 'title' =&gt; 'mail-uid', 'description' =&gt; 'welche uid sollen die e-mails haben?', ], 'vmail_gid' =&gt; [ 'title' =&gt; 'mail-gid', 'description' =&gt; 'welche gid sollen die e-mails haben?', ], 'vmail_homedir' =&gt; [ 'title' =&gt; 'mail-homedir', 'description' =&gt; 'wo sollen die e-mails liegen?', ], 'adminmail' =&gt; [ 'title' =&gt; 'absenderadresse', 'description' =&gt; 'wie lautet die absenderadresse fr e-mails aus dem panel?', ], 'phpmyadmin_url' =&gt; [ 'title' =&gt; 'phpmyadmin-url', 'description' =&gt; 'wo liegt phpmyadmin? (muss mit http(s):// beginnen)', ], 'webmail_url' =&gt; [ 'title' =&gt; 'webmail-url', 'description' =&gt; 'wo liegt der webmail-client? (muss mit http(s):// beginnen)', ], 'webftp_url' =&gt; [ 'title' =&gt; 'webftp-url', 'description' =&gt; 'wo liegt der webftp-client? (muss mit http(s):// beginnen)', ], 'language' =&gt; [ 'description' =&gt; 'welche sprache ist ihre standardsprache?', ], 'maxloginattempts' =&gt; [ 'title' =&gt; 'maximale loginversuche', 'description' =&gt; 'maximale anzahl loginversuchen bis der account deaktiviert wird.', ], 'deactivatetime' =&gt; [ 'title' =&gt; 'lnge der deaktivierung', 'description' =&gt; 'zeitraum (in sekunden) fr den der account deaktiviert ist.', ], 'pathedit' =&gt; [ 'title' =&gt; 'pfad-eingabemethode', 'description' =&gt; 'soll ein pfad via auswahlliste ausgewhlt oder manuell eingegeben werden knnen?', ], 'nameservers' =&gt; [ 'title' =&gt; 'nameserver', 'description' =&gt; 'eine durch komma getrennte liste mit den hostnamen aller nameserver. der erste ist der primre.', ], 'mxservers' =&gt; [ 'title' =&gt; 'mx-server', 'description' =&gt; 'eine durch komma getrenne liste, die ein paar mit einer nummer und den hostnamen einen mx-servers, getrennt durch ein leerzeichen, enthlt (z. b. \'10 mx.example.tld\').', ], 'paging' =&gt; [ 'title' =&gt; 'eintrge pro seite', 'description' =&gt; 'wie viele eintrge sollen auf einer seite angezeigt werden? (0 = paging deaktivieren)', ], 'defaultip' =&gt; [ 'title' =&gt; 'standard-ip/port-kombination', 'description' =&gt; 'welche ip/port-kombination sollen standardmig verwendet werden?', ], 'defaultsslip' =&gt; [ 'title' =&gt; 'standard ssl ip/port-kombination', 'description' =&gt; 'welche ssl-fhigen ip/port-kombination sollen standardmig verwendet werden?', ], 'phpappendopenbasedir' =&gt; [ 'title' =&gt; 'anzuhngende pfade bei openbasedir', 'description' =&gt; 'diese (durch doppelpunkte getrennten) pfade werden dem openbasedir-statement jedem vhost-container angehngt.', ], 'natsorting' =&gt; [ 'title' =&gt; 'natrliche sortierung der listenansicht nutzen', 'description' =&gt; 'sortiert die liste der reihenfolge web1 -&gt; web2 -&gt; web11 statt web1 -&gt; web11 -&gt; web2.', ], 'deactivateddocroot' =&gt; [ 'title' =&gt; 'docroot fr deaktivierte benutzer', 'description' =&gt; 'dieser pfad wird als docroot fr deaktivierte benutzer verwendet. ist das feld leer, wird kein vhost erstellt.', ], 'mailpwcleartext' =&gt; [ 'title' =&gt; 'passwrter der mail-konten auch im klartext der datenbank speichern', 'description' =&gt; 'wenn diese einstellung auf ja gesetzt wird, werden alle passwrter auch unverschlsselt (also im klartext, fr jeden mit zugriff auf die froxlor-datenbank sofort lesbar) der mail_users-tabelle gespeichert. aktivieren sie diese option nur dann, wenn sie sasl nutzen!', ], 'ftpdomain' =&gt; [ 'title' =&gt; 'ftp-benutzerkonten @domain', 'description' =&gt; 'knnen kunden ftp-benutzerkonten user@domain anlegen?', ], 'mod_fcgid' =&gt; [ 'title' =&gt; 'php ber mod_fcgid/suexec einbinden', 'description' =&gt; 'php wird unter dem benutzer des kunden ausgefhrt.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;dies bentigt eine spezielle webserver-konfiguration fr apache, siehe &lt;a target="_blank" href="https://docs.froxlor.org/latest/admin-guide/configuration/fcgid/"&gt;fcgid-handbuch&lt;/a&gt;.&lt;/b&gt;', 'configdir' =&gt; [ 'title' =&gt; 'konfigurations-verzeichnis', 'description' =&gt; 'wo sollen alle konfigurationsdateien von fcgid liegen? wenn sie keine selbst kompilierte suexec binary benutzen, der regel der fall ist, muss dieser pfad unter /var/www/ liegen.&lt;br /&gt;&lt;br /&gt;&lt;div class="text-danger"&gt;achtung: der inhalt dieses ordners wird regelmig geleert, daher sollten dort keinerlei daten manuell abgelegt werden.&lt;/div&gt;', ], 'tmpdir' =&gt; [ 'title' =&gt; 'temporres verzeichnis', 'description' =&gt; 'wo sollen die temporren verzeichnisse erstellt werden', ], 'starter' =&gt; [ 'title' =&gt; 'prozesse je domain', 'description' =&gt; 'wieviele php-prozesse pro domain sollen gestartet/erlaubt werden. der wert 0 wird empfohlen, da php die anzahl dann selbst effizient verwaltet.', ], 'wrapper' =&gt; [ 'title' =&gt; 'wrappereinbindung vhosts', 'description' =&gt; 'wie sollen die wrapper den vhosts eingebunden werden', ], 'peardir' =&gt; [ 'title' =&gt; 'globale pear verzeichnisse', 'description' =&gt; 'welche globalen pear verzeichnisse sollen den php.ini-einstellungen ersetzt werden? einzelne verzeichnisse sind mit einem doppelpunkt zu trennen.', ], 'maxrequests' =&gt; [ 'title' =&gt; 'maximale requests pro domain', 'description' =&gt; 'wieviele php-requests pro domain sollen erlaubt werden?', ], 'defaultini' =&gt; 'voreingestellte php-konfiguration fr neue domains', 'defaultini_ownvhost' =&gt; 'voreingestellte php-konfiguration fr den froxlor-vhost', 'idle_timeout' =&gt; [ 'title' =&gt; 'idle-timeout', 'description' =&gt; 'timeout-einstellung fr mod_fastcgi.', ], ], 'sendalternativemail' =&gt; [ 'title' =&gt; 'alternative e-mail-adresse benutzen', 'description' =&gt; 'whrend des erstellens eines accounts das passwort eine andere e-mail-adresse senden', ], 'apacheconf_vhost' =&gt; [ 'title' =&gt; 'webserver vhost-konfigurations-datei/verzeichnis-name', 'description' =&gt; 'wo sollen die vhost-konfigurationen abgelegt werden? sie knnen entweder eine datei (also mit allen vhosts) oder einen ordner (mit einer datei pro vhost) angeben.', ], 'apacheconf_diroptions' =&gt; [ 'title' =&gt; 'webserver verzeichnisoption-konfigurations-datei/verzeichnis-name', 'description' =&gt; 'wo sollen die verzeichnisoption-konfigurationen abgelegt werden? sie knnen entweder eine datei (also mit allen vhosts) oder einen ordner (mit einer datei pro vhost) angeben.', ], 'apacheconf_htpasswddir' =&gt; [ 'title' =&gt; 'webserver htpasswd verzeichnisname', 'description' =&gt; 'wo sollen die htpasswd-dateien fr den verzeichnisschutz abgelegt werden?', ], 'mysql_access_host' =&gt; [ 'title' =&gt; 'mysql-access-hosts', 'description' =&gt; 'eine durch komma getrennte liste mit den hostnamen aller hostnames/ip-adressen, von denen sich die benutzer einloggen drfen. um ein subnetz zu erlauben ist die netzmaske oder cidr syntax erlaubt.', ], 'webalizer_quiet' =&gt; [ 'title' =&gt; 'webalizerausgabe', 'description' =&gt; 'ausgabefreudigkeit des webalizer-programms', ], 'logger' =&gt; [ 'enable' =&gt; 'logging ja/nein', 'severity' =&gt; 'logging level', 'types' =&gt; [ 'title' =&gt; 'log-art(en)', 'description' =&gt; 'whlen sie hier die gewnschten logtypen. fr mehrfachauswahl, halten sie whrend der auswahl strg gedrckt&lt;br /&gt;mgliche logtypen sind: syslog, file, mysql', ], 'logfile' =&gt; [ 'title' =&gt; 'dateiname der logdatei', 'description' =&gt; 'wird nur verwendet, wenn die log-art "file" ausgewhlt ist. diese datei wird unter froxlor/logs/ geschrieben. dieser ordner ist vor webzugriff geschtzt.', ], 'logcron' =&gt; 'logge cronjobs', 'logcronoption' =&gt; [ 'never' =&gt; 'nie', 'once' =&gt; 'einmalig', 'always' =&gt; 'immer', ], ], 'ssl' =&gt; [ 'use_ssl' =&gt; [ 'title' =&gt; 'aktiviere ssl', 'description' =&gt; 'erlaubt die nutzung von ssl fr den webserver', ], 'ssl_cert_file' =&gt; [ 'title' =&gt; 'pfad zum ssl-zertifikat', 'description' =&gt; 'geben sie den pfad inklusive dateinamen des zertifikats (meist .crt .pem).', ], 'openssl_cnf' =&gt; 'standardwerte zum erstellen eines zertifikats', 'ssl_key_file' =&gt; [ 'title' =&gt; 'pfad zum ssl private-key', 'description' =&gt; 'geben sie den pfad inklusive dateinamen der schlssel-datei (der private-key, meist .key).', ], 'ssl_ca_file' =&gt; [ 'title' =&gt; 'pfad zum ssl-ca-zertifikat (optional)', 'description' =&gt; 'client authentifizierung, dieses feld sollte nur gesetzt werden, wenn es wirklich gebraucht wird.', ], 'ssl_cipher_list' =&gt; [ 'title' =&gt; 'erlaubte ssl ciphers festlegen', 'description' =&gt; 'dies ist eine liste von ciphers, die genutzt werden sollen (oder auch nicht genutzt werden sollen), wenn eine ssl verbindung besteht. eine liste aller ciphers und wie diese hinzugefgt/ausgeschlossen werden ist den abschnitten "cipher list format" und "cipher strings" &lt;a href="https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html"&gt;der man-page fr ciphers&lt;/a&gt; zu finden.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;standard-wert ist:&lt;/b&gt;&lt;pre&gt;ecdh+aesgcm:ecdh+aes256:!anull:!md5:!dss:!dh:!aes128&lt;/pre&gt;', ], 'apache24_ocsp_cache_path' =&gt; [ 'title' =&gt; 'apache 2.4: pfad zum ocsp-stapling-cache', 'description' =&gt; 'konfiguriert den cache-pfad zum zwischenspeichern der ocsp-antworten,&lt;br /&gt;die tls-handshakes angehngt werden.', ], 'ssl_protocols' =&gt; [ 'title' =&gt; 'ssl protokollversion festlegen', 'description' =&gt; 'dies ist eine liste von ssl/tls protokollversionen die genutzt werden sollen (oder auch nicht genutzt werden sollen), wenn ssl verwendet wird. &lt;b&gt;hinweis:&lt;/b&gt; ltere browser sind mglicherweise nicht vollstndig zum neusten protokoll kompatibel.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;standard-wert ist:&lt;/b&gt;&lt;pre&gt;tlsv1.2&lt;/pre&gt;', ], 'tlsv13_cipher_list' =&gt; [ 'title' =&gt; 'explizite tlsv1.3 ciphers, wenn genutzt', 'description' =&gt; 'dies ist eine liste von ciphers, die genutzt werden sollen (oder auch nicht genutzt werden sollen), wenn eine tlsv1.3 verbindung hergestellt werden soll. eine liste aller ciphers und wie diese hinzugefgt/ausgeschlossen werden ist &lt;a href="https://wiki.openssl.org/index.php/tls1.3"&gt;der dokumentation fr tlsv1.3&lt;/a&gt; zu entnehmen.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;standard-wert ist leer&lt;/b&gt;', ], ], 'default_vhostconf' =&gt; [ 'title' =&gt; 'standard vhost-einstellungen', 'description' =&gt; 'der inhalt dieses feldes wird direkt den ip/port-vhost-container bernommen. die folgenden variablen knnen verwendet werden:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (wenn zutreffend)&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;achtung:&lt;/strong&gt; der code wird nicht auf fehler geprft. etwaige fehler werden also auch bernommen. der webserver knnte nicht mehr starten!', ], 'default_vhostconf_domain' =&gt; [ 'description' =&gt; 'der inhalt dieses feldes wird direkt jeden domain-vhost-container bernommen. die folgenden variablen knnen verwendet werden:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (wenn zutreffend)&lt;br/&gt;&lt;strong&gt;achtung:&lt;/strong&gt; der code wird nicht auf fehler geprft. etwaige fehler werden also auch bernommen. der webserver knnte nicht mehr starten!', ], 'apache_globaldiropt' =&gt; [ 'title' =&gt; 'kunden-prefix ordner-optionen', 'description' =&gt; 'der inhalt dieses feldes wird die 05_froxlor_dirfix_nofcgid.conf apache konfigurationsdatei eingefgt. wenn leer werden folgende standardwerte verwendet:&lt;br&gt;&lt;br&gt;apache &gt;=2.4&lt;br&gt;&lt;code&gt;require granted&lt;br&gt;allowoverride all&lt;/code&gt;&lt;br&gt;&lt;br&gt;apache &lt;=2.2&lt;br&gt;&lt;code&gt;order allow,deny&lt;br&gt;allow all&lt;/code&gt;', ], 'decimal_places' =&gt; 'nachkommastellen bei der ausgabe von traffic/webspace', 'selfdns' =&gt; [ 'title' =&gt; 'manuelle dns-einstellungen fr domains', ], 'selfdnscustomer' =&gt; [ 'title' =&gt; 'erlaube kunden eigene dns-einstellungen vorzunehmen.', ], 'unix_names' =&gt; [ 'title' =&gt; 'benutze unix-kompatible benutzernamen.', 'description' =&gt; 'erlaubt die nutzung von &lt;strong&gt;-&lt;/strong&gt; und &lt;strong&gt;_&lt;/strong&gt; benutzernamen wenn &lt;strong&gt;nein&lt;/strong&gt;.', ], 'allow_password_reset' =&gt; [ 'title' =&gt; 'erlaube das zurcksetzen des kundenpassworts.', 'description' =&gt; 'kunden knnen ihr passwort zurcksetzen und bekommen einen aktivierungs-link per e-mail zugesandt', ], 'allow_password_reset_admin' =&gt; [ 'title' =&gt; 'erlaube das zurcksetzen von admin-/reseller-passwrtern.', 'description' =&gt; 'admins/reseller knnen ihr passwort zurcksetzen und bekommen einen aktivierungs-link per e-mail zugesandt', ], 'mail_quota' =&gt; [ 'title' =&gt; 'mailbox-kontingent', 'description' =&gt; 'standard-kontingent fr neu erstellte e-mail-benutzerkonten (megabyte).', ], 'mail_quota_enabled' =&gt; [ 'title' =&gt; 'nutze e-mail-kontingent fr kunden', 'description' =&gt; 'aktiviere kontingent fr e-mail-konten. standard ist &lt;b&gt;nein&lt;/b&gt;, da dies eine spezielle konfiguration voraussetzt.', 'removelink' =&gt; 'hier klicken, um alle e-mail-kontingente zu entfernen', 'enforcelink' =&gt; 'hier klicken, um allen benutzern das standard-kontingent zu zuweisen.', ], 'session_allow_multiple_login' =&gt; [ 'title' =&gt; 'erlaube gleichzeitigen login', 'description' =&gt; 'wenn diese option aktiviert ist, knnen sich nutzer mehrmals gleichzeitig anmelden.', ], 'panel_allow_domain_change_admin' =&gt; [ 'title' =&gt; 'erlaube verschieben von domains unter admins', 'description' =&gt; 'wenn diese option aktiviert ist, kann unter domaineinstellungen die domain einem anderen admin zugewiesen werden.&lt;br /&gt;&lt;b&gt;achtung:&lt;/b&gt; wenn der kunde einer domain nicht dem gleichen admin zugeordnet ist wie die domain selbst, kann dieser admin alle anderen domains des kunden sehen!', ], 'panel_allow_domain_change_customer' =&gt; [ 'title' =&gt; 'erlaube verschieben von domains unter kunden', 'description' =&gt; 'wenn diese option aktiviert ist, kann unter domaineinstellungen die domain einem anderen kunden zugewiesen werden.&lt;br /&gt;&lt;b&gt;achtung:&lt;/b&gt; der dokumenten-pfad der domain wird auf den heimatpfad (+ domain-ordner, sofern aktiviert) des neuen kunden gesetzt.', ], 'specialsettingsforsubdomains' =&gt; [ 'description' =&gt; 'wenn ja, werden die individuellen einstellungen fr alle subdomains bernommen.&lt;br /&gt;wenn nein, werden subdomain-specialsettings entfernt.', ], 'panel_password_min_length' =&gt; [ 'title' =&gt; 'mindestlnge von passwrtern', 'description' =&gt; 'hier knnen sie die mindestlnge fr passwrter festlegen. \'0\' bedeutet: keine mindestlnge', ], 'system_store_index_file_subs' =&gt; [ 'title' =&gt; 'erstelle index-datei auch neuen unterordnern', 'description' =&gt; 'wenn aktiviert, wird fr jede subdomain mit neuem unterordner die standard-index datei angelegt.', ], 'adminmail_return' =&gt; [ 'title' =&gt; 'antwort-adresse', 'description' =&gt; 'standard-antwort-adresse fr e-mails aus dem panel.', ], 'adminmail_defname' =&gt; 'panel-absender-name', 'stdsubdomainhost' =&gt; [ 'title' =&gt; 'kunden standard-subdomain', 'description' =&gt; 'welcher hostname soll fr das erstellen der kunden-standard-subdomain verwendet werden? falls leer wird der system-hostname verwendet.', ], 'awstats_path' =&gt; 'pfad zu awstats \'awstats_buildstaticpages.pl\'', 'awstats_conf' =&gt; 'awstats konfigurations-pfad', 'defaultttl' =&gt; 'domain ttl fr bind sekunden (default \'604800\' = 1 woche)', 'defaultwebsrverrhandler_enabled' =&gt; 'verwende standard-fehlerdokumente fr alle kunden', 'defaultwebsrverrhandler_err401' =&gt; [ 'title' =&gt; 'datei/url fr fehler 401', 'description' =&gt; '&lt;div class="text-danger"&gt;nicht untersttzt in: lighttpd&lt;/div&gt;', ], 'defaultwebsrverrhandler_err403' =&gt; [ 'title' =&gt; 'datei/url fr fehler 403', 'description' =&gt; '&lt;div class="text-danger"&gt;nicht untersttzt in: lighttpd&lt;/div&gt;', ], 'defaultwebsrverrhandler_err404' =&gt; 'datei/url fr fehler 404', 'defaultwebsrverrhandler_err500' =&gt; [ 'title' =&gt; 'datei/url fr fehler 500', 'description' =&gt; '&lt;div class="text-danger"&gt;nicht untersttzt in: lighttpd&lt;/div&gt;', ], 'ftpserver' =&gt; [ 'desc' =&gt; 'wenn pureftpd ausgewhlt ist, werden die .ftpquota dateien fr das quota erstellt und tglich aktualisiert.', ], 'customredirect_enabled' =&gt; [ 'title' =&gt; 'erlaube kunden-redirect', 'description' =&gt; 'erlaubt es kunden den http-status code fr einen redirect zu whlen', ], 'customredirect_default' =&gt; [ 'title' =&gt; 'standard-redirect', 'description' =&gt; 'dieser redirect wird immer genutzt, sofern der kunde keinen anderen auswhlt.', ], 'mail_also_with_mxservers' =&gt; 'erstelle mail-, imap-, pop3- smtp-"a record" auch wenn mx-server angegeben sind', 'froxlordirectlyviahostname' =&gt; 'froxlor direkt ber den hostnamen erreichbar machen', 'panel_password_regex' =&gt; [ 'title' =&gt; 'regulrer ausdruck fr passwrter', 'description' =&gt; 'hier knnen sie einen regulren ausdruck fr passwort-komplexitt festlegen.&lt;br /&gt;leer = keine bestimmten anforderungen', ], 'perl_path' =&gt; [ 'title' =&gt; 'pfad zu perl', 'description' =&gt; 'standard ist /usr/bin/perl', ], 'mod_fcgid_ownvhost' =&gt; [ 'title' =&gt; 'verwende fcgid im froxlor-vhost', 'description' =&gt; 'wenn verwendet, wird froxlor selbst unter einem lokalen benutzer ausgefhrt', ], 'perl' =&gt; [ 'suexecworkaround' =&gt; [ 'title' =&gt; 'aktiviere suexec-workaround', 'description' =&gt; 'aktivieren sie den workaround nur, wenn die kunden-heimatverzeichnisse sich nicht unterhalb des suexec-pfades liegen.&lt;br /&gt;wenn aktiviert erstellt froxlor eine verknpfung des vom kunden fr perl aktiviertem pfad + /cgi-bin/ im angegebenen suexec-pfad.&lt;br /&gt;bitte beachten sie, dass perl dann nur im unterordner /cgi-bin/ des kunden-ordners funktioniert und nicht direkt diesem ordner (wie es ohne den workaround wre!)', ], 'suexeccgipath' =&gt; [ 'title' =&gt; 'pfad fr verknpfungen zu kunden-perl-verzeichnis', 'description' =&gt; 'diese einstellung wird nur bentigt, wenn der suexec-workaround aktiviert ist.&lt;br /&gt;achtung: stellen sie sicher, dass sich der angegebene pfad innerhalb des suexec-pfades befindet ansonsten ist der workaround nutzlos', ], ], 'awstats_awstatspath' =&gt; 'pfad zu awstats \'awstats.pl\'', 'awstats_icons' =&gt; [ 'title' =&gt; 'pfad zum awstats-icon-ordner', 'description' =&gt; 'z. b. /usr/share/awstats/htdocs/icon/', ], 'login_domain_login' =&gt; 'erlaube anmeldung mit domains', 'perl_server' =&gt; [ 'title' =&gt; 'perl server-socket', 'description' =&gt; 'eine einfache anleitung hier zu findet man unter &lt;a target="blank" href="http://wiki.nginx.org/simplecgihttps://www.nginx.com/resources/wiki/start/topics/examples/fcgiwrap/"&gt;nginx.com&lt;/a&gt;', ], 'nginx_php_backend' =&gt; [ 'title' =&gt; 'nginx-php-backend', 'description' =&gt; 'dies ist das backend, auf dem php auf anfragen von nginx hrt. kann ein unix socket oder eine ip:port kombination sein&lt;br /&gt;*nicht relevant bei php-fpm', ], 'phpreload_command' =&gt; [ 'title' =&gt; 'php-reload-befehl', 'description' =&gt; 'dieser wird bentigt, um das php-backend bei bedarf durch den cronjob neu zu laden. (standard: leer)&lt;br /&gt;*nicht relevant bei php-fpm', ], 'phpfpm' =&gt; [ 'title' =&gt; 'aktiviere php-fpm', 'description' =&gt; '&lt;b&gt;dies bentigt eine spezielle webserver-konfiguration, siehe &lt;a target="_blank" href="https://docs.froxlor.org/latest/admin-guide/configuration/php-fpm/"&gt;php-fpm handbuch&lt;/a&gt;&lt;/b&gt;', ], 'phpfpm_settings' =&gt; [ 'configdir' =&gt; 'pfad zu php-fpm-konfigurationen', 'aliasconfigdir' =&gt; 'alias-ordner der php-fpm konfiguration', 'reload' =&gt; 'kommando zum neustarten von php-fpm', 'pm' =&gt; 'prozess manager control (pm)', 'max_children' =&gt; [ 'title' =&gt; 'anzahl der kind-prozesse', 'description' =&gt; 'die anzahl der zu startenden kind-prozesse wenn pm auf \'static\' steht und die maximale anzahl der prozesse wenn pm auf \'dynamic/ondemand\' steht.&lt;br /&gt;equivalent zu php_fcgi_children', ], 'start_servers' =&gt; [ 'title' =&gt; 'anzahl der beim starten zu erstellenden kind-prozesse', 'description' =&gt; 'hinweis: nur wenn pm auf \'dynamic\' steht', ], 'min_spare_servers' =&gt; [ 'title' =&gt; 'mindestanzahl der idle-prozesse', 'description' =&gt; 'hinweis: nur wenn pm auf \'dynamic\' steht&lt;br /&gt;wichtig: pflichtangabe wenn pm auf \'dynamic\' steht', ], 'max_spare_servers' =&gt; [ 'title' =&gt; 'maximale anzahl der idle-prozesse', 'description' =&gt; 'hinweis: nur wenn pm auf \'dynamic\' steht&lt;br /&gt;wichtig: pflichtangabe wenn pm auf \'dynamic\' steht', ], 'max_requests' =&gt; [ 'title' =&gt; 'requests pro kindprozess bevor neuerstellung (respawning)', 'description' =&gt; 'fr keine begrenzung \'0\' angeben. equivalent zu php_fcgi_max_requests.', ], 'idle_timeout' =&gt; [ 'title' =&gt; 'idle-timeout', 'description' =&gt; 'timeout-einstellung fr php-fpm fastcgi.', ], 'ipcdir' =&gt; [ 'title' =&gt; 'fastcgi ipc verzeichnis', 'description' =&gt; 'in dieses verzeichnis werden die php-fpm sockets vom webserver abgelegt.&lt;br /&gt;das verzeichnis muss fr den webserver lesbar sein.', ], 'limit_extensions' =&gt; [ 'title' =&gt; 'erlaubte dateiendungen', 'description' =&gt; 'beschrnkt die dateierweiterungen des haupt-skripts, das fpm zu parsen erlaubt. dies kann konfigurationsfehler auf der webserverseite verhindern. sie sollten fpm nur auf .php erweiterungen beschrnken, um zu verhindern, dass bsartige nutzter andere erweiterungen verwenden, um php code auszufhren. standardwert: .php', ], 'envpath' =&gt; 'pfade fr die path umgebungsvariable. leerlassen, um keine path umgebungsvariable zu setzen.', 'override_fpmconfig' =&gt; 'berschreibe fpm-daemon einstellungen (pm, max_children, etc.)', 'override_fpmconfig_addinfo' =&gt; '&lt;br /&gt;&lt;span class="text-danger"&gt;nur verwendet wenn "berschreibe fpm-daemon einstellungen" auf "ja" gestellt ist&lt;/span&gt;', 'restart_note' =&gt; 'achtung: der code wird nicht auf fehler geprft. bei etwaigen fehlern knnte der php-fpm-prozess nicht mehr starten!', 'custom_config' =&gt; [ 'title' =&gt; 'benutzerdefinierte konfiguration', 'description' =&gt; 'fge eine benutzerdefinierte einstellungen zur php-fpm instanz hinzu, beispielsweise &lt;i&gt;pm.status_path = /status&lt;/i&gt; fr monitoring. unten ersichtliche variablen knnen verwendet werden. &lt;strong&gt;achtung: der code wird nicht auf fehler geprft. bei etwaigen fehlern knnte der php-fpm-prozess nicht mehr starten!&lt;/strong&gt;', ], 'allow_all_customers' =&gt; [ 'title' =&gt; 'fr aktuelle kunden automatisch hinzufgen', 'description' =&gt; 'ist diese einstellung aktiv, wird die konfiguration automatisch allen aktuell existierenden kunden-accounts zugewiesen. diese einstellung ist nicht permanent, kann aber mehrfach / nach bedarf ausgefhrt werden.', ], ], 'report' =&gt; [ 'report' =&gt; 'aktiviere das senden von reports ber webspace- und trafficverbrauch', 'webmax' =&gt; [ 'title' =&gt; 'warn-level prozent fr webspace', 'description' =&gt; 'gltige werte sind von 0 bis 150. der wert 0 deaktiviert diesen report.', ], 'trafficmax' =&gt; [ 'title' =&gt; 'warn-level prozent fr traffic', 'description' =&gt; 'gltige werte sind von 0 bis 150. der wert 0 deaktiviert diesen report.', ], ], 'dropdown' =&gt; 'auswahlliste', 'manual' =&gt; 'manuelle eingabe', 'default_theme' =&gt; 'standard-theme', 'validate_domain' =&gt; 'validiere domainnamen', 'diskquota_enabled' =&gt; 'quota aktiviert?', 'diskquota_repquota_path' =&gt; [ 'description' =&gt; 'pfad zu repquota', ], 'diskquota_quotatool_path' =&gt; [ 'description' =&gt; 'pfad zu quotatool', ], 'diskquota_customer_partition' =&gt; [ 'description' =&gt; 'partition, auf welcher die kundendaten liegen', ], 'vmail_maildirname' =&gt; [ 'title' =&gt; 'maildir-(unter-)ordner', 'description' =&gt; 'der maildir-ordner innerhalb des kontos des benutzers (normalerweise \'maildir\', manchen fllen auch \'.maildir\'). sollen die e-mails direkt das verzeichnis, diese option leer lassen.', ], 'catchall_enabled' =&gt; [ 'title' =&gt; 'catchall verwenden', 'description' =&gt; 'mchten sie ihren kunden die funktion catchall zur verfgung stellen?', ], 'apache_24' =&gt; [ 'title' =&gt; 'anpassungen fr apache 2.4 verwenden', 'description' =&gt; '&lt;div class="text-danger"&gt;achtung: bitte nur verwenden, wenn wirklich apache mit version 2.4 oder hher installiert ist, ansonsten wird der webserver nicht starten.&lt;/div&gt;', ], 'nginx_fastcgiparams' =&gt; [ 'title' =&gt; 'pfad zur fastcgi_params datei', 'description' =&gt; 'geben sie den pfad zu nginx\'s fastcgi_params datei an. inklusive dateiname!', ], 'documentroot_use_default_value' =&gt; [ 'title' =&gt; 'verwende domainnamen im documentroot', 'description' =&gt; 'wenn aktiviert wird dem standard documentroot zustzlich der domain-name angehngt.&lt;br /&gt;&lt;br /&gt;beispiel:&lt;br /&gt;/var/customers/webs/customer_name/example.tld/&lt;br /&gt;/var/customers/webs/customer_name/subdomain.example.tld/', ], 'panel_phpconfigs_hidesubdomains' =&gt; [ 'title' =&gt; 'verstecke subdomains php-konfigurations-bersicht', 'description' =&gt; 'wenn aktiviert, werden die subdomains der kunden nicht der php-konfigurations-bersicht angezeigt, lediglich die anzahl.&lt;br /&gt;&lt;br /&gt;hinweis: nur relevant, wenn fcgid oder php-fpm aktiviert ist.', ], 'panel_phpconfigs_hidestdsubdomain' =&gt; [ 'title' =&gt; 'verstecke standard-subdomains php-konfigurations-bersicht', 'description' =&gt; 'wenn aktiviert, werden die standard-subdomains der kunden nicht mehr der php-konfigurations-bersicht angezeigt.&lt;br /&gt;&lt;br /&gt;hinweis: nur relevant, wenn fcgid oder php-fpm aktiviert ist.', ], 'passwordcryptfunc' =&gt; [ 'title' =&gt; 'whlen sie die zu verwendende passwort-verschlsselungsmethode', 'description' =&gt; 'whlen sie, welche methode zur verschlsselung von kennwrtern verwendet werden soll. wenn sie diese einstellung ndern, werden nur neue kennwrter mit der neuen methode verschlsselt. bestehende passwrter werden nicht gendert.' ], 'systemdefault' =&gt; 'systemstandard', 'panel_allow_theme_change_admin' =&gt; 'erlaube admins das theme zu wechseln', 'panel_allow_theme_change_customer' =&gt; 'erlaube kunden das theme zu wechseln', 'axfrservers' =&gt; [ 'title' =&gt; 'axfr server', 'description' =&gt; 'eine durch kommas getrennte liste von ip adressen, die dns-zonen transferieren drfen (axfr).', ], 'powerdns_mode' =&gt; [ 'title' =&gt; 'powerdns operation mode', 'description' =&gt; 'whlen sie den powerdns-modus: native fr keine dns-replikation (standard) / master wenn eine dns-replikation bentigt wird.', ], 'customerssl_directory' =&gt; [ 'title' =&gt; 'webserver-kunden-ssl-zertifikatsverzeichnis', 'description' =&gt; 'wo sollen kundenspezifizierte ssl-zertifikate erstellt werden?&lt;br /&gt;&lt;br /&gt;&lt;div class="text-danger"&gt;achtung: der inhalt dieses ordners wird regelmig geleert, daher sollten dort keinerlei daten manuell abgelegt werden.&lt;/div&gt;', ], 'allow_error_report_admin' =&gt; [ 'title' =&gt; 'erlaube administrator/reseller das melden von datenbankfehlern froxlor', 'description' =&gt; 'bitte beachten: senden sie zu keiner zeit irgendwelche datenschutzrelevanten/persnlichen (kunden-)daten uns!', ], 'allow_error_report_customer' =&gt; [ 'title' =&gt; 'erlaube kunden das melden von datenbankfehlern froxlor', 'description' =&gt; 'bitte beachten: senden sie zu keiner zeit irgendwelche datenschutzrelevanten/persnlichen (kunden-)daten uns!', ], 'mailtraffic_enabled' =&gt; [ 'title' =&gt; 'analysiere mailtraffic', 'description' =&gt; 'aktiviere das analysieren der logdateien des mailsystems, um den verbrauchten traffic zu berechnen.', ], 'mdaserver' =&gt; [ 'title' =&gt; 'typ des mda', 'description' =&gt; 'der eingesetzte mail delivery server', ], 'mdalog' =&gt; [ 'title' =&gt; 'logdatei des mda', 'description' =&gt; 'die logdatei des mail delivery server', ], 'mtaserver' =&gt; [ 'title' =&gt; 'typ des mta', 'description' =&gt; 'der eingesetzte mail transfer agent', ], 'mtalog' =&gt; [ 'title' =&gt; 'logdatei des mta', 'description' =&gt; 'die logdatei des mail transfer agent', ], 'system_cronconfig' =&gt; [ 'title' =&gt; 'cron-konfigurationsdatei', 'description' =&gt; 'pfad zur konfigurationsdatei des cron-dienstes. diese datei wird von froxlor automatisch aktualisiert.&lt;br /&gt;hinweis: bitte verwenden sie &lt;strong&gt;exakt&lt;/strong&gt; die gleiche datei wie fr den froxlor-haupt-cronjob (standard: /etc/cron.d/froxlor)!&lt;br&gt;&lt;br&gt;wird &lt;b&gt;freebsd&lt;/b&gt; verwendet, sollte hier &lt;i&gt;/etc/crontab&lt;/i&gt; angegeben werden!', ], 'system_crondreload' =&gt; [ 'title' =&gt; 'cron-daemon reload befehl', 'description' =&gt; 'geben sie hier den befehl zum neuladen des cron-daemons an', ], 'system_croncmdline' =&gt; [ 'title' =&gt; 'cron startbefehl (php programm)', 'description' =&gt; 'befehl zum ausfhren des cronjobs. ndern dieser einstellung nur wenn ntig (standard: "/usr/bin/nice -n 5 /usr/bin/php -q")!', ], 'system_cron_allowautoupdate' =&gt; [ 'title' =&gt; 'erlaube automatische datenbank-aktualisierungen', 'description' =&gt; '&lt;strong class="text-danger"&gt;warnung:&lt;/strong&gt; diese einstellung erlaubt es dem cronjob die prfung der dateien- und datenbank-version zu umgehen und bei einem versions-unterschied die datenbank-aktualisierungen automatisiert auszufhren.&lt;br /&gt;&lt;br/&gt;&lt;div class="text-danger"&gt;das automatische update setzt fr neue einstellungen und nderungen immer die default-werte. diese mssen nicht zwingend zu dem genutzten system passen. bitte zwei mal nachdenken, bevor diese option aktiviert wird.&lt;/div&gt;', ], 'dns_createhostnameentry' =&gt; 'erstelle bind-zone/konfiguration fr den system-hostnamen', 'panel_password_alpha_lower' =&gt; [ 'title' =&gt; 'kleinbuchstaben', 'description' =&gt; 'das passwort muss mindestens einen kleinbuchstaben (a-z) enthalten.', ], 'panel_password_alpha_upper' =&gt; [ 'title' =&gt; 'grobuchstaben', 'description' =&gt; 'das passwort muss mindestens einen grobuchstaben (a-z) enthalten.', ], 'panel_password_numeric' =&gt; [ 'title' =&gt; 'zahlen', 'description' =&gt; 'das passwort muss mindestens eine zahl (0-9) enthalten.', ], 'panel_password_special_char_required' =&gt; [ 'title' =&gt; 'sonderzeichen', 'description' =&gt; 'das passwort muss mindestens eines der untenstehenden sonderzeichen enthalten', ], 'panel_password_special_char' =&gt; [ 'title' =&gt; 'sonderzeichen-liste', 'description' =&gt; 'mindestens eines dieser sonderzeichen muss dem passwort vorkommen, sofern die sonderzeichen-option aktiviert ist.', ], 'apache_itksupport' =&gt; [ 'title' =&gt; 'anpassungen fr apache itk-mpm verwenden', 'description' =&gt; '&lt;div class="text-danger"&gt;achtung: bitte nur verwenden, wenn wirklich apache itk-mpm verwendet wird, ansonsten wird der webserver nicht starten.&lt;/div&gt;', ], 'letsencryptca' =&gt; [ 'title' =&gt; 'acme umgebung', 'description' =&gt; 'umgebung, welche genutzt wird um zertifikate zu bestellen.', ], 'letsencryptchallengepath' =&gt; [ 'title' =&gt; 'verzeichnis fr let\'s encrypt challenges', 'description' =&gt; 'let\'s encrypt challenges werden aus diesem verzeichnis ber einen globalen alias ausgeliefert.', ], 'letsencryptkeysize' =&gt; [ 'title' =&gt; 'schlsselgre fr neue let\'s encrypt zertifikate', 'description' =&gt; 'gre des schlssels bit fr neue let\'s encrypt zertifikate.', ], 'letsencryptreuseold' =&gt; [ 'title' =&gt; 'let\'s encrypt schlssel wiederverwenden', 'description' =&gt; 'wenn dies aktiviert ist, wird der alte schlssel bei jeder verlngerung verwendet, andernfalls wird ein neues paar generiert.', ], 'leenabled' =&gt; [ 'title' =&gt; 'let\'s encrypt verwenden', 'description' =&gt; 'wenn dies aktiviert ist, knnen kunden durch froxlor automatisch generierte und verlngerbare let\'s encrypt ssl-zertifikate fr domains mit ssl ip/port nutzen.&lt;br /&gt;&lt;br /&gt;bitte die webserver-konfiguration beachten wenn aktiviert, da dieses feature eine spezielle konfiguration bentigt.', ], 'caa_entry' =&gt; [ 'title' =&gt; 'caa dns eintrge generieren', 'description' =&gt; 'generiert caa eintrge automatisch fr alle domains mit aktiviertem ssl und let\'s encrypt', ], 'caa_entry_custom' =&gt; [ 'title' =&gt; 'zustzliche caa dns eintrge', 'description' =&gt; 'dns certification authority authorization (caa) verwendet das domain name system, um dem besitzer einer domain die mglichkeit zu bieten, gewisse zertifizierungsstellen (cas) dazu zu berechtigen,&lt;br&gt;ein zertifikat fr die betroffene domain auszustellen. caa records sollen verhindern, dass zertifikate flschlicherweise fr eine domain ausgestellt werden.&lt;br&gt;&lt;br&gt;der inhalt dieses feldes wird direkt die dns zone bernommen (eine zeile pro caa record). wenn let\'s encrypt fr eine domain aktiviert wurde und die obige option aktiviert wurde, wird immer automatisch dieser eintrag angefgt und muss nicht selber angegeben werden:&lt;br&gt;&lt;code&gt;0 issue "letsencrypt.org"&lt;/code&gt; (wenn wildcard aktiviert ist, wird statdessen issuewild benutzt).&lt;br&gt;um incident reporting per mail zu aktivieren, muss eine &lt;code&gt;iodef&lt;/code&gt; zeile angefgt werden. ein beispiel fr einen report &lt;code&gt;me@example.com&lt;/code&gt; wre:&lt;br&gt;&lt;code&gt;0 iodef "mailto:me@example.com"&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;strong&gt;achtung:&lt;/strong&gt; der code wird nicht auf fehler geprft. etwaige fehler werden also auch bernommen. die caa finalen eintrge knnten daher falsch sein!', ], 'exportenabled' =&gt; [ 'title' =&gt; 'daten-export fr kunden aktivieren', 'description' =&gt; 'wenn dies aktiviert ist, kann der kunde daten-exporte planen (cron-export) welche ein archiv sein heimatverzeichnis ablegen (unterordner vom kunden whlbar)', ], 'dnseditorenable' =&gt; [ 'title' =&gt; 'dns editor aktivieren', 'description' =&gt; 'erlaubt es admins und kunden die dns eintrge ihrer domains zu verwalten.', ], 'dns_server' =&gt; [ 'title' =&gt; 'dns server dienst', 'description' =&gt; 'dienste mssen mit den froxlor konfigurationstemplates konfiguriert werden', ], 'panel_customer_hide_options' =&gt; [ 'title' =&gt; 'menpunkte und traffic-charts im kundenbereich ausblenden', 'description' =&gt; 'whlen sie hier die gewnschten menpunkte und traffic-charts aus, welche im kundenbereich ausgeblendet werden sollen. fr mehrfachauswahl, halten sie whrend der auswahl strg gedrckt.', ], 'allow_allow_customer_shell' =&gt; [ 'title' =&gt; 'erlaube kunden fr ftp benutzer eine shell auszuwhlen', 'description' =&gt; '&lt;strong class="text-danger"&gt;bitte beachten: shell zugriff gestattet dem benutzer verschiedene programme auf ihrem system auszufhren. mit groer vorsicht verwenden. bitte aktiviere dies nur wenn wirklich bekannt ist, das bedeutet!!!&lt;/strong&gt;', ], 'available_shells' =&gt; [ 'title' =&gt; 'liste der verfgbaren shells', 'description' =&gt; 'komma-getrennte liste von shells, die der kunde fr seine ftp-konten whlen kann.&lt;br&gt;&lt;br&gt;hinweis: die standard-shell &lt;strong&gt;/bin/false&lt;/strong&gt; wird immer eine auswahlmglichkeit sein (wenn aktiviert), auch wenn diese einstellung leer ist. sie ist jedem fall der standardwert fr alle ftp-konten', ], 'le_froxlor_enabled' =&gt; [ 'title' =&gt; 'let\'s encrypt fr den froxlor vhost verwenden', 'description' =&gt; 'wenn dies aktiviert ist, erstellt froxlor fr seinen vhost automatisch ein let\'s encrypt zertifikat.', ], 'le_froxlor_redirect' =&gt; [ 'title' =&gt; 'ssl-weiterleitung fr den froxlor vhost aktivieren', 'description' =&gt; 'wenn dies aktiviert ist, werden alle http anfragen die entsprechende ssl seite weitergeleitet.', ], 'option_unavailable_websrv' =&gt; '&lt;br&gt;&lt;em class="text-danger"&gt;nur verfgbar fr: %s&lt;/em&gt;', 'option_unavailable' =&gt; '&lt;br&gt;&lt;em class="text-danger"&gt;option aufgrund anderer einstellungen nicht verfgbar.&lt;/em&gt;', 'letsencryptacmeconf' =&gt; [ 'title' =&gt; 'pfad zu acme.conf', 'description' =&gt; 'dateiname der konfiguration, die dem webserver erlaubt, die acme-challenges zu bedienen.', ], 'mail_use_smtp' =&gt; 'nutze smtp fr das senden von e-mails', 'mail_smtp_host' =&gt; 'smtp server', 'mail_smtp_usetls' =&gt; 'aktiviere tls verschlsselung', 'mail_smtp_auth' =&gt; 'nutze smtp authentifizierung', 'mail_smtp_port' =&gt; 'tcp port fr smtp', 'mail_smtp_user' =&gt; 'smtp benutzer', 'mail_smtp_passwd' =&gt; 'smtp passwort', 'http2_support' =&gt; [ 'title' =&gt; 'http2 untersttzung', 'description' =&gt; 'aktiviere http2 untersttzung fr ssl.&lt;br&gt;&lt;em class="text-danger"&gt;nur aktivieren, wenn der webserver diese funktion untersttzt (nginx version 1.9.5+, apache2 version 2.4.17+)&lt;/em&gt;', ], 'nssextrausers' =&gt; [ 'title' =&gt; 'verwende libnss-extrausers anstatt libnss-mysql', 'description' =&gt; 'lese benutzer nicht direkt aus der datenbank sondern ber dateien. bitte nur aktivieren, wenn die entsprechende konfiguration vorgenommen wurde (system -&gt; libnss-extrausers).&lt;br&gt;&lt;strong class="text-danger"&gt;nur fr debian/ubuntu (oder wenn libnss-extrausers manuell kompiliert wurde!)&lt;/strong&gt;', ], 'le_domain_dnscheck' =&gt; [ 'title' =&gt; 'validiere dns der domains wenn let\'s encrypt genutzt wird', 'description' =&gt; 'wenn aktiviert wird froxlor berprfen ob die dns eintrge der domains, welche ein let\'s encrypt zertifikat beantragt, mindestens auf eine der system ip adressen auflst.', ], 'le_domain_dnscheck_resolver' =&gt; [ 'title' =&gt; 'dns resolver fr die dns berprfung', 'description' =&gt; 'ip adresse des dns servers, welcher fr die dns berprfung genutzt werden soll. wenn leer, wird der standard dns resolver des systems genutzt.', ], 'phpsettingsforsubdomains' =&gt; [ 'description' =&gt; 'wenn ja, wird die gewhlte php-config fr alle subdomains bernommen', ], 'leapiversion' =&gt; [ 'title' =&gt; 'whlen sie die let\'s encrypt acme implementierung', 'description' =&gt; 'aktuell untersttzt froxlor lediglich die acme v2 implementierung von let\'s encrypt.', ], 'enable_api' =&gt; [ 'title' =&gt; 'aktiviere externe api nutzung', 'description' =&gt; 'um die froxlor api nutzen zu knnen, muss diese option aktiviert sein. fr detaillierte informationen siehe &lt;a href="https://docs.froxlor.org/latest/api-guide/" target="_new"&gt;https://docs.froxlor.org/&lt;/a&gt;', ], 'api_customer_default' =&gt; '"erlaube api nutzung" vorbelegung fr neue kunden', 'dhparams_file' =&gt; [ 'title' =&gt; 'dhparams datei (diffiehellman key exchange)', 'description' =&gt; 'wird eine dhparams.pem datei hier angegeben, wir sie die webserver konfiguration mit eingefgt.&lt;br&gt;beispiel: /etc/ssl/webserver/dhparams.pem&lt;br&gt;&lt;br&gt;existiert die datei nicht, wird sie wie folgt erstellt: &lt;code&gt;openssl dhparam -out /etc/ssl/webserver/dhparams.pem 4096&lt;/code&gt;. es wird empfohlen die datei zu erstellen, bevor sie hier angegeben wird, da die erstellung lngere zeit anspruch nimmt und den cronjob blockiert.', ], 'errorlog_level' =&gt; [ 'title' =&gt; 'ausfhrlichkeit des fehlerprotokolls', 'description' =&gt; 'steuert die ausfhrlichkeit des fehlerprotokolls. voreinstellung ist "warn" bei apache und "error" bei nginx.', ], 'letsencryptecc' =&gt; [ 'title' =&gt; 'ecc / ecdsa zertifikate ausstellen', 'description' =&gt; 'wenn eine schlsselgre ausgewhlt wird, werden ecc / ecdsa zertifikate erstellt', ], 'froxloraliases' =&gt; [ 'title' =&gt; 'domain aliase fr froxlor vhost', 'description' =&gt; 'komma getrennte liste von domains, welche als server alias zum froxlor vhost hinzugefgt werden', ], 'default_sslvhostconf' =&gt; [ 'title' =&gt; 'standard ssl vhost-einstellungen', 'description' =&gt; 'der inhalt dieses feldes wird direkt den ip/port-vhost-container bernommen. die folgenden variablen knnen verwendet werden:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (wenn zutreffend)&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;achtung:&lt;/strong&gt; der code wird nicht auf fehler geprft. etwaige fehler werden also auch bernommen. der webserver knnte nicht mehr starten!', ], 'includedefault_sslvhostconf' =&gt; 'nicht-ssl vhost-einstellungen ssl-vhost inkludieren', 'apply_specialsettings_default' =&gt; 'standardwert fr "bernehme einstellungen fr alle subdomains (*.beispiel.de)" einstellung beim bearbeiten einer domain', 'apply_phpconfigs_default' =&gt; 'standardwert fr "php-config fr alle subdomains bernehmen:" einstellung beim bearbeiten einer domain', 'awstats' =&gt; [ 'logformat' =&gt; [ 'title' =&gt; 'logformat einstellung', 'description' =&gt; 'wenn ein benutzerdefiniertes logformat beim webserver verwendet wird, muss logformat von awstats ebenso angepasst werden.&lt;br/&gt;standard ist 1. fr weitere informationen siehe dokumentation unter &lt;a target="_blank" href="https://awstats.sourceforge.io/docs/awstats_config.html#logformat"&gt;hier&lt;/a&gt;.', ], ], 'hide_incompatible_settings' =&gt; 'inkompatible einstellungen ausblenden', 'soaemail' =&gt; 'mail-adresse fr soa-eintrge (verwendet panel-absender-name der panel-einstellungen falls leer)', 'imprint_url' =&gt; [ 'title' =&gt; 'url zum impressum', 'description' =&gt; 'die url zur impressums-seite. der link ist auf der login-seite und wenn eingeloggt, der fuzeile sichtbar.', ], 'terms_url' =&gt; [ 'title' =&gt; 'url zu den agb', 'description' =&gt; 'die url zur agb-seite. der link ist auf der login-seite und wenn eingeloggt, der fuzeile sichtbar.', ], 'privacy_url' =&gt; [ 'title' =&gt; 'url zur datenschutzerklrung', 'description' =&gt; 'die url zur datenschutzerklrungs-seite. der link ist auf der login-seite und wenn eingeloggt, der fuzeile sichtbar.', ], 'logo_image_header' =&gt; [ 'title' =&gt; 'logo bild (header)', 'description' =&gt; 'das hochgeladene bild wird als logo oben links nach dem login angezeigt (empfohlene hhe sind 30px)', ], 'logo_image_login' =&gt; [ 'title' =&gt; 'logo bild (login)', 'description' =&gt; 'das hochgeladene bild wird als logo whrend des logins angezeigt', ], 'logo_overridetheme' =&gt; [ 'title' =&gt; 'berschreibe theme-logo mit "logo bild" (header und login, siehe unten)', 'description' =&gt; 'ist die nutzung eines hochgeladenen logos gewnscht, muss diese einstellung auf "ja" gesetzt werden. alternativ kann weiterhin das theme-basierte berschreiben via "logo_custom.png" und "logo_custom_login.png" genutzt werden.', ], 'logo_overridecustom' =&gt; [ 'title' =&gt; 'berschreibe benutzerdefinierte theme-logos (logo_custom.png und logo_custom_login.png) mit "logo bold" (header und login, siehe unten)', 'description' =&gt; 'ist diese einstellung aktiv, werden benutzerdefinierte logos im theme-ordner mit dem "logo bild" ersetzt', ], 'createstdsubdom_default' =&gt; [ 'title' =&gt; 'standardwert fr "standardsubdomain anlegen" bei erstellung eines kunden', 'description' =&gt; '', ], 'froxlorusergroup' =&gt; [ 'title' =&gt; 'benutzerdefinierte gruppe fr alle kunden-benutzer', 'description' =&gt; 'voraussetzung hierfr ist die nutzung von libnss-extrausers (system-einstellungen). ein leerer wert bedeutet, es wird keine gruppe erstellt, bzw. vorhandene gruppe wird entfernt.', ], 'acmeshpath' =&gt; [ 'title' =&gt; 'pfad zu acme.sh', 'description' =&gt; 'installationspfad zu acme.sh, inklusive acme.sh script&lt;br&gt;standard ist &lt;b&gt;/root/.acme.sh/acme.sh&lt;/b&gt;', ], 'update_channel' =&gt; [ 'title' =&gt; 'froxlor update kanal', 'description' =&gt; 'whle den bevorzugten update kanal. standard ist "stable"', ], 'traffictool' =&gt; [ 'toolselect' =&gt; 'traffic analyzer', ], 'requires_reconfiguration' =&gt; 'nderungen dieser einstellungen bentigen unter umstnden eine erneute konfiguration der folgenden dienste:&lt;br&gt;&lt;strong&gt;%s&lt;/strong&gt;', 'req_limit_per_interval' =&gt; [ 'title' =&gt; 'anzahl der http-anfragen pro intervall', 'description' =&gt; 'erlaubte anzahl von http-anfragen pro intervall (siehe unten) auf froxlor, standard ist "60"', ], 'req_limit_interval' =&gt; [ 'title' =&gt; 'rate-limit-intervall', 'description' =&gt; 'zeit sekunden fr die maximale anzahl von http-anfragen, standard ist "60".', ], 'option_requires_otp' =&gt; 'das ndern dieser einstellung erfordert otp validierung', 'panel_menu_collapsed' =&gt; [ 'title' =&gt; 'menabschnitte einklappen', 'description' =&gt; 'bei deaktivierung werden die menbereiche auf der linken seite immer aufgeklappt angezeigt.', ], 'le_renew_services' =&gt; [ 'title' =&gt; 'verwende das froxlor let\'s encrypt zertifikat fr folgende dienste', 'description' =&gt; 'wenn auf "keine" gesetzt (oder der renew-hook-befehl unten leer ist), werden keine konfigurationsanpassungen bezglich ssl den ausgewhlten diensten vorgenommen.&lt;br&gt;&lt;br&gt;der reload-befehl fr die ausgewhlten dienste sollte im renew-hook-befehl hinzugefgt werden, da sonst die konfigurationsnderungen oder erneuerten zertifikate mglicherweise nicht korrekt angewendet werden.', ], 'le_renew_hook' =&gt; [ 'title' =&gt; 'let\'s encrypt renew-hook befehl', 'description' =&gt; 'lege den befehl fest, der die oben ausgewhlten dienste neu startet, damit erneuerte zertifikate vom dienst ordnungsgem verwendet werden.', ], ], 'spf' =&gt; [ 'use_spf' =&gt; [ 'title' =&gt; 'aktiviere spf fr domains?', 'description' =&gt; 'erfordert einen speziellen dns eintrag fr die domain. wenn das nameserver-feature nicht genutzt wird, muss dieser eintrag manuell verwaltet werden.', ], 'spf_entry' =&gt; 'spf-eintrag fr alle domains', ], 'dmarc' =&gt; [ 'use_dmarc' =&gt; [ 'title' =&gt; 'aktiviere dmarc fr domains?', 'description' =&gt; 'erfordert einen speziellen dns eintrag fr die domain. wenn das nameserver-feature nicht genutzt wird, muss dieser eintrag manuell verwaltet werden.', ], 'dmarc_entry' =&gt; 'dmarc-eintrag fr alle domains', ], 'success' =&gt; [ 'success' =&gt; 'information', 'clickheretocontinue' =&gt; 'hier klicken, um fortzufahren', 'settingssaved' =&gt; 'die einstellungen wurden erfolgreich gespeichert.', 'rebuildingconfigs' =&gt; 'task fr neuerstellung der konfigurationen wurde erfolgreich eingetragen', 'domain_import_successfully' =&gt; 'erfolgreich %s domains importiert.', 'exportscheduled' =&gt; 'ihr daten-export wurde erfolgreich geplant. bitte warten sie nun, bis dieser bearbeitet wurde.', 'exportaborted' =&gt; 'der geplante daten-export wurde abgebrochen', 'dns_record_added' =&gt; 'eintrag erfolgreich hinzugefgt', 'dns_record_deleted' =&gt; 'eintrag erfolgreich entfernt', 'testmailsent' =&gt; 'test e-mail erfolgreich gesendet', 'settingsimported' =&gt; 'einstellungnen erfolgreich importiert', 'sent_error_report' =&gt; 'fehlerbericht erfolgreich gesendet. danke fr die untersttzung.', ], 'tasks' =&gt; [ 'outstanding_tasks' =&gt; 'ausstehende cron-aufgaben', 'rebuild_vhost' =&gt; 'neuerstellung der webserver-konfiguration', 'create_home' =&gt; 'erstelle neuen kunden %s', 'rebuild_dns' =&gt; 'neuerstellung der bind-konfiguration', 'create_ftp' =&gt; 'erstelle verzeichnis fr neuen ftp-benutzer', 'delete_customer_files' =&gt; 'lschen von kunden-dateien %s', 'noneoutstanding' =&gt; 'zur zeit gibt es keine ausstehenden aufgaben fr froxlor', 'delete_email_data' =&gt; 'e-mail-dateien des kunden lschen', 'delete_ftp_data' =&gt; 'kunden ftp-konto dateien lschen', 'rebuild_rspamd' =&gt; 'neuerstellung der antispam-konfiguration', 'create_quota' =&gt; 'quota auf dem dateisystem setzen', 'rebuild_cron' =&gt; 'neuerstellung der cron.d-datei', 'create_customer_datadump' =&gt; 'daten-export fr kunde %s', 'delete_domain_pdns' =&gt; 'lsche domain %s von powerdns datenbank', 'delete_domain_ssl' =&gt; 'lsche ssl dateien von domain %s', 'update_le_services' =&gt; 'aktualisiere systemdienste fr let\'s encrypt', ], 'terms' =&gt; 'agb', 'traffic' =&gt; [ 'month' =&gt; 'monat', 'months' =&gt; [ 1 =&gt; 'januar', 2 =&gt; 'februar', 3 =&gt; 'mrz', 4 =&gt; 'april', 5 =&gt; 'mai', 6 =&gt; 'juni', 7 =&gt; 'juli', 8 =&gt; 'august', 9 =&gt; 'september', 10 =&gt; 'oktober', 11 =&gt; 'november', 12 =&gt; 'dezember', 'jan' =&gt; 'jan', 'feb' =&gt; 'feb', 'mar' =&gt; 'mr', 'apr' =&gt; 'apr', 'may' =&gt; 'mai', 'jun' =&gt; 'jun', 'jul' =&gt; 'jul', 'aug' =&gt; 'aug', 'sep' =&gt; 'sep', 'oct' =&gt; 'okt', 'nov' =&gt; 'nov', 'dec' =&gt; 'dez', 'total' =&gt; 'gesamt', ], 'mb' =&gt; 'traffic', 'day' =&gt; 'tag', 'sumtotal' =&gt; 'gesamt traffic', 'sumhttp' =&gt; 'http-traffic', 'sumftp' =&gt; 'ftp-traffic', 'summail' =&gt; 'mail-traffic', 'customer' =&gt; 'kunde', 'trafficoverview' =&gt; 'bersicht traffic', 'bycustomers' =&gt; 'traffic nach kunden', 'details' =&gt; 'details', 'http' =&gt; 'http', 'ftp' =&gt; 'ftp', 'mail' =&gt; 'mail', 'nocustomers' =&gt; 'es wird mindestens ein kunde bentigt um die traffic statistiken anzuzeigen.', 'top5customers' =&gt; 'top 5 kunden', 'nodata' =&gt; 'keine daten im angegebenen zeitraum.', 'ranges' =&gt; [ 'last24h' =&gt; 'die letzten 24 std', 'last7d' =&gt; 'die letzten 7 tage', 'last30d' =&gt; 'die letzten 30 tage', 'cm' =&gt; 'aktueller monat', 'last3m' =&gt; 'die letzten 3 monate', 'last6m' =&gt; 'die letzten 6 monate', 'last12m' =&gt; 'die letzten 12 monate', 'cy' =&gt; 'aktuelles jahr', ], 'byrange' =&gt; 'nach angegebenem zeitraum', ], 'translator' =&gt; '', 'update' =&gt; [ 'updateinprogress_onlyadmincanlogin' =&gt; 'eine neuere version von froxlor wurde installiert, aber noch nicht eingerichtet.&lt;br /&gt;nur der administrator kann sich anmelden und die aktualisierung abschlieen.', 'update' =&gt; 'froxlor aktualisierung', 'proceed' =&gt; 'ausfhren', 'update_information' =&gt; [ 'part_a' =&gt; 'die froxlor-dateien wurden aktualisiert. neue version ist &lt;strong&gt;%s&lt;/strong&gt;. die bisher installierte version ist &lt;strong&gt;%s&lt;/strong&gt;', 'part_b' =&gt; '&lt;br /&gt;&lt;br /&gt;ein kunden-login ist vor abschluss des aktualisierungsvorganges nicht mglich.&lt;br /&gt;&lt;strong&gt;aktualisierung ausfhren?&lt;/strong&gt;', ], 'noupdatesavail' =&gt; 'die genutzte %sversion von froxlor ist aktuell.', 'description' =&gt; 'aktualisierung der froxlor datenbank', 'uc_newinfo' =&gt; 'eine neuere %sversion ist verfgbar: "%s" (aktuell installierte version: %s)', 'notify_subject' =&gt; 'neues update verfgbar', 'dbupdate_required' =&gt; 'froxlor-dateien wurden aktualisiert, datenbank-aktualisierung notwendig', ], 'usersettings' =&gt; [ 'custom_notes' =&gt; [ 'title' =&gt; 'eigene notizen', 'description' =&gt; 'hier knnen notizen je nach lust und laune eingetragen werden. diese werden der administrator/kunden-bersicht bei dem jeweiligen benutzer angezeigt.&lt;br&gt;markdown ist untersttzt, html wird entfernt.', 'show' =&gt; 'zeige die notizen auf dem dashboard des benutzers', ], 'api_allowed' =&gt; [ 'title' =&gt; 'erlaube api zugriff', 'description' =&gt; 'wenn den einstellungen aktiviert, kann der benutzer api schlssel erstellen und auf die froxlor api zugreifen', 'notice' =&gt; 'api zugriff ist fr dieses konto deaktiviert.', ], 'gui_access' =&gt; [ 'title' =&gt; 'webui-anmeldung zulassen', 'description' =&gt; 'wenn diese option deaktiviert ist, kann sich der benutzer nicht bei der froxlor-weboberflche anmelden, aber alle dienste (web, ftp, e-mail, datenbanken, api-zugriff, usw.) funktionieren normal.', ], ], 'install' =&gt; [ 'preflight' =&gt; 'system-prfung', 'critical_error' =&gt; 'kritischer fehler', 'suggestions' =&gt; 'nicht notwendig, aber emfohlen', 'phpinfosuccess' =&gt; 'auf dem system ist php %s installiert', 'suggestionsnote' =&gt; 'es liegen keine kritische fehler vor, die eine installation verhindern, allerdings beachten sie bitte die empfehlungen weiter unten fr ein optimales erlebnis.', 'phpinfowarn' =&gt; 'die genutzte php version ist kleiner als die geforderte version %s', 'phpinfoupdate' =&gt; 'aktualisierung von php version %s auf %s oder hher notwendig', 'start_installation' =&gt; 'installation starten', 'check_again' =&gt; 'erneut prfen...', 'switchmode_advanced' =&gt; 'erweiterte optionen anzeigen', 'switchmode_basic' =&gt; 'erweiterte optionen ausblenden', 'dependency_check' =&gt; [ 'title' =&gt; 'willkommen bei froxlor', 'description' =&gt; 'das system wird auf abhngigkeiten berprft, um sicher zu stellen das alle erforderlichen php erweiterungen vorhanden und aktiviert sind, dass froxlor einwandfrei funktioniert.', ], 'database' =&gt; [ 'top' =&gt; 'datenbank', 'title' =&gt; 'datenbank und benutzer erstellen', 'description' =&gt; 'froxlor bentigt eine datenbank und zustzlich &lt;a href="https://docs.froxlor.org/latest/general/installation/tarball.html#_3-create-privileged-database-user" target="_blank"&gt;einen benutzer mit privilegierten rechten&lt;/a&gt;, welcher benutzer und datenbanken erstellen darf (grant option). die angegebene datenbank und der unprivilegierte benutzer werden automatisch diesem prozess erstellt. der privilegierte benutzer muss existieren.', 'user' =&gt; 'unprivilegierter datenbank benutzer', 'dbname' =&gt; 'datenbank name', 'force_create' =&gt; 'sichern und berschreiben, sofern datenbank existiert?', ], 'admin' =&gt; [ 'top' =&gt; 'admin konto', 'title' =&gt; 'erstellen des haupt-administrators.', 'description' =&gt; 'dieser benutzer erhlt alle berechtigungen zur anpassungen von einstellungen und erstellen/bearbeiten/lschen von resourcen wie kunden, domains, etc.', 'use_admin_email_as_sender' =&gt; 'verwende die oben angegebene e-mail-adresse als absenderadresse. wenn die option deaktiviert ist, geben sie unten bitte eine absenderadresse an.', 'use_autogenerated_email_as_sender' =&gt; 'leer lassen fr standard: admin@servername', ], 'system' =&gt; [ 'top' =&gt; 'system setup', 'title' =&gt; 'detailangaben zum server', 'description' =&gt; 'gebe hier informationen und relevante daten zu dem server damit froxlor dein system kennt. diese angaben sind entscheidend fr die konfiguration und den betrieb der dienste.', 'ipv4' =&gt; 'primre ipv4 adresse (sofern zutreffend)', 'ipv6' =&gt; 'primre ipv6 adresse (sofern zutreffend)', 'servername' =&gt; 'server name (fqdn, keine ip adresse)', 'phpbackend' =&gt; 'php backend', 'activate_newsfeed' =&gt; 'offizielles newsfeed aktivieren&lt;br&gt;&lt;small&gt;(externe quelle: https://inside.froxlor.org/news/)&lt;/small&gt;', ], 'install' =&gt; [ 'top' =&gt; 'abschluss', 'title' =&gt; 'ein letzter schritt...', 'description' =&gt; 'der untenstehende befehl ldt, installiert und konfiguriert die bentigten dienste auf dem system aufgrund der angaben die whrend des installationsprozessen gesammelt wurden.&lt;br&gt;&lt;br&gt;&lt;span class="text-danger"&gt;fhre die gezeigten befehle als &lt;b&gt;root&lt;/b&gt; der shell/konsole des servers aus. &lt;b&gt;beachte bitte&lt;/b&gt; das dieser befehl vorhandene konfigurationen &lt;b&gt;berschreibt&lt;/b&gt; (sicherungsdateien werden erstellt)!&lt;br&gt;sollte dies nicht gewnscht sein, whle &lt;i&gt;ich werden die dienste manuell konfigurieren&lt;/i&gt; ende dieser seite.&lt;/span&gt;', 'runcmd' =&gt; 'folgende befehle ausfhren, um die installation abzuschlieen:', 'manual_config' =&gt; 'ich werden die dienste manuell konfigurieren, direkt zum login umleiten', 'waitforconfig' =&gt; 'warte auf abschluss der dienstkonfiguration...', ], 'errors' =&gt; [ 'wrong_ownership' =&gt; 'die froxlor dateien gehren nicht vollstndig dem benutzer %s:%s', 'missing_extensions' =&gt; 'folgende php erweiterungen werden zustzlich bentigt', 'suggestedextensions' =&gt; 'folgende php erweiterungen werden empfohlen', 'databaseexists' =&gt; 'datenbank existiert bereits, uberschreiben-option oder anderen namen whlen.', 'unabletocreatedb' =&gt; 'test-datenbank konnte nicht erstellt werden', 'unabletodropdb' =&gt; 'test-datenbank konnte nicht gelscht werden', 'mysqlusernameexists' =&gt; 'der unprivilegierte datenbank-benutzer existiert bereits. anderen benutzername angeben oder vorhandenen benutzer lschen.', 'unabletocreateuser' =&gt; 'test-benutzer konnte nicht erstellt werden', 'unabletodropuser' =&gt; 'test-benutzer konnte nicht gelscht werden', 'unabletoflushprivs' =&gt; 'der privilegierte benutzer kann berechtigungen nicht bernehmen (flush privileges)', 'nov4andnov6ip' =&gt; 'es muss mindestens eine ipv4- oder ipv6-adresse angegeben werden', 'servernameneedstobevalid' =&gt; 'der angegebene server-name scheint kein gltiger fqdn oder hostname zu sein', 'websrvuserdoesnotexist' =&gt; 'der angegebene webserver-benutzer scheint auf dem system nicht zu existieren', 'websrvgrpdoesnotexist' =&gt; 'die angegebene webserver-gruppe scheint auf dem system nicht zu existieren', 'notyetconfigured' =&gt; 'es scheint als wren die dienste (noch) nicht erfolgreich konfiguriert worden. bitte den angezeigten befehl ausfhren oder berspringen (direkt zum login)', 'mandatory_field_not_set' =&gt; 'pflichtfeld "%s" ist nicht gesetzt!', 'unexpected_database_error' =&gt; 'eine unerwarteter datenbankfehler ist aufgetreten. %s', 'sql_import_failed' =&gt; 'der import von sql-daten ist fehlgeschlagen!', 'unprivileged_sql_connection_failed' =&gt; 'unprivilegierte sql-verbindung konnte nicht initialisiert werden!', 'privileged_sql_connection_failed' =&gt; 'initialisierung der privilegierten sql-verbindung fehlgeschlagen!', 'mysqldump_backup_failed' =&gt; 'es kann keine datenbanksicherung erstellt werden, wir haben einen fehler von mysqldump erhalten.', 'sql_backup_file_missing' =&gt; 'es kann keine datenbanksicherung erstellt werden, die sicherungsdatei ist nicht vorhanden.', 'backup_binary_missing' =&gt; 'es kann keine datenbanksicherung erstellen werden, stelle sicher, dass mysqldump installiert wurde.', 'creating_configfile_failed' =&gt; 'konfigurationsdateien knnen nicht erstellt werden, datei kann nicht geschrieben werden.', 'database_already_exiting' =&gt; 'es existiert bereits eine datenbank, diese darf aber nicht berschreiben werden!' ] ], 'welcome' =&gt; [ 'title' =&gt; 'willkommen bei froxlor!', 'config_note' =&gt; 'damit froxlor mit dem backend vernnftig kommunizieren kann, musst du dieses noch konfigurieren.', 'config_now' =&gt; 'jetzt konfigurieren' ], ];</file><file name="lng/pt.lng.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @author ricardo luiz costa &lt;ricardo@winger.com.br&gt; * @author thiago goncalves de castro &lt;thiago@davoi.com.br&gt; * @author rafael andrade &lt;slyppp@gmail.com&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'admin' =&gt; [ 'overview' =&gt; 'viso geral', 'ressourcedetails' =&gt; 'recursos usados', 'systemdetails' =&gt; 'detalhes sistema', 'froxlordetails' =&gt; 'detalhes froxlor', 'installedversion' =&gt; 'verso instalada', 'latestversion' =&gt; 'ultima verso', 'lookfornewversion' =&gt; [ 'clickhere' =&gt; 'procurar pela internet', 'error' =&gt; 'erro de leitura', ], 'resources' =&gt; 'recursos', 'customer' =&gt; 'cliente', 'customers' =&gt; 'clientes', 'customer_add' =&gt; 'criar cliente', 'customer_edit' =&gt; 'editar cliente', 'domains' =&gt; 'domnios', 'domain_add' =&gt; 'criar domnio', 'domain_edit' =&gt; 'editar domnio', 'subdomainforemail' =&gt; 'subdomnio como "emaildomains"', 'admin' =&gt; 'administrador', 'admins' =&gt; 'administradores', 'admin_add' =&gt; 'criar administrador', 'admin_edit' =&gt; 'editar administrador', 'customers_see_all' =&gt; 'mostrar todos os clientes', 'change_serversettings' =&gt; 'alterar configuraes servidor?', 'server' =&gt; 'sistema', 'serversettings' =&gt; 'configuraes', 'rebuildconf' =&gt; 'escrever de novo os configs', 'stdsubdomain' =&gt; 'subdomnio padro', 'stdsubdomain_add' =&gt; 'criar subdomnio padro', 'phpenabled' =&gt; 'php habilitado', 'deactivated' =&gt; 'desativado', 'deactivated_user' =&gt; 'desativar usurio', 'sendpassword' =&gt; 'enviar senha', 'ownvhostsettings' =&gt; 'own vhost-settings', 'configfiles' =&gt; [ 'serverconfiguration' =&gt; 'configuraes', 'overview' =&gt; 'viso geral', 'wizard' =&gt; 'assistente', 'distribution' =&gt; 'distribuio', 'service' =&gt; 'servio', 'daemon' =&gt; 'daemon', 'http' =&gt; 'servidor web (http)', 'dns' =&gt; 'servidor de nomes (dns)', 'mail' =&gt; 'servidor de emails (pop3/imap)', 'smtp' =&gt; 'servidor de emails (smtp)', 'ftp' =&gt; 'servidor ftp', 'etc' =&gt; 'outros (sistema)', 'choosedistribution' =&gt; 'escolha uma distribuio', 'chooseservice' =&gt; 'escolha um servio', 'choosedaemon' =&gt; 'escolha um daemon', 'statistics' =&gt; 'estatsticas', ], 'templates' =&gt; [ 'templates' =&gt; 'templates', 'template_add' =&gt; 'adicionar template', 'template_edit' =&gt; 'editar template', 'action' =&gt; 'ao', 'email' =&gt; 'e-mail', 'subject' =&gt; 'assunto', 'mailbody' =&gt; 'mensagem', 'createcustomer' =&gt; 'e-mail de boas-vindas para novos clientes', 'pop_success' =&gt; 'e-mail de boas-vindas para nova conta de e-mail', 'template_replace_vars' =&gt; 'variaveis para serem substituidas template:', 'firstname' =&gt; 'altere para primeiro nome cliente.', 'name' =&gt; 'altere para nome cliente.', 'username' =&gt; 'altere para nome da conta cliente.', 'password' =&gt; 'altere com senha da conta cliente.', 'email' =&gt; 'altere com os dados servidor pop3/imap.', 'traffic' =&gt; 'substitudo com trfego, que foi atribudo ao cliente.', 'trafficused' =&gt; 'substitudo com trfego, que foi esgotado pela cliente.', 'pop_success_alternative' =&gt; 'bem-vindo para novas contas e-mail enviado ao endereo alternativo', 'email_password' =&gt; 'substitudo senha da conta pop3/imap.', 'index_html' =&gt; 'indice de arquivo recm-criado diretrio de cliente', 'servername' =&gt; 'substitua pelo nome servidor.', 'customer' =&gt; 'substitua pelo login cliente.', 'admin' =&gt; 'substitua pelo login admin.', 'customer_email' =&gt; 'substitua pelo endereo de email cliente.', 'admin_email' =&gt; 'substitua pelo endereo de email administrador.', 'filetemplates' =&gt; 'modelo de arquivo', 'filecontent' =&gt; 'contedo arquivo', ], 'ipsandports' =&gt; [ 'ipsandports' =&gt; 'ips e portas', 'add' =&gt; 'adicionar ip/porta', 'edit' =&gt; 'editar ip/porta', 'ipandport' =&gt; 'ip/porta', 'ip' =&gt; 'ip', 'port' =&gt; 'porta', 'create_listen_statement' =&gt; 'criar instruo de escuta', 'create_namevirtualhost_statement' =&gt; 'criar instruo de namevirtualhost', 'create_vhostcontainer' =&gt; 'criar vhost-container', 'create_vhostcontainer_servername_statement' =&gt; 'criar instruo de servername vhost-container', 'enable_ssl' =&gt; 'esta uma porta ssl?', 'ssl_cert_file' =&gt; 'caminho para certificado ssl', ], 'valuemandatory' =&gt; 'este valor imperativo.', 'valuemandatorycompany' =&gt; 'qualquer um "nome" e "nome" "companhia" deve ser enchido.', 'webserver' =&gt; 'servidor web', 'memorylimitdisabled' =&gt; 'desabilitado', 'serversoftware' =&gt; 'servidor de software', 'phpversion' =&gt; 'verso php', 'phpmemorylimit' =&gt; 'memria limite php', 'mysqlserverversion' =&gt; 'verso mysql server', 'mysqlclientversion' =&gt; 'verso mysql client', 'webserverinterface' =&gt; 'interface servidor web', 'accountsettings' =&gt; 'configuraes de conta', 'panelsettings' =&gt; 'painel de controle', 'systemsettings' =&gt; 'configuraes sistema', 'webserversettings' =&gt; 'configuraes webserver', 'mailserversettings' =&gt; 'configuraes servidor de email', 'nameserversettings' =&gt; 'configuraes dos servidores de nomes', 'updatecounters' =&gt; 'recalcular utilizao de recursos', 'subcanemaildomain' =&gt; [ 'never' =&gt; 'nunca', 'choosableno' =&gt; 'escolhe, default no', 'choosableyes' =&gt; 'escolher, default sim', 'always' =&gt; 'sempre', ], 'webalizersettings' =&gt; 'configuraes webalizer', 'webalizer' =&gt; [ 'normal' =&gt; 'normal', 'quiet' =&gt; 'quieto', 'veryquiet' =&gt; 'sem sada', ], 'domain_nocustomeraddingavailable' =&gt; 'no adicionar um domnio corretamente. voc primeiro precisa adicionar um cliente.', 'loggersettings' =&gt; 'configuraes de logs', 'logger' =&gt; [ 'normal' =&gt; 'normal', 'paranoid' =&gt; 'paranico', ], 'emaildomain' =&gt; 'domnio de email', 'email_only' =&gt; 'somente email?', 'wwwserveralias' =&gt; 'adicionar um "www." serveralias', 'subject' =&gt; 'assunto', 'recipient' =&gt; 'destinatrio', 'message' =&gt; 'escrever uma mensagem', 'text' =&gt; 'mensagem', 'sslsettings' =&gt; 'configurao de ssl', 'dkimsettings' =&gt; 'configuraes de chave de domnios', 'caneditphpsettings' =&gt; 'pode alterar configuraes php relacionadas com domnio?', 'allips' =&gt; 'todos os ips', 'awstatssettings' =&gt; 'configuraes awtats', 'domain_dns_settings' =&gt; 'configuraes de dns', 'activated' =&gt; 'ativado', 'statisticsettings' =&gt; 'configuraes de estatsticas', 'or' =&gt; 'ou', 'sysload' =&gt; 'carga sistema', 'noloadavailable' =&gt; 'no disponvel', 'nouptimeavailable' =&gt; 'no disponvel', 'nosubject' =&gt; '(sem assunto)', 'accountdata' =&gt; 'data da conta', 'contactdata' =&gt; 'data de contato', 'servicedata' =&gt; 'data de servio', 'security_settings' =&gt; 'opes de segurana', 'know_what_youre_doing' =&gt; 'somente altere, se voc sabe que est fazendo', 'show_version_login' =&gt; [ 'title' =&gt; 'mostrar verso froxlor login', 'description' =&gt; 'mostar verso froxlor rodap da pgina de login', ], 'show_version_footer' =&gt; [ 'title' =&gt; 'mostar verso froxlor rodap', 'description' =&gt; 'mostar verso froxlor rodap resto das pginas', ], 'froxlor_graphic' =&gt; [ 'title' =&gt; 'cabealho grfico froxlor', 'description' =&gt; 'quais grficos devem aparece topor', ], 'phpsettings' =&gt; [ 'title' =&gt; 'configuraes php', 'description' =&gt; 'descrio', 'actions' =&gt; 'aes', 'activedomains' =&gt; 'em uso pelo(s) domnio(s)', 'notused' =&gt; 'configurao est em uso', 'editsettings' =&gt; 'alterar configurao php', 'addsettings' =&gt; 'criar novas configuraes php', 'viewsettings' =&gt; 'visualizar configurao php', 'phpinisettings' =&gt; 'configuraes php.ini', 'addnew' =&gt; 'criar novas configuraes', 'binary' =&gt; 'binrio php', 'file_extensions' =&gt; 'extenses de arquivos', 'file_extensions_note' =&gt; '(sem pontos, separados por espaos)', ], 'misc' =&gt; 'variados', 'phpconfig' =&gt; [ 'template_replace_vars' =&gt; 'as variveis que sero substitudas nas configuraes', 'pear_dir' =&gt; 'sero substitudos com definio global para diretrio pear.', 'open_basedir' =&gt; 'sero substitudos com definio domnio open_basedir.', 'tmp_dir' =&gt; 'substitudo com diretrio temporrio domnio.', 'open_basedir_global' =&gt; 'sero substitudos com valor global caminho que ser anexado ao open_basedir.', 'customer_email' =&gt; 'sero substitudos com endereo de e-mail cliente que dono desse domnio.', 'admin_email' =&gt; 'sero substitudos por e-mail administrador quem possui esse domnio.', 'domain' =&gt; 'sero substitudos com domnio.', 'customer' =&gt; 'ser substituda pelo nome login cliente que dono desse domnio.', 'admin' =&gt; 'ser substituda pelo nome de login administrador que possui esse domnio.', ], 'expert_settings' =&gt; 'configuraes avanadas', 'mod_fcgid_starter' =&gt; [ 'title' =&gt; 'processos php para este domnio (vazio para usar valor padro)', ], 'phpserversettings' =&gt; 'configurao php', 'mod_fcgid_maxrequests' =&gt; [ 'title' =&gt; 'mximo de requisies php para este domnio (vazio para valor default)', ], ], 'changepassword' =&gt; [ 'old_password' =&gt; 'senha atual', 'new_password' =&gt; 'nova senha', 'new_password_confirm' =&gt; 'repita nova senha', 'new_password_ifnotempty' =&gt; 'nova senha (em branco = alterar)', 'also_change_ftp' =&gt; ' trocar tambem senha da conta principal de ftp', 'also_change_stats' =&gt; 'troca senha das estatsticas', ], 'cronjobs' =&gt; [ 'notyetrun' =&gt; 'ainda est rodando', ], 'customer' =&gt; [ 'documentroot' =&gt; 'diretrio home', 'name' =&gt; 'sobrenome', 'firstname' =&gt; 'primeiro nome', 'company' =&gt; 'empresa', 'street' =&gt; 'endereo', 'zipcode' =&gt; 'cep', 'city' =&gt; 'cidade', 'phone' =&gt; 'telefone', 'fax' =&gt; 'fax', 'email' =&gt; 'e-mail', 'customernumber' =&gt; 'cliente id', 'diskspace' =&gt; 'espao de disco (mb)', 'traffic' =&gt; 'trfego (gb)', 'mysqls' =&gt; 'bancos de dados-mysql', 'emails' =&gt; 'endereos de e-mail', 'accounts' =&gt; 'contas de e-mail', 'forwarders' =&gt; 'redirecionamentos de e-mail', 'ftps' =&gt; 'contas de ftp', 'subdomains' =&gt; 'sub-domnio(s)', 'domains' =&gt; 'domnio(s)', 'email_quota' =&gt; 'e-mail quota', 'email_imap' =&gt; 'e-mail imap', 'email_pop3' =&gt; 'e-mail pop3', 'mail_quota' =&gt; 'quota de email', 'title' =&gt; 'ttulo', 'country' =&gt; 'pas', ], 'dkim' =&gt; [ 'dkim_prefix' =&gt; [ 'title' =&gt; 'prefixo', 'description' =&gt; 'por favor, especifique caminho para os arquivos dkim rsa, bem como para os arquivos de configurao para plugin milter', ], 'dkim_domains' =&gt; [ 'title' =&gt; 'nome de arquivo de domnios', 'description' =&gt; '&lt;em&gt;nome arquivo&lt;/em&gt; dos domnios dkim, parmetro especificado na configurao dkim-milter', ], 'dkim_dkimkeys' =&gt; [ 'title' =&gt; 'nome de arquivo de chaves', 'description' =&gt; '&lt;em&gt;nome arquivo&lt;/em&gt;dkim keylist parmetro especificado na configurao dkim-milter', ], 'dkimrestart_command' =&gt; [ 'title' =&gt; 'comando para reiniciar milter', 'description' =&gt; 'por favor especifique um comando para reiniciar dkim milter', ], 'use_dkim' =&gt; [ 'title' =&gt; 'ativar suporte para dkim?', 'description' =&gt; 'voc deseja usar sistema de chaves de domnio (dkim) ?', ], ], 'dns' =&gt; [ 'destinationip' =&gt; 'domnio ip', 'standardip' =&gt; 'ip padro servidor', 'a_record' =&gt; 'gravar-a(opcional ipv6)', 'cname_record' =&gt; 'gravar-cname', 'mxrecords' =&gt; 'definir entradas mx', 'standardmx' =&gt; 'servidor mx padro', 'mxconfig' =&gt; 'registros mx personalizados', 'priority10' =&gt; 'prioridade 10', 'priority20' =&gt; 'prioridade 20', 'txtrecords' =&gt; 'difinir entradas txt', 'txtexample' =&gt; 'exemplo (entrada-spf):&lt;br /&gt;v=spf1 ip4:xxx.xxx.xx.0/23 -all', ], 'domain' =&gt; [ 'docroot' =&gt; 'trajeto da linha acima de', 'homedir' =&gt; 'diretrio da casa', 'openbasedirpath' =&gt; 'caminho openbasedir', ], 'domains' =&gt; [ 'description' =&gt; 'aqui voc pode criar (sub-)domnios e alterar seu destino.&lt;br /&gt;o sistema ir levar algum tempo para aplicar novas configuraes depois de salvas.', 'domainsettings' =&gt; 'configurar domnio', 'domainname' =&gt; 'nome domnio', 'subdomain_add' =&gt; 'criar sub-domnio', 'subdomain_edit' =&gt; 'editar (sub)domnio', 'wildcarddomain' =&gt; 'criar um wildcarddomain?', 'aliasdomain' =&gt; 'alis para domnio', 'noaliasdomain' =&gt; 'no domnio alis', 'hasaliasdomains' =&gt; 'possui alinhas de domnio(s)', 'statstics' =&gt; 'estatsticas de uso', 'isassigneddomain' =&gt; ' um domnio assinado', 'add_date' =&gt; 'adicionado froxlor', 'registration_date' =&gt; 'adicionado registro', 'topleveldomain' =&gt; 'top-level-domain', 'associated_with_domain' =&gt; 'associado', 'aliasdomains' =&gt; 'encaminhamento de domnios', ], 'emails' =&gt; [ 'description' =&gt; 'aqui voc pode criar e alterer seus e-mails.&lt;br /&gt;uma conta como uma caixa de correio na frente de sua casa. quando alguem envia para voc um e-mail, ele colocado nesta conta.&lt;br /&gt;&lt;br /&gt;para baixar seus e-mails use seguintes configuraes seu propraga de e-mails favorito: (os dados em &lt;i&gt;italico&lt;/i&gt; devem ser substituidos pelo equivalente da conta que voc criou!)&lt;br /&gt;hostname: &lt;b&gt;&lt;i&gt;nome de seu domnio&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;usurio: &lt;b&gt;&lt;i&gt;nome da conta / endereo de e-mail&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;senha: &lt;b&gt;&lt;i&gt;a senha que voc escolheu&lt;/i&gt;&lt;/b&gt;', 'emailaddress' =&gt; 'endereos de e-mail', 'emails_add' =&gt; 'criar e-mail', 'emails_edit' =&gt; 'editar e-mail', 'catchall' =&gt; 'pega tudo', 'iscatchall' =&gt; 'definir como endereo pega tudo?', 'account' =&gt; 'conta', 'account_add' =&gt; 'criar conta', 'account_delete' =&gt; 'excluir conta', 'from' =&gt; 'origem', 'to' =&gt; 'destino', 'forwarders' =&gt; 'redirecionamentos', 'forwarder_add' =&gt; 'criar redirecionamento', 'alternative_emailaddress' =&gt; 'endereo de e-mail alternativo', 'quota' =&gt; 'quota', 'noquota' =&gt; 'sem quota', 'updatequota' =&gt; 'atualizar', ], 'error' =&gt; [ 'error' =&gt; 'erro', 'directorymustexist' =&gt; 'o diretrio %s deve existir. por favor crie ele primeiro com seu programa de ftp.', 'filemustexist' =&gt; 'o arquivo %s deve existir.', 'allresourcesused' =&gt; 'voc j usou todos os seus recursos.', 'domains_cantdeletemaindomain' =&gt; 'voc pode deletar um domnio que esta sendo usado como email-domain.', 'domains_canteditdomain' =&gt; 'voc pode editar este domnio. ele foi desabilitado pelo administrador.', 'domains_cantdeletedomainwithemail' =&gt; 'voc pode deletar um domnio que usado como email-domain. delete todos contas de e-mail primeiro.', 'firstdeleteallsubdomains' =&gt; 'voc deve deletar todos subdomnios antes de poder criar um wildcard domain.', 'youhavealreadyacatchallforthisdomain' =&gt; 'voc j definiu uma conta pega tudo para este domnio.', 'ftp_cantdeletemainaccount' =&gt; 'voc pode deletar conta principal de ftp', 'login' =&gt; 'o usurio ou senha digitados, esto corretos. por favor tente novamente!', 'login_blocked' =&gt; 'esta conta est suspensa por exceder tentativas de login permitidas. &lt;br /&gt;por favor tente novamente em %s segundos.', 'notallreqfieldsorerrors' =&gt; 'voc preencheu todos os campos ou preencheu algum campo incorretamente.', 'oldpasswordnotcorrect' =&gt; 'a senha antiga confere.', 'youcantallocatemorethanyouhave' =&gt; 'voc pode alocar mais recursos que voc mesmo possui.', 'mustbeurl' =&gt; 'voc digitou uma url vlida (ex. http://seudominio.com/erro404.htm)', 'invalidpath' =&gt; 'optou por um url vlido (eventuais problemas na lista directrio)', 'stringisempty' =&gt; 'faltando informao campo', 'stringiswrong' =&gt; 'erro na informao campo', 'newpasswordconfirmerror' =&gt; 'a nova senha e confirmao conferem', 'mydomain' =&gt; '\'domnio\'', 'mydocumentroot' =&gt; '\'documento principal\'', 'loginnameexists' =&gt; 'login %s j existe', 'emailiswrong' =&gt; 'e-mail %s contm caracteres invlidos ou est incompleto', 'loginnameiswrong' =&gt; 'login %s contm caracteres invlidos', 'loginnameiswrong2' =&gt; 'login contm muitos caracteres. somente %s caracteres aceitos.', 'userpathcombinationdupe' =&gt; 'usuario e caminho j existem', 'patherror' =&gt; 'erro geral! caminho pode ficar em branco', 'errordocpathdupe' =&gt; 'opo de caminho %s j existe', 'adduserfirst' =&gt; 'por favor crie um cliente primeiro', 'domainalreadyexists' =&gt; 'o domnio %s j est apontado para outro cliente', 'nolanguageselect' =&gt; 'nenhum idioma selecionado.', 'nosubjectcreate' =&gt; 'voc deve definir um nome para este e-mail template.', 'nomailbodycreate' =&gt; 'voc deve definir texto para este e-mail template.', 'templatenotfound' =&gt; 'template encontrado.', 'alltemplatesdefined' =&gt; 'voc pode definir mais templates, todos idiomas j suportados.', 'wwwnotallowed' =&gt; 'www permitido como nome de subdomnio.', 'subdomainiswrong' =&gt; 'o subdomnio %s contm caracteres invlidos.', 'domaincantbeempty' =&gt; 'o nome domnio pode estar vazio.', 'domainexistalready' =&gt; 'o domnio %s j existe.', 'domainisaliasorothercustomer' =&gt; 'o domnio-alias escolhido ele prprio um domnio-alias ou este pertence um outro cliente.', 'emailexistalready' =&gt; 'o e-mail %s j existe.', 'maindomainnonexist' =&gt; 'o domnio principal %s existe.', 'destinationnonexist' =&gt; 'por favor crie seu redirecionamento campo \'destino\'.', 'destinationalreadyexistasmail' =&gt; 'o redirecionamento %s j existe como uma conta de e-mail.', 'destinationalreadyexist' =&gt; 'voc j definiu um redirecionamento para %s .', 'destinationiswrong' =&gt; 'o redirecionamento %s contm caracteres invlidos ou incompletos.', 'ipstillhasdomains' =&gt; 'o ip/porta que voc quer deletar ainda possui domnios associados e eles, por favor altere ip/porta destes domnios antes de delet-los.', 'cantdeletedefaultip' =&gt; 'voc pode deletar ip/porta padro revendedor, por favor defina outro ip/porta como padro antes deletar ip/porta desejado', 'cantdeletesystemip' =&gt; 'voc pode deletar ip sistema, nem criar uma nova combinao ip/porta para sistema ou trocar ip sistema.', 'myipaddress' =&gt; '\'ip\'', 'myport' =&gt; '\'porta\'', 'myipdefault' =&gt; 'voc precisa selecionar ip/porta que ser padro.', 'myipnotdouble' =&gt; 'esta combinao ip/porta j existe.', 'cantchangesystemip' =&gt; 'voc pode mudar ltimo sistema ip, para criar uma outra combinao nova de ip/port para sistema ip ou para mudar sistema ip', 'loginnameissystemaccount' =&gt; 'voc pode criar os clientes que similares aos systemaccounts. incorpore por favor um outro accountname.', 'admin_domain_emailsystemhostname' =&gt; 'desculpe. voc pode usar hostname servidor como domnio de email', 'sessiontimeoutiswrong' =&gt; 'apenas numeros "timeout da sesso" permitido.', 'maxloginattemptsiswrong' =&gt; 'apenas numero "tentativa maxima de login" permitido.', 'deactivatetimiswrong' =&gt; 'apenas numero "desativar tempo" permitido.', 'accountprefixiswrong' =&gt; 'o "prefixo" est errado.', 'mysqlprefixiswrong' =&gt; 'o "prefixo sql" est errado.', 'ftpprefixiswrong' =&gt; 'o "prefixo ftp" est errado.', 'ipiswrong' =&gt; 'o "endereo-ip" est errado. apenas um endereo-ip vlido permitido.', 'vmailuidiswrong' =&gt; 'o "uid e-mail" est errado. permitido um nmero de id.', 'vmailgidiswrong' =&gt; 'o "gid e-mail" est errado. permitido um nmero de id.', 'adminmailiswrong' =&gt; 'o "endereo de envio" est errado. apenas um endereo de e-mail vlido permitido.', 'pagingiswrong' =&gt; 'o "entradas por pginas"-value est errado. somente caracteres nmericos permitidos.', 'phpmyadminiswrong' =&gt; 'o caminho para phpmyamin vlido', 'webmailiswrong' =&gt; 'o caminho para webmail vlido', 'webftpiswrong' =&gt; 'o caminho para webftp vlido', 'stringformaterror' =&gt; 'o valor par ao campo "%s" esta formato correto.', 'youcantdeleteyourself' =&gt; 'voc pode apagar voc mesmo por motivos de segurana', 'youcanteditallfieldsofyourself' =&gt; 'nota: voc pode editar todos os campos de sua prpria conta por motivos de segurana', 'documentrootexists' =&gt; 'o diretrio "%s" j existe para este usuario. por favor remova-o e depois tente novamente.', 'formtokencompromised' =&gt; 'o pedido parece estar correto. por motivos de segurana voc est desconectado.', 'logerror' =&gt; 'log-erro: %s', 'nomessagetosend' =&gt; 'voc entrou com uma mensagem', 'norecipientsgiven' =&gt; 'voc especificou um destinatrio', 'errorsendingmail' =&gt; 'a mensagem para "%s" falhou', 'cannotreaddir' =&gt; 'no possvel ler diretrio "%s"', 'vmailquotawrong' =&gt; 'a tamanho da quota deve ser entre 1 e 999', 'invalidip' =&gt; 'endereo de ip invlido: %s', 'invalidmysqlhost' =&gt; 'endereo de servidor mysql invlido: %s', 'cannotuseawstatsandwebalizeratonetime' =&gt; 'voc pode ativar webalizer e awstats ao mesmo tempo, por favor, escolha uma delas', 'cannotwritetologfile' =&gt; 'no pode abrir arquivo de log %s para escrita', 'missingfields' =&gt; 'nem todos os campos necessrios estavam campo.', 'accountnotexisting' =&gt; 'esta conta existe.', 'nopermissionsorinvalidid' =&gt; 'voc tem permisses suficientes para alterar essa configurao ou um id invlido foi dado.', 'phpsettingidwrong' =&gt; 'no existe uma configurao de php para este id', 'descriptioninvalid' =&gt; 'a descrio muito curta, muito longa ou contm caracteres ilegais', 'info' =&gt; 'informaes', 'filecontentnotset' =&gt; 'o arquivo pode ser vazio', 'index_file_extension' =&gt; 'a extenso ndice arquivo deve ficar entre 1 e 6 caracteres. prorrogao pode conter caracteres como az, az e 0-9', 'customerdoesntexist' =&gt; 'o cliente que voc escolheu existe', 'admindoesntexist' =&gt; 'o administrador que voc escolheu existe', 'ipportdoesntexist' =&gt; 'a combinao de ip/porta que voc escolheu existe', ], 'extras' =&gt; [ 'description' =&gt; 'aqui voc pode adicoionar alguns recursos extras, como por exemplo um diretrio protegido.&lt;br /&gt;o sistema ira precisar de algum tempo para aplicar suas alteraes depois de salvas.', 'directoryprotection_add' =&gt; 'adicionar diretrio pretogido', 'view_directory' =&gt; 'mostrar contedo diretrio', 'pathoptions_add' =&gt; 'adicionar opes de caminho', 'directory_browsing' =&gt; 'pesquizar contedo de diretrio', 'pathoptions_edit' =&gt; 'esitar opes de caminhos', 'errordocument404path' =&gt; 'url para pgina de erro 404', 'errordocument403path' =&gt; 'url para pgina de erro 403', 'errordocument500path' =&gt; 'url para pgina de erro 500', 'errordocument401path' =&gt; 'url para pgina de erro 401', ], 'ftp' =&gt; [ 'description' =&gt; 'aqui voc pode criar e alterar suas contas de ftp.&lt;br /&gt;as alteraes instantneas e podem ser utilizadas imediatamente depois de salvas.', 'account_add' =&gt; 'criar conta', ], 'index' =&gt; [ 'customerdetails' =&gt; 'detalhes dos clientes', 'accountdetails' =&gt; 'detalhes das contas', ], 'logger' =&gt; [ 'date' =&gt; 'data', 'type' =&gt; 'tipo', 'action' =&gt; 'ao', 'user' =&gt; 'usurio', 'truncate' =&gt; 'log vazio', ], 'login' =&gt; [ 'username' =&gt; 'usurio', 'password' =&gt; 'senha', 'language' =&gt; 'idioma', 'login' =&gt; 'login', 'logout' =&gt; 'sair', 'profile_lng' =&gt; 'idioma padro', 'forgotpwd' =&gt; 'perdeu sua senha?', 'presend' =&gt; 'resetar senha', 'email' =&gt; 'endereo de e-mail', 'remind' =&gt; 'resetar minha senha', 'usernotfound' =&gt; 'suario encontrado', 'backtologin' =&gt; 'voltar ao login', ], 'mails' =&gt; [ 'pop_success' =&gt; [ 'mailbody' =&gt; 'ol,\\n\\n sua conta de e-mail {email}\\n foi criada com sucesso.\\n\\nesta uma mensagem automtica\\nemail, por favor responda!\\n\\natenciosamente, equipe de desenvolvimento froxlor', 'subject' =&gt; 'conta de e-mail criada com sucesso!', ], 'createcustomer' =&gt; [ 'mailbody' =&gt; 'ol {firstname} {name},\\n\\nseguem os detalhes de sua nova conta de e-mail:\\n\\nusuario: {username}\\nsenha: {password}\\n\\nobrigado,\\nequipe de desenvolvimento froxlor', 'subject' =&gt; 'informaes da conta', ], 'pop_success_alternative' =&gt; [ 'mailbody' =&gt; 'oi,\\n\\nsua conta de email {email}\\nfoi configurada corretamente.\\nsua senha {password}.\\n\\nemail criado automaticamente\\n, por favor responda!\\n\\ncumprimentos, equipe froxlor.', 'subject' =&gt; 'conta de email criada com sucesso', ], 'password_reset' =&gt; [ 'subject' =&gt; 'reset de senha', 'mailbody' =&gt; 'oi {username},\\n\\nsua senha froxlor foi resetada!\\na nova senha : {link}\\n\\nobrigado,\\nequipe froxlor', ], ], 'menu' =&gt; [ 'message' =&gt; 'mensagens', ], 'menue' =&gt; [ 'main' =&gt; [ 'main' =&gt; 'principal', 'changepassword' =&gt; 'trocar senha', 'changelanguage' =&gt; 'trocar idioma', 'username' =&gt; 'logado como', ], 'email' =&gt; [ 'email' =&gt; 'e-mail', 'emails' =&gt; 'endereos', 'webmail' =&gt; 'webmail', ], 'mysql' =&gt; [ 'mysql' =&gt; 'mysql', 'databases' =&gt; 'banco de dados', 'phpmyadmin' =&gt; 'phpmyadmin', ], 'domains' =&gt; [ 'domains' =&gt; 'domnios', 'settings' =&gt; 'configuraes', ], 'ftp' =&gt; [ 'ftp' =&gt; 'ftp', 'accounts' =&gt; 'contas', 'webftp' =&gt; 'webftp', ], 'extras' =&gt; [ 'extras' =&gt; 'extras', 'directoryprotection' =&gt; 'diretrio protegido', 'pathoptions' =&gt; 'opes de caminhos', ], 'traffic' =&gt; [ 'traffic' =&gt; 'trfego', 'current' =&gt; 'ms corrente', ], 'phpsettings' =&gt; [ 'maintitle' =&gt; 'configuraes php', ], 'logger' &gt; [ 'logger' =&gt; 'sistema-log', ], ], 'message' =&gt; [ 'norecipients' =&gt; 'email enviado porque tem destinatrio banco de dados', 'success' =&gt; 'mensagens enviadas para %s destinatrios com sucesso', ], 'mysql' =&gt; [ 'description' =&gt; 'aqui voc pode criar e alterar seus bancos de dados mysql.&lt;br /&gt;as alteraes instantneas e podem ser utilizadas imediatamente depois de salvas.&lt;br /&gt;no menu lado esquerdo voc pode encontrar ferramenta phpmyadmin e com ela facilmente administrar seus bancos de dados.&lt;br /&gt;&lt;br /&gt;para usar seu banco de dados com scripts em php use seguintes configuraes: (os dados em &lt;i&gt;italico&lt;/i&gt; devem ser substituidos pelo equivalente banco de dados que voc criou!)&lt;br /&gt;hostname: &lt;b&gt;&lt;sql_host&gt;&lt;/b&gt;&lt;br /&gt;usuario: &lt;b&gt;&lt;i&gt;nome banco de dadose&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;senha: &lt;b&gt;&lt;i&gt;a senha que voc escolheu&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;banco de dados: &lt;b&gt;&lt;i&gt;nome banco de dados', 'databasename' =&gt; 'usuario / nome banco de dados', 'databasedescription' =&gt; 'descrio banco de dados', 'database_create' =&gt; 'criar banco de dados', ], 'panel' =&gt; [ 'edit' =&gt; 'editar', 'delete' =&gt; 'deletar', 'create' =&gt; 'criar', 'save' =&gt; 'salvar', 'yes' =&gt; 'sim', 'no' =&gt; 'no', 'emptyfornochanges' =&gt; 'sair sem salvar', 'emptyfordefault' =&gt; 'restaurar padro', 'path' =&gt; 'caminho', 'toggle' =&gt; 'toggle', 'next' =&gt; 'prximo', 'dirsmissing' =&gt; 'directrio disponvel ou ilegvel', 'urloverridespath' =&gt; 'url (caminho completo)', 'pathorurl' =&gt; 'caminho ou url', 'ascending' =&gt; 'crescente', 'descending' =&gt; 'decrescente', 'search' =&gt; 'procurar', 'used' =&gt; 'usado', 'translator' =&gt; 'tradutor', 'reset' =&gt; 'descartar mudanas', 'pathdescription' =&gt; 'se diretrio existir, ser criado automaticamente', 'back' =&gt; 'volta', 'reseller' =&gt; 'revenda', 'admin' =&gt; 'administrador', 'customer' =&gt; 'cliente(s)', 'send' =&gt; 'enviar', 'nosslipsavailable' =&gt; 'no existem atualmente ip ssl / porta para este servidor.', 'backtooverview' =&gt; 'voltar para viso geral', 'dateformat' =&gt; 'aaaa-mm-dd', 'dateformat_function' =&gt; 'a-m-d', 'timeformat_function' =&gt; 'h:i:s', 'default' =&gt; 'padro', 'never' =&gt; 'nunca', 'active' =&gt; 'ativo', 'please_choose' =&gt; 'por favor escolha', 'allow_modifications' =&gt; 'aceita alteraoes', 'not_supported' =&gt; 'no suportado em:', 'view' =&gt; 'visualizar', ], 'pwdreminder' =&gt; [ 'success' =&gt; 'redefinio de senha com sucesso. &lt;br /&gt; voc agora deve receber um e-mail com sua nova senha.', 'notallowed' =&gt; 'reset de senhas est desativado', ], 'question' =&gt; [ 'question' =&gt; 'pergunta de segurana', 'admin_customer_reallydelete' =&gt; 'voc realmente deseja deletar cliente %s? este comando poder ser cancelado!', 'admin_domain_reallydelete' =&gt; 'voc realmente deseja deletar domnio %s?', 'admin_domain_reallydisablesecuritysetting' =&gt; 'voc realmente deseja desativar estas configuraes de segurana (openbasedir)?', 'admin_admin_reallydelete' =&gt; 'voc realmente deseja deletar administrador %s? todos clientes e domnios sero realocados para administrador principal.', 'admin_template_reallydelete' =&gt; 'voc realmente deseja deletar template \'%s\'?', 'domains_reallydelete' =&gt; 'voc realmente deseja deletar domnio %s?', 'email_reallydelete' =&gt; 'voc realmente deseja deletar e-mail %s?', 'email_reallydelete_account' =&gt; 'voc realmente deseja deletar conta de e-mail %s?', 'email_reallydelete_forwarder' =&gt; 'voc realmente deseja deletar redirecionamento %s?', 'extras_reallydelete' =&gt; 'voc realmente deseja deletar proteo diretrio %s?', 'extras_reallydelete_pathoptions' =&gt; 'voc realmente deseja deletar caminho %s?', 'ftp_reallydelete' =&gt; 'voc realmente deseja deletar conta de ftp %s?', 'mysql_reallydelete' =&gt; 'voc realmente deseja deletar banco de dados %s? este comando poder ser cancelado!', 'admin_configs_reallyrebuild' =&gt; 'est certo que quer deixar reconfigurar os ficheiros de configurao de apache e bind?', 'admin_customer_alsoremovefiles' =&gt; 'remover arquivos usurio tambm?', 'admin_customer_alsoremovemail' =&gt; 'remover todos os dados de e-mail sistema de arquivos?', 'admin_customer_alsoremoveftphomedir' =&gt; 'remover diretrio home usurio ftp?', 'admin_ip_reallydelete' =&gt; 'voc realmente deseja deletar este endereo ip?', 'admin_domain_reallydocrootoutofcustomerroot' =&gt; ' voc certo, voc quer raiz original para este domnio, estando dentro customerroot cliente?', 'admin_counters_reallyupdate' =&gt; 'voc deseja recalcular os recursos utilizados?', 'logger_reallytruncate' =&gt; 'voc realmente deseja dividir tabela "%s"?', 'admin_quotas_reallywipe' =&gt; 'voc realmente deseja limpar todas quotas na tabela mail_users? isto pode ser revertido', 'phpsetting_reallydelete' =&gt; 'voc realmente deseja apagar esta configurao? todos os domnios que atualmente utilizam esta configurao sero alterada para configurao padro.', ], 'serversettings' =&gt; [ 'session_timeout' =&gt; [ 'title' =&gt; 'tempo esgotado', 'description' =&gt; 'quanto tempo usuario deve estar inativo para ser desconectado (segundos)?', ], 'accountprefix' =&gt; [ 'title' =&gt; 'prefixo cliente', 'description' =&gt; 'qual prefixo "customeraccounts" deve ter?', ], 'mysqlprefix' =&gt; [ 'title' =&gt; 'sql prefixo', 'description' =&gt; 'qual prefixo contas mysql devem ter?', ], 'ftpprefix' =&gt; [ 'title' =&gt; 'ftp prefixo', 'description' =&gt; 'qual prefixo contas de ftp devem ter?', ], 'documentroot_prefix' =&gt; [ 'title' =&gt; 'diretrio de documentao', 'description' =&gt; 'aonde os documentos dever ser gravados?', ], 'logfiles_directory' =&gt; [ 'title' =&gt; 'diretrio de log', 'description' =&gt; 'aonde os arquivos de log dever ser gravados?', ], 'ipaddress' =&gt; [ 'title' =&gt; 'endereos de ip', 'description' =&gt; 'quais os endereos ip deste servidor?', ], 'hostname' =&gt; [ 'title' =&gt; 'hostname', 'description' =&gt; 'qual hostname deste servidor?', ], 'apachereload_command' =&gt; [ 'title' =&gt; 'comando de reiniciar apache', 'description' =&gt; 'qual comando para reiniciar apache?', ], 'bindenable' =&gt; [ 'title' =&gt; 'habilitar servidor de nomes', 'description' =&gt; 'aqui servidor de nomes pode ser habilitado ou desabilitado globalmente.', ], 'bindconf_directory' =&gt; [ 'title' =&gt; 'diretrio de configurao bind', 'description' =&gt; 'aonde esto os arquivos de configurao bind?', ], 'bindreload_command' =&gt; [ 'title' =&gt; 'comando de reiniciar bind', 'description' =&gt; 'qual comando para reiniciar bind?', ], 'vmail_uid' =&gt; [ 'title' =&gt; 'mails-uid', 'description' =&gt; 'qual userid os e-mails devem ter?', ], 'vmail_gid' =&gt; [ 'title' =&gt; 'mails-gid', 'description' =&gt; 'qual groupid os e-mails devem ter?', ], 'vmail_homedir' =&gt; [ 'title' =&gt; 'mails-homedir', 'description' =&gt; 'aonde os e-mails devem ser gravados?', ], 'adminmail' =&gt; [ 'title' =&gt; 'remetente', 'description' =&gt; 'qual remetente dos e-mails enviados pelo painel?', ], 'phpmyadmin_url' =&gt; [ 'title' =&gt; 'phpmyadmin url', 'description' =&gt; 'qual url phpmyadmin? (deve iniciar com http://)', ], 'webmail_url' =&gt; [ 'title' =&gt; 'webmail url', 'description' =&gt; 'qual url webmail? (deve iniciar com http://)', ], 'webftp_url' =&gt; [ 'title' =&gt; 'webftp url', 'description' =&gt; 'qual url webftp? (deve iniciar com http://)', ], 'language' =&gt; [ 'description' =&gt; 'qual idioma padro servidor?', ], 'maxloginattempts' =&gt; [ 'title' =&gt; 'tentativas maximas de login', 'description' =&gt; 'tentativas maximas de login para conta ser desativada.', ], 'deactivatetime' =&gt; [ 'title' =&gt; 'tempo que conta deve permanecer desativada', 'description' =&gt; 'tempo (sec.) qua conta permanece desativada depois de muitas tentativas de login.', ], 'pathedit' =&gt; [ 'title' =&gt; 'file-mtodo de entrada', 'description' =&gt; 'a escolha file tem que ser feita atravs dropdown-menu ou pode ser feita manualmente?', ], 'paging' =&gt; [ 'title' =&gt; 'entradas por pagina', 'description' =&gt; 'quantas entradas devem ser mostradas por pagina? (0 = desabilitar paginas)', ], 'nameservers' =&gt; [ 'title' =&gt; 'servidores dns', ], 'mxservers' =&gt; [ 'title' =&gt; 'servidores de email', 'description' =&gt; 'uma lista separada por vrgulas que contm numero de prioridade e hostname separados por um espao (por exemplo: \'mx.example.com 10 \'), contendo os servidores mx.', ], 'defaultip' =&gt; [ 'title' =&gt; 'ip/porta padro', 'description' =&gt; 'qual ip/porta padro?', ], 'phpappendopenbasedir' =&gt; [ 'title' =&gt; 'caminho para adicionar openbasedir', 'description' =&gt; 'estes caminhos (separados por dois pontos) sero acrescentados ao openbasedir em cada vhost.', ], 'natsorting' =&gt; [ 'title' =&gt; 'usar classificao natural na visualizao', 'description' =&gt; 'ordenar listas como: web1 -&gt; web2 -&gt; web11 ao invz de web1 -&gt; web11 -&gt; web2.', ], 'deactivateddocroot' =&gt; [ 'title' =&gt; 'docroots desativado para usurios', 'description' =&gt; 'quando um usurio estiver desativado, esse caminho usado como seu docroot. deixe em branco para criar um vhost todos.', ], 'mailpwcleartext' =&gt; [ 'title' =&gt; 'salva senhas de usurios sempre criptografia banco de dados', 'description' =&gt; 'se voc selecionar sim, todas senhas sero guardadas descriptografadas (poder ser lido por todos com acesso ao banco de dados ) na tabela mail_users-table. somente ative essa opo se voc realmente precise!', 'removelink' =&gt; 'clique aqui para limpar todas senhas criptografadas da tabela&lt;br /&gt;voc realmente deseja limpar todas senhas encriptadas partir da tabela mail_users? isto pode ser revertido!', ], 'ftpdomain' =&gt; [ 'title' =&gt; 'contas ftp @domnio', 'description' =&gt; 'clientes podem criar contas de ftp user@domniodocliente?', ], 'mod_fcgid' =&gt; [ 'title' =&gt; 'incluir php via mod_fcgid/suexec', 'description' =&gt; 'use mod_fcgid/suexec/libnss_mysql run php corresponding useraccount.&lt;br/&gt;&lt;b&gt;this needs special apache configuration. following options valid module enabled.&lt;/b&gt;', 'configdir' =&gt; [ 'title' =&gt; 'diretrio de configurao', 'description' =&gt; 'aonde todos os arquivos de configurao fcgid vo ser guardados? se voc utiliza um binrio compilado, est uma situao normal, deve estar dentro de /var/www/', ], 'tmpdir' =&gt; [ 'title' =&gt; 'diretrio temporrio', 'description' =&gt; 'aonde os arquivos temporrios devem ser guardados', ], 'starter' =&gt; [ 'title' =&gt; 'processos por domnio', 'description' =&gt; 'quantos processos devem ser iniciadas / permitidas por domnio? valor 0 recomendado. php ir ento gerir quantidade de processos.', ], 'wrapper' =&gt; [ 'title' =&gt; 'wrapper vhosts', 'description' =&gt; 'como os wrapper vo ser includos nos vhosts', ], 'peardir' =&gt; [ 'title' =&gt; 'diretrios globais pear', 'description' =&gt; 'diretrios globais pear que devero ser substitudos em cada configurao php.ini? diferentes diretrios devem ser separados por dois pontos.', ], 'maxrequests' =&gt; [ 'title' =&gt; 'mximo de solicitaes por domnio', 'description' =&gt; 'quantas solicitaes sero aceitas por domnio?', ], ], 'sendalternativemail' =&gt; [ 'title' =&gt; 'utilize endereo de e-mail alternativo', 'description' =&gt; 'enviar e-mail senha para um endereo diferente durante uma criao de conta de e-mail', ], 'apacheconf_vhost' =&gt; [ 'title' =&gt; 'arquivo/diretrio de configuraes apache vhost', 'description' =&gt; 'onde configurao de vhost devem ser guardadas? voc pode especificar um arquivo (todos os vhosts em um arquivo) ou diretrio (cada vhost com seu prprio arquivo) aqui.', ], 'apacheconf_diroptions' =&gt; [ 'title' =&gt; 'configurao de diretrio apache arquivo/nome diretrio.', 'description' =&gt; 'quando opes de configurao de diretrio deve ser armazenada? voc poderia especificar um arquivo (todas opes em um arquivo) ou diretrio ( cada opo seu prprio arquivo).', ], 'apacheconf_htpasswddir' =&gt; [ 'title' =&gt; 'apache htpasswd dirname', 'description' =&gt; 'onde deve ser diretrio de arquivos htpasswd?', ], 'mysql_access_host' =&gt; [ 'title' =&gt; 'hosts de acesso mysql', 'description' =&gt; 'uma lista separada por vrgulas de hosts partir qual os utilizadores devem ter possibilidade de conectar-se ao mysql-server.', ], 'webalizer_quiet' =&gt; [ 'title' =&gt; 'saida webalizer', 'description' =&gt; 'modo verbose webalizer', ], 'logger' =&gt; [ 'enable' =&gt; 'habilitar/desabilitar logs', 'severity' =&gt; 'nvel de logs', 'types' =&gt; [ 'title' =&gt; 'tipos de log(s)', 'description' =&gt; 'especificar tipos de logs separados por vrgula.&lt;br /&gt;tipos de lgs disponveis: syslog, file, mysql', ], 'logfile' =&gt; 'caminho arquivo de log incluindo nome de arquivo', 'logcron' =&gt; 'logar tarefas cron', 'logcronoption' =&gt; [ 'never' =&gt; 'nunca', 'once' =&gt; 'uma vez', 'always' =&gt; 'sempre', ], ], 'ssl' =&gt; [ 'openssl_cnf' =&gt; 'padro para criar arquivo de certificado', ], 'default_vhostconf' =&gt; [ 'title' =&gt; 'configurao de vhost padro', 'description' =&gt; 'o contedo deste campo ser includo cada novo vhost criado. ateno: cdigo ser checado para algum erro. se contiver erros, apache pode iniciar mais', ], 'mail_quota' =&gt; [ 'title' =&gt; 'quota de email', 'description' =&gt; 'quota default para novas caixas criadas', ], 'mail_quota_enabled' =&gt; [ 'title' =&gt; 'usar quota para clientes', 'description' =&gt; 'ative para usar cotas em caixas de email. padro &lt;b&gt;no&lt;/b&gt; visto que requer uma configurao especial.', 'removelink' =&gt; 'clique aqui para limpar todas quotas para contas de email.', ], 'decimal_places' =&gt; 'nmero de casas decimais trfego / espao de paginas web', 'webalizer_enabled' =&gt; 'ativar estatsticas webalizer', 'awstats_enabled' =&gt; 'ativar estatsticas awstats', 'selfdns' =&gt; [ 'title' =&gt; 'configuraes dns-domiio personalizadas', ], 'selfdnscustomer' =&gt; [ 'title' =&gt; 'aceita clientes para editar configuraes de dns', ], 'unix_names' =&gt; [ 'title' =&gt; 'usar nomes compatveis com unix', 'description' =&gt; 'aceita voc usar &lt;strong&gt;-&lt;/strong&gt; &lt;strong&gt;_&lt;/strong&gt; em nomes de usurios se &lt;strong&gt;no&lt;/strong&gt;estiver marcado', ], 'allow_password_reset' =&gt; [ 'title' =&gt; 'aceita reset de senha por clientes', 'description' =&gt; 'os clientes podem redefinir sua senha e sero enviadas para seu endereo de e-mail', ], 'allow_password_reset_admin' =&gt; [ 'title' =&gt; 'ativa reset de senhas pelos administradores', 'description' =&gt; 'admins / revendedor pode redefinir sua senha e nova senha ser enviada para seu endereo de e-mail', ], 'index_file_extension' =&gt; [ 'description' =&gt; 'qual extenso deve ser utilizada para ndice arquivo recm-criado diretrio cliente? esta extenso ser utilizado, se voc ou um de seus administradores criou seu prprio ndice arquivo modelo.', 'title' =&gt; 'extenso arquivo recm-criado ndice diretrio cliente.', ], 'session_allow_multiple_login' =&gt; [ 'title' =&gt; 'ativa login mltiplo', 'description' =&gt; 'se ativado um usurio pode ter mltiplos logins', ], 'panel_allow_domain_change_admin' =&gt; [ 'title' =&gt; 'ativa mover domnios entre admins', 'description' =&gt; 'if activated change admin domain domainsettings.&lt;br /&gt;&lt;b&gt;attention:&lt;/b&gt; customer isn\'t assigned admin domain, admin see every domain customer!', ], 'panel_allow_domain_change_customer' =&gt; [ 'title' =&gt; 'ativa mover domnios entre clientes', 'description' =&gt; 'se ativado voc pode trocar cliente de um domnio para administrao de outro.&lt;br /&gt;&lt;b&gt;attention:&lt;/b&gt; froxlor troca nenhum caminho. isto pode fazer com que domnios parem de funcionar', ], ], 'traffic' =&gt; [ 'month' =&gt; 'ms', 'day' =&gt; 'diariamente', 'months' =&gt; [ 1 =&gt; 'janeiro', 2 =&gt; 'fevereiro', 3 =&gt; 'maro', 4 =&gt; 'abril', 5 =&gt; 'maio', 6 =&gt; 'junho', 7 =&gt; 'julho', 8 =&gt; 'agosto', 9 =&gt; 'setembro', 10 =&gt; 'outubro', 11 =&gt; 'novembro', 12 =&gt; 'dezembro', ], 'mb' =&gt; 'trfego (mb)', 'distribution' =&gt; '&lt;font color="#019522"&gt;ftp&lt;/font&gt; | &lt;font color="#0000ff"&gt;http&lt;/font&gt; | &lt;font color="#800000"&gt;e-mail&lt;/font&gt;', 'sumhttp' =&gt; 'resumo trfego de http em', 'sumftp' =&gt; 'resumo trfego de ftp em', 'summail' =&gt; 'resumo trfego de http em', ], 'translator' =&gt; 'ricardo luiz costa, rafael andrade, thiago goncalves de castro', ];</file><file name="lng/en.lng.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'languages' =&gt; [ 'cz' =&gt; 'czech', 'de' =&gt; 'german', 'en' =&gt; 'english', 'fr' =&gt; 'french', 'it' =&gt; 'italian', 'nl' =&gt; 'dutch', 'pt' =&gt; 'portuguese', 'se' =&gt; 'swedish', 'es' =&gt; 'spanish', 'ca' =&gt; 'catalan', ], '2fa' =&gt; [ '2fa' =&gt; '2fa options', '2fa_enabled' =&gt; 'activate two-factor authentication (2fa)', '2fa_removed' =&gt; '2fa removed successfully', '2fa_added' =&gt; '2fa activated successfully&lt;br&gt;&lt;a class="alert-link" href="%s?page=2fa"&gt;view 2fa details&lt;/a&gt;', '2fa_add' =&gt; 'activate 2fa', '2fa_delete' =&gt; 'deactivate 2fa', '2fa_verify' =&gt; 'verify code', '2fa_overview_desc' =&gt; 'here activate two-factor authentication account.&lt;br&gt;&lt;br&gt;you either use authenticator-app (time-based one-time password / totp) let froxlor send email account-address successful login one-time password.', '2fa_email_desc' =&gt; 'your account set use one-time passwords via e-mail. deactivate, click "deactivate 2fa"', '2fa_ga_desc' =&gt; 'your account set use time-based one-time passwords via authenticator-app. please scan qr code desired authenticator app generate codes. deactivate, click "deactivate 2fa"', '2fa_not_activated' =&gt; 'two-factor authentication enabled', '2fa_not_activated_for_user' =&gt; 'two-factor authentication enabled current user', 'type_2fa' =&gt; '2fa status', ], 'admin' =&gt; [ 'overview' =&gt; 'overview', 'ressourcedetails' =&gt; 'used resources', 'systemdetails' =&gt; 'system details', 'froxlordetails' =&gt; 'froxlor details', 'installedversion' =&gt; 'installed version', 'latestversion' =&gt; 'latest version', 'lookfornewversion' =&gt; [ 'clickhere' =&gt; 'search via webservice', 'error' =&gt; 'error reading', ], 'resources' =&gt; 'resources', 'customer' =&gt; 'customer', 'customers' =&gt; 'customers', 'customers_list_desc' =&gt; 'manage customers', 'customer_add' =&gt; 'create customer', 'customer_edit' =&gt; 'edit customer', 'username_default_msg' =&gt; 'leave empty autogenerated value', 'password_default_msg' =&gt; 'autogenerated empty', 'domains' =&gt; 'domains', 'domain_add' =&gt; 'create domain', 'domain_edit' =&gt; 'edit domain', 'subdomainforemail' =&gt; 'subdomains email-domains', 'admin' =&gt; 'admin', 'admins' =&gt; 'admins', 'admin_add' =&gt; 'create admin', 'admin_edit' =&gt; 'edit admin', 'customers_see_all' =&gt; 'can access admins/resellers resources?', 'change_serversettings' =&gt; 'can change server settings?', 'server' =&gt; 'system', 'serversettings' =&gt; 'settings', 'serversettings_desc' =&gt; 'manage froxlor system', 'rebuildconf' =&gt; 'rebuild config files', 'stdsubdomain' =&gt; 'standard subdomain', 'stdsubdomain_add' =&gt; 'create standard subdomain', 'phpenabled' =&gt; 'php enabled', 'deactivated' =&gt; 'deactivated', 'deactivated_user' =&gt; 'deactivate user', 'sendpassword' =&gt; 'send password', 'ownvhostsettings' =&gt; 'own vhost-settings', 'configfiles' =&gt; [ 'serverconfiguration' =&gt; 'configuration', 'overview' =&gt; 'overview', 'wizard' =&gt; 'wizard', 'distribution' =&gt; 'distribution', 'service' =&gt; 'service', 'daemon' =&gt; 'daemon', 'http' =&gt; 'webserver (http)', 'dns' =&gt; 'nameserver (dns)', 'mail' =&gt; 'mailserver (imap/pop3)', 'smtp' =&gt; 'mailserver (smtp)', 'ftp' =&gt; 'ftp-server', 'etc' =&gt; 'others (system)', 'choosedistribution' =&gt; '-- choose distribution --', 'chooseservice' =&gt; '-- choose service --', 'choosedaemon' =&gt; '-- choose daemon --', 'statistics' =&gt; 'statistics', 'compactoverview' =&gt; 'compact-overview', 'legend' =&gt; '&lt;h3&gt;you configure service/daemon&lt;/h3&gt;', 'commands' =&gt; '&lt;span class="text-danger"&gt;commands:&lt;/span&gt; commands executed line line root-user shell. safe copy whole block paste shell.', 'files' =&gt; '&lt;span class="text-danger"&gt;config files:&lt;/span&gt; commands textfields open editor target file. copy paste contents editor save file.&lt;br&gt;&lt;span class="text-danger"&gt;please note:&lt;/span&gt; mysql-password replaced security reasons. please replace "froxlor_mysql_password" use javascript form replace on-site. forgot mysql-password you\'ll find "lib/userdata.inc.php"', 'importexport' =&gt; 'import/export', 'finishnote' =&gt; 'parameter file generated successfully. run following command root:', 'description' =&gt; 'configure system services', 'minihowto' =&gt; 'on page view different configuration templates service, (re-)configure specific services needed export current selection json file use cli scripts another server.&lt;br&gt;&lt;br&gt;&lt;b&gt;note&lt;/b&gt; services highlighted reflect current setup show requirements/recommendations current setting values.', 'skipconfig' =&gt; 'don\'t (re)configure', 'recommendednote' =&gt; 'recommended/required services based current system settings', 'selectrecommended' =&gt; 'select recommended', 'downloadselected' =&gt; 'export selected', ], 'templates' =&gt; [ 'templates' =&gt; 'email-templates', 'template_add' =&gt; 'add template', 'template_fileadd' =&gt; 'add file template', 'template_edit' =&gt; 'edit template', 'action' =&gt; 'action', 'email' =&gt; 'email &amp; file templates', 'subject' =&gt; 'subject', 'mailbody' =&gt; 'mail body', 'createcustomer' =&gt; 'welcome mail new customers', 'pop_success' =&gt; 'welcome mail new email accounts', 'template_replace_vars' =&gt; 'variables replaced template:', 'salutation' =&gt; 'replaced correct salutation (name company)', 'firstname' =&gt; 'replaced customer\'s first name.', 'name' =&gt; 'replaced customers name.', 'company' =&gt; 'replaces customer\'s company name', 'username' =&gt; 'replaced customer\'s account username.', 'password' =&gt; 'replaced customer\'s account password.', 'email' =&gt; 'replaced address pop3/imap account.', 'customer_no' =&gt; 'replaces customer number', 'traffic' =&gt; 'replaced traffic, assigned customer.', 'trafficused' =&gt; 'replaced traffic, exhausted customer.', 'pop_success_alternative' =&gt; 'welcome mail new email accounts sent alternative address', 'email_password' =&gt; 'replaced pop3/imap account password.', 'index_html' =&gt; 'index file newly created customer directories', 'unconfigured_html' =&gt; 'index file unconfigured/unknown domains', 'unconfigured_content_fallback' =&gt; 'this domain requires configuration via froxlor server management panel, currently assigned customer.', 'file_extension' =&gt; [ 'description' =&gt; 'the file extension index file must 1 6 characters long. extension contain characters like a-z, a-z 0-9&lt;br&gt;&lt;br&gt;default: html', 'title' =&gt; 'file extension file template', ], 'servername' =&gt; 'replaced servername.', 'customer' =&gt; 'replaced loginname customer. "index file newly created customer directories"', 'admin' =&gt; 'replaced loginname admin. "index file newly created customer directories"', 'customer_email' =&gt; 'replaced e-mail address customer. "index file newly created customer directories"', 'admin_email' =&gt; 'replaced e-mail address admin. "index file newly created customer directories"', 'filetemplates' =&gt; 'file templates', 'filecontent' =&gt; 'file content', 'new_database_by_customer' =&gt; 'customer-notification database created', 'new_ftpaccount_by_customer' =&gt; 'customer-notification ftp-user created', 'newdatabase' =&gt; 'notification-mails new databases', 'newftpuser' =&gt; 'notification-mails new ftp-user', 'cust_name' =&gt; 'customer name', 'db_name' =&gt; 'database name', 'db_pass' =&gt; 'database password', 'db_desc' =&gt; 'database description', 'db_srv' =&gt; 'database server', 'pma_uri' =&gt; 'url phpmyadmin (if given)', 'usr_name' =&gt; 'ftp username', 'usr_pass' =&gt; 'ftp password', 'usr_path' =&gt; 'ftp homedir (relative customer-docroot)', 'forgotpwd' =&gt; 'notification-mails password-reset', 'password_reset' =&gt; 'customer-notification password-reset', 'trafficmaxpercent' =&gt; 'notification mail customers given maximum percent traffic exhausted', 'max_percent' =&gt; 'replaced diskusage/traffic limit sending reports percent.', 'usage_percent' =&gt; 'replaced diskusage/traffic, exhausted customer percent.', 'diskmaxpercent' =&gt; 'notification mail customers given maximum percent diskspace exhausted', 'diskavailable' =&gt; 'replaced diskusage, assigned customer.', 'diskused' =&gt; 'replaced diskusage, exhausted customer.', 'link' =&gt; 'replaced customers password reset link.', 'server_hostname' =&gt; 'replaces system-hostname (url froxlor)', 'server_ip' =&gt; 'replaces default server ip-address', 'server_port' =&gt; 'replaces default server port', 'domainname' =&gt; 'replaces customers standard-subdomain (can empty none generated)', ], 'webserver' =&gt; 'webserver', 'createzonefile' =&gt; 'create dns zone domain', 'custombindzone' =&gt; 'custom / unmanaged zone file', 'bindzonewarning' =&gt; 'empty defaults&lt;br /&gt;&lt;strong class="text-danger"&gt;attention:&lt;/strong&gt; use zonefile manage required records sub-zones manually well.', 'ipsandports' =&gt; [ 'ipsandports' =&gt; 'ips ports', 'add' =&gt; 'add ip/port', 'edit' =&gt; 'edit ip/port', 'ipandport' =&gt; 'ip/port', 'ip' =&gt; 'ip', 'ipnote' =&gt; '&lt;div id="ipnote" class="invalid-feedback"&gt;note: although private ip addresses allowed, features like dns might behave correctly.&lt;br&gt;only use private ip addresses sure.&lt;/div&gt;', 'port' =&gt; 'port', 'create_listen_statement' =&gt; 'create listen statement', 'create_namevirtualhost_statement' =&gt; 'create namevirtualhost statement', 'create_vhostcontainer' =&gt; 'create vhost-container', 'create_vhostcontainer_servername_statement' =&gt; 'create servername statement vhost-container', 'enable_ssl' =&gt; 'is ssl port?', 'ssl_cert_file' =&gt; 'path ssl certificate', 'webserverdefaultconfig' =&gt; 'webserver default config', 'webserverdomainconfig' =&gt; 'webserver domain config', 'webserverssldomainconfig' =&gt; 'webserver ssl config', 'ssl_key_file' =&gt; 'path ssl keyfile', 'ssl_ca_file' =&gt; 'path ssl ca certificate', 'default_vhostconf_domain' =&gt; 'default vhost-settings every domain container', 'ssl_cert_chainfile' =&gt; [ 'title' =&gt; 'path ssl certificatechainfile', 'description' =&gt; 'mostly ca_bundle, similar, probably want set bought ssl certificate.', ], 'docroot' =&gt; [ 'title' =&gt; 'custom docroot (empty = point froxlor)', 'description' =&gt; 'you define custom document-root (the destination request) ip/port combination here.&lt;br /&gt;&lt;strong&gt;attention:&lt;/strong&gt; please careful enter here!', ], 'ssl_paste_description' =&gt; 'paste complete certificate content textbox', 'ssl_cert_file_content' =&gt; 'content ssl certificate', 'ssl_key_file_content' =&gt; 'content ssl (private-) key file', 'ssl_ca_file_content' =&gt; 'content ssl ca file (optional)', 'ssl_ca_file_content_desc' =&gt; '&lt;br /&gt;&lt;br /&gt;client authentication, set know is.', 'ssl_cert_chainfile_content' =&gt; 'content certificate chain file (optional)', 'ssl_cert_chainfile_content_desc' =&gt; '&lt;br /&gt;&lt;br /&gt;mostly ca_bundle, similar, probably want set bought ssl certificate.', 'ssl_default_vhostconf_domain' =&gt; 'default ssl vhost-settings every domain container', ], 'memorylimitdisabled' =&gt; 'disabled', 'valuemandatory' =&gt; 'this value mandatory', 'valuemandatorycompany' =&gt; 'either "name" "firstname" "company" must filled', 'serversoftware' =&gt; 'serversoftware', 'phpversion' =&gt; 'php-version', 'mysqlserverversion' =&gt; 'mysql server version', 'webserverinterface' =&gt; 'webserver interface', 'accountsettings' =&gt; 'account settings', 'panelsettings' =&gt; 'panel settings', 'systemsettings' =&gt; 'system settings', 'webserversettings' =&gt; 'webserver settings', 'mailserversettings' =&gt; 'mailserver settings', 'nameserversettings' =&gt; 'nameserver settings', 'updatecounters' =&gt; 'recalculate resource usage', 'subcanemaildomain' =&gt; [ 'never' =&gt; 'never', 'choosableno' =&gt; 'choosable, default no', 'choosableyes' =&gt; 'choosable, default yes', 'always' =&gt; 'always', ], 'wipecleartextmailpwd' =&gt; 'clear plaintext passwords', 'webalizersettings' =&gt; 'webalizer settings', 'webalizer' =&gt; [ 'normal' =&gt; 'normal', 'quiet' =&gt; 'quiet', 'veryquiet' =&gt; 'no output', ], 'domain_nocustomeraddingavailable' =&gt; 'it\'s possible add domain currently. first need add least one customer.', 'loggersettings' =&gt; 'log settings', 'logger' =&gt; [ 'normal' =&gt; 'normal', 'paranoid' =&gt; 'paranoid', ], 'emaildomain' =&gt; 'emaildomain', 'email_only' =&gt; 'only email?', 'wwwserveralias' =&gt; 'add "www." serveralias', 'subject' =&gt; 'subject', 'recipient' =&gt; 'recipient', 'message' =&gt; 'write message', 'text' =&gt; 'message', 'sslsettings' =&gt; 'ssl settings', 'specialsettings_replacements' =&gt; 'you use following variables:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (if applicable)&lt;br/&gt;', 'antispam_settings' =&gt; 'antispam settings', 'caneditphpsettings' =&gt; 'can change php-related domain settings?', 'allips' =&gt; 'all ip\'s', 'awstatssettings' =&gt; 'awstats settings', 'domain_dns_settings' =&gt; 'domain dns settings', 'activated' =&gt; 'activated', 'statisticsettings' =&gt; 'statistic settings', 'or' =&gt; 'or', 'sysload' =&gt; 'system load', 'noloadavailable' =&gt; 'not available', 'nouptimeavailable' =&gt; 'not available', 'nosubject' =&gt; '(no subject)', 'security_settings' =&gt; 'security options', 'know_what_youre_doing' =&gt; 'change only, know you\'re doing!', 'show_version_login' =&gt; [ 'title' =&gt; 'show froxlor version login', 'description' =&gt; 'show froxlor version footer login page', ], 'show_version_footer' =&gt; [ 'title' =&gt; 'show froxlor version footer', 'description' =&gt; 'show froxlor version footer rest pages', ], 'froxlor_graphic' =&gt; [ 'title' =&gt; 'header graphic froxlor', 'description' =&gt; 'what graphic shown header', ], 'phpsettings' =&gt; [ 'title' =&gt; 'php configuration', 'description' =&gt; 'short description', 'actions' =&gt; 'actions', 'activedomains' =&gt; 'in use domain(s)', 'notused' =&gt; 'configuration use', 'editsettings' =&gt; 'change php settings', 'addsettings' =&gt; 'create new php settings', 'viewsettings' =&gt; 'view php settings', 'phpinisettings' =&gt; 'php.ini settings', 'addnew' =&gt; 'create new php configuration', 'binary' =&gt; 'php binary', 'fpmdesc' =&gt; 'php-fpm config', 'file_extensions' =&gt; 'file extensions', 'file_extensions_note' =&gt; '(without dot, separated spaces)', 'enable_slowlog' =&gt; 'enable slowlog (per domain)', 'request_terminate_timeout' =&gt; 'request terminate-timeout', 'request_slowlog_timeout' =&gt; 'request slowlog-timeout', 'activephpconfigs' =&gt; 'in use php-config(s)', 'pass_authorizationheader' =&gt; 'passing http auth basic/digest headers apache php', ], 'misc' =&gt; 'miscellaneous', 'fpmsettings' =&gt; [ 'addnew' =&gt; 'create new php version', 'edit' =&gt; 'change php version' ], 'phpconfig' =&gt; [ 'template_replace_vars' =&gt; 'variables replaced configs', 'pear_dir' =&gt; 'will replaced global setting pear directory.', 'open_basedir_c' =&gt; 'will insert ; (semicolon) comment-out/disable open_basedir set', 'open_basedir' =&gt; 'will replaced open_basedir setting domain.', 'tmp_dir' =&gt; 'will replaced temporary directory domain.', 'open_basedir_global' =&gt; 'will replaced global value path attached open_basedir (see webserver settings).', 'customer_email' =&gt; 'will replaced e-mail address customer owns domain.', 'admin_email' =&gt; 'will replaced e-mail address admin owns domain.', 'domain' =&gt; 'will replaced domain.', 'customer' =&gt; 'will replaced loginname customer owns domain.', 'admin' =&gt; 'will replaced loginname admin owns domain.', 'docroot' =&gt; 'will replaced domain\'s document-root.', 'homedir' =&gt; 'will replaced customer\'s home-directory.', ], 'expert_settings' =&gt; 'expert settings!', 'mod_fcgid_starter' =&gt; [ 'title' =&gt; 'php processes domain (empty default value)', ], 'phpserversettings' =&gt; 'php settings', 'mod_fcgid_maxrequests' =&gt; [ 'title' =&gt; 'maximum php requests domain (empty default value)', ], 'spfsettings' =&gt; 'domain spf settings', 'specialsettingsforsubdomains' =&gt; 'apply specialsettings subdomains (*.example.com)', 'accountdata' =&gt; 'account data', 'contactdata' =&gt; 'contact data', 'servicedata' =&gt; 'service data', 'newerversionavailable' =&gt; 'there newer version froxlor available.', 'newerversiondetails' =&gt; 'update version &lt;b&gt;%s&lt;/b&gt; now?&lt;br/&gt;(your current version is: %s)', 'extractdownloadedzip' =&gt; 'extract downloaded archive "%s"?', 'cron' =&gt; [ 'cronsettings' =&gt; 'cronjob settings', 'add' =&gt; 'add cronjob', ], 'cronjob_edit' =&gt; 'edit cronjob', 'warning' =&gt; 'warning - please note!', 'lastlogin_succ' =&gt; 'last login', 'ftpserver' =&gt; 'ftp server', 'ftpserversettings' =&gt; 'ftp server settings', 'webserver_user' =&gt; 'webserver user-name', 'webserver_group' =&gt; 'webserver group-name', 'perlenabled' =&gt; 'perl enabled', 'fcgid_settings' =&gt; 'fcgid', 'mod_fcgid_user' =&gt; 'local user use fcgid (froxlor vhost)', 'mod_fcgid_group' =&gt; 'local group use fcgid (froxlor vhost)', 'perl_settings' =&gt; 'perl/cgi', 'notgiven' =&gt; '[not given]', 'store_defaultindex' =&gt; 'store default index-file customers docroot', 'phpfpm_settings' =&gt; 'php-fpm', 'traffic' =&gt; 'traffic', 'traffic_sub' =&gt; 'details traffic usage', 'domaintraffic' =&gt; 'domains', 'customertraffic' =&gt; 'customers', 'assignedmax' =&gt; 'assigned / max', 'usedmax' =&gt; 'used / max', 'used' =&gt; 'used', 'speciallogwarning' =&gt; '&lt;div id="speciallogfilenote" class="invalid-feedback"&gt;warning: changing setting lose old statistics domain.&lt;/div&gt;', 'speciallogfile' =&gt; [ 'title' =&gt; 'separate logfile', 'description' =&gt; 'enable get separate access-log file domain', ], 'domain_editable' =&gt; [ 'title' =&gt; 'allow editing domain', 'desc' =&gt; 'if set yes, customer allowed change several domain-settings.&lt;br /&gt;if set no, nothing changed customer.', ], 'writeaccesslog' =&gt; [ 'title' =&gt; 'write access log', 'description' =&gt; 'enable get access-log file domain', ], 'writeerrorlog' =&gt; [ 'title' =&gt; 'write error log', 'description' =&gt; 'enable get error-log file domain', ], 'phpfpm.ininote' =&gt; 'not values may want define used php-fpm pool configuration', 'phpinfo' =&gt; 'phpinfo()', 'selectserveralias' =&gt; 'serveralias value domain', 'selectserveralias_desc' =&gt; 'choose whether froxlor create wildcard-entry (*.domain.tld), www-alias (www.domain.tld) alias all', 'show_news_feed' =&gt; [ 'title' =&gt; 'show news-feed admin-dashboard', 'description' =&gt; 'enable show official froxlor newsfeed (https://inside.froxlor.org/news/) dashboard never miss important information release-announcements.', ], 'cronsettings' =&gt; 'cronjob settings', 'integritycheck' =&gt; 'database validation', 'integrityname' =&gt; 'name', 'integrityresult' =&gt; 'result', 'integrityfix' =&gt; 'fix problems automatically', 'customer_show_news_feed' =&gt; 'show newsfeed customer-dashboard', 'customer_news_feed_url' =&gt; [ 'title' =&gt; 'use custom rss-feed', 'description' =&gt; 'specify custom rss-feed shown customers dashboard.&lt;br /&gt;&lt;small&gt;leave empty use official froxlor newsfeed (https://inside.froxlor.org/news/).&lt;/small&gt;', ], 'movetoadmin' =&gt; 'move customer', 'movecustomertoadmin' =&gt; [ 'title' =&gt; 'move customer selected admin/reseller', 'description' =&gt; 'leave empty change.&lt;br /&gt;if desired admin show list, customer-limit reached.', ], 'note' =&gt; 'note', 'mod_fcgid_umask' =&gt; [ 'title' =&gt; 'umask (default: 022)', ], 'apcuinfo' =&gt; 'apcu info', 'opcacheinfo' =&gt; 'opcache info', 'letsencrypt' =&gt; [ 'title' =&gt; 'use let\'s encrypt', 'description' =&gt; 'get free certificate &lt;a href="https://letsencrypt.org"&gt;let\'s encrypt&lt;/a&gt;. certificate created renewed automatically.&lt;br&gt;&lt;strong class="text-danger"&gt;attention:&lt;/strong&gt; wildcards enabled, option automatically disabled.', ], 'autoupdate' =&gt; 'auto-update', 'server_php' =&gt; 'php', 'dnsenabled' =&gt; 'enable dns editor', 'froxlorvhost' =&gt; 'froxlor virtualhost settings', 'hostname' =&gt; 'hostname', 'memory' =&gt; 'memory usage', 'webserversettings_ssl' =&gt; 'webserver ssl settings', 'domain_hsts_maxage' =&gt; [ 'title' =&gt; 'http strict transport security (hsts)', 'description' =&gt; 'specify max-age value strict-transport-security header&lt;br&gt;the value &lt;i&gt;0&lt;/i&gt; disable hsts domain. user set value &lt;i&gt;31536000&lt;/i&gt; (one year).', ], 'domain_hsts_incsub' =&gt; [ 'title' =&gt; 'include hsts subdomain', 'description' =&gt; 'the optional "includesubdomains" directive, present, signals ua hsts policy applies hsts host well subdomains host\'s domain name.', ], 'domain_hsts_preload' =&gt; [ 'title' =&gt; 'include domain hsts preload list', 'description' =&gt; 'if would like domain included &lt;a href="https://hstspreload.org/" target="_blank"&gt;hsts preload list&lt;/a&gt; maintained chrome (and used firefox safari), use activate this.&lt;br&gt;sending preload directive site permanent consequences prevent users accessing site subdomains.&lt;br&gt;please read details &lt;a href="https://hstspreload.org/#removal" target="_blank"&gt;https://hstspreload.org/#removal&lt;/a&gt; sending header "preload".', ], 'domain_ocsp_stapling' =&gt; [ 'title' =&gt; 'ocsp stapling', 'description' =&gt; 'see &lt;a target="_blank" href="https://en.wikipedia.org/wiki/ocsp_stapling"&gt;wikipedia&lt;/a&gt; detailed explanation ocsp stapling', 'nginx_version_warning' =&gt; '&lt;br /&gt;&lt;strong class="text-danger"&gt;warning:&lt;/strong&gt; nginx version 1.3.7 required ocsp stapling. version older, webserver start correctly ocsp stapling enabled!', ], 'domain_http2' =&gt; [ 'title' =&gt; 'http2 support', 'description' =&gt; 'see &lt;a target="_blank" href="https://en.wikipedia.org/wiki/http/2"&gt;wikipedia&lt;/a&gt; detailed explanation http2', ], 'testmail' =&gt; 'smtp test', 'phpsettingsforsubdomains' =&gt; 'apply php-config subdomains:', 'plans' =&gt; [ 'name' =&gt; 'plan name', 'description' =&gt; 'description', 'last_update' =&gt; 'last updated', 'plans' =&gt; 'hosting plans', 'plan_details' =&gt; 'plan details', 'add' =&gt; 'add new plan', 'edit' =&gt; 'edit plan', 'use_plan' =&gt; 'apply plan', ], 'notryfiles' =&gt; [ 'title' =&gt; 'no autogenerated try_files', 'description' =&gt; 'say yes want specify custom try_files directive specialsettings (needed wordpress plugins example).', ], 'logviewenabled' =&gt; 'enable access access/error-logs', 'novhostcontainer' =&gt; '&lt;br&gt;&lt;br&gt;&lt;small class="text-danger"&gt;none ips ports "create vhost-container" option enabled, many settings available&lt;/small&gt;', 'ownsslvhostsettings' =&gt; 'own ssl vhost-settings', 'domain_override_tls' =&gt; 'override system tls settings', 'domain_override_tls_addinfo' =&gt; '&lt;br /&gt;&lt;span class="text-danger"&gt;only used "override system tls settings" set "yes"&lt;/span&gt;', 'domain_sslenabled' =&gt; 'enable usage ssl', 'domain_honorcipherorder' =&gt; 'honor (server) cipher order, default &lt;strong&gt;no&lt;/strong&gt;', 'domain_sessiontickets' =&gt; 'enable tls sessiontickets (rfc 5077), default &lt;strong&gt;yes&lt;/strong&gt;', 'domain_sessionticketsenabled' =&gt; [ 'title' =&gt; 'enable usage tls sessiontickets globally', 'description' =&gt; 'default &lt;strong&gt;yes&lt;/strong&gt;&lt;br&gt;requires apache-2.4.11+ nginx-1.5.9+', ], 'domaindefaultalias' =&gt; 'default serveralias value new domains', 'smtpsettings' =&gt; 'smtp settings', 'smtptestaddr' =&gt; 'send test-mail to', 'smtptestnote' =&gt; 'note values reflect current settings adjusted (see link top right corner)', 'smtptestsend' =&gt; 'send test-mail', 'mysqlserver' =&gt; [ 'mysqlserver' =&gt; 'mysql server', 'dbserver' =&gt; 'server #', 'caption' =&gt; 'description', 'host' =&gt; 'hostname / ip', 'port' =&gt; 'port', 'user' =&gt; 'privileged user', 'add' =&gt; 'add new mysql server', 'edit' =&gt; 'edit mysql server', 'password' =&gt; 'privileged user password', 'password_emptynochange' =&gt; 'new password, leave empty change', 'allowall' =&gt; [ 'title' =&gt; 'allow use server currently existing customers', 'description' =&gt; 'set "true" want allow use database-server currently existing customers add databases it. setting permanent run multiple times.', ], 'testconn' =&gt; 'test connection saving', 'ssl' =&gt; 'use ssl connection database-server', 'ssl_cert_file' =&gt; 'the file path ssl certificate authority', 'verify_ca' =&gt; 'enable verification server ssl certificate', ], 'settings_importfile' =&gt; 'chose import file', 'documentation' =&gt; 'documentation', 'adminguide' =&gt; 'admin guide', 'userguide' =&gt; 'user guide', 'apiguide' =&gt; 'api guide', 'domain_duplicate' =&gt; 'duplicate domain', 'domain_duplicate_named' =&gt; 'duplicate %s', 'backups' =&gt; [ 'backups' =&gt; 'backups', ], 'emaildomainwarning' =&gt; '&lt;div id="emaildomainnote" class="invalid-feedback"&gt;warning: changing setting delete existing e-mail addresses -accounts permanently.&lt;/div&gt;', ], 'apcuinfo' =&gt; [ 'clearcache' =&gt; 'clear apcu cache', 'generaltitle' =&gt; 'general cache information', 'version' =&gt; 'apcu version', 'phpversion' =&gt; 'php version', 'host' =&gt; 'apcu host', 'sharedmem' =&gt; 'shared memory', 'sharedmemval' =&gt; '%d segment(s) %s (%s memory)', 'start' =&gt; 'start time', 'uptime' =&gt; 'uptime', 'upload' =&gt; 'file upload support', 'cachetitle' =&gt; 'cache information', 'cvar' =&gt; 'cached variables', 'hit' =&gt; 'hits', 'miss' =&gt; 'misses', 'reqrate' =&gt; 'request rate (hits, misses)', 'creqsec' =&gt; 'cache requests/second', 'hitrate' =&gt; 'hit rate', 'missrate' =&gt; 'miss rate', 'insrate' =&gt; 'insert rate', 'cachefull' =&gt; 'cache full count', 'runtime' =&gt; 'runtime settings', 'memnote' =&gt; 'memory usage', 'total' =&gt; 'total', 'free' =&gt; 'free', 'used' =&gt; 'used', 'hitmiss' =&gt; 'hits &amp; misses', 'detailmem' =&gt; 'detailed memory usage fragmentation', 'fragment' =&gt; 'fragmentation', 'nofragment' =&gt; 'no fragmentation', 'fragments' =&gt; 'fragments', ], 'apikeys' =&gt; [ 'no_api_keys' =&gt; 'no api keys found', 'key_add' =&gt; 'add new key', 'apikey_removed' =&gt; 'the api key id #%s removed successfully', 'apikey_added' =&gt; 'a new api key generated successfully', 'clicktoview' =&gt; 'click view', 'allowed_from' =&gt; 'allowed from', 'allowed_from_help' =&gt; 'comma separated list ip addresses / networks.&lt;br&gt;default empty (allow all).', 'valid_until' =&gt; 'valid until', 'valid_until_help' =&gt; 'date valid, format yyyy-mm-ddthh:mm', ], 'changepassword' =&gt; [ 'old_password' =&gt; 'old password', 'new_password' =&gt; 'new password', 'new_password_confirm' =&gt; 'confirm password', 'new_password_ifnotempty' =&gt; 'new password (empty = change)', 'also_change_ftp' =&gt; ' also change password main ftp account', 'also_change_stats' =&gt; ' also change password statistics page', 'also_change_global_mysql' =&gt; 'also change password global mysql account', ], 'cron' =&gt; [ 'cronname' =&gt; 'cronjob-name', 'lastrun' =&gt; 'last run', 'interval' =&gt; 'interval', 'isactive' =&gt; 'enabled', 'description' =&gt; 'description', 'changewarning' =&gt; 'changing values negative cause behavior froxlor automated tasks.&lt;br /&gt;please change values here, sure know doing.', ], 'crondesc' =&gt; [ 'cron_unknown_desc' =&gt; 'no description given', 'cron_tasks' =&gt; 'generating configfiles', 'cron_legacy' =&gt; 'legacy (old) cronjob', 'cron_traffic' =&gt; 'traffic calculation', 'cron_usage_report' =&gt; 'web- traffic-reports', 'cron_mailboxsize' =&gt; 'mailbox-size calculation', 'cron_letsencrypt' =&gt; 'let\'s encrypt certificate updates', 'cron_export' =&gt; 'process data-export jobs', 'cron_backup' =&gt; 'process system- customer backup jobs', ], 'cronjob' =&gt; [ 'cronjobsettings' =&gt; 'cronjob settings', 'cronjobintervalv' =&gt; 'runtime interval value', 'cronjobinterval' =&gt; 'runtime interval', ], 'cronjobs' =&gt; [ 'notyetrun' =&gt; 'not yet run', ], 'cronmgmt' =&gt; [ 'minutes' =&gt; 'minutes', 'hours' =&gt; 'hours', 'days' =&gt; 'days', 'weeks' =&gt; 'weeks', 'months' =&gt; 'months', ], 'customer' =&gt; [ 'documentroot' =&gt; 'home directory', 'name' =&gt; 'name', 'firstname' =&gt; 'first name', 'lastname' =&gt; 'last name', 'company' =&gt; 'company', 'nameorcompany_desc' =&gt; 'either firstname/lastname company required', 'street' =&gt; 'street', 'zipcode' =&gt; 'zipcode', 'city' =&gt; 'city', 'phone' =&gt; 'phone', 'fax' =&gt; 'fax', 'email' =&gt; 'email', 'customernumber' =&gt; 'customer id', 'diskspace' =&gt; 'webspace', 'traffic' =&gt; 'traffic', 'mysqls' =&gt; 'mysql-databases', 'emails' =&gt; 'email-addresses', 'accounts' =&gt; 'email-accounts', 'forwarders' =&gt; 'email-forwarders', 'ftps' =&gt; 'ftp-accounts', 'subdomains' =&gt; 'subdomains', 'domains' =&gt; 'domains', 'mib' =&gt; 'mib', 'gib' =&gt; 'gib', 'title' =&gt; 'title', 'country' =&gt; 'country', 'email_quota' =&gt; 'e-mail quota', 'email_imap' =&gt; 'e-mail imap', 'email_pop3' =&gt; 'e-mail pop3', 'sendinfomail' =&gt; 'send data via email me', 'generated_pwd' =&gt; 'password suggestion', 'usedmax' =&gt; 'used / max', 'services' =&gt; 'services', 'letsencrypt' =&gt; [ 'title' =&gt; 'use let\'s encrypt', 'description' =&gt; 'get free certificate &lt;a href="https://letsencrypt.org"&gt;let\'s encrypt&lt;/a&gt;. certificate created renewed automatically.', ], 'selectserveralias_addinfo' =&gt; 'this option set editing domain. initial value inherited parent-domain.', 'total_diskspace' =&gt; 'total diskspace', 'mysqlserver' =&gt; 'usable mysql-server', ], 'diskquota' =&gt; 'quota', 'antispam' =&gt; [ 'config_file' =&gt; [ 'title' =&gt; 'antispam settings file', 'description' =&gt; 'please specify filename email-antispam rules', ], 'reload_command' =&gt; [ 'title' =&gt; 'milter restart command', 'description' =&gt; 'please specify restart command rspamd service', ], 'activated' =&gt; [ 'title' =&gt; 'activate antispam?', 'description' =&gt; 'would like use rspamd antispam service?', ], 'dkim_keylength' =&gt; [ 'title' =&gt; 'dkim key-length', 'description' =&gt; 'attention: changes apply new keys&lt;br/&gt;&lt;br/&gt;requires specific dns entry domain. using nameserver feature, manually manage entries.', ], 'spam_tag_level' =&gt; [ 'title' =&gt; 'spam tag level', 'description' =&gt; 'score required mark email spam&lt;br/&gt;default: 7.0' ], 'rewrite_subject' =&gt; [ 'title' =&gt; 'rewrite subject', 'description' =&gt; 'whether add &lt;strong&gt;***spam***&lt;/strong&gt; email subject applicable', ], 'spam_kill_level' =&gt; [ 'title' =&gt; 'spam kill level', 'description' =&gt; 'score required discard email entirely&lt;br/&gt;default: 14.0' ], 'bypass_spam' =&gt; [ 'title' =&gt; 'bypass spamfilter', 'description' =&gt; 'activate bypass/disable spamfiltering address.&lt;br/&gt;default: no' ], 'policy_greylist' =&gt; [ 'title' =&gt; 'use greylisting', 'description' =&gt; 'incoming emails protected &lt;a href="https://en.wikipedia.org/wiki/greylisting_(email)" target="_blank"&gt;greylisting&lt;/a&gt;.&lt;br/&gt;default: yes' ], 'required_spf_dns' =&gt; 'required spf dns entry', 'required_dmarc_dns' =&gt; 'required dmarc dns entry', 'required_dkim_dns' =&gt; 'required dkim dns entry', 'default_select' =&gt; [ 'on_changeable' =&gt; 'activated, adjustable', 'off_changeable' =&gt; 'deactivated, adjustable', 'on_unchangeable' =&gt; 'activated, adjustable', 'off_unchangeable' =&gt; 'deactivated, adjustable', ], 'default_bypass_spam' =&gt; [ 'title' =&gt; 'bypass spamfilter default value', 'description' =&gt; 'whether new email accounts "bypass spamfilter" activated default whether setting adjustable customer.&lt;br/&gt;default: deactivated, adjustable' ], 'default_spam_rewrite_subject' =&gt; [ 'title' =&gt; 'rewrite subject default value', 'description' =&gt; 'whether new email accounts "rewrite subject" activated default whether setting adjustable customer.&lt;br/&gt;default: activated, adjustable' ], 'default_policy_greylist' =&gt; [ 'title' =&gt; 'use greylisting default value', 'description' =&gt; 'whether new email accounts "use greylisting" activated default whether setting adjustable customer.&lt;br/&gt;default: activated, adjustable' ], ], 'dns' =&gt; [ 'destinationip' =&gt; 'domain ip(s)', 'standardip' =&gt; 'server standard ip', 'a_record' =&gt; 'a-record (ipv6 optional)', 'cname_record' =&gt; 'cname-record', 'mxrecords' =&gt; 'define mx records', 'standardmx' =&gt; 'server standard mx record', 'mxconfig' =&gt; 'custom mx records', 'priority10' =&gt; 'priority 10', 'priority20' =&gt; 'priority 20', 'txtrecords' =&gt; 'define txt records', 'txtexample' =&gt; 'example (spf-entry):&lt;br /&gt;v=spf1 ip4:xxx.xxx.xx.0/23 -all', 'howitworks' =&gt; 'here manage dns entries domain. note froxlor automatically generate ns/mx/a/aaaa records you. custom entries preferred, missing entries automatically generated.', ], 'dnseditor' =&gt; [ 'edit' =&gt; 'edit dns', 'records' =&gt; 'records', 'notes' =&gt; [ 'a' =&gt; '32-bit ipv4 address, used map hostnames ip address host.', 'aaaa' =&gt; '128-bit ipv6 address, used map hostnames ip address host.', 'caa' =&gt; 'the caa resource record allows dns domain name holder specify one certification authorities (cas) authorized issue certificates domain.&lt;br&gt;structure: &lt;code&gt;flag tag[issue|issuewild|iodef|contactmail|contactphone] value&lt;/code&gt;&lt;br&gt;example: &lt;code&gt;0 issue "ca.example.net"&lt;br&gt;0 iodef "mailto:security@example.com"&lt;/code&gt;', 'cname' =&gt; 'alias domain name, dns lookup continue retrying lookup new name. possible subdomains!', 'dname' =&gt; 'creates alias entire subtree domain name tree', 'loc' =&gt; 'geographic location information domain name.&lt;br&gt;structure: &lt;code&gt;( d1 [m1 [s1]] {"n"|"s"} d2 [m2 [s2]] {"e"|"w"} alt["m"] [siz["m"] [hp["m"] [vp["m"]]]] )&lt;/code&gt;&lt;br&gt;description: &lt;code&gt;d1: [0 .. 90] (degrees latitude) d2: [0 .. 180] (degrees longitude) m1, m2: [0 .. 59] (minutes latitude/longitude) s1, s2: [0 .. 59.999] (seconds latitude/longitude) alt: [-100000.00 .. 42849672.95] .01 (altitude meters) siz, hp, vp: [0 .. 90000000.00] (size/precision meters)&lt;/code&gt;&lt;br&gt;example: &lt;code&gt;52 22 23.000 n 4 53 32.000 e -2.00m 0.00m 10000m 10m&lt;/code&gt;', 'mx' =&gt; 'mail exchange record, maps domain name mailserver domain.&lt;br&gt;example: &lt;code&gt;10 mail.example.com&lt;/code&gt;&lt;br&gt;note: priority, use field above', 'ns' =&gt; 'delegates dns zone use given authoritative name servers.', 'rp' =&gt; 'responsible person record&lt;br&gt;structure: &lt;code&gt;mailbox[replace @ dot] txt-record-name&lt;/code&gt;&lt;br&gt;example: &lt;code&gt;team.froxlor.org. froxlor.org.&lt;/code&gt;', 'srv' =&gt; 'service location record, used newer protocols instead creating protocol-specific records mx.&lt;br&gt;structure: &lt;code&gt;priority weight port target&lt;/code&gt;&lt;br&gt;example: &lt;code&gt;0 5 5060 sipserver.example.com.&lt;/code&gt;&lt;br&gt;note: priority, use field above', 'sshfp' =&gt; 'the sshfp resource record used publish secure shell (ssh) key fingerprints dns.&lt;br&gt;structure: &lt;code&gt;algorithm type fingerprint&lt;/code&gt;&lt;br&gt;algorithms: &lt;code&gt;0: reserved, 1: rsa, 2: dsa, 3: ecdsa, 4: ed25519, 6: ed448&lt;/code&gt;&lt;br&gt;types: &lt;code&gt;0: reserved, 1: sha-1, 2: sha-256&lt;/code&gt;&lt;br&gt;example: &lt;code&gt;2 1 123456789abcdef67890123456789abcdef67890&lt;/code&gt;', 'tlsa' =&gt; 'tlsa (tls authentication) record used publish fingerprint tls/ssl certificate. commonly used dane.&lt;br&gt;tlsa records trusted dnssec enabled domain.&lt;br&gt;structure: &lt;code&gt;usage selector type fingerprint&lt;/code&gt;&lt;br&gt;certificate usage: &lt;code&gt;0: pkix-t, 1: pkix-ee, 2: dane-ta, 3: dane-ee&lt;/code&gt;&lt;br&gt;selector: &lt;code&gt;0: use full certificate, 1: use subject public key&lt;/code&gt;&lt;br&gt;matching type: &lt;code&gt;0: full: hash, 1: sha-256 hash, 2:sha-512 hash&lt;/code&gt;&lt;br&gt;example: &lt;code&gt;3 1 1 123456789abcdef67890123456789abcdef123456789abcdef123456789abcde&lt;/code&gt;', 'txt' =&gt; 'free definable, descriptive text.' ] ], 'domain' =&gt; [ 'openbasedirpath' =&gt; 'openbasedir-path', 'inherited' =&gt; 'same parent-domain', 'docroot' =&gt; 'path field above', 'homedir' =&gt; 'home directory', 'docparent' =&gt; 'parent-directory path field above', 'ssl_certificate_placeholder' =&gt; '---- begin certificate---' . php_eol . '[...]' . php_eol . '----end certificate----', 'ssl_key_placeholder' =&gt; '---- begin rsa private key-----' . php_eol . '[...]' . php_eol . '-----end rsa private key-----', ], 'domains' =&gt; [ 'description' =&gt; 'here create (sub-)domains change paths.&lt;br /&gt;the system need time apply new settings every change.', 'domainsettings' =&gt; 'domain settings', 'domainname' =&gt; 'domain name', 'subdomain_add' =&gt; 'create subdomain', 'subdomain_edit' =&gt; 'edit (sub)domain', 'wildcarddomain' =&gt; 'create wildcarddomain?', 'aliasdomain' =&gt; 'alias domain', 'noaliasdomain' =&gt; 'no alias domain', 'hasaliasdomains' =&gt; 'has alias domain(s)', 'statstics' =&gt; 'usage statistics', 'isassigneddomain' =&gt; 'is assigned domain', 'add_date' =&gt; 'added froxlor', 'registration_date' =&gt; 'added registry', 'topleveldomain' =&gt; 'top-level-domain', 'associated_with_domain' =&gt; 'associated', 'aliasdomains' =&gt; 'alias domains', 'redirectifpathisurl' =&gt; 'redirect code (default: empty)', 'redirectifpathisurlinfo' =&gt; 'you need select one entered url path&lt;br/&gt;&lt;strong class="text-danger"&gt;note:&lt;/strong&gt; changes applied given path url.', 'ipandport_multi' =&gt; [ 'title' =&gt; 'ip address(es)', 'description' =&gt; 'specify one ip address domain.&lt;br /&gt;&lt;br /&gt;&lt;div class="text-danger"&gt;note: ip addresses cannot changed domain configured &lt;strong&gt;alias-domain&lt;/strong&gt; another domain.&lt;/div&gt;', ], 'ipandport_ssl_multi' =&gt; [ 'title' =&gt; 'ssl ip address(es)', ], 'ssl_redirect' =&gt; [ 'title' =&gt; 'ssl redirect', 'description' =&gt; 'this option creates redirects non-ssl vhosts requests redirected ssl-vhost.&lt;br /&gt;&lt;br /&gt;e.g. request &lt;strong&gt;http&lt;/strong&gt;://domain.tld/ redirect &lt;strong&gt;https&lt;/strong&gt;://domain.tld/', ], 'serveraliasoption_wildcard' =&gt; 'wildcard (*.domain.tld)', 'serveraliasoption_www' =&gt; 'www (www.domain.tld)', 'serveraliasoption_none' =&gt; 'no alias', 'domain_import' =&gt; 'import domains', 'import_separator' =&gt; 'separator', 'import_offset' =&gt; 'offset', 'import_file' =&gt; 'csv-file', 'import_description' =&gt; 'detailed information structure import-file import successfully, please visit &lt;a href="https://docs.froxlor.org/latest/admin-guide/domain-import/" target="_blank" class="alert-link"&gt;https://docs.froxlor.org/latest/admin-guide/domain-import/&lt;/a&gt;', 'ssl_redirect_temporarilydisabled' =&gt; '&lt;br&gt;the ssl redirect temporarily deactivated new let\'s encrypt certificate generated. activated certificate generated.', 'termination_date' =&gt; 'date termination', 'termination_date_overview' =&gt; 'terminated ', 'ssl_certificates' =&gt; 'ssl certificates', 'ssl_certificate_removed' =&gt; 'the certificate id #%s removed successfully', 'ssl_certificate_error' =&gt; 'error reading certificate domain: %s', 'no_ssl_certificates' =&gt; 'there domains ssl certificate', 'isaliasdomainof' =&gt; 'is aliasdomain %s', 'isbinddomain' =&gt; 'create dns zone', 'dkimenabled' =&gt; 'dkim enabled', 'openbasedirenabled' =&gt; 'openbasedir restiction', 'hsts' =&gt; 'hsts enabled', 'aliasdomainid' =&gt; 'id alias domain', 'nodomainsassignedbyadmin' =&gt; 'your account currently (active) domains assigned it. please contact administrator think wrong.', 'email_only' =&gt; 'email only', ], 'emails' =&gt; [ 'description' =&gt; 'here create change email addresses.&lt;br /&gt;an account like letterbox front house. someone sends email, dropped account.&lt;br /&gt;&lt;br /&gt;to download emails use following settings mailprogram: (the data &lt;i&gt;italics&lt;/i&gt; changed equivalents typed in!)&lt;br /&gt;hostname: &lt;b&gt;&lt;i&gt;domainname&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;username: &lt;b&gt;&lt;i&gt;account name / e-mail address&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;password: &lt;b&gt;&lt;i&gt;the password you\'ve chosen&lt;/i&gt;&lt;/b&gt;', 'emailaddress' =&gt; 'email-address', 'emails_add' =&gt; 'create email-address', 'emails_edit' =&gt; 'edit email-address', 'catchall' =&gt; 'catchall', 'iscatchall' =&gt; 'define catchall-address?', 'account' =&gt; 'account', 'account_add' =&gt; 'create account', 'account_delete' =&gt; 'delete account', 'from' =&gt; 'source', 'to' =&gt; 'destination', 'forwarders' =&gt; 'forwarders', 'forwarder_add' =&gt; 'create forwarder', 'alternative_emailaddress' =&gt; 'alternative e-mail-address', 'quota' =&gt; 'quota', 'noquota' =&gt; 'no quota', 'updatequota' =&gt; 'update quota', 'quota_edit' =&gt; 'change e-mail quota', 'noemaildomainaddedyet' =&gt; 'you (email-)domain account yet.', 'back_to_overview' =&gt; 'back domain overview', 'accounts' =&gt; 'accounts', 'emails' =&gt; 'addresses', ], 'error' =&gt; [ 'error' =&gt; 'error', 'directorymustexist' =&gt; 'the directory %s must exist. please create ftp client.', 'filemustexist' =&gt; 'the file %s must exist.', 'allresourcesused' =&gt; 'you already used resources.', 'domains_cantdeletemaindomain' =&gt; 'you cannot delete assigned domain.', 'domains_canteditdomain' =&gt; 'you cannot edit domain. disabled admin.', 'domains_cantdeletedomainwithemail' =&gt; 'you cannot delete domain used email-domain. delete email addresses first.', 'firstdeleteallsubdomains' =&gt; 'you delete subdomains first create wildcard domain.', 'youhavealreadyacatchallforthisdomain' =&gt; 'you already defined catchall domain.', 'ftp_cantdeletemainaccount' =&gt; 'you cannot delete main ftp account', 'login' =&gt; 'the username password typed wrong. please try again!', 'login_blocked' =&gt; 'this account suspended many login errors. &lt;br /&gt;please try %s seconds.', 'notallreqfieldsorerrors' =&gt; 'you filled filled fields incorrectly.', 'oldpasswordnotcorrect' =&gt; 'the old password correct.', 'youcantallocatemorethanyouhave' =&gt; 'you cannot allocate resources yourself.', 'mustbeurl' =&gt; 'you typed valid complete url (e.g. http://somedomain.com/error404.htm)', 'invalidpath' =&gt; 'you chosen valid url (maybe problems dirlisting?)', 'stringisempty' =&gt; 'missing input field', 'stringiswrong' =&gt; 'wrong input field', 'newpasswordconfirmerror' =&gt; 'new password confirmation match', 'mydomain' =&gt; '\'domain\'', 'mydocumentroot' =&gt; '\'documentroot\'', 'loginnameexists' =&gt; 'loginname %s already exists', 'emailiswrong' =&gt; 'email-address %s contains invalid characters incomplete', 'emailexists' =&gt; 'email-address %s already use another admin', 'emailexistsanon' =&gt; 'email-address %s already use.', 'alternativeemailiswrong' =&gt; 'the given alternative email address %s send credentials seems invalid', 'loginnameiswrong' =&gt; 'loginname "%s" contains illegal characters.', 'loginnameiswrong2' =&gt; 'loginname contains many characters. %s characters allowed.', 'userpathcombinationdupe' =&gt; 'combination username path already exists', 'patherror' =&gt; 'general error! path cannot empty', 'errordocpathdupe' =&gt; 'option path %s already exists', 'adduserfirst' =&gt; 'please create customer first', 'domainalreadyexists' =&gt; 'the domain %s already assigned customer', 'nolanguageselect' =&gt; 'no language selected.', 'nosubjectcreate' =&gt; 'you must define topic mail template.', 'nomailbodycreate' =&gt; 'you must define mail-text mail template.', 'templatenotfound' =&gt; 'template found.', 'alltemplatesdefined' =&gt; 'you can\'t define templates, languages supported already.', 'wwwnotallowed' =&gt; 'www allowed subdomains.', 'subdomainiswrong' =&gt; 'the subdomain %s contains invalid characters.', 'domaincantbeempty' =&gt; 'the domain-name empty.', 'domainexistalready' =&gt; 'the domain %s already exists.', 'domainisaliasorothercustomer' =&gt; 'the selected alias domain either alias domain, different ip/port combination belongs another customer.', 'emailexistalready' =&gt; 'the email-address %s already exists.', 'maindomainnonexist' =&gt; 'the main-domain %s exist.', 'maindomaindeactivated' =&gt; 'the main-domain %s deactivated.', 'destinationnonexist' =&gt; 'please create forwarder field \'destination\'.', 'destinationalreadyexistasmail' =&gt; 'the forwarder %s already exists active email-address.', 'destinationalreadyexist' =&gt; 'you already defined forwarder "%s"', 'destinationiswrong' =&gt; 'the forwarder %s contains invalid character(s) incomplete.', 'dumpfoldercannotbedocroot' =&gt; 'the folder data-dumps cannot homedir, please chose folder within homedir, e.g. /dumps', 'templatelanguagecombodefined' =&gt; 'the selected language/template combination already defined.', 'templatelanguageinvalid' =&gt; 'the selected language exist', 'ipstillhasdomains' =&gt; 'the ip/port combination want delete still domains assigned it, please reassign ip/port combinations deleting ip/port combination.', 'cantdeletedefaultip' =&gt; 'you cannot delete default ip/port combination, please make another ip/port combination default deleting ip/port combination.', 'cantdeletesystemip' =&gt; 'you cannot delete last system ip, either create new ip/port combination system ip change system ip.', 'myipaddress' =&gt; '\'ip\'', 'myport' =&gt; '\'port\'', 'myipdefault' =&gt; 'you need select ip/port combination become default.', 'myipnotdouble' =&gt; 'this ip/port combination already exists.', 'admin_domain_emailsystemhostname' =&gt; 'the server-hostname cannot used customer-domain.', 'cantchangesystemip' =&gt; 'you cannot change last system ip, either create another new ip/port combination system ip change system ip.', 'sessiontimeoutiswrong' =&gt; 'only numerical "session timeout" allowed.', 'maxloginattemptsiswrong' =&gt; 'only numerical "max login attempts" allowed.', 'deactivatetimiswrong' =&gt; 'only numerical "deactivation time" allowed.', 'accountprefixiswrong' =&gt; 'the "customerprefix" wrong.', 'mysqlprefixiswrong' =&gt; 'the "sql prefix" wrong.', 'ftpprefixiswrong' =&gt; 'the "ftp prefix" wrong.', 'ipiswrong' =&gt; 'the "ip-address" wrong. valid ip-address allowed.', 'vmailuidiswrong' =&gt; 'the "mails-uid" wrong. numerical uid allowed.', 'vmailgidiswrong' =&gt; 'the "mails-gid" wrong. numerical gid allowed.', 'adminmailiswrong' =&gt; 'the "sender-address" wrong. valid email-address allowed.', 'pagingiswrong' =&gt; 'the "entries per page"-value wrong. numerical characters allowed.', 'phpmyadminiswrong' =&gt; 'the phpmyadmin-link valid link.', 'webmailiswrong' =&gt; 'the webmail-link valid link.', 'webftpiswrong' =&gt; 'the webftp-link valid link.', 'stringformaterror' =&gt; 'the value field "%s" expected format.', 'loginnameisusingprefix' =&gt; 'you cannot create accounts begin "%s", prefix set used automatic account-naming. please enter another account name.', 'loginnameissystemaccount' =&gt; 'the account "%s" already exists system cannot used. please enter another account name.', 'loginnameisreservedname' =&gt; 'the account-name "%s" reserved system internals cannot used.', 'youcantdeleteyourself' =&gt; 'you cannot delete security reasons.', 'youcanteditallfieldsofyourself' =&gt; 'note: cannot edit fields account security reasons.', 'documentrootexists' =&gt; 'the directory "%s" already exists customer. please remove adding customer again.', 'norepymailiswrong' =&gt; 'the "noreply-address" wrong. valid email-address allowed.', 'logerror' =&gt; 'log-error: %s', 'nomessagetosend' =&gt; 'you enter message.', 'norecipientsgiven' =&gt; 'you specify recipient', 'errorsendingmail' =&gt; 'the message "%s" failed', 'errorsendingmailpub' =&gt; 'the message given email-address failed', 'cannotreaddir' =&gt; 'unable read directory "%s"', 'invalidip' =&gt; 'invalid ip address: %s', 'invalidmysqlhost' =&gt; 'invalid mysql host address: %s', 'cannotuseawstatsandwebalizeratonetime' =&gt; 'you cannot enable webalizer awstats time, please chose one them', 'cannotwritetologfile' =&gt; 'cannot open logfile %s writing', 'vmailquotawrong' =&gt; 'the quotasize must positive number.', 'allocatetoomuchquota' =&gt; 'you tried allocate %s mb quota, enough left.', 'missingfields' =&gt; 'not required fields filled out.', 'requiredfield' =&gt; 'this field required.', 'accountnotexisting' =&gt; 'the given email account doesn\'t exist.', 'nopermissionsorinvalidid' =&gt; 'you don\'t enough permissions change settings invalid id given.', 'phpsettingidwrong' =&gt; 'a php configuration id doesn\'t exist', 'descriptioninvalid' =&gt; 'the description short, long contains illegal characters.', 'info' =&gt; 'info', 'filecontentnotset' =&gt; 'the file cannot empty!', 'customerdoesntexist' =&gt; 'the customer chosen doesn\'t exist.', 'admindoesntexist' =&gt; 'the admin chosen doesn\'t exist.', 'ipportdoesntexist' =&gt; 'the ip/port combination chosen doesn\'t exist.', 'usernamealreadyexists' =&gt; 'the username %s already exists.', 'plausibilitychecknotunderstood' =&gt; 'answer plausibility check understood.', 'errorwhensaving' =&gt; 'an error occurred saving field %s', 'hiddenfieldvaluechanged' =&gt; 'the value hidden field "%s" changed editing settings.&lt;br /&gt;&lt;br /&gt;this usually big problem settings could saved this.', 'notrequiredpasswordlength' =&gt; 'the given password short. please enter least %s characters.', 'overviewsettingoptionisnotavalidfield' =&gt; 'whoops, field displayed option settings-overview excepted type. blame developers this. happen!', 'pathmaynotcontaincolon' =&gt; 'the path entered contain colon (":"). please enter correct path value.', 'exception' =&gt; '%s', 'notrequiredpasswordcomplexity' =&gt; 'the specified password-complexity satisfied.&lt;br /&gt;please contact administrator questions complexity-specification', 'stringerrordocumentnotvalidforlighty' =&gt; 'a string errordocument work lighttpd, please specify path file', 'urlerrordocumentnotvalidforlighty' =&gt; 'an url errordocument work lighttpd, please specify path file', 'invaliderrordocumentvalue' =&gt; 'the value given errordocument seem valid file, url string.', 'intvaluetoolow' =&gt; 'the given number low (field %s)', 'intvaluetoohigh' =&gt; 'the given number high (field %s)', 'phpfpmstillenabled' =&gt; 'php-fpm currently active. please deactivate activating fcgid', 'fcgidstillenabled' =&gt; 'fcgid currently active. please deactivate activating php-fpm', 'domains_cantdeletedomainwithaliases' =&gt; 'you cannot delete domain used alias-domains. delete aliases first.', 'user_banned' =&gt; 'your account locked. please contact administrator information.', 'session_timeout' =&gt; 'value low', 'session_timeout_desc' =&gt; 'you set session timeout lower 1 minute.', 'invalidhostname' =&gt; 'hostname needs valid domain. can\'t empty consist whitespaces', 'operationnotpermitted' =&gt; 'operation permitted!', 'featureisdisabled' =&gt; 'feature %s disabled. please contact service provider.', 'usercurrentlydeactivated' =&gt; 'the user %s currently deactivated', 'setlessthanalreadyused' =&gt; 'you cannot set less resources \'%s\' user already used&lt;br /&gt;', 'stringmustntbeempty' =&gt; 'the value field %s must empty', 'sslcertificateismissingprivatekey' =&gt; 'you need specify private key certificate', 'sslcertificatewrongdomain' =&gt; 'the given certificate belong domain', 'sslcertificateinvalidcert' =&gt; 'the given certificate-content seem valid certificate', 'sslcertificateinvalidcertkeypair' =&gt; 'the given private-key belong given certificate', 'sslcertificateinvalidca' =&gt; 'the given ca certificate data seem valid certificate', 'sslcertificateinvalidchain' =&gt; 'the given certificate chain data seem valid certificate', 'givendirnotallowed' =&gt; 'the given directory field %s allowed.', 'sslredirectonlypossiblewithsslipport' =&gt; 'using let\'s encrypt possible domain least one ssl-enabled ip/port combination assigned.', 'fcgidstillenableddeadlock' =&gt; 'fcgid currently active.&lt;br /&gt;please deactivate switching another webserver apache2 lighttpd', 'send_report_title' =&gt; 'send error report', 'send_report_desc' =&gt; 'thank reporting error helping us improve froxlor.&lt;br /&gt;this email sent froxlor developer team:', 'send_report' =&gt; 'send report', 'send_report_error' =&gt; 'error sending report: &lt;br /&gt;%s', 'notallowedtouseaccounts' =&gt; 'your account allow using imap/pop3. cannot add email accounts.', 'cannotdeletehostnamephpconfig' =&gt; 'this php-configuration used froxlor-vhost cannot deleted.', 'cannotdeletedefaultphpconfig' =&gt; 'this php-configuration set default cannot deleted.', 'passwordshouldnotbeusername' =&gt; 'the password username.', 'no_phpinfo' =&gt; 'sorry, unable read phpinfo()', 'moveofcustomerfailed' =&gt; 'moving customer selected admin/reseller failed. keep mind changes customer applied successfully stage.&lt;br&gt;&lt;br&gt;error-message: %s', 'domain_import_error' =&gt; 'following error occurred importing domains: %s', 'fcgidandphpfpmnogoodtogether' =&gt; 'fcgid php-fpm cannot activated time', 'no_apcuinfo' =&gt; 'no cache info available. apcu appear running.', 'no_opcacheinfo' =&gt; 'no opcache info available. opcache appear loaded.', 'inactive_opcacheinfo' =&gt; 'opcache seems installed activated.', 'nowildcardwithletsencrypt' =&gt; 'let\'s encrypt cannot handle wildcard-domains using acme froxlor (requires dns-challenge), sorry. please set serveralias www disable completely', 'customized_version' =&gt; 'it looks like froxlor installation modified, support sorry.', 'autoupdate_0' =&gt; 'unknown error', 'autoupdate_1' =&gt; 'php setting allow_url_fopen disabled. autoupdate needs setting enabled php.ini', 'autoupdate_2' =&gt; 'php zip extension found, please ensure installed activated', 'autoupdate_4' =&gt; 'the froxlor archive could stored disk :(', 'autoupdate_5' =&gt; 'version.froxlor.org returned unacceptable values :(', 'autoupdate_6' =&gt; 'whoops, (valid) version given download :(', 'autoupdate_7' =&gt; 'the downloaded archive could found :(', 'autoupdate_8' =&gt; 'the archive could extracted :(', 'autoupdate_9' =&gt; 'the downloaded file pass integrity check. please try update again.', 'autoupdate_10' =&gt; 'minimum supported version php 7.4.0', 'autoupdate_11' =&gt; 'webupdate disabled', 'mailaccistobedeleted' =&gt; 'another account name (%s) currently deleted therefore added moment.', 'customerhasongoingexportjob' =&gt; 'there already data export job waiting processed, please patient.', 'exportfunctionnotenabled' =&gt; 'the export function enabled', 'dns_domain_nodns' =&gt; 'dns enabled domain', 'dns_content_empty' =&gt; 'no content given', 'dns_content_invalid' =&gt; 'dns content invalid', 'dns_arec_noipv4' =&gt; 'no valid ip address a-record given', 'dns_aaaarec_noipv6' =&gt; 'no valid ip address aaaa-record given', 'dns_mx_prioempty' =&gt; 'invalid mx priority given', 'dns_mx_needdom' =&gt; 'the mx content value must valid domain-name', 'dns_mx_noalias' =&gt; 'the mx-content value cannot cname entry.', 'dns_cname_invaliddom' =&gt; 'invalid domain-name cname record', 'dns_cname_nomorerr' =&gt; 'there already exists resource-record record-name. used cname.', 'dns_other_nomorerr' =&gt; 'there already exists cname record record-name. used another type.', 'dns_ns_invaliddom' =&gt; 'invalid domain-name ns record', 'dns_srv_prioempty' =&gt; 'invalid srv priority given', 'dns_srv_invalidcontent' =&gt; 'invalid srv content, must contain fields weight, port target, e.g.: 5 5060 sipserver.example.com.', 'dns_srv_needdom' =&gt; 'the srv target value must valid domain-name', 'dns_srv_noalias' =&gt; 'the srv-target value cannot cname entry.', 'dns_duplicate_entry' =&gt; 'record already exists', 'dns_notfoundorallowed' =&gt; 'domain found permission', 'domain_nopunycode' =&gt; 'you must specify punycode (idna). domain automatically converted', 'domain_noipaddress' =&gt; 'cannot add ip address domain', 'dns_record_toolong' =&gt; 'records/labels 63 characters', 'noipportgiven' =&gt; 'no ip/port given', 'nosslippportgiven' =&gt; 'when enabling ssl need select ssl ip/port', 'jsonextensionnotfound' =&gt; 'this feature requires php json-extension.', 'cannotdeletesuperadmin' =&gt; 'the first admin cannot deleted.', 'no_wwwcnamae_ifwwwalias' =&gt; 'cannot set cname record "www" domain set generate www-alias. please change settings either "no alias" "wildcard alias"', 'local_group_exists' =&gt; 'the given group already exists system.', 'local_group_invalid' =&gt; 'the given group name invalid', 'invaliddnsforletsencrypt' =&gt; 'the domains dns include chosen ip addresses. let\'s encrypt certificate generation possible.', 'notallowedphpconfigused' =&gt; 'trying use php-config assigned customer', 'pathmustberelative' =&gt; 'the user permission specify directories outside customers home-directory. please specify relative path (no leading /).', 'mysqlserverstillhasdbs' =&gt; 'cannot remove database server customers allow-list still databases it.', 'domaincannotbeedited' =&gt; 'you permitted edit domain %s', 'invalidcronjobintervalvalue' =&gt; 'cronjob interval must one of: %s', 'phpgdextensionnotavailable' =&gt; 'the php gd extension available. unable validate image-data', '2fa_wrongcode' =&gt; 'the code entered valid', 'gnupgextensionnotavailable' =&gt; 'the php gnupg extension available. unable validate pgp public key', 'invalidpgppublickey' =&gt; 'the pgp public key valid', 'invalid_validtime' =&gt; 'valid time seconds 10 120', 'customerphpenabledbutnoconfig' =&gt; 'customer php activated php-configuration selected.', 'emaildomainstillhasaddresses' =&gt; 'cannot deactivate mail-domain flag, still email-addresses domain.', ], 'extras' =&gt; [ 'description' =&gt; 'here add extras, example directory protection.&lt;br /&gt;the system need time apply new settings every change.', 'directoryprotection_add' =&gt; 'add directory protection', 'view_directory' =&gt; 'display directory content', 'pathoptions_add' =&gt; 'add path options', 'directory_browsing' =&gt; 'directory content browsing', 'pathoptions_edit' =&gt; 'edit path options', 'error404path' =&gt; '404', 'error403path' =&gt; '403', 'error500path' =&gt; '500', 'error401path' =&gt; '401', 'errordocument404path' =&gt; 'errordocument 404', 'errordocument403path' =&gt; 'errordocument 403', 'errordocument500path' =&gt; 'errordocument 500', 'errordocument401path' =&gt; 'errordocument 401', 'execute_perl' =&gt; 'execute perl/cgi', 'htpasswdauthname' =&gt; 'authentication reason (authname)', 'directoryprotection_edit' =&gt; 'edit directory protection', 'export' =&gt; 'create data dump', 'dump_web' =&gt; 'include web-data', 'dump_mail' =&gt; 'include mail-data', 'dump_dbs' =&gt; 'include databases', 'path_protection_label' =&gt; '&lt;strong class="text-danger"&gt;important&lt;/strong&gt;', 'path_protection_info' =&gt; 'we strongly recommend protecting given path, see "extras" -&gt; "directory protection"', ], 'ftp' =&gt; [ 'description' =&gt; 'here create change ftp-accounts.&lt;br /&gt;the changes made instantly accounts used immediately.', 'account_add' =&gt; 'create account', 'account_edit' =&gt; 'edit ftp account', 'editpassdescription' =&gt; 'set new password leave blank change.', ], 'gender' =&gt; [ 'title' =&gt; 'title', 'male' =&gt; 'mr.', 'female' =&gt; 'mrs.', 'undef' =&gt; '', ], 'imprint' =&gt; 'legal notes', 'index' =&gt; [ 'customerdetails' =&gt; 'customer details', 'accountdetails' =&gt; 'account details', ], 'integrity_check' =&gt; [ 'databasecharset' =&gt; 'character set database (should utf-8)', 'domainiptable' =&gt; 'ip &amp;lt;&amp;dash;&amp;gt; domain references', 'subdomainsslredirect' =&gt; 'false ssl-redirect flag non-ssl domains', 'froxlorlocalgroupmemberforfcgidphpfpm' =&gt; 'froxlor-user customer groups (for fcgid/php-fpm)', 'webservergroupmemberforfcgidphpfpm' =&gt; 'webserver-user customer groups (for fcgid/php-fpm)', 'subdomainletsencrypt' =&gt; 'main domains ssl-port assigned don\'t subdomains active ssl redirect', ], 'logger' =&gt; [ 'date' =&gt; 'date', 'type' =&gt; 'type', 'action' =&gt; 'action', 'user' =&gt; 'user', 'truncate' =&gt; 'empty log', 'reseller' =&gt; 'reseller', 'admin' =&gt; 'administrator', 'cron' =&gt; 'cronjob', 'login' =&gt; 'login', 'intern' =&gt; 'internal', 'unknown' =&gt; 'unknown', ], 'login' =&gt; [ 'username' =&gt; 'username', 'password' =&gt; 'password', 'language' =&gt; 'language', 'login' =&gt; 'login', 'logout' =&gt; 'logout', 'profile_lng' =&gt; 'profile language', 'welcomemsg' =&gt; 'please log access account.', 'forgotpwd' =&gt; 'forgot password?', 'presend' =&gt; 'reset password', 'email' =&gt; 'e-mail address', 'remind' =&gt; 'reset password', 'usernotfound' =&gt; 'user found!', 'backtologin' =&gt; 'back login', 'combination_not_found' =&gt; 'combination user email address found.', '2fa' =&gt; 'two-factor authentication (2fa)', '2facode' =&gt; 'please enter 2fa code', '2faremember' =&gt; 'trust browser', ], 'mails' =&gt; [ 'pop_success' =&gt; [ 'mailbody' =&gt; 'hello,\\n\\nyour mail account {email}\\nwas set successfully.\\n\\nthis automatically created\\ne-mail, please answer!\\n\\nyours sincerely, administrator', 'subject' =&gt; 'mail account set successfully', ], 'createcustomer' =&gt; [ 'mailbody' =&gt; 'hello {salutation},\\n\\nhere account information:\\n\\nusername: {username}\\npassword: {password}\\n\\nthank you,\\nyour administrator', 'subject' =&gt; 'account information', ], 'pop_success_alternative' =&gt; [ 'mailbody' =&gt; 'hello {salutation},\\n\\nyour mail account {email}\\nwas set successfully.\\nyour password {password}.\\n\\nthis automatically created\\ne-mail, please answer!\\n\\nyours sincerely, administrator', 'subject' =&gt; 'mail account set successfully', ], 'password_reset' =&gt; [ 'subject' =&gt; 'password reset', 'mailbody' =&gt; 'hello {salutation},\\n\\nhere link setting new password. link valid next 24 hours.\\n\\n{link}\\n\\nthank you,\\nyour administrator', ], 'new_database_by_customer' =&gt; [ 'subject' =&gt; '[froxlor] new database created', 'mailbody' =&gt; 'hello {cust_name}, added new database. entered information: databasename: {db_name} password: {db_pass} description: {db_desc} db-hostname: {db_srv} phpmyadmin: {pma_uri} sincerely, administrator', ], 'new_ftpaccount_by_customer' =&gt; [ 'subject' =&gt; 'new ftp-user created', 'mailbody' =&gt; 'hello {cust_name}, added new ftp-user. entered information: username: {usr_name} password: {usr_pass} path: {usr_path} sincerely, administrator', ], 'trafficmaxpercent' =&gt; [ 'mailbody' =&gt; 'dear {salutation},\\n\\nyou used {trafficused} available {traffic} traffic.\\nthis {max_percent}%%.\\n\\nyours sincerely, administrator', 'subject' =&gt; 'reaching traffic limit', ], 'diskmaxpercent' =&gt; [ 'mailbody' =&gt; 'dear {salutation},\\n\\nyou used {diskused} available {diskavailable} diskspace.\\nthis {max_percent}%%.\\n\\nyours sincerely, administrator', 'subject' =&gt; 'reaching diskspace limit', ], '2fa' =&gt; [ 'mailbody' =&gt; 'hello,\\n\\nyour 2fa login-code is: {code}.\\n\\nthis automatically created\\ne-mail, please answer!\\n\\nyours sincerely, administrator', 'subject' =&gt; 'froxlor - 2fa code', ], ], 'menue' =&gt; [ 'main' =&gt; [ 'main' =&gt; 'main', 'changepassword' =&gt; 'change password', 'changelanguage' =&gt; 'change language', 'username' =&gt; 'logged as: ', 'changetheme' =&gt; 'change theme', 'apihelp' =&gt; 'api help', 'apikeys' =&gt; 'api keys', ], 'email' =&gt; [ 'email' =&gt; 'email', 'emails' =&gt; 'addresses', 'webmail' =&gt; 'webmail', 'emailsoverview' =&gt; 'email domains overview', ], 'mysql' =&gt; [ 'mysql' =&gt; 'mysql', 'databases' =&gt; 'databases', 'phpmyadmin' =&gt; 'phpmyadmin', ], 'domains' =&gt; [ 'domains' =&gt; 'domains', 'settings' =&gt; 'domains overview', ], 'ftp' =&gt; [ 'ftp' =&gt; 'ftp', 'accounts' =&gt; 'accounts', 'webftp' =&gt; 'webftp', ], 'extras' =&gt; [ 'extras' =&gt; 'extras', 'directoryprotection' =&gt; 'directory protection', 'pathoptions' =&gt; 'path options', 'export' =&gt; 'data export', ], 'traffic' =&gt; [ 'traffic' =&gt; 'traffic', 'current' =&gt; 'current month', 'overview' =&gt; 'total traffic', ], 'phpsettings' =&gt; [ 'maintitle' =&gt; 'php configurations', 'fpmdaemons' =&gt; 'php-fpm versions', ], 'logger' =&gt; [ 'logger' =&gt; 'system log', ], ], 'message' =&gt; [ 'norecipients' =&gt; 'no e-mail sent recipients database', 'success' =&gt; 'successfully sent message %s recipients', ], 'mysql' =&gt; [ 'databasename' =&gt; 'user/database name', 'databasedescription' =&gt; 'database description', 'database_create' =&gt; 'create database', 'description' =&gt; 'here create change mysql-databases.&lt;br /&gt;the changes made instantly database used immediately.&lt;br /&gt;at menu left side find tool phpmyadmin easily administer database.&lt;br /&gt;&lt;br /&gt;to use databases php-scripts use following settings: (the data &lt;i&gt;italics&lt;/i&gt; changed equivalents typed in!)&lt;br /&gt;hostname: &lt;b&gt;&lt;sql_host&gt;&lt;/b&gt;&lt;br /&gt;username: &lt;b&gt;&lt;i&gt;databasename&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;password: &lt;b&gt;&lt;i&gt;the password you\'ve chosen&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;database: &lt;b&gt;&lt;i&gt;databasename&lt;/i&gt;&lt;/b&gt;', 'mysql_server' =&gt; 'mysql-server', 'database_edit' =&gt; 'edit database', 'size' =&gt; 'size', 'privileged_user' =&gt; 'privileged database user', 'privileged_passwd' =&gt; 'password privileged user', 'unprivileged_passwd' =&gt; 'password unprivileged user', 'mysql_ssl_ca_file' =&gt; 'ssl server certificate', 'mysql_ssl_verify_server_certificate' =&gt; 'verify ssl server certificate', 'globaluserinfo' =&gt; 'to access databases, additionally use froxlor login (user: %s) automatically access databases.&lt;br /&gt;it recommended &lt;b&gt;not&lt;/b&gt; use applications, administration (e.g. via phpmyadmin).', 'edit_global_user' =&gt; 'edit admin user', ], 'opcacheinfo' =&gt; [ 'generaltitle' =&gt; 'general information', 'resetcache' =&gt; 'reset opcache', 'version' =&gt; 'opcache version', 'phpversion' =&gt; 'php version', 'runtimeconf' =&gt; 'runtime configuration', 'start' =&gt; 'start time', 'lastreset' =&gt; 'last restart', 'oomrestarts' =&gt; 'oom restart count', 'hashrestarts' =&gt; 'hash restart count', 'manualrestarts' =&gt; 'manual restart count', 'hitsc' =&gt; 'hits count', 'missc' =&gt; 'miss count', 'blmissc' =&gt; 'blacklist miss count', 'status' =&gt; 'status', 'never' =&gt; 'never', 'enabled' =&gt; 'opcache enabled', 'cachefull' =&gt; 'cache full', 'restartpending' =&gt; 'pending restart', 'restartinprogress' =&gt; 'restart progress', 'cachedscripts' =&gt; 'cached scripts count', 'memusage' =&gt; 'memory usage', 'totalmem' =&gt; 'total memory', 'usedmem' =&gt; 'used memory', 'freemem' =&gt; 'free memory', 'wastedmem' =&gt; 'wasted memory', 'maxkey' =&gt; 'maximum keys', 'usedkey' =&gt; 'used keys', 'wastedkey' =&gt; 'wasted keys', 'strinterning' =&gt; 'string interning', 'strcount' =&gt; 'string count', 'keystat' =&gt; 'cached keys statistic', 'used' =&gt; 'used', 'free' =&gt; 'free', 'blacklist' =&gt; 'blacklist', 'novalue' =&gt; '&lt;i&gt;no value&lt;/i&gt;', 'true' =&gt; '&lt;i&gt;true&lt;/i&gt;', 'false' =&gt; '&lt;i&gt;false&lt;/i&gt;', 'funcsavail' =&gt; 'available functions', ], 'panel' =&gt; [ 'edit' =&gt; 'edit', 'delete' =&gt; 'delete', 'create' =&gt; 'create', 'save' =&gt; 'save', 'yes' =&gt; 'yes', 'no' =&gt; 'no', 'emptyfornochanges' =&gt; 'empty changes', 'emptyfordefault' =&gt; 'empty defaults', 'path' =&gt; 'path', 'toggle' =&gt; 'toggle', 'next' =&gt; 'next', 'dirsmissing' =&gt; 'can find read directory!', 'unlimited' =&gt; '', 'urloverridespath' =&gt; 'url (overrides path)', 'pathorurl' =&gt; 'path url', 'ascending' =&gt; 'ascending', 'descending' =&gt; 'descending', 'search' =&gt; 'search', 'used' =&gt; 'used', 'translator' =&gt; 'translator', 'reset' =&gt; 'discard changes', 'pathdescription' =&gt; 'if directory doesn\'t exist, created automatically.', 'pathdescriptionex' =&gt; '&lt;br /&gt;&lt;br /&gt;&lt;span class="text-danger"&gt;please note:&lt;/span&gt; path &lt;code&gt;/&lt;/code&gt; allowed due administrative settings, automatically set &lt;code&gt;/chosen.subdomain.tld/&lt;/code&gt; set another directory.', 'pathdescriptionsubdomain' =&gt; 'if directory doesn\'t exist, created automatically.&lt;br /&gt;&lt;br /&gt;if want redirect another domain entry start http:// https://.&lt;br /&gt;&lt;br /&gt;if url ends / considered folder, not, treated file.', 'back' =&gt; 'back', 'reseller' =&gt; 'reseller', 'admin' =&gt; 'admin', 'customer' =&gt; 'customer/s', 'send' =&gt; 'send', 'nosslipsavailable' =&gt; 'there currently ssl ip/port combinations server', 'backtooverview' =&gt; 'back overview', 'dateformat' =&gt; 'yyyy-mm-dd', 'dateformat_function' =&gt; 'y-m-d', 'timeformat_function' =&gt; 'h:i:s', 'default' =&gt; 'default', 'never' =&gt; 'never', 'active' =&gt; 'active', 'please_choose' =&gt; 'please choose', 'allow_modifications' =&gt; 'allow modifications', 'megabyte' =&gt; 'megabyte', 'not_supported' =&gt; 'not supported in: ', 'view' =&gt; 'view', 'toomanydirs' =&gt; 'too many subdirectories. falling back manual path-select.', 'abort' =&gt; 'abort', 'not_activated' =&gt; 'not activated', 'off' =&gt; 'off', 'options' =&gt; 'options', 'neverloggedin' =&gt; 'no login yet', 'descriptionerrordocument' =&gt; 'can url, path file string wrapped around " "&lt;br /&gt;leave empty use server default value.', 'unlock' =&gt; 'unlock', 'theme' =&gt; 'theme', 'variable' =&gt; 'variable', 'description' =&gt; 'description', 'cancel' =&gt; 'cancel', 'ssleditor' =&gt; 'ssl settings domain', 'ssleditor_infoshared' =&gt; 'currently using certificate parentdomain', 'ssleditor_infoglobal' =&gt; 'currently using global certificate', 'dashboard' =&gt; 'dashboard', 'assigned' =&gt; 'assigned', 'available' =&gt; 'available', 'news' =&gt; 'news', 'newsfeed_disabled' =&gt; 'the newsfeed disabled. click edit icon go settings.', 'ftpdesc' =&gt; 'ftp description', 'letsencrypt' =&gt; 'using let\'s encrypt', 'set' =&gt; 'apply', 'shell' =&gt; 'shell', 'exportpath' =&gt; [ 'title' =&gt; 'destination path exported data', 'description' =&gt; 'this path export-archive stored. web-data included, files homedir stored excluding folder specified here.', ], 'export_pgp_public_key' =&gt; [ 'title' =&gt; 'public pgp key encryption', 'description' =&gt; 'this public pgp key used encrypt export. leave field empty, export encrypted.', ], 'pgp_public_key' =&gt; 'public pgp key', 'none_value' =&gt; 'none', 'viewlogs' =&gt; 'view logfiles', 'not_configured' =&gt; 'system configured yet. click go configurations.', 'ihave_configured' =&gt; 'i configured services', 'system_is_configured' =&gt; '&lt;i class="fa-solid fa-circle-exclamation me-1"&gt;&lt;/i&gt;system already set configured', 'settings_before_configuration' =&gt; 'please sure adjusted settings prior configuring services here', 'image_field_delete' =&gt; 'delete existing current image', 'usage_statistics' =&gt; 'resource usage', 'security_question' =&gt; 'security question', 'listing_empty' =&gt; 'no entries found', 'unspecified' =&gt; 'unspecified', 'settingsmode' =&gt; 'mode', 'settingsmodebasic' =&gt; 'basic', 'settingsmodeadvanced' =&gt; 'advanced', 'settingsmodetoggle' =&gt; 'click toggle mode', 'modalclose' =&gt; 'close', 'managetablecolumnsmodal' =&gt; [ 'title' =&gt; 'manage table columns', 'description' =&gt; 'here customize visible columns', ], 'mandatoryfield' =&gt; 'field mandatory', 'select_all' =&gt; 'select all', 'unselect_all' =&gt; 'unselect all', 'searchtablecolumnsmodal' =&gt; [ 'title' =&gt; 'search fields', 'description' =&gt; 'select field want search in' ], 'upload_import' =&gt; 'upload import', 'profile' =&gt; 'my profile', 'use_checkbox_for_unlimited' =&gt; 'the value "0" deactivates resource. checkbox right allows "unlimited" usage.', 'use_checkbox_to_disable' =&gt; 'to disable, activate checkbox right input field', ], 'phpfpm' =&gt; [ 'vhost_httpuser' =&gt; 'local user use php-fpm (froxlor vhost)', 'vhost_httpgroup' =&gt; 'local group use php-fpm (froxlor vhost)', 'ownvhost' =&gt; [ 'title' =&gt; 'enable php-fpm froxlor vhost', 'description' =&gt; 'if enabled, froxlor also running local user', ], 'use_mod_proxy' =&gt; [ 'title' =&gt; 'use mod_proxy / mod_proxy_fcgi', 'description' =&gt; '&lt;strong class="text-danger"&gt;must enabled using debian 9.x (stretch) newer&lt;/strong&gt;. activate use php-fpm via mod_proxy_fcgi. requires least apache-2.4.9', ], 'ini_flags' =&gt; 'enter possible &lt;strong&gt;php_flag&lt;/strong&gt;s php.ini. one entry per line', 'ini_values' =&gt; 'enter possible &lt;strong&gt;php_value&lt;/strong&gt;s php.ini. one entry per line', 'ini_admin_flags' =&gt; 'enter possible &lt;strong&gt;php_admin_flag&lt;/strong&gt;s php.ini. one entry per line', 'ini_admin_values' =&gt; 'enter possible &lt;strong&gt;php_admin_value&lt;/strong&gt;s php.ini. one entry per line', ], 'privacy' =&gt; 'privacy policy', 'pwdreminder' =&gt; [ 'success' =&gt; 'password reset successfully requested. please follow instructions email received.', 'notallowed' =&gt; 'unknown user password reset disabled', 'changed' =&gt; 'your password updated successfully. login new password.', 'wrongcode' =&gt; 'sorry, activation-code exist already expired.', 'choosenew' =&gt; 'set new password', ], 'question' =&gt; [ 'question' =&gt; 'security question', 'admin_customer_reallydelete' =&gt; 'do really want delete customer %s? cannot undone!', 'admin_domain_reallydelete' =&gt; 'do really want delete domain %s?&lt;br&gt;&lt;span class="text-danger"&gt;&lt;strong&gt;note:&lt;/strong&gt; subdomains, ftp-accounts email-addresses/accounts connected domain removed!&lt;/span&gt;', 'admin_domain_reallydisablesecuritysetting' =&gt; 'do really want disable security setting openbasedir?', 'admin_admin_reallydelete' =&gt; 'do really want delete admin %s? every customer domain reassigned account.', 'admin_template_reallydelete' =&gt; 'do really want delete template \'%s\'?', 'domains_reallydelete' =&gt; 'do really want delete domain %s?', 'email_reallydelete' =&gt; 'do really want delete email-address %s?', 'email_reallydelete_account' =&gt; 'do really want delete email-account %s?', 'email_reallydelete_forwarder' =&gt; 'do really want delete forwarder %s?', 'extras_reallydelete' =&gt; 'do really want delete directory protection %s?', 'extras_reallydelete_pathoptions' =&gt; 'do really want delete path options %s?', 'extras_reallydelete_export' =&gt; 'do really want abort planned export job?', 'ftp_reallydelete' =&gt; 'do really want delete ftp-account %s?', 'mysql_reallydelete' =&gt; 'do really want delete database %s? cannot undone!', 'admin_configs_reallyrebuild' =&gt; 'do really want rebuild config files?', 'admin_customer_alsoremovefiles' =&gt; 'remove user files too?', 'admin_customer_alsoremovemail' =&gt; 'completely remove email data filesystem?', 'admin_customer_alsoremoveftphomedir' =&gt; 'also remove ftp-user homedir?', 'admin_ip_reallydelete' =&gt; 'do really want delete ip address %s?', 'admin_domain_reallydocrootoutofcustomerroot' =&gt; 'are sure, want document root domain, within customer root customer?', 'admin_counters_reallyupdate' =&gt; 'do really want recalculate resource usage?', 'admin_cleartextmailpws_reallywipe' =&gt; 'do really want wipe unencrypted mail account passwords table mail_users? cannot reverted! setting store email passwords unencrypted also set off', 'logger_reallytruncate' =&gt; 'do really want truncate table "%s"?', 'admin_quotas_reallywipe' =&gt; 'do really want wipe quotas table mail_users? cannot reverted!', 'admin_quotas_reallyenforce' =&gt; 'do really want enforce default quota users? cannot reverted!', 'phpsetting_reallydelete' =&gt; 'do really want delete settings? domains use settings currently changed default config.', 'fpmsetting_reallydelete' =&gt; 'do really want delete php-fpm settings? php configurations use settings currently changed default config.', 'customer_reallyunlock' =&gt; 'do really want unlock customer %s?', 'admin_integritycheck_reallyfix' =&gt; 'do really want try fixing database integrity problems automatically?', 'plan_reallydelete' =&gt; 'do really want delete hosting plan %s?', 'apikey_reallydelete' =&gt; 'do really want delete api-key?', 'apikey_reallyadd' =&gt; 'do really want create new api-key?', 'dnsentry_reallydelete' =&gt; 'do really want delete zone entry?', 'certificate_reallydelete' =&gt; 'do really want delete certificate?', 'cache_reallydelete' =&gt; 'do really want clear cache?', 'please_enter_otp' =&gt; 'please enter 2fa code', 'admin_mysqlserver_reallydelete' =&gt; 'do really want delete mysql-server?', ], 'redirect_desc' =&gt; [ 'rc_default' =&gt; 'default', 'rc_movedperm' =&gt; 'moved permanently', 'rc_found' =&gt; 'found', 'rc_seeother' =&gt; 'see other', 'rc_tempred' =&gt; 'temporary redirect', ], 'serversettings' =&gt; [ 'session_timeout' =&gt; [ 'title' =&gt; 'session timeout', 'description' =&gt; 'how long user inactive session gets invalid (seconds)?', ], 'accountprefix' =&gt; [ 'title' =&gt; 'customer prefix', 'description' =&gt; 'which prefix customer accounts have?', ], 'mysqlprefix' =&gt; [ 'title' =&gt; 'sql prefix', 'description' =&gt; 'which prefix mysql accounts have?&lt;/br&gt;use "random" value get 3-digit random prefix&lt;/br&gt;use "dbname" value, database name field used together customer name prefix.', ], 'ftpprefix' =&gt; [ 'title' =&gt; 'ftp prefix', 'description' =&gt; 'which prefix ftp accounts have?&lt;br/&gt;&lt;b&gt;if change also change quota sql query ftp server config file case use it!&lt;/b&gt; ', ], 'documentroot_prefix' =&gt; [ 'title' =&gt; 'home directory', 'description' =&gt; 'where home directories stored?', ], 'logfiles_directory' =&gt; [ 'title' =&gt; 'logfiles directory', 'description' =&gt; 'where log files stored?', ], 'logfiles_script' =&gt; [ 'title' =&gt; 'custom script pipe log-files to', 'description' =&gt; 'you specify script use placeholders &lt;strong&gt;{logfile}, {domain} {customer}&lt;/strong&gt; needed. case want use need activate &lt;strong&gt;pipe webserver logfiles&lt;/strong&gt; option too. prefixed pipe-character needed.', ], 'logfiles_format' =&gt; [ 'title' =&gt; 'access-log format', 'description' =&gt; 'enter custom log-format according webservers specifications, leave empty default. depending format string must quoted.&lt;br/&gt;if used nginx, look like &lt;i&gt;log_format frx_custom {configured_value}&lt;/i&gt;.&lt;br/&gt;if used apache, look like &lt;i&gt;logformat {configured_value} frx_custom&lt;/i&gt;.&lt;br/&gt;&lt;strong&gt;attention&lt;/strong&gt;: code won\'t checked errors. contains errors, webserver might start again!', ], 'logfiles_type' =&gt; [ 'title' =&gt; 'access-log type', 'description' =&gt; 'choose &lt;strong&gt;combined&lt;/strong&gt; &lt;strong&gt;vhost_combined&lt;/strong&gt; here.', ], 'logfiles_piped' =&gt; [ 'title' =&gt; 'pipe webserver logfiles specified script (see above)', 'description' =&gt; 'when using custom script logfiles need activate order executed', ], 'ipaddress' =&gt; [ 'title' =&gt; 'ip-address', 'description' =&gt; 'what\'s main ip-address server?', ], 'hostname' =&gt; [ 'title' =&gt; 'hostname', 'description' =&gt; 'what\'s hostname server?', ], 'apachereload_command' =&gt; [ 'title' =&gt; 'webserver reload command', 'description' =&gt; 'what\'s webserver command reload configfiles?', ], 'bindenable' =&gt; [ 'title' =&gt; 'enable nameserver', 'description' =&gt; 'here nameserver enabled disabled globally.', ], 'bindconf_directory' =&gt; [ 'title' =&gt; 'dns server config directory', 'description' =&gt; 'where dns-server config files saved?', ], 'bindreload_command' =&gt; [ 'title' =&gt; 'dns server reload command', 'description' =&gt; 'what\'s command reload dns server daemon?', ], 'vmail_uid' =&gt; [ 'title' =&gt; 'mails-uid', 'description' =&gt; 'which userid mails have?', ], 'vmail_gid' =&gt; [ 'title' =&gt; 'mails-gid', 'description' =&gt; 'which groupid mails have?', ], 'vmail_homedir' =&gt; [ 'title' =&gt; 'mails-homedir', 'description' =&gt; 'where mails stored?', ], 'adminmail' =&gt; [ 'title' =&gt; 'sender', 'description' =&gt; 'what\'s sender address emails sent panel?', ], 'phpmyadmin_url' =&gt; [ 'title' =&gt; 'phpmyadmin url', 'description' =&gt; 'what\'s url phpmyadmin? (has start http(s)://)', ], 'webmail_url' =&gt; [ 'title' =&gt; 'webmail url', 'description' =&gt; 'what\'s url webmail? (has start http(s)://)', ], 'webftp_url' =&gt; [ 'title' =&gt; 'webftp url', 'description' =&gt; 'what\'s url webftp? (has start http(s)://)', ], 'language' =&gt; [ 'description' =&gt; 'what\'s standard server language?', ], 'maxloginattempts' =&gt; [ 'title' =&gt; 'max login attempts', 'description' =&gt; 'maximum login attempts account gets disabled.', ], 'deactivatetime' =&gt; [ 'title' =&gt; 'deactivation time', 'description' =&gt; 'time (sec.) account gets disabled many login tries.', ], 'pathedit' =&gt; [ 'title' =&gt; 'type path input', 'description' =&gt; 'should path selected dropdown menu input field?', ], 'nameservers' =&gt; [ 'title' =&gt; 'nameservers', 'description' =&gt; 'a comma separated list containing hostnames nameservers. first one primary one.', ], 'mxservers' =&gt; [ 'title' =&gt; 'mx servers', 'description' =&gt; 'a comma separated list containing pair number hostname separated whitespace (e.g. \'10 mx.example.com\') containing mx servers.', ], 'paging' =&gt; [ 'title' =&gt; 'entries per page', 'description' =&gt; 'how many entries shall shown one page? (0 = disable paging)', ], 'defaultip' =&gt; [ 'title' =&gt; 'default ip/port', 'description' =&gt; 'select ip-addresses want use default new domains', ], 'defaultsslip' =&gt; [ 'title' =&gt; 'default ssl ip/port', 'description' =&gt; 'select ssl-enabled ip-addresses want use default new domains', ], 'phpappendopenbasedir' =&gt; [ 'title' =&gt; 'paths append openbasedir', 'description' =&gt; 'these paths (separated colons) added openbasedir-statement every vhost-container.', ], 'natsorting' =&gt; [ 'title' =&gt; 'use natural human sorting list view', 'description' =&gt; 'sorts lists web1 -&gt; web2 -&gt; web11 instead web1 -&gt; web11 -&gt; web2.', ], 'deactivateddocroot' =&gt; [ 'title' =&gt; 'docroot deactivated users', 'description' =&gt; 'when user deactivated path used docroot. leave empty creating vhost all.', ], 'mailpwcleartext' =&gt; [ 'title' =&gt; 'also save passwords mail accounts unencrypted database', 'description' =&gt; 'if set yes, passwords also saved unencrypted (clear text, plain readable everyone database access) mail_users-table. activate intend use sasl!', ], 'ftpdomain' =&gt; [ 'title' =&gt; 'ftp accounts @domain', 'description' =&gt; 'customers create ftp accounts user@customerdomain?', ], 'mod_fcgid' =&gt; [ 'title' =&gt; 'enable fcgid', 'description' =&gt; 'use run php corresponding user account.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;this needs special webserver configuration apache, see &lt;a target="_blank" href="https://docs.froxlor.org/latest/admin-guide/configuration/fcgid/"&gt;fcgid - handbook&lt;/a&gt;&lt;/b&gt;', 'configdir' =&gt; [ 'title' =&gt; 'configuration directory', 'description' =&gt; 'where fcgid-configuration files stored? don\'t use self compiled suexec binary, normal situation, path must /var/www/&lt;br /&gt;&lt;br /&gt;&lt;div class="text-danger"&gt;note: folder\'s content gets deleted regularly avoid storing data manually.&lt;/div&gt;', ], 'tmpdir' =&gt; [ 'title' =&gt; 'temp directory', 'description' =&gt; 'where temp directories stored', ], 'starter' =&gt; [ 'title' =&gt; 'processes per domain', 'description' =&gt; 'how many processes started/allowed per domain? value 0 recommended cause php manage amount processes efficiently.', ], 'wrapper' =&gt; [ 'title' =&gt; 'wrapper vhosts', 'description' =&gt; 'how wrapper included vhosts', ], 'peardir' =&gt; [ 'title' =&gt; 'global pear directories', 'description' =&gt; 'which global pear directories replaced every php.ini config? different directories must separated colon.', ], 'maxrequests' =&gt; [ 'title' =&gt; 'maximum requests per domain', 'description' =&gt; 'how many requests allowed per domain?', ], 'defaultini' =&gt; 'default php configuration new domains', 'defaultini_ownvhost' =&gt; 'default php configuration froxlor-vhost', 'idle_timeout' =&gt; [ 'title' =&gt; 'idle timeout', 'description' =&gt; 'timeout setting mod fastcgi.', ], ], 'sendalternativemail' =&gt; [ 'title' =&gt; 'use alternative email-address', 'description' =&gt; 'send password-email different address email-account-creation', ], 'apacheconf_vhost' =&gt; [ 'title' =&gt; 'webserver vhost configuration file/dirname', 'description' =&gt; 'where vhost configuration stored? could either specify file (all vhosts one file) directory (each vhost file) here.', ], 'apacheconf_diroptions' =&gt; [ 'title' =&gt; 'webserver diroptions configuration file/dirname', 'description' =&gt; 'where diroptions configuration stored? could either specify file (all diroptions one file) directory (each diroption file) here.', ], 'apacheconf_htpasswddir' =&gt; [ 'title' =&gt; 'webserver htpasswd dirname', 'description' =&gt; 'where htpasswd files directory protection stored?', ], 'mysql_access_host' =&gt; [ 'title' =&gt; 'mysql-access-hosts', 'description' =&gt; 'a comma separated list hosts users allowed connect mysql-server. allow subnet netmask cidr syntax valid.', ], 'webalizer_quiet' =&gt; [ 'title' =&gt; 'webalizer output', 'description' =&gt; 'verbosity webalizer-program', ], 'logger' =&gt; [ 'enable' =&gt; 'logging enabled/disabled', 'severity' =&gt; 'logging level', 'types' =&gt; [ 'title' =&gt; 'log-type(s)', 'description' =&gt; 'specify logtypes. select multiple types, hold ctrl selecting.&lt;br /&gt;available logtypes are: syslog, file, mysql', ], 'logfile' =&gt; [ 'title' =&gt; 'filename log', 'description' =&gt; 'only used log-type includes "file". file created froxlor/logs/. folder protected public access.', ], 'logcron' =&gt; 'log cronjobs', 'logcronoption' =&gt; [ 'never' =&gt; 'never', 'once' =&gt; 'once', 'always' =&gt; 'always', ], ], 'ssl' =&gt; [ 'use_ssl' =&gt; [ 'title' =&gt; 'enable ssl usage', 'description' =&gt; 'check want use ssl webserver', ], 'ssl_cert_file' =&gt; [ 'title' =&gt; 'path ssl certificate', 'description' =&gt; 'specify path including filename .crt .pem file (main certificate)', ], 'openssl_cnf' =&gt; 'defaults creating cert file', 'ssl_key_file' =&gt; [ 'title' =&gt; 'path ssl keyfile', 'description' =&gt; 'specify path including filename private-key file (.key mostly)', ], 'ssl_ca_file' =&gt; [ 'title' =&gt; 'path ssl ca certificate (optional)', 'description' =&gt; 'client authentication, set know is.', ], 'ssl_cipher_list' =&gt; [ 'title' =&gt; 'configure allowed ssl ciphers', 'description' =&gt; 'this list ciphers want (or don\'t want) use talking ssl. list ciphers include/exclude them, see sections "cipher list format" "cipher strings" &lt;a href="https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html"&gt;the man-page ciphers&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;default value is:&lt;/b&gt;&lt;pre&gt;ecdh+aesgcm:ecdh+aes256:!anull:!md5:!dss:!dh:!aes128&lt;/pre&gt;', ], 'apache24_ocsp_cache_path' =&gt; [ 'title' =&gt; 'apache 2.4: path ocsp stapling cache', 'description' =&gt; 'configures cache used store ocsp responses get included tls handshakes.', ], 'ssl_protocols' =&gt; [ 'title' =&gt; 'configure tls protocol version', 'description' =&gt; 'this list ssl protocols want (or don\'t want) use using ssl. &lt;b&gt;notice:&lt;/b&gt; older browsers may support newest protocol versions.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;default value is:&lt;/b&gt;&lt;pre&gt;tlsv1.2&lt;/pre&gt;', ], 'tlsv13_cipher_list' =&gt; [ 'title' =&gt; 'configure explicit tlsv1.3 ciphers used', 'description' =&gt; 'this list ciphers want (or don\'t want) use talking tlsv1.3. list ciphers include/exclude them, see &lt;a href="https://wiki.openssl.org/index.php/tls1.3"&gt;the docs tlsv1.3&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;default value empty&lt;/b&gt;', ], ], 'default_vhostconf' =&gt; [ 'title' =&gt; 'default vhost-settings', 'description' =&gt; 'the content field included ip/port vhost container directly. use following variables:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (if applicable)&lt;br/&gt; attention: code won\'t checked errors. contains errors, webserver might start again!', ], 'apache_globaldiropt' =&gt; [ 'title' =&gt; 'directory options customer-prefix', 'description' =&gt; 'the content field included 05_froxlor_dirfix_nofcgid.conf apache config. empty, default value used:&lt;br&gt;&lt;br&gt;apache &gt;=2.4&lt;br&gt;&lt;code&gt;require granted&lt;br&gt;allowoverride all&lt;/code&gt;&lt;br&gt;&lt;br&gt;apache &lt;=2.2&lt;br&gt;&lt;code&gt;order allow,deny&lt;br&gt;allow all&lt;/code&gt;', ], 'default_vhostconf_domain' =&gt; [ 'description' =&gt; 'the content field included domain vhost container directly. use following variables:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (if applicable)&lt;br/&gt; attention: code won\'t checked errors. contains errors, webserver might start again!', ], 'decimal_places' =&gt; 'number decimal places traffic/webspace output', 'selfdns' =&gt; [ 'title' =&gt; 'customer domain dns settings', ], 'selfdnscustomer' =&gt; [ 'title' =&gt; 'allow customers edit domain dns settings', ], 'unix_names' =&gt; [ 'title' =&gt; 'use unix compatible usernames', 'description' =&gt; 'allows use &lt;strong&gt;-&lt;/strong&gt; &lt;strong&gt;_&lt;/strong&gt; usernames &lt;strong&gt;no&lt;/strong&gt;', ], 'allow_password_reset' =&gt; [ 'title' =&gt; 'allow password reset customers', 'description' =&gt; 'customers reset password activation link sent e-mail address', ], 'allow_password_reset_admin' =&gt; [ 'title' =&gt; 'allow password reset admins', 'description' =&gt; 'admins/reseller reset password activation link sent e-mail address', ], 'mail_quota' =&gt; [ 'title' =&gt; 'mailbox-quota', 'description' =&gt; 'the default quota new created mailboxes (megabyte).', ], 'mail_quota_enabled' =&gt; [ 'title' =&gt; 'use mailbox-quota customers', 'description' =&gt; 'activate use quotas mailboxes. default &lt;b&gt;no&lt;/b&gt; since requires special setup.', 'removelink' =&gt; 'click wipe quotas mail accounts.', 'enforcelink' =&gt; 'click enforce default quota user mail accounts.', ], 'session_allow_multiple_login' =&gt; [ 'title' =&gt; 'allow multiple login', 'description' =&gt; 'if activated user could login multiple times.', ], 'panel_allow_domain_change_admin' =&gt; [ 'title' =&gt; 'allow moving domains admins', 'description' =&gt; 'if activated change admin domain domainsettings.&lt;br /&gt;&lt;b&gt;attention:&lt;/b&gt; customer isn\'t assigned admin domain, admin see every domain customer!', ], 'panel_allow_domain_change_customer' =&gt; [ 'title' =&gt; 'allow moving domains customers', 'description' =&gt; 'if activated change customer domain domainsettings.&lt;br /&gt;&lt;b&gt;attention:&lt;/b&gt; froxlor changes documentroot new customer\'s default homedir (+ domain-folder activated)', ], 'specialsettingsforsubdomains' =&gt; [ 'description' =&gt; 'if yes custom vhost-settings added subdomains; subdomain-specialsettings removed.', ], 'panel_password_min_length' =&gt; [ 'title' =&gt; 'minimum password length', 'description' =&gt; 'here set minimum length passwords. \'0\' means: minimum length required.', ], 'system_store_index_file_subs' =&gt; [ 'title' =&gt; 'store default index file also new subfolders', 'description' =&gt; 'if enabled, default index-file stored every subdomain-path newly created (not folder already exists!)', ], 'adminmail_return' =&gt; [ 'title' =&gt; 'reply-to address', 'description' =&gt; 'define e-mail address reply-to-address mails sent panel.', ], 'adminmail_defname' =&gt; 'panel e-mail sender name', 'stdsubdomainhost' =&gt; [ 'title' =&gt; 'customer standard subdomain', 'description' =&gt; 'what hostname used create standard subdomains customer. empty, system-hostname used.', ], 'awstats_path' =&gt; 'path awstats \'awstats_buildstaticpages.pl\'', 'awstats_conf' =&gt; 'awstats configuration path', 'defaultttl' =&gt; 'domain ttl bind seconds (default \'604800\' = 1 week)', 'defaultwebsrverrhandler_enabled' =&gt; 'enable default errordocuments customers', 'defaultwebsrverrhandler_err401' =&gt; [ 'title' =&gt; 'file/url error 401', 'description' =&gt; '&lt;div class="text-danger"&gt;not supported in: lighttpd&lt;/div&gt;', ], 'defaultwebsrverrhandler_err403' =&gt; [ 'title' =&gt; 'file/url error 403', 'description' =&gt; '&lt;div class="text-danger"&gt;not supported in: lighttpd&lt;/div&gt;', ], 'defaultwebsrverrhandler_err404' =&gt; 'file/url error 404', 'defaultwebsrverrhandler_err500' =&gt; [ 'title' =&gt; 'file/url error 500', 'description' =&gt; '&lt;div class="text-danger"&gt;not supported in: lighttpd&lt;/div&gt;', ], 'ftpserver' =&gt; [ 'desc' =&gt; 'if pureftpd selected .ftpquota files user quotas created updated daily', ], 'customredirect_enabled' =&gt; [ 'title' =&gt; 'allow customer redirects', 'description' =&gt; 'allow customers choose http-status code redirects used', ], 'customredirect_default' =&gt; [ 'title' =&gt; 'default redirect', 'description' =&gt; 'set default redirect-code used customer set himself', ], 'mail_also_with_mxservers' =&gt; 'create mail-, imap-, pop3- smtp-"a record" also mx-servers set', 'froxlordirectlyviahostname' =&gt; 'access froxlor directly via hostname', 'panel_password_regex' =&gt; [ 'title' =&gt; 'regular expression passwords', 'description' =&gt; 'here set regular expression passwords-complexity.&lt;br /&gt;empty = specific requirement', ], 'perl_path' =&gt; [ 'title' =&gt; 'path perl', 'description' =&gt; 'default /usr/bin/perl', ], 'mod_fcgid_ownvhost' =&gt; [ 'title' =&gt; 'enable fcgid froxlor vhost', 'description' =&gt; 'if enabled, froxlor also running local user', ], 'perl' =&gt; [ 'suexecworkaround' =&gt; [ 'title' =&gt; 'enable suexec workaround', 'description' =&gt; 'enable customer docroots within apache suexec path.&lt;br /&gt;if enabled, froxlor generate symlink customers perl-enabled directory + /cgi-bin/ given path.&lt;br /&gt;note perl work folders subdirectory /cgi-bin/ folder (as without fix!)', ], 'suexeccgipath' =&gt; [ 'title' =&gt; 'path customer perl-enabled directory symlinks', 'description' =&gt; 'you need set suexec-workaround enabled.&lt;br /&gt;attention: sure path within suexec path else workaround useless', ], ], 'awstats_awstatspath' =&gt; 'path awstats \'awstats.pl\'', 'awstats_icons' =&gt; [ 'title' =&gt; 'path awstats icons folder', 'description' =&gt; 'e.g. /usr/share/awstats/htdocs/icon/', ], 'login_domain_login' =&gt; 'allow login domains', 'perl_server' =&gt; [ 'title' =&gt; 'perl server socket location', 'description' =&gt; 'a simple guide found at: &lt;a target="blank" href="https://www.nginx.com/resources/wiki/start/topics/examples/fcgiwrap/"&gt;nginx.com&lt;/a&gt;', ], 'nginx_php_backend' =&gt; [ 'title' =&gt; 'nginx php backend', 'description' =&gt; 'this php process listening requests nginx, unix socket ip:port combination&lt;br /&gt;*not used php-fpm', ], 'phpreload_command' =&gt; [ 'title' =&gt; 'php reload command', 'description' =&gt; 'this used reload php backend used&lt;br /&gt;default: blank&lt;br /&gt;*not used php-fpm', ], 'phpfpm' =&gt; [ 'title' =&gt; 'enable php-fpm', 'description' =&gt; '&lt;b&gt;this needs special webserver configuration see &lt;a target="_blank" href="https://docs.froxlor.org/latest/admin-guide/configuration/php-fpm/"&gt;php-fpm handbook&lt;/a&gt;&lt;/b&gt;', ], 'phpfpm_settings' =&gt; [ 'configdir' =&gt; 'configuration directory php-fpm', 'aliasconfigdir' =&gt; 'configuration alias-directory php-fpm', 'reload' =&gt; 'php-fpm restart command', 'pm' =&gt; 'process manager control (pm)', 'max_children' =&gt; [ 'title' =&gt; 'the number child processes', 'description' =&gt; 'the number child processes created pm set \'static\' maximum number child processes created pm set \'dynamic/ondemand\'&lt;br /&gt;equivalent php_fcgi_children', ], 'start_servers' =&gt; [ 'title' =&gt; 'the number child processes created startup', 'description' =&gt; 'note: used pm set \'dynamic\'', ], 'min_spare_servers' =&gt; [ 'title' =&gt; 'the desired minimum number idle server processes', 'description' =&gt; 'note: used pm set \'dynamic\'&lt;br /&gt;note: mandatory pm set \'dynamic\'', ], 'max_spare_servers' =&gt; [ 'title' =&gt; 'the desired maximum number idle server processes', 'description' =&gt; 'note: used pm set \'dynamic\'&lt;br /&gt;note: mandatory pm set \'dynamic\'', ], 'max_requests' =&gt; [ 'title' =&gt; 'requests per child respawning', 'description' =&gt; 'for endless request processing specify \'0\'. equivalent php_fcgi_max_requests.', ], 'idle_timeout' =&gt; [ 'title' =&gt; 'idle timeout', 'description' =&gt; 'timeout setting php fpm fastcgi.', ], 'ipcdir' =&gt; [ 'title' =&gt; 'fastcgi ipc directory', 'description' =&gt; 'the directory php-fpm sockets stored webserver.&lt;br /&gt;this directory readable webserver', ], 'limit_extensions' =&gt; [ 'title' =&gt; 'allowed extensions', 'description' =&gt; 'limits extensions main script fpm allow parse. prevent configuration mistakes web server side. limit fpm .php extensions prevent malicious users use extensions execute php code. default value: .php', ], 'envpath' =&gt; 'paths add path environment. leave empty path environment variable', 'override_fpmconfig' =&gt; 'override fpm-daemon settings (pm, max_children, etc.)', 'override_fpmconfig_addinfo' =&gt; '&lt;br /&gt;&lt;span class="text-danger"&gt;only used "override fpm-daemon settings" set "yes"&lt;/span&gt;', 'restart_note' =&gt; 'attention: config won\'t checked errors. contains errors, php-fpm might start again!', 'custom_config' =&gt; [ 'title' =&gt; 'custom configuration', 'description' =&gt; 'add custom configuration php-fpm version instance, example &lt;i&gt;pm.status_path = /status&lt;/i&gt; monitoring. variables used here. &lt;strong&gt;attention: config won\'t checked errors. contains errors, php-fpm might start again!&lt;/strong&gt;', ], 'allow_all_customers' =&gt; [ 'title' =&gt; 'assign configuration currently existing customers', 'description' =&gt; 'set "true" want assign configuration currently existing customers used them. setting permanent run multiple times.', ], ], 'report' =&gt; [ 'report' =&gt; 'enable sending reports web- traffic-usage', 'webmax' =&gt; [ 'title' =&gt; 'warning-level percent webspace', 'description' =&gt; 'valid values 0 150. setting value 0 disables report.', ], 'trafficmax' =&gt; [ 'title' =&gt; 'warning-level percent traffic', 'description' =&gt; 'valid values 0 150. setting value 0 disables report.', ], ], 'dropdown' =&gt; 'dropdown', 'manual' =&gt; 'manual', 'default_theme' =&gt; 'default theme', 'validate_domain' =&gt; 'validate domain names', 'diskquota_enabled' =&gt; 'quota activated?', 'diskquota_repquota_path' =&gt; [ 'description' =&gt; 'path repquota', ], 'diskquota_quotatool_path' =&gt; [ 'description' =&gt; 'path quotatool', ], 'diskquota_customer_partition' =&gt; [ 'description' =&gt; 'partition, customer files stored', ], 'vmail_maildirname' =&gt; [ 'title' =&gt; 'maildir name', 'description' =&gt; 'maildir directory user\'s account. normally \'maildir\', implementations \'.maildir\', directly user\'s directory left blank.', ], 'catchall_enabled' =&gt; [ 'title' =&gt; 'use catchall', 'description' =&gt; 'do want provide customers catchall-feature?', ], 'apache_24' =&gt; [ 'title' =&gt; 'use modifications apache 2.4', 'description' =&gt; '&lt;strong class="text-danger"&gt;attention:&lt;/strong&gt; use actually apache version 2.4 higher installed&lt;br /&gt;otherwise webserver able start', ], 'nginx_fastcgiparams' =&gt; [ 'title' =&gt; 'path fastcgi_params file', 'description' =&gt; 'specify path nginx\'s fastcgi_params file including filename', ], 'documentroot_use_default_value' =&gt; [ 'title' =&gt; 'use domain name default value documentroot path', 'description' =&gt; 'if enabled documentroot path empty, default value (sub)domain name.&lt;br /&gt;&lt;br /&gt;examples: &lt;br /&gt;/var/customers/webs/customer_name/example.com/&lt;br /&gt;/var/customers/webs/customer_name/subdomain.example.com/', ], 'panel_phpconfigs_hidesubdomains' =&gt; [ 'title' =&gt; 'hide subdomains php-configuration overview', 'description' =&gt; 'if activated subdomains customers listed php-configurations overview, number subdomains shown.&lt;br /&gt;&lt;br /&gt;note: visible enabled fcgid php-fpm', ], 'panel_phpconfigs_hidestdsubdomain' =&gt; [ 'title' =&gt; 'hide standard-subdomains php-configuration overview', 'description' =&gt; 'if activated standard-subdomains customers displayed php-configurations overview&lt;br /&gt;&lt;br /&gt;note: visible enabled fcgid php-fpm', ], 'passwordcryptfunc' =&gt; [ 'title' =&gt; 'choose password-crypt method used', 'description' =&gt; 'choose password-crypt method used. change setting, new passwords encrypted new method. existing passwords changed.', ], 'systemdefault' =&gt; 'system default', 'panel_allow_theme_change_admin' =&gt; 'allow admins change theme', 'panel_allow_theme_change_customer' =&gt; 'allow customers change theme', 'axfrservers' =&gt; [ 'title' =&gt; 'axfr servers', 'description' =&gt; 'a comma separated list ip addresses allowed transfer (axfr) dns zones.', ], 'powerdns_mode' =&gt; [ 'title' =&gt; 'powerdns operation mode', 'description' =&gt; 'select powedns mode: native replication (default) / master dns replication needed.', ], 'customerssl_directory' =&gt; [ 'title' =&gt; 'webserver customer-ssl certificates-directory', 'description' =&gt; 'where customer-specified ssl-certificates created?&lt;br /&gt;&lt;br /&gt;&lt;div class="text-danger"&gt;note: folder\'s content gets deleted regularly avoid storing data manually.&lt;/div&gt;', ], 'allow_error_report_admin' =&gt; [ 'title' =&gt; 'allow administrators/resellers report database-errors froxlor', 'description' =&gt; 'please note: never send personal (customer-)data us!', ], 'allow_error_report_customer' =&gt; [ 'title' =&gt; 'allow customers report database-errors froxlor', 'description' =&gt; 'please note: never send personal (customer-)data us!', ], 'mailtraffic_enabled' =&gt; [ 'title' =&gt; 'analyse mail traffic', 'description' =&gt; 'enable analysing mailserver logs calculate traffic', ], 'mdaserver' =&gt; [ 'title' =&gt; 'mda type', 'description' =&gt; 'type mail delivery server', ], 'mdalog' =&gt; [ 'title' =&gt; 'mda log', 'description' =&gt; 'logfile mail delivery server', ], 'mtaserver' =&gt; [ 'title' =&gt; 'mta type', 'description' =&gt; 'type mail transfer agent', ], 'mtalog' =&gt; [ 'title' =&gt; 'mta log', 'description' =&gt; 'logfile mail transfer agent', ], 'system_cronconfig' =&gt; [ 'title' =&gt; 'cron configuration file', 'description' =&gt; 'path cron-service configuration-file. file updated regularly automatically froxlor.&lt;br /&gt;note: please &lt;b&gt;be sure&lt;/b&gt; use filename main froxlor cronjob (default: /etc/cron.d/froxlor)!&lt;br&gt;&lt;br&gt;if using &lt;b&gt;freebsd&lt;/b&gt;, please specify &lt;i&gt;/etc/crontab&lt;/i&gt; here!', ], 'system_crondreload' =&gt; [ 'title' =&gt; 'cron-daemon reload command', 'description' =&gt; 'specify command execute order reload systems cron-daemon', ], 'system_croncmdline' =&gt; [ 'title' =&gt; 'cron execution command (php-binary)', 'description' =&gt; 'command execute cronjobs. change know (default: "/usr/bin/nice -n 5 /usr/bin/php -q")!', ], 'system_cron_allowautoupdate' =&gt; [ 'title' =&gt; 'allow automatic database updates', 'description' =&gt; '&lt;div class="text-danger"&gt;&lt;b&gt;attention:&lt;/b&gt;&lt;/div&gt; settings allows cronjob bypass version-check froxlors files database runs database-updates case version-mismatch occurs.&lt;br&gt;&lt;br&gt;&lt;div class="text-danger"&gt;auto-update always set default values new settings changes. might always suite system. please think twice activating option&lt;/div&gt;', ], 'dns_createhostnameentry' =&gt; 'create bind-zone/config system hostname', 'panel_password_alpha_lower' =&gt; [ 'title' =&gt; 'lowercase character', 'description' =&gt; 'password must contain least one lowercase letter (a-z).', ], 'panel_password_alpha_upper' =&gt; [ 'title' =&gt; 'uppercase character', 'description' =&gt; 'password must contain least one uppercase letter (a-z).', ], 'panel_password_numeric' =&gt; [ 'title' =&gt; 'numbers', 'description' =&gt; 'password must contain least one number (0-9).', ], 'panel_password_special_char_required' =&gt; [ 'title' =&gt; 'special character', 'description' =&gt; 'password must contain least one characters defined below.', ], 'panel_password_special_char' =&gt; [ 'title' =&gt; 'special characters list', 'description' =&gt; 'one characters required option set.', ], 'apache_itksupport' =&gt; [ 'title' =&gt; 'use modifications apache itk-mpm', 'description' =&gt; '&lt;strong class="text-danger"&gt;attention:&lt;/strong&gt; use actually apache itk-mpm enabled&lt;br /&gt;otherwise webserver able start', ], 'letsencryptca' =&gt; [ 'title' =&gt; 'acme environment', 'description' =&gt; 'environment used let\'s encrypt / zerossl certificates.', ], 'letsencryptchallengepath' =&gt; [ 'title' =&gt; 'path let\'s encrypt challenges', 'description' =&gt; 'directory let\'s encrypt challenges offered via global alias.', ], 'letsencryptkeysize' =&gt; [ 'title' =&gt; 'key size new let\'s encrypt certificates', 'description' =&gt; 'size key bits new let\'s encrypt certificates.', ], 'letsencryptreuseold' =&gt; [ 'title' =&gt; 're-use let\'s encrypt key', 'description' =&gt; 'if activated, key used every renew, otherwise new key generated every time.', ], 'leenabled' =&gt; [ 'title' =&gt; 'enable let\'s encrypt', 'description' =&gt; 'if activated, customers able let froxlor automatically generate renew let\'s encrypt ssl-certificates domains ssl ip/port.&lt;br /&gt;&lt;br /&gt;please remember need go webserver-configuration enabled feature needs special configuration.', ], 'caa_entry' =&gt; [ 'title' =&gt; 'generate caa dns records', 'description' =&gt; 'automatically generates caa records ssl-enabled domains using let\'s encrypt', ], 'caa_entry_custom' =&gt; [ 'title' =&gt; 'additional caa dns records', 'description' =&gt; 'dns certification authority authorization (caa) internet security policy mechanism allows domain name holders indicate certificate authorities&lt;br&gt;whether authorized issue digital certificates particular domain name. means new "caa" domain name system (dns) resource record.&lt;br&gt;&lt;br&gt;the content field included dns zone directly (each line results caa record).&lt;br&gt;if let\'s encrypt enabled domain, entry always added automatically need added manually:&lt;br&gt;&lt;code&gt;0 issue "letsencrypt.org"&lt;/code&gt; (if domain wildcard domain, issuewild used instead).&lt;br&gt;to enable incident reporting, add &lt;code&gt;iodef&lt;/code&gt; record. example sending report &lt;code&gt;me@example.com&lt;/code&gt; would be:&lt;br&gt;&lt;code&gt;0 iodef "mailto:me@example.com"&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;strong&gt;attention:&lt;/strong&gt; code won\'t checked errors. contains errors, caa records might work!', ], 'exportenabled' =&gt; [ 'title' =&gt; 'enable data export customers', 'description' =&gt; 'if activated, customer able schedule data export jobs (cron-export) generates archive within docroot (subdirectory chosable customer)', ], 'dnseditorenable' =&gt; [ 'title' =&gt; 'enable dns editor', 'description' =&gt; 'allows admins customer manage domain dns entries', ], 'dns_server' =&gt; [ 'title' =&gt; 'dns server daemon', 'description' =&gt; 'remember daemons configured using froxlors configuration templates', ], 'panel_customer_hide_options' =&gt; [ 'title' =&gt; 'hide menu items traffic charts customer panel', 'description' =&gt; 'select items hide customer panel. select multiple options, hold ctrl selecting.', ], 'allow_allow_customer_shell' =&gt; [ 'title' =&gt; 'allow customers enable shell access ftp-users', 'description' =&gt; '&lt;strong class="text-danger"&gt;please note: shell access allows user execute various binaries system. use extrem caution. please activate really know doing!!!&lt;/strong&gt;', ], 'available_shells' =&gt; [ 'title' =&gt; 'list available shells', 'description' =&gt; 'comma separated list shells available customer chose ftp-users.&lt;br&gt;&lt;br&gt;note default shell &lt;strong&gt;/bin/false&lt;/strong&gt; always choice (if enabled), even setting empty. default value ftp-users case', ], 'le_froxlor_enabled' =&gt; [ 'title' =&gt; 'enable let\'s encrypt froxlor vhost', 'description' =&gt; 'if activated, froxlor vhost automatically secured using let\'s encrypt certificate.', ], 'le_froxlor_redirect' =&gt; [ 'title' =&gt; 'enable ssl-redirect froxlor vhost', 'description' =&gt; 'if activated, http requests froxlor redirected corresponding ssl site.', ], 'option_unavailable_websrv' =&gt; '&lt;br&gt;&lt;em class="text-danger"&gt;available for: %s&lt;/em&gt;', 'option_unavailable' =&gt; '&lt;br&gt;&lt;em class="text-danger"&gt;option available due settings.&lt;/em&gt;', 'letsencryptacmeconf' =&gt; [ 'title' =&gt; 'path acme.conf snippet', 'description' =&gt; 'file name config snippet allows web server serve acme challenge.', ], 'mail_use_smtp' =&gt; 'set mailer use smtp', 'mail_smtp_host' =&gt; 'specify smtp server', 'mail_smtp_usetls' =&gt; 'enable tls encryption', 'mail_smtp_auth' =&gt; 'enable smtp authentication', 'mail_smtp_port' =&gt; 'tcp port connect to', 'mail_smtp_user' =&gt; 'smtp username', 'mail_smtp_passwd' =&gt; 'smtp password', 'http2_support' =&gt; [ 'title' =&gt; 'http2 support', 'description' =&gt; 'enable http2 support ssl.&lt;br&gt;&lt;em class="text-danger"&gt;enable webserver supports feature (nginx version 1.9.5+, apache2 version 2.4.17+)&lt;/em&gt;', ], 'nssextrausers' =&gt; [ 'title' =&gt; 'use libnss-extrausers instead libnss-mysql', 'description' =&gt; 'do read users database files. please activate already gone required configuration steps (system -&gt; libnss-extrausers).&lt;br&gt;&lt;strong class="text-danger"&gt;for debian/ubuntu (or compiled libnss-extrausers yourself!)&lt;/strong&gt;', ], 'le_domain_dnscheck' =&gt; [ 'title' =&gt; 'validate dns domains using let\'s encrypt', 'description' =&gt; 'if activated, froxlor validate whether domain requests let\'s encrypt certificate resolves least one system ip addresses.', ], 'le_domain_dnscheck_resolver' =&gt; [ 'title' =&gt; 'use external nameserver dns validation', 'description' =&gt; 'if set, froxlor use dns validate dns domains using let\'s encrypt. empty, system\'s default dns resolver used.', ], 'phpsettingsforsubdomains' =&gt; [ 'description' =&gt; 'if yes chosen php-config updated subdomains', ], 'leapiversion' =&gt; [ 'title' =&gt; 'choose let\'s encrypt acme implementation', 'description' =&gt; 'currently acme v2 implementation let\'s encrypt supported.', ], 'enable_api' =&gt; [ 'title' =&gt; 'enable external api usage', 'description' =&gt; 'in order use froxlor api need activate option. detailed information see &lt;a href="https://docs.froxlor.org/latest/api-guide/" target="_new"&gt;https://docs.froxlor.org/&lt;/a&gt;', ], 'api_customer_default' =&gt; '"allow api access" default value new customers', 'dhparams_file' =&gt; [ 'title' =&gt; 'dhparams file (diffiehellman key exchange)', 'description' =&gt; 'if dhparams.pem file specified included webserver configuration. leave empty disable.&lt;br&gt;example: /etc/ssl/webserver/dhparams.pem&lt;br&gt;&lt;br&gt;if file exist, created automatically following command: &lt;code&gt;openssl dhparam -out /etc/ssl/webserver/dhparams.pem 4096&lt;/code&gt;. recommended create file prior specifying creation takes quite blocks cronjob.', ], 'errorlog_level' =&gt; [ 'title' =&gt; 'error log-level', 'description' =&gt; 'specify error log level. default "warn" apache-users "error" nginx-users.', ], 'letsencryptecc' =&gt; [ 'title' =&gt; 'issue ecc / ecdsa certificate', 'description' =&gt; 'if set valid key-size certificate issued use ecc / ecdsa', ], 'froxloraliases' =&gt; [ 'title' =&gt; 'domain aliases froxlor vhost', 'description' =&gt; 'comma separated list domains add server alias froxlor vhost', ], 'default_sslvhostconf' =&gt; [ 'title' =&gt; 'default ssl vhost-settings', 'description' =&gt; 'the content field included ip/port vhost container directly. use following variables:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (if applicable)&lt;br/&gt; attention: code won\'t checked errors. contains errors, webserver might start again!', ], 'includedefault_sslvhostconf' =&gt; 'include non-ssl vhost-settings ssl-vhost', 'apply_specialsettings_default' =&gt; 'default value "apply specialsettings subdomains (*.example.com)" setting editing domain', 'apply_phpconfigs_default' =&gt; 'default value "apply php-config subdomains" setting editing domain', 'awstats' =&gt; [ 'logformat' =&gt; [ 'title' =&gt; 'logformat setting', 'description' =&gt; 'if use customized logformat webserver, need change awstats logformat too.&lt;br/&gt;default 1. information check documentation &lt;a target="_blank" href="https://awstats.sourceforge.io/docs/awstats_config.html#logformat"&gt;here&lt;/a&gt;.', ], ], 'hide_incompatible_settings' =&gt; 'hide incompatible settings', 'soaemail' =&gt; 'mail address use soa records (defaults sender address panel settings empty)', 'imprint_url' =&gt; [ 'title' =&gt; 'url legal notes / imprint', 'description' =&gt; 'specify url legal notes / imprint site. link visible login screen footer logged in.', ], 'terms_url' =&gt; [ 'title' =&gt; 'url terms use', 'description' =&gt; 'specify url terms use site. link visible login screen footer logged in.', ], 'privacy_url' =&gt; [ 'title' =&gt; 'url privacy policy', 'description' =&gt; 'specify url privacy policy site / imprint site. link visible login screen footer logged in.', ], 'logo_image_header' =&gt; [ 'title' =&gt; 'logo image (header)', 'description' =&gt; 'upload logo image shown header login (recommended height 30px)', ], 'logo_image_login' =&gt; [ 'title' =&gt; 'logo image (login)', 'description' =&gt; 'upload logo image shown login', ], 'logo_overridetheme' =&gt; [ 'title' =&gt; 'overwrites logo defined theme "logo image" (header login, see below)', 'description' =&gt; 'this needs set "true" intend use uploaded logo; alternatively still use theme-based "logo_custom.png" "logo_custom_login.png" possibility.', ], 'logo_overridecustom' =&gt; [ 'title' =&gt; 'overwrite custom logo (logo_custom.png logo_custom_login.png) defined theme "logo image" (header login, see below)', 'description' =&gt; 'set "true" want ignore theme-specific custom logos header login use "logo image"', ], 'createstdsubdom_default' =&gt; [ 'title' =&gt; 'preselected value "create standard subdomain" creating customer', 'description' =&gt; '', ], 'froxlorusergroup' =&gt; [ 'title' =&gt; 'custom system group customer users', 'description' =&gt; 'usage libnss-extrausers (system-settings) required take effect. empty value skips creation removes existing group.', ], 'acmeshpath' =&gt; [ 'title' =&gt; 'path acme.sh', 'description' =&gt; 'set acme.sh installed to, including acme.sh script&lt;br&gt;default &lt;b&gt;/root/.acme.sh/acme.sh&lt;/b&gt;', ], 'update_channel' =&gt; [ 'title' =&gt; 'froxlor update-channel', 'description' =&gt; 'select update channel froxlor. default "stable"', ], 'uc_stable' =&gt; 'stable', 'uc_testing' =&gt; 'testing', 'uc_nightly' =&gt; 'nightly', 'traffictool' =&gt; [ 'toolselect' =&gt; 'traffic analyzer', 'webalizer' =&gt; 'webalizer', 'awstats' =&gt; 'awstats', 'goaccess' =&gt; 'goaccess' ], 'requires_reconfiguration' =&gt; 'changing settings might require reconfiguration following services:&lt;br&gt;&lt;strong&gt;%s&lt;/strong&gt;', 'req_limit_per_interval' =&gt; [ 'title' =&gt; 'number http requests per interval', 'description' =&gt; 'limit number http requests per interval (see below) froxlor, default "60"', ], 'req_limit_interval' =&gt; [ 'title' =&gt; 'rate-limit interval', 'description' =&gt; 'specify time seconds number http requests, default "60"', ], 'option_requires_otp' =&gt; 'this setting requires otp validation', 'panel_menu_collapsed' =&gt; [ 'title' =&gt; 'collapse menu-sections', 'description' =&gt; 'if deactivated, left-side menu sections always expanded.', ], 'le_renew_services' =&gt; [ 'title' =&gt; 'use froxlor let\'s encrypt certificate services', 'description' =&gt; 'if set none (or renew-hook command empty), configuration adjustments regarding ssl made selected services.&lt;br&gt;&lt;br&gt;the reload-command services selected added renew-hook command configuration changes renewed certificates may applied correctly.', ], 'le_renew_hook' =&gt; [ 'title' =&gt; 'let\'s encrypt renew-hook command', 'description' =&gt; 'set command restarts services selected order renewed certificates used correctly service.', ], ], 'spf' =&gt; [ 'use_spf' =&gt; [ 'title' =&gt; 'activate spf domains?', 'description' =&gt; 'requires specific dns entry domain. using nameserver feature, manually manage entries.', ], 'spf_entry' =&gt; 'spf entry domains', ], 'dmarc' =&gt; [ 'use_dmarc' =&gt; [ 'title' =&gt; 'activate dmarc domains?', 'description' =&gt; 'requires specific dns entry domain. using nameserver feature, manually manage entries.', ], 'dmarc_entry' =&gt; 'dmarc entry domains', ], 'ssl_certificates' =&gt; [ 'certificate_for' =&gt; 'certificate for', 'valid_from' =&gt; 'valid from', 'valid_until' =&gt; 'valid until', 'issuer' =&gt; 'issuer', ], 'success' =&gt; [ 'success' =&gt; 'information', 'clickheretocontinue' =&gt; 'click continue', 'settingssaved' =&gt; 'the settings successfully saved.', 'rebuildingconfigs' =&gt; 'successfully inserted tasks rebuild configfiles', 'domain_import_successfully' =&gt; 'successfully imported %s domains.', 'exportscheduled' =&gt; 'your export job scheduled. please wait processed', 'exportaborted' =&gt; 'your scheduled export cancelled', 'dns_record_added' =&gt; 'record added successfully', 'dns_record_deleted' =&gt; 'record deleted successfully', 'testmailsent' =&gt; 'test mail sent successfully', 'settingsimported' =&gt; 'settings imported successfully', 'sent_error_report' =&gt; 'succesfully sent error report. thank contribution.', ], 'tasks' =&gt; [ 'outstanding_tasks' =&gt; 'pending cron-tasks', 'rebuild_vhost' =&gt; 'rebuilding webserver-configuration', 'create_home' =&gt; 'adding new customer %s', 'rebuild_dns' =&gt; 'rebuilding bind-configuration', 'create_ftp' =&gt; 'creating directory new ftp-user', 'delete_customer_files' =&gt; 'deleting customer-files %s', 'noneoutstanding' =&gt; 'there currently outstanding tasks froxlor', 'delete_email_data' =&gt; 'delete customer e-mail data.', 'delete_ftp_data' =&gt; 'delete customer ftp-account data.', 'rebuild_rspamd' =&gt; 'rebuilding antispam-configuration.', 'create_quota' =&gt; 'set quota filesystem', 'rebuild_cron' =&gt; 'rebuilding cron.d-file', 'create_customer_datadump' =&gt; 'data export job customer %s', 'delete_domain_pdns' =&gt; 'delete domain %s powerdns database', 'delete_domain_ssl' =&gt; 'delete ssl files domain %s', 'update_le_services' =&gt; 'updating system services let\'s encrypt', ], 'terms' =&gt; 'terms use', 'traffic' =&gt; [ 'month' =&gt; 'month', 'day' =&gt; 'day', 'months' =&gt; [ 1 =&gt; 'january', 2 =&gt; 'february', 3 =&gt; 'march', 4 =&gt; 'april', 5 =&gt; 'may', 6 =&gt; 'june', 7 =&gt; 'july', 8 =&gt; 'august', 9 =&gt; 'september', 10 =&gt; 'october', 11 =&gt; 'november', 12 =&gt; 'december', 'jan' =&gt; 'jan', 'feb' =&gt; 'feb', 'mar' =&gt; 'mar', 'apr' =&gt; 'apr', 'may' =&gt; 'may', 'jun' =&gt; 'jun', 'jul' =&gt; 'jul', 'aug' =&gt; 'aug', 'sep' =&gt; 'sep', 'oct' =&gt; 'oct', 'nov' =&gt; 'nov', 'dec' =&gt; 'dec', 'total' =&gt; 'total', ], 'mb' =&gt; 'traffic', 'sumtotal' =&gt; 'total traffic', 'sumhttp' =&gt; 'http traffic', 'sumftp' =&gt; 'ftp traffic', 'summail' =&gt; 'mail traffic', 'customer' =&gt; 'customer', 'domain' =&gt; 'domain', 'trafficoverview' =&gt; 'traffic summary', 'bycustomers' =&gt; 'traffic customers', 'details' =&gt; 'details', 'http' =&gt; 'http', 'ftp' =&gt; 'ftp', 'mail' =&gt; 'mail', 'nocustomers' =&gt; 'you need least one customer view traffic reports.', 'top5customers' =&gt; 'top 5 customers', 'nodata' =&gt; 'no data given range found.', 'ranges' =&gt; [ 'last24h' =&gt; 'last 24 hours', 'last7d' =&gt; 'last 7 days', 'last30d' =&gt; 'last 30 days', 'cm' =&gt; 'current month', 'last3m' =&gt; 'last 3 months', 'last6m' =&gt; 'last 6 months', 'last12m' =&gt; 'last 12 months', 'cy' =&gt; 'current year', ], 'byrange' =&gt; 'specified range', ], 'translator' =&gt; '', 'update' =&gt; [ 'updateinprogress_onlyadmincanlogin' =&gt; 'a newer version froxlor installed yet set up.&lt;br /&gt;only administrator log finish update.', 'update' =&gt; 'froxlor update', 'proceed' =&gt; 'proceed', 'update_information' =&gt; [ 'part_a' =&gt; 'the froxlor files updated version &lt;strong&gt;%s&lt;/strong&gt;. installed version &lt;strong&gt;%s&lt;/strong&gt;.', 'part_b' =&gt; '&lt;br /&gt;&lt;br /&gt;customers able log update finished.&lt;br /&gt;&lt;strong&gt;proceed?&lt;/strong&gt;', ], 'noupdatesavail' =&gt; 'you already latest %sversion froxlor installed.', 'description' =&gt; 'running database updates froxlor installation', 'uc_newinfo' =&gt; 'there newer %sversion available: "%s" (your current version is: %s)', 'notify_subject' =&gt; 'new update available', 'dbupdate_required' =&gt; 'froxlor files updated, database update required', ], 'usersettings' =&gt; [ 'custom_notes' =&gt; [ 'title' =&gt; 'custom notes', 'description' =&gt; 'feel free put notes want/need here. show admin/customer overview corresponding user.&lt;br&gt;markdown supported, html removed.', 'show' =&gt; 'show notes dashboard user', ], 'api_allowed' =&gt; [ 'title' =&gt; 'allow api access', 'description' =&gt; 'when enabled settings, user create api keys access froxlor api', 'notice' =&gt; 'api access allowed account.', ], 'gui_access' =&gt; [ 'title' =&gt; 'allow webui login', 'description' =&gt; 'when disabled, user cannot log froxlor web-ui services (web, ftp, mail, databases, api-access, etc.) work normally.', ], ], 'install' =&gt; [ 'slogan' =&gt; 'froxlor server management panel', 'preflight' =&gt; 'system check', 'critical_error' =&gt; 'critical error', 'suggestions' =&gt; 'not required recommended', 'phpinfosuccess' =&gt; 'your system running php %s', 'suggestionsnote' =&gt; 'there critical errors prevent installation, please follow recommendations optimal experience.', 'phpinfowarn' =&gt; 'your system running lower version php %s', 'phpinfoupdate' =&gt; 'update current php version %s %s higher', 'start_installation' =&gt; 'start installation', 'check_again' =&gt; 'reload check again', 'switchmode_advanced' =&gt; 'show advanced options', 'switchmode_basic' =&gt; 'hide advanced options', 'dependency_check' =&gt; [ 'title' =&gt; 'welcome froxlor', 'description' =&gt; 'we check system dependencies ensure required php extensions modules enabled froxlor runs properly.', ], 'database' =&gt; [ 'top' =&gt; 'database', 'title' =&gt; 'create database user', 'description' =&gt; 'froxlor requires database additionally &lt;a href="https://docs.froxlor.org/latest/general/installation/tarball.html#_3-create-privileged-database-user" target="_blank"&gt;a privileged user&lt;/a&gt; able create users databases (grant option). given database unprivileged database-user created process. privileged user must exist.', 'user' =&gt; 'unprivileged database user', 'dbname' =&gt; 'database name', 'force_create' =&gt; 'backup overwrite database exists?', ], 'admin' =&gt; [ 'top' =&gt; 'admin user', 'title' =&gt; 'let\'s create main administrator user.', 'description' =&gt; 'this user granted privileges adjust settings add/update/delete resources like customers, domains, etc.', 'use_admin_email_as_sender' =&gt; 'use email address sender address. unchecked, please specify sender address below.', 'use_autogenerated_email_as_sender' =&gt; 'leave empty default: admin@servername', ], 'system' =&gt; [ 'top' =&gt; 'system setup', 'title' =&gt; 'details server', 'description' =&gt; 'set environment well server relevant data options let froxlor know system. values crucial system configuration operating.', 'ipv4' =&gt; 'primary ipv4 address (if applicable)', 'ipv6' =&gt; 'primary ipv6 address (if applicable)', 'servername' =&gt; 'server name (fqdn, ip-address)', 'phpbackend' =&gt; 'php backend', 'activate_newsfeed' =&gt; 'enable official newsfeed&lt;br&gt;&lt;small&gt;(external source: https://inside.froxlor.org/news/)&lt;/small&gt;', ], 'install' =&gt; [ 'top' =&gt; 'finish setup', 'title' =&gt; 'one last step...', 'description' =&gt; 'the command download, install configure required services system according data given installation process.&lt;br&gt;&lt;br&gt;&lt;span class="text-danger"&gt;be sure run following command &lt;b&gt;root&lt;/b&gt; server\'s shell/terminal &lt;b&gt;be aware&lt;/b&gt; command &lt;b&gt;overwrite&lt;/b&gt; existing configuration used services (backups created)!.&lt;br&gt;if want overwrite configurations, select &lt;i&gt;i manually configure services&lt;/i&gt; bottom page!&lt;/span&gt;', 'runcmd' =&gt; 'run following command finish installation:', 'manual_config' =&gt; 'i manually configure services, take login', 'waitforconfig' =&gt; 'waiting services configured...', ], 'errors' =&gt; [ 'wrong_ownership' =&gt; 'make sure froxlor files owned %s:%s', 'missing_extensions' =&gt; 'the following php extensions required installed', 'suggestedextensions' =&gt; 'the following php extensions could found recommended', 'databaseexists' =&gt; 'database already exist, please set override option rebuild chose another name', 'unabletocreatedb' =&gt; 'test database could created', 'unabletodropdb' =&gt; 'test database could dropped', 'mysqlusernameexists' =&gt; 'the user specified unprivileged user already exist. please use another username delete first.', 'unabletocreateuser' =&gt; 'test user could created', 'unabletodropuser' =&gt; 'test user could dropped', 'unabletoflushprivs' =&gt; 'given privileged user unable flush privileges', 'nov4andnov6ip' =&gt; 'either ipv4- ipv6-address must given', 'servernameneedstobevalid' =&gt; 'given servername seem fqdn hostname', 'websrvuserdoesnotexist' =&gt; 'given webserver-user seem exist system', 'websrvgrpdoesnotexist' =&gt; 'given webserver-group seem exist system', 'notyetconfigured' =&gt; 'it seems services yet configured (successfully). please either run command shown check box later.', 'mandatory_field_not_set' =&gt; 'mandatory field "%s" set!', 'unexpected_database_error' =&gt; 'unexpected database exception occurred. %s', 'sql_import_failed' =&gt; 'failed import sql data!', 'unprivileged_sql_connection_failed' =&gt; 'failed initialize unprivileged sql connection!', 'privileged_sql_connection_failed' =&gt; 'failed initialize privileged sql connection!', 'mysqldump_backup_failed' =&gt; 'cannot create database backup, got error mysqldump.', 'sql_backup_file_missing' =&gt; 'cannot create database backup, backup file exist.', 'backup_binary_missing' =&gt; 'cannot create database backup, make sure installed mysqldump.', 'creating_configfile_failed' =&gt; 'cannot create config files, unable write file.', 'database_already_exiting' =&gt; 'we found database allow override it!' ] ], 'welcome' =&gt; [ 'title' =&gt; 'welcome froxlor!', 'config_note' =&gt; 'in order froxlor able communicate properly backend, configure it.', 'config_now' =&gt; 'configure now' ], ];</file><file name="lng/fr.lng.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @author tim zielosko &lt;tim.zielosko@syscp.de&gt; * @author aldo reset &lt;aldo.reset@placenet.org&gt; * @author romain mariadassou &lt;roms2000@free.fr&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'admin' =&gt; [ 'overview' =&gt; 'sommaire', 'ressourcedetails' =&gt; 'ressources utilises', 'systemdetails' =&gt; 'informations du systme', 'froxlordetails' =&gt; 'informations de froxlor', 'installedversion' =&gt; 'version installe', 'latestversion' =&gt; 'dernire version en date', 'lookfornewversion' =&gt; [ 'clickhere' =&gt; 'vrifier par internet', 'error' =&gt; 'erreur pour vrifier la dernire version', ], 'resources' =&gt; 'ressources', 'customer' =&gt; 'compte', 'customers' =&gt; 'comptes', 'customer_add' =&gt; 'ajouter un compte', 'customer_edit' =&gt; 'modifier un compte', 'domains' =&gt; 'domaines', 'domain_add' =&gt; 'ajouter un domaine', 'domain_edit' =&gt; 'modifier le domaine', 'subdomainforemail' =&gt; 'sous-domaines comme domaine e-mail', 'admin' =&gt; 'administrateur', 'admins' =&gt; 'administrateurs', 'admin_add' =&gt; 'ajouter un administrateur', 'admin_edit' =&gt; 'modifier un administrateur', 'customers_see_all' =&gt; 'peut voir tous les comptes ?', 'change_serversettings' =&gt; 'peut modifier la configuration du serveur ?', 'server' =&gt; 'systme', 'serversettings' =&gt; 'paramtres', 'rebuildconf' =&gt; 'rgnrer la configuration', 'stdsubdomain' =&gt; 'sous-domaine type', 'stdsubdomain_add' =&gt; 'ajouter un sous-domaine type', 'phpenabled' =&gt; 'php activ', 'deactivated' =&gt; 'dsactiver', 'deactivated_user' =&gt; 'dsactiver l\'utilisateur', 'sendpassword' =&gt; 'envoyer le mot de passe', 'ownvhostsettings' =&gt; 'configuration spciale du vhost', 'configfiles' =&gt; [ 'serverconfiguration' =&gt; 'exemple de configuration', 'overview' =&gt; 'aperu', 'wizard' =&gt; 'assistant', 'distribution' =&gt; 'distribution', 'service' =&gt; 'service', 'daemon' =&gt; 'dmon', 'http' =&gt; 'serveur web (http)', 'dns' =&gt; 'serveur de noms (dns)', 'mail' =&gt; 'serveur de mails (imap/pop3)', 'smtp' =&gt; 'serveur de mails (smtp)', 'ftp' =&gt; 'serveur ftp', 'etc' =&gt; 'autres (systme)', 'choosedistribution' =&gt; '-- choisissez une distribution --', 'chooseservice' =&gt; '-- choisissez un service --', 'choosedaemon' =&gt; '-- choisissez un dmon --', 'statistics' =&gt; 'statistiques', ], 'templates' =&gt; [ 'templates' =&gt; 'modles', 'template_add' =&gt; 'ajouter un modle', 'template_edit' =&gt; 'modifier un modle', 'action' =&gt; 'action', 'email' =&gt; 'e-mail', 'subject' =&gt; 'rfrence', 'mailbody' =&gt; 'texte de l\'e-mail', 'createcustomer' =&gt; 'e-mail de bienvenue pour les nouveaux clients', 'pop_success' =&gt; 'e-mail de bienvenue pour les nouveaux accs e-mail', 'template_replace_vars' =&gt; 'les variables qui seront remplaces dans le template :', 'firstname' =&gt; 'sera remplac par le prnom.', 'name' =&gt; 'sera remplac par le nom.', 'username' =&gt; 'sera remplac par le login.', 'password' =&gt; 'sera remplac par le mot de passe du client.', 'email' =&gt; 'sera remplac par l\'accs e-mail.', 'traffic' =&gt; 'sera remplac par le taux de trafic qui attribu l\'utilisateur.', 'trafficused' =&gt; 'sera remplac par le taux de trafic qui consomm par l\'utilisateur.', 'pop_success_alternative' =&gt; 'message de bienvenue envoy l\'adresse e-mail alternative pour les nouveaux comptes e-mails', 'email_password' =&gt; 'remplacer par le mot de passe du compte pop3 / imap.', ], 'ipsandports' =&gt; [ 'ipsandports' =&gt; 'ips et ports', 'add' =&gt; 'ajouter une ip / port', 'edit' =&gt; 'modifier une ip / port', 'create_listen_statement' =&gt; 'dclaration des ports d\'coute', 'create_namevirtualhost_statement' =&gt; 'dclaration des htes virtuels "namevirtualhost"', 'create_vhostcontainer' =&gt; 'dclaration des conteneurs virtuels "vhost"', 'create_vhostcontainer_servername_statement' =&gt; 'dclaration des noms d\'htes "servername" dans les conteneurs virtuels "vhost"', 'enable_ssl' =&gt; 'est-ce un port ssl ?', 'ssl_cert_file' =&gt; 'emplacement du certificat ssl', ], 'memorylimitdisabled' =&gt; 'dsactiv', 'valuemandatory' =&gt; 'cette valeur est obligatoire', 'valuemandatorycompany' =&gt; 'vous devez indiquer au moins l\'une des 3 valeurs suivantes : "nom" ou "prnom" ou "entreprise"', 'serversoftware' =&gt; 'logiciel serveur', 'phpversion' =&gt; 'version de php', 'phpmemorylimit' =&gt; 'limite mmoire de php', 'mysqlserverversion' =&gt; 'version du serveur mysql', 'mysqlclientversion' =&gt; 'version du client mysql', 'webserverinterface' =&gt; 'interface web', 'accountsettings' =&gt; 'paramtres du compte', 'panelsettings' =&gt; 'paramtres du panel', 'systemsettings' =&gt; 'paramtres du systme', 'webserversettings' =&gt; 'paramtres du serveur web', 'mailserversettings' =&gt; 'paramtres du serveur de mail', 'nameserversettings' =&gt; 'paramtres du serveur de noms', 'updatecounters' =&gt; 'recalculer les ressources utilises', 'subcanemaildomain' =&gt; [ 'never' =&gt; 'jamais', 'choosableno' =&gt; 'a choisir, par dfaut : non', 'choosableyes' =&gt; 'a choisir, par dfaut : oui', 'always' =&gt; 'toujours', ], 'webalizersettings' =&gt; 'paramtres pour webalizer', 'webalizer' =&gt; [ 'normal' =&gt; 'normal', 'quiet' =&gt; 'silencieux', 'veryquiet' =&gt; 'aucune sortie', ], 'domain_nocustomeraddingavailable' =&gt; 'il n\'est acutellement pas possible d\'ajouter de domaines. vous devez d\'abord ajouter un client.', 'loggersettings' =&gt; 'paramtres des logs', 'logger' =&gt; [ 'normal' =&gt; 'normal', 'paranoid' =&gt; 'paranoaque', ], 'emaildomain' =&gt; 'domaine e-mail', 'email_only' =&gt; 'seulement des e-mails ?', 'wwwserveralias' =&gt; 'ajouter un "www." l\'alias du serveur "serveralias"', 'subject' =&gt; 'sujet', 'recipient' =&gt; 'destinataire', 'message' =&gt; 'ecrire un message', 'text' =&gt; 'message', 'sslsettings' =&gt; 'paramtres ssl', 'dkimsettings' =&gt; 'paramtres dkim', 'caneditphpsettings' =&gt; 'peut changer les paramtres php du domaine ?', 'allips' =&gt; 'toutes les adresses ip', 'awstatssettings' =&gt; 'paramtres awstats', 'domain_dns_settings' =&gt; 'paramtres dns', 'activated' =&gt; 'activ', 'statisticsettings' =&gt; 'paramtres des statistiques', 'or' =&gt; 'ou', 'sysload' =&gt; 'charge du systme', 'noloadavailable' =&gt; 'non disponible', 'nouptimeavailable' =&gt; 'non disponible', 'nosubject' =&gt; '(aucun sujet)', ], 'changepassword' =&gt; [ 'old_password' =&gt; 'ancien mot de passe', 'new_password' =&gt; 'nouveau mot de passe', 'new_password_confirm' =&gt; 'nouveau mot de passe (confirmation)', 'new_password_ifnotempty' =&gt; 'nouveau mot de passe (veuillez laisser vide pour ne pas changer)', 'also_change_ftp' =&gt; 'changer aussi le mot de passe du compte ftp principal ?', 'also_change_webalizer' =&gt; 'changer aussi le mot de passe des statistiques webalizer ?', ], 'cronjobs' =&gt; [ 'notyetrun' =&gt; 'pas encore lanc', ], 'customer' =&gt; [ 'documentroot' =&gt; 'chemin', 'name' =&gt; 'nom', 'firstname' =&gt; 'prnom', 'company' =&gt; 'entreprise', 'street' =&gt; 'rue', 'zipcode' =&gt; 'code postal', 'city' =&gt; 'ville', 'phone' =&gt; 'tlphone', 'fax' =&gt; 'fax', 'email' =&gt; 'e-mail', 'customernumber' =&gt; 'numro du client', 'diskspace' =&gt; 'espace web (mo)', 'traffic' =&gt; 'trafic (go)', 'mysqls' =&gt; 'base(s) de donnes mysql', 'emails' =&gt; 'adresse(s) e-mail', 'accounts' =&gt; 'accs e-mail', 'forwarders' =&gt; 'transfert(s) e-mail', 'ftps' =&gt; 'accs ftp', 'subdomains' =&gt; 'sous-domaine(s)', 'domains' =&gt; 'domaine(s)', 'email_quota' =&gt; 'quota e-mail', 'email_imap' =&gt; 'e-mail imap', 'email_pop3' =&gt; 'e-mail pop3', 'mail_quota' =&gt; 'quota e-mail', 'title' =&gt; 'titre', 'country' =&gt; 'pays', ], 'dkim' =&gt; [ 'dkim_prefix' =&gt; [ 'title' =&gt; 'prefix dkim', 'description' =&gt; 'veuillez entrer l\'emplacement des fichiers rsa pour dkim ainsi que l\'emplacement du fichier de configuration pour le plugin milter', ], 'dkim_domains' =&gt; [ 'title' =&gt; 'nom du fichier dkim', 'description' =&gt; '&lt;strong&gt;nom du fichier&lt;/strong&gt; des paramtres dkim pour les domaines tel que entr dans la configuration de dkim-milter', ], 'dkim_dkimkeys' =&gt; [ 'title' =&gt; 'nom du fichier des clefs dkim', 'description' =&gt; '&lt;strong&gt;nom du fichier&lt;/strong&gt; des paramtres des clefs dkim tel que entr dans la configuration de dkim-milter', ], 'dkimrestart_command' =&gt; [ 'title' =&gt; 'commande de redmarrage de dkim-milter', 'description' =&gt; 'veuillez entrer la commande de redmarrage du service dkim-milter', ], 'use_dkim' =&gt; [ 'title' =&gt; 'activer le support dkim ?', 'description' =&gt; 'voulez-vous utiliser le systme dkim (domainkeys identified mail) ?', ], ], 'dns' =&gt; [ 'destinationip' =&gt; 'ip du domaine', 'standardip' =&gt; 'ip standard du serveur', 'a_record' =&gt; 'enregistrement de type "a" (ipv6 optionnel)', 'cname_record' =&gt; 'enregistrement cname', 'mxrecords' =&gt; 'dfinition des enregistrements mx', 'standardmx' =&gt; 'enregistrements mx standard du serveur', 'mxconfig' =&gt; 'enregistrements mx personnalis', 'priority10' =&gt; 'priorit 10', 'priority20' =&gt; 'priorit 20', 'txtrecords' =&gt; 'dfinir des enregistrement txt', 'txtexample' =&gt; 'exemple (pour spf) :&lt;br /&gt;v=spf1 ip4:xxx.xxx.xx.0/23 -all', ], 'domain' =&gt; [ 'openbasedirpath' =&gt; 'dossier "openbasedir"', 'docroot' =&gt; 'identique au dossier ci-dessus', 'homedir' =&gt; 'dossier principal', ], 'domains' =&gt; [ 'description' =&gt; 'ici, vous pouvez ajouter des sites et domaines et changer leurs doosiers.&lt;br /&gt;il vous faudra patienter quelques minutes aprs chaque changement pour que la configuration soit active.', 'domainsettings' =&gt; 'configuration des domaines', 'domainname' =&gt; 'nom du domaine', 'subdomain_add' =&gt; 'ajouter un sous-domaine', 'subdomain_edit' =&gt; 'changer un sous-domaine', 'wildcarddomain' =&gt; 'domaine gnrique (wilcard) ?', 'aliasdomain' =&gt; 'alias pour le domaine', 'noaliasdomain' =&gt; 'domaine sans alias', 'hasaliasdomains' =&gt; 'le domaine possde un ou des alias.', 'statstics' =&gt; 'frquentation', 'isassigneddomain' =&gt; 'le domaine est attribu', 'add_date' =&gt; 'ajouter froxlor', 'registration_date' =&gt; 'ajouter l\'enregistrement', ], 'emails' =&gt; [ 'description' =&gt; 'ici, vous pouvez ajouter vos botes e-mails.&lt;br /&gt;&lt;br /&gt;les informations pour configurer votre logiciel e-mail sont les suivantes : &lt;br /&gt;&lt;br /&gt;nom du serveur : &lt;b&gt;&lt;i&gt;votre-domaine.com&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;identifiant : &lt;b&gt;&lt;i&gt;l\'adresse e-mail&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;mot de passe : &lt;b&gt;&lt;i&gt;le mot de passe que vous avez choisi&lt;/i&gt;&lt;/b&gt;', 'emailaddress' =&gt; 'adresse', 'emails_add' =&gt; 'ajouter une adresse e-mail', 'emails_edit' =&gt; 'changer une adresse e-mail', 'catchall' =&gt; 'catchall', 'iscatchall' =&gt; 'dfinir comme adresse "catchall" ?', 'account' =&gt; 'accs', 'account_add' =&gt; 'ajouter un accs', 'account_delete' =&gt; 'supprimer l\'accs', 'from' =&gt; 'de', 'to' =&gt; '', 'forwarders' =&gt; 'rexpdition', 'forwarder_add' =&gt; 'ajouter un renvoi', 'alternative_emailaddress' =&gt; 'adresse e-mail alternative', 'quota' =&gt; 'quota', 'noquota' =&gt; 'pas de quota', 'updatequota' =&gt; 'mise jour', ], 'error' =&gt; [ 'error' =&gt; 'erreur', 'directorymustexist' =&gt; 'le dossier que vous avez choisi n\'existe pas. veuillez ajouter le dossier avec votre client ftp.', 'filemustexist' =&gt; 'le fichier que vous avez slectionn n\'existe pas.', 'allresourcesused' =&gt; 'vous avez dj utilis toutes les ressources.', 'domains_cantdeletemaindomain' =&gt; 'vous ne pouvez pas supprimer un domaine qui est utilis pour des adresses e-mails.', 'domains_canteditdomain' =&gt; 'vous n\'avez pas le droit de configurer ce domaine.', 'domains_cantdeletedomainwithemail' =&gt; 'vous ne pouvez pas supprimer un domaine qui est utilis pour des e-mails. vous devez d\'abord supprimer toutes les adresses e-mails qu\'il contient.', 'firstdeleteallsubdomains' =&gt; 'il faut d\'abord supprimer tous les sous-domaines avant d\'ajouter un domaine "wildcard".', 'youhavealreadyacatchallforthisdomain' =&gt; 'vous avez dj dfini une adresse "catchall" pour ce domaine.', 'ftp_cantdeletemainaccount' =&gt; 'vous ne pouvez pas supprimer votre accs principal.', 'login' =&gt; 'identifiant / mot de passe invalide.', 'login_blocked' =&gt; 'cet identifiant bloqu cause de nombreuses tentatives de connexions invalides.&lt;br /&gt;veuillez ressayer dans %s secondes.', 'notallreqfieldsorerrors' =&gt; 'vous n\'avez pas rempli toutes les cases obligatoires ou vous les avez remplis avec des informations invalides.', 'oldpasswordnotcorrect' =&gt; 'l\'ancien mot de passe n\'est pas correct.', 'youcantallocatemorethanyouhave' =&gt; 'vous ne pouvez pas distribuer plus de ressources qu\'il n\'en reste.', 'mustbeurl' =&gt; 'vous n\'avez pas entr une adresse url valide.', 'invalidpath' =&gt; 'vous n\'avez pas choisi une adresse url valide (probablement cause de problmes avec le listing de dossiers ?)', 'stringisempty' =&gt; 'entre manquante', 'stringiswrong' =&gt; 'entre invalide', 'newpasswordconfirmerror' =&gt; 'le nouveau mot de passe et sa confirmation ne sont pas identiques pas.', 'mydomain' =&gt; '"domaine"', 'loginnameexists' =&gt; 'l\'identifiant "%s" existe dj.', 'emailiswrong' =&gt; 'l\'adresse "%s" contient des signes invalides ou est incomplte.', 'loginnameiswrong' =&gt; 'l\'identifiant "%s" contient des signes invalides.', 'userpathcombinationdupe' =&gt; 'cette combinaison d\'identifiant et de dossier existe dj.', 'patherror' =&gt; 'erreur gnrale ! le dossier ne doit pas tre vide.', 'errordocpathdupe' =&gt; 'il dj une option concernant le dossier "%s".', 'adduserfirst' =&gt; 'vous devez d\'abord ajouter un.', 'domainalreadyexists' =&gt; 'le domaine "%s" existe dj.', 'nolanguageselect' =&gt; 'aucune langue choisis.', 'nosubjectcreate' =&gt; 'il faut entrer un sujet.', 'nomailbodycreate' =&gt; 'il faut entrer un corps de texte.', 'templatenotfound' =&gt; 'aucun modle trouv.', 'alltemplatesdefined' =&gt; 'vous avez dj appliqu des modles pour toutes les langues.', 'wwwnotallowed' =&gt; 'un sous-domaine ne peut pas s\'appeler www.', 'subdomainiswrong' =&gt; 'le sous-domaine "%s" contient des signes invalides.', 'domaincantbeempty' =&gt; 'le nom de domaine ne doit pas tre vide.', 'domainexistalready' =&gt; 'le domaine "%s" existe dj.', 'domainisaliasorothercustomer' =&gt; 'l\'alias du domaine choisi est soit un alias existant d\'un autre client ou soit fait rfrence lui mme.', 'emailexistalready' =&gt; 'l\'adresse "%s" existe dj.', 'maindomainnonexist' =&gt; 'le domaine "%s" n\'existe pas.', 'destinationnonexist' =&gt; 'veuillez crire votre adresse de renvoi l\'emplacement "".', 'destinationalreadyexistasmail' =&gt; 'le renvoi vers l\'adresse "%s" existe dj comme adresse active.', 'destinationalreadyexist' =&gt; 'il existe dj une rexpdition vers l\'adresse "%s".', 'destinationiswrong' =&gt; 'l\'adresse "%s" contient des signes invalides ou est incomplte.', 'loginnameissystemaccount' =&gt; 'vous ne pouvez pas crer de compte ressemblant aux comptes systme (ex : "%s"). veuillez entrer un autre nom de compte.', 'ipstillhasdomains' =&gt; 'la combinaison ip / port est encore utilise, veuillez rassigner le ou les domaines existant(s) avec cette adresse ip / port concern(s) une autre combinaison ip / port avant de supprimer celle-ci.', 'cantdeletedefaultip' =&gt; 'vous ne pouvez pas supprimer cette combinaison ip / port, veuillez d\'abord attribuer une autre combinaison ip / port par dfaut ce revendeur avant de supprimer celle-ci.', 'cantdeletesystemip' =&gt; 'vous ne pouvez pas crer, modifier ou supprimer l\'ip du systme.', 'myipdefault' =&gt; 'choissez une combinaison ip / port par dfaut.', 'myipnotdouble' =&gt; 'cette combinaison existe dj', 'cantchangesystemip' =&gt; 'vous ne pouvez pas modifier l\'adresse ip du systme, ni en ajouter de nouvelle.', 'sessiontimeoutiswrong' =&gt; 'seule une valeur numrique pour le temps d\'inactivit est autorise.', 'maxloginattemptsiswrong' =&gt; 'seule une valeur numrique pour "nombre maximum de tentative de connexion" est autorise.', 'deactivatetimiswrong' =&gt; 'seule une valeur numrique pour la dure de dsactivation est autorise.', 'accountprefixiswrong' =&gt; 'le "prfixe client" n\'est pas valide.', 'mysqlprefixiswrong' =&gt; 'le "prfixe sql" n\'est pas valide.', 'ftpprefixiswrong' =&gt; 'le "prfixe ftp" n\'est pas valide.', 'ipiswrong' =&gt; 'l\'"adresse ip" n\'est pas valide.', 'vmailuidiswrong' =&gt; 'l\'"uid e-mail" est incorrect. seul un uid numrique est autoris.', 'vmailgidiswrong' =&gt; 'le "gid e-mail" est incorrect. seul un gid numrique est autoris.', 'adminmailiswrong' =&gt; 'l\'adresse e-mail de l\'administrateur est incorrect. seulement une adresse e-mail valide est autoris.', 'pagingiswrong' =&gt; 'la valeur "nombre de rsultats page" est incorrecte. seul une valeur numrique est autorise.', 'phpmyadminiswrong' =&gt; 'le lien pour phpmyadmin n\'est pas valide.', 'webmailiswrong' =&gt; 'le lien pour le webmail n\'est pas valide.', 'webftpiswrong' =&gt; 'le lien pour le webftp n\'est pas valide.', 'stringformaterror' =&gt; 'la valeur pour "%s" n\'est pas dans un format reconnu.', 'youcantdeleteyourself' =&gt; 'vous ne pouvez pas supprimer votre propre compte pour des raisons vidente de scurit ...', 'youcanteditallfieldsofyourself' =&gt; 'note : vous ne pouvez pas diter tous les champs de votre propre compte pour des raisons de scurit.', 'documentrootexists' =&gt; 'le dossier "%s" existe dj pour cet utilisateur. veuillez le supprimer / dplacer avant de ressayer l\'ajout de cet utilisateur.', 'formtokencompromised' =&gt; 'la requte semble compromise. pour des raisons de scurit, vous avez dconnect.', 'logerror' =&gt; 'erreur log : %s', 'nomessagetosend' =&gt; 'vous n\'avez pas entr de message.', 'norecipientsgiven' =&gt; 'vous n\'avez pas spcifier de destinataire', 'errorsendingmail' =&gt; 'echec d\'envoi du message "%s"', 'cannotreaddir' =&gt; 'impossible de lire dossier "%s"', 'vmailquotawrong' =&gt; 'la taille du quota doit tre entre 1 et 999', 'invalidip' =&gt; 'adresse ip invalide : %s', 'invalidmysqlhost' =&gt; 'adresse hte mysql invalide : "%s"', 'cannotuseawstatsandwebalizeratonetime' =&gt; 'vous ne pouvez pas activer awstats &lt;u&gt;et&lt;/u&gt; webalizer en mme temps. veuillez n\'en choisir qu\'un seul.', 'cannotwritetologfile' =&gt; 'ne peut ouvrir le fichier de log %s en criture', ], 'extras' =&gt; [ 'description' =&gt; 'ici, vous pouvez ajouter des extras, comme par exemple, la protection de dossiers du site.&lt;br /&gt;il vous faudra patienter quelques minutes aprs chaque changement pour que la configuration soit active.', 'directoryprotection_add' =&gt; 'ajouter une protection de dossier', 'view_directory' =&gt; 'aperu du dossier', 'pathoptions_add' =&gt; 'ajouter des options sur le dossier', 'directory_browsing' =&gt; 'afficher le contenu des dossiers', 'pathoptions_edit' =&gt; 'modifier les options de dossier', 'errordocument404path' =&gt; 'emplacement du document "erreur 404"', 'errordocument403path' =&gt; 'emplacement du document "erreur 403"', 'errordocument500path' =&gt; 'emplacement du document "erreur 500"', 'errordocument401path' =&gt; 'emplacement du document "erreur 401"', ], 'ftp' =&gt; [ 'description' =&gt; 'ici, vous pouvez ajouter des accs ftp supplmentaires.&lt;br /&gt;les changements, ainsi que l\'accs, sont immdiatement oprationnels.', 'account_add' =&gt; 'ajouter un accs', ], 'index' =&gt; [ 'customerdetails' =&gt; 'informations personnelles', 'accountdetails' =&gt; 'informations du compte', ], 'logger' =&gt; [ 'date' =&gt; 'date', 'type' =&gt; 'type', 'action' =&gt; 'action', 'user' =&gt; 'utilisateur', 'truncate' =&gt; 'vider les logs', ], 'login' =&gt; [ 'username' =&gt; 'identifiant', 'password' =&gt; 'mot de passe', 'language' =&gt; 'langue', 'login' =&gt; 'se connecter', 'logout' =&gt; 'se dconnecter', 'profile_lng' =&gt; 'langue du profil', 'forgotpwd' =&gt; 'mot de passe oubli ?', 'presend' =&gt; 'rinitialiser le mot de passe', 'email' =&gt; 'adresse e-mail', 'remind' =&gt; 'rinitialiser mon mot de passe', 'usernotfound' =&gt; 'erreur : utilisateur inconnu !', ], 'mails' =&gt; [ 'pop_success' =&gt; [ 'mailbody' =&gt; 'bonjour,\\n\\nvotre accs pop3 / imap {email}\\na cr avec succs.\\n\\nceci est un e-mail gnr automatiquement, veuillez ne pas rpondre ce message.\\n\\ncordialement,\\nl\'quipe froxlor\\nhttp://www.froxlor.org', 'subject' =&gt; 'accs pop3 / imap cr', ], 'createcustomer' =&gt; [ 'mailbody' =&gt; 'bonjour {firstname} {name},\\n\\nvous trouverez ci-dessous vos informations d\'accs au panel d\'administration :\\n\\nadresse d\'administration : http://demo.froxlor.org\\n\\nidentifiant : {username}\\nmot de passe : {password}\\n\\ncordialement,\\nl\'quipe froxlor\\nhttp://www.froxlor.org\\n', 'subject' =&gt; 'froxlor : informations pour votre accs au panel d\'administration', ], 'pop_success_alternative' =&gt; [ 'mailbody' =&gt; 'bonjour,\\n\\nvotre compte e-mail {email} correctement cr.\\n\\nvotre mot de passe est : {password}.\\n\\nceci est un message gnr automatiquemenent, veuillez ne pas rpondre cet e-mail car il ne serait tre consulter.\\n\\ncordialement,\\nl\'quipe froxlor.', 'subject' =&gt; 'compte e-mail correctement cr', ], 'password_reset' =&gt; [ 'subject' =&gt; 'rinitialisation du mot de passe', 'mailbody' =&gt; 'bonjour {username},\\n\\nvotre mot de passe pour froxlor rinitialiser !\\nle nouveau mot de passe est : {link}\\n\\ncordialement,\\nl\'quipe froxlor.', ], ], 'menu' =&gt; [ 'message' =&gt; 'messages', ], 'menue' =&gt; [ 'main' =&gt; [ 'main' =&gt; 'gnral', 'changepassword' =&gt; 'changer de mot de passe', 'changelanguage' =&gt; 'changer de langue', 'username' =&gt; 'utilisateur : ', ], 'email' =&gt; [ 'email' =&gt; 'e-mail', 'emails' =&gt; 'adresse(s) e-mail(s)', 'webmail' =&gt; 'webmail', ], 'mysql' =&gt; [ 'mysql' =&gt; 'mysql', 'databases' =&gt; 'bases de donnes', 'phpmyadmin' =&gt; 'phpmyadmin', ], 'domains' =&gt; [ 'domains' =&gt; 'domaines', 'settings' =&gt; 'paramtres des sites', ], 'ftp' =&gt; [ 'ftp' =&gt; 'ftp', 'accounts' =&gt; 'comptes d\'accs ftp', 'webftp' =&gt; 'webftp', ], 'extras' =&gt; [ 'extras' =&gt; 'extras', 'directoryprotection' =&gt; 'protection des dossiers', 'pathoptions' =&gt; 'options des dossiers', ], 'traffic' =&gt; [ 'traffic' =&gt; 'trafic', 'current' =&gt; 'mois actuel', ], 'logger' =&gt; [ 'logger' =&gt; 'log systme', ], ], 'message' =&gt; [ 'norecipients' =&gt; 'aucun e-mail n\'a envoy car il n\'existe aucun destinataire dans la base de donnes', 'success' =&gt; 'le message envoy aux destinataires "%s"', ], 'mysql' =&gt; [ 'databasename' =&gt; 'nom de la base de donnes', 'databasedescription' =&gt; 'description de la base de donnes', 'database_create' =&gt; 'ajouter une base de donnes', 'description' =&gt; 'ici, vous pouvez ajouter et effacer des bases de donnes mysql.&lt;br /&gt;les changements, ainsi que les bases de donnes, sont immdiatement oprationnels.&lt;br /&gt;dans le menu, vous trouverez un lien vers phpmyadmin, avec lequel vous pouvez grer vos bases de donnes.&lt;br /&gt;&lt;br /&gt;l\'accs aux bases de donnes depuis les scripts php fonctionne comme suit : (il faut remplacer les valeurs en &lt;i&gt;&lt;b&gt;italique&lt;/b&gt;&lt;/i&gt; par vos informations !)&lt;br /&gt;&lt;br /&gt;$connexion = mysql_connect(\'localhost\', \'&lt;i&gt;&lt;b&gt;votre identifiant&lt;/b&gt;&lt;/i&gt;\', \'&lt;i&gt;&lt;b&gt;votre mot de passe&lt;/b&gt;&lt;/i&gt;\');&lt;br /&gt;mysql_select_db(\'&lt;i&gt;&lt;b&gt;le nom de la base de donnes&lt;/b&gt;&lt;/i&gt;\', $connexion);', ], 'panel' =&gt; [ 'edit' =&gt; 'modifier', 'delete' =&gt; 'supprimer', 'create' =&gt; 'ajouter', 'save' =&gt; 'sauvegarder', 'yes' =&gt; 'oui', 'no' =&gt; 'non', 'emptyfornochanges' =&gt; 'laissez vide pour ne pas modifier', 'emptyfordefault' =&gt; 'laissez vide pour l\'option standard', 'path' =&gt; 'dossier', 'toggle' =&gt; 'activer / dsactiver', 'next' =&gt; 'continuer', 'dirsmissing' =&gt; 'dossiers non disponibles ou illisibles', 'urloverridespath' =&gt; 'url (supplante la valeur dossier)', 'pathorurl' =&gt; 'dossier ou url', 'ascending' =&gt; 'ascendant', 'descending' =&gt; 'descendant', 'search' =&gt; 'rechercher', 'used' =&gt; 'utilis', 'translator' =&gt; 'traducteur(s)', 'reset' =&gt; 'ignorer les changements', 'pathdescription' =&gt; 'si le dossier n\'existe pas, il sera cr automatiquement.', 'back' =&gt; 'retour', 'reseller' =&gt; 'revendeur', 'admin' =&gt; 'administrateur', 'customer' =&gt; 'client(s)', 'send' =&gt; 'envoy', 'nosslipsavailable' =&gt; 'il n\'y actuellement aucune combinaison ip / port configurer pour ssl', 'backtooverview' =&gt; 'retour l\'aperu', 'dateformat' =&gt; 'yyyy-mm-dd', 'dateformat_function' =&gt; 'y-m-d', 'timeformat_function' =&gt; 'h:i:s', 'default' =&gt; 'par dfaut', 'never' =&gt; 'jamais', 'active' =&gt; 'actif', 'please_choose' =&gt; 'veuillez choisir', ], 'pwdreminder' =&gt; [ 'success' =&gt; 'mot de passe correctement rinitialiser.&lt;br /&gt;vous devriez recevoir un e-mail avec votre nouveau mot de passe d\'ici quelques minutes.', 'notallowed' =&gt; 'la rinitialisation des mots de passe est dsactive.', ], 'question' =&gt; [ 'question' =&gt; 'question de scurit', 'admin_customer_reallydelete' =&gt; 'etes-vous sr de vouloir supprimer le compte "%s" ?&lt;br /&gt;attention ! toutes ses informations seront supprimes ! une fois fait, il vous appartiendra de supprimer manuellement tous les dossiers du compte sur le systme de fichiers.', 'admin_domain_reallydelete' =&gt; 'etes-vous sr de vouloir supprimer le domaine "%s" ?', 'admin_domain_reallydisablesecuritysetting' =&gt; 'etes-vous sr de vouloir dsactiver les modes de scurit suivants : openbasedir et / safemode ?', 'admin_admin_reallydelete' =&gt; 'etes-vous sr de vouloir supprimer l\'administrateur "%s" ?&lt;br /&gt;tous ses comptes seront affects l\'administrateur principal.', 'admin_template_reallydelete' =&gt; 'etes-vous sr de vouloir supprimer le modle "%s" ?', 'domains_reallydelete' =&gt; 'etes-vous sr de vouloir supprimer le domaine "%s" ?', 'email_reallydelete' =&gt; 'etes-vous sr de vouloir supprimer l\'adresse e-mail "%s" ? ', 'email_reallydelete_account' =&gt; 'etes-vous sr de vouloir supprimer l\'accs e-mail "%s" ?', 'email_reallydelete_forwarder' =&gt; 'etes-vous sr de vouloir supprimer le renvoi vers "%s" ?', 'extras_reallydelete' =&gt; 'etes-vous sr de vouloir supprimer la protection du dossier "%s" ?', 'extras_reallydelete_pathoptions' =&gt; 'etes-vous sr de vouloir supprimer les options du dossier "%s" ?', 'ftp_reallydelete' =&gt; 'etes-vous sr de vouloir supprimer l\'accs ftp "%s" ?', 'mysql_reallydelete' =&gt; 'etes-vous sr de vouloir supprimer la base de donnes "%s" ?&lt;br /&gt;attention : toutes les donnes seront perdues jamais !', 'admin_configs_reallyrebuild' =&gt; 'etes-vous sr de vouloir rgnrer les fichiers de configuration apache et bind ?', 'admin_ip_reallydelete' =&gt; 'etes-vous sr de vouloir supprimer l\'adresse ip "%s" ?', 'admin_domain_reallydocrootoutofcustomerroot' =&gt; 'etes-vous sr de vouloir diffrencier la racine principale de ce domaine de la racine principale du client ?', 'admin_counters_reallyupdate' =&gt; 'etes-vous sr de vouloir recalculer les ressources utilises ?', 'admin_cleartextmailpws_reallywipe' =&gt; 'etes-vous sr de vouloir retirer tous les mots de passe en clairs des comptes e-mails de la table mail_users ? cette action ne peut tre annule !', 'logger_reallytruncate' =&gt; 'etes-vous sr de vouloir vider la table "%s" ?', 'admin_quotas_reallywipe' =&gt; 'etes-vous sr de vouloir retirer tous les quotas de la table mail_users ? cette action ne peut tre annule !', ], 'serversettings' =&gt; [ 'session_timeout' =&gt; [ 'title' =&gt; 'dure d\'inactivit maximale', 'description' =&gt; 'combien de secondes d\'inactivit avant qu\'une session ne se ferme ?', ], 'accountprefix' =&gt; [ 'title' =&gt; 'prfix des comptes', 'description' =&gt; 'quel prfix doivent avoir les comptes ?', ], 'mysqlprefix' =&gt; [ 'title' =&gt; 'prfix sql', 'description' =&gt; 'quel prfix doivent avoir les bases de donnes ?', ], 'ftpprefix' =&gt; [ 'title' =&gt; 'prfix ftp', 'description' =&gt; 'quel prfix doivent avoir les accs ftp ?', ], 'documentroot_prefix' =&gt; [ 'title' =&gt; 'dossier de stockage', 'description' =&gt; 'o doivent tre stocks tous les dossiers et fichiers des diffrents comptes ?', ], 'logfiles_directory' =&gt; [ 'title' =&gt; 'dossier des fichiers de log', 'description' =&gt; 'o doivent tre stocks les archives des logs d\'accs du serveur web ?', ], 'ipaddress' =&gt; [ 'title' =&gt; 'adresse ip', 'description' =&gt; 'quelle est l\'adresse ip du serveur ?', ], 'hostname' =&gt; [ 'title' =&gt; 'nom d\'hte', 'description' =&gt; 'quel est le nom d\'hte (hostname) du serveur ?', ], 'apachereload_command' =&gt; [ 'title' =&gt; 'commande de rechargement d\'apache', 'description' =&gt; 'quelle est la commande pour recharger / redmarrer apache ?', ], 'bindconf_directory' =&gt; [ 'title' =&gt; 'emplacement du dossier de configuration de bind / named', 'description' =&gt; 'o doit tre stock la configuration de bind / named ?', ], 'bindreload_command' =&gt; [ 'title' =&gt; 'commande de rechargement de bind / named', 'description' =&gt; 'quelle est la commande pour recharger / redmarrer bind / named ?', ], 'vmail_uid' =&gt; [ 'title' =&gt; 'uid des e-mails', 'description' =&gt; 'quel uid doivent avoir les e-mails ?', ], 'vmail_gid' =&gt; [ 'title' =&gt; 'gid des e-mails', 'description' =&gt; 'quel gid doivent avoir les e-mails ?', ], 'vmail_homedir' =&gt; [ 'title' =&gt; 'emplacement des e-mails', 'description' =&gt; 'dans quel dossier doivent tre stocker les e-mails ?', ], 'adminmail' =&gt; [ 'title' =&gt; 'adresse e-mail de l\'administrateur', 'description' =&gt; 'quelle est l\'adresse e-mail par dfaut des e-mails envoys par froxlor ?', ], 'phpmyadmin_url' =&gt; [ 'title' =&gt; 'adresse url de phpmyadmin', 'description' =&gt; 'a quelle adresse se trouve phpmyadmin ?', ], 'webmail_url' =&gt; [ 'title' =&gt; 'adresse url du webmail', 'description' =&gt; 'a quelle adresse se trouve le webmail ?', ], 'webftp_url' =&gt; [ 'title' =&gt; 'adresse url du webftp', 'description' =&gt; 'a quelle adresse se trouve le webftp ?', ], 'language' =&gt; [ 'description' =&gt; 'quelle langue est la langue par dfaut ?', ], 'maxloginattempts' =&gt; [ 'title' =&gt; 'nombre d\'essais maximum avant dsactivation', 'description' =&gt; 'nombre de tentatives maximum avant la dsactivation de l\'accs.', ], 'deactivatetime' =&gt; [ 'title' =&gt; 'dure de la dsactivation', 'description' =&gt; 'dure (en secondes) pendant laquelle l\'accs sera dsactiv.', ], 'pathedit' =&gt; [ 'title' =&gt; 'mode de slection des dossiers', 'description' =&gt; 'choisir un dossier par une liste droulante ou l\'entrer manuellement ?', ], 'nameservers' =&gt; [ 'title' =&gt; 'serveurs de nom nameservers', 'description' =&gt; 'une liste spare par des virgules contenant les noms d\'htes de tous les serveurs de noms. le premier dans la liste sera le serveur primaire.', ], 'mxservers' =&gt; [ 'title' =&gt; 'serveurs de messagerie mx', 'description' =&gt; 'une liste spare par des virgules contenant les serveurs de messagerie avec leur poid : un nombre et le nom d\'hte spar par un espace; par exemple : "10 mx.exemple.com".', ], 'paging' =&gt; [ 'title' =&gt; 'nombre de rsultats par page', 'description' =&gt; 'nombre de rsultats par page ? (0 = dsactive la pagination)', ], 'defaultip' =&gt; [ 'title' =&gt; 'ip / port par dfaut', 'description' =&gt; 'quel est l\'ip / port par dfaut ?', ], 'phpappendopenbasedir' =&gt; [ 'title' =&gt; 'dossier(s) de l\'openbasedir', 'description' =&gt; 'liste de dossiers spare par des virgules qui sera ajout la variable "openbasedir" des conteneurs vhosts.', ], 'natsorting' =&gt; [ 'title' =&gt; 'utiliser un tri naturel dans les diffrentes vues', 'description' =&gt; 'trier les listes comme web1 -&gt; web2 -&gt; etc ... -&gt; web11 au lieu de web1 -&gt; web11 -&gt; web2.', ], 'deactivateddocroot' =&gt; [ 'title' =&gt; 'dossier "documentroot" pour les utilisateurs dsactivs', 'description' =&gt; 'quand un utilisateur est dsactiv, ce dossier sera utilis comme dossier racine pour le serveur web. laissez vide pour ne pas crer de vhost et ne rien afficher du tout lorsque l\'utilisateur est dsactiv.', ], 'mailpwcleartext' =&gt; [ 'title' =&gt; 'sauvegarder aussi les mots de passe des comptes e-mails de faon dcrypter dans la base de donnes', 'description' =&gt; 'si cela est oui, tous les mots de passe seront aussi sauvegarder de faon dcrypter dans la table mail_users (en texte clair pour toutes personnes qui auraient accs la base de donnes). activer cette option, uniquement si vous en avez vraiment besoin !', 'removelink' =&gt; 'cliquez ici pour retirer tous les mots de passe en texte clair de la base de donnes.', ], 'ftpdomain' =&gt; [ 'title' =&gt; 'comptes ftp @domaine', 'description' =&gt; 'les utilisateurs peuvent-ils crer des comptes ftp de la forme utilisateur@domaine.com ?', ], 'mod_fcgid' =&gt; [ 'title' =&gt; 'utiliser php par mod_fcgid / suexec', 'description' =&gt; 'utiliser mod_fcgid / suexec / libnss_mysql pour lancer php avec le compte correspondant l\'utilisateur ?&lt;br/&gt;&lt;b&gt;cela besoin d\'une configuration spcifique d\'apache !&lt;/b&gt;', 'configdir' =&gt; [ 'title' =&gt; 'dossier de configuration fcgi', 'description' =&gt; 'o doivent tre stocks les fichiers de configuration pour fcgi ?', ], 'tmpdir' =&gt; [ 'title' =&gt; 'dossier temporaire pour fcgi', ], ], 'sendalternativemail' =&gt; [ 'title' =&gt; 'utiliser une adresse e-mail alternative', 'description' =&gt; 'envoyer le mot de passe du compte e-mail une adresse diffrents pour la cration du compte e-mail ?', ], 'apacheconf_vhost' =&gt; [ 'title' =&gt; 'dossier / fichier de configuration des vhosts pour apache', 'description' =&gt; 'o doit tre stock le fichier de configuration des vhosts ? vous pouvez soit entrer le nom d\'un fichier (tous les vhosts dans un seul fichier), soit le nom d\'un dossier (chacun des vhosts dans un fichier spar du dossier).', ], 'apacheconf_diroptions' =&gt; [ 'title' =&gt; 'fichier / dossier de configuration des options des dossiers pour apache', 'description' =&gt; 'o doit tre stock le fichier de configuration des options de dossiers ? vous pouvez soit entrer le nom d\'un fichier (toutes les options des dossiers dans un seul fichier), soit le nom d\'un dossier (chacune des options de dossier dans un fichier spar du dossier).', ], 'apacheconf_htpasswddir' =&gt; [ 'title' =&gt; 'dossier du fichier htpasswd pour apache', 'description' =&gt; 'o doit tre stock le fichier de configuration de protection des dossiers "htpasswd" pour apache ?', ], 'mysql_access_host' =&gt; [ 'title' =&gt; 'htes de connexion mysql', 'description' =&gt; 'une liste spare par des virgules contenant la liste des htes depuis lesquels les utilisateurs sont autoriss se connecter au serveur mysql.', ], 'webalizer_quiet' =&gt; [ 'title' =&gt; 'sortie webalizer', 'description' =&gt; 'verbosit du programme webalizer', ], 'logger' =&gt; [ 'enable' =&gt; 'activer / dsactiver les logs', 'severity' =&gt; 'niveau de log', 'types' =&gt; [ 'title' =&gt; 'type(s) de log', 'description' =&gt; 'spcifiez les types de log spars par des virgules.&lt;br /&gt;les types de log disponible sont : syslog, file, mysql', ], 'logfile' =&gt; 'nom du fichier de log, dossier + nom du fichier', 'logcron' =&gt; 'loguer les travaux de cron', 'logcronoption' =&gt; [ 'never' =&gt; 'jamais', 'once' =&gt; 'une fois', 'always' =&gt; 'toujours', ], ], 'ssl' =&gt; [ 'openssl_cnf' =&gt; 'paramtres par dfaut pour crer le certificat', ], 'default_vhostconf' =&gt; [ 'title' =&gt; 'paramtres par dfaut pour les vhosts', ], 'mail_quota' =&gt; [ 'title' =&gt; 'quota de la bote aux lettres', 'description' =&gt; 'quota par dfaut pour toutes nouvelles botes aux lettres cres.', ], 'mail_quota_enabled' =&gt; [ 'title' =&gt; 'utiliser les quotas de botes aux lettres pour les clients', 'description' =&gt; 'activez cette option pour utiliser les quotas sur les botes aux lettres. par dfaut, cette option est &lt;b&gt;non&lt;/b&gt; car cela requiert une configuration spcifique.', 'removelink' =&gt; 'cliquez ici pour retirer tous les quotas de tous les comptes e-mails.', ], 'decimal_places' =&gt; 'nombre de dcimales afficher pour le trafic / espace web', 'webalizer_enabled' =&gt; 'activer les statistiques webalizer', 'awstats_enabled' =&gt; 'activer les statistiques awstats', 'selfdns' =&gt; [ 'title' =&gt; 'paramtres manuel des dns du domaine', ], 'selfdnscustomer' =&gt; [ 'title' =&gt; 'permettre aux clients de modifier les paramtes dns du domaine', ], 'unix_names' =&gt; [ 'title' =&gt; 'utiliser des noms d\'utilisateurs compatible unix', 'description' =&gt; 'vous permet d\'utiliser les &lt;strong&gt;-&lt;/strong&gt; et &lt;strong&gt;_&lt;/strong&gt; dans les noms d\'utilisateurs si l\'option est &lt;strong&gt;non&lt;/strong&gt;', ], 'allow_password_reset' =&gt; [ 'title' =&gt; 'permettre aux clients de rinitialiser leurs mots de passe', 'description' =&gt; 'les clients peuvent rinitialiser leurs mots de passe et il sera envoy leurs propres adresses e-mails', ], 'allow_password_reset_admin' =&gt; [ 'title' =&gt; 'permettre la rinitialisation des mots de passe par les administrateurs', 'description' =&gt; 'les administrateurs / revendeurs peuvent rinitialiser leurs mots de passe et il sera envoy leurs propres adresses e-mails', ], ], 'traffic' =&gt; [ 'month' =&gt; 'mois', 'day' =&gt; 'jour', 'months' =&gt; [ 1 =&gt; 'janvier', 2 =&gt; 'fvrier', 3 =&gt; 'mars', 4 =&gt; 'avril', 5 =&gt; 'mai', 6 =&gt; 'juin', 7 =&gt; 'juillet', 8 =&gt; 'aot', 9 =&gt; 'septembre', 10 =&gt; 'octobre', 11 =&gt; 'novembre', 12 =&gt; 'dcembre', ], 'mb' =&gt; 'trafic (mo)', 'distribution' =&gt; '&lt;font color="#019522"&gt;ftp&lt;/font&gt; | &lt;font color="#0000ff"&gt;http&lt;/font&gt; | &lt;font color="#800000"&gt;e-mail&lt;/font&gt;', 'sumhttp' =&gt; 'trafic http total entrant', 'sumftp' =&gt; 'trafic ftp total entrant', 'summail' =&gt; 'trafic e-mail total entrant', ], 'translator' =&gt; 'tim zielosko, aldo reset, romain mariadassou', ];</file><file name="lng/es.lng.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return [ 'languages' =&gt; [ 'cz' =&gt; 'checo', 'de' =&gt; 'alemn', 'en' =&gt; 'ingls', 'fr' =&gt; 'francs', 'it' =&gt; 'italia', 'nl' =&gt; 'holands', 'pt' =&gt; 'portugus', 'se' =&gt; 'sueco', 'es' =&gt; 'espaol', ], '2fa' =&gt; [ '2fa' =&gt; 'opciones 2fa', '2fa_enabled' =&gt; 'activar la autenticacin de dos factores (2fa)', '2fa_removed' =&gt; '2fa eliminado correctamente', '2fa_added' =&gt; '2fa activado correctamente&lt;br /&gt;&lt;a class="alert-link" href="%s?page=2fa"&gt;ver detalles de 2fa&lt;/a&gt;', '2fa_add' =&gt; 'activar 2fa', '2fa_delete' =&gt; 'desactivar 2fa', '2fa_verify' =&gt; 'verificar cdigo', '2fa_overview_desc' =&gt; 'aqu puede activar una autenticacin de dos factores para su cuenta.&lt;br /&gt;&lt;br /&gt;puede utilizar una aplicacin de autenticacin (contrasea de un solo uso basada en el tiempo / totp) dejar que froxlor le enve un correo electrnico la direccin de su cuenta despus de cada inicio de sesin correcto con una contrasea de un solo uso.', '2fa_email_desc' =&gt; 'su cuenta est configurada para utilizar contraseas de un solo uso por correo electrnico. para desactivarla, haga clic en "desactivar 2fa".', '2fa_ga_desc' =&gt; 'su cuenta est configurada para utilizar contraseas de un solo uso basadas en el tiempo travs de una aplicacin de autenticacin. escanee el cdigo qr que aparece continuacin con la aplicacin de autenticacin que desee para generar los cdigos. para desactivar, haga clic en "desactivar 2fa".' ], 'admin' =&gt; [ 'overview' =&gt; 'visin general', 'ressourcedetails' =&gt; 'recursos usados', 'systemdetails' =&gt; 'detalles del sistema', 'froxlordetails' =&gt; 'detalles de froxlor', 'installedversion' =&gt; 'versin instalada', 'latestversion' =&gt; 'ltima versin', 'lookfornewversion' =&gt; [ 'clickhere' =&gt; 'bsqueda mediante webservice', 'error' =&gt; 'error de lectura' ], 'resources' =&gt; 'recursos', 'customer' =&gt; 'cliente', 'customers' =&gt; 'clientes', 'customers_list_desc' =&gt; 'gestione sus clientes', 'customer_add' =&gt; 'crear cliente', 'customer_edit' =&gt; 'editar cliente', 'username_default_msg' =&gt; 'dejar vaco para el valor autogenerado', 'domains' =&gt; 'dominios', 'domain_add' =&gt; 'crear dominio', 'domain_edit' =&gt; 'editar dominio', 'subdomainforemail' =&gt; 'subdominios como dominios de correo electrnico', 'admin' =&gt; 'administrador', 'admins' =&gt; 'admins', 'admin_add' =&gt; 'crear administrador', 'admin_edit' =&gt; 'editar admin', 'customers_see_all' =&gt; 'puede acceder los recursos de otros administradores/revendedores?', 'change_serversettings' =&gt; 'puede cambiar la configuracin del servidor?', 'server' =&gt; 'sistema', 'serversettings' =&gt; 'ajustes', 'serversettings_desc' =&gt; 'administrar su sistema froxlor', 'rebuildconf' =&gt; 'reconstruir archivos de configuracin', 'stdsubdomain' =&gt; 'subdominio estndar', 'stdsubdomain_add' =&gt; 'crear subdominio estndar', 'phpenabled' =&gt; 'php habilitado', 'deactivated' =&gt; 'desactivado', 'deactivated_user' =&gt; 'desactivar usuario', 'sendpassword' =&gt; 'enviar contrasea', 'ownvhostsettings' =&gt; 'configuracin vhost propia', 'configfiles' =&gt; [ 'serverconfiguration' =&gt; 'configuracin', 'overview' =&gt; 'visin general', 'wizard' =&gt; 'asistente', 'distribution' =&gt; 'distribucin', 'service' =&gt; 'servicio', 'daemon' =&gt; 'daemon', 'http' =&gt; 'servidor web (http)', 'dns' =&gt; 'servidor de nombres (dns)', 'mail' =&gt; 'servidor de correo (imap/pop3)', 'smtp' =&gt; 'servidor de correo (smtp)', 'ftp' =&gt; 'servidor ftp', 'etc' =&gt; 'otros (sistema)', 'choosedistribution' =&gt; '-- elija una distribucin --', 'chooseservice' =&gt; '-- elija un servicio --', 'choosedaemon' =&gt; '-- elija un demonio --', 'statistics' =&gt; 'estadsticas', 'compactoverview' =&gt; 'vista general compacta', 'legend' =&gt; '&lt;h3&gt;est punto de configurar un servicio/demonio&lt;/h3&gt;', 'commands' =&gt; '&lt;span class="text-danger"&gt;comandos:&lt;/span&gt; estos comandos deben ser ejecutados lnea por lnea como usuario root en un shell. es seguro copiar todo el bloque pegarlo en el shell.', 'files' =&gt; '&lt;span class="text-danger"&gt;archivos de configuracin:&lt;/span&gt; los comandos antes de los campos de texto deben abrir un editor con el archivo de destino. slo tienes que copiar pegar el contenido en el editor guardar el archivo.&lt;br /&gt;&lt;span class="text-danger"&gt;nota:&lt;/span&gt; la contrasea mysql ha sido reemplazada por razones de seguridad. por favor, reemplaza "froxlor_mysql_password" por tu cuenta utiliza el formulario javascript de abajo para reemplazarla situ. si olvidaste tu contrasea mysql la encontrars en "lib/userdata.inc.php".', 'importexport' =&gt; 'importar/exportar', 'finishnote' =&gt; 'archivo de parmetros generado correctamente. ahora ejecute el siguiente comando como root:', 'description' =&gt; 'configurar los servicios del sistema', 'minihowto' =&gt; 'en esta pgina puede ver las diferentes plantillas de configuracin para cada servicio, (re)configurar servicios especficos si es necesario exportar la seleccin actual un archivo json para utilizarlo en los scripts cli en otro servidor.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;tenga en cuenta&lt;/b&gt; que los servicios resaltados reflejan su configuracin actual, sino que muestran requisitos/recomendaciones de sus valores de configuracin actuales.', 'skipconfig' =&gt; 'no (re)configurar', 'recommendednote' =&gt; 'servicios recomendados/requeridos segn la configuracin actual del sistema', 'selectrecommended' =&gt; 'seleccionar recomendados', 'downloadselected' =&gt; 'exportar seleccionado' ], 'templates' =&gt; [ 'templates' =&gt; 'plantillas de correo electrnico', 'template_add' =&gt; 'aadir plantilla', 'template_fileadd' =&gt; 'aadir plantilla de archivo', 'template_edit' =&gt; 'editar plantilla', 'action' =&gt; 'accin', 'email' =&gt; 'plantillas de correo electrnico archivos', 'subject' =&gt; 'asunto', 'mailbody' =&gt; 'cuerpo del correo', 'createcustomer' =&gt; 'correo de bienvenida para nuevos clientes', 'pop_success' =&gt; 'correo de bienvenida para nuevas cuentas de correo electrnico', 'template_replace_vars' =&gt; 'variables sustituir en la plantilla:', 'salutation' =&gt; 'sustituido por un saludo correcto (nombre empresa)', 'firstname' =&gt; 'sustituido por el nombre del cliente.', 'name' =&gt; 'se sustituye por el nombre del cliente.', 'company' =&gt; 'se sustituye por el nombre de la empresa del cliente.', 'username' =&gt; 'se sustituye por el nombre de usuario de la cuenta del cliente.', 'password' =&gt; 'se sustituye por la contrasea de la cuenta del cliente.', 'email' =&gt; 'se sustituye por la direccin de la cuenta pop3/imap.', 'customer_no' =&gt; 'sustituido por el nmero de cliente', 'traffic' =&gt; 'se sustituye por el trfico asignado al cliente.', 'trafficused' =&gt; 'sustituido por el trfico, que fue agotado por el cliente.', 'pop_success_alternative' =&gt; 'correo de bienvenida para nuevas cuentas de correo electrnico enviado la direccin alternativa', 'email_password' =&gt; 'sustituido por la contrasea de la cuenta pop3/imap.', 'index_html' =&gt; 'archivo de ndice para directorios de clientes recin creados', 'servername' =&gt; 'sustituido por el nombre del servidor.', 'customer' =&gt; 'sustituido por el nombre de usuario del cliente.', 'admin' =&gt; 'se sustituye por el nombre de usuario del administrador.', 'customer_email' =&gt; 'se sustituye por la direccin de correo electrnico del cliente.', 'admin_email' =&gt; 'se sustituye por la direccin de correo electrnico del administrador.', 'filetemplates' =&gt; 'plantillas de archivos', 'filecontent' =&gt; 'contenido del fichero', 'new_database_by_customer' =&gt; 'notificacin al cliente de la creacin de una base de datos', 'new_ftpaccount_by_customer' =&gt; 'notificacin al cliente de la creacin de un usuario ftp', 'newdatabase' =&gt; 'correos de notificacin para nuevas bases de datos', 'newftpuser' =&gt; 'correos de notificacin para nuevos usuarios ftp', 'cust_name' =&gt; 'nombre del cliente', 'db_name' =&gt; 'nombre de la base de datos', 'db_pass' =&gt; 'contrasea de la base de datos', 'db_desc' =&gt; 'descripcin de la base de datos', 'db_srv' =&gt; 'servidor de base de datos', 'pma_uri' =&gt; 'url de phpmyadmin (si se indica)', 'usr_name' =&gt; 'nombre de usuario ftp', 'usr_pass' =&gt; 'contrasea ftp', 'usr_path' =&gt; 'ftp homedir (relativo customer-docroot)', 'forgotpwd' =&gt; 'correos de notificacin de restablecimiento de contrasea', 'password_reset' =&gt; 'notificacin al cliente de restablecimiento de contrasea', 'trafficmaxpercent' =&gt; 'correo de notificacin para los clientes cuando se agota un determinado porcentaje mximo de trfico', 'max_percent' =&gt; 'sustituido por el lmite de diskusage/trfico para el envo de informes en porcentaje.', 'usage_percent' =&gt; 'reemplazado con el diskusage/trfico agotado por el cliente en porcentaje.', 'diskmaxpercent' =&gt; 'correo de notificacin los clientes cuando se agota el porcentaje mximo de espacio en disco.', 'diskavailable' =&gt; 'sustituido por el uso de disco asignado al cliente.', 'diskused' =&gt; 'reemplazado por el uso de disco, que fue agotado por el cliente.', 'link' =&gt; 'sustituido por el enlace de restablecimiento de contrasea del cliente.', 'server_hostname' =&gt; 'reemplaza el system-hostname (url froxlor)', 'server_ip' =&gt; 'reemplaza la direccin ip del servidor por defecto', 'server_port' =&gt; 'reemplaza el puerto por defecto del servidor', 'domainname' =&gt; 'reemplaza el subdominio estndar del cliente (puede estar vaco si se genera ninguno)' ], 'webserver' =&gt; 'servidor web', 'createzonefile' =&gt; 'crear zona dns para el dominio', 'custombindzone' =&gt; 'archivo de zona personalizado / gestionado', 'bindzonewarning' =&gt; 'vaco por defecto&lt;br /&gt;&lt;strong class="text-danger"&gt;atencin:&lt;/strong&gt; si utiliza un archivo de zonas, tendr que gestionar tambin manualmente todos los registros necesarios para todas las subzonas.', 'ipsandports' =&gt; [ 'ipsandports' =&gt; 'ips puertos', 'add' =&gt; 'aadir ip/puerto', 'edit' =&gt; 'editar ip/puerto', 'ipandport' =&gt; 'ip/puerto', 'ip' =&gt; 'ip', 'ipnote' =&gt; '&lt;div id="ipnote" class="invalid-feedback"&gt;nota: aunque las direcciones ip privadas estn permitidas, algunas caractersticas como dns podran comportarse correctamente.&lt;br /&gt;slo use direcciones ip privadas si est seguro.&lt;/div&gt;', 'port' =&gt; 'puerto', 'create_listen_statement' =&gt; 'crear sentencia listen', 'create_namevirtualhost_statement' =&gt; 'crear sentencia namevirtualhost', 'create_vhostcontainer' =&gt; 'crear vhost-container', 'create_vhostcontainer_servername_statement' =&gt; 'crear sentencia servername en vhost-container', 'enable_ssl' =&gt; 'se trata de un puerto ssl?', 'ssl_cert_file' =&gt; 'ruta al certificado ssl', 'webserverdefaultconfig' =&gt; 'configuracin por defecto del servidor web', 'webserverdomainconfig' =&gt; 'configuracin de dominio del servidor web', 'webserverssldomainconfig' =&gt; 'configuracin ssl del servidor web', 'ssl_key_file' =&gt; 'ruta al archivo de claves ssl', 'ssl_ca_file' =&gt; 'ruta al certificado ssl ca', 'default_vhostconf_domain' =&gt; 'configuracin vhost por defecto para cada contenedor de dominio', 'ssl_cert_chainfile' =&gt; [ 'title' =&gt; 'ruta al archivo ssl certificatechainfile', 'description' =&gt; 'mayormente ca_bundle, similar, probablemente quieras configurar esto si comprado un certificado ssl.' ], 'docroot' =&gt; [ 'title' =&gt; 'docroot personalizado (vaco = apunta froxlor)', 'description' =&gt; 'aqu puedes definir un document-root personalizado (el destino de una peticin) para esta combinacin ip/puerto.&lt;br/&gt;&lt;strong&gt;atencin:&lt;/strong&gt; por favor, ten cuidado con lo que introduces aqu!' ], 'ssl_paste_description' =&gt; 'pegue el contenido completo de su certificado en el cuadro de texto', 'ssl_cert_file_content' =&gt; 'contenido del certificado ssl', 'ssl_key_file_content' =&gt; 'contenido del archivo de clave ssl (privada)', 'ssl_ca_file_content' =&gt; 'contenido del archivo ssl ca (opcional)', 'ssl_ca_file_content_desc' =&gt; '&lt;br/&gt;&lt;br/&gt;autenticacin del cliente, configure esto slo si sabe lo que es.', 'ssl_cert_chainfile_content' =&gt; 'contenido del archivo de cadena de certificados (opcional)', 'ssl_cert_chainfile_content_desc' =&gt; '&lt;br/&gt;&lt;br/&gt;principalmente ca_bundle, similar, probablemente quiera establecer esto si compr un certificado ssl.', 'ssl_default_vhostconf_domain' =&gt; 'configuracin ssl vhost por defecto para cada contenedor de dominio' ], 'memorylimitdisabled' =&gt; 'desactivado', 'valuemandatory' =&gt; 'este valor es obligatorio', 'valuemandatorycompany' =&gt; 'o bien "nombre" "nombre" "empresa" debe ser llenado', 'serversoftware' =&gt; 'serversoftware', 'phpversion' =&gt; 'versin php', 'mysqlserverversion' =&gt; 'versin del servidor mysql', 'webserverinterface' =&gt; 'interfaz del servidor web', 'accountsettings' =&gt; 'configuracin de la cuenta', 'panelsettings' =&gt; 'configuracin del panel', 'systemsettings' =&gt; 'configuracin del sistema', 'webserversettings' =&gt; 'configuracin del servidor web', 'mailserversettings' =&gt; 'configuracin del servidor de correo', 'nameserversettings' =&gt; 'configuracin del servidor de nombres', 'updatecounters' =&gt; 'recalcular el uso de recursos', 'subcanemaildomain' =&gt; [ 'never' =&gt; 'nunca', 'choosableno' =&gt; 'seleccionable, por defecto no', 'choosableyes' =&gt; 'seleccionable, por defecto s', 'always' =&gt; 'siempre' ], 'wipecleartextmailpwd' =&gt; 'borrar contraseas en texto plano', 'webalizersettings' =&gt; 'configuracin de webalizer', 'webalizer' =&gt; [ 'normal' =&gt; 'normal', 'quiet' =&gt; 'silencioso', 'veryquiet' =&gt; 'sin salida' ], 'domain_nocustomeraddingavailable' =&gt; 'actualmente es posible aadir un dominio. primero debe aadir al menos un cliente.', 'loggersettings' =&gt; 'configuracin del registro', 'logger' =&gt; [ 'normal' =&gt; 'normal', 'paranoid' =&gt; 'paranoico' ], 'emaildomain' =&gt; 'emaildomain', 'email_only' =&gt; 'slo correo electrnico?', 'wwwserveralias' =&gt; 'aada un "www." serveralias', 'subject' =&gt; 'asunto', 'recipient' =&gt; 'destinatario', 'message' =&gt; 'escribir un mensaje', 'text' =&gt; 'mensaje', 'sslsettings' =&gt; 'configuracin ssl', 'specialsettings_replacements' =&gt; 'puede utilizar las siguientes variables:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (si procede)&lt;br/&gt;', 'dkimsettings' =&gt; 'configuracin de domainkey', 'caneditphpsettings' =&gt; 'puede cambiar los ajustes de dominio relacionados con php?', 'allips' =&gt; 'todas las ip', 'awstatssettings' =&gt; 'configuracin de awstats', 'domain_dns_settings' =&gt; 'configuracin dns del dominio', 'activated' =&gt; 'activado', 'statisticsettings' =&gt; 'configuracin de estadsticas', 'or' =&gt; 'o', 'sysload' =&gt; 'carga del sistema', 'noloadavailable' =&gt; 'no disponible', 'nouptimeavailable' =&gt; 'no disponible', 'nosubject' =&gt; '(sin asunto)', 'security_settings' =&gt; 'opciones de seguridad', 'know_what_youre_doing' =&gt; 'cambiar slo, si sabes lo que haces!', 'show_version_login' =&gt; [ 'title' =&gt; 'mostrar la versin de froxlor en el login', 'description' =&gt; 'mostrar la versin de froxlor en el pie de pgina en la pgina de inicio de sesin' ], 'show_version_footer' =&gt; [ 'title' =&gt; 'mostrar la versin de froxlor en el pie de pgina', 'description' =&gt; 'mostrar la versin de froxlor en el pie de pgina del resto de pginas' ], 'froxlor_graphic' =&gt; [ 'title' =&gt; 'grfico de cabecera para froxlor', 'description' =&gt; 'qu grfico debe mostrarse en la cabecera' ], 'phpsettings' =&gt; [ 'title' =&gt; 'configuracin php', 'description' =&gt; 'breve descripcin', 'actions' =&gt; 'acciones', 'activedomains' =&gt; 'en uso para dominio(s)', 'notused' =&gt; 'configuracin en uso', 'editsettings' =&gt; 'cambiar configuracin php', 'addsettings' =&gt; 'crear nueva configuracin php', 'viewsettings' =&gt; 'ver configuracin php', 'phpinisettings' =&gt; 'configuracin php.ini', 'addnew' =&gt; 'crear nueva configuracin php', 'binary' =&gt; 'php binario', 'fpmdesc' =&gt; 'configuracin php-fpm', 'file_extensions' =&gt; 'extensiones de archivos', 'file_extensions_note' =&gt; '(sin punto, separadas por espacios)', 'enable_slowlog' =&gt; 'activar slowlog (por dominio)', 'request_terminate_timeout' =&gt; 'solicitar terminate-timeout', 'request_slowlog_timeout' =&gt; 'solicitar slowlog-timeout', 'activephpconfigs' =&gt; 'en uso para php-config(s)', 'pass_authorizationheader' =&gt; 'aade "-pass-header authorization" / "cgipassauth on" vhosts' ], 'misc' =&gt; 'varios', 'fpmsettings' =&gt; [ 'addnew' =&gt; 'crear nueva versin php', 'edit' =&gt; 'cambiar versin php' ], 'phpconfig' =&gt; [ 'template_replace_vars' =&gt; 'variables que sern reemplazadas en las configs', 'pear_dir' =&gt; 'ser reemplazada con la configuracin global para el directorio pear.', 'open_basedir_c' =&gt; 'se insertar un ; (punto coma) para comentar/desactivar open_basedir cuando se establezca', 'open_basedir' =&gt; 'se sustituir por la configuracin open_basedir del dominio.', 'tmp_dir' =&gt; 'ser reemplazado por el directorio temporal del dominio.', 'open_basedir_global' =&gt; 'se sustituir por el valor global de la ruta que se adjuntar open_basedir (ver configuracin del servidor web).', 'customer_email' =&gt; 'se sustituir por la direccin de correo electrnico del cliente propietario del dominio.', 'admin_email' =&gt; 'se sustituir por la direccin de correo electrnico del administrador propietario del dominio.', 'domain' =&gt; 'se sustituir por el dominio.', 'customer' =&gt; 'se sustituir por el nombre de usuario del cliente propietario del dominio.', 'admin' =&gt; 'se sustituir por el nombre de usuario del administrador propietario del dominio.', 'docroot' =&gt; 'se sustituir por la raz del documento del dominio.', 'homedir' =&gt; 'se sustituir por el directorio raz del cliente.' ], 'expert_settings' =&gt; 'configuracin experta', 'mod_fcgid_starter' =&gt; [ 'title' =&gt; 'procesos php para este dominio (vaco por defecto)' ], 'phpserversettings' =&gt; 'configuracin php', 'mod_fcgid_maxrequests' =&gt; [ 'title' =&gt; 'peticiones php mximas para este dominio (vaco por defecto)' ], 'spfsettings' =&gt; 'configuracin spf del dominio', 'specialsettingsforsubdomains' =&gt; 'aplicar configuracin especial todos los subdominios (*.ejemplo.com)', 'accountdata' =&gt; 'datos de la cuenta', 'contactdata' =&gt; 'datos de contacto', 'servicedata' =&gt; 'datos de servicio', 'newerversionavailable' =&gt; 'hay una nueva versin de froxlor disponible.', 'newerversiondetails' =&gt; 'actualice ahora la versin &lt;b&gt;%s&lt;/b&gt;?&lt;br/&gt;(su versin actual es: %s)', 'extractdownloadedzip' =&gt; 'extraer el archivo descargado "%s"?', 'cron' =&gt; [ 'cronsettings' =&gt; 'configuracin de cronjob', 'add' =&gt; 'aadir cronjob' ], 'cronjob_edit' =&gt; 'editar cronjob', 'warning' =&gt; 'advertencia - tenga en cuenta!', 'lastlogin_succ' =&gt; 'ltimo acceso', 'ftpserver' =&gt; 'servidor ftp', 'ftpserversettings' =&gt; 'configuracin del servidor ftp', 'webserver_user' =&gt; 'nombre de usuario del servidor web', 'webserver_group' =&gt; 'nombre de grupo del servidor web', 'perlenabled' =&gt; 'perl activado', 'fcgid_settings' =&gt; 'fcgid', 'mod_fcgid_user' =&gt; 'usuario local utilizar para fcgid (froxlor vhost)', 'mod_fcgid_group' =&gt; 'grupo local utilizar para fcgid (froxlor vhost)', 'perl_settings' =&gt; 'perl/cgi', 'notgiven' =&gt; '[no indicado]', 'store_defaultindex' =&gt; 'almacenar el archivo de ndice por defecto en el docroot del cliente', 'phpfpm_settings' =&gt; 'php-fpm', 'traffic' =&gt; 'trfico', 'traffic_sub' =&gt; 'detalles sobre el uso del trfico', 'domaintraffic' =&gt; 'dominios', 'customertraffic' =&gt; 'clientes', 'assignedmax' =&gt; 'asignado / max', 'usedmax' =&gt; 'usado / max', 'used' =&gt; 'usado', 'speciallogwarning' =&gt; '&lt;div id="speciallogfilenote" class="invalid-feedback"&gt;advertencia: al cambiar esta configuracin perder todas sus antiguas estadsticas para este dominio.&lt;/div&gt;', 'speciallogfile' =&gt; [ 'title' =&gt; 'archivo de registro separado', 'description' =&gt; 'active esta opcin para obtener un archivo de registro de acceso independiente para este dominio.' ], 'domain_editable' =&gt; [ 'title' =&gt; 'permitir editar el dominio', 'desc' =&gt; 'si se establece en s, el cliente puede cambiar varios ajustes del dominio.&lt;br/&gt;si se establece en no, el cliente puede cambiar nada.' ], 'writeaccesslog' =&gt; [ 'title' =&gt; 'escribir un registro de acceso', 'description' =&gt; 'active esta opcin para obtener un archivo de registro de acceso para este dominio.' ], 'writeerrorlog' =&gt; [ 'title' =&gt; 'escribir un registro de errores', 'description' =&gt; 'active esta opcin para obtener un archivo de registro de errores para este dominio.' ], 'phpfpm.ininote' =&gt; 'no todos los valores que quiera definir pueden ser usados en la configuracin del pool php-fpm', 'phpinfo' =&gt; 'phpinfo()', 'selectserveralias' =&gt; 'valor serveralias para el dominio', 'selectserveralias_desc' =&gt; 'elija si froxlor debe crear una entrada comodn (*.dominio.tld), un alias www (www.domain.tld) ningn alias.', 'show_news_feed' =&gt; [ 'title' =&gt; 'mostrar noticias en el panel de administracin', 'description' =&gt; 'activa esta opcin para mostrar las noticias oficiales de froxlor (https://inside.froxlor.org/news/) en tu panel de control perderte nunca informacin importante anuncios de lanzamientos.' ], 'cronsettings' =&gt; 'configuracin de cronjob', 'integritycheck' =&gt; 'validacin de la base de datos', 'integrityname' =&gt; 'nombre', 'integrityresult' =&gt; 'resultado', 'integrityfix' =&gt; 'solucin automtica de problemas', 'customer_show_news_feed' =&gt; 'mostrar noticias en el panel del cliente', 'customer_news_feed_url' =&gt; [ 'title' =&gt; 'utilizar un canal rss personalizado', 'description' =&gt; 'especifique un canal rss personalizado que se mostrar sus clientes en su panel de control.&lt;br/&gt;&lt;small&gt;deje este campo vaco para utilizar el canal de noticias oficial de froxlor (https://inside.froxlor.org/news/).&lt;/small&gt;' ], 'movetoadmin' =&gt; 'mover cliente', 'movecustomertoadmin' =&gt; 'mueve el cliente al administrador/revendedor seleccionado&lt;br/&gt;&lt;small&gt;deja esto vaco para hacer cambios.&lt;br/&gt;si el administrador deseado aparece en la lista, su lmite de clientes ha sido alcanzado.&lt;/small&gt;', 'note' =&gt; 'nota', 'mod_fcgid_umask' =&gt; [ 'title' =&gt; 'mscara (por defecto: 022)' ], 'apcuinfo' =&gt; 'informacin apcu', 'opcacheinfo' =&gt; 'informacin opcache', 'letsencrypt' =&gt; [ 'title' =&gt; 'usar let\'s encrypt', 'description' =&gt; 'obtenga un certificado gratuito de &lt;a href="https://letsencrypt.org"&gt;let\'s encrypt&lt;/a&gt;. el certificado se crear renovar automticamente.&lt;br /&gt;&lt;strong class="text-danger"&gt;atencin:&lt;/strong&gt; si los comodines estn activados, esta opcin se desactivar automticamente.' ], 'autoupdate' =&gt; 'actualizar automticamente', 'server_php' =&gt; 'php', 'dnsenabled' =&gt; 'habilitar editor dns', 'froxlorvhost' =&gt; 'configuracin de froxlor virtualhost', 'hostname' =&gt; 'nombre de host', 'memory' =&gt; 'uso de memoria', 'webserversettings_ssl' =&gt; 'configuracin ssl del servidor web', 'domain_hsts_maxage' =&gt; [ 'title' =&gt; 'seguridad estricta de transporte http (hsts)', 'description' =&gt; 'especifique el valor max-age para la cabecera strict-transport-security&lt;br/&gt;el valor &lt;i&gt;0&lt;/i&gt; desactivar hsts para el dominio. la mayora de los usuarios establecen un valor de &lt;i&gt;31536000&lt;/i&gt; (un ao).' ], 'domain_hsts_incsub' =&gt; [ 'title' =&gt; 'incluir hsts para cualquier subdominio', 'description' =&gt; 'la directiva opcional "includesubdomains", si est presente, indica la ua que la poltica hsts se aplica este host hsts como cualquier subdominio del nombre de dominio del host.' ], 'domain_hsts_preload' =&gt; [ 'title' =&gt; 'incluir dominio en la &lt;a href="https://hstspreload.org/" target="_blank"&gt;lista de precarga&lt;/a&gt; hsts', 'description' =&gt; 'si desea que este dominio se incluya en la lista de precarga hsts mantenida por chrome (y utilizada por firefox safari), active esta opcin.&lt;br /&gt;el envo de la directiva de precarga desde su sitio puede tener consecuencias permanentes e impedir que los usuarios accedan su sitio cualquiera de sus subdominios.&lt;br /&gt;por favor, lea los detalles en &lt;a href="https://hstspreload.org/#removal" target="_blank"&gt;https://hstspreload.org/#removal&lt;/a&gt; antes de enviar la cabecera con "preload".' ], 'domain_ocsp_stapling' =&gt; [ 'title' =&gt; 'engrapado ocsp', 'description' =&gt; 'consulte &lt;a target="_blank" href="https://en.wikipedia.org/wiki/ocsp_stapling"&gt;wikipedia&lt;/a&gt; para una explicacin detallada del grapado ocsp', 'nginx_version_warning' =&gt; '&lt;br /&gt;&lt;strong class="text-danger"&gt;advertencia:&lt;/strong&gt; se requiere la versin 1.3.7 superior de nginx para el grapado ocsp. si su versin es anterior, el servidor web se iniciar correctamente mientras el grapado ocsp est activado!' ], 'domain_http2' =&gt; [ 'title' =&gt; 'soporte http2', 'description' =&gt; 'consulte &lt;a target="_blank" href="https://en.wikipedia.org/wiki/http/2"&gt;wikipedia&lt;/a&gt; para una explicacin detallada de http2' ], 'testmail' =&gt; 'prueba smtp', 'phpsettingsforsubdomains' =&gt; 'aplicar php-config todos los subdominios:', 'plans' =&gt; [ 'name' =&gt; 'nombre del plan', 'description' =&gt; 'descripcin', 'last_update' =&gt; 'ltima actualizacin', 'plans' =&gt; 'planes de alojamiento', 'plan_details' =&gt; 'detalles del plan', 'add' =&gt; 'aadir nuevo plan', 'edit' =&gt; 'editar plan', 'use_plan' =&gt; 'aplicar plan' ], 'notryfiles' =&gt; [ 'title' =&gt; 'no autogenerated try_files', 'description' =&gt; 'diga aqu si desea especificar una directiva try_files personalizada en specialsettings (necesaria para algunos plugins de wordpress, por ejemplo).' ], 'logviewenabled' =&gt; 'habilitar acceso access/error-logs', 'novhostcontainer' =&gt; '&lt;br /&gt;&lt;br /&gt;&lt;small class="text-danger"&gt;ninguna de las ips puertos tiene activada la opcin "crear vhost-container", muchos ajustes aqu estarn disponibles&lt;/small&gt;', 'ownsslvhostsettings' =&gt; 'configuracin propia de ssl vhost', 'domain_override_tls' =&gt; 'anular la configuracin tls del sistema', 'domain_override_tls_addinfo' =&gt; '&lt;br /&gt;&lt;span class="text-danger"&gt;slo se utiliza si la opcin "override system tls settings" est configurada como "yes".&lt;/span&gt;', 'domain_sslenabled' =&gt; 'habilitar el uso de ssl', 'domain_honorcipherorder' =&gt; 'respetar el orden de cifrado (servidor), por defecto &lt;strong&gt;no&lt;/strong&gt;', 'domain_sessiontickets' =&gt; 'habilitar tls sessiontickets (rfc 5077), por defecto &lt;strong&gt;s&lt;/strong&gt;', 'domain_sessionticketsenabled' =&gt; [ 'title' =&gt; 'habilitar el uso de tls sessiontickets globalmente', 'description' =&gt; 'por defecto &lt;strong&gt;s&lt;/strong&gt;&lt;br/&gt;requiere apache-2.4.11+ nginx-1.5.9+' ], 'domaindefaultalias' =&gt; 'valor por defecto de serveralias para nuevos dominios', 'smtpsettings' =&gt; 'configuracin smtp', 'smtptestaddr' =&gt; 'enviar correo de prueba a', 'smtptestnote' =&gt; 'tenga en cuenta que los valores siguientes reflejan su configuracin actual slo pueden ajustarse (vase el enlace en la esquina superior derecha)', 'smtptestsend' =&gt; 'enviar correo de prueba', 'mysqlserver' =&gt; [ 'mysqlserver' =&gt; 'servidor mysql', 'dbserver' =&gt; 'servidor', 'caption' =&gt; 'descripcin', 'host' =&gt; 'nombre de host / ip', 'port' =&gt; 'puerto', 'user' =&gt; 'usuario privilegiado', 'add' =&gt; 'aadir nuevo servidor mysql', 'edit' =&gt; 'editar servidor mysql', 'password' =&gt; 'contrasea de usuario privilegiado', 'password_emptynochange' =&gt; 'nueva contrasea, dejar vaco para ningn cambio', 'allowall' =&gt; [ 'title' =&gt; 'permitir el uso de este servidor todos los clientes existentes actualmente', 'description' =&gt; 'establezca esta opcin en "true" si desea permitir el uso de este servidor de base de datos todos los clientes existentes para que puedan aadir bases de datos en l. esta configuracin es permanente, pero se puede ejecutar varias veces.' ], 'testconn' =&gt; 'probar la conexin al guardar', 'ssl' =&gt; 'utilizar ssl para la conexin al servidor de base de datos', 'ssl_cert_file' =&gt; 'la ruta del archivo la autoridad del certificado ssl', 'verify_ca' =&gt; 'habilitar la verificacin del certificado ssl del servidor' ], 'settings_importfile' =&gt; 'elegir archivo de importacin', 'documentation' =&gt; 'documentacin', 'adminguide' =&gt; 'gua del administrador', 'userguide' =&gt; 'gua del usuario', 'apiguide' =&gt; 'gua de la api' ], 'apcuinfo' =&gt; [ 'clearcache' =&gt; 'borrar cach de apcu', 'generaltitle' =&gt; 'informacin general sobre la cach', 'version' =&gt; 'versin de apcu', 'phpversion' =&gt; 'versin php', 'host' =&gt; 'host apcu', 'sharedmem' =&gt; 'memoria compartida', 'sharedmemval' =&gt; '%d segmento(s) con %s (%s memoria)', 'start' =&gt; 'hora de inicio', 'uptime' =&gt; 'tiempo de actividad', 'upload' =&gt; 'soporte de carga de archivos', 'cachetitle' =&gt; 'informacin de la cach', 'cvar' =&gt; 'variables en cach', 'hit' =&gt; 'aciertos', 'miss' =&gt; 'fallos', 'reqrate' =&gt; 'tasa de peticiones (aciertos, fallos)', 'creqsec' =&gt; 'peticiones de cach/segundo', 'hitrate' =&gt; 'tasa de aciertos', 'missrate' =&gt; 'porcentaje de fallos', 'insrate' =&gt; 'tasa de inserciones', 'cachefull' =&gt; 'recuento de cach llena', 'runtime' =&gt; 'configuracin de tiempo de ejecucin', 'memnote' =&gt; 'uso de memoria', 'total' =&gt; 'total', 'free' =&gt; 'libre', 'used' =&gt; 'usado', 'hitmiss' =&gt; 'aciertos errores', 'detailmem' =&gt; 'uso detallado de memoria fragmentacin', 'fragment' =&gt; 'fragmentacin', 'nofragment' =&gt; 'sin fragmentacin', 'fragments' =&gt; 'fragmentos' ], 'apikeys' =&gt; [ 'no_api_keys' =&gt; 'no se han encontrado claves api', 'key_add' =&gt; 'aadir nueva clave', 'apikey_removed' =&gt; 'la clave api con el id #%s ha sido eliminada con xito', 'apikey_added' =&gt; 'se ha generado correctamente una nueva clave api', 'clicktoview' =&gt; 'haga clic para ver', 'allowed_from' =&gt; 'permitido desde', 'allowed_from_help' =&gt; 'lista separada por comas de direcciones ip / redes.&lt;br /&gt;por defecto est vaco (permitir desde todos).', 'valid_until' =&gt; 'vlido hasta', 'valid_until_help' =&gt; 'fecha hasta la que es vlido, formato aaaa-mm-ddthh:mm' ], 'changepassword' =&gt; [ 'old_password' =&gt; 'contrasea antigua', 'new_password' =&gt; 'nueva contrasea', 'new_password_confirm' =&gt; 'confirme la contrasea', 'new_password_ifnotempty' =&gt; 'nueva contrasea (vaca = sin cambios)', 'also_change_ftp' =&gt; ' cambie tambin la contrasea de la cuenta ftp principal', 'also_change_stats' =&gt; ' cambie tambin la contrasea de la pgina de estadsticas' ], 'cron' =&gt; [ 'cronname' =&gt; 'cronjob-name', 'lastrun' =&gt; 'ltima ejecucin', 'interval' =&gt; 'intervalo', 'isactive' =&gt; 'activado', 'description' =&gt; 'descripcin', 'changewarning' =&gt; 'cambiar estos valores puede tener una causa negativa en el comportamiento de froxlor sus tareas automatizadas.&lt;br/&gt;por favor, slo cambie los valores aqu, si est seguro de lo que est haciendo.' ], 'crondesc' =&gt; [ 'cron_unknown_desc' =&gt; 'no description given', 'cron_tasks' =&gt; 'generacin de archivos de configuracin', 'cron_legacy' =&gt; 'cronjob heredado (antiguo)', 'cron_traffic' =&gt; 'clculo de trfico', 'cron_usage_report' =&gt; 'informes web de trfico', 'cron_mailboxsize' =&gt; 'clculo del tamao del buzn', 'cron_letsencrypt' =&gt; 'actualizacin de certificados let\'s encrypt', 'cron_backup' =&gt; 'procesar tareas de copia de seguridad' ], 'cronjob' =&gt; [ 'cronjobsettings' =&gt; 'configuracin de cronjob', 'cronjobintervalv' =&gt; 'valor del intervalo de tiempo de ejecucin', 'cronjobinterval' =&gt; 'intervalo de ejecucin' ], 'cronjobs' =&gt; [ 'notyetrun' =&gt; 'an ejecutado' ], 'cronmgmt' =&gt; [ 'minutes' =&gt; 'minutos', 'hours' =&gt; 'horas', 'days' =&gt; 'das', 'weeks' =&gt; 'semanas', 'months' =&gt; 'meses' ], 'customer' =&gt; [ 'documentroot' =&gt; 'directorio de inicio', 'name' =&gt; 'nombre', 'firstname' =&gt; 'nombre de pila', 'lastname' =&gt; 'apellidos', 'company' =&gt; 'empresa', 'nameorcompany_desc' =&gt; 'se requiere nombre/apellido empresa', 'street' =&gt; 'calle', 'zipcode' =&gt; 'cdigo postal', 'city' =&gt; 'ciudad', 'phone' =&gt; 'telfono', 'fax' =&gt; 'fax', 'email' =&gt; 'correo electrnico', 'customernumber' =&gt; 'id de cliente', 'diskspace' =&gt; 'espacio web', 'traffic' =&gt; 'trfico', 'mysqls' =&gt; 'bases de datos mysql', 'emails' =&gt; 'direcciones de correo electrnico', 'accounts' =&gt; 'cuentas de correo electrnico', 'forwarders' =&gt; 'remitentes de correo electrnico', 'ftps' =&gt; 'cuentas ftp', 'subdomains' =&gt; 'subdominios', 'domains' =&gt; 'dominios', 'mib' =&gt; 'mib', 'gib' =&gt; 'gib', 'title' =&gt; 'ttulo', 'country' =&gt; 'pas', 'email_quota' =&gt; 'cuota de correo electrnico', 'email_imap' =&gt; 'correo imap', 'email_pop3' =&gt; 'correo electrnico pop3', 'sendinfomail' =&gt; 'enviarme datos por correo electrnico', 'generated_pwd' =&gt; 'sugerencia de contrasea', 'usedmax' =&gt; 'usado / max', 'services' =&gt; 'servicios', 'letsencrypt' =&gt; [ 'title' =&gt; 'usar let\'s encrypt', 'description' =&gt; 'obtenga un certificado gratuito de &lt;a href="https://letsencrypt.org"&gt;let\'s encrypt&lt;/a&gt;. el certificado se crear renovar automticamente.' ], 'selectserveralias_addinfo' =&gt; 'esta opcin se puede configurar al editar el dominio. su valor inicial se hereda del dominio padre.', 'total_diskspace' =&gt; 'espacio total en disco', 'mysqlserver' =&gt; 'servidor mysql utilizable' ], 'diskquota' =&gt; 'cuota', 'dns' =&gt; [ 'destinationip' =&gt; 'ip(s) del dominio', 'standardip' =&gt; 'ip estndar del servidor', 'a_record' =&gt; 'registro (ipv6 opcional)', 'cname_record' =&gt; 'registro cname', 'mxrecords' =&gt; 'definir registros mx', 'standardmx' =&gt; 'registro mx estndar del servidor', 'mxconfig' =&gt; 'registros mx personalizados', 'priority10' =&gt; 'prioridad 10', 'priority20' =&gt; 'prioridad 20', 'txtrecords' =&gt; 'definir registros txt', 'txtexample' =&gt; 'ejemplo (spf-entry):&lt;br/&gt;v=spf1 ip4:xxx.xxx.xx.0/23 -all', 'howitworks' =&gt; 'aqu puedes gestionar las entradas dns para tu dominio. ten en cuenta que froxlor generar automticamente los registros ns/mx/a/aaaa por ti. las entradas personalizadas son preferibles, slo las entradas que falten sern generadas automticamente.' ], 'dnseditor' =&gt; [ 'edit' =&gt; 'editar dns', 'records' =&gt; 'registros', 'notes' =&gt; [ 'a' =&gt; 'direccin ipv4 de 32 bits, usada para mapear nombres de host una direccin ip del host.', 'aaaa' =&gt; 'direccin ipv6 de 128 bits, utilizada para asignar nombres de host una direccin ip del host.', 'caa' =&gt; 'el registro de recursos caa permite al titular de un nombre de dominio dns especificar una varias autoridades de certificacin (ca) autorizadas emitir certificados para ese dominio.&lt;br/&gt;estructura: &lt;code&gt;flag tag[issue|issuewild|iodef|contactmail|contactphone] value&lt;/code&gt;&lt;br/&gt;ejemplo: &lt;code&gt;0 issue "ca.example.net"&lt;br/&gt;&lt;/code&gt; 0 &lt;code&gt;iodef "mailto:security@example.com"&lt;/code&gt;', 'cname' =&gt; 'alias del nombre de dominio, la bsqueda dns continuar reintentando la bsqueda con el nuevo nombre. slo es posible para subdominios.', 'dname' =&gt; 'crea un alias para todo un subrbol del rbol de nombres de dominio', 'loc' =&gt; 'informacin sobre la ubicacin geogrfica de un nombre de dominio.&lt;br/&gt;estructura: &lt;code&gt;( d1 [m1 [s1]] { d2 [m2 [s2]] { alt["m"] [siz["m"] [hp["m"] [vp["m"]]]] )&lt;/code&gt;&lt;br/&gt;descripcin: &lt;code&gt;d1&lt;/code&gt;: [0 . &lt;code&gt;. 90] (grados de latitud) d2: [0 .. 180] (grados de longitud) m1, m2: [0 .. 59] (minutos latitud/longitud) s1, s2: [0 .. 59,999] (segundos latitud/longitud) alt: [-100000.00 .. 42849672.95] por .01 (altitud en metros) siz, hp, vp: [0 .. 90000000.00] (tamao/precisin en metros)&lt;/code&gt;&lt;br/&gt;ejemplo: &lt;code&gt;52 22 23.000 n 4 53 32.000 e -2.00m 0.00m 10000m 10m&lt;/code&gt;', 'mx' =&gt; 'registro de intercambio de correo, asigna un nombre de dominio un servidor de correo para ese dominio.&lt;br/&gt;ejemplo: &lt;code&gt;10 mail.example.com&lt;/code&gt;&lt;br/&gt;nota: para la prioridad, utilice el campo anterior.', 'ns' =&gt; 'delega una zona dns para que utilice los servidores de nombres autoritativos indicados.', 'rp' =&gt; 'registro de persona responsable&lt;br/&gt;estructura: &lt;code&gt;mailbox[sustituir @ por un punto] txt-record-name&lt;/code&gt;&lt;br/&gt;ejemplo: &lt;code&gt;team.froxlor.org. froxlor.org.&lt;/code&gt;', 'srv' =&gt; 'registro de ubicacin de servicio, utilizado para protocolos ms recientes en lugar de crear registros especficos de protocolo como mx.&lt;br/&gt;estructura: &lt;code&gt;priority weight port target&lt;/code&gt;&lt;br/&gt;ejemplo: &lt;code&gt;0 5 5060 sipserver.example.com.&lt;/code&gt;&lt;br/&gt;nota: para la prioridad, utilice el campo anterior.', 'sshfp' =&gt; 'el registro de recursos sshfp se utiliza para publicar huellas digitales de claves de shell seguro (ssh) en el dns.&lt;br/&gt;estructura: &lt;code&gt;tipo de algoritmo huella digital&lt;/code&gt;&lt;br/&gt;algoritmos: 0: reservado &lt;code&gt;, 1: rsa, 2: dsa, 3: ecdsa, 4: ed25519, 6: ed448&lt;/code&gt;&lt;br/&gt;tipos: 0 &lt;code&gt;: reservado, 1: sha-1, 2: sha-256&lt;/code&gt;&lt;br/&gt;ejemplo: &lt;code&gt;2 1 123456789abcdef67890123456789abcdef67890&lt;/code&gt;', 'txt' =&gt; 'texto descriptivo de libre definicin.' ] ], 'domain' =&gt; [ 'openbasedirpath' =&gt; 'ruta openbasedir', 'docroot' =&gt; 'ruta del campo anterior', 'homedir' =&gt; 'directorio de inicio', 'docparent' =&gt; 'directorio padre de la ruta del campo anterior', 'ssl_certificate_placeholder' =&gt; '---- begin certificate---' . php_eol . '[...]' . php_eol . '----end certificate----', 'ssl_key_placeholder' =&gt; '---- begin rsa private key-----' . php_eol . '[...]' . php_eol . '-----end rsa private key-----', ], 'domains' =&gt; [ 'description' =&gt; 'aqu puede crear (sub)dominios cambiar sus rutas.&lt;br/&gt;el sistema necesitar algn tiempo para aplicar la nueva configuracin despus de cada cambio.', 'domainsettings' =&gt; 'configuracin del dominio', 'domainname' =&gt; 'nombre de dominio', 'subdomain_add' =&gt; 'crear subdominio', 'subdomain_edit' =&gt; 'editar (sub)dominio', 'wildcarddomain' =&gt; 'crear como dominio comodn?', 'aliasdomain' =&gt; 'alias para dominio', 'noaliasdomain' =&gt; 'sin alias de dominio', 'hasaliasdomains' =&gt; 'tiene dominio(s) alias', 'statstics' =&gt; 'estadsticas de uso', 'isassigneddomain' =&gt; 'dominio asignado', 'add_date' =&gt; 'aadido froxlor', 'registration_date' =&gt; 'aadido al registro', 'topleveldomain' =&gt; 'top-level-dominio', 'associated_with_domain' =&gt; 'asociado', 'aliasdomains' =&gt; 'alias dominios', 'redirectifpathisurl' =&gt; 'cdigo de redireccin (por defecto: vaco)', 'redirectifpathisurlinfo' =&gt; 'slo tiene que seleccionar una de estas opciones si ha introducido una url como ruta&lt;br/&gt;&lt;strong class="text-danger"&gt;nota:&lt;/strong&gt; los cambios slo se aplican si la ruta indicada es una url.', 'ipandport_multi' =&gt; [ 'title' =&gt; 'direcciones ip', 'description' =&gt; 'especifique una ms direcciones ip para el dominio.&lt;br/&gt;&lt;br/&gt;&lt;div class="text-danger"&gt;nota: las direcciones ip pueden cambiarse cuando el dominio est configurado como &lt;strong&gt;alias-dominio&lt;/strong&gt; de otro dominio.&lt;/div&gt;' ], 'ipandport_ssl_multi' =&gt; [ 'title' =&gt; 'direccin(es) ip ssl' ], 'ssl_redirect' =&gt; [ 'title' =&gt; 'redireccin ssl', 'description' =&gt; 'esta opcin crea redireccionamientos para vhosts ssl de forma que todas las peticiones son redirigidas al vhost ssl.&lt;br/&gt;&lt;br/&gt;p.e. una peticin &lt;strong&gt;http://domain.tld/&lt;/strong&gt; le redirigir &lt;strong&gt;https://domain.tld/&lt;/strong&gt;' ], 'serveraliasoption_wildcard' =&gt; 'comodn (*.dominio.tld)', 'serveraliasoption_www' =&gt; 'www (www.domain.tld)', 'serveraliasoption_none' =&gt; 'sin alias', 'domain_import' =&gt; 'importar dominios', 'import_separator' =&gt; 'separador', 'import_offset' =&gt; 'desplazamiento', 'import_file' =&gt; 'archivo csv', 'import_description' =&gt; 'para obtener informacin detallada sobre la estructura del archivo de importacin sobre cmo realizar la importacin correctamente, visite &lt;a href="https://docs.froxlor.org/latest/admin-guide/domain-import/" target="_blank" class="alert-link"&gt;https://docs.froxlor.org/latest/admin-guide/domain-import/&lt;/a&gt;.', 'ssl_redirect_temporarilydisabled' =&gt; '&lt;br/&gt;la redireccin ssl se desactiva temporalmente mientras se genera un nuevo certificado let\'s encrypt. se volver activar una vez generado el certificado.', 'termination_date' =&gt; 'fecha de terminacin', 'termination_date_overview' =&gt; 'terminado partir de ', 'ssl_certificates' =&gt; 'certificados ssl', 'ssl_certificate_removed' =&gt; 'el certificado con el id #%s ha sido eliminado con xito', 'ssl_certificate_error' =&gt; 'error al leer el certificado para el dominio: %s', 'no_ssl_certificates' =&gt; 'no hay dominios con certificado ssl', 'isaliasdomainof' =&gt; 'es aliasdomain para %s', 'isbinddomain' =&gt; 'crear zona dns', 'dkimenabled' =&gt; 'dkim activado', 'openbasedirenabled' =&gt; 'restriccin de openbasedir', 'hsts' =&gt; 'hsts habilitado', 'aliasdomainid' =&gt; 'id de aliasdominio' ], 'emails' =&gt; [ 'description' =&gt; 'aqu puedes crear modificar tus direcciones de correo electrnico.&lt;br/&gt;una cuenta es como el buzn que tienes delante de casa. si alguien le enva un correo electrnico, ste caer en la cuenta.&lt;br/&gt;&lt;br/&gt;para descargar sus correos electrnicos utilice la siguiente configuracin en su programa de correo: (los datos en &lt;i&gt;cursiva&lt;/i&gt; deben cambiarse por los equivalentes que haya escrito!)&lt;br/&gt;hostname: &lt;b&gt;&lt;i&gt;nombre del dominio&lt;/i&gt;&lt;/b&gt;&lt;br/&gt;username: &lt;b&gt;&lt;i&gt;nombre de la cuenta / direccin de correo electrnico&lt;/i&gt;&lt;/b&gt;&lt;br/&gt;password: &lt;b&gt;&lt;i&gt;la contrasea que haya elegido&lt;/i&gt;&lt;/b&gt;', 'emailaddress' =&gt; 'direccin de correo electrnico', 'emails_add' =&gt; 'crear direccin de correo electrnico', 'emails_edit' =&gt; 'editar direccin de correo electrnico', 'catchall' =&gt; 'catchall', 'iscatchall' =&gt; 'definir como direccin "catchall"?', 'account' =&gt; 'cuenta', 'account_add' =&gt; 'crear cuenta', 'account_delete' =&gt; 'eliminar cuenta', 'from' =&gt; 'fuente', 'to' =&gt; 'destino', 'forwarders' =&gt; 'transitarios', 'forwarder_add' =&gt; 'crear expedidor', 'alternative_emailaddress' =&gt; 'direccin de correo electrnico alternativa', 'quota' =&gt; 'cuota', 'noquota' =&gt; 'sin cuota', 'updatequota' =&gt; 'actualizar cuota', 'quota_edit' =&gt; 'modificar cuota de correo electrnico', 'noemaildomainaddedyet' =&gt; 'an tiene un dominio (de correo electrnico) en su cuenta.', 'back_to_overview' =&gt; 'volver la vista general de dominios', 'accounts' =&gt; 'cuentas', 'emails' =&gt; 'direcciones' ], 'error' =&gt; [ 'error' =&gt; 'error', 'directorymustexist' =&gt; 'el directorio %s debe existir. por favor, cralo con tu cliente ftp.', 'filemustexist' =&gt; 'el archivo %s debe existir.', 'allresourcesused' =&gt; 'ya ha utilizado todos sus recursos.', 'domains_cantdeletemaindomain' =&gt; 'no puede eliminar un dominio asignado.', 'domains_canteditdomain' =&gt; 'no puede editar este dominio. ha sido desactivado por el administrador.', 'domains_cantdeletedomainwithemail' =&gt; 'no puede eliminar un dominio que se utiliza como dominio de correo electrnico. elimine primero todas las direcciones de correo electrnico.', 'firstdeleteallsubdomains' =&gt; 'antes de crear un dominio comodn, debe eliminar todos los subdominios.', 'youhavealreadyacatchallforthisdomain' =&gt; 'ya ha definido un dominio comodn para este dominio.', 'ftp_cantdeletemainaccount' =&gt; 'no puede eliminar su cuenta ftp principal', 'login' =&gt; 'el nombre de usuario la contrasea que introducido son incorrectos. intntalo de nuevo.', 'login_blocked' =&gt; 'esta cuenta ha sido suspendida debido demasiados errores de inicio de sesin. &lt;br/&gt;por favor, intntelo %s nuevo en segundos.', 'notallreqfieldsorerrors' =&gt; 'no ha rellenado todos los campos ha rellenado algunos incorrectamente.', 'oldpasswordnotcorrect' =&gt; 'la contrasea antigua es correcta.', 'youcantallocatemorethanyouhave' =&gt; 'no puede asignarse ms recursos de los que posee.', 'mustbeurl' =&gt; 'no escrito una url vlida completa (por ejemplo http://somedomain.com/error404.htm)', 'invalidpath' =&gt; 'no ha elegido una url vlida (quizs problemas con la lista de direcciones?)', 'stringisempty' =&gt; 'falta informacin en el campo', 'stringiswrong' =&gt; 'campo incorrecto', 'newpasswordconfirmerror' =&gt; 'la nueva contrasea la confirmacin coinciden', 'mydomain' =&gt; 'dominio', 'mydocumentroot' =&gt; 'documentroot', 'loginnameexists' =&gt; 'loginname %s ya existe', 'emailiswrong' =&gt; 'email-address %s contiene caracteres vlidos est incompleto', 'alternativeemailiswrong' =&gt; 'las %s direccin de correo electrnico alternativas dadas para enviar las credenciales parecen ser vlidas', 'loginnameiswrong' =&gt; 'loginname "%s" contiene caracteres ilegales.', 'loginnameiswrong2' =&gt; 'loginname contiene demasiados caracteres. slo se permiten caracteres de %s.', 'userpathcombinationdupe' =&gt; 'la combinacin de nombre de usuario ruta ya existe', 'patherror' =&gt; 'error general la ruta puede estar vaca', 'errordocpathdupe' =&gt; 'la opcin para la %s la ruta ya existe', 'adduserfirst' =&gt; 'por favor, cree primero un cliente', 'domainalreadyexists' =&gt; 'el %s dominio ya est asignado un cliente', 'nolanguageselect' =&gt; 'no se ha seleccionado ningn idioma.', 'nosubjectcreate' =&gt; 'debe definir un asunto para esta plantilla de correo.', 'nomailbodycreate' =&gt; 'debe definir un texto de correo para esta plantilla de correo.', 'templatenotfound' =&gt; 'no se ha encontrado la plantilla.', 'alltemplatesdefined' =&gt; 'no puede definir ms plantillas, todos los idiomas ya estn soportados.', 'wwwnotallowed' =&gt; 'www est permitido para subdominios.', 'subdomainiswrong' =&gt; 'la %s del subdominio contiene caracteres vlidos.', 'domaincantbeempty' =&gt; 'el nombre de dominio puede estar vaco.', 'domainexistalready' =&gt; 'el dominio %s ya existe.', 'domainisaliasorothercustomer' =&gt; 'el dominio alias seleccionado es en mismo un dominio alias, tiene una combinacin ip/puerto diferente pertenece otro cliente.', 'emailexistalready' =&gt; 'la direccin de correo electrnico %s ya existe.', 'maindomainnonexist' =&gt; 'el dominio principal %s existe.', 'destinationnonexist' =&gt; 'por favor, cree su redireccionador en el campo "destino".', 'destinationalreadyexistasmail' =&gt; 'el remitente %s ya existe como direccin de correo electrnico activa.', 'destinationalreadyexist' =&gt; 'ya ha definido un reenviador para "%s".', 'destinationiswrong' =&gt; 'la %s la redireccin contiene caracteres vlidos est incompleta.', 'templatelanguagecombodefined' =&gt; 'la combinacin idioma/plantilla seleccionada ya ha sido definida.', 'templatelanguageinvalid' =&gt; 'el idioma seleccionado existe.', 'ipstillhasdomains' =&gt; 'la combinacin ip/puerto que desea eliminar todava tiene dominios asignados, por favor reasgnelos otras combinaciones ip/puerto antes de eliminar esta combinacin ip/puerto.', 'cantdeletedefaultip' =&gt; 'no puede borrar la combinacin ip/puerto por defecto, por favor haga otra combinacin ip/puerto por defecto para antes de borrar esta combinacin ip/puerto.', 'cantdeletesystemip' =&gt; 'no puede borrar la ltima ip del sistema, cree una nueva combinacin ip/puerto para la ip del sistema cambie la ip del sistema.', 'myipaddress' =&gt; 'ip', 'myport' =&gt; 'puerto', 'myipdefault' =&gt; 'debe seleccionar una combinacin ip/puerto que se convierta en predeterminada.', 'myipnotdouble' =&gt; 'esta combinacin ip/puerto ya existe.', 'admin_domain_emailsystemhostname' =&gt; 'el nombre de host del servidor se puede utilizar como dominio del cliente.', 'cantchangesystemip' =&gt; 'no puede cambiar la ltima ip del sistema, cree otra nueva combinacin ip/puerto para la ip del sistema cambie la ip del sistema.', 'sessiontimeoutiswrong' =&gt; 'slo se permite un "tiempo de espera de sesin" numrico.', 'maxloginattemptsiswrong' =&gt; 'slo se permiten "intentos de inicio de sesin mximos" numricos.', 'deactivatetimiswrong' =&gt; 'slo se permite "tiempo de desactivacin" numrico.', 'accountprefixiswrong' =&gt; 'el "customerprefix" es incorrecto.', 'mysqlprefixiswrong' =&gt; 'el "prefijo sql" es incorrecto.', 'ftpprefixiswrong' =&gt; 'el "prefijo ftp" es incorrecto.', 'ipiswrong' =&gt; 'la "direccin ip" es incorrecta. slo se permite una direccin ip vlida.', 'vmailuidiswrong' =&gt; 'el "mails-uid" es incorrecto. slo se permite un uid numrico.', 'vmailgidiswrong' =&gt; 'el "mails-gid" es incorrecto. slo se permite un gid numrico.', 'adminmailiswrong' =&gt; 'la direccin del remitente es incorrecta. slo se permite una direccin de correo electrnico vlida.', 'pagingiswrong' =&gt; 'el valor "entries per page" es incorrecto. slo se permiten caracteres numricos.', 'phpmyadminiswrong' =&gt; 'el enlace phpmyadmin es un enlace vlido.', 'webmailiswrong' =&gt; 'el enlace webmail es un enlace vlido.', 'webftpiswrong' =&gt; 'el enlace webftp es un enlace vlido.', 'stringformaterror' =&gt; 'el valor del campo "%s" tiene el formato esperado.', 'loginnameisusingprefix' =&gt; 'no puede crear cuentas que empiecen por "%s", ya que este prefijo est configurado para ser utilizado en la asignacin automtica de nombres de cuenta. por favor, introduzca otro nombre de cuenta.', 'loginnameissystemaccount' =&gt; 'la cuenta "%s" ya existe en el sistema se puede utilizar. por favor, introduzca otro nombre de cuenta.', 'youcantdeleteyourself' =&gt; 'no puede borrarse por razones de seguridad.', 'youcanteditallfieldsofyourself' =&gt; 'nota: puede editar todos los campos de su propia cuenta por razones de seguridad.', 'documentrootexists' =&gt; 'el directorio "%s" ya existe para este cliente. por favor, elimnelo antes de aadir el cliente de nuevo.', 'norepymailiswrong' =&gt; 'la direccin "noreply-address" es incorrecta. slo se permite una direccin de correo electrnico vlida.', 'logerror' =&gt; 'log-error: %s', 'nomessagetosend' =&gt; 'no ha introducido ningn mensaje.', 'norecipientsgiven' =&gt; 'no ha especificado ningn destinatario', 'errorsendingmail' =&gt; 'el mensaje "%s" ha fallado', 'errorsendingmailpub' =&gt; 'el mensaje la direccin de correo electrnico indicada ha fallado', 'cannotreaddir' =&gt; 'no se ha podido leer el directorio "%s".', 'invalidip' =&gt; 'direccin ip vlida: %s', 'invalidmysqlhost' =&gt; 'direccin de host mysql vlida: %s', 'cannotuseawstatsandwebalizeratonetime' =&gt; 'no puede activar webalizer awstats al mismo tiempo, por favor elija uno de ellos.', 'cannotwritetologfile' =&gt; 'no se puede abrir el archivo de registro %s para escribir', 'vmailquotawrong' =&gt; 'el quotasize debe ser un nmero positivo.', 'allocatetoomuchquota' =&gt; 'ha intentado asignar la cuota %s mb, pero tiene suficiente.', 'missingfields' =&gt; 'no se han rellenado todos los campos obligatorios.', 'requiredfield' =&gt; 'este campo es obligatorio.', 'accountnotexisting' =&gt; 'la cuenta de correo electrnico indicada existe.', 'nopermissionsorinvalidid' =&gt; 'no tiene permisos suficientes para cambiar esta configuracin se ha introducido un identificador vlido.', 'phpsettingidwrong' =&gt; 'no existe una configuracin php con este id.', 'descriptioninvalid' =&gt; 'la descripcin es demasiado corta, demasiado larga contiene caracteres ilegales.', 'info' =&gt; 'informacin', 'filecontentnotset' =&gt; 'el archivo puede estar vaco.', 'index_file_extension' =&gt; 'la extensin del fichero ndice debe tener entre 1 6 caracteres. la extensin slo puede contener caracteres como a-z, a-z 0-9', 'customerdoesntexist' =&gt; 'el cliente seleccionado existe.', 'admindoesntexist' =&gt; 'el administrador elegido existe.', 'ipportdoesntexist' =&gt; 'la combinacin ip/puerto que ha elegido existe.', 'usernamealreadyexists' =&gt; 'el nombre de usuario %s ya existe.', 'plausibilitychecknotunderstood' =&gt; 'no se ha entendido la respuesta de la comprobacin de plausibilidad.', 'errorwhensaving' =&gt; 'se ha producido un error al guardar la %s campos', 'hiddenfieldvaluechanged' =&gt; 'el valor del campo oculto "%s" ha cambiado al editar la configuracin.&lt;br/&gt;&lt;br/&gt;esto suele ser un gran problema, pero la configuracin se ha podido guardar por este motivo.', 'notrequiredpasswordlength' =&gt; 'la contrasea introducida es demasiado corta. por favor, introduzca al menos caracteres de %s.', 'overviewsettingoptionisnotavalidfield' =&gt; 'ups, un campo que debera mostrarse como una opcin en la vista de configuracin es un tipo exceptuado. puedes culpar los desarrolladores por esto. esto debera ocurrir.', 'pathmaynotcontaincolon' =&gt; 'la ruta introducida debe contener dos puntos (":"). por favor, introduzca un valor de ruta correcto.', 'exception' =&gt; '%s', 'notrequiredpasswordcomplexity' =&gt; 'la complejidad de la contrasea especificada se ha cumplido.&lt;br/&gt;pngase en contacto con su administrador si tiene alguna duda sobre la complejidad especificada.', 'stringerrordocumentnotvalidforlighty' =&gt; 'una cadena como errordocument funciona en lighttpd, por favor especifique una ruta un archivo.', 'urlerrordocumentnotvalidforlighty' =&gt; 'una url como errordocument funciona en lighttpd, por favor especifique una ruta un archivo', 'invaliderrordocumentvalue' =&gt; 'el valor dado como errordocument parece ser un archivo, url cadena vlidos.', 'intvaluetoolow' =&gt; 'el nmero dado es demasiado bajo (campo %s))', 'intvaluetoohigh' =&gt; 'el nmero dado es demasiado alto (campo %s)', 'phpfpmstillenabled' =&gt; 'php-fpm est actualmente activo. desactvelo antes de activar fcgid.', 'fcgidstillenabled' =&gt; 'fcgid est actualmente activo. desactvelo antes de activar php-fpm.', 'domains_cantdeletedomainwithaliases' =&gt; 'no se puede eliminar un dominio que se utiliza para alias. primero debe eliminar los alias.', 'user_banned' =&gt; 'su cuenta ha sido bloqueada. por favor, contacte con su administrador para ms informacin.', 'session_timeout' =&gt; 'valor demasiado bajo', 'session_timeout_desc' =&gt; 'el tiempo de espera de la sesin debe ser inferior 1 minuto.', 'invalidhostname' =&gt; 'el nombre de host debe ser un dominio vlido. puede estar vaco ni estar formado slo por espacios en blanco.', 'operationnotpermitted' =&gt; 'operacin permitida', 'featureisdisabled' =&gt; 'la funcin de %s est desactivada. pngase en contacto con su proveedor de servicios.', 'usercurrentlydeactivated' =&gt; 'el usuario %s est actualmente desactivado', 'setlessthanalreadyused' =&gt; 'no puede establecer menos recursos de \'%s\' de los que este usuario ya ha utilizado&lt;br/&gt;', 'stringmustntbeempty' =&gt; 'el valor del campo %s debe estar vaco', 'sslcertificateismissingprivatekey' =&gt; 'necesita especificar una clave privada para su certificado', 'sslcertificatewrongdomain' =&gt; 'el certificado indicado pertenece este dominio', 'sslcertificateinvalidcert' =&gt; 'el contenido del certificado indicado parece ser un certificado vlido.', 'sslcertificateinvalidcertkeypair' =&gt; 'la clave privada indicada pertenece al certificado en cuestin.', 'sslcertificateinvalidca' =&gt; 'los datos del certificado de la ca parecen ser un certificado vlido.', 'sslcertificateinvalidchain' =&gt; 'los datos de la cadena del certificado parecen ser un certificado vlido.', 'givendirnotallowed' =&gt; 'el directorio indicado en el campo %s est permitido.', 'sslredirectonlypossiblewithsslipport' =&gt; 'el uso de let\'s encrypt slo es posible cuando el dominio tiene asignada al menos una combinacin ip/puerto habilitada para ssl.', 'fcgidstillenableddeadlock' =&gt; 'fcgid est actualmente activo.&lt;br/&gt;por favor, desactvelo antes de cambiar otro servidor web que sea apache2 lighttpd', 'send_report_title' =&gt; 'enviar informe de error', 'send_report_desc' =&gt; 'gracias por informar de este error ayudarnos mejorar froxlor.&lt;br/&gt;este es el correo electrnico que se enviar al equipo de desarrolladores de froxlor:', 'send_report' =&gt; 'enviar informe', 'send_report_error' =&gt; 'error al enviar el informe: &lt;br/&gt;%s', 'notallowedtouseaccounts' =&gt; 'tu cuenta permite usar imap/pop3. puedes aadir cuentas de correo.', 'cannotdeletehostnamephpconfig' =&gt; 'esta configuracin php es usada por el froxlor-vhost puede ser borrada.', 'cannotdeletedefaultphpconfig' =&gt; 'esta configuracin php est establecida por defecto puede ser borrada.', 'passwordshouldnotbeusername' =&gt; 'la contrasea debe ser la misma que el nombre de usuario.', 'no_phpinfo' =&gt; 'lo sentimos, puedo leer phpinfo()', 'moveofcustomerfailed' =&gt; 'el cambio del cliente al administrador/revendedor seleccionado ha fallado. tenga en cuenta que todos los dems cambios en el cliente se aplicaron con xito en esta etapa.&lt;br/&gt;&lt;br/&gt;mensaje de error: %s', 'domain_import_error' =&gt; 'se ha producido el siguiente error al importar dominios: %s', 'fcgidandphpfpmnogoodtogether' =&gt; 'fcgid php-fpm pueden ser activados al mismo tiempo', 'no_apcuinfo' =&gt; 'no hay informacin de cach disponible. apcu parece estar ejecutndose.', 'no_opcacheinfo' =&gt; 'no hay informacin de cach disponible. opcache parece estar ejecutndose.', 'nowildcardwithletsencrypt' =&gt; 'let\'s encrypt puede manejar dominios comodn usando acme en froxlor (requiere dns-challenge), lo siento. por favor, establezca el serveralias www desactvelo completamente.', 'customized_version' =&gt; 'parece que tu instalacin de froxlor ha sido modificada, hay soporte, lo sentimos.', 'autoupdate_0' =&gt; 'error desconocido', 'autoupdate_1' =&gt; 'el ajuste de php allow_url_fopen est desactivado. autoupdate necesita que este ajuste est habilitado en php.ini', 'autoupdate_2' =&gt; 'extensin php zip encontrada, por favor asegrese de que est instalada activada', 'autoupdate_4' =&gt; 'el archivo froxlor pudo ser almacenado en el disco :(', 'autoupdate_5' =&gt; 'version.froxlor.org devolvi valores inaceptables :(', 'autoupdate_6' =&gt; 'whoops, haba una versin (vlida) dada para descargar :(', 'autoupdate_7' =&gt; 'no se pudo encontrar el archivo descargado :(', 'autoupdate_8' =&gt; 'no se ha podido extraer el archivo :(', 'autoupdate_9' =&gt; 'el archivo descargado ha pasado la comprobacin de integridad. por favor, intente actualizar de nuevo.', 'autoupdate_10' =&gt; 'la versin mnima soportada de php es 7.4.0', 'autoupdate_11' =&gt; 'webupdate est desactivado', 'mailaccistobedeleted' =&gt; 'otra cuenta con el mismo nombre (%s) est siendo eliminada por lo tanto puede ser aadida en este momento.', 'dns_domain_nodns' =&gt; 'dns est habilitado para este dominio', 'dns_content_empty' =&gt; 'no hay contenido', 'dns_content_invalid' =&gt; 'el contenido dns es vlido', 'dns_arec_noipv4' =&gt; 'no se ha proporcionado una direccin ip vlida para el registro a.', 'dns_aaaarec_noipv6' =&gt; 'no se ha indicado una direccin ip vlida para el registro aaaa', 'dns_mx_prioempty' =&gt; 'prioridad mx vlida', 'dns_mx_needdom' =&gt; 'el valor de contenido mx debe ser un nombre de dominio vlido.', 'dns_mx_noalias' =&gt; 'el valor de contenido mx puede ser una entrada cname.', 'dns_cname_invaliddom' =&gt; 'nombre de dominio vlido para el registro cname', 'dns_cname_nomorerr' =&gt; 'ya existe un resource-record con el mismo nombre de registro. se puede utilizar como cname.', 'dns_other_nomorerr' =&gt; 'ya existe un registro cname con el mismo nombre de registro. se puede utilizar para otro tipo.', 'dns_ns_invaliddom' =&gt; 'nombre de dominio vlido para el registro ns', 'dns_srv_prioempty' =&gt; 'prioridad srv vlida', 'dns_srv_invalidcontent' =&gt; 'contenido srv vlido, debe contener los campos weight, port target, p.ej: 5 5060 sipserver.ejemplo.com.', 'dns_srv_needdom' =&gt; 'el valor srv target debe ser un nombre de dominio vlido', 'dns_srv_noalias' =&gt; 'el valor srv-target puede ser una entrada cname.', 'dns_duplicate_entry' =&gt; 'el registro ya existe', 'dns_notfoundorallowed' =&gt; 'dominio encontrado sin permiso', 'domain_nopunycode' =&gt; 'no debe especificar punycode (idna). el dominio se convertir automticamente', 'dns_record_toolong' =&gt; 'los registros/etiquetas slo pueden tener un mximo de 63 caracteres', 'noipportgiven' =&gt; 'no se ha especificado ip/puerto', 'jsonextensionnotfound' =&gt; 'esta funcin requiere la extensin php json.', 'cannotdeletesuperadmin' =&gt; 'el primer administrador puede ser eliminado.', 'no_wwwcnamae_ifwwwalias' =&gt; 'no se puede establecer un registro cname para "www" porque el dominio est configurado para generar un alias www. cambie la configuracin "sin alias" "alias comodn".', 'local_group_exists' =&gt; 'el grupo indicado ya existe en el sistema.', 'local_group_invalid' =&gt; 'el nombre del grupo es vlido', 'invaliddnsforletsencrypt' =&gt; 'el dns del dominio incluye ninguna de las direcciones ip seleccionadas. la generacin del certificado let\'s encrypt es posible.', 'notallowedphpconfigused' =&gt; 'intentando usar php-config que est asignado al cliente', 'pathmustberelative' =&gt; 'el usuario tiene permiso para especificar directorios fuera del directorio personal del cliente. por favor, especifique una ruta relativa (sin /).', 'mysqlserverstillhasdbs' =&gt; 'no se puede eliminar el servidor de base de datos de la lista de clientes permitidos, ya que todava hay bases de datos en l.', 'domaincannotbeedited' =&gt; 'no se le permite editar la %s dominio.', 'invalidcronjobintervalvalue' =&gt; 'el intervalo de cronjob debe ser uno de los siguientes: %s' ], 'extras' =&gt; [ 'description' =&gt; 'aqu puede aadir algunos extras, por ejemplo proteccin de directorios.&lt;br/&gt;el sistema necesitar algn tiempo para aplicar la nueva configuracin despus de cada cambio.', 'directoryprotection_add' =&gt; 'aadir proteccin de directorio', 'view_directory' =&gt; 'mostrar el contenido del directorio', 'pathoptions_add' =&gt; 'aadir opciones de ruta', 'directory_browsing' =&gt; 'exploracin del contenido del directorio', 'pathoptions_edit' =&gt; 'editar opciones de ruta', 'error404path' =&gt; '404', 'error403path' =&gt; '403', 'error500path' =&gt; '500', 'error401path' =&gt; '401', 'errordocument404path' =&gt; 'documentoerror 404', 'errordocument403path' =&gt; 'documentoerror 403', 'errordocument500path' =&gt; 'documentoerror 500', 'errordocument401path' =&gt; 'documentoerror 401', 'execute_perl' =&gt; 'ejecutar perl/cgi', 'htpasswdauthname' =&gt; 'razn de autenticacin (authname)', 'directoryprotection_edit' =&gt; 'editar proteccin de directorio', 'path_protection_label' =&gt; '&lt;strong class="text-danger"&gt;importante&lt;/strong&gt;', 'path_protection_info' =&gt; 'le recomendamos encarecidamente que proteja la ruta indicada, consulte "extras" -&gt; "proteccin de directorios".' ], 'ftp' =&gt; [ 'description' =&gt; 'aqu puede crear modificar sus cuentas ftp.&lt;br/&gt;los cambios se realizan al instante las cuentas pueden utilizarse inmediatamente.', 'account_add' =&gt; 'crear cuenta', 'account_edit' =&gt; 'editar cuenta ftp', 'editpassdescription' =&gt; 'establezca una nueva contrasea djela en blanco para cambiarla.' ], 'gender' =&gt; [ 'title' =&gt; 'ttulo', 'male' =&gt; 'sr.', 'female' =&gt; 'sra.', 'undef' =&gt; '' ], 'imprint' =&gt; 'aviso legal', 'index' =&gt; [ 'customerdetails' =&gt; 'datos del cliente', 'accountdetails' =&gt; 'datos de la cuenta' ], 'integrity_check' =&gt; [ 'databasecharset' =&gt; 'juego de caracteres de la base de datos (debe ser utf-8)', 'domainiptable' =&gt; 'referencias ip &lt;-&gt; dominio', 'subdomainsslredirect' =&gt; 'bandera falsa ssl-redirect para dominios ssl', 'froxlorlocalgroupmemberforfcgidphpfpm' =&gt; 'froxlor-usuario en los grupos de clientes (para fcgid/php-fpm)', 'webservergroupmemberforfcgidphpfpm' =&gt; 'webserver-user en los grupos de clientes (para fcgid/php-fpm)', 'subdomainletsencrypt' =&gt; 'los dominios principales sin puerto ssl asignado tienen subdominios con redireccin ssl activa' ], 'logger' =&gt; [ 'date' =&gt; 'fecha', 'type' =&gt; 'tipo', 'action' =&gt; 'accin', 'user' =&gt; 'usuario', 'truncate' =&gt; 'registro vaco', 'reseller' =&gt; 'revendedor', 'admin' =&gt; 'administrador', 'cron' =&gt; 'cronjob', 'login' =&gt; 'inicio de sesin', 'intern' =&gt; 'interno', 'unknown' =&gt; 'desconocido' ], 'login' =&gt; [ 'username' =&gt; 'nombre de usuario', 'password' =&gt; 'contrasea', 'language' =&gt; 'idioma', 'login' =&gt; 'inicio de sesin', 'logout' =&gt; 'cierre de sesin', 'profile_lng' =&gt; 'idioma del perfil', 'welcomemsg' =&gt; 'inicie sesin para acceder su cuenta.', 'forgotpwd' =&gt; 'ha olvidado su contrasea?', 'presend' =&gt; 'restablecer contrasea', 'email' =&gt; 'correo electrnico', 'remind' =&gt; 'restablecer mi contrasea', 'usernotfound' =&gt; 'usuario encontrado', 'backtologin' =&gt; 'volver al inicio de sesin', 'combination_not_found' =&gt; 'no se ha encontrado la combinacin de usuario direccin de correo electrnico.', '2fa' =&gt; 'autenticacin de dos factores (2fa)', '2facode' =&gt; 'introduzca el cdigo 2fa' ], 'mails' =&gt; [ 'pop_success' =&gt; [ 'mailbody' =&gt; 'hola,\\nsu cuenta de correo {email} configurado correctamente.\\neste es un correo creado\\nautomticamente, por favor conteste!\\nsu atentamente, su administrador', 'subject' =&gt; 'cuenta de correo configurada correctamente' ], 'createcustomer' =&gt; [ 'mailbody' =&gt; 'hola {salutation}, aqu estn los datos de su cuenta: nombre de usuario: {username}: {password}, su administrador.', 'subject' =&gt; 'informacin de la cuenta' ], 'pop_success_alternative' =&gt; [ 'mailbody' =&gt; 'hola {salutation}, su cuenta de correo {email} se ha configurado correctamente. su contrasea es {password}. este es un correo creado automticamente, por favor conteste. atentamente, su administrador.', 'subject' =&gt; 'cuenta de correo configurada correctamente' ], 'password_reset' =&gt; [ 'subject' =&gt; 'restablecer contrasea', 'mailbody' =&gt; 'hola {salutation}, aqu est su enlace para establecer una nueva contrasea. este enlace es vlido durante las prximas 24 horas. {link}, su administrador.' ], 'new_database_by_customer' =&gt; [ 'subject' =&gt; '[nueva base de datos creada', 'mailbody' =&gt; 'hola {cust_name}, acabas de aadir una nueva base de datos. aqu est la informacin introducida: nombre de base de datos: {db_name} contrasea: {db_pass} descripcin: {db_desc} nombre de host de base de datos: {db_srv} phpmyadmin: {pma_uri} atentamente, su administrador' ], 'new_ftpaccount_by_customer' =&gt; [ 'subject' =&gt; 'nuevo usuario ftp creado', 'mailbody' =&gt; 'hola {cust_name} acabas de aadir un nuevo usuario ftp. aqu est la informacin introducida: nombre de usuario: {usr_name} contrasea: {usr_pass} ruta: {usr_path} atentamente, su administrador' ], 'trafficmaxpercent' =&gt; [ 'mailbody' =&gt; 'estimado {salutation}, ha utilizado {trafficused} del {max_percent} de su {traffic} disponible de trfico.', 'subject' =&gt; 'alcanzando su lmite de trfico' ], 'diskmaxpercent' =&gt; [ 'mailbody' =&gt; 'estimado {salutation}, ha utilizado el {diskused} de su {diskavailable} disponible de espacio en disco. esto es ms del {max_percent}.', 'subject' =&gt; 'alcanzando el lmite de espacio en disco' ], '2fa' =&gt; [ 'mailbody' =&gt; 'hola, su cdigo de acceso 2fa es..: {code}. este es un correo creado automticamente, por favor responda. atentamente, su administrador.', 'subject' =&gt; 'froxlor - cdigo 2fa' ] ], 'menue' =&gt; [ 'main' =&gt; [ 'main' =&gt; 'principal', 'changepassword' =&gt; 'cambiar contrasea', 'changelanguage' =&gt; 'cambiar idioma', 'username' =&gt; 'iniciar sesin como ', 'changetheme' =&gt; 'cambiar tema', 'apihelp' =&gt; 'ayuda api', 'apikeys' =&gt; 'claves de la api' ], 'email' =&gt; [ 'email' =&gt; 'correo electrnico', 'emails' =&gt; 'direcciones', 'webmail' =&gt; 'correo web', 'emailsoverview' =&gt; 'vista general de dominios de correo electrnico' ], 'mysql' =&gt; [ 'mysql' =&gt; 'mysql', 'databases' =&gt; 'bases de datos', 'phpmyadmin' =&gt; 'phpmyadmin' ], 'domains' =&gt; [ 'domains' =&gt; 'dominios', 'settings' =&gt; 'vista general de dominios' ], 'ftp' =&gt; [ 'ftp' =&gt; 'ftp', 'accounts' =&gt; 'cuentas', 'webftp' =&gt; 'webftp' ], 'extras' =&gt; [ 'extras' =&gt; 'extras', 'directoryprotection' =&gt; 'proteccin de directorios', 'pathoptions' =&gt; 'opciones de ruta', 'export' =&gt; 'exportacin de datos' ], 'traffic' =&gt; [ 'traffic' =&gt; 'trfico', 'current' =&gt; 'mes en curso', 'overview' =&gt; 'trfico total' ], 'phpsettings' =&gt; [ 'maintitle' =&gt; 'configuraciones php', 'fpmdaemons' =&gt; 'versiones de php-fpm' ], 'logger' =&gt; [ 'logger' =&gt; 'registro del sistema' ] ], 'message' =&gt; [ 'norecipients' =&gt; 'no se ha enviado ningn correo electrnico porque hay destinatarios en la base de datos', 'success' =&gt; 'mensaje enviado correctamente los destinatarios de %s', ], 'mysql' =&gt; [ 'databasename' =&gt; 'usuario/nombre de la base de datos', 'databasedescription' =&gt; 'descripcin de la base de datos', 'database_create' =&gt; 'crear base de datos', 'description' =&gt; 'aqu puede crear modificar sus bases de datos mysql.&lt;br/&gt;los cambios se realizan al instante la base de datos se puede utilizar inmediatamente.&lt;br/&gt;en el men de la izquierda encontrar la herramienta phpmyadmin con la que puede administrar fcilmente su base de datos.&lt;br/&gt;&lt;br/&gt;para utilizar sus bases de datos en sus propios scripts php utilice los siguientes ajustes: (los datos en &lt;i&gt;cursiva&lt;/i&gt; tienen que cambiarse por los equivalentes que haya escrito!)&lt;br/&gt;nombre de host: &lt;b&gt;&lt;sql_host/&gt;&lt;/b&gt;&lt;br/&gt;nombre de usuario: &lt;b&gt;&lt;i&gt;databasename&lt;/i&gt;&lt;/b&gt;&lt;br/&gt;contrasea: &lt;b&gt;&lt;i&gt;la contrasea que hayas elegido&lt;/i&gt;&lt;/b&gt;&lt;br/&gt;base de datos: &lt;b&gt;&lt;i&gt;databasename&lt;/i&gt;&lt;/b&gt;', 'mysql_server' =&gt; 'servidor mysql', 'database_edit' =&gt; 'editar base de datos', 'size' =&gt; 'tamao', 'privileged_user' =&gt; 'usuario privilegiado de la base de datos', 'privileged_passwd' =&gt; 'contrasea para usuario privilegiado', 'unprivileged_passwd' =&gt; 'contrasea para usuario sin privilegios', 'mysql_ssl_ca_file' =&gt; 'certificado del servidor ssl', 'mysql_ssl_verify_server_certificate' =&gt; 'verificar certificado de servidor ssl' ], 'opcacheinfo' =&gt; [ 'generaltitle' =&gt; 'informacin general', 'resetcache' =&gt; 'restablecer opcache', 'version' =&gt; 'versin de opcache', 'phpversion' =&gt; 'versin php', 'runtimeconf' =&gt; 'configuracin de tiempo de ejecucin', 'start' =&gt; 'hora de inicio', 'lastreset' =&gt; 'ltimo reinicio', 'oomrestarts' =&gt; 'recuento de reinicios oom', 'hashrestarts' =&gt; 'recuento de reinicios hash', 'manualrestarts' =&gt; 'recuento de reinicios manuales', 'hitsc' =&gt; 'nmero de aciertos', 'missc' =&gt; 'faltas', 'blmissc' =&gt; 'lista negra', 'status' =&gt; 'estado', 'never' =&gt; 'nunca', 'enabled' =&gt; 'opcache activado', 'cachefull' =&gt; 'cach llena', 'restartpending' =&gt; 'reinicio pendiente', 'restartinprogress' =&gt; 'reinicio en curso', 'cachedscripts' =&gt; 'recuento de scripts en cach', 'memusage' =&gt; 'uso de memoria', 'totalmem' =&gt; 'memoria total', 'usedmem' =&gt; 'memoria utilizada', 'freemem' =&gt; 'memoria libre', 'wastedmem' =&gt; 'memoria desperdiciada', 'maxkey' =&gt; 'teclas mximas', 'usedkey' =&gt; 'teclas usadas', 'wastedkey' =&gt; 'teclas desperdiciadas', 'strinterning' =&gt; 'intercalacin de cadenas', 'strcount' =&gt; 'recuento de cadenas', 'keystat' =&gt; 'estadstica de claves en cach', 'used' =&gt; 'usado', 'free' =&gt; 'libre', 'blacklist' =&gt; 'lista negra', 'novalue' =&gt; '&lt;i&gt;sin valor&lt;/i&gt;', 'true' =&gt; '&lt;i&gt;verdadero&lt;/i&gt;', 'false' =&gt; '&lt;i&gt;falso&lt;/i&gt;', 'funcsavail' =&gt; 'funciones disponibles' ], 'panel' =&gt; [ 'edit' =&gt; 'editar', 'delete' =&gt; 'eliminar', 'create' =&gt; 'crear', 'save' =&gt; 'guardar', 'yes' =&gt; 's', 'no' =&gt; 'no', 'emptyfornochanges' =&gt; 'vaco para ningn cambio', 'emptyfordefault' =&gt; 'vaco para valores por defecto', 'path' =&gt; 'ruta', 'toggle' =&gt; 'conmutar', 'next' =&gt; 'siguiente', 'dirsmissing' =&gt; 'no se puede encontrar leer el directorio!', 'unlimited' =&gt; '', 'urloverridespath' =&gt; 'url (anula la ruta)', 'pathorurl' =&gt; 'ruta url', 'ascending' =&gt; 'ascendente', 'descending' =&gt; 'descendente', 'search' =&gt; 'buscar en', 'used' =&gt; 'utilizada', 'translator' =&gt; 'traductor', 'reset' =&gt; 'descartar cambios', 'pathdescription' =&gt; 'si el directorio existe, se crear automticamente.', 'pathdescriptionex' =&gt; '&lt;br/&gt;&lt;br/&gt;&lt;span class="text-danger"&gt;nota:&lt;/span&gt; la ruta &lt;code&gt;/&lt;/code&gt; est permitida debido la configuracin administrativa, se establecer automticamente en &lt;code&gt;/elegido.subdominio.tld/&lt;/code&gt; si se establece en otro directorio.', 'pathdescriptionsubdomain' =&gt; 'si el directorio existe, se crear automticamente.&lt;br/&gt;&lt;br/&gt;si desea una redireccin otro dominio, esta entrada debe empezar por http:// https://.&lt;br/&gt;&lt;br/&gt;si la url termina en / se considera una carpeta, si no, se trata como archivo.', 'back' =&gt; 'volver', 'reseller' =&gt; 'revendedor', 'admin' =&gt; 'admin', 'customer' =&gt; 'cliente/s', 'send' =&gt; 'enviar', 'nosslipsavailable' =&gt; 'actualmente hay combinaciones ip/puerto ssl para este servidor', 'backtooverview' =&gt; 'volver la vista general', 'dateformat' =&gt; 'aaaa-mm-dd', 'dateformat_function' =&gt; 'y-m-d', 'timeformat_function' =&gt; 'h:i:s', 'default' =&gt; 'por defecto', 'never' =&gt; 'nunca', 'active' =&gt; 'activo', 'please_choose' =&gt; 'seleccione una opcin', 'allow_modifications' =&gt; 'permitir modificaciones', 'megabyte' =&gt; 'megabyte', 'not_supported' =&gt; 'no soportado en: ', 'view' =&gt; 'ver', 'toomanydirs' =&gt; 'demasiados subdirectorios. volver la seleccin manual de ruta.', 'abort' =&gt; 'abortar', 'not_activated' =&gt; 'no activado', 'off' =&gt; 'desactivado', 'options' =&gt; 'opciones', 'neverloggedin' =&gt; 'an se ha iniciado sesin', 'descriptionerrordocument' =&gt; 'puede ser una url, la ruta un archivo simplemente una cadena rodeada de " "&lt;br/&gt;djelo vaco para utilizar el valor predeterminado del servidor.', 'unlock' =&gt; 'desbloquear', 'theme' =&gt; 'tema', 'variable' =&gt; 'variable', 'description' =&gt; 'descripcin', 'cancel' =&gt; 'cancelar', 'ssleditor' =&gt; 'configuracin ssl para este dominio', 'ssleditor_infoshared' =&gt; 'actualmente usando el certificado del dominio padre', 'ssleditor_infoglobal' =&gt; 'actualmente usando certificado global', 'dashboard' =&gt; 'panel de control', 'assigned' =&gt; 'asignado', 'available' =&gt; 'disponible', 'news' =&gt; 'noticias', 'newsfeed_disabled' =&gt; 'la fuente de noticias est desactivada. haga clic en el icono de edicin para ir la configuracin.', 'ftpdesc' =&gt; 'descripcin de ftp', 'letsencrypt' =&gt; 'usando let\'s encrypt', 'set' =&gt; 'aplicar', 'shell' =&gt; 'shell', 'backuppath' =&gt; [ 'title' =&gt; 'ruta de destino de la copia de seguridad', 'description' =&gt; 'esta es la ruta donde se almacenarn las copias de seguridad. si se selecciona la copia de seguridad de los datos web, todos los archivos de la carpeta de inicio se almacenan excluyendo la carpeta de copia de seguridad especificada aqu.' ], 'none_value' =&gt; 'ninguno', 'viewlogs' =&gt; 'ver archivos de registro', 'not_configured' =&gt; 'el sistema est configurado. pulse aqu para ir la configuracin.', 'ihave_configured' =&gt; 'he configurado los servicios', 'system_is_configured' =&gt; '&lt;i class="fa-solid fa-circle-exclamation me-1"/&gt;el sistema ya est configurado', 'settings_before_configuration' =&gt; 'por favor, asegrese de ajustar la configuracin antes de configurar los servicios aqu', 'image_field_delete' =&gt; 'borrar la imagen actual existente', 'usage_statistics' =&gt; 'uso de recursos', 'security_question' =&gt; 'cuestin de seguridad', 'listing_empty' =&gt; 'no se han encontrado entradas', 'unspecified' =&gt; 'sin especificar', 'settingsmode' =&gt; 'modo', 'settingsmodebasic' =&gt; 'bsico', 'settingsmodeadvanced' =&gt; 'avanzado', 'settingsmodetoggle' =&gt; 'haga clic para cambiar el modo', 'modalclose' =&gt; 'cerrar', 'managetablecolumnsmodal' =&gt; [ 'title' =&gt; 'administrar columnas de la tabla', 'description' =&gt; 'aqu puede personalizar las columnas visibles' ], 'mandatoryfield' =&gt; 'campo obligatorio', 'select_all' =&gt; 'seleccionar todo', 'unselect_all' =&gt; 'deseleccionar todo', 'searchtablecolumnsmodal' =&gt; [ 'title' =&gt; 'buscar en campos', 'description' =&gt; 'seleccione el campo en el que desea buscar' ], 'upload_import' =&gt; 'cargar e importar' ], 'phpfpm' =&gt; [ 'vhost_httpuser' =&gt; 'usuario local usar para php-fpm (froxlor vhost)', 'vhost_httpgroup' =&gt; 'grupo local usar para php-fpm (froxlor vhost)', 'ownvhost' =&gt; [ 'title' =&gt; 'habilitar php-fpm para el vhost de froxlor', 'description' =&gt; 'si est habilitado, froxlor tambin se ejecutar bajo un usuario local' ], 'use_mod_proxy' =&gt; [ 'title' =&gt; 'usar mod_proxy / mod_proxy_fcgi', 'description' =&gt; '&lt;strong class="text-danger"&gt;debe activarse cuando se use debian 9.x (stretch) posterior&lt;/strong&gt;. activar para usar php-fpm via mod_proxy_fcgi. requiere al menos apache-2.4.9' ], 'ini_flags' =&gt; 'introduzca posibles &lt;strong&gt;php_flags&lt;/strong&gt;para php.ini. una entrada por lnea', 'ini_values' =&gt; 'introduzca posibles &lt;strong&gt;php_values&lt;/strong&gt;para php.ini. una entrada por lnea', 'ini_admin_flags' =&gt; 'introduzca posibles &lt;strong&gt;php_admin_flags&lt;/strong&gt;para php.ini. una entrada por lnea', 'ini_admin_values' =&gt; 'introduzca posibles &lt;strong&gt;php_admin_values&lt;/strong&gt;para php.ini. una entrada por lnea' ], 'privacy' =&gt; 'poltica de privacidad', 'pwdreminder' =&gt; [ 'success' =&gt; 'restablecimiento de contrasea solicitado con xito. por favor, siga las instrucciones del correo electrnico que ha recibido.', 'notallowed' =&gt; 'usuario desconocido el restablecimiento de contrasea est desactivado', 'changed' =&gt; 'su contrasea se ha actualizado correctamente. ya puede iniciar sesin con su nueva contrasea.', 'wrongcode' =&gt; 'lo sentimos, su cdigo de activacin existe ya ha caducado.', 'choosenew' =&gt; 'establecer nueva contrasea' ], 'question' =&gt; [ 'question' =&gt; 'cuestin de seguridad', 'admin_customer_reallydelete' =&gt; 'realmente desea eliminar el cliente %s? se puede deshacer.', 'admin_domain_reallydelete' =&gt; 'realmente quieres borrar el dominio %s?', 'admin_domain_reallydisablesecuritysetting' =&gt; 'realmente quieres desactivar esta configuracin de seguridad openbasedir?', 'admin_admin_reallydelete' =&gt; 'realmente quieres borrar el admin %s? todos los clientes dominios sern reasignados tu cuenta.', 'admin_template_reallydelete' =&gt; 'realmente quieres borrar la plantilla \'%s\'?', 'domains_reallydelete' =&gt; 'realmente quieres borrar el dominio %s?', 'email_reallydelete' =&gt; 'realmente quieres borrar la direccin de email %s?', 'email_reallydelete_account' =&gt; 'realmente quieres borrar la cuenta de correo de %s?', 'email_reallydelete_forwarder' =&gt; 'realmente quieres borrar el forwarder %s?', 'extras_reallydelete' =&gt; 'realmente quieres borrar la proteccin de directorio de %s?', 'extras_reallydelete_pathoptions' =&gt; 'realmente quieres borrar las opciones de ruta de %s?', 'ftp_reallydelete' =&gt; 'realmente quieres borrar la cuenta ftp %s?', 'mysql_reallydelete' =&gt; 'realmente quieres borrar la base de datos %s? esto se puede deshacer.', 'admin_configs_reallyrebuild' =&gt; 'realmente quieres reconstruir todos los archivos de configuracin?', 'admin_customer_alsoremovefiles' =&gt; 'quitar tambin los archivos de usuario?', 'admin_customer_alsoremovemail' =&gt; 'eliminar completamente los datos de correo electrnico del sistema de archivos?', 'admin_customer_alsoremoveftphomedir' =&gt; 'quitar tambin el directorio del usuario ftp?', 'admin_ip_reallydelete' =&gt; 'realmente quieres borrar la direccin ip %s?', 'admin_domain_reallydocrootoutofcustomerroot' =&gt; 'ests seguro de que quieres que la raz del documento para este dominio est dentro de la raz del cliente?', 'admin_counters_reallyupdate' =&gt; 'realmente quiere recalcular el uso de recursos?', 'admin_cleartextmailpws_reallywipe' =&gt; 'realmente quiere borrar todas las contraseas encriptadas de las cuentas de correo de la tabla mail_users? esto se puede revertir. la opcin de almacenar las contraseas de correo electrnico sin cifrar tambin se desactivar.', 'logger_reallytruncate' =&gt; 'realmente quieres truncar la tabla "%s"?', 'admin_quotas_reallywipe' =&gt; 'realmente desea borrar todas las cuotas de la tabla mail_users? esto se puede revertir.', 'admin_quotas_reallyenforce' =&gt; 'realmente desea aplicar la cuota por defecto todos los usuarios? esto se puede revertir.', 'phpsetting_reallydelete' =&gt; 'realmente desea eliminar esta configuracin? todos los dominios que usen esta configuracin sern cambiados la configuracin por defecto.', 'fpmsetting_reallydelete' =&gt; 'realmente desea eliminar esta configuracin de php-fpm? todas las configuraciones de php que utilicen estos ajustes se cambiarn la configuracin por defecto.', 'customer_reallyunlock' =&gt; 'realmente quieres desbloquear al cliente %s?', 'admin_integritycheck_reallyfix' =&gt; 'realmente quieres intentar arreglar todos los problemas de integridad de la base de datos automticamente?', 'plan_reallydelete' =&gt; 'de verdad quieres eliminar el plan de alojamiento %s?', 'apikey_reallydelete' =&gt; 'realmente quieres borrar esta api-key?', 'apikey_reallyadd' =&gt; 'realmente quieres crear una nueva api-key?', 'dnsentry_reallydelete' =&gt; 'realmente desea eliminar esta entrada de zona?', 'certificate_reallydelete' =&gt; 'realmente quieres borrar este certificado?', 'cache_reallydelete' =&gt; 'realmente quieres borrar la cach?' ], 'redirect_desc' =&gt; [ 'rc_default' =&gt; 'por defecto', 'rc_movedperm' =&gt; 'movido permanentemente', 'rc_found' =&gt; 'encontrado', 'rc_seeother' =&gt; 'ver otro', 'rc_tempred' =&gt; 'redireccin temporal' ], 'serversettings' =&gt; [ 'session_timeout' =&gt; [ 'title' =&gt; 'tiempo de espera de la sesin', 'description' =&gt; 'cunto tiempo tiene que estar inactivo un usuario para que se invalide la sesin (segundos)?' ], 'accountprefix' =&gt; [ 'title' =&gt; 'prefijo de cliente', 'description' =&gt; 'qu prefijo deben tener las cuentas de cliente?' ], 'mysqlprefix' =&gt; [ 'title' =&gt; 'prefijo sql', 'description' =&gt; 'qu prefijo deben tener las cuentas mysql?&lt;br/&gt;utilice "random" como valor para obtener un prefijo aleatorio de 3 dgitos&lt;br/&gt;utilice "dbname" como valor, se utiliza un campo de nombre de base de datos junto con el nombre del cliente como prefijo.' ], 'ftpprefix' =&gt; [ 'title' =&gt; 'prefijo ftp', 'description' =&gt; 'qu prefijo deben tener las cuentas ftp?&lt;br/&gt;&lt;b&gt;si cambias esto, tambin tendrs que cambiar la consulta sql quota en el archivo de configuracin del servidor ftp en caso de que lo utilices&lt;/b&gt;. ' ], 'documentroot_prefix' =&gt; [ 'title' =&gt; 'directorio de inicio', 'description' =&gt; 'dnde deben almacenarse todos los directorios de inicio?' ], 'logfiles_directory' =&gt; [ 'title' =&gt; 'directorio logfiles', 'description' =&gt; 'dnde deben almacenarse todos los archivos de registro?' ], 'logfiles_script' =&gt; [ 'title' =&gt; 'script personalizado al que enviar los archivos de registro', 'description' =&gt; 'puede especificar un script aqu utilizar los marcadores de posicin &lt;strong&gt;{logfile}, {domain} {customer}&lt;/strong&gt; si es necesario. en caso de que desee utilizarlo, deber activar tambin la opcin &lt;strong&gt;pipe webserver logfiles&lt;/strong&gt;. es necesario el prefijo pipe.' ], 'logfiles_format' =&gt; [ 'title' =&gt; 'formato de registro de acceso', 'description' =&gt; 'introduzca aqu un formato de registro personalizado de acuerdo con las especificaciones de su servidor web, deje vaco por defecto. dependiendo de su formato, la cadena debe estar entre comillas.&lt;br/&gt;si se utiliza con nginx, se ver como &lt;i&gt;log_format&lt;/i&gt; &lt;i&gt;frx_custom&lt;/i&gt; &lt;i&gt; {configured_value}&lt;/i&gt;.&lt;br/&gt;si se utiliza con apache, se ver como &lt;i&gt;logformat {configured_value} frx_custom&lt;/i&gt;.&lt;br/&gt;&lt;strong&gt;atencin&lt;/strong&gt;: se comprobar si el cdigo contiene errores. si contiene errores, el servidor web podra volver arrancar!' ], 'logfiles_type' =&gt; [ 'title' =&gt; 'tipo de registro de acceso', 'description' =&gt; 'elija aqu entre &lt;strong&gt;combinado&lt;/strong&gt; &lt;strong&gt;vhost_combinado&lt;/strong&gt;.' ], 'logfiles_piped' =&gt; [ 'title' =&gt; 'canalizar los archivos de registro del servidor web al script especificado (ver arriba)', 'description' =&gt; 'si utiliza un script personalizado para los archivos de registro, deber activarlo para que se ejecute.' ], 'ipaddress' =&gt; [ 'title' =&gt; 'direccin ip', 'description' =&gt; 'cul es la direccin ip principal de este servidor?' ], 'hostname' =&gt; [ 'title' =&gt; 'nombre de host', 'description' =&gt; 'cul es el nombre de host de este servidor?' ], 'apachereload_command' =&gt; [ 'title' =&gt; 'comando de recarga del servidor web', 'description' =&gt; 'cul es el comando del servidor web para recargar los archivos de configuracin?' ], 'bindenable' =&gt; [ 'title' =&gt; 'habilitar servidor de nombres', 'description' =&gt; 'aqu se puede habilitar deshabilitar globalmente el servidor de nombres.' ], 'bindconf_directory' =&gt; [ 'title' =&gt; 'directorio de configuracin del servidor dns', 'description' =&gt; 'dnde deben guardarse los archivos de configuracin del servidor dns?' ], 'bindreload_command' =&gt; [ 'title' =&gt; 'comando de recarga del servidor dns', 'description' =&gt; 'cul es el comando para recargar el demonio del servidor dns?' ], 'vmail_uid' =&gt; [ 'title' =&gt; 'mails-uid', 'description' =&gt; 'qu userid deben tener los correos?' ], 'vmail_gid' =&gt; [ 'title' =&gt; 'mails-gid', 'description' =&gt; 'qu groupid debe tener mails?' ], 'vmail_homedir' =&gt; [ 'title' =&gt; 'mails-homedir', 'description' =&gt; 'dnde deberan almacenarse todos los correos?' ], 'adminmail' =&gt; [ 'title' =&gt; 'remitente', 'description' =&gt; 'cul es la direccin del remitente para los emails enviados desde el panel?' ], 'phpmyadmin_url' =&gt; [ 'title' =&gt; 'url de phpmyadmin', 'description' =&gt; 'cul es la url de phpmyadmin? (debe empezar por http(s)://)' ], 'webmail_url' =&gt; [ 'title' =&gt; 'url de webmail', 'description' =&gt; 'cul es la url de webmail? (debe empezar por http(s)://)' ], 'webftp_url' =&gt; [ 'title' =&gt; 'url de webftp', 'description' =&gt; 'cul es la url de webftp? (debe empezar por http(s)://)' ], 'language' =&gt; [ 'description' =&gt; 'cul es el lenguaje estndar de su servidor?' ], 'maxloginattempts' =&gt; [ 'title' =&gt; 'nmero mximo de intentos de inicio de sesin', 'description' =&gt; 'nmero mximo de intentos de inicio de sesin tras los cuales se desactiva la cuenta.' ], 'deactivatetime' =&gt; [ 'title' =&gt; 'tiempo de desactivacin', 'description' =&gt; 'tiempo (seg.) que se desactiva una cuenta despus de demasiados intentos de inicio de sesin.' ], 'pathedit' =&gt; [ 'title' =&gt; 'tipo de entrada de ruta', 'description' =&gt; 'debe seleccionarse una ruta mediante un men desplegable mediante un campo de entrada?' ], 'nameservers' =&gt; [ 'title' =&gt; 'servidores de nombres', 'description' =&gt; 'una lista separada por comas que contiene los nombres de host de todos los servidores de nombres. el primero ser el principal.' ], 'mxservers' =&gt; [ 'title' =&gt; 'servidores mx', 'description' =&gt; 'una lista separada por comas que contiene un par de un nmero un nombre de host separados por espacios en blanco (por ejemplo, \'10 mx.ejemplo.com\') que contiene los servidores mx.' ], 'paging' =&gt; [ 'title' =&gt; 'entradas por pgina', 'description' =&gt; 'cuntas entradas se mostrarn en una pgina? (0 = desactivar la paginacin)' ], 'defaultip' =&gt; [ 'title' =&gt; 'ip/puerto por defecto', 'description' =&gt; 'seleccione todas las direcciones ip que desee utilizar como predeterminadas para los nuevos dominios.' ], 'defaultsslip' =&gt; [ 'title' =&gt; 'ip/puerto ssl por defecto', 'description' =&gt; 'seleccione todas las direcciones ip con ssl habilitado que desee utilizar por defecto para los nuevos dominios' ], 'phpappendopenbasedir' =&gt; [ 'title' =&gt; 'rutas aadir openbasedir', 'description' =&gt; 'estas rutas (separadas por dos puntos) se aadirn la declaracin openbasedir en cada contenedor vhost.' ], 'natsorting' =&gt; [ 'title' =&gt; 'usar ordenacin humana natural en la vista de lista', 'description' =&gt; 'ordena las listas como web1 -&gt; web2 -&gt; web11 en lugar de web1 -&gt; web11 -&gt; web2.' ], 'deactivateddocroot' =&gt; [ 'title' =&gt; 'docroot para usuarios desactivados', 'description' =&gt; 'cuando un usuario es desactivado esta ruta es usada como su docroot. dejar vaco para crear ningn vhost.' ], 'mailpwcleartext' =&gt; [ 'title' =&gt; 'guardar tambin las contraseas de las cuentas de correo sin cifrar en la base de datos', 'description' =&gt; 'si esta opcin est activada, todas las contraseas sern guardadas sin encriptar (texto claro, legible para cualquiera con acceso la base de datos) en la tabla mail_users. active esta opcin slo si desea utilizar sasl.' ], 'ftpdomain' =&gt; [ 'title' =&gt; 'cuentas ftp @dominio', 'description' =&gt; 'los clientes pueden crear cuentas ftp user@customerdomain?' ], 'mod_fcgid' =&gt; [ 'title' =&gt; 'activar fcgid', 'description' =&gt; 'use esto para ejecutar php con la cuenta de usuario correspondiente.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;esto necesita una configuracin especial del servidor web para apache, vea &lt;a target="_blank" href="https://docs.froxlor.org/latest/admin-guide/configuration/fcgid/"&gt;fcgid - manual&lt;/a&gt;&lt;/b&gt;', 'configdir' =&gt; [ 'title' =&gt; 'directorio de configuracin', 'description' =&gt; 'dnde deben guardarse todos los archivos de configuracin fcgid? si utiliza un binario suexec autocompilado, que es la situacin normal, esta ruta debe estar bajo /var/www/&lt;br/&gt;&lt;br/&gt;&lt;div class="text-danger"&gt;nota: el contenido de esta carpeta se borra regularmente, que evite almacenar datos manualmente.&lt;/div&gt;' ], 'tmpdir' =&gt; [ 'title' =&gt; 'directorio temporal', 'description' =&gt; 'dnde deben almacenarse los directorios temporales' ], 'starter' =&gt; [ 'title' =&gt; 'procesos por dominio', 'description' =&gt; 'cuntos procesos deberan iniciarse/permitirse por dominio? se recomienda el valor 0 porque php gestionar entonces la cantidad de procesos por mismo de forma muy eficiente.' ], 'wrapper' =&gt; [ 'title' =&gt; 'wrapper en vhosts', 'description' =&gt; 'cmo debe incluirse el wrapper en los vhosts' ], 'peardir' =&gt; [ 'title' =&gt; 'directorios globales de pear', 'description' =&gt; 'qu directorios globales de pear deben ser reemplazados en cada configuracin php.ini? los diferentes directorios deben estar separados por dos puntos.' ], 'maxrequests' =&gt; [ 'title' =&gt; 'nmero mximo de peticiones por dominio', 'description' =&gt; 'cuntas peticiones deben permitirse por dominio?' ], 'defaultini' =&gt; 'configuracin php por defecto para nuevos dominios', 'defaultini_ownvhost' =&gt; 'configuracin php por defecto para froxlor-vhost', 'idle_timeout' =&gt; [ 'title' =&gt; 'tiempo de espera', 'description' =&gt; 'configuracin de tiempo de espera para mod fastcgi.' ] ], 'sendalternativemail' =&gt; [ 'title' =&gt; 'utilizar una direccin de correo electrnico alternativa', 'description' =&gt; 'enviar la contrasea una direccin diferente durante la creacin de la cuenta de correo electrnico.' ], 'apacheconf_vhost' =&gt; [ 'title' =&gt; 'archivo/nombre de directorio de configuracin del servidor web vhost', 'description' =&gt; 'dnde debe guardarse la configuracin del vhost? puede especificar aqu un archivo (todos los vhosts en un archivo) un directorio (cada vhost en su propio archivo).' ], 'apacheconf_diroptions' =&gt; [ 'title' =&gt; 'archivo/nombre de directorio de configuracin de diropciones del servidor web', 'description' =&gt; 'dnde debe almacenarse la configuracin de diroptions? puede especificar un archivo (todas las diropciones en un archivo) directorio (cada diropcin en su propio archivo) aqu.' ], 'apacheconf_htpasswddir' =&gt; [ 'title' =&gt; 'webserver htpasswd dirname', 'description' =&gt; 'dnde deben guardarse los archivos htpasswd para la proteccin de directorios?' ], 'mysql_access_host' =&gt; [ 'title' =&gt; 'mysql-access-hosts', 'description' =&gt; 'una lista separada por comas de los hosts desde los que se debe permitir los usuarios conectarse al servidor mysql. para permitir una subred es vlida la sintaxis netmask cidr.' ], 'webalizer_quiet' =&gt; [ 'title' =&gt; 'salida de webalizer', 'description' =&gt; 'verbosidad del programa webalizer' ], 'logger' =&gt; [ 'enable' =&gt; 'registro activado/desactivado', 'severity' =&gt; 'nivel de registro', 'types' =&gt; [ 'title' =&gt; 'tipo(s) de registro', 'description' =&gt; 'especifique los tipos de registro. para seleccionar varios tipos, mantenga pulsada la tecla ctrl mientras selecciona.&lt;br/&gt;los tipos de registro disponibles son: syslog, file, mysql' ], 'logfile' =&gt; [ 'title' =&gt; 'nombre del archivo de registro', 'description' =&gt; 'slo se utiliza si log-type incluye "file". este archivo se crear en froxlor/logs/. esta carpeta est protegida contra el acceso pblico.' ], 'logcron' =&gt; 'log cronjobs', 'logcronoption' =&gt; [ 'never' =&gt; 'nunca', 'once' =&gt; 'una vez', 'always' =&gt; 'siempre' ] ], 'ssl' =&gt; [ 'use_ssl' =&gt; [ 'title' =&gt; 'activar uso de ssl', 'description' =&gt; 'marque esta opcin si desea utilizar ssl para su servidor web' ], 'ssl_cert_file' =&gt; [ 'title' =&gt; 'ruta al certificado ssl', 'description' =&gt; 'especifique la ruta incluyendo el nombre del archivo .crt .pem (certificado principal)' ], 'openssl_cnf' =&gt; 'valores predeterminados para crear el archivo cert', 'ssl_key_file' =&gt; [ 'title' =&gt; 'ruta al archivo de claves ssl', 'description' =&gt; 'especifique la ruta incluyendo el nombre de archivo para el archivo de clave privada (.key principalmente)' ], 'ssl_ca_file' =&gt; [ 'title' =&gt; 'ruta al certificado ssl ca (opcional)', 'description' =&gt; 'autenticacin del cliente, configure esto slo si sabe lo que es.' ], 'ssl_cipher_list' =&gt; [ 'title' =&gt; 'configure los cifrados ssl permitidos', 'description' =&gt; 'esta es una lista de cifradores que quiere (o quiere) usar cuando hable ssl. para una lista de cifradores cmo incluirlos/excluirlos, vea las secciones "cipher list format" "cipher strings" en &lt;a href="https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html"&gt;la pgina man de cifradores&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;el valor por defecto es:&lt;/b&gt;&lt;pre&gt;ecdh+aesgcm:ecdh+aes256:!anull:!md5:!dss:!dh:!aes128&lt;/pre&gt;' ], 'apache24_ocsp_cache_path' =&gt; [ 'title' =&gt; 'apache 2.4: ruta la cach de grapado ocsp', 'description' =&gt; 'configura la cach utilizada para almacenar las respuestas ocsp que se incluyen en los handshakes tls.' ], 'ssl_protocols' =&gt; [ 'title' =&gt; 'configurar la versin del protocolo tls', 'description' =&gt; 'esta es una lista de protocolos ssl que quiere (o quiere) usar cuando use ssl. &lt;b&gt;nota:&lt;/b&gt; es posible que algunos navegadores antiguos admitan las versiones de protocolo ms recientes.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;el valor predeterminado es:&lt;/b&gt;&lt;pre&gt;tlsv1.2&lt;/pre&gt;' ], 'tlsv13_cipher_list' =&gt; [ 'title' =&gt; 'configurar cifrados explcitos tlsv1.3 si se utilizan', 'description' =&gt; 'esta es una lista de cifradores que desea (o desea) utilizar cuando hable tlsv1.3. para una lista de cifradores como incluirlos/excluirlos, vea &lt;a href="https://wiki.openssl.org/index.php/tls1.3"&gt;los documentos para tlsv1.3&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;el valor por defecto es vaco&lt;/b&gt;' ] ], 'default_vhostconf' =&gt; [ 'title' =&gt; 'configuracin vhost por defecto', 'description' =&gt; 'el contenido de este campo se incluir en este contenedor ip/port vhost directamente. puede utilizar las siguientes variables:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (si procede)&lt;br/&gt; atencin: se comprobar si el cdigo contiene errores. si contiene errores, el servidor web podra volver arrancar!' ], 'apache_globaldiropt' =&gt; [ 'title' =&gt; 'opciones de directorio para customer-prefix', 'description' =&gt; 'el contenido de este campo se incluir en la configuracin de apache 05_froxlor_dirfix_nofcgid.conf. si est vaco, se usar el valor por defecto:&lt;br/&gt;&lt;br/&gt;apache &gt;=2.4&lt;br/&gt;&lt;code&gt;require granted&lt;br/&gt;allowoverride all&lt;/code&gt;&lt;br/&gt;&lt;br/&gt;apache &lt;=2.2&lt;br/&gt;&lt;code&gt;order allow,deny&lt;br/&gt;allow all&lt;/code&gt;' ], 'default_vhostconf_domain' =&gt; [ 'description' =&gt; 'el contenido de este campo se incluir directamente en el contenedor vhost del dominio. puede utilizar las siguientes variables:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (si procede)&lt;br/&gt; atencin: se comprobar si el cdigo contiene errores. si contiene errores, el servidor web podra volver arrancar!' ], 'decimal_places' =&gt; 'nmero de decimales en la salida de trfico/espacio web', 'selfdns' =&gt; [ 'title' =&gt; 'configuracin dns del dominio del cliente' ], 'selfdnscustomer' =&gt; [ 'title' =&gt; 'permitir los clientes editar la configuracin dns del dominio' ], 'unix_names' =&gt; [ 'title' =&gt; 'utilizar nombres de usuario compatibles con unix', 'description' =&gt; 'permite utilizar &lt;strong&gt;-&lt;/strong&gt; &lt;strong&gt;_&lt;/strong&gt; en los nombres de usuario si &lt;strong&gt;no&lt;/strong&gt;' ], 'allow_password_reset' =&gt; [ 'title' =&gt; 'permitir que los clientes restablezcan la contrasea', 'description' =&gt; 'los clientes pueden restablecer su contrasea se les enviar un enlace de activacin su direccin de correo electrnico.' ], 'allow_password_reset_admin' =&gt; [ 'title' =&gt; 'permitir que los administradores restablezcan la contrasea', 'description' =&gt; 'los administradores/revendedores pueden restablecer su contrasea se les enviar un enlace de activacin su direccin de correo electrnico.' ], 'mail_quota' =&gt; [ 'title' =&gt; 'cuota de buzn', 'description' =&gt; 'la cuota por defecto para los nuevos buzones creados (megabyte).' ], 'mail_quota_enabled' =&gt; [ 'title' =&gt; 'usar mailbox-quota para clientes', 'description' =&gt; 'activar para utilizar cuotas en los buzones de correo. por defecto es &lt;b&gt;no&lt;/b&gt; ya que esto requiere una configuracin especial.', 'removelink' =&gt; 'haga clic aqu para borrar todas las cuotas de las cuentas de correo.', 'enforcelink' =&gt; 'haga clic aqu para aplicar la cuota por defecto todas las cuentas de correo de los usuarios.' ], 'index_file_extension' =&gt; [ 'description' =&gt; 'qu extensin de archivo debe utilizarse para el archivo de ndice en los directorios de clientes recin creados? esta extensin de archivo se utilizar si usted uno de sus administradores ha creado su propia plantilla de archivo de ndice.', 'title' =&gt; 'extensin de archivo para el archivo de ndice en directorios de clientes recin creados' ], 'session_allow_multiple_login' =&gt; [ 'title' =&gt; 'permitir inicio de sesin mltiple', 'description' =&gt; 'si se activa, un usuario puede iniciar sesin varias veces.' ], 'panel_allow_domain_change_admin' =&gt; [ 'title' =&gt; 'permitir mover dominios entre administradores', 'description' =&gt; 'si est activado puede cambiar el admin de un dominio en domainsettings.&lt;br/&gt;&lt;b&gt;atencin:&lt;/b&gt; si un cliente est asignado al mismo administrador que el dominio, el administrador puede ver todos los dems dominios de ese cliente!' ], 'panel_allow_domain_change_customer' =&gt; [ 'title' =&gt; 'permitir mover dominios entre clientes', 'description' =&gt; 'si est activado puedes cambiar el cliente de un dominio en domainsettings.&lt;br/&gt;&lt;b&gt;atencin:&lt;/b&gt; froxlor cambia el documentroot al homedir por defecto del nuevo cliente (+ carpeta de dominio si est activado)' ], 'specialsettingsforsubdomains' =&gt; [ 'description' =&gt; 'en caso afirmativo, estos ajustes personalizados de vhost se aadirn todos los subdominios; en caso negativo, se eliminarn los ajustes especiales de subdominio.' ], 'panel_password_min_length' =&gt; [ 'title' =&gt; 'longitud mnima de contrasea', 'description' =&gt; 'aqu puede establecer una longitud mnima para las contraseas. 0\' significa que se requiere longitud mnima.' ], 'system_store_index_file_subs' =&gt; [ 'title' =&gt; 'almacenar el fichero ndice por defecto tambin en las nuevas subcarpetas', 'description' =&gt; 'si se activa, el archivo de ndice por defecto se almacena en cada ruta de subdominio recin creada (no si la carpeta ya existe).' ], 'adminmail_return' =&gt; [ 'title' =&gt; 'direccin de respuesta', 'description' =&gt; 'defina una direccin de email como direccin de respuesta para los emails enviados por el panel.' ], 'adminmail_defname' =&gt; 'nombre del remitente del e-mail del panel', 'stdsubdomainhost' =&gt; [ 'title' =&gt; 'subdominio estndar del cliente', 'description' =&gt; 'qu nombre de host debe usarse para crear subdominios estndar para el cliente. si est vaco, se utiliza el nombre de host del sistema.' ], 'awstats_path' =&gt; 'ruta awstats \'awstats_buildstaticpages.pl\'', 'awstats_conf' =&gt; 'ruta de configuracin de awstats', 'defaultttl' =&gt; 'ttl de dominio para bind en segundos (por defecto \'604800\' = 1 semana)', 'defaultwebsrverrhandler_enabled' =&gt; 'habilitar documentos de error por defecto para todos los clientes', 'defaultwebsrverrhandler_err401' =&gt; [ 'title' =&gt; 'archivo/url para error 401', 'description' =&gt; '&lt;div class="text-danger"&gt;no soportado en: lighttpd&lt;/div&gt;' ], 'defaultwebsrverrhandler_err403' =&gt; [ 'title' =&gt; 'archivo/url para error 403', 'description' =&gt; '&lt;div class="text-danger"&gt;no soportado en: lighttpd&lt;/div&gt;' ], 'defaultwebsrverrhandler_err404' =&gt; 'archivo/url para error 404', 'defaultwebsrverrhandler_err500' =&gt; [ 'title' =&gt; 'archivo/url para error 500', 'description' =&gt; '&lt;div class="text-danger"&gt;no soportado en: lighttpd&lt;/div&gt;' ], 'ftpserver' =&gt; [ 'desc' =&gt; 'si se selecciona pureftpd, los archivos .ftpquota para cuotas de usuario se crean actualizan diariamente' ], 'customredirect_enabled' =&gt; [ 'title' =&gt; 'permitir redireccionamientos de clientes', 'description' =&gt; 'permitir los clientes elegir el cdigo http-status para las redirecciones que se utilizarn' ], 'customredirect_default' =&gt; [ 'title' =&gt; 'redireccin por defecto', 'description' =&gt; 'establece el cdigo de redireccin por defecto que se utilizar si el cliente lo establece por mismo' ], 'mail_also_with_mxservers' =&gt; 'crear mail-, imap-, pop3- smtp-"a record" tambin con mx-servers set', 'froxlordirectlyviahostname' =&gt; 'acceder froxlor directamente travs del nombre de host', 'panel_password_regex' =&gt; [ 'title' =&gt; 'expresin regular para contraseas', 'description' =&gt; 'aqu puede establecer una expresin regular para la complejidad de las contraseas.&lt;br/&gt;empty = specific requirement' ], 'perl_path' =&gt; [ 'title' =&gt; 'ruta perl', 'description' =&gt; 'por defecto es /usr/bin/perl' ], 'mod_fcgid_ownvhost' =&gt; [ 'title' =&gt; 'habilitar fcgid para el vhost de froxlor', 'description' =&gt; 'si est habilitado, froxlor tambin se ejecutar bajo un usuario local' ], 'perl' =&gt; [ 'suexecworkaround' =&gt; [ 'title' =&gt; 'habilitar solucin suexec', 'description' =&gt; 'habilitar slo si los directorios del cliente estn dentro de la ruta apache suexec.&lt;br/&gt;si est habilitado, froxlor generar un enlace simblico desde el directorio del cliente habilitado para perl + /cgi-bin/ la ruta dada.&lt;br/&gt;tenga en cuenta que perl slo funcionar en el subdirectorio de carpetas /cgi-bin/ en la carpeta en (como lo hace sin esta solucin!)' ], 'suexeccgipath' =&gt; [ 'title' =&gt; 'ruta para los enlaces simblicos de directorio habilitados para perl del cliente', 'description' =&gt; 'slo necesita configurar esto si la solucin de suexec est activada.&lt;br/&gt;atencin: asegrese de que esta ruta est dentro de la ruta de suexec de lo contrario esta solucin es intil.' ] ], 'awstats_awstatspath' =&gt; 'ruta awstats \'awstats.pl\'.', 'awstats_icons' =&gt; [ 'title' =&gt; 'ruta la carpeta de iconos de awstats', 'description' =&gt; 'e.g. /usr/share/awstats/htdocs/icon/' ], 'login_domain_login' =&gt; 'permitir login con dominios', 'perl_server' =&gt; [ 'title' =&gt; 'ubicacin del socket del servidor perl', 'description' =&gt; 'puede encontrar una gua sencilla en: &lt;a target="blank" href="https://www.nginx.com/resources/wiki/start/topics/examples/fcgiwrap/"&gt;nginx.com&lt;/a&gt;' ], 'nginx_php_backend' =&gt; [ 'title' =&gt; 'nginx php backend', 'description' =&gt; 'aqu es donde el proceso php est escuchando peticiones de nginx, puede ser un socket unix de combinacin ip:port&lt;br/&gt;*no se usa con php-fpm' ], 'phpreload_command' =&gt; [ 'title' =&gt; 'comando php reload', 'description' =&gt; 'se usa para recargar el backend php si se usa alguno&lt;br/&gt;por defecto: en blanco&lt;br/&gt;*no se usa con php-fpm' ], 'phpfpm' =&gt; [ 'title' =&gt; 'habilitar php-fpm', 'description' =&gt; '&lt;b&gt;esto necesita una configuracin especial del servidor web ver &lt;a target="_blank" href="https://docs.froxlor.org/latest/admin-guide/configuration/php-fpm/"&gt;manual php-fpm&lt;/a&gt;&lt;/b&gt;' ], 'phpfpm_settings' =&gt; [ 'configdir' =&gt; 'directorio de configuracin de php-fpm', 'aliasconfigdir' =&gt; 'directorio alias de configuracin de php-fpm', 'reload' =&gt; 'comando de reinicio de php-fpm', 'pm' =&gt; 'control del gestor de procesos (pm)', 'max_children' =&gt; [ 'title' =&gt; 'nmero de procesos hijo', 'description' =&gt; 'el nmero de procesos hijo ser creados cuando pm est en \'static\' el nmero mximo de procesos hijo ser creados cuando pm est en \'dynamic/ondemand\'&lt;br/&gt;equivalente php_fcgi_children' ], 'start_servers' =&gt; [ 'title' =&gt; 'el nmero de procesos hijo creados al inicio', 'description' =&gt; 'nota: slo se usa cuando pm est configurado como \'dynamic' ], 'min_spare_servers' =&gt; [ 'title' =&gt; 'el nmero mnimo deseado de procesos de servidor inactivos', 'description' =&gt; 'nota: slo se usa cuando pm es \'dynamic\'&lt;br/&gt;nota: obligatorio cuando pm es \'dynamic' ], 'max_spare_servers' =&gt; [ 'title' =&gt; 'el nmero mximo deseado de procesos de servidor inactivos', 'description' =&gt; 'nota: slo se utiliza cuando pm tiene el valor "dynamic".&lt;br/&gt;nota: obligatorio cuando pm tiene el valor "dynamic".' ], 'max_requests' =&gt; [ 'title' =&gt; 'peticiones por hijo antes de respawning', 'description' =&gt; 'para un procesamiento infinito de peticiones especifique \'0\'. equivalente php_fcgi_max_requests.' ], 'idle_timeout' =&gt; [ 'title' =&gt; 'tiempo de espera', 'description' =&gt; 'configuracin de tiempo de espera para php fpm fastcgi.' ], 'ipcdir' =&gt; [ 'title' =&gt; 'directorio ipc fastcgi', 'description' =&gt; 'el directorio donde los sockets php-fpm sern almacenados por el servidor web.&lt;br/&gt;este directorio debe ser legible para el servidor web.' ], 'limit_extensions' =&gt; [ 'title' =&gt; 'extensiones permitidas', 'description' =&gt; 'limita las extensiones del script principal que fpm permitir analizar. esto puede evitar errores de configuracin en el servidor web. slo debe limitar fpm extensiones .php para evitar que usuarios maliciosos utilicen otras extensiones para ejecutar cdigo php. valor por defecto: .php' ], 'envpath' =&gt; 'rutas aadir al entorno path. dejar vaco para ninguna variable de entorno path', 'override_fpmconfig' =&gt; 'anular la configuracin de fpm-daemon (pm, max_children, etc.)', 'override_fpmconfig_addinfo' =&gt; '&lt;br/&gt;&lt;span class="text-danger"&gt;slo se usa si "override fpm-daemon settings" est en "yes"&lt;/span&gt;', 'restart_note' =&gt; 'atencin: la configuracin ser revisada por errores. si contiene errores, php-fpm podra arrancar de nuevo.', 'custom_config' =&gt; [ 'title' =&gt; 'configuracin personalizada', 'description' =&gt; 'agregue configuracin personalizada cada instancia de versin de php-fpm, por ejemplo &lt;i&gt;pm.status_path = /status&lt;/i&gt; para monitoreo. las variables de abajo pueden ser usadas aqu. &lt;strong&gt;atencin: la configuracin ser revisada por errores. si contiene errores, php-fpm podra arrancar de nuevo!&lt;/strong&gt;' ], 'allow_all_customers' =&gt; [ 'title' =&gt; 'asigne esta configuracin todos los clientes existentes', 'description' =&gt; 'establzcalo en "true" si desea asignar esta configuracin todos los clientes existentes para que puedan utilizarla. esta configuracin es permanente, pero puede ejecutarse varias veces.' ] ], 'report' =&gt; [ 'report' =&gt; 'habilitar el envo de informes sobre el uso de la web el trfico', 'webmax' =&gt; [ 'title' =&gt; 'nivel de advertencia en porcentaje para el espacio web', 'description' =&gt; 'los valores vlidos son 0 hasta 150. establecer este valor 0 desactiva este informe.' ], 'trafficmax' =&gt; [ 'title' =&gt; 'nivel de advertencia en porcentaje para el trfico', 'description' =&gt; 'los valores vlidos son de 0 150. el valor 0 desactiva este informe.' ] ], 'dropdown' =&gt; 'desplegable', 'manual' =&gt; 'manual', 'default_theme' =&gt; 'tema por defecto', 'validate_domain' =&gt; 'validar nombres de dominio', 'diskquota_enabled' =&gt; 'cuota activada?', 'diskquota_repquota_path' =&gt; [ 'description' =&gt; 'ruta repquota' ], 'diskquota_quotatool_path' =&gt; [ 'description' =&gt; 'ruta quotatool' ], 'diskquota_customer_partition' =&gt; [ 'description' =&gt; 'particin en la que se almacenan los archivos del cliente' ], 'vmail_maildirname' =&gt; [ 'title' =&gt; 'nombre del maildir', 'description' =&gt; 'directorio maildir en la cuenta del usuario. normalmente \'maildir\', en algunas implementaciones \'.maildir\', directamente en el directorio del usuario si se deja en blanco.' ], 'catchall_enabled' =&gt; [ 'title' =&gt; 'utilizar catchall', 'description' =&gt; 'quiere proporcionar sus clientes la funcin catchall?' ], 'apache_24' =&gt; [ 'title' =&gt; 'utilice las modificaciones para apache 2.4', 'description' =&gt; '&lt;strong class="text-danger"&gt;atencin:&lt;/strong&gt; utilcelo slo si tiene instalada la versin 2.4 superior de apache&lt;br/&gt;de lo contrario su servidor web podr arrancar' ], 'nginx_fastcgiparams' =&gt; [ 'title' =&gt; 'ruta al archivo fastcgi_params', 'description' =&gt; 'especifique la ruta al archivo fastcgi_params de nginx incluyendo el nombre de archivo' ], 'documentroot_use_default_value' =&gt; [ 'title' =&gt; 'usar el nombre de dominio como valor por defecto para la ruta documentroot', 'description' =&gt; 'si est habilitado la ruta documentroot est vaca, el valor por defecto ser el (sub)nombre de dominio.&lt;br/&gt;&lt;br/&gt;ejemplos: &lt;br/&gt;/var/clientes/nombre_cliente/ejemplo.com/&lt;br/&gt;/var/clientes/nombre_cliente/subdominio.ejemplo.com/' ], 'panel_phpconfigs_hidesubdomains' =&gt; [ 'title' =&gt; 'ocultar subdominios en la vista general de configuracin php', 'description' =&gt; 'si se activa, los subdominios de los clientes se mostrarn en la vista general de configuraciones php, slo se mostrar el nmero de subdominios.&lt;br/&gt;&lt;br/&gt;nota: esto slo es visible si ha activado fcgid php-fpm.' ], 'panel_phpconfigs_hidestdsubdomain' =&gt; [ 'title' =&gt; 'ocultar subdominios estndar en la vista general de configuraciones php', 'description' =&gt; 'si se activa, los subdominios estndar de los clientes se mostrarn en la vista general de configuraciones php&lt;br/&gt;&lt;br/&gt;nota: esto slo es visible si ha activado fcgid php-fpm.' ], 'passwordcryptfunc' =&gt; [ 'title' =&gt; 'elija el mtodo de cifrado de contraseas utilizar' ], 'systemdefault' =&gt; 'sistema por defecto', 'panel_allow_theme_change_admin' =&gt; 'permitir los administradores cambiar el tema', 'panel_allow_theme_change_customer' =&gt; 'permitir los clientes cambiar el tema', 'axfrservers' =&gt; [ 'title' =&gt; 'servidores axfr', 'description' =&gt; 'una lista separada por comas de direcciones ip permitidas para transferir (axfr) zonas dns.' ], 'powerdns_mode' =&gt; [ 'title' =&gt; 'modo de funcionamiento powerdns', 'description' =&gt; 'seleccione el modo powedns: nativo para replicacin (predeterminado) / maestro si se necesita replicacin dns.' ], 'customerssl_directory' =&gt; [ 'title' =&gt; 'webserver customer-ssl certificates-directory', 'description' =&gt; 'dnde deben crearse los certificados ssl especificados por el cliente?&lt;br/&gt;&lt;br/&gt;&lt;div class="text-danger"&gt;nota: el contenido de esta carpeta se borra con regularidad, que evite almacenar datos manualmente.&lt;/div&gt;' ], 'allow_error_report_admin' =&gt; [ 'title' =&gt; 'permitir los administradores/revendedores informar de errores en la base de datos froxlor', 'description' =&gt; 'nota: nunca nos enves datos personales (de clientes)!' ], 'allow_error_report_customer' =&gt; [ 'title' =&gt; 'permitir los clientes informar de errores en la base de datos froxlor', 'description' =&gt; 'nota: nos enve nunca datos personales (de clientes)!' ], 'mailtraffic_enabled' =&gt; [ 'title' =&gt; 'analizar el trfico de correo', 'description' =&gt; 'permitir el anlisis de los registros del servidor de correo para calcular el trfico' ], 'mdaserver' =&gt; [ 'title' =&gt; 'tipo de mda', 'description' =&gt; 'tipo de servidor de entrega de correo' ], 'mdalog' =&gt; [ 'title' =&gt; 'registro mda', 'description' =&gt; 'archivo de registro del mail delivery server' ], 'mtaserver' =&gt; [ 'title' =&gt; 'tipo de mta', 'description' =&gt; 'tipo de agente de transferencia de correo' ], 'mtalog' =&gt; [ 'title' =&gt; 'registro mta', 'description' =&gt; 'archivo de registro del agente de transferencia de correo' ], 'system_cronconfig' =&gt; [ 'title' =&gt; 'archivo de configuracin de cron', 'description' =&gt; 'ruta al archivo de configuracin del servicio cron. este archivo ser actualizado regular automticamente por froxlor.&lt;br/&gt;nota: por favor &lt;b&gt;asegrese&lt;/b&gt; de usar el mismo nombre de archivo que para el froxlor cronjob principal (por defecto: /etc/cron.d/froxlor)!&lt;br/&gt;&lt;br/&gt;si est usando &lt;b&gt;freebsd&lt;/b&gt;, por favor especifique &lt;i&gt;/etc/crontab&lt;/i&gt; aqu!' ], 'system_crondreload' =&gt; [ 'title' =&gt; 'comando cron-daemon reload', 'description' =&gt; 'especifique el comando ejecutar para recargar el cron-daemon de su sistema' ], 'system_croncmdline' =&gt; [ 'title' =&gt; 'comando de ejecucin de cron (php-binario)', 'description' =&gt; 'comando para ejecutar nuestros cronjobs. cmbielo slo si sabe lo que est haciendo (por defecto: "/usr/bin/nice -n 5 /usr/bin/php -q").' ], 'system_cron_allowautoupdate' =&gt; [ 'title' =&gt; 'permitir la actualizacin automtica de la base de datos', 'description' =&gt; '&lt;div class="text-danger"&gt;&lt;b&gt;atencin:&lt;/b&gt;&lt;/div&gt; esta configuracin permite al cronjob saltarse la comprobacin de versin de los archivos froxlors la base de datos ejecuta la actualizacin de la base de datos en caso de que ocurra un desajuste de versin.&lt;br/&gt;&lt;br/&gt;&lt;div class="text-danger"&gt;auto-update siempre establecer valores por defecto para nuevas configuraciones cambios. esto puede ser siempre adecuado para su sistema. por favor, pinselo dos veces antes de activar esta opcin&lt;/div&gt;' ], 'dns_createhostnameentry' =&gt; 'crear bind-zone/config para el nombre de host del sistema', 'panel_password_alpha_lower' =&gt; [ 'title' =&gt; 'carcter en minsculas', 'description' =&gt; 'la contrasea debe contener al menos una letra minscula (a-z).' ], 'panel_password_alpha_upper' =&gt; [ 'title' =&gt; 'maysculas', 'description' =&gt; 'la contrasea debe contener al menos una letra mayscula (a-z).' ], 'panel_password_numeric' =&gt; [ 'title' =&gt; 'nmeros', 'description' =&gt; 'la contrasea debe contener al menos un nmero (0-9).' ], 'panel_password_special_char_required' =&gt; [ 'title' =&gt; 'carcter especial', 'description' =&gt; 'la contrasea debe contener al menos uno de los caracteres definidos continuacin.' ], 'panel_password_special_char' =&gt; [ 'title' =&gt; 'lista de caracteres especiales', 'description' =&gt; 'se requiere uno de estos caracteres si se establece la opcin anterior.' ], 'apache_itksupport' =&gt; [ 'title' =&gt; 'modificaciones de uso para apache itk-mpm', 'description' =&gt; '&lt;strong class="text-danger"&gt;atencin:&lt;/strong&gt; utilcela slo si tiene apache itk-mpm habilitado&lt;br/&gt;, de lo contrario su servidor web podr iniciarse.' ], 'letsencryptca' =&gt; [ 'title' =&gt; 'entorno acme', 'description' =&gt; 'entorno que se utilizar para los certificados let\'s encrypt / zerossl.' ], 'letsencryptchallengepath' =&gt; [ 'title' =&gt; 'ruta para los desafos let\'s encrypt', 'description' =&gt; 'directorio desde el que se ofrecern los retos let\'s encrypt travs de un alias global.' ], 'letsencryptkeysize' =&gt; [ 'title' =&gt; 'tamao de la clave para nuevos certificados let\'s encrypt', 'description' =&gt; 'tamao de la clave en bits para nuevos certificados let\'s encrypt.' ], 'letsencryptreuseold' =&gt; [ 'title' =&gt; 'reutilizar clave let\'s encrypt', 'description' =&gt; 'si se activa, se utilizar la misma clave para cada renovacin, de lo contrario se generar una nueva clave cada vez.' ], 'leenabled' =&gt; [ 'title' =&gt; 'activar let\'s encrypt', 'description' =&gt; 'si se activa, los clientes pueden dejar que froxlor automticamente genere renueve certificados ssl let\'s encrypt para dominios con una ip/puerto ssl.&lt;br/&gt;&lt;br/&gt;por favor recuerda que necesitas ir travs de la configuracin del servidor web cuando se activa porque esta caracterstica necesita una configuracin especial.' ], 'caa_entry' =&gt; [ 'title' =&gt; 'generar registros dns caa', 'description' =&gt; 'genera automticamente registros caa para dominios habilitados para ssl que utilizan let\'s encrypt.' ], 'caa_entry_custom' =&gt; [ 'title' =&gt; 'registros dns caa adicionales', 'description' =&gt; 'dns certification authority authorization (caa) es un mecanismo de poltica de seguridad en internet que permite los titulares de nombres de dominio indicar las autoridades de certificacin&lt;br/&gt;si estn autorizadas emitir certificados digitales para un nombre de dominio concreto. lo hace mediante un nuevo registro de recursos del sistema de nombres de dominio (dns) "caa".&lt;br/&gt;&lt;br/&gt;el contenido de este campo se incluir en la zona dns directamente (cada lnea da lugar un registro caa).&lt;br/&gt;si let\'s encrypt est habilitado para este dominio, esta entrada siempre se aadir automticamente es necesario aadirla manualmente:&lt;br/&gt; 0&lt;code&gt;issue "letsencrypt.org"&lt;/code&gt; (si el dominio es un dominio comodn, se utilizar issuewild en su lugar).&lt;br/&gt;para habilitar el informe de incidentes, puede aadir un registro &lt;code&gt;iodef&lt;/code&gt;. un ejemplo para enviar dicho informe &lt;code&gt;me@example.com&lt;/code&gt; sera:&lt;br/&gt; 0&lt;code&gt;iodef "mailto:me@example.com"&lt;/code&gt;&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;atencin:&lt;/strong&gt; se comprobar si el cdigo contiene errores. si contiene errores, es posible que sus registros caa funcionen!' ], 'dnseditorenable' =&gt; [ 'title' =&gt; 'habilitar editor dns', 'description' =&gt; 'permite los administradores los clientes gestionar las entradas dns del dominio' ], 'dns_server' =&gt; [ 'title' =&gt; 'demonio del servidor dns', 'description' =&gt; 'recuerde que los daemons tienen que ser configurados usando las plantillas de configuracin de froxlors' ], 'panel_customer_hide_options' =&gt; [ 'title' =&gt; 'ocultar elementos de men grficos de trfico en el panel de cliente', 'description' =&gt; 'seleccione los elementos que desea ocultar en el panel de cliente. para seleccionar varias opciones, mantenga pulsada la tecla ctrl mientras selecciona.' ], 'allow_allow_customer_shell' =&gt; [ 'title' =&gt; 'permitir los clientes habilitar el acceso shell para usuarios ftp', 'description' =&gt; '&lt;strong class="text-danger"&gt;atencin: el acceso shell permite al usuario ejecutar varios binarios en su sistema. utilcelo con extrema precaucin. por favor, active esto slo si realmente sabe lo que est haciendo!!!&lt;/strong&gt;' ], 'available_shells' =&gt; [ 'title' =&gt; 'lista de shells disponibles', 'description' =&gt; 'lista separada por comas de los intrpretes de comandos que estn disponibles para que el cliente elija para sus usuarios ftp.&lt;br/&gt;&lt;br/&gt;tenga en cuenta que el intrprete de comandos predeterminado &lt;strong&gt;/bin/false&lt;/strong&gt; siempre ser una opcin (si est habilitado), incluso si esta configuracin est vaca. es el valor por defecto para los usuarios ftp en cualquier caso.' ], 'le_froxlor_enabled' =&gt; [ 'title' =&gt; 'activar let\'s encrypt para el froxlor vhost', 'description' =&gt; 'si se activa, el froxlor vhost se asegurar automticamente usando un certificado let\'s encrypt.' ], 'le_froxlor_redirect' =&gt; [ 'title' =&gt; 'activar ssl-redirect para froxlor vhost', 'description' =&gt; 'si se activa, todas las peticiones http su froxlor sern redirigidas al sitio ssl correspondiente.' ], 'option_unavailable_websrv' =&gt; '&lt;br/&gt;&lt;em class="text-danger"&gt;disponible slo para: %s&lt;/em&gt;', 'option_unavailable' =&gt; '&lt;br/&gt;&lt;em class="text-danger"&gt;opcin disponible debido otros ajustes.&lt;/em&gt;', 'letsencryptacmeconf' =&gt; [ 'title' =&gt; 'ruta al fragmento acme.conf', 'description' =&gt; 'nombre de archivo del fragmento de configuracin que permite al servidor web servir el desafo acme.' ], 'mail_use_smtp' =&gt; 'configurar mailer para usar smtp', 'mail_smtp_host' =&gt; 'especifique el servidor smtp', 'mail_smtp_usetls' =&gt; 'activar el cifrado tls', 'mail_smtp_auth' =&gt; 'activar la autenticacin smtp', 'mail_smtp_port' =&gt; 'puerto tcp al que conectarse', 'mail_smtp_user' =&gt; 'nombre de usuario smtp', 'mail_smtp_passwd' =&gt; 'contrasea smtp', 'http2_support' =&gt; [ 'title' =&gt; 'soporte http2', 'description' =&gt; 'habilite el soporte http2 para ssl.&lt;br/&gt;&lt;em class="text-danger"&gt;habilitar slo si su webserver soporta esta caracterstica (nginx versin 1.9.5+, apache2 versin 2.4.17+)&lt;/em&gt;' ], 'nssextrausers' =&gt; [ 'title' =&gt; 'usar libnss-extrausers en lugar de libnss-mysql', 'description' =&gt; 'no leer usuarios de la base de datos sino de ficheros. por favor, actvelo slo si ya ha realizado los pasos de configuracin necesarios (system -&gt;&lt;strong class="text-danger"&gt;libnss-extrausers).&lt;/strong&gt;&lt;br/&gt;&lt;strong class="text-danger"&gt;slo para debian/ubuntu (o si ha compilado libnss-extrausers usted mismo!)&lt;/strong&gt;' ], 'le_domain_dnscheck' =&gt; [ 'title' =&gt; 'validar dns de dominios al usar let\'s encrypt', 'description' =&gt; 'si est activado, froxlor validar si el dominio que solicita un certificado let\'s encrypt resuelve al menos una de las direcciones ip del sistema.' ], 'le_domain_dnscheck_resolver' =&gt; [ 'title' =&gt; 'usar un servidor de nombres externo para validacin dns', 'description' =&gt; 'si se establece, froxlor usar este dns para validar los dns de los dominios cuando use let\'s encrypt. si est vaco, se usar el resolver dns por defecto del sistema.' ], 'phpsettingsforsubdomains' =&gt; [ 'description' =&gt; 'en caso afirmativo se actualizar el php-config elegido todos los subdominios' ], 'leapiversion' =&gt; [ 'title' =&gt; 'elegir la implementacin acme de let\'s encrypt', 'description' =&gt; 'actualmente slo se soporta la implementacin acme v2 para let\'s encrypt.' ], 'enable_api' =&gt; [ 'title' =&gt; 'habilitar uso de api externa', 'description' =&gt; 'para utilizar la api froxlor es necesario activar esta opcin. para obtener informacin ms detallada, consulte &lt;a href="https://docs.froxlor.org/latest/api-guide/" target="_new"&gt;https://docs.froxlor.org/&lt;/a&gt;' ], 'api_customer_default' =&gt; '"permitir acceso la api" valor por defecto para nuevos clientes', 'dhparams_file' =&gt; [ 'title' =&gt; 'archivo dhparams (intercambio de claves diffie-hellman)', 'description' =&gt; 'si se especifica aqu un archivo dhparams.pem, se incluir en la configuracin del servidor web. djelo vaco para desactivarlo.&lt;br/&gt;ejemplo: &lt;code&gt;/etc/ssl/webserver/dhparams&lt;/code&gt;.pem&lt;br/&gt;&lt;br/&gt;si el archivo existe, se crear automticamente con el siguiente comando: &lt;code&gt;openssl dhparam -out /etc/ssl/webserver/dhparams.pem 4096&lt;/code&gt;. se recomienda crear el archivo antes de especificarlo aqu, ya que la creacin tarda bastante bloquea el cronjob.' ], 'errorlog_level' =&gt; [ 'title' =&gt; 'nivel de registro de errores', 'description' =&gt; 'especifique el nivel de registro de errores. por defecto es "warn" para usuarios apache "error" para usuarios nginx.' ], 'letsencryptecc' =&gt; [ 'title' =&gt; 'emitir certificado ecc / ecdsa', 'description' =&gt; 'si se establece un tamao de clave vlido, el certificado emitido utilizar ecc / ecdsa.' ], 'froxloraliases' =&gt; [ 'title' =&gt; 'alias de dominio para froxlor vhost', 'description' =&gt; 'lista separada por comas de dominios para aadir como alias de servidor al froxlor vhost' ], 'default_sslvhostconf' =&gt; [ 'title' =&gt; 'ssl por defecto vhost-settings', 'description' =&gt; 'el contenido de este campo se incluir en este contenedor ip/port vhost directamente. puede utilizar las siguientes variables:&lt;br/&gt;&lt;code&gt;{domain}&lt;/code&gt;, &lt;code&gt;{docroot}&lt;/code&gt;, &lt;code&gt;{customer}&lt;/code&gt;, &lt;code&gt;{ip}&lt;/code&gt;, &lt;code&gt;{port}&lt;/code&gt;, &lt;code&gt;{scheme}&lt;/code&gt;, &lt;code&gt;{fpmsocket}&lt;/code&gt; (si procede)&lt;br/&gt; atencin: se comprobar si el cdigo contiene errores. si contiene errores, el servidor web podra volver arrancar!' ], 'includedefault_sslvhostconf' =&gt; 'incluir configuracin de vhost ssl en ssl-vhost', 'apply_specialsettings_default' =&gt; [ 'title' =&gt; 'valor por defecto para "apply specialsettings subdomains (*.example.com)\' setting editing domain' ], 'apply_phpconfigs_default' =&gt; [ 'title' =&gt; 'valor por defecto para "aplicar php-config todos los subdominios:\' al editar un dominio' ], 'awstats' =&gt; [ 'logformat' =&gt; [ 'title' =&gt; 'configuracin de logformat', 'description' =&gt; 'si utilizas un formato de registro personalizado para tu servidor web, necesitas cambiar tambin el awstats logformat.&lt;br/&gt;por defecto es 1. para ms informacin consulta la documentacin &lt;a target="_blank" href="https://awstats.sourceforge.io/docs/awstats_config.html#logformat"&gt;aqu&lt;/a&gt;.' ] ], 'hide_incompatible_settings' =&gt; 'ocultar configuraciones incompatibles', 'soaemail' =&gt; 'direccin de correo usar en registros soa (por defecto la direccin del remitente de la configuracin del panel si est vaca)', 'imprint_url' =&gt; [ 'title' =&gt; 'url notas legales / impresin', 'description' =&gt; 'especifique una url su sitio de notas legales / impresin. el enlace ser visible en la pantalla de inicio de sesin en el pie de pgina una vez iniciada la sesin.' ], 'terms_url' =&gt; [ 'title' =&gt; 'url las condiciones de uso', 'description' =&gt; 'especifique una url su sitio de condiciones de uso. el enlace ser visible en la pantalla de inicio de sesin en el pie de pgina al iniciar sesin.' ], 'privacy_url' =&gt; [ 'title' =&gt; 'url la poltica de privacidad', 'description' =&gt; 'especifique una url su sitio de poltica de privacidad / sitio de impresin. el enlace ser visible en la pantalla de inicio de sesin en el pie de pgina al iniciar sesin.' ], 'logo_image_header' =&gt; [ 'title' =&gt; 'imagen de logotipo (cabecera)', 'description' =&gt; 'cargue su propia imagen de logotipo para que se muestre en el encabezado despus del inicio de sesin (altura recomendada 30px)' ], 'logo_image_login' =&gt; [ 'title' =&gt; 'imagen del logotipo (inicio de sesin)', 'description' =&gt; 'cargue su propia imagen de logotipo para que se muestre durante el inicio de sesin' ], 'logo_overridetheme' =&gt; [ 'title' =&gt; 'sobrescribe el logo definido en el tema por "logo image" (cabecera login, ver ms abajo)', 'description' =&gt; 'esta opcin debe establecerse como "true" si desea utilizar el logotipo que ha cargado; como alternativa, puede seguir utilizando las posibilidades basadas en el tema "logo_custom.png" "logo_custom_login.png".' ], 'logo_overridecustom' =&gt; [ 'title' =&gt; 'sobrescribir el logotipo personalizado (logo_custom.png logo_custom_login.png) definido en el tema por "imagen del logotipo" (cabecera e inicio de sesin, ver ms abajo).', 'description' =&gt; 'establezca este valor en "true" si desea ignorar los logotipos personalizados especficos del tema para el encabezado el inicio de sesin utilizar "logo image".' ], 'createstdsubdom_default' =&gt; [ 'title' =&gt; 'valor preseleccionado para "crear subdominio estndar" al crear un cliente', 'description' =&gt; '' ], 'froxlorusergroup' =&gt; [ 'title' =&gt; 'grupo de sistema personalizado para todos los usuarios del cliente', 'description' =&gt; 'se requiere el uso de libnss-extrausers (system-settings) para que esto tenga efecto. un valor vaco omite la creacin elimina el grupo existente.' ], 'acmeshpath' =&gt; [ 'title' =&gt; 'ruta acme.sh', 'description' =&gt; 'establzcalo donde se instala acme.sh, incluyendo el script acme.sh&lt;br/&gt;por defecto es &lt;b&gt;/root/.acme.sh/acme.sh&lt;/b&gt;' ], 'update_channel' =&gt; [ 'title' =&gt; 'froxlor actualizar-canal', 'description' =&gt; 'seleccione el canal de actualizacin de froxlor. por defecto es "estable"' ], 'uc_stable' =&gt; 'estable', 'uc_testing' =&gt; 'testing', 'traffictool' =&gt; [ 'toolselect' =&gt; 'analizador de trfico', 'webalizer' =&gt; 'webalizer', 'awstats' =&gt; 'awstats', 'goaccess' =&gt; 'goaccess' ], 'requires_reconfiguration' =&gt; 'el cambio de esta configuracin podra requerir una reconfiguracin de los siguientes servicios:&lt;br/&gt;&lt;strong&gt;%s&lt;/strong&gt;' ], 'spf' =&gt; [ 'use_spf' =&gt; 'activar spf para dominios?', 'spf_entry' =&gt; 'entrada spf para todos los dominios' ], 'ssl_certificates' =&gt; [ 'certificate_for' =&gt; 'certificado para', 'valid_from' =&gt; 'vlido de', 'valid_until' =&gt; 'vlido hasta', 'issuer' =&gt; 'emisor' ], 'success' =&gt; [ 'success' =&gt; 'informacin', 'clickheretocontinue' =&gt; 'haga clic aqu para continuar', 'settingssaved' =&gt; 'la configuracin se ha guardado correctamente.', 'rebuildingconfigs' =&gt; 'tareas insertadas con xito para reconstruir archivos de configuracin', 'domain_import_successfully' =&gt; 'se han importado correctamente los dominios %s.', 'dns_record_added' =&gt; 'registro aadido correctamente', 'dns_record_deleted' =&gt; 'registro eliminado correctamente', 'testmailsent' =&gt; 'correo de prueba enviado correctamente', 'settingsimported' =&gt; 'ajustes importados correctamente', 'sent_error_report' =&gt; 'informe de error enviado correctamente. gracias por su contribucin.' ], 'tasks' =&gt; [ 'outstanding_tasks' =&gt; 'tareas cron pendientes', 'rebuild_vhost' =&gt; 'reconstruccin de la configuracin del servidor web', 'create_home' =&gt; 'aadir nueva %s cliente', 'rebuild_dns' =&gt; 'reconstruccin de la configuracin bind', 'create_ftp' =&gt; 'crear directorio para nuevo usuario ftp', 'delete_customer_files' =&gt; 'borrar archivos de cliente %s', 'noneoutstanding' =&gt; 'actualmente hay tareas pendientes para froxlor', 'create_quota' =&gt; 'establecer cuota en el sistema de archivos', 'delete_email_data' =&gt; 'borrar datos de e-mail del cliente.', 'delete_ftp_data' =&gt; 'borrar los datos de la cuenta ftp del cliente.', 'rebuild_cron' =&gt; 'reconstruir el archivo cron.d', 'delete_domain_pdns' =&gt; 'borrar dominio %s de la base de datos powerdns', 'delete_domain_ssl' =&gt; 'borrar archivos ssl de dominio %s' ], 'terms' =&gt; 'condiciones de uso', 'traffic' =&gt; [ 'month' =&gt; 'mes', 'day' =&gt; 'da', 'months' =&gt; [ '1' =&gt; 'enero', '2' =&gt; 'febrero', '3' =&gt; 'marzo', '4' =&gt; 'abril', '5' =&gt; 'mayo', '6' =&gt; 'junio', '7' =&gt; 'julio', '8' =&gt; 'agosto', '9' =&gt; 'septiembre', '10' =&gt; 'octubre', '11' =&gt; 'noviembre', '12' =&gt; 'diciembre', 'jan' =&gt; 'enero', 'feb' =&gt; 'febrero', 'mar' =&gt; 'mar', 'apr' =&gt; 'abr', 'may' =&gt; 'mayo', 'jun' =&gt; 'jun', 'jul' =&gt; 'jul', 'aug' =&gt; 'ago', 'sep' =&gt; 'sep', 'oct' =&gt; 'oct', 'nov' =&gt; 'nov', 'dec' =&gt; 'diciembre', 'total' =&gt; 'total' ], 'mb' =&gt; 'trfico', 'sumtotal' =&gt; 'trfico total', 'sumhttp' =&gt; 'trfico http', 'sumftp' =&gt; 'trfico ftp', 'summail' =&gt; 'trfico de correo', 'customer' =&gt; 'cliente', 'domain' =&gt; 'dominio', 'trafficoverview' =&gt; 'resumen del trfico', 'bycustomers' =&gt; 'trfico por clientes', 'details' =&gt; 'detalles', 'http' =&gt; 'http', 'ftp' =&gt; 'ftp', 'mail' =&gt; 'correo', 'nocustomers' =&gt; 'necesita al menos un cliente para ver los informes de trfico.', 'top5customers' =&gt; 'top 5 clientes', 'nodata' =&gt; 'no se han encontrado datos para el intervalo dado.', 'ranges' =&gt; [ 'last24h' =&gt; 'ltimas 24 horas', 'last7d' =&gt; 'ltimos 7 das', 'last30d' =&gt; 'ltimos 30 das', 'cm' =&gt; 'mes actual', 'last3m' =&gt; 'ltimos 3 meses', 'last6m' =&gt; 'ltimos 6 meses', 'last12m' =&gt; 'ltimos 12 meses', 'cy' =&gt; 'ao en curso' ], 'byrange' =&gt; 'especificado por rango' ], 'translator' =&gt; '', 'update' =&gt; [ 'updateinprogress_onlyadmincanlogin' =&gt; 'se ha instalado una versin ms reciente de froxlor pero se ha configurado.&lt;br/&gt;slo el administrador puede iniciar sesin finalizar la actualizacin.', 'update' =&gt; 'actualizacin de froxlor', 'proceed' =&gt; 'proceder', 'update_information' =&gt; [ 'part_a' =&gt; 'los archivos froxlor han sido actualizados la versin &lt;strong&gt;%s&lt;/strong&gt;. la versin instalada es &lt;strong&gt;%s&lt;/strong&gt;.', 'part_b' =&gt; '&lt;br/&gt;&lt;br/&gt;los clientes podrn conectarse hasta que la actualizacin haya finalizado.&lt;br/&gt;&lt;strong&gt;proceder?&lt;/strong&gt;' ], 'noupdatesavail' =&gt; 'ya tiene instalada la ltima %sversion de froxlor.', 'description' =&gt; 'ejecutando actualizaciones de la base de datos para su instalacin de froxlor', 'uc_newinfo' =&gt; 'hay un %sversion ms reciente disponible: "%s" (su versin actual es: %s)', 'notify_subject' =&gt; 'nueva actualizacin disponible' ], 'usersettings' =&gt; [ 'custom_notes' =&gt; [ 'title' =&gt; 'notas personalizadas', 'description' =&gt; 'sintete libre de poner las notas que quieras/necesites aqu. se mostrarn en la vista general del administrador/cliente para el usuario correspondiente.', 'show' =&gt; 'mostrar tus notas en el panel de control del usuario' ], 'api_allowed' =&gt; [ 'title' =&gt; 'permitir el acceso la api', 'description' =&gt; 'cuando est habilitado en la configuracin, este usuario puede crear claves api acceder la api froxlor', 'notice' =&gt; 'el acceso la api est permitido para su cuenta.' ] ], 'install' =&gt; [ 'slogan' =&gt; 'panel de gestin del servidor froxlor', 'preflight' =&gt; 'comprobacin del sistema', 'critical_error' =&gt; 'error crtico', 'suggestions' =&gt; 'no requerido pero recomendado', 'phpinfosuccess' =&gt; 'su sistema funciona con php %s', 'phpinfowarn' =&gt; 'su sistema est ejecutando una versin inferior php %s', 'phpinfoupdate' =&gt; 'actualice su versin php actual de %s %s superior', 'start_installation' =&gt; 'inicie la instalacin', 'check_again' =&gt; 'recargar para comprobar de nuevo', 'switchmode_advanced' =&gt; 'mostrar opciones avanzadas', 'switchmode_basic' =&gt; 'ocultar opciones avanzadas', 'dependency_check' =&gt; [ 'title' =&gt; 'bienvenido froxlor', 'description' =&gt; 'comprobamos las dependencias del sistema para asegurarnos de que todas las extensiones mdulos php necesarios estn habilitados para que froxlor funcione correctamente.' ], 'database' =&gt; [ 'top' =&gt; 'base de datos', 'title' =&gt; 'crear base de datos usuario', 'description' =&gt; 'froxlor requiere una base de datos adicionalmente un usuario privilegiado para poder crear usuarios bases de datos (opcin grant). la base de datos el usuario privilegiado sern creados en este proceso. el usuario privilegiado debe existir.', 'user' =&gt; 'usuario privilegiado de la base de datos', 'dbname' =&gt; 'nombre de la base de datos', 'force_create' =&gt; 'hacer copia de seguridad sobrescribir la base de datos si existe?' ], 'admin' =&gt; [ 'top' =&gt; 'usuario administrador', 'title' =&gt; 'vamos crear el usuario administrador principal.', 'description' =&gt; 'este usuario tendr todos los privilegios para ajustar la configuracin aadir/actualizar/eliminar recursos como clientes, dominios, etc.' ], 'system' =&gt; [ 'top' =&gt; 'configuracin del sistema', 'title' =&gt; 'detalles sobre su servidor', 'description' =&gt; 'establezca su entorno como los datos opciones relevantes del servidor aqu para que froxlor conozca su sistema. estos valores son cruciales para la configuracin el funcionamiento del sistema.', 'ipv4' =&gt; 'direccin ipv4 primaria (si procede)', 'ipv6' =&gt; 'direccin ipv6 primaria (si procede)', 'servername' =&gt; 'nombre del servidor (fqdn, sin direccin ip)', 'phpbackend' =&gt; 'php backend', 'activate_newsfeed' =&gt; 'habilitar la fuente oficial de noticias&lt;br/&gt;&lt;small&gt;(fuente externa: https://inside.froxlor.org/news/)&lt;/small&gt;' ], 'install' =&gt; [ 'top' =&gt; 'finalizar la configuracin', 'title' =&gt; 'un ltimo paso...', 'description' =&gt; 'el siguiente comando descargar, instalar configurar los servicios necesarios en tu sistema de acuerdo con los datos que facilitado en este proceso de instalacin.', 'runcmd' =&gt; 'ejecute el siguiente comando como usuario root en su shell en este servidor:', 'manual_config' =&gt; 'configurar manualmente los servicios, llvame al inicio de sesin', 'waitforconfig' =&gt; 'esperando que se configuren los servicios...' ], 'errors' =&gt; [ 'wrong_ownership' =&gt; 'asegrese de que los archivos froxlor son propiedad de %s:%s', 'missing_extensions' =&gt; 'las siguientes extensiones de php son necesarias estn instaladas', 'suggestedextensions' =&gt; 'no se han encontrado las siguientes extensiones de php pero se recomiendan', 'databaseexists' =&gt; 'la base de datos ya existe, por favor establezca la opcin override para reconstruir elija otro nombre', 'unabletocreatedb' =&gt; 'no se ha podido crear la base de datos de prueba', 'unabletodropdb' =&gt; 'no se ha podido eliminar la base de datos de prueba', 'mysqlusernameexists' =&gt; 'el usuario especificado para el usuario sin privilegios ya existe. por favor, utilice otro nombre de usuario elimnelo primero.', 'unabletocreateuser' =&gt; 'no se ha podido crear el usuario de prueba', 'unabletodropuser' =&gt; 'no se ha podido eliminar el usuario de prueba.', 'unabletoflushprivs' =&gt; 'el usuario privilegiado puede eliminar privilegios.', 'nov4andnov6ip' =&gt; 'debe indicarse una direccin ipv4 ipv6.', 'servernameneedstobevalid' =&gt; 'el nombre de servidor indicado parece ser un fqdn un nombre de host.', 'websrvuserdoesnotexist' =&gt; 'el usuario del servidor web parece existir en el sistema.', 'websrvgrpdoesnotexist' =&gt; 'el webserver-group indicado parece existir en el sistema.', 'notyetconfigured' =&gt; 'parece que los servicios se han configurado (correctamente). por favor, ejecute el comando que se muestra continuacin marque la casilla para hacerlo ms tarde.', 'mandatory_field_not_set' =&gt; 'el campo obligatorio "%s" est configurado.', 'unexpected_database_error' =&gt; 'se ha producido una excepcin inesperada en la base de datos. %s', 'sql_import_failed' =&gt; 'error al importar datos sql.', 'unprivileged_sql_connection_failed' =&gt; 'error al inicializar una conexin sql sin privilegios.', 'privileged_sql_connection_failed' =&gt; 'error al inicializar la conexin sql privilegiada.', 'mysqldump_backup_failed' =&gt; 'no se puede crear una copia de seguridad de la base de datos, tenemos un error de mysqldump.', 'sql_backup_file_missing' =&gt; 'no se puede crear una copia de seguridad de la base de datos, el archivo de copia de seguridad existe.', 'backup_binary_missing' =&gt; 'no se puede crear una copia de seguridad de la base de datos, asegrese de que ha instalado mysqldump.', 'creating_configfile_failed' =&gt; 'no se pueden crear archivos de configuracin, se puede escribir el archivo.', 'database_already_exiting' =&gt; 'encontramos una base de datos se nos permiti sobreescribirla!' ] ], 'welcome' =&gt; [ 'title' =&gt; 'bienvenido froxlor!', 'config_note' =&gt; 'para que froxlor pueda comunicarse correctamente con el backend, tienes que configurarlo.', 'config_now' =&gt; 'configurar ahora' ] ];</file><file name="lng/index.html" /><file name="install/install.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\http\ratelimiter; use froxlor\ui\panel\ui; use froxlor\install\install; require dirname(__dir__) . '/lib/functions.php'; // define default theme configurehint, etc. $_deftheme = 'froxlor'; // validate correct php version (version_compare("7.4.0", php_version, "&gt;=")) { die(view($_deftheme . '/misc/phprequirementfailed.html.twig', [ '{{ basehref }}' =&gt; '../', '{{ froxlor_min_version }}' =&gt; '7.4.0', '{{ current_version }}' =&gt; php_version, '{{ current_year }}' =&gt; date('y', time()), ])); } // validate vendor autoloader (!file_exists(dirname(__dir__) . '/vendor/autoload.php')) { die(view($_deftheme . '/misc/vendormissinghint.html.twig', [ '{{ basehref }}' =&gt; '../', '{{ froxlor_install_dir }}' =&gt; dirname(__dir__), '{{ current_year }}' =&gt; date('y', time()), ])); } // check installation status (file_exists(dirname(__dir__) . '/lib/userdata.inc.php')) { header("location: ../"); exit; } require dirname(__dir__) . '/vendor/autoload.php'; require dirname(__dir__) . '/lib/tables.inc.php'; // init twig ui::inittwig(true); ui::sendheaders(); ratelimiter::run(true); $installer = new install(); $installer-&gt;handle();</file><file name="install/updatesql.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\froxlor; use froxlor\filedir; use froxlor\froxlorlogger; use froxlor\settings; use froxlor\ui\response; use froxlor\database\integritycheck; use froxlor\install\update; (!defined('_cron_update')) { (!defined('area') || (defined('area') &amp;&amp; area != 'admin') || !isset($userinfo['loginname']) || (isset($userinfo['loginname']) &amp;&amp; $userinfo['loginname'] == '')) { header('location: ../index.php'); exit(); } } $filelog = froxlorlogger::getinstanceof(array( 'loginname' =&gt; 'updater' )); // first writing work we'll stop, tell user fix // let try again. try { $filelog-&gt;logaction(froxlorlogger::adm_action, log_warning, '-------------- start log --------------'); } catch (exception $e) { response::standarderror('exception', $e-&gt;getmessage()); } (froxlor::isfroxlor()) { include_once(filedir::makecorrectfile(dirname(__file__) . '/updates/froxlor/update_0.10.inc.php')); include_once(filedir::makecorrectfile(dirname(__file__) . '/updates/froxlor/update_2.0.inc.php')); include_once(filedir::makecorrectfile(dirname(__file__) . '/updates/froxlor/update_2.1.inc.php')); include_once(filedir::makecorrectfile(dirname(__file__) . '/updates/froxlor/update_2.2.inc.php')); // check froxlor - database integrity (only happens updates done, know db-layout okay) update::showupdatestep("checking database integrity"); $integrity = new integritycheck(); (!$integrity-&gt;checkall()) { update::laststepstatus(1, 'integrity could validated'); update::showupdatestep("trying automatically restore integrity"); (!$integrity-&gt;fixall()) { update::laststepstatus(2, 'failed', 'check "database validation" admin left-side menu see problem is'); } else { update::laststepstatus(0, 'integrity restored'); } } else { update::laststepstatus(0); } // reset cached version check settings::set('system.updatecheck_data', ''); $filelog-&gt;logaction(froxlorlogger::adm_action, log_warning, '--------------- end log ---------------'); unset($filelog); }</file><file name="install/froxlor.sql.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ return &lt;&lt;&lt;'froxlorsql' drop table exists `ftp_groups`; create table `ftp_groups` ( `id` int(20) null auto_increment, `groupname` varchar(60) null default '', `gid` int(5) null default '0', `members` longtext null, `customerid` int(11) null default '0', primary key (`id`), unique key `groupname` (`groupname`), key `customerid` (`customerid`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `ftp_users`; create table `ftp_users` ( `id` int(20) null auto_increment, `username` varchar(255) null, `uid` int(5) null default '0', `gid` int(5) null default '0', `password` varchar(255) null, `homedir` varchar(255) null default '', `shell` varchar(255) null default '/bin/false', `login_enabled` enum('n','y') null default 'n', `login_count` int(15) null default '0', `last_login` datetime default null, `up_count` int(15) null default '0', `up_bytes` bigint(30) null default '0', `down_count` int(15) null default '0', `down_bytes` bigint(30) null default '0', `customerid` int(11) null default '0', `description` varchar(255) null default '', primary key (`id`), unique key `username` (`username`), key `customerid` (`customerid`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `mail_users`; create table `mail_users` ( `id` int(11) null auto_increment, `email` varchar(255) null default '', `username` varchar(255) null default '', `password` varchar(255) null default '', `password_enc` varchar(255) null default '', `uid` int(11) null default '0', `gid` int(11) null default '0', `homedir` varchar(255) null default '', `maildir` varchar(255) null default '', `postfix` enum('y','n') null default 'y', `domainid` int(11) null default '0', `customerid` int(11) null default '0', `quota` bigint(13) null default '0', `pop3` tinyint(1) null default '1', `imap` tinyint(1) null default '1', `mboxsize` bigint(30) null default '0', primary key (`id`), unique key `email` (`email`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `mail_virtual`; create table `mail_virtual` ( `id` int(11) null auto_increment, `email` varchar(255) null default '', `email_full` varchar(255) null default '', `destination` text, `domainid` int(11) null default '0', `customerid` int(11) null default '0', `popaccountid` int(11) null default '0', `iscatchall` tinyint(1) unsigned null default '0', `description` varchar(255) null default '', `spam_tag_level` float(4,1) null default 7.0, `rewrite_subject` tinyint(1) null default '1', `spam_kill_level` float(4,1) null default 14.0, `bypass_spam` tinyint(1) null default '0', `policy_greylist` tinyint(1) null default '1', primary key (`id`), key `email` (`email`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_activation`; create table `panel_activation` ( `id` int(11) unsigned null auto_increment, `userid` int(11) unsigned null default '0', `admin` tinyint(1) unsigned null default '0', `creation` int(11) unsigned null default '0', `activationcode` varchar(50) default null, primary key (id) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_admins`; create table `panel_admins` ( `adminid` int(11) unsigned null auto_increment, `loginname` varchar(50) null, `password` varchar(255) null, `name` varchar(255) null default '', `email` varchar(255) null default '', `def_language` varchar(100) null default '', `ip` varchar(500) null default '-1', `customers` int(15) null default '0', `customers_used` int(15) null default '0', `customers_see_all` tinyint(1) null default '0', `domains` int(15) null default '0', `domains_used` int(15) null default '0', `caneditphpsettings` tinyint(1) null default '0', `change_serversettings` tinyint(1) null default '0', `diskspace` int(15) null default '0', `diskspace_used` int(15) null default '0', `mysqls` int(15) null default '0', `mysqls_used` int(15) null default '0', `emails` int(15) null default '0', `emails_used` int(15) null default '0', `email_accounts` int(15) null default '0', `email_accounts_used` int(15) null default '0', `email_forwarders` int(15) null default '0', `email_forwarders_used` int(15) null default '0', `email_quota` bigint(13) null default '0', `email_quota_used` bigint(13) null default '0', `ftps` int(15) null default '0', `ftps_used` int(15) null default '0', `subdomains` int(15) null default '0', `subdomains_used` int(15) null default '0', `traffic` bigint(30) null default '0', `traffic_used` bigint(30) null default '0', `deactivated` tinyint(1) null default '0', `lastlogin_succ` int(11) unsigned null default '0', `lastlogin_fail` int(11) unsigned null default '0', `loginfail_count` int(11) unsigned null default '0', `reportsent` tinyint(4) unsigned null default '0', `theme` varchar(50) null default 'froxlor', `custom_notes` text, `custom_notes_show` tinyint(1) null default '0', `type_2fa` tinyint(1) null default '0', `data_2fa` varchar(25) null default '', `api_allowed` tinyint(1) null default '1', `gui_access` tinyint(1) null default '1', primary key (`adminid`), unique key `loginname` (`loginname`) ) engine=innodb charset=utf8 collate=utf8_general_ci row_format=dynamic; drop table exists `panel_customers`; create table `panel_customers` ( `customerid` int(11) unsigned null auto_increment, `loginname` varchar(50) null, `password` varchar(255) null default '', `adminid` int(11) unsigned null default '0', `name` varchar(255) null default '', `firstname` varchar(255) null default '', `gender` int(1) null default '0', `company` varchar(255) null default '', `street` varchar(255) null default '', `zipcode` varchar(25) null default '', `city` varchar(255) null default '', `phone` varchar(50) null default '', `fax` varchar(50) null default '', `email` varchar(255) null default '', `customernumber` varchar(100) null default '', `def_language` varchar(100) null default '', `diskspace` bigint(30) null default '0', `diskspace_used` bigint(30) null default '0', `mysqls` int(15) null default '0', `mysqls_used` int(15) null default '0', `emails` int(15) null default '0', `emails_used` int(15) null default '0', `email_accounts` int(15) null default '0', `email_accounts_used` int(15) null default '0', `email_forwarders` int(15) null default '0', `email_forwarders_used` int(15) null default '0', `email_quota` bigint(13) null default '0', `email_quota_used` bigint(13) null default '0', `ftps` int(15) null default '0', `ftps_used` int(15) null default '0', `subdomains` int(15) null default '0', `subdomains_used` int(15) null default '0', `traffic` bigint(30) null default '0', `traffic_used` bigint(30) null default '0', `documentroot` varchar(255) null default '', `standardsubdomain` int(11) null default '0', `guid` int(5) null default '0', `ftp_lastaccountnumber` int(11) null default '0', `mysql_lastaccountnumber` int(11) null default '0', `deactivated` tinyint(1) null default '0', `phpenabled` tinyint(1) null default '1', `lastlogin_succ` int(11) unsigned null default '0', `lastlogin_fail` int(11) unsigned null default '0', `loginfail_count` int(11) unsigned null default '0', `reportsent` tinyint(4) unsigned null default '0', `pop3` tinyint(1) null default '1', `imap` tinyint(1) null default '1', `perlenabled` tinyint(1) null default '0', `dnsenabled` tinyint(1) null default '0', `theme` varchar(50) null default 'froxlor', `custom_notes` text, `custom_notes_show` tinyint(1) null default '0', `lepublickey` mediumtext default null, `leprivatekey` mediumtext default null, `leregistered` tinyint(1) null default '0', `allowed_phpconfigs` text null, `type_2fa` tinyint(1) null default '0', `data_2fa` varchar(25) null default '', `api_allowed` tinyint(1) null default '1', `logviewenabled` tinyint(1) null default '0', `allowed_mysqlserver` text null, `gui_access` tinyint(1) null default '1', primary key (`customerid`), unique key `loginname` (`loginname`) ) engine=innodb charset=utf8 collate=utf8_general_ci row_format=dynamic; drop table exists `panel_databases`; create table `panel_databases` ( `id` int(11) unsigned null auto_increment, `customerid` int(11) null default '0', `databasename` varchar(255) null default '', `description` varchar(255) null default '', `dbserver` int(11) unsigned null default '0', primary key (`id`), key `customerid` (`customerid`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_domains`; create table `panel_domains` ( `id` int(11) unsigned null auto_increment, `domain` varchar(255) null, `domain_ace` varchar(255) null default '', `adminid` int(11) unsigned null default '0', `customerid` int(11) unsigned null default '0', `aliasdomain` int(11) unsigned null, `documentroot` varchar(255) null default '', `isbinddomain` tinyint(1) null default '0', `isemaildomain` tinyint(1) null default '0', `email_only` tinyint(1) null default '0', `iswildcarddomain` tinyint(1) null default '1', `subcanemaildomain` tinyint(1) null default '0', `caneditdomain` tinyint(1) null default '1', `zonefile` varchar(255) null default '', `dkim` tinyint(1) null default '0', `dkim_id` int(11) unsigned null default '0', `dkim_privkey` text, `dkim_pubkey` text, `wwwserveralias` tinyint(1) null default '1', `parentdomainid` int(11) null default '0', `phpenabled` tinyint(1) null default '0', `openbasedir` tinyint(1) null default '0', `openbasedir_path` tinyint(1) null default '0', `speciallogfile` tinyint(1) null default '0', `ssl_redirect` tinyint(4) null default '0', `specialsettings` text, `ssl_specialsettings` text, `include_specialsettings` tinyint(1) null default '0', `deactivated` tinyint(1) null default '0', `bindserial` varchar(10) null default '2000010100', `add_date` int( 11 ) null default '0', `registration_date` date default null, `termination_date` date default null, `phpsettingid` int( 11 ) unsigned null default '1', `mod_fcgid_starter` int(4) default '-1', `mod_fcgid_maxrequests` int(4) default '-1', `letsencrypt` tinyint(1) null default '0', `hsts` varchar(10) null default '0', `hsts_sub` tinyint(1) null default '0', `hsts_preload` tinyint(1) null default '0', `ocsp_stapling` tinyint(1) default '0', `http2` tinyint(1) default '0', `notryfiles` tinyint(1) default '0', `writeaccesslog` tinyint(1) default '1', `writeerrorlog` tinyint(1) default '1', `override_tls` tinyint(1) default '0', `ssl_protocols` varchar(255) null default '', `ssl_cipher_list` varchar(500) null default '', `tlsv13_cipher_list` varchar(500) null default '', `ssl_enabled` tinyint(1) default '1', `ssl_honorcipherorder` tinyint(1) default '0', `ssl_sessiontickets` tinyint(1) default '1', `description` varchar(255) null default '', primary key (`id`), key `customerid` (`customerid`), key `parentdomain` (`parentdomainid`), key `domain` (`domain`) ) engine=innodb charset=utf8 collate=utf8_general_ci row_format=dynamic; drop table exists `panel_ipsandports`; create table `panel_ipsandports` ( `id` int(11) unsigned null auto_increment, `ip` varchar(39) null, `port` int(5) null default '80', `listen_statement` tinyint(1) null default '0', `namevirtualhost_statement` tinyint(1) null default '0', `vhostcontainer` tinyint(1) null default '0', `vhostcontainer_servername_statement` tinyint(1) null default '0', `specialsettings` text, `ssl` tinyint(4) null default '0', `ssl_cert_file` varchar(255) null default '', `ssl_key_file` varchar(255) null default '', `ssl_ca_file` varchar(255) null default '', `default_vhostconf_domain` text, `ssl_cert_chainfile` varchar(255) null default '', `docroot` varchar(255) null default '', `ssl_specialsettings` text, `include_specialsettings` tinyint(1) null default '0', `ssl_default_vhostconf_domain` text, `include_default_vhostconf_domain` tinyint(1) null default '0', primary key (`id`), unique key `ip_port` (`ip`,`port`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_htaccess`; create table `panel_htaccess` ( `id` int(11) unsigned null auto_increment, `customerid` int(11) unsigned null default '0', `path` varchar(255) null default '', `options_indexes` tinyint(1) null default '0', `error404path` varchar(255) null default '', `error403path` varchar(255) null default '', `error500path` varchar(255) null default '', `error401path` varchar(255) null default '', `options_cgi` tinyint(1) null default '0', primary key (`id`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_htpasswds`; create table `panel_htpasswds` ( `id` int(11) unsigned null auto_increment, `customerid` int(11) unsigned null default '0', `path` varchar(255) null default '', `username` varchar(255) null default '', `password` varchar(255) null default '', `authname` varchar(255) null default 'restricted area', primary key (`id`), key `customerid` (`customerid`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_settings`; create table `panel_settings` ( `settingid` int(11) unsigned null auto_increment, `settinggroup` varchar(255) null default '', `varname` varchar(255) null default '', `value` text null, primary key (`settingid`) ) engine=innodb charset=utf8 collate=utf8_general_ci; insert `panel_settings` (`settinggroup`, `varname`, `value`) values ('catchall', 'catchall_enabled', '1'), ('session', 'allow_multiple_login', '0'), ('session', 'sessiontimeout', '600'), ('customer', 'accountprefix', 'web'), ('customer', 'ftpprefix', 'ftp'), ('customer', 'mysqlprefix', 'sql'), ('customer', 'ftpatdomain', '0'), ('customer', 'show_news_feed', '0'), ('customer', 'news_feed_url', ''), ('logger', 'enabled', '1'), ('logger', 'log_cron', '0'), ('logger', 'logfile', ''), ('logger', 'logtypes', 'syslog,mysql'), ('logger', 'severity', '1'), ('antispam', 'activated', '0'), ('antispam', 'config_file', '/etc/rspamd/local.d/froxlor_settings.conf'), ('antispam', 'reload_command', 'service rspamd restart'), ('antispam', 'dkim_keylength', '1024'), ('antispam', 'default_bypass_spam', '2'), ('antispam', 'default_spam_rewrite_subject', '1'), ('antispam', 'default_policy_greylist', '1'), ('admin', 'show_news_feed', '0'), ('admin', 'show_version_login', '0'), ('admin', 'show_version_footer', '0'), ('caa', 'caa_entry', ''), ('spf', 'use_spf', '0'), ('spf', 'spf_entry', 'v=spf1 mx -all'), ('dmarc', 'use_dmarc', '0'), ('dmarc', 'dmarc_entry', 'v=dmarc1; p=none;'), ('defaultwebsrverrhandler', 'enabled', '0'), ('defaultwebsrverrhandler', 'err401', ''), ('defaultwebsrverrhandler', 'err403', ''), ('defaultwebsrverrhandler', 'err404', ''), ('defaultwebsrverrhandler', 'err500', ''), ('customredirect', 'enabled', '1'), ('customredirect', 'default', '1'), ('perl', 'suexecworkaround', '0'), ('perl', 'suexecpath', '/var/www/cgi-bin/'), ('login', 'domain_login', '0'), ('login', 'maxloginattempts', '3'), ('login', 'deactivatetime', '900'), ('phpfpm', 'enabled', '0'), ('phpfpm', 'tmpdir', '/var/customers/tmp/'), ('phpfpm', 'peardir', '/usr/share/php/:/usr/share/php5/'), ('phpfpm', 'envpath', '/usr/local/bin:/usr/bin:/bin'), ('phpfpm', 'enabled_ownvhost', '0'), ('phpfpm', 'vhost_httpuser', 'froxlorlocal'), ('phpfpm', 'vhost_httpgroup', 'froxlorlocal'), ('phpfpm', 'aliasconfigdir', '/var/www/php-fpm/'), ('phpfpm', 'defaultini', '1'), ('phpfpm', 'vhost_defaultini', '2'), ('phpfpm', 'fastcgi_ipcdir', '/var/lib/apache2/fastcgi/'), ('phpfpm', 'use_mod_proxy', '1'), ('phpfpm', 'ini_flags', 'asp_tags display_errors display_startup_errors html_errors log_errors magic_quotes_gpc magic_quotes_runtime magic_quotes_sybase mail.add_x_header session.cookie_secure session.use_cookies short_open_tag track_errors xmlrpc_errors suhosin.simulation suhosin.session.encrypt suhosin.session.cryptua suhosin.session.cryptdocroot suhosin.cookie.encrypt suhosin.cookie.cryptua suhosin.cookie.cryptdocroot suhosin.executor.disable_eval mbstring.func_overload'), ('phpfpm', 'ini_values', 'auto_append_file auto_prepend_file date.timezone default_charset error_reporting include_path log_errors_max_len mail.log max_execution_time session.cookie_domain session.cookie_lifetime session.cookie_path session.name session.serialize_handler upload_max_filesize xmlrpc_error_number session.auto_start always_populate_raw_post_data suhosin.session.cryptkey suhosin.session.cryptraddr suhosin.session.checkraddr suhosin.cookie.cryptkey suhosin.cookie.plainlist suhosin.cookie.cryptraddr suhosin.cookie.checkraddr suhosin.executor.func.blacklist suhosin.executor.eval.whitelist'), ('phpfpm', 'ini_admin_flags', 'allow_call_time_pass_reference allow_url_fopen allow_url_include auto_detect_line_endings cgi.fix_pathinfo cgi.force_redirect enable_dl expose_php file_uploads ignore_repeated_errors ignore_repeated_source log_errors register_argc_argv report_memleaks opcache.enable opcache.consistency_checks opcache.dups_fix opcache.load_comments opcache.revalidate_path opcache.save_comments opcache.use_cwd opcache.fast_shutdown'), ('phpfpm', 'ini_admin_values', 'cgi.redirect_status_env disable_classes disable_functions error_log gpc_order max_input_time max_input_vars memory_limit open_basedir output_buffering post_max_size precision sendmail_path session.gc_divisor session.gc_probability variables_order opcache.log_verbosity_level opcache.restrict_api opcache.revalidate_freq opcache.max_accelerated_files opcache.memory_consumption opcache.interned_strings_buffer opcache.validate_timestamps'), ('nginx', 'fastcgiparams', '/etc/nginx/fastcgi_params'), ('system', 'lastaccountnumber', '0'), ('system', 'lastguid', '9999'), ('system', 'documentroot_prefix', '/var/customers/webs/'), ('system', 'logfiles_directory', '/var/customers/logs/'), ('system', 'ipaddress', 'serverip'), ('system', 'apachereload_command', 'service apache2 reload'), ('system', 'last_traffic_run', '000000'), ('system', 'vmail_uid', '2000'), ('system', 'vmail_gid', '2000'), ('system', 'vmail_homedir', '/var/customers/mail/'), ('system', 'vmail_maildirname', 'maildir'), ('system', 'bind_enable', '0'), ('system', 'bindconf_directory', '/etc/bind/'), ('system', 'bindreload_command', 'service bind9 reload'), ('system', 'hostname', 'servername'), ('system', 'mysql_access_host', 'localhost'), ('system', 'lastcronrun', ''), ('system', 'defaultip', '1'), ('system', 'defaultsslip', ''), ('system', 'phpappendopenbasedir', '/tmp/'), ('system', 'deactivateddocroot', '/var/www/html/froxlor/templates/misc/deactivated/'), ('system', 'mailpwcleartext', '0'), ('system', 'last_tasks_run', '000000'), ('system', 'nameservers', ''), ('system', 'mxservers', ''), ('system', 'mod_fcgid', '0'), ('system', 'apacheconf_vhost', '/etc/apache2/sites-enabled/'), ('system', 'apacheconf_diroptions', '/etc/apache2/sites-enabled/'), ('system', 'apacheconf_htpasswddir', '/etc/apache2/froxlor-htpasswd/'), ('system', 'webalizer_quiet', '2'), ('system', 'last_archive_run', '000000'), ('system', 'mod_fcgid_configdir', '/var/www/php-fcgi-scripts'), ('system', 'mod_fcgid_tmpdir', '/var/customers/tmp'), ('system', 'ssl_cert_file', '/etc/ssl/froxlor_selfsigned.pem'), ('system', 'use_ssl', '0'), ('system', 'default_vhostconf', ''), ('system', 'default_sslvhostconf', ''), ('system', 'mail_quota_enabled', '0'), ('system', 'mail_quota', '100'), ('system', 'httpuser', 'www-data'), ('system', 'httpgroup', 'www-data'), ('system', 'webserver', 'apache2'), ('system', 'mod_fcgid_wrapper', '1'), ('system', 'mod_fcgid_starter', '0'), ('system', 'mod_fcgid_peardir', '/usr/share/php/:/usr/share/php5/'), ('system', 'mod_fcgid_maxrequests', '250'), ('system', 'ssl_key_file','/etc/ssl/froxlor_selfsigned.key'), ('system', 'ssl_ca_file', ''), ('system', 'debug_cron', '0'), ('system', 'store_index_file_subs', '1'), ('system', 'stdsubdomain', ''), ('system', 'awstats_path', '/usr/share/awstats/tools/'), ('system', 'awstats_conf', '/etc/awstats/'), ('system', 'awstats_logformat', '1'), ('system', 'defaultttl', '604800'), ('system', 'mod_fcgid_defaultini', '1'), ('system', 'ftpserver', 'proftpd'), ('system', 'dns_createmailentry', '0'), ('system', 'dns_createcaaentry', '1'), ('system', 'froxlordirectlyviahostname', '1'), ('system', 'report_enable', '1'), ('system', 'report_webmax', '90'), ('system', 'report_trafficmax', '90'), ('system', 'validate_domain', '1'), ('system', 'diskquota_enabled', '0'), ('system', 'diskquota_repquota_path', '/usr/sbin/repquota'), ('system', 'diskquota_quotatool_path', '/usr/bin/quotatool'), ('system', 'diskquota_customer_partition', '/dev/root'), ('system', 'mod_fcgid_idle_timeout', '30'), ('system', 'perl_path', '/usr/bin/perl'), ('system', 'mod_fcgid_ownvhost', '0'), ('system', 'mod_fcgid_httpuser', 'froxlorlocal'), ('system', 'mod_fcgid_httpgroup', 'froxlorlocal'), ('system', 'awstats_awstatspath', '/usr/lib/cgi-bin/'), ('system', 'mod_fcgid_defaultini_ownvhost', '2'), ('system', 'awstats_icons', '/usr/share/awstats/icon/'), ('system', 'ssl_cert_chainfile', ''), ('system', 'ssl_cipher_list', 'ecdh+aesgcm:ecdh+aes256:!anull:!md5:!dss:!dh:!aes128'), ('system', 'nginx_php_backend', '127.0.0.1:8888'), ('system', 'http2_support', '0'), ('system', 'perl_server', 'unix:/var/run/nginx/cgiwrap-dispatch.sock'), ('system', 'phpreload_command', ''), ('system', 'apache24', '1'), ('system', 'apache24_ocsp_cache_path', 'shmcb:/var/run/apache2/ocsp-stapling.cache(131072)'), ('system', 'documentroot_use_default_value', '0'), ('system', 'passwordcryptfunc', '2y'), ('system', 'axfrservers', ''), ('system', 'powerdns_mode', 'native'), ('system', 'customer_ssl_path', '/etc/ssl/froxlor-custom/'), ('system', 'allow_error_report_admin', '1'), ('system', 'allow_error_report_customer', '0'), ('system', 'mdalog', '/var/log/mail.log'), ('system', 'mtalog', '/var/log/mail.log'), ('system', 'mdaserver', 'dovecot'), ('system', 'mtaserver', 'postfix'), ('system', 'mailtraffic_enabled', '1'), ('system', 'cronconfig', '/etc/cron.d/froxlor'), ('system', 'crondreload', 'service cron reload'), ('system', 'croncmdline', '/usr/bin/nice -n 5 /usr/bin/php -q'), ('system', 'cron_allowautoupdate', '0'), ('system', 'dns_createhostnameentry', '0'), ('system', 'send_cron_errors', '0'), ('system', 'apacheitksupport', '0'), ('system', 'leprivatekey', 'unset'), ('system', 'lepublickey', 'unset'), ('system', 'letsencryptca', 'letsencrypt'), ('system', 'letsencryptchallengepath', '/var/www/html/froxlor'), ('system', 'letsencryptkeysize', '4096'), ('system', 'letsencryptreuseold', 0), ('system', 'leenabled', '0'), ('system', 'leapiversion', '2'), ('system', 'exportenabled', '0'), ('system', 'dnsenabled', '0'), ('system', 'dns_server', 'bind'), ('system', 'apacheglobaldiropt', ''), ('system', 'allow_customer_shell', '0'), ('system', 'available_shells', ''), ('system', 'le_froxlor_enabled', '0'), ('system', 'le_froxlor_redirect', '0'), ('system', 'le_renew_hook', 'systemctl restart postfix dovecot proftpd'), ('system', 'le_renew_services', ''), ('system', 'letsencryptacmeconf', '/etc/apache2/conf-enabled/acme.conf'), ('system', 'mail_use_smtp', '0'), ('system', 'mail_smtp_host', 'localhost'), ('system', 'mail_smtp_port', '25'), ('system', 'mail_smtp_usetls', '1'), ('system', 'mail_smtp_auth', '1'), ('system', 'mail_smtp_user', ''), ('system', 'mail_smtp_passwd', ''), ('system', 'hsts_maxage', '10368000'), ('system', 'hsts_incsub', '0'), ('system', 'hsts_preload', '0'), ('system', 'leregistered', '0'), ('system', 'leaccount', ''), ('system', 'nssextrausers', '1'), ('system', 'le_domain_dnscheck', '1'), ('system', 'le_domain_dnscheck_resolver', '1.1.1.1'), ('system', 'ssl_protocols', 'tlsv1.2'), ('system', 'tlsv13_cipher_list', ''), ('system', 'honorcipherorder', '0'), ('system', 'sessiontickets', '1'), ('system', 'sessionticketsenabled', '1'), ('system', 'logfiles_format', ''), ('system', 'logfiles_type', '1'), ('system', 'logfiles_piped', '0'), ('system', 'logfiles_script', ''), ('system', 'dhparams_file', ''), ('system', 'errorlog_level', 'warn'), ('system', 'leecc', '0'), ('system', 'froxloraliases', ''), ('system', 'apply_specialsettings_default', '1'), ('system', 'apply_phpconfigs_default', '1'), ('system', 'hide_incompatible_settings', '1'), ('system', 'include_default_vhostconf', '0'), ('system', 'soaemail', ''), ('system', 'domaindefaultalias', '0'), ('system', 'createstdsubdom_default', '1'), ('system', 'froxlorusergroup', ''), ('system', 'froxlorusergroup_gid', ''), ('system', 'acmeshpath', '/root/.acme.sh/acme.sh'), ('system', 'distribution', ''), ('system', 'update_channel', 'stable'), ('system', 'updatecheck_data', ''), ('system', 'update_notify_last', ''), ('system', 'traffictool', 'goaccess'), ('system', 'req_limit_per_interval', 60), ('system', 'req_limit_interval', 60), ('api', 'enabled', '0'), ('api', 'customer_default', '1'), ('2fa', 'enabled', '1'), ('panel', 'decimal_places', '4'), ('panel', 'adminmail', 'admin_mail'), ('panel', 'phpmyadmin_url', ''), ('panel', 'webmail_url', ''), ('panel', 'webftp_url', ''), ('panel', 'standardlanguage', 'en'), ('panel', 'pathedit', 'manual'), ('panel', 'paging', '20'), ('panel', 'natsorting', '1'), ('panel', 'sendalternativemail', '0'), ('panel', 'allow_domain_change_admin', '0'), ('panel', 'allow_domain_change_customer', '0'), ('panel', 'frontend', 'froxlor'), ('panel', 'default_theme', 'froxlor'), ('panel', 'password_min_length', '0'), ('panel', 'adminmail_defname', 'froxlor administrator'), ('panel', 'adminmail_return', ''), ('panel', 'unix_names', '1'), ('panel', 'allow_preset', '1'), ('panel', 'allow_preset_admin', '0'), ('panel', 'password_regex', ''), ('panel', 'phpconfigs_hidestdsubdomain', '0'), ('panel', 'phpconfigs_hidesubdomains', '1'), ('panel', 'allow_theme_change_admin', '1'), ('panel', 'allow_theme_change_customer', '1'), ('panel', 'password_alpha_lower', '1'), ('panel', 'password_alpha_upper', '1'), ('panel', 'password_numeric', '0'), ('panel', 'password_special_char_required', '0'), ('panel', 'password_special_char', '!?&lt;&gt;$%+#=@'), ('panel', 'customer_hide_options', ''), ('panel', 'is_configured', '0'), ('panel', 'imprint_url', ''), ('panel', 'terms_url', ''), ('panel', 'privacy_url', ''), ('panel', 'logo_image_header', ''), ('panel', 'logo_image_login', ''), ('panel', 'logo_overridetheme', '0'), ('panel', 'logo_overridecustom', '0'), ('panel', 'settings_mode', '0'), ('panel', 'menu_collapsed', '1'), ('panel', 'version', '2.2.5'), ('panel', 'db_version', '202412030'); drop table exists `panel_tasks`; create table `panel_tasks` ( `id` int(11) unsigned null auto_increment, `type` int(11) null default '0', `data` text, primary key (`id`) ) engine=innodb charset=utf8 collate=utf8_general_ci; insert `panel_tasks` (`type`) values ('99'); drop table exists `panel_templates`; create table `panel_templates` ( `id` int(11) null auto_increment, `adminid` int(11) null default '0', `language` varchar(255) null default '', `templategroup` varchar(255) null default '', `varname` varchar(255) null default '', `value` longtext null, `file_extension` varchar(50) null default 'html', primary key (id), key adminid (adminid) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_traffic`; create table `panel_traffic` ( `id` int(11) unsigned null auto_increment, `customerid` int(11) unsigned null default '0', `year` int(4) unsigned zerofill null default '0000', `month` int(2) unsigned zerofill null default '00', `day` int(2) unsigned zerofill null default '00', `stamp` int(11) unsigned null default '0', `http` bigint(30) unsigned null default '0', `ftp_up` bigint(30) unsigned null default '0', `ftp_down` bigint(30) unsigned null default '0', `mail` bigint(30) unsigned null default '0', primary key (`id`), key `customerid` (`customerid`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_traffic_admins`; create table `panel_traffic_admins` ( `id` int(11) unsigned null auto_increment, `adminid` int(11) unsigned null default '0', `year` int(4) unsigned zerofill null default '0000', `month` int(2) unsigned zerofill null default '00', `day` int(2) unsigned zerofill null default '00', `stamp` int(11) unsigned null default '0', `http` bigint(30) unsigned null default '0', `ftp_up` bigint(30) unsigned null default '0', `ftp_down` bigint(30) unsigned null default '0', `mail` bigint(30) unsigned null default '0', primary key (`id`), key `adminid` (`adminid`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_diskspace`; create table `panel_diskspace` ( `id` int(11) unsigned null auto_increment, `customerid` int(11) unsigned null default '0', `year` int(4) unsigned zerofill null default '0000', `month` int(2) unsigned zerofill null default '00', `day` int(2) unsigned zerofill null default '00', `stamp` int(11) unsigned null default '0', `webspace` bigint(30) unsigned null default '0', `mail` bigint(30) unsigned null default '0', `mysql` bigint(30) unsigned null default '0', primary key (`id`), key `customerid` (`customerid`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_syslog`; create table exists `panel_syslog` ( `logid` bigint(20) null auto_increment, `action` int(5) null default '10', `type` int(5) null default '0', `date` int(15) null, `user` varchar(50) null, `text` text null, primary key (`logid`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_fpmdaemons`; create table `panel_fpmdaemons` ( `id` int(11) unsigned null auto_increment, `description` varchar(50) null, `reload_cmd` varchar(255) null, `config_dir` varchar(255) null, `pm` varchar(15) null default 'dynamic', `max_children` int(4) null default '5', `start_servers` int(4) null default '2', `min_spare_servers` int(4) null default '1', `max_spare_servers` int(4) null default '3', `max_requests` int(4) null default '0', `idle_timeout` int(4) null default '10', `limit_extensions` varchar(255) null default '.php', `custom_config` text, primary key (`id`), unique key `reload` (`reload_cmd`), unique key `config` (`config_dir`) ) engine=innodb charset=utf8 collate=utf8_general_ci; insert `panel_fpmdaemons` (`id`, `description`, `reload_cmd`, `config_dir`) values (1, 'system default', 'service php7.4-fpm restart', '/etc/php/7.4/fpm/pool.d/'); drop table exists `panel_phpconfigs`; create table `panel_phpconfigs` ( `id` int(11) unsigned null auto_increment, `description` varchar(50) null, `binary` varchar(255) null, `file_extensions` varchar(255) null, `mod_fcgid_starter` int(4) null default '-1', `mod_fcgid_maxrequests` int(4) null default '-1', `mod_fcgid_umask` varchar(15) null default '022', `fpm_slowlog` tinyint(1) null default '0', `fpm_reqterm` varchar(15) null default '60s', `fpm_reqslow` varchar(15) null default '5s', `phpsettings` text null, `fpmsettingid` int(11) null default '1', `pass_authorizationheader` tinyint(1) null default '0', `override_fpmconfig` tinyint(1) null default '0', `pm` varchar(15) null default 'dynamic', `max_children` int(4) null default '5', `start_servers` int(4) null default '2', `min_spare_servers` int(4) null default '1', `max_spare_servers` int(4) null default '3', `max_requests` int(4) null default '0', `idle_timeout` int(4) null default '10', `limit_extensions` varchar(255) null default '.php', primary key (`id`), key `fpmsettingid` (`fpmsettingid`) ) engine=innodb charset=utf8 collate=utf8_general_ci; insert `panel_phpconfigs` (`id`, `description`, `binary`, `file_extensions`, `mod_fcgid_starter`, `mod_fcgid_maxrequests`, `pass_authorizationheader`, `phpsettings`) values (1, 'default config', '/usr/bin/php-cgi', 'php', '-1', '-1', '1', 'allow_url_fopen = off\r\nallow_url_include = off\r\nauto_append_file =\r\nauto_globals_jit = on\r\nauto_prepend_file =\r\nbcmath.scale = 0\r\ncli_server.color = on\r\ndefault_charset = "utf-8"\r\ndefault_mimetype = "text/html"\r\ndefault_socket_timeout = 60\r\nasp_tags = off\r\ndisable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,curl_exec,curl_multi_exec,exec,parse_ini_file,passthru,popen,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,shell_exec,show_source,system\r\ndisplay_errors = off\r\ndisplay_startup_errors = off\r\ndoc_root =\r\nenable_dl = off\r\nerror_reporting = e_all &amp; ~e_deprecated &amp; ~e_strict &amp; ~e_notice\r\nexpose_php = off\r\nfile_uploads = on\r\nhtml_errors = on\r\nignore_repeated_errors = off\r\nignore_repeated_source = off\r\ninclude_path = ".:{pear_dir}"\r\nimplicit_flush = off\r\nldap.max_links = -1\r\nlog_errors = on\r\nlog_errors_max_len = 1024\r\nmail.add_x_header = off\r\nmax_execution_time = 30\r\nmax_file_uploads = 20\r\nmax_input_time = 60\r\nmemory_limit = 128m\r\n{open_basedir_c}open_basedir = "{open_basedir}"\r\noutput_buffering = 4096\r\npost_max_size = 16m\r\nprecision = 14\r\nregister_argc_argv = off\r\nreport_memleaks = on\r\nrequest_order = "gp"\r\nsendmail_path = "/usr/sbin/sendmail -t -i -f {customer_email}"\r\nserialize_precision = -1\r\nsession.auto_start = 0\r\nsession.cache_expire = 180\r\nsession.cache_limiter = nocache\r\nsession.cookie_domain =\r\nsession.cookie_httponly =\r\nsession.cookie_lifetime = 0\r\nsession.cookie_path = /\r\nsession.cookie_samesite =\r\nsession.gc_divisor = 1000\r\nsession.gc_maxlifetime = 1440\r\nsession.gc_probability = 0\r\nsession.name = phpsessid\r\nsession.referer_check =\r\nsession.save_handler = files\r\nsession.save_path = "{tmp_dir}"\r\nsession.serialize_handler = php\r\nsession.sid_bits_per_character = 5\r\nsession.sid_length = 26\r\nsession.trans_sid_tags = "a=href,area=href,frame=src,form="\r\nsession.use_cookies = 1\r\nsession.use_only_cookies = 1\r\nsession.use_strict_mode = 0\r\nsession.use_trans_sid = 0\r\nshort_open_tag = on\r\nupload_max_filesize = 32m\r\nupload_tmp_dir = "{tmp_dir}"\r\nvariables_order = "gpcs"\r\nopcache.restrict_api = "{document_root}"\r\n'), (2, 'froxlor vhost config', '/usr/bin/php-cgi', 'php', '-1', '-1', '1', 'allow_url_fopen = on\r\nallow_url_include = off\r\nauto_append_file =\r\nauto_globals_jit = on\r\nauto_prepend_file =\r\nbcmath.scale = 0\r\ncli_server.color = on\r\ndefault_charset = "utf-8"\r\ndefault_mimetype = "text/html"\r\ndefault_socket_timeout = 60\r\nasp_tags = off\r\ndisable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,curl_multi_exec,parse_ini_file,passthru,popen,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,shell_exec,show_source,system\r\ndisplay_errors = off\r\ndisplay_startup_errors = off\r\ndoc_root =\r\nenable_dl = off\r\nerror_reporting = e_all &amp; ~e_deprecated &amp; ~e_strict &amp; ~e_notice\r\nexpose_php = off\r\nfile_uploads = on\r\nhtml_errors = on\r\nignore_repeated_errors = off\r\nignore_repeated_source = off\r\ninclude_path = ".:{pear_dir}"\r\nimplicit_flush = off\r\nldap.max_links = -1\r\nlog_errors = on\r\nlog_errors_max_len = 1024\r\nmail.add_x_header = off\r\nmax_execution_time = 60\r\nmax_file_uploads = 20\r\nmax_input_time = 60\r\nmemory_limit = 128m\r\noutput_buffering = 4096\r\npost_max_size = 16m\r\nprecision = 14\r\nregister_argc_argv = off\r\nreport_memleaks = on\r\nrequest_order = "gp"\r\nsendmail_path = "/usr/sbin/sendmail -t -i -f {customer_email}"\r\nserialize_precision = -1\r\nsession.auto_start = 0\r\nsession.cache_expire = 180\r\nsession.cache_limiter = nocache\r\nsession.cookie_domain =\r\nsession.cookie_httponly =\r\nsession.cookie_lifetime = 0\r\nsession.cookie_path = /\r\nsession.cookie_samesite =\r\nsession.gc_divisor = 1000\r\nsession.gc_maxlifetime = 1440\r\nsession.gc_probability = 0\r\nsession.name = phpsessid\r\nsession.referer_check =\r\nsession.save_handler = files\r\nsession.save_path = "{tmp_dir}"\r\nsession.serialize_handler = php\r\nsession.sid_bits_per_character = 5\r\nsession.sid_length = 26\r\nsession.trans_sid_tags = "a=href,area=href,frame=src,form="\r\nsession.use_cookies = 1\r\nsession.use_only_cookies = 1\r\nsession.use_strict_mode = 0\r\nsession.use_trans_sid = 0\r\nshort_open_tag = on\r\nupload_max_filesize = 32m\r\nupload_tmp_dir = "{tmp_dir}"\r\nvariables_order = "gpcs"\r\nopcache.restrict_api = ""\r\n'); drop table exists `cronjobs_run`; create table exists `cronjobs_run` ( `id` bigint(20) null auto_increment, `module` varchar(250) null, `cronfile` varchar(250) null, `cronclass` varchar(500) null, `lastrun` int(15) null default '0', `interval` varchar(100) null default '5 minute', `isactive` tinyint(1) default '1', `desc_lng_key` varchar(100) null default 'cron_unknown_desc', primary key (`id`) ) engine=innodb charset=utf8 collate=utf8_general_ci; insert `cronjobs_run` (`id`, `module`, `cronfile`, `cronclass`, `interval`, `isactive`, `desc_lng_key`) values (1, 'froxlor/core', 'tasks', '\\froxlor\\cron\\system\\taskscron', '5 minute', '1', 'cron_tasks'), (2, 'froxlor/core', 'traffic', '\\froxlor\\cron\\traffic\\trafficcron', '1 day', '1', 'cron_traffic'), (3, 'froxlor/reports', 'usage_report', '\\froxlor\\cron\\traffic\\reportscron', '1 day', '1', 'cron_usage_report'), (4, 'froxlor/core', 'mailboxsize', '\\froxlor\\cron\\system\\mailboxsizecron', '6 hour', '1', 'cron_mailboxsize'), (5, 'froxlor/letsencrypt', 'letsencrypt', '\\froxlor\\cron\\http\\letsencrypt\\acmesh', '5 minute', '0', 'cron_letsencrypt'), (6, 'froxlor/export', 'export', '\\froxlor\\cron\\system\\exportcron', '1 hour', '0', 'cron_export'); drop table exists `ftp_quotalimits`; create table exists `ftp_quotalimits` ( `name` varchar(255) default null, `quota_type` enum('user','group','class','all') null default 'user', `per_session` enum('false','true') null default 'false', `limit_type` enum('soft','hard') null default 'hard', `bytes_in_avail` float null, `bytes_out_avail` float null, `bytes_xfer_avail` float null, `files_in_avail` int(10) unsigned null, `files_out_avail` int(10) unsigned null, `files_xfer_avail` int(10) unsigned null ) engine=innodb charset=utf8 collate=utf8_general_ci; insert `ftp_quotalimits` (`name`, `quota_type`, `per_session`, `limit_type`, `bytes_in_avail`, `bytes_out_avail`, `bytes_xfer_avail`, `files_in_avail`, `files_out_avail`, `files_xfer_avail`) values ('froxlor', 'user', 'false', 'hard', 0, 0, 0, 0, 0, 0); drop table exists `ftp_quotatallies`; create table exists `ftp_quotatallies` ( `name` varchar(255) null, `quota_type` enum('user','group','class','all') null, `bytes_in_used` float null, `bytes_out_used` float null, `bytes_xfer_used` float null, `files_in_used` int(10) unsigned null, `files_out_used` int(10) unsigned null, `files_xfer_used` int(10) unsigned null ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `redirect_codes`; create table exists `redirect_codes` ( `id` int(5) null auto_increment, `code` varchar(3) null, `desc` varchar(200) null, `enabled` tinyint(1) default '1', primary key (`id`) ) engine=innodb charset=utf8 collate=utf8_general_ci; insert `redirect_codes` (`id`, `code`, `desc`, `enabled`) values (1, '---', 'rc_default', 1), (2, '301', 'rc_movedperm', 1), (3, '302', 'rc_found', 1), (4, '303', 'rc_seeother', 1), (5, '307', 'rc_tempred', 1); drop table exists `domain_redirect_codes`; create table exists `domain_redirect_codes` ( `rid` int(5) null, `did` int(11) unsigned null, unique key `rc` (`rid`, `did`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `domain_ssl_settings`; create table exists `domain_ssl_settings` ( `id` int(5) null auto_increment, `domainid` int(11) null, `ssl_cert_file` mediumtext, `ssl_key_file` mediumtext, `ssl_ca_file` mediumtext, `ssl_cert_chainfile` mediumtext, `ssl_csr_file` mediumtext, `ssl_fullchain_file` mediumtext, `validfromdate` datetime default null, `validtodate` datetime default null, `issuer` varchar(255) null default '', primary key (`id`), unique key (`domainid`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_domaintoip`; create table exists `panel_domaintoip` ( `id_domain` int(11) unsigned null, `id_ipandports` int(11) unsigned null, primary key (`id_domain`,`id_ipandports`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `domain_dns_entries`; create table `domain_dns_entries` ( `id` int(20) null auto_increment, `domain_id` int(15) null, `record` varchar(255) null, `type` varchar(10) null default 'a', `content` text null, `ttl` int(11) null default '18000', `prio` int(11) default null, primary key (`id`) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_plans`; create table `panel_plans` ( `id` int(11) null auto_increment, `adminid` int(11) null default '0', `name` varchar(255) null default '', `description` text null, `value` longtext null, `ts` int(15) null default '0', primary key (id), key adminid (adminid) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `api_keys`; create table `api_keys` ( `id` int(11) null auto_increment, `adminid` int(11) null default '0', `customerid` int(11) null default '0', `apikey` varchar(500) null default '', `secret` varchar(500) null default '', `allowed_from` text null, `valid_until` int(15) null default '0', primary key (id), key adminid (adminid), key customerid (customerid) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_usercolumns`; create table `panel_usercolumns` ( `adminid` int(11) null default '0', `customerid` int(11) null default '0', `section` varchar(500) null default '', `columns` text null, unique key `user_section` (`adminid`, `customerid`, `section`), key adminid (adminid), key customerid (customerid) ) engine=innodb charset=utf8 collate=utf8_general_ci; drop table exists `panel_loginlinks`; create table `panel_loginlinks` ( `hash` varchar(500) null, `loginname` varchar(50) null, `valid_until` int(15) null, `allowed_from` text null, unique key `loginname` (`loginname`) ) engine=innodb default charset=utf8 collate=utf8_general_ci; drop table exists `panel_2fa_tokens`; create table `panel_2fa_tokens` ( `id` int(11) null auto_increment, `selector` varchar(200) null, `token` varchar(200) null, `userid` int(11) null default '0', `valid_until` int(15) null, primary key (id) ) engine=innodb default charset=utf8 collate=utf8_general_ci; froxlorsql;</file><file name="install/index.html" /><file name="install/updates/index.html" /><file name="install/updates/preconfig/preconfig_2.2.inc.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\install\update; $preconfig = [ 'title' =&gt; '2.2.x updates', 'fields' =&gt; [] ]; $return = []; (update::versioninupdate($current_version, '2.2.0-dev1')) { $has_preconfig = true; $description = 'froxlor features antispam configurations using rspamd. would like enable antispam feature (required re-configuration services)?&lt;br&gt;&lt;strong&gt;attention:&lt;/strong&gt; enabled former domainkey feature used, keep mind existing domainkeys domain removed dkim-flag disabled domains.'; $question = '&lt;strong&gt;enable antispam (recommended)&lt;/strong&gt;&amp;nbsp;'; $return['antispam_activated'] = [ 'type' =&gt; 'checkbox', 'value' =&gt; 1, 'checked' =&gt; 0, 'label' =&gt; $question, 'prior_infotext' =&gt; $description ]; } $preconfig['fields'] = $return; return $preconfig;</file><file name="install/updates/preconfig/preconfig_0.10.inc.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\install\update; $preconfig = [ 'title' =&gt; '0.10.x updates', 'fields' =&gt; [] ]; $return = []; (update::versioninupdate($current_db_version, '202004140')) { $has_preconfig = true; $description = 'froxlor optionally validate dns entries domains request lets encrypt certificates reduce dns-related problems (e.g. freshly registered domain updated a-record).'; $question = '&lt;strong&gt;validate dns domains using lets encrypt&lt;/strong&gt;'; $return['system_le_domain_dnscheck'] = [ 'type' =&gt; 'checkbox', 'value' =&gt; 1, 'checked' =&gt; 1, 'label' =&gt; $question, 'prior_infotext' =&gt; $description ]; } $preconfig['fields'] = $return; return $preconfig;</file><file name="install/updates/preconfig/preconfig_2.0.inc.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\froxlor; use froxlor\filedir; use froxlor\config\configparser; use froxlor\install\update; use froxlor\settings; $preconfig = [ 'title' =&gt; '2.0.x updates', 'fields' =&gt; [] ]; $return = []; (update::versioninupdate($current_version, '2.0.0-beta1')) { $description = 'we rearranged settings split basic advanced categories. makes easier users need detailed specific settings options gives better overview basic/mostly used settings.'; $question = '&lt;strong&gt;chose settings mode (you change time)&lt;/strong&gt;'; $return['panel_settings_mode'] = [ 'type' =&gt; 'select', 'select_var' =&gt; [ 0 =&gt; 'basic', 1 =&gt; 'advanced' ], 'selected' =&gt; 1, 'label' =&gt; $question, 'prior_infotext' =&gt; $description ]; $description = 'the configuration page preselect distribution, please select current distribution'; $question = '&lt;strong&gt;select distribution&lt;/strong&gt;'; $config_dir = filedir::makecorrectdir(froxlor::getinstalldir() . '/lib/configfiles/'); // show list available distro's $distros = glob($config_dir . '*.xml'); // selection required $distributions_select[''] = '-'; // read distros foreach ($distros $_distribution) { // get configparser object $dist = new configparser($_distribution); // store tmp array $distributions_select[str_replace(".xml", "", strtolower(basename($_distribution)))] = $dist-&gt;getcompletedistroname(); } // sort distribution name asort($distributions_select); $return['system_distribution'] = [ 'type' =&gt; 'select', 'select_var' =&gt; $distributions_select, 'selected' =&gt; '', 'label' =&gt; $question, 'prior_infotext' =&gt; $description ]; } (update::versioninupdate($current_db_version, '202301120')) { $acmesh_challenge_dir = rtrim(filedir::makecorrectdir(settings::get('system.letsencryptchallengepath')), "/"); $recommended = rtrim(filedir::makecorrectdir(froxlor::getinstalldir()), "/"); ((int) settings::get('system.leenabled') == 1 &amp;&amp; $acmesh_challenge_dir != $recommended) { $has_preconfig = true; $description = 'acme challenge docroot settings differs current installation directory.'; $question = '&lt;strong&gt;validate let\'s encrypt challenge path (recommended value: ' . $recommended . ')&lt;/strong&gt;'; $return['system_letsencryptchallengepath_upd'] = [ 'type' =&gt; 'text', 'value' =&gt; $recommended, 'placeholder' =&gt; $acmesh_challenge_dir, 'label' =&gt; $question, 'prior_infotext' =&gt; $description, 'mandatory' =&gt; true, ]; } } (update::versioninupdate($current_db_version, '202301180')) { ((int) settings::get('system.leenabled') == 1) { $has_preconfig = true; $description = 'froxlor supports set external dns resolver let\'s encrypt pre-check.'; $question = '&lt;strong&gt;specify dns resolver ip (recommended value: 1.1.1.1 similar)&lt;/strong&gt;'; $return['system_le_domain_dnscheck_resolver'] = [ 'type' =&gt; 'text', 'pattern' =&gt; '^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$|^(([0-9a-fa-f]{1,4}:){7,7}[0-9a-fa-f]{1,4}|([0-9a-fa-f]{1,4}:){1,7}:|([0-9a-fa-f]{1,4}:){1,6}:[0-9a-fa-f]{1,4}|([0-9a-fa-f]{1,4}:){1,5}(:[0-9a-fa-f]{1,4}){1,2}|([0-9a-fa-f]{1,4}:){1,4}(:[0-9a-fa-f]{1,4}){1,3}|([0-9a-fa-f]{1,4}:){1,3}(:[0-9a-fa-f]{1,4}){1,4}|([0-9a-fa-f]{1,4}:){1,2}(:[0-9a-fa-f]{1,4}){1,5}|[0-9a-fa-f]{1,4}:((:[0-9a-fa-f]{1,4}){1,6})|:((:[0-9a-fa-f]{1,4}){1,7}|:))$|^\s*$', 'value' =&gt; '1.1.1.1', 'placeholder' =&gt; '1.1.1.1', 'label' =&gt; $question, 'prior_infotext' =&gt; $description, ]; } } $preconfig['fields'] = $return; return $preconfig;</file><file name="install/updates/preconfig/index.html" /><file name="install/updates/preconfig/preconfig_2.1.inc.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\froxlor; use froxlor\filedir; use froxlor\config\configparser; use froxlor\install\update; use froxlor\settings; $preconfig = [ 'title' =&gt; '2.1.x updates', 'fields' =&gt; [] ]; $return = []; (update::versioninupdate($current_version, '2.1.0-dev1')) { } $preconfig['fields'] = $return; return $preconfig;</file><file name="install/updates/froxlor/update_2.1.inc.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @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; (!defined('_cron_update')) { (!defined('area') || (defined('area') &amp;&amp; area != 'admin') || !isset($userinfo['loginname']) || (isset($userinfo['loginname']) &amp;&amp; $userinfo['loginname'] == '')) { header('location: ../../../../index.php'); exit(); } } (froxlor::isfroxlorversion('2.0.24')) { update::showupdatestep("cleaning domains table"); database::query("alter table `" . table_panel_domains . "` row_format=dynamic;"); database::query("alter table `" . table_panel_domains . "` drop column `ismainbutsubto`;"); update::laststepstatus(0); update::showupdatestep("creating new tables fields"); database::query("drop table exists `panel_loginlinks`;"); $sql = "create table `panel_loginlinks` ( `hash` varchar(500) null, `loginname` varchar(50) null, `valid_until` int(15) null, `allowed_from` text null, unique key `loginname` (`loginname`) ) engine=innodb default charset=utf8 collate=utf8_general_ci;"; database::query($sql); update::laststepstatus(0); update::showupdatestep("adding new settings"); settings::addnew('panel.menu_collapsed', 1); update::laststepstatus(0); update::showupdatestep("adjusting setting deactivated webroot"); $current_deactivated_webroot = settings::get('system.deactivateddocroot'); (empty($current_deactivated_webroot)) { settings::set('system.deactivateddocroot', filedir::makecorrectdir(froxlor::getinstalldir() . '/templates/misc/deactivated/')); update::laststepstatus(0); } else { update::laststepstatus(1, 'customized setting, changing'); } update::showupdatestep("adjusting cronjobs"); $cfupd_stmt = database::prepare(" update `" . table_panel_cronruns . "` set `module`= 'froxlor/export', `cronfile` = 'export', `cronclass` = :cc, `interval` = '1 hour', `desc_lng_key` = 'cron_export' `module` = 'froxlor/backup' "); database::pexecute($cfupd_stmt, [ 'cc' =&gt; '\\froxlor\\cron\\system\\exportcron' ]); update::laststepstatus(0); update::showupdatestep("adjusting system data-export function"); database::query("update `" . table_panel_settings . "`set `varname` = 'exportenabled' `settinggroup`= 'system' `varname`= 'backupenabled'"); database::query("update `" . table_panel_settings . "`set `value` = replace(`value`, 'extras.backup', 'extras.export') `settinggroup` = 'panel' `varname` = 'customer_hide_options'"); database::query("delete `" . table_panel_usercolumns . "` `section` = 'backup_list'"); database::query("delete `" . table_panel_tasks . "` `type` = '20'"); update::laststepstatus(0); froxlor::updatetodbversion('202305240'); froxlor::updatetoversion('2.1.0-dev1'); } (froxlor::isfroxlorversion('2.1.0-dev1')) { update::showupdatestep("updating 2.1.0-dev1 2.1.0-beta1", false); froxlor::updatetoversion('2.1.0-beta1'); } (froxlor::isfroxlorversion('2.1.0-beta1')) { update::showupdatestep("updating 2.1.0-beta1 2.1.0-beta2", false); update::showupdatestep("removing unused table"); database::query("drop table exists `panel_sessions`;"); update::laststepstatus(0); froxlor::updatetoversion('2.1.0-beta2'); } (froxlor::isfroxlorversion('2.1.0-beta2')) { update::showupdatestep("updating 2.1.0-beta2 2.1.0-rc1", false); froxlor::updatetoversion('2.1.0-rc1'); } (froxlor::isfroxlorversion('2.1.0-rc1')) { update::showupdatestep("updating 2.1.0-rc1 2.1.0-rc2", false); update::showupdatestep("adjusting setting spf_entry"); $spf_entry = settings::get('spf.spf_entry'); (!preg_match('/^v=spf[a-z0-9:~?\s.-]+$/i', $spf_entry)) { settings::set('spf.spf_entry', 'v=spf1 mx -all'); update::laststepstatus(1, 'corrected'); } else { update::laststepstatus(0); } froxlor::updatetoversion('2.1.0-rc2'); } (froxlor::isdatabaseversion('202305240')) { update::showupdatestep("adjusting file-template file extension setttings"); $current_fileextension = settings::get('system.index_file_extension'); database::query("delete `" . table_panel_settings . "` `settinggroup`= 'system' `varname`= 'index_file_extension'"); database::query("alter table `" . table_panel_templates . "` add `file_extension` varchar(50) null default 'html';"); (!empty(trim($current_fileextension)) &amp;&amp; strtolower(trim($current_fileextension)) != 'html') { $stmt = database::prepare("update `" . table_panel_templates . "` set `file_extension` = :ext `templategroup` = 'files'"); database::pexecute($stmt, ['ext' =&gt; strtolower(trim($current_fileextension))]); } update::laststepstatus(0); froxlor::updatetodbversion('202311260'); } (froxlor::isfroxlorversion('2.1.0-rc2')) { update::showupdatestep("updating 2.1.0-rc2 2.1.0-rc3", false); froxlor::updatetoversion('2.1.0-rc3'); } (froxlor::isdatabaseversion('202311260')) { $to_clean = array( "install/updates/froxlor/update_2.x.inc.php", "install/updates/preconfig/preconfig_2.x.inc.php", "lib/froxlor/api/commands/customerbackups.php", "lib/froxlor/cli/action", "lib/froxlor/cli/action.php", "lib/froxlor/cli/cmdlinehandler.php", "lib/froxlor/cli/configservicescmd.php", "lib/froxlor/cli/phpsessioncleancmd.php", "lib/froxlor/cli/switchserveripcmd.php", "lib/froxlor/cli/updateclicmd.php", "lib/froxlor/cron/system/backupcron.php", "lib/formfields/customer/extras/formfield.backup.php", "lib/tablelisting/customer/tablelisting.backups.php", "templates/froxlor/assets/mix-manifest.json", "templates/froxlor/assets/css", "templates/froxlor/assets/webfonts", "templates/froxlor/assets/js/main.js", "templates/froxlor/assets/js/main.js.license.txt", "templates/froxlor/src", "templates/froxlor/user/change_language.html.twig", "templates/froxlor/user/change_password.html.twig", "templates/froxlor/user/change_theme.html.twig", "tests/backup/customerbackupstest.php" ); update::cleanoldfiles($to_clean); froxlor::updatetodbversion('202312050'); } (froxlor::isfroxlorversion('2.1.0-rc3')) { update::showupdatestep("updating 2.1.0-rc3 2.1.0 stable", false); froxlor::updatetoversion('2.1.0'); } (froxlor::isfroxlorversion('2.1.0')) { update::showupdatestep("updating 2.1.0 2.1.1", false); froxlor::updatetoversion('2.1.1'); } (froxlor::isdatabaseversion('202312050')) { $to_clean = array( "lib/configfiles/centos7.xml", "lib/configfiles/centos8.xml", "lib/configfiles/stretch.xml", "lib/configfiles/xenial.xml", "lib/configfiles/buster.xml", "lib/configfiles/bionic.xml", ); update::cleanoldfiles($to_clean); froxlor::updatetodbversion('202312100'); } (froxlor::isdatabaseversion('202312100')) { update::showupdatestep("adjusting table row format larger tables"); database::query("alter table `" . table_panel_admins . "` row_format=dynamic;"); database::query("alter table `" . table_panel_domains . "` row_format=dynamic;"); update::laststepstatus(0); froxlor::updatetodbversion('202312120'); } (froxlor::isfroxlorversion('2.1.1')) { update::showupdatestep("updating 2.1.1 2.1.2", false); froxlor::updatetoversion('2.1.2'); } (froxlor::isfroxlorversion('2.1.2')) { update::showupdatestep("updating 2.1.2 2.1.3", false); froxlor::updatetoversion('2.1.3'); } (froxlor::isfroxlorversion('2.1.3')) { update::showupdatestep("updating 2.1.3 2.1.4", false); froxlor::updatetoversion('2.1.4'); } (froxlor::isfroxlorversion('2.1.4')) { update::showupdatestep("updating 2.1.4 2.1.5", false); froxlor::updatetoversion('2.1.5'); } (froxlor::isfroxlorversion('2.1.5')) { update::showupdatestep("updating 2.1.5 2.1.6", false); froxlor::updatetoversion('2.1.6'); } (froxlor::isfroxlorversion('2.1.6')) { update::showupdatestep("updating 2.1.6 2.1.7", false); froxlor::updatetoversion('2.1.7'); } (froxlor::isfroxlorversion('2.1.7')) { update::showupdatestep("updating 2.1.7 2.1.8", false); froxlor::updatetoversion('2.1.8'); } (froxlor::isfroxlorversion('2.1.8')) { update::showupdatestep("updating 2.1.8 2.1.9", false); froxlor::updatetoversion('2.1.9'); }</file><file name="install/updates/froxlor/update_2.0.inc.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @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; (!defined('_cron_update')) { (!defined('area') || (defined('area') &amp;&amp; area != 'admin') || !isset($userinfo['loginname']) || (isset($userinfo['loginname']) &amp;&amp; $userinfo['loginname'] == '')) { header('location: ../../../../index.php'); exit(); } } // last 0.10.x release (froxlor::isfroxlorversion('0.10.38.3')) { $update_to = '2.0.0-beta1'; update::showupdatestep("updating 0.10.38.3 " . $update_to, false); update::showupdatestep("removing unused table"); database::query("drop table exists `panel_sessions`;"); database::query("drop table exists `panel_languages`;"); update::laststepstatus(0); update::showupdatestep("updating froxlor - theme"); database::query("update `" . table_panel_admins . "` set `theme` = 'froxlor' `theme` &lt;&gt; 'froxlor';"); database::query("update `" . table_panel_customers . "` set `theme` = 'froxlor' `theme` &lt;&gt; 'froxlor';"); settings::set('panel.default_theme', 'froxlor'); update::laststepstatus(0); update::showupdatestep("creating new tables fields"); database::query("drop table exists `panel_usercolumns`;"); $sql = "create table `panel_usercolumns` ( `adminid` int(11) null default '0', `customerid` int(11) null default '0', `section` varchar(500) null default '', `columns` text 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) null default '';"); database::query("alter table `" . table_panel_customers . "` change column `allowed_phpconfigs` `allowed_phpconfigs` text null;"); database::query("alter table `" . table_panel_customers . "` add `allowed_mysqlserver` text null;"); $has_customer_table_update_200 = true; // ftp_users adjustments database::query("alter table `" . table_ftp_users . "` change column `password` `password` varchar(255) 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) null default '';"); database::query("alter table `" . table_mail_users . "` change column `password_enc` `password_enc` varchar(255) null default '';"); // drop domains_see_all field panel_admins database::query("alter table `" . table_panel_admins . "` drop column `domains_see_all`;"); update::laststepstatus(0); update::showupdatestep("checking multiple mysql-servers allow access customers existing databases"); $dbservers_stmt = database::query(" select `customerid`, group_concat(distinct `dbserver` separator ',') allowed_mysqlserver `" . table_panel_databases . "` group `customerid`; "); $upd_stmt = database::prepare("update `" . table_panel_customers . "` set `allowed_mysqlserver` = :allowed_mysqlserver `customerid` = :customerid"); ($dbserver = $dbservers_stmt-&gt;fetch(pdo::fetch_assoc)) { (isset($dbserver['allowed_mysqlserver']) &amp;&amp; !empty($dbserver['allowed_mysqlserver'])) { $allowed_mysqlserver = json_encode(explode(",", $dbserver['allowed_mysqlserver'])); database::pexecute($upd_stmt, ['allowed_mysql_server' =&gt; $allowed_mysqlserver, 'customerid' =&gt; $dbserver['customerid']]); } } update::laststepstatus(0); $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", ); update::cleanoldfiles($to_clean); 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' =&gt; 'de', 'english' =&gt; 'en', 'fran&amp;ccedil;ais' =&gt; 'fr', 'portugu&amp;ecirc;s' =&gt; 'pt', 'italiano' =&gt; 'it', 'nederlands' =&gt; 'nl', 'svenska' =&gt; 'se', '&amp;#268;esk&amp;aacute; republika' =&gt; 'cz' ]; // update user default languages $upd_adm_stmt = database::prepare("update `" . table_panel_admins . "` set `def_language` = :nv `def_language` = :ov"); $upd_cus_stmt = database::prepare("update `" . table_panel_customers . "` set `def_language` = :nv `def_language` = :ov"); foreach ($lang_map $old_val =&gt; $new_val) { database::pexecute($upd_adm_stmt, ['nv' =&gt; $new_val, 'ov' =&gt; $old_val]); database::pexecute($upd_cus_stmt, ['nv' =&gt; $new_val, 'ov' =&gt; $old_val]); } settings::set('panel.standardlanguage', $lang_map[settings::get('panel_standardlanguage')] ?? 'en'); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'system' `varname` = 'debug_cron'"); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'system' `varname` = 'letsencryptcountrycode'"); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'system' `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$') substring(`password_enc`, 1, 3) = '$1$'"); database::query("update `" . table_mail_users . "` set `password_enc` = replace(`password_enc`, '$5$', '{sha256-crypt}$5$') substring(`password_enc`, 1, 3) = '$5$'"); database::query("update `" . table_mail_users . "` set `password_enc` = replace(`password_enc`, '$6$', '{sha512-crypt}$6$') substring(`password_enc`, 1, 3) = '$6$'"); database::query("update `" . table_mail_users . "` set `password_enc` = replace(`password_enc`, '$2y$', '{blf-crypt}$2y$') substring(`password_enc`, 1, 4) = '$2y$'"); update::laststepstatus(0); froxlor::updatetoversion($update_to); } (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 `" . table_panel_settings . "` `settinggroup` = 'system' `varname` = 'awstats_enabled'"); update::laststepstatus(0); froxlor::updatetodbversion('202211030'); } (froxlor::isdatabaseversion('202211030')) { update::showupdatestep("creating backward compatibility cronjob"); $disabled = explode(',', ini_get('disable_functions')); $exec_allowed = !in_array('exec', $disabled); // check whether old files could deleted previous updates not, // user run cron regenerate cron.d-file manually run // commands manually update file would deleted ($exec_allowed) { $complete_filedir = froxlor::getinstalldir() . '/scripts'; mkdir($complete_filedir, 0750, true); $newcronbin = froxlor::getinstalldir() . '/bin/froxlor-cli'; $compcron = &lt;&lt;&lt;eof &lt;?php chmod('$newcronbin', 0755); // re-create cron.d configuration file exec('$newcronbin froxlor:cron -r 99'); exit; eof; file_put_contents($complete_filedir . '/froxlor_master_cronjob.php', $compcron); update::laststepstatus(0); } else { $cron_run_cmd = 'chmod +x ' . filedir::makecorrectfile(froxlor::getinstalldir() . '/bin/froxlor-cli') . php_eol; $cron_run_cmd .= filedir::makecorrectfile(froxlor::getinstalldir() . '/bin/froxlor-cli') . ' froxlor:cron -r 99'; update::laststepstatus(1, 'manual commands needed', 'please run following commands manually:&lt;br&gt;&lt;pre&gt;' . $cron_run_cmd . '&lt;/pre&gt;'); } froxlor::updatetodbversion('202212060'); } (froxlor::isfroxlorversion('2.0.0-beta1')) { update::showupdatestep("updating 2.0.0-beta1 2.0.0", false); froxlor::updatetoversion('2.0.0'); } (froxlor::isfroxlorversion('2.0.0')) { update::showupdatestep("updating 2.0.0 2.0.1", false); (!isset($has_customer_table_update_200)) { update::showupdatestep("creating new tables fields"); // new customer allowed_mysqlserver field database::query("alter table `" . table_panel_customers . "` change column `allowed_mysqlserver` `allowed_mysqlserver` text null;"); database::query("alter table `" . table_panel_customers . "` change column `allowed_phpconfigs` `allowed_phpconfigs` text null;"); database::query("alter table `" . table_panel_customers . "` change column `customernumber` `customernumber` varchar(100) null default '';"); update::laststepstatus(0); } froxlor::updatetoversion('2.0.1'); } (froxlor::isfroxlorversion('2.0.1')) { update::showupdatestep("updating 2.0.1 2.0.2", false); froxlor::updatetoversion('2.0.2'); } (froxlor::isfroxlorversion('2.0.2')) { update::showupdatestep("updating 2.0.2 2.0.3", false); froxlor::updatetoversion('2.0.3'); } (froxlor::isfroxlorversion('2.0.3')) { update::showupdatestep("updating 2.0.3 2.0.4", false); $complete_filedir = froxlor::getinstalldir() . '/scripts'; // check compat. cronjob still exists (most likely run successfully b/c error former 2.0 release) (@file_exists($complete_filedir . '/froxlor_master_cronjob.php')) { update::showupdatestep("adjusting backward compatibility cronjob"); $disabled = explode(',', ini_get('disable_functions')); $exec_allowed = !in_array('exec', $disabled); ($exec_allowed) { $newcronbin = froxlor::getinstalldir() . '/bin/froxlor-cli'; $compcron = &lt;&lt;&lt;eof &lt;?php chmod('$newcronbin', 0755); // re-create cron.d configuration file exec('$newcronbin froxlor:cron -r 99'); exit; eof; file_put_contents($complete_filedir . '/froxlor_master_cronjob.php', $compcron); update::laststepstatus(0); } else { $cron_run_cmd = 'chmod +x ' . filedir::makecorrectfile(froxlor::getinstalldir() . '/bin/froxlor-cli') . php_eol; $cron_run_cmd .= filedir::makecorrectfile(froxlor::getinstalldir() . '/bin/froxlor-cli') . ' froxlor:cron -r 99'; update::laststepstatus(1, 'manual commands needed', 'please run following commands manually:&lt;br&gt;&lt;pre&gt;' . $cron_run_cmd . '&lt;/pre&gt;'); } } froxlor::updatetoversion('2.0.4'); } (froxlor::isfroxlorversion('2.0.4')) { update::showupdatestep("updating 2.0.4 2.0.5", false); froxlor::updatetoversion('2.0.5'); } (froxlor::isfroxlorversion('2.0.5')) { update::showupdatestep("updating 2.0.5 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$') substring(`password_enc`, 1, 3) = '$1$'"); database::query("update `" . table_mail_users . "` set `password_enc` = replace(`password_enc`, '$5$', '{sha256-crypt}$5$') substring(`password_enc`, 1, 3) = '$5$'"); database::query("update `" . table_mail_users . "` set `password_enc` = replace(`password_enc`, '$6$', '{sha512-crypt}$6$') substring(`password_enc`, 1, 3) = '$6$'"); database::query("update `" . table_mail_users . "` set `password_enc` = replace(`password_enc`, '$2y$', '{blf-crypt}$2y$') substring(`password_enc`, 1, 4) = '$2y$'"); update::laststepstatus(0); froxlor::updatetoversion('2.0.6'); } (froxlor::isfroxlorversion('2.0.6')) { update::showupdatestep("updating 2.0.6 2.0.7", false); update::showupdatestep("correcting allowed_mysqlserver customers"); database::query("update `" . table_panel_customers . "` set `allowed_mysqlserver` = '[0]' `allowed_mysqlserver` = ''"); update::laststepstatus(0); froxlor::updatetoversion('2.0.7'); } (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; ($acmesh_challenge_dir != $system_letsencryptchallengepath_upd) { settings::set('system.letsencryptchallengepath', $system_letsencryptchallengepath_upd); ((int)settings::get('system.leenabled') == 1) { // create json string --apply $dist = settings::get('system.distribution'); $webserver = settings::get('system.webserver'); ($webserver == 'apache2') { $webserver = 'apache22'; (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 &lt;pre&gt;bin/froxlor-cli froxlor:config-services --apply='" . $apply_json . "'&lt;/pre&gt;" . '&lt;br&gt;or adjust path manually &lt;pre&gt;' . settings::get('system.letsencryptacmeconf') . '&lt;/pre&gt;' . '&lt;br&gt;&lt;br&gt;in case already certificates issued, run following command validate correct webroot used renewal:&lt;br&gt;' . '&lt;pre&gt;bin/froxlor-cli froxlor:validate-acme-webroot&lt;/pre&gt;&lt;br&gt;' ); } else { update::laststepstatus(0); } } else { update::laststepstatus(0); } froxlor::updatetodbversion('202301120'); } (froxlor::isfroxlorversion('2.0.7')) { update::showupdatestep("updating 2.0.7 2.0.8", false); // adjust file-logging set froxlor/logs/ $logtypes = explode(',', settings::get('logger.logtypes')); (in_array('file', $logtypes)) { update::showupdatestep("adjusting froxlor logfile system-logging stored logs/froxlor.log"); settings::set('logger.logfile', 'froxlor.log'); update::laststepstatus(0); } froxlor::updatetoversion('2.0.8'); } (froxlor::isdatabaseversion('202301120')) { update::showupdatestep("adding new setting dns resolver 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'); } (froxlor::isfroxlorversion('2.0.8')) { update::showupdatestep("updating 2.0.8 2.0.9", false); froxlor::updatetoversion('2.0.9'); } (froxlor::isfroxlorversion('2.0.9')) { update::showupdatestep("updating 2.0.9 2.0.10", false); froxlor::updatetoversion('2.0.10'); } (froxlor::isdatabaseversion('202301180')) { update::showupdatestep("adding new setting 'allow api access' default value new customers"); settings::addnew("api.customer_default", "1"); update::laststepstatus(0); froxlor::updatetodbversion('202302030'); } (froxlor::isfroxlorversion('2.0.10')) { update::showupdatestep("updating 2.0.10 2.0.11", false); froxlor::updatetoversion('2.0.11'); } (froxlor::isfroxlorversion('2.0.11')) { update::showupdatestep("updating 2.0.11 2.0.12", false); froxlor::updatetoversion('2.0.12'); } (froxlor::isfroxlorversion('2.0.12')) { update::showupdatestep("updating 2.0.12 2.0.13", false); froxlor::updatetoversion('2.0.13'); } (froxlor::isdatabaseversion('202302030')) { update::showupdatestep("correcting language mapping templates created pre 2.0.x"); // languages 0.10.x $language_mapping_comp = [ 'de' =&gt; 'deutsch', 'en' =&gt; 'english', 'fr' =&gt; 'fran&amp;ccedil;ais', 'pt' =&gt; 'portugu&amp;ecirc;s', 'it' =&gt; 'italiano', 'nl' =&gt; 'nederlands', 'se' =&gt; 'svenska', 'cz' =&gt; '&amp;#268;esk&amp;aacute; republika' ]; $upd_tpl_stmt = database::prepare("update `" . table_panel_templates . "` set `language` = :iso `language` = :lng"); foreach ($language_mapping_comp $iso =&gt; $lang) { database::pexecute($upd_tpl_stmt, ['iso' =&gt; $iso, 'lng' =&gt; $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 `ssl_fullchain_file`;"); database::query("alter table `" . table_panel_domain_ssl_settings . "` add `issuer` varchar(255) null default '' `validtodate`;"); update::laststepstatus(0); update::showupdatestep("filling new ssl data fields existing certificate data"); $crt_upd_stmt = database::prepare("update `" . table_panel_domain_ssl_settings . "` set `validfromdate` = :validfromdate, `issuer` = :issuer `id` = :id"); $crt_stmt = database::prepare("select * `" . table_panel_domain_ssl_settings . "`"); database::pexecute($crt_stmt); ($cert = $crt_stmt-&gt;fetch(\pdo::fetch_assoc)) { $cert_content = openssl_x509_parse($cert['ssl_cert_file']); (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' =&gt; $validfromdate, 'issuer' =&gt; $issuer, 'id' =&gt; $cert['id']]); } } // clear possible user customized columns database::query("delete `" . table_panel_usercolumns . "` `section` = 'sslcertificates_list'"); update::laststepstatus(0); froxlor::updatetodbversion('202303150'); } (froxlor::isfroxlorversion('2.0.13')) { update::showupdatestep("updating 2.0.13 2.0.14", false); froxlor::updatetoversion('2.0.14'); } (froxlor::isfroxlorversion('2.0.14')) { update::showupdatestep("updating 2.0.14 2.0.15", false); froxlor::updatetoversion('2.0.15'); } (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'); } (froxlor::isfroxlorversion('2.0.15')) { update::showupdatestep("updating 2.0.15 2.0.16", false); froxlor::updatetoversion('2.0.16'); } (froxlor::isfroxlorversion('2.0.16')) { update::showupdatestep("updating 2.0.16 2.0.17", false); froxlor::updatetoversion('2.0.17'); } (froxlor::isfroxlorversion('2.0.17')) { update::showupdatestep("updating 2.0.17 2.0.18", false); froxlor::updatetoversion('2.0.18'); } (froxlor::isfroxlorversion('2.0.18')) { update::showupdatestep("updating 2.0.18 2.0.19", false); froxlor::updatetoversion('2.0.19'); } (froxlor::isfroxlorversion('2.0.19')) { update::showupdatestep("updating 2.0.19 2.0.20", false); froxlor::updatetoversion('2.0.20'); } (froxlor::isfroxlorversion('2.0.20')) { update::showupdatestep("updating 2.0.20 2.0.21", false); froxlor::updatetoversion('2.0.21'); } (froxlor::isfroxlorversion('2.0.21')) { update::showupdatestep("updating 2.0.21 2.0.22", false); froxlor::updatetoversion('2.0.22'); } (froxlor::isfroxlorversion('2.0.22')) { update::showupdatestep("updating 2.0.22 2.0.23", false); froxlor::updatetoversion('2.0.23'); } (froxlor::isfroxlorversion('2.0.23')) { update::showupdatestep("updating 2.0.23 2.0.24", false); froxlor::updatetoversion('2.0.24'); }</file><file name="install/updates/froxlor/update_0.10.inc.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @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; use froxlor\system\cronjob; use froxlor\system\iptools; (!defined('_cron_update')) { (!defined('area') || (defined('area') &amp;&amp; area != 'admin') || !isset($userinfo['loginname']) || (isset($userinfo['loginname']) &amp;&amp; $userinfo['loginname'] == '')) { header('location: ../../../../index.php'); exit(); } } (froxlor::isfroxlorversion('0.9.40.1')) { update::showupdatestep("updating 0.9.40.1 0.10.0-rc1", false); update::showupdatestep("adding new api keys table"); database::query("drop table exists `api_keys`;"); $sql = "create table `api_keys` ( `id` int(11) null auto_increment, `adminid` int(11) null default '0', `customerid` int(11) null default '0', `apikey` varchar(500) null default '', `secret` varchar(500) null default '', `allowed_from` text null, `valid_until` int(15) null default '0', primary key (id), key adminid (adminid), key customerid (customerid) ) engine=myisam charset=utf8 collate=utf8_general_ci;"; database::query($sql); update::laststepstatus(0); update::showupdatestep("adding new api settings"); settings::addnew('api.enabled', 0); update::laststepstatus(0); update::showupdatestep("adding new default-ssl-ip setting"); settings::addnew('system.defaultsslip', ''); update::laststepstatus(0); update::showupdatestep("altering admin ip's field allow multiple ip addresses"); // get admins updating new field $sel_stmt = database::prepare("select adminid, ip `panel_admins`"); database::pexecute($sel_stmt); $all_admins = $sel_stmt-&gt;fetchall(pdo::fetch_assoc); database::query("alter table `panel_admins` modify `ip` varchar(500) null default '-1';"); $upd_stmt = database::prepare("update `panel_admins` set `ip` = :ip `adminid` = :adminid"); foreach ($all_admins $adm) { ($adm['ip'] != '-1') { database::pexecute($upd_stmt, array( 'ip' =&gt; json_encode($adm['ip']), 'adminid' =&gt; $adm['adminid'] )); } } update::laststepstatus(0); froxlor::updatetoversion('0.10.0-rc1'); } (froxlor::isdatabaseversion('201809280')) { update::showupdatestep("adding dhparams-file setting"); settings::addnew("system.dhparams_file", ''); update::laststepstatus(0); froxlor::updatetodbversion('201811180'); } (froxlor::isdatabaseversion('201811180')) { update::showupdatestep("adding new settings 2fa"); settings::addnew('2fa.enabled', '1'); update::laststepstatus(0); update::showupdatestep("adding new fields admin-table 2fa"); database::query("alter table `" . table_panel_admins . "` add `type_2fa` tinyint(1) null default '0';"); database::query("alter table `" . table_panel_admins . "` add `data_2fa` varchar(500) null default '' `type_2fa`;"); update::laststepstatus(0); update::showupdatestep("adding new fields customer-table 2fa"); database::query("alter table `" . table_panel_customers . "` add `type_2fa` tinyint(1) null default '0';"); database::query("alter table `" . table_panel_customers . "` add `data_2fa` varchar(500) null default '' `type_2fa`;"); update::laststepstatus(0); froxlor::updatetodbversion('201811300'); } (froxlor::isdatabaseversion('201811300')) { update::showupdatestep("adding new logview-flag customers"); database::query("alter table `" . table_panel_customers . "` add `logviewenabled` tinyint(1) null default '0';"); update::laststepstatus(0); froxlor::updatetodbversion('201812010'); } (froxlor::isdatabaseversion('201812010')) { update::showupdatestep("adding new is_configured-flag"); // updated systems already configured (most likely :p) settings::addnew('panel.is_configured', '1'); update::laststepstatus(0); froxlor::updatetodbversion('201812100'); } (froxlor::isdatabaseversion('201812100')) { update::showupdatestep("adding fields writeaccesslog writeerrorlog domains"); database::query("alter table `" . table_panel_domains . "` add `writeaccesslog` tinyint(1) null default '1';"); database::query("alter table `" . table_panel_domains . "` add `writeerrorlog` tinyint(1) null default '1';"); update::laststepstatus(0); froxlor::updatetodbversion('201812180'); } (froxlor::isdatabaseversion('201812180')) { update::showupdatestep("updating cronjob table"); database::query("alter table `" . table_panel_cronruns . "` add `cronclass` varchar(500) null `cronfile`"); $upd_stmt = database::prepare("update `" . table_panel_cronruns . "` set `cronclass` = :cc `cronfile` = :cf"); database::pexecute($upd_stmt, array( 'cc' =&gt; '\\froxlor\\cron\\system\\taskscron', 'cf' =&gt; 'tasks' )); database::pexecute($upd_stmt, array( 'cc' =&gt; '\\froxlor\\cron\\traffic\\trafficcron', 'cf' =&gt; 'traffic' )); database::pexecute($upd_stmt, array( 'cc' =&gt; '\\froxlor\\cron\\traffic\\reportscron', 'cf' =&gt; 'usage_report' )); database::pexecute($upd_stmt, array( 'cc' =&gt; '\\froxlor\\cron\\system\\mailboxsizecron', 'cf' =&gt; 'mailboxsize' )); database::pexecute($upd_stmt, array( 'cc' =&gt; '\\froxlor\\cron\\http\\letsencrypt\\letsencrypt', 'cf' =&gt; 'letsencrypt' )); database::pexecute($upd_stmt, array( 'cc' =&gt; '\\froxlor\\cron\\system\\backupcron', 'cf' =&gt; 'backup' )); database::query("delete `" . table_panel_cronruns . "` `module` = 'froxlor/ticket'"); update::laststepstatus(0); update::showupdatestep("removing ticketsystem"); database::query("alter table `" . table_panel_admins . "` drop `tickets`"); database::query("alter table `" . table_panel_admins . "` drop `tickets_used`"); database::query("alter table `" . table_panel_admins . "` drop `tickets_see_all`"); database::query("alter table `" . table_panel_customers . "` drop `tickets`"); database::query("alter table `" . table_panel_customers . "` drop `tickets_used`"); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'ticket'"); define('table_panel_tickets', 'panel_tickets'); define('table_panel_ticket_cats', 'panel_ticket_categories'); database::query("drop table exists `" . table_panel_tickets . "`;"); database::query("drop table exists `" . table_panel_ticket_cats . "`;"); update::laststepstatus(0); update::showupdatestep("updating nameserver settings"); $dns_target = 'bind'; (settings::get('system.dns_server') != 'bind') { $dns_target = 'powerdns'; } $upd_stmt = database::prepare("update `" . table_panel_settings . "` set `value` = :v `settinggroup` = 'system' `varname` = 'dns_server'"); database::pexecute($upd_stmt, array( 'v' =&gt; $dns_target )); update::laststepstatus(0); froxlor::updatetodbversion('201812190'); } (froxlor::isdatabaseversion('201812190')) { update::showupdatestep("adding new webserver error-log-level setting"); settings::addnew('system.errorlog_level', (\froxlor\settings::get('system.webserver') == 'nginx' ? 'error' : 'warn')); update::laststepstatus(0); froxlor::updatetodbversion('201902120'); } (froxlor::isdatabaseversion('201902120')) { update::showupdatestep("adding new ecc / ecdsa setting let's encrypt"); settings::addnew('system.leecc', '0'); $upd_stmt = database::prepare("update `" . table_panel_cronruns . "` set `cronclass` = :cc `cronfile` = :cf"); database::pexecute($upd_stmt, array( 'cc' =&gt; '\\froxlor\\cron\\http\\letsencrypt\\acmesh', 'cf' =&gt; 'letsencrypt' )); settings::set('system.letsencryptkeysize', '4096', true); update::laststepstatus(0); update::showupdatestep("removing current let's encrypt certificates due new implementation acme.sh"); $sel_result = database::query("select id `" . table_panel_domains . "` `letsencrypt` = '1'"); $domain_ids = $sel_result-&gt;fetchall(\pdo::fetch_assoc); (count($domain_ids) &gt; 0) { $domain_in = ""; foreach ($domain_ids $domain_id) { $domain_in .= "'" . $domain_id['id'] . "',"; } $domain_in = substr($domain_in, 0, -1); database::query("delete `" . table_panel_domain_ssl_settings . "` `domainid` (" . $domain_in . ")"); } // check froxlor domain using let's encrypt (settings::get('system.le_froxlor_enabled') == 1) { database::query("delete `" . table_panel_domain_ssl_settings . "` `domainid` = '0'"); } update::laststepstatus(0); update::showupdatestep("inserting job regenerate configfiles"); cronjob::inserttask('1'); update::laststepstatus(0); froxlor::updatetodbversion('201902170'); } (froxlor::isdatabaseversion('201902170')) { update::showupdatestep("adding new froxlor vhost domain alias setting"); settings::addnew('system.froxloraliases', ""); update::laststepstatus(0); froxlor::updatetodbversion('201902210'); } (froxlor::isdatabaseversion('201902210')) { // set correct version people tested 0.10.0 froxlor::updatetoversion('0.10.0-rc1'); froxlor::updatetodbversion('201904100'); } (froxlor::isdatabaseversion('201904100')) { update::showupdatestep("converting myisam tables innodb"); database::needroot(true); database::needsqldata(); $sql_data = database::getsqldata(); $result = database::query("select table_name information_schema.tables table_schema = '" . $sql_data['db'] . "' engine = 'myisam'"); ($row = $result-&gt;fetch(pdo::fetch_assoc)) { database::query("alter table `" . $row['table_name'] . "` engine=innodb"); } update::laststepstatus(0); froxlor::updatetodbversion('201904250'); } (froxlor::isfroxlorversion('0.10.0-rc1')) { update::showupdatestep("updating 0.10.0-rc1 0.10.0-rc2", false); froxlor::updatetoversion('0.10.0-rc2'); } (froxlor::isdatabaseversion('201904250')) { update::showupdatestep("adding new settings caa"); settings::addnew('caa.caa_entry', ''); settings::addnew('system.dns_createcaaentry', 1); update::laststepstatus(0); froxlor::updatetodbversion('201907270'); } (froxlor::isdatabaseversion('201907270')) { update::showupdatestep("cleaning old files"); $to_clean = array( "actions/admin/settings/000.version.php", "actions/admin/settings/190.ticket.php", "admin_tickets.php", "customer_tickets.php", "install/scripts/language-check.php", "install/updates/froxlor/upgrade_syscp.inc.php", "lib/classes", "lib/configfiles/precise.xml", "lib/cron_init.php", "lib/cron_shutdown.php", "lib/formfields/admin/tickets", "lib/formfields/customer/tickets", "lib/functions.php", "lib/functions", "lib/navigation/10.tickets.php", "scripts/classes", "scripts/jobs", "templates/sparkle/admin/tickets", "templates/sparkle/customer/tickets" ); $disabled = explode(',', ini_get('disable_functions')); $exec_allowed = !in_array('exec', $disabled); $del_list = ""; foreach ($to_clean $filedir) { $complete_filedir = froxlor::getinstalldir() . $filedir; (file_exists($complete_filedir)) { ($exec_allowed) { filedir::safe_exec("rm -rf " . escapeshellarg($complete_filedir)); } else { $del_list .= "rm -rf " . escapeshellarg($complete_filedir) . php_eol; } } } ($exec_allowed) { update::laststepstatus(0); } else { (empty($del_list)) { // none files existed update::laststepstatus(0); } else { update::laststepstatus(1, 'manual commands needed', 'please run following commands manually:&lt;br&gt;&lt;pre&gt;' . $del_list . '&lt;/pre&gt;'); } } froxlor::updatetodbversion('201909150'); } (froxlor::isfroxlorversion('0.10.0-rc2')) { update::showupdatestep("updating 0.10.0-rc2 0.10.0 final", false); froxlor::updatetoversion('0.10.0'); } (froxlor::isdatabaseversion('201909150')) { update::showupdatestep("adding tlsv1.3-cipherlist setting"); settings::addnew("system.tlsv13_cipher_list", ''); update::laststepstatus(0); froxlor::updatetodbversion('201910030'); } (froxlor::isdatabaseversion('201910030')) { update::showupdatestep("adding field api_allowed admins customers"); database::query("alter table `" . table_panel_admins . "` add `api_allowed` tinyint(1) null default '1';"); database::query("alter table `" . table_panel_customers . "` add `api_allowed` tinyint(1) null default '1';"); update::laststepstatus(0); froxlor::updatetodbversion('201910090'); } (froxlor::isfroxlorversion('0.10.0')) { update::showupdatestep("updating 0.10.0 0.10.1 final", false); froxlor::updatetoversion('0.10.1'); } (froxlor::isdatabaseversion('201910090')) { update::showupdatestep("adjusting let's encrypt api setting"); settings::set("system.leapiversion", '2'); update::laststepstatus(0); froxlor::updatetodbversion('201910110'); } (froxlor::isdatabaseversion('201910110')) { update::showupdatestep("adding new settings ssl-vhost default content"); settings::addnew("system.default_sslvhostconf", ''); settings::addnew("system.include_default_vhostconf", '0'); update::laststepstatus(0); update::showupdatestep("adding new fields ips ports-table"); database::query("alter table `" . table_panel_ipsandports . "` add `ssl_specialsettings` text `docroot`;"); database::query("alter table `" . table_panel_ipsandports . "` add `include_specialsettings` tinyint(1) null default '0' `ssl_specialsettings`;"); database::query("alter table `" . table_panel_ipsandports . "` add `ssl_default_vhostconf_domain` text `include_specialsettings`;"); database::query("alter table `" . table_panel_ipsandports . "` add `include_default_vhostconf_domain` tinyint(1) null default '0' `ssl_default_vhostconf_domain`;"); update::laststepstatus(0); update::showupdatestep("adding new fields domains-table"); database::query("alter table `" . table_panel_domains . "` add `ssl_specialsettings` text `specialsettings`;"); database::query("alter table `" . table_panel_domains . "` add `include_specialsettings` tinyint(1) null default '0' `ssl_specialsettings`;"); update::laststepstatus(0); // select ips/ports specialsettings ssl enabled include specialsettings ssl-vhost // former implementation included users might rely that, see https://github.com/froxlor/froxlor/issues/727 $sel_stmt = database::prepare("select * `" . table_panel_ipsandports . "` `specialsettings` &lt;&gt; '' `ssl` = '1'"); database::pexecute($sel_stmt); $upd_stmt = database::prepare("update `" . table_panel_ipsandports . "` set `include_specialsettings` = '1' `id` = :id"); ($sel_stmt-&gt;columncount() &gt; 0) { update::showupdatestep("adjusting ip/port settings downward compatibility"); ($row = $sel_stmt-&gt;fetch(pdo::fetch_assoc)) { database::pexecute($upd_stmt, [ 'id' =&gt; $row['id'] ]); } update::laststepstatus(0); } // select domains ssl ip connected specialsettings content include ssl-vhost // maintain former behavior $sel_stmt = database::prepare(" select d.id `" . table_panel_domains . "` left join `" . table_domaintoip . "` d2i d2i.id_domain = d.id left join `" . table_panel_ipsandports . "` i.id = d2i.id_ipandports d.specialsettings &lt;&gt; '' i.ssl = '1' "); database::pexecute($sel_stmt); $upd_stmt = database::prepare("update `" . table_panel_domains . "` set `include_specialsettings` = '1' `id` = :id"); ($sel_stmt-&gt;columncount() &gt; 0) { update::showupdatestep("adjusting domain settings downward compatibility"); ($row = $sel_stmt-&gt;fetch(pdo::fetch_assoc)) { database::pexecute($upd_stmt, [ 'id' =&gt; $row['id'] ]); } update::laststepstatus(0); } froxlor::updatetodbversion('201910120'); } (froxlor::isfroxlorversion('0.10.1')) { update::showupdatestep("updating 0.10.1 0.10.2", false); froxlor::updatetoversion('0.10.2'); } (froxlor::isdatabaseversion('201910120')) { update::showupdatestep("adding new tls options domains-table"); database::query("alter table `" . table_panel_domains . "` add `override_tls` tinyint(1) default '0' `writeerrorlog`;"); database::query("alter table `" . table_panel_domains . "` add `ssl_protocols` text `override_tls`;"); database::query("alter table `" . table_panel_domains . "` add `ssl_cipher_list` text `ssl_protocols`;"); database::query("alter table `" . table_panel_domains . "` add `tlsv13_cipher_list` text `ssl_cipher_list`;"); update::laststepstatus(0); froxlor::updatetodbversion('201910200'); } (froxlor::isfroxlorversion('0.10.2')) { update::showupdatestep("updating 0.10.2 0.10.3", false); froxlor::updatetoversion('0.10.3'); } (froxlor::isfroxlorversion('0.10.3')) { update::showupdatestep("updating 0.10.3 0.10.4", false); froxlor::updatetoversion('0.10.4'); } (froxlor::isfroxlorversion('0.10.4')) { update::showupdatestep("updating 0.10.4 0.10.5", false); froxlor::updatetoversion('0.10.5'); } (froxlor::isdatabaseversion('201910200')) { update::showupdatestep("optimizing customer admin table size"); // alter table `panel_customers` change `name` `name` varchar(250) character set utf8 collate utf8_general_ci null default ''; database::query("alter table `" . table_panel_customers . "` change `zipcode` `zipcode` varchar(25) null default '';"); database::query("alter table `" . table_panel_customers . "` change `phone` `phone` varchar(50) null default '';"); database::query("alter table `" . table_panel_customers . "` change `fax` `fax` varchar(50) null default '';"); database::query("alter table `" . table_panel_customers . "` change `def_language` `def_language` varchar(100) null default '';"); database::query("alter table `" . table_panel_customers . "` change `theme` `theme` varchar(50) null default 'sparkle';"); database::query("alter table `" . table_panel_customers . "` change `data_2fa` `data_2fa` varchar(25) null default '';"); database::query("alter table `" . table_panel_customers . "` change `def_language` `def_language` varchar(100) null default '';"); database::query("alter table `" . table_panel_customers . "` drop `leaccount`;"); database::query("alter table `" . table_panel_admins . "` change `def_language` `def_language` varchar(100) null default '';"); database::query("alter table `" . table_panel_admins . "` change `theme` `theme` varchar(50) null default 'sparkle';"); database::query("alter table `" . table_panel_admins . "` change `data_2fa` `data_2fa` varchar(25) null default '';"); update::laststepstatus(0); froxlor::updatetodbversion('201911130'); } (froxlor::isfroxlorversion('0.10.5')) { update::showupdatestep("updating 0.10.5 0.10.6", false); froxlor::updatetoversion('0.10.6'); } (froxlor::isdatabaseversion('201911130')) { update::showupdatestep("adding new settings domain edit form default values"); settings::addnew("system.apply_specialsettings_default", '1'); settings::addnew("system.apply_phpconfigs_default", '1'); update::laststepstatus(0); froxlor::updatetodbversion('201911220'); } (froxlor::isfroxlorversion('0.10.6')) { update::showupdatestep("updating 0.10.6 0.10.7", false); froxlor::updatetoversion('0.10.7'); } (froxlor::isfroxlorversion('0.10.7')) { update::showupdatestep("updating 0.10.7 0.10.8", false); froxlor::updatetoversion('0.10.8'); } (froxlor::isfroxlorversion('0.10.8')) { update::showupdatestep("updating 0.10.8 0.10.9", false); froxlor::updatetoversion('0.10.9'); } (froxlor::isdatabaseversion('201911220')) { update::showupdatestep("adding enhanced ssl control domains"); // customer domains database::query("alter table `" . table_panel_domains . "` add `ssl_enabled` tinyint(1) default '1';"); database::query("alter table `" . table_panel_domains . "` add `ssl_honorcipherorder` tinyint(1) default '0' `ssl_enabled`;"); database::query("alter table `" . table_panel_domains . "` add `ssl_sessiontickets` tinyint(1) default '1' `ssl_honorcipherorder`;"); // setting froxlor vhost settings::addnew("system.honorcipherorder", '0'); settings::addnew("system.sessiontickets", '1'); update::laststepstatus(0); froxlor::updatetodbversion('201912100'); } (froxlor::isfroxlorversion('0.10.9')) { update::showupdatestep("updating 0.10.9 0.10.10", false); froxlor::updatetoversion('0.10.10'); } (froxlor::isdatabaseversion('201912100')) { update::showupdatestep("adding option disable ssl sessiontickets older systems"); settings::addnew("system.sessionticketsenabled", '1'); update::laststepstatus(0); froxlor::updatetodbversion('201912310'); } (froxlor::isdatabaseversion('201912310')) { update::showupdatestep("adding custom phpfpm pool configuration field"); database::query("alter table `" . table_panel_fpmdaemons . "` add `custom_config` text `limit_extensions`;"); update::laststepstatus(0); froxlor::updatetodbversion('201912311'); } (froxlor::isfroxlorversion('0.10.10')) { update::showupdatestep("updating 0.10.10 0.10.11", false); froxlor::updatetoversion('0.10.11'); } (froxlor::isdatabaseversion('201912311')) { update::showupdatestep("migrate logfiles_format setting"); $current_format = settings::set('system.logfiles_format'); (!empty($current_format)) { settings::set('system.logfiles_format', '"' . settings::get('system.logfiles_format') . '"'); update::laststepstatus(0); } else { update::laststepstatus(0, 'not needed'); } froxlor::updatetodbversion('201912312'); } (froxlor::isdatabaseversion('201912312')) { update::showupdatestep("adding option change awstats logformat"); settings::addnew("system.awstats_logformat", '1'); update::laststepstatus(0); froxlor::updatetodbversion('201912313'); } (froxlor::isfroxlorversion('0.10.11')) { update::showupdatestep("updating 0.10.11 0.10.12", false); froxlor::updatetoversion('0.10.12'); } (froxlor::isfroxlorversion('0.10.12')) { update::showupdatestep("updating 0.10.12 0.10.13", false); froxlor::updatetoversion('0.10.13'); } (froxlor::isdatabaseversion('201912313')) { update::showupdatestep("adding new field domains table"); database::query("alter table `" . table_panel_domains . "` add `domain_ace` varchar(255) null default '' `domain`;"); update::laststepstatus(0); update::showupdatestep("updating domain entries"); $upd_stmt = database::prepare("update `" . table_panel_domains . "` set `domain_ace` = :ace `id` = :domainid"); $sel_stmt = database::prepare("select id, domain `" . table_panel_domains . "` order id asc"); database::pexecute($sel_stmt); $idna_convert = new \froxlor\idna\idnawrapper(); ($domain = $sel_stmt-&gt;fetch(\pdo::fetch_assoc)) { database::pexecute($upd_stmt, [ 'ace' =&gt; $idna_convert-&gt;decode($domain['domain']), 'domainid' =&gt; $domain['id'] ]); } update::laststepstatus(0); froxlor::updatetodbversion('202002290'); } (froxlor::isfroxlorversion('0.10.13')) { update::showupdatestep("updating 0.10.13 0.10.14", false); froxlor::updatetoversion('0.10.14'); } (froxlor::isfroxlorversion('0.10.14')) { update::showupdatestep("updating 0.10.14 0.10.15", false); froxlor::updatetoversion('0.10.15'); } (froxlor::isdatabaseversion('202002290')) { update::showupdatestep("adding new setting validate dns using let's encrypt"); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'system' `varname` = 'disable_le_selfcheck'"); $le_domain_dnscheck = isset($_post['system_le_domain_dnscheck']) ? (int) $_post['system_le_domain_dnscheck'] : '1'; settings::addnew("system.le_domain_dnscheck", $le_domain_dnscheck); update::laststepstatus(0); froxlor::updatetodbversion('202004140'); } (froxlor::isfroxlorversion('0.10.15')) { update::showupdatestep("updating 0.10.15 0.10.16", false); froxlor::updatetoversion('0.10.16'); } (froxlor::isdatabaseversion('202004140')) { update::showupdatestep("adding unique key domainid field domain ssl table"); // check duplicate entries prior set unique key avoid errors update database::query(" delete a.* domain_ssl_settings left join domain_ssl_settings b ((b.`domainid`=a.`domainid` unix_timestamp(b.`expirationdate`) &gt; unix_timestamp(a.`expirationdate`)) (unix_timestamp(b.`expirationdate`) = unix_timestamp(a.`expirationdate`) b.`id`&gt;a.`id`)) b.`id` null "); database::query("alter table `domain_ssl_settings` add unique(`domainid`)"); update::laststepstatus(0); froxlor::updatetodbversion('202005150'); } (froxlor::isfroxlorversion('0.10.16')) { update::showupdatestep("updating 0.10.16 0.10.17", false); froxlor::updatetoversion('0.10.17'); } (froxlor::isfroxlorversion('0.10.17')) { update::showupdatestep("updating 0.10.17 0.10.18", false); froxlor::updatetoversion('0.10.18'); } (froxlor::isfroxlorversion('0.10.18')) { update::showupdatestep("updating 0.10.18 0.10.19", false); froxlor::updatetoversion('0.10.19'); } (froxlor::isdatabaseversion('202005150')) { update::showupdatestep("add new performance indexes", true); database::query("alter table panel_customers add index guid (guid);"); database::query("alter table panel_tasks add index type (type);"); database::query("alter table mail_users add index username (username);"); database::query("alter table mail_users add index imap (imap);"); database::query("alter table mail_users add index pop3 (pop3);"); database::query("alter table ftp_groups add index gid (gid);"); update::laststepstatus(0); froxlor::updatetodbversion('202007240'); } (froxlor::isfroxlorversion('0.10.19')) { update::showupdatestep("updating 0.10.19 0.10.20", false); froxlor::updatetoversion('0.10.20'); } (froxlor::isdatabaseversion('202007240')) { update::showupdatestep("removing old unused table", true); database::query("drop table exists `panel_diskspace_admins`;"); update::laststepstatus(0); froxlor::updatetodbversion('202009070'); } (froxlor::isfroxlorversion('0.10.20')) { update::showupdatestep("updating 0.10.20 0.10.21", false); froxlor::updatetoversion('0.10.21'); } (froxlor::isfroxlorversion('0.10.21')) { update::showupdatestep("adding settings ssl-vhost default content updated db-version 201910110", true); settings::addnew("system.default_sslvhostconf", ''); update::laststepstatus(0); update::showupdatestep("updating 0.10.21 0.10.22", false); froxlor::updatetoversion('0.10.22'); } (froxlor::isfroxlorversion('0.10.22')) { update::showupdatestep("updating 0.10.22 0.10.23", false); froxlor::updatetoversion('0.10.23'); } (froxlor::isfroxlorversion('0.10.23')) { update::showupdatestep("updating 0.10.23 0.10.23.1", false); froxlor::updatetoversion('0.10.23.1'); } (froxlor::isdatabaseversion('202009070')) { update::showupdatestep("adding setting hide incompatible settings", true); settings::addnew("system.hide_incompatible_settings", '0'); update::laststepstatus(0); froxlor::updatetodbversion('202012300'); } (froxlor::isdatabaseversion('202012300')) { update::showupdatestep("adding setting dkim private key extension/suffix", true); settings::addnew("dkim.privkeysuffix", '.priv'); update::laststepstatus(0); froxlor::updatetodbversion('202101200'); } (froxlor::isfroxlorversion('0.10.23.1')) { update::showupdatestep("updating 0.10.23.1 0.10.24", false); froxlor::updatetoversion('0.10.24'); } (froxlor::isdatabaseversion('202101200')) { update::showupdatestep("adding setting mail address used soa records", true); settings::addnew("system.soaemail", ''); update::laststepstatus(0); froxlor::updatetodbversion('202102200'); } (froxlor::isfroxlorversion('0.10.24')) { update::showupdatestep("updating 0.10.24 0.10.25", false); froxlor::updatetoversion('0.10.25'); } (froxlor::isdatabaseversion('202102200') || froxlor::isdatabaseversion('202103030')) { update::showupdatestep("refactoring columns large tables", true); database::query("alter table panel_domains change `ssl_protocols` `ssl_protocols` varchar(255) null default '';"); database::query("alter table panel_domains change `ssl_cipher_list` `ssl_cipher_list` varchar(500) null default '';"); database::query("alter table panel_domains change `tlsv13_cipher_list` `tlsv13_cipher_list` varchar(500) null default '';"); update::laststepstatus(0); update::showupdatestep("add new description fields mail domain table", true); $result = database::query("describe `panel_domains`"); $columnfound = 0; ($row = $result-&gt;fetch(pdo::fetch_assoc)) { ($row['field'] == 'description') { $columnfound = 1; } } (!$columnfound) { database::query("alter table panel_domains add `description` varchar(255) null default '' `ssl_sessiontickets`;"); } $result = database::query("describe `mail_virtual`"); $columnfound = 0; ($row = $result-&gt;fetch(pdo::fetch_assoc)) { ($row['field'] == 'description') { $columnfound = 1; } } (!$columnfound) { database::query("alter table mail_virtual add `description` varchar(255) null default '' `iscatchall`"); } update::laststepstatus(0); froxlor::updatetodbversion('202103110'); } (froxlor::isdatabaseversion('202103110')) { update::showupdatestep("adding settings imprint, terms use privacy policy urls", true); settings::addnew("panel.imprint_url", ''); settings::addnew("panel.terms_url", ''); settings::addnew("panel.privacy_url", ''); update::laststepstatus(0); froxlor::updatetodbversion('202103240'); } (froxlor::isfroxlorversion('0.10.25')) { update::showupdatestep("updating 0.10.25 0.10.26", false); froxlor::updatetoversion('0.10.26'); } (froxlor::isdatabaseversion('202103240')) { update::showupdatestep("adding setting default serveralias value new domains", true); settings::addnew("system.domaindefaultalias", '0'); update::laststepstatus(0); froxlor::updatetodbversion('202106160'); } (froxlor::isdatabaseversion('202106160')) { update::showupdatestep("adjusting let's encrypt endpoint configuration support zerossl", true); (settings::get('system.letsencryptca') == 'testing') { settings::set("system.letsencryptca", 'letsencrypt_test'); } else { settings::set("system.letsencryptca", 'letsencrypt'); } update::laststepstatus(0); froxlor::updatetodbversion('202106270'); } (froxlor::isdatabaseversion('202106270')) { update::showupdatestep("adding custom logo image settings", true); settings::addnew("panel.logo_image_header", ''); settings::addnew("panel.logo_image_login", ''); update::laststepstatus(0); // migrating old custom logo over, exists $custom_logo_file_old = froxlor::getinstalldir() . '/templates/sparkle/assets/img/logo_custom.png'; (file_exists($custom_logo_file_old)) { update::showupdatestep("migrating existing custom logo new settings", true); $path = froxlor::getinstalldir() . '/img/'; (!is_dir($path) &amp;&amp; !mkdir($path, 0775)) { throw new \exception("img directory exist cannot created"); } (!is_writable($path)) { (!chmod($path, 0775)) { throw new \exception("cannot write img directory"); } } // save new custom logo header $save_to = 'logo_header.png'; copy($custom_logo_file_old, $path . $save_to); settings::set("panel.logo_image_header", "img/{$save_to}?v=" . time()); // save new custom logo login $save_to = 'logo_login.png'; copy($custom_logo_file_old, $path . $save_to); settings::set("panel.logo_image_login", "img/{$save_to}?v=" . time()); update::laststepstatus(0); } froxlor::updatetodbversion('202107070'); } (froxlor::isfroxlorversion('0.10.26')) { update::showupdatestep("updating 0.10.26 0.10.27", false); froxlor::updatetoversion('0.10.27'); } (froxlor::isdatabaseversion('202107070')) { update::showupdatestep("adding settings overwrite theme- custom theme-logo new logo settings", true); settings::addnew("panel.logo_overridetheme", '0'); settings::addnew("panel.logo_overridecustom", '0'); update::laststepstatus(0); froxlor::updatetodbversion('202107200'); } (froxlor::isdatabaseversion('202107200')) { update::showupdatestep("adding settings define default value 'create std-subdomain' creating customer", true); settings::addnew("system.createstdsubdom_default", '1'); update::laststepstatus(0); froxlor::updatetodbversion('202107210'); } (froxlor::isdatabaseversion('202107210')) { update::showupdatestep("normalizing ipv6 correct comparison", true); $result_stmt = database::prepare( " select `id`, `ip` `" . table_panel_ipsandports . "`" ); database::pexecute($result_stmt); $upd_stmt = database::prepare("update `" . table_panel_ipsandports . "` set `ip` = :ip `id` = :id"); ($iprow = $result_stmt-&gt;fetch(\pdo::fetch_assoc)) { (iptools::is_ipv6($iprow['ip'])) { $ip = inet_ntop(inet_pton($iprow['ip'])); database::pexecute($upd_stmt, [ 'ip' =&gt; $ip, 'id' =&gt; $iprow['id'] ]); } } update::laststepstatus(0); froxlor::updatetodbversion('202107260'); } (froxlor::isdatabaseversion('202107260')) { update::showupdatestep("removing setting search-engine allow yes/no", true); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'panel' `varname` = 'no_robots'"); update::laststepstatus(0); update::showupdatestep("adding setting froxlor customers local group", true); settings::addnew("system.froxlorusergroup", ''); settings::addnew("system.froxlorusergroup_gid", ''); update::laststepstatus(0); froxlor::updatetodbversion('202107300'); } (froxlor::isdatabaseversion('202107300')) { update::showupdatestep("adds possibility select powerdns operation mode", true); settings::addnew("system.powerdns_mode", 'native'); update::laststepstatus(0); froxlor::updatetodbversion('202108180'); } (froxlor::isfroxlorversion('0.10.27')) { update::showupdatestep("updating 0.10.27 0.10.28", false); froxlor::updatetoversion('0.10.28'); } (froxlor::isdatabaseversion('202108180')) { update::showupdatestep("adding czech language file", true); database::query("insert `panel_languages` set `language` = '&amp;#268;esk&amp;aacute; republika', `iso` = 'cs', `file` = 'lng/czech.lng.php'"); update::laststepstatus(0); froxlor::updatetodbversion('202109040'); } (froxlor::isfroxlorversion('0.10.28')) { update::showupdatestep("updating 0.10.28 0.10.29", false); froxlor::updatetoversion('0.10.29'); } (froxlor::isfroxlorversion('0.10.29')) { update::showupdatestep("updating 0.10.29 0.10.29.1", false); froxlor::updatetoversion('0.10.29.1'); } (froxlor::isfroxlorversion('0.10.29.1')) { update::showupdatestep("updating 0.10.29.1 0.10.30", false); froxlor::updatetoversion('0.10.30'); } (froxlor::isfroxlorversion('0.10.30')) { update::showupdatestep("updating 0.10.30 0.10.31", false); froxlor::updatetoversion('0.10.31'); } (froxlor::isdatabaseversion('202109040')) { update::showupdatestep("add setting acme.sh install location", true); settings::addnew("system.acmeshpath", '/root/.acme.sh/acme.sh'); update::laststepstatus(0); froxlor::updatetodbversion('202112310'); } (froxlor::isfroxlorversion('0.10.31')) { update::showupdatestep("updating 0.10.31 0.10.32", false); froxlor::updatetoversion('0.10.32'); } (froxlor::isfroxlorversion('0.10.32')) { update::showupdatestep("updating 0.10.32 0.10.33", false); froxlor::updatetoversion('0.10.33'); } (froxlor::isfroxlorversion('0.10.33')) { update::showupdatestep("updating 0.10.33 0.10.34", false); froxlor::updatetoversion('0.10.34'); } (froxlor::isfroxlorversion('0.10.34')) { update::showupdatestep("updating 0.10.34 0.10.34.1", false); froxlor::updatetoversion('0.10.34.1'); } (froxlor::isfroxlorversion('0.10.34.1')) { update::showupdatestep("updating 0.10.34.1 0.10.35", false); froxlor::updatetoversion('0.10.35'); } (froxlor::isfroxlorversion('0.10.35')) { update::showupdatestep("updating 0.10.35 0.10.35.1", false); froxlor::updatetoversion('0.10.35.1'); } (froxlor::isfroxlorversion('0.10.35.1')) { update::showupdatestep("updating 0.10.35.1 0.10.36", false); froxlor::updatetoversion('0.10.36'); } (froxlor::isfroxlorversion('0.10.36')) { update::showupdatestep("updating 0.10.36 0.10.37", false); froxlor::updatetoversion('0.10.37'); } (froxlor::isfroxlorversion('0.10.37')) { update::showupdatestep("updating 0.10.37 0.10.38", false); froxlor::updatetoversion('0.10.38'); } (froxlor::isfroxlorversion('0.10.38')) { update::showupdatestep("updating 0.10.38 0.10.38.1", false); froxlor::updatetoversion('0.10.38.1'); } (froxlor::isfroxlorversion('0.10.38.1')) { update::showupdatestep("updating 0.10.38.1 0.10.38.2", false); froxlor::updatetoversion('0.10.38.2'); } (froxlor::isfroxlorversion('0.10.38.2')) { update::showupdatestep("updating 0.10.38.2 0.10.38.3", false); froxlor::updatetoversion('0.10.38.3'); }</file><file name="install/updates/froxlor/index.html" /><file name="install/updates/froxlor/update_2.2.inc.php">&lt;?php /** * file part froxlor project. * copyright (c) 2010 froxlor team (see authors). * * program free software; redistribute and/or * modify terms gnu general public license * published free software foundation; either version 2 * license, (at option) later version. * * program distributed hope useful, * without warranty; without even implied warranty * merchantability fitness particular purpose. see * gnu general public license details. * * received copy gnu general public license * along program; not, also view online * https://files.froxlor.org/misc/copying.txt * * @copyright authors * @author froxlor team &lt;team@froxlor.org&gt; * @license https://files.froxlor.org/misc/copying.txt gplv2 */ use froxlor\database\database; use froxlor\database\dbmanager; use froxlor\froxlor; use froxlor\froxlorlogger; use froxlor\install\update; use froxlor\settings; (!defined('_cron_update')) { (!defined('area') || (defined('area') &amp;&amp; area != 'admin') || !isset($userinfo['loginname']) || (isset($userinfo['loginname']) &amp;&amp; $userinfo['loginname'] == '')) { header('location: ../../../../index.php'); exit(); } } (froxlor::isfroxlorversion('2.1.9')) { update::showupdatestep("enhancing virtual email table"); database::query("alter table `" . table_mail_virtual . "` add `spam_tag_level` float(4,1) null default 7.0;"); database::query("alter table `" . table_mail_virtual . "` add `spam_kill_level` float(4,1) null default 14.0;"); database::query("alter table `" . table_mail_virtual . "` add `bypass_spam` tinyint(1) null default '0';"); database::query("alter table `" . table_mail_virtual . "` add `policy_greylist` tinyint(1) null default '1';"); update::laststepstatus(0); update::showupdatestep("adjusting settings"); $antispam_activated = $_post['antispam_activated'] ?? 0; database::query("update `" . table_panel_settings . "` set `settinggroup` = 'antispam', `varname` = 'activated', `value` = '" . (int)$antispam_activated . "' `settinggroup` = 'dkim' `varname` = 'use_dkim';"); database::query("update `" . table_panel_settings . "` set `settinggroup` = 'antispam', `varname` = 'reload_command', `value` = 'service rspamd restart' `settinggroup` = 'dkim' `varname` = 'dkimrestart_command';"); database::query("update `" . table_panel_settings . "` set `settinggroup` = 'antispam', `varname` = 'config_file', `value` = '/etc/rspamd/local.d/froxlor_settings.conf' `settinggroup` = 'dkim' `varname` = 'dkim_prefix';"); database::query("update `" . table_panel_settings . "` set `settinggroup` = 'antispam' `settinggroup` = 'dkim' `varname` = 'dkim_keylength';"); settings::addnew("dmarc.use_dmarc", "0"); settings::addnew("dmarc.dmarc_entry", "v=dmarc1; p=none;"); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'dkim' `varname` = 'privkeysuffix';"); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'dkim' `varname` = 'dkim_domains';"); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'dkim' `varname` = 'dkim_algorithm';"); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'dkim' `varname` = 'dkim_notes';"); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'dkim' `varname` = 'dkim_add_adsp';"); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'dkim' `varname` = 'dkim_dkimkeys';"); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'dkim' `varname` = 'dkim_servicetype';"); database::query("delete `" . table_panel_settings . "` `settinggroup` = 'dkim' `varname` = 'dkim_add_adsppolicy';"); update::laststepstatus(0); ($antispam_activated) { update::showupdatestep("converting existing domainkeys"); $sel_stmt = database::prepare("select * `" . table_panel_domains . "` `dkim` = '1' `dkim_pubkey` &lt;&gt; ''"); database::pexecute($sel_stmt); $upd_stmt = database::prepare("update `" . table_panel_domains . "` set `dkim_pubkey` = :pkey `id` = :did"); ($domain = $sel_stmt-&gt;fetch(\pdo::fetch_assoc)) { $pubkey = trim(preg_replace( '/-----begin public key-----(.+)-----end public key-----/s', '$1', str_replace("\n", '', $domain['dkim_pubkey']) )); database::pexecute($upd_stmt, ['pkey' =&gt; $pubkey, 'did' =&gt; $domain['id']]); } update::laststepstatus(0); update::showupdatestep("configure antispam services"); $froxlorclibin = froxlor::getinstalldir() . '/bin/froxlor-cli'; $currentdistro = settings::get('system.distribution'); $manual_command = &lt;&lt;&lt;eoc {$froxlorclibin} froxlor:config-services -a '{"http":"x","dns":"x","smtp":"x","mail":"x","antispam":"rspamd","ftp":"x","distro":"{$currentdistro}","system":[]}' eoc; update::laststepstatus( 1, 'manual action needed', "please run following command manually root:&lt;br&gt;&lt;pre&gt;" . $manual_command . "&lt;/pre&gt;" ); } else { update::showupdatestep("removing existing domainkeys antispam disabled"); database::query("update `" . table_panel_domains . "` set `dkim` = '0', `dkim_id` = '0', `dkim_privkey` = '', `dkim_pubkey` = '' `dkim` = '1';"); update::laststepstatus(1, '!!!'); } update::showupdatestep("enhancing admin user table"); database::query("alter table `" . table_panel_admins . "` add `gui_access` tinyint(1) null default '1';"); database::query("alter table `" . table_panel_customers . "` add `gui_access` tinyint(1) null default '1';"); update::laststepstatus(0); $to_clean = [ 'actions/admin/settings/180.dkim.php', 'actions/admin/settings/185.spf.php', ]; update::cleanoldfiles($to_clean); froxlor::updatetodbversion('202312230'); froxlor::updatetoversion('2.2.0-dev1'); } (froxlor::isdatabaseversion('202312230')) { update::showupdatestep("adding new settings"); settings::addnew("system.le_renew_services", ""); settings::addnew("system.le_renew_hook", "systemctl restart postfix dovecot proftpd"); update::laststepstatus(0); froxlor::updatetodbversion('202401090'); } (froxlor::isfroxlorversion('2.2.0-dev1')) { update::showupdatestep("updating 2.2.0-dev1 2.2.0-rc1", false); froxlor::updatetoversion('2.2.0-rc1'); } (froxlor::isdatabaseversion('202401090')) { update::showupdatestep("adding new table 2fa tokens"); database::query("drop table exists `panel_2fa_tokens`;"); $sql = "create table `panel_2fa_tokens` ( `id` int(11) null auto_increment, `selector` varchar(20) null, `token` varchar(200) null, `userid` int(11) null default '0', `valid_until` int(15) null, primary key (id) ) engine=innodb default charset=utf8 collate=utf8_general_ci;"; database::query($sql); update::laststepstatus(0); froxlor::updatetodbversion('202407200'); } (froxlor::isfroxlorversion('2.2.0-rc1')) { update::showupdatestep("updating 2.2.0-rc1 2.2.0-rc2", false); froxlor::updatetoversion('2.2.0-rc2'); } (froxlor::isfroxlorversion('2.2.0-rc2')) { update::showupdatestep("updating 2.2.0-rc2 2.2.0-rc3", false); froxlor::updatetoversion('2.2.0-rc3'); } (froxlor::isdatabaseversion('202407200')) { update::showupdatestep("adjusting field 2fa-token table"); database::query("alter table `panel_2fa_tokens` change column `selector` `selector` varchar(200) null;"); update::laststepstatus(0); froxlor::updatetodbversion('202408140'); } (froxlor::isfroxlorversion('2.2.0-rc3')) { update::showupdatestep("updating 2.2.0-rc3 2.2.0 stable", false); froxlor::updatetoversion('2.2.0'); } (froxlor::isfroxlorversion('2.2.0')) { update::showupdatestep("updating 2.2.0 2.2.1", false); froxlor::updatetoversion('2.2.1'); } (froxlor::isdatabaseversion('202408140')) { update::showupdatestep("adding new rewrite-subject field email table"); database::query("alter table `" . table_mail_virtual . "` add `rewrite_subject` tinyint(1) null default '1' `spam_tag_level`;"); update::laststepstatus(0); froxlor::updatetodbversion('202409280'); } (froxlor::isfroxlorversion('2.2.1')) { update::showupdatestep("updating 2.2.1 2.2.2", false); froxlor::updatetoversion('2.2.2'); } (froxlor::isfroxlorversion('2.2.2')) { update::showupdatestep("updating 2.2.2 2.2.3", false); froxlor::updatetoversion('2.2.3'); } (froxlor::isfroxlorversion('2.2.3')) { update::showupdatestep("updating 2.2.3 2.2.4", false); froxlor::updatetoversion('2.2.4'); } (froxlor::isfroxlorversion('2.2.4')) { update::showupdatestep("updating 2.2.4 2.2.5", false); froxlor::updatetoversion('2.2.5'); } (froxlor::isdatabaseversion('202409280')) { update::showupdatestep("adding new antispam settings"); settings::addnew("antispam.default_bypass_spam", "2"); settings::addnew("antispam.default_spam_rewrite_subject", "1"); settings::addnew("antispam.default_policy_greylist", "1"); update::laststepstatus(0); froxlor::updatetodbversion('202411200'); } (froxlor::isdatabaseversion('202411200')) { update::showupdatestep("adjusting customer mysql global user"); // get customers deactivated least one database (hence global database-user) $customers = database::query(" select distinct c.loginname, c.allowed_mysqlserver `" . table_panel_customers . "` c left join `" . table_panel_databases . "` c.customerid = d.customerid c.deactivated = '0' d.id null "); ($customer = $customers-&gt;fetch(\pdo::fetch_assoc)) { $current_allowed_mysqlserver = !empty($customer['allowed_mysqlserver']) ? json_decode($customer['allowed_mysqlserver'], true) : []; foreach ($current_allowed_mysqlserver $dbserver) { // require privileged access target db-server database::needroot(true, $dbserver, true); // get dbmanager $dbm = new dbmanager(froxlorlogger::getinstanceof()); foreach (array_map('trim', explode(',', settings::get('system.mysql_access_host'))) $mysql_access_host) { ($dbm-&gt;getmanager()-&gt;userexistsonhost($customer['loginname'], $mysql_access_host)) { // deactivate temporarily $dbm-&gt;getmanager()-&gt;disableuser($customer['loginname'], $mysql_access_host); // re-enable $dbm-&gt;getmanager()-&gt;enableuser($customer['loginname'], $mysql_access_host, true); } } $dbm-&gt;getmanager()-&gt;flushprivileges(); database::needroot(false); } } update::laststepstatus(0); froxlor::updatetodbversion('202412030'); }</file></source>