Merge branch '0.11-dev' of github.com:Froxlor/Froxlor into 0.11-dev

This commit is contained in:
envoyr 2022-02-25 21:17:45 +01:00
commit d48baf0cb5
No known key found for this signature in database
GPG Key ID: 5A16F49AF96F462F
52 changed files with 1262 additions and 753 deletions

View File

@ -41,11 +41,15 @@ if ($page == 'admins' && $userinfo['change_serversettings'] == '1') {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $admin_list_data['admin_list']),
]);
UI::twigOutputBuffer();
} elseif ($action == 'su') {
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $admin_list_data['admin_list']),
'actions_links' => [[
'href' => $linker->getLink(['section' => 'admins', 'page' => $page, 'action' => 'add']),
'label' => $lng['admin']['admin_add']
]]
]);
UI::twigOutputBuffer();
} elseif ($action == 'su') {
try {
$json_result = Admins::getLocal($userinfo, array(

View File

@ -33,18 +33,27 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_customers");
try {
$customer_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.customers.php';
$customer_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.customers.php';
$collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Customers::class, $userinfo))
->has('admin', \Froxlor\Api\Commands\Admins::class, 'adminid', 'adminid')
->withPagination($customer_list_data['customer_list']['columns']);
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
->has('admin', \Froxlor\Api\Commands\Admins::class, 'adminid', 'adminid')
->withPagination($customer_list_data['customer_list']['columns']);
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $customer_list_data['customer_list']),
]);
UI::twigOutputBuffer();
$actions_links = false;
if ($userinfo['customers_used'] < $userinfo['customers'] || $userinfo['customers'] == '-1') {
$actions_links = [[
'href' => $linker->getLink(['section' => 'customers', 'page' => $page, 'action' => 'add']),
'label' => $lng['admin']['customer_add']
]];
}
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $customer_list_data['customer_list']),
'actions_links' => $actions_links
]);
UI::twigOutputBuffer();
} elseif ($action == 'su' && $id != 0) {
try {
$json_result = Customers::getLocal($userinfo, array(

View File

@ -38,14 +38,31 @@ if ($page == 'domains' || $page == 'overview') {
$collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Domains::class, $userinfo))
->has('customer', \Froxlor\Api\Commands\Customers::class, 'customerid', 'customerid')
->withPagination($domain_list_data['domain_list']['columns']);
$customerCollection = (new \Froxlor\UI\Collection(Customers::class, $userinfo));
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $domain_list_data['domain_list']),
]);
UI::twigOutputBuffer();
$actions_links = false;
if (($userinfo['domains_used'] < $userinfo['domains'] || $userinfo['domains'] == '-1') && $customerCollection->count() != 0) {
$actions_links = [];
$actions_links[] = [
'href' => $linker->getLink(['section' => 'domains', 'page' => $page, 'action' => 'add']),
'label' => $lng['admin']['domain_add']
];
$actions_links[] = [
'href' => $linker->getLink(['section' => 'domains', 'page' => $page, 'action' => 'import']),
'label' => $lng['domains']['domain_import'],
'icon' => 'fa-solid fa-file-import',
'class' => 'btn-secondary'
];
}
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $domain_list_data['domain_list']),
'actions_links' => $actions_links
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) {
try {

View File

@ -39,10 +39,14 @@ if ($page == 'ipsandports' || $page == 'overview') {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $ipsandports_list_data['ipsandports_list']),
]);
UI::twigOutputBuffer();
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $ipsandports_list_data['ipsandports_list']),
'actions_links' => [[
'href' => $linker->getLink(['section' => 'ipsandports', 'page' => $page, 'action' => 'add']),
'label' => $lng['admin']['ipsandports']['add']
]]
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) {
try {
$json_result = IpsAndPorts::getLocal($userinfo, array(

View File

@ -40,10 +40,14 @@ if ($page == '' || $page == 'overview') {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $plan_list_data['plan_list']),
]);
UI::twigOutputBuffer();
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $plan_list_data['plan_list']),
'actions_links' => [[
'href' => $linker->getLink(['section' => 'plans', 'page' => $page, 'action' => 'add']),
'label' => $lng['admin']['plans']['add']
]]
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) {
try {

View File

@ -33,75 +33,40 @@ if (Settings::IsInList('panel.customer_hide_options', 'domains')) {
$id = (int) Request::get('id');
if ($page == 'overview') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_domains");
eval("echo \"" . \Froxlor\UI\Template::getTemplate("domains/domains") . "\";");
} elseif ($page == 'domains') {
if ($page == 'overview' || $page == 'domains') {
if ($action == '') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_domains::domains");
$fields = array(
'd.domain_ace' => $lng['domains']['domainname'],
'd.aliasdomain' => $lng['domains']['aliasdomain']
);
$parentdomain_id = (int) Request::get('pid', '0');
try {
// get total count
$json_result = SubDomains::getLocal($userinfo)->listingCount();
$result = json_decode($json_result, true)['data'];
// initialize pagination and filtering
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = SubDomains::getLocal($userinfo, $paging->getApiCommandParams())->listing();
$domain_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.domains.php';
$list = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\SubDomains::class, $userinfo))
//->addParam(['sql_search' => ['d.parentdomainid' => $parentdomain_id]])
->withPagination($domain_list_data['domain_list']['columns'])
->getList();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$json_result = SubDomains::getLocal($userinfo, ['sql_search' => ['d.parentdomainid' => 0]])->listing();
$result = json_decode($json_result, true)['data'];
$parentdomains_count = $result['count'];
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$domains = '';
$parentdomains_count = 0;
$domains_count = $paging->getEntries();
$domain_array = array();
foreach ($result['list'] as $row) {
formatDomainEntry($row, $idna_convert);
if ($row['parentdomainid'] == '0' && $row['caneditdomain'] == '1') {
$parentdomains_count++;
}
$domain_array[$row['parentdomainname']][] = $row;
$actions_links = false;
if (($userinfo['subdomains_used'] < $userinfo['subdomains'] || $userinfo['subdomains'] == '-1') && $parentdomains_count != 0) {
$actions_links = [[
'href' => $linker->getLink(['section' => 'domains', 'page' => 'domains', 'action' => 'add']),
'label' => $lng['domains']['subdomain_add']
]];
}
foreach ($domain_array as $parentdomain => $sdomains) {
// PARENTDOMAIN
if (Settings::Get('system.awstats_enabled') == '1') {
$statsapp = 'awstats';
} else {
$statsapp = 'webalizer';
}
$row = [
'domain' => $idna_convert->decode($parentdomain)
];
eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_delimiter") . "\";");
foreach ($sdomains as $domain) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($domain);
// show docroot nicely
if (strpos($row['documentroot'], $userinfo['documentroot']) === 0) {
$row['documentroot'] = \Froxlor\FileDir::makeCorrectDir(str_replace($userinfo['documentroot'], "/", $row['documentroot']));
}
// get ssl-ips if activated
$show_ssledit = false;
if (Settings::Get('system.use_ssl') == '1' && \Froxlor\Domain\Domain::domainHasSslIpPort($row['id']) && $row['caneditdomain'] == '1' && $row['letsencrypt'] == 0) {
$show_ssledit = true;
}
eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_domain") . "\";");
}
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("domains/domainlist") . "\";");
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($list, $domain_list_data['domain_list']),
'actions_links' => $actions_links,
'entity_info' => $lng['domains']['description']
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) {
try {
$json_result = SubDomains::getLocal($userinfo, array(

View File

@ -34,97 +34,18 @@ if (Settings::IsInList('panel.customer_hide_options', 'email')) {
$id = (int) Request::get('id');
if ($page == 'overview') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_email");
eval("echo \"" . \Froxlor\UI\Template::getTemplate("email/email") . "\";");
} elseif ($page == 'emails') {
if ($page == 'overview' || $page == 'emails') {
if ($action == '') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_email::emails");
$fields = array(
'd.domain_ace' => $lng['domains']['domainname'],
'm.email_full' => $lng['emails']['emailaddress'],
'm.destination' => $lng['emails']['forwarders']
);
try {
// get total count
$json_result = Emails::getLocal($userinfo)->listingCount();
$result = json_decode($json_result, true)['data'];
// initialize pagination and filtering
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = Emails::getLocal($userinfo, $paging->getApiCommandParams())->listing();
$email_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.emails.php';
$list = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Emails::class, $userinfo))
->withPagination($email_list_data['email_list']['columns'])
->getList();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$emails = array();
$emailscount = $paging->getEntries();
foreach ($result['list'] as $row) {
if (! isset($emails[$row['domain']]) || ! is_array($emails[$row['domain']])) {
$emails[$row['domain']] = array();
}
$emails[$row['domain']][$row['email_full']] = $row;
}
if ($paging->sortfield == 'd.domain_ace' && $paging->sortorder == 'desc') {
krsort($emails);
} else {
ksort($emails);
}
$count = 0;
$accounts = '';
$emails_count = 0;
$domainname = '';
foreach ($emails as $domainid => $emailaddresses) {
if ($paging->sortfield == 'm.email_full' && $paging->sortorder == 'desc') {
krsort($emailaddresses);
} else {
ksort($emailaddresses);
}
foreach ($emailaddresses as $row) {
if ($domainname != $idna_convert->decode($row['domain'])) {
$domainname = $idna_convert->decode($row['domain']);
eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate("email/emails_domain") . "\";");
}
$emails_count ++;
$row['email'] = $idna_convert->decode($row['email']);
$row['email_full'] = $idna_convert->decode($row['email_full']);
$row['destination'] = explode(' ', $row['destination']);
uasort($row['destination'], 'strcasecmp');
$dest_list = $row['destination'];
foreach ($dest_list as $dest_id => $destination) {
$row['destination'][$dest_id] = $idna_convert->decode($row['destination'][$dest_id]);
if ($row['destination'][$dest_id] == $row['email_full']) {
unset($row['destination'][$dest_id]);
}
}
$destinations_count = count($row['destination']);
$row['destination'] = implode(', ', $row['destination']);
if (strlen($row['destination']) > 35) {
$row['destination'] = substr($row['destination'], 0, 32) . '... (' . $destinations_count . ')';
}
$row['mboxsize'] = \Froxlor\PhpHelper::sizeReadable($row['mboxsize'], 'GiB', 'bi', '%01.' . (int) Settings::Get('panel.decimal_places') . 'f %s');
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate("email/emails_email") . "\";");
$count ++;
}
}
$result_stmt = Database::prepare("
SELECT COUNT(`id`) as emaildomains
@ -136,7 +57,20 @@ if ($page == 'overview') {
));
$emaildomains_count = $result2['emaildomains'];
eval("echo \"" . \Froxlor\UI\Template::getTemplate("email/emails") . "\";");
$actions_links = false;
if (($userinfo['emails_used'] < $userinfo['emails'] || $userinfo['emails'] == '-1') && $emaildomains_count !=0) {
$actions_links = [[
'href' => $linker->getLink(['section' => 'email', 'page' => $page, 'action' => 'add']),
'label' => $lng['emails']['emails_add']
]];
}
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($list, $email_list_data['email_list']),
'actions_links' => $actions_links,
'entity_info' => $lng['emails']['description']
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) {
try {
$json_result = Emails::getLocal($userinfo, array(

View File

@ -33,10 +33,7 @@ if (Settings::IsInList('panel.customer_hide_options', 'extras')) {
$id = (int) Request::get('id');
if ($page == 'overview') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_extras");
eval("echo \"" . \Froxlor\UI\Template::getTemplate("extras/extras") . "\";");
} elseif ($page == 'htpasswds') {
if ($page == 'overview' || $page == 'htpasswds') {
// redirect if this customer sub-page is hidden via settings
if (Settings::IsInList('panel.customer_hide_options', 'extras.directoryprotection')) {
@ -50,36 +47,23 @@ if ($page == 'overview') {
'path' => $lng['panel']['path']
);
try {
// get total count
$json_result = DirProtections::getLocal($userinfo)->listingCount();
$result = json_decode($json_result, true)['data'];
// initialize pagination and filtering
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = DirProtections::getLocal($userinfo, $paging->getApiCommandParams())->listing();
$htpasswd_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.htpasswd.php';
$list = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\DirProtections::class, $userinfo))
->withPagination($htpasswd_list_data['htpasswd_list']['columns'])
->getList();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$count = 0;
$htpasswds = '';
foreach ($result['list'] as $row) {
if (strpos($row['path'], $userinfo['documentroot']) === 0) {
$row['path'] = str_replace($userinfo['documentroot'], "/", $row['path']);
}
$row['path'] = \Froxlor\FileDir::makeCorrectDir($row['path']);
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
eval("\$htpasswds.=\"" . \Froxlor\UI\Template::getTemplate("extras/htpasswds_htpasswd") . "\";");
$count ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("extras/htpasswds") . "\";");
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($list, $htpasswd_list_data['htpasswd_list']),
'actions_links' => [[
'href' => $linker->getLink(['section' => 'extras', 'page' => 'htpasswds', 'action' => 'add']),
'label' => $lng['extras']['directoryprotection_add']
]],
'entity_info' => $lng['extras']['description']
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) {
try {
$json_result = DirProtections::getLocal($userinfo, array(
@ -181,51 +165,27 @@ if ($page == 'overview') {
if ($action == '') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_extras::htaccess");
$fields = array(
'path' => $lng['panel']['path'],
'options_indexes' => $lng['extras']['view_directory'],
'error404path' => $lng['extras']['error404path'],
'error403path' => $lng['extras']['error403path'],
'error500path' => $lng['extras']['error500path'],
'options_cgi' => $lng['extras']['execute_perl']
);
try {
// get total count
$json_result = DirOptions::getLocal($userinfo)->listingCount();
$result = json_decode($json_result, true)['data'];
// initialize pagination and filtering
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = DirOptions::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$count = 0;
$htaccess = '';
$cperlenabled = \Froxlor\Customer\Customer::customerHasPerlEnabled($userinfo['customerid']);
foreach ($result['list'] as $row) {
if (strpos($row['path'], $userinfo['documentroot']) === 0) {
$row['path'] = str_replace($userinfo['documentroot'], "/", $row['path']);
}
$row['path'] = \Froxlor\FileDir::makeCorrectDir($row['path']);
$row['options_indexes'] = str_replace('1', $lng['panel']['yes'], $row['options_indexes']);
$row['options_indexes'] = str_replace('0', $lng['panel']['no'], $row['options_indexes']);
$row['options_cgi'] = str_replace('1', $lng['panel']['yes'], $row['options_cgi']);
$row['options_cgi'] = str_replace('0', $lng['panel']['no'], $row['options_cgi']);
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
eval("\$htaccess.=\"" . \Froxlor\UI\Template::getTemplate("extras/htaccess_htaccess") . "\";");
$count ++;
try {
$htaccess_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.htaccess.php';
$list = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\DirOptions::class, $userinfo))
->withPagination($htaccess_list_data['htaccess_list']['columns'])
->getList();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("extras/htaccess") . "\";");
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($list, $htaccess_list_data['htaccess_list']),
'add_link' => [
'href' => $linker->getLink(['section' => 'extras', 'page' => 'htaccess', 'action' => 'add']),
'label' => $lng['extras']['pathoptions_add']
],
'entity_info' => $lng['extras']['description']
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) {
try {
$json_result = DirOptions::getLocal($userinfo, array(
@ -363,7 +323,7 @@ if ($page == 'overview') {
\Froxlor\UI\Response::standard_success('backupscheduled');
} else {
if (! empty($existing_backupJob)) {
if (!empty($existing_backupJob)) {
$action = "abort";
$row = $existing_backupJob['data'];
@ -371,18 +331,19 @@ if ($page == 'overview') {
$row['backup_web'] = ($row['backup_web'] == '1') ? $lng['panel']['yes'] : $lng['panel']['no'];
$row['backup_mail'] = ($row['backup_mail'] == '1') ? $lng['panel']['yes'] : $lng['panel']['no'];
$row['backup_dbs'] = ($row['backup_dbs'] == '1') ? $lng['panel']['yes'] : $lng['panel']['no'];
}
$pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']);
$backup_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.backup.php';
$backup_form = \Froxlor\UI\HtmlForm::genHTMLForm($backup_data);
$title = $backup_data['backup']['title'];
$image = $backup_data['backup']['image'];
if (! empty($existing_backupJob)) {
// overwrite backup_form after we took everything from it we needed
eval("\$backup_form = \"" . \Froxlor\UI\Template::getTemplate("extras/backup_listexisting") . "\";");
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("extras/backup") . "\";");
$pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']);
$backup_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.backup.php';
UI::twigBuffer('user/form.html.twig', [
'formaction' => $linker->getLink(array('section' => 'extras')),
'formdata' => $backup_data['backup']
]);
UI::twigOutputBuffer();
}
}
} else {

View File

@ -32,50 +32,32 @@ if (Settings::IsInList('panel.customer_hide_options', 'ftp')) {
$id = (int) Request::get('id', 0);
if ($page == 'overview') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_ftp");
eval("echo \"" . \Froxlor\UI\Template::getTemplate('ftp/ftp') . "\";");
} elseif ($page == 'accounts') {
if ($page == 'overview' || $page == 'accounts') {
if ($action == '') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_ftp::accounts");
$fields = array(
'username' => $lng['login']['username'],
'homedir' => $lng['panel']['path'],
'description' => $lng['panel']['ftpdesc']
);
try {
// get total count
$json_result = Ftps::getLocal($userinfo)->listingCount();
$result = json_decode($json_result, true)['data'];
// initialize pagination and filtering
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = Ftps::getLocal($userinfo, $paging->getApiCommandParams())->listing();
$ftp_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.ftps.php';
$list = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Ftps::class, $userinfo))
->withPagination($ftp_list_data['ftp_list']['columns'])
->getList();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$ftps_count = $paging->getEntries();
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$count = 0;
$accounts = '';
foreach ($result['list'] as $row) {
if (strpos($row['homedir'], $userinfo['documentroot']) === 0) {
$row['documentroot'] = str_replace($userinfo['documentroot'], "/", $row['homedir']);
} else {
$row['documentroot'] = $row['homedir'];
}
$row['documentroot'] = \Froxlor\FileDir::makeCorrectDir($row['documentroot']);
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate('ftp/accounts_account') . "\";");
$count++;
$actions_links = false;
if ($userinfo['ftps_used'] < $userinfo['ftps'] || $userinfo['ftps'] == '-1') {
$actions_links = [[
'href' => $linker->getLink(['section' => 'ftp', 'page' => 'accounts', 'action' => 'add']),
'label' => $lng['ftp']['account_add']
]];
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate('ftp/accounts') . "\";");
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($list, $ftp_list_data['ftp_list']),
'actions_links' => $actions_links,
'entity_info' => $lng['ftp']['description']
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) {
try {
$json_result = Ftps::getLocal($userinfo, array(

View File

@ -38,65 +38,41 @@ Database::needRoot(false);
$id = (int) Request::get('id');
if ($page == 'overview') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_mysql");
Database::needSqlData();
$sql = Database::getSqlData();
$lng['mysql']['description'] = str_replace('<SQL_HOST>', $sql['host'], $lng['mysql']['description']);
eval("echo \"" . \Froxlor\UI\Template::getTemplate('mysql/mysql') . "\";");
} elseif ($page == 'mysqls') {
if ($page == 'overview' || $page == 'mysqls') {
if ($action == '') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_mysql::mysqls");
$fields = array(
'databasename' => $lng['mysql']['databasename'],
'description' => $lng['mysql']['databasedescription']
);
try {
// get total count
$json_result = Mysqls::getLocal($userinfo)->listingCount();
$result = json_decode($json_result, true)['data'];
// initialize pagination and filtering
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = Mysqls::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$mysqls_count = $paging->getEntries();
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$count = 0;
$mysqls = '';
$dbservers_stmt = Database::query("SELECT COUNT(DISTINCT `dbserver`) as numservers FROM `" . TABLE_PANEL_DATABASES . "`");
$dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC);
$count_mysqlservers = $dbserver['numservers'];
// Begin root-session
Database::needRoot(true);
foreach ($result['list'] as $row) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
$mbdata_stmt = Database::prepare("SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES
WHERE table_schema = :table_schema
GROUP BY table_schema");
$mbdata = Database::pexecute_first($mbdata_stmt, array(
"table_schema" => $row['databasename']
));
if (!$mbdata) {
$mbdata = array('MB' => 0);
}
$row['size'] = \Froxlor\PhpHelper::sizeReadable($mbdata['MB'], 'GiB', 'bi', '%01.' . (int) Settings::Get('panel.decimal_places') . 'f %s');
eval("\$mysqls.=\"" . \Froxlor\UI\Template::getTemplate('mysql/mysqls_database') . "\";");
$count++;
try {
$mysql_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.mysqls.php';
$list = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Mysqls::class, $userinfo))
->withPagination($mysql_list_data['mysql_list']['columns'])
->getList();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
Database::needRoot(false);
// End root-session
eval("echo \"" . \Froxlor\UI\Template::getTemplate('mysql/mysqls') . "\";");
Database::needSqlData();
$sql = Database::getSqlData();
$lng['mysql']['description'] = str_replace('<SQL_HOST>', $sql['host'], $lng['mysql']['description']);
$actions_links = false;
if ($userinfo['mysqls_used'] < $userinfo['mysqls'] || $userinfo['mysqls'] == '-1') {
$actions_links = [[
'href' => $linker->getLink(['section' => 'mysql', 'page' => 'mysqls', 'action' => 'add']),
'label' => $lng['mysql']['database_create']
]];
}
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($list, $mysql_list_data['mysql_list']),
'actions_links' => $actions_links,
'entity_info' => $lng['mysql']['description']
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) {
try {

View File

@ -19,13 +19,13 @@ if (! defined('AREA')) {
*
*/
use Froxlor\Api\Commands\DomainZones as DomainZones;
use Froxlor\Api\Commands\DomainZones;
use Froxlor\UI\Request;
// This file is being included in admin_domains and customer_domains
// and therefore does not need to require lib/init.php
$domain_id = (int) Request::get(['domain_id']);
$domain_id = (int) Request::get('domain_id');
$record = isset($_POST['record']['record']) ? trim($_POST['record']['record']) : null;
$type = isset($_POST['record']['type']) ? $_POST['record']['type'] : 'A';

View File

@ -545,6 +545,6 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
return $this->response(true);
}
return $this->response(null, 204);
return $this->response(true, 304);
}
}

View File

@ -3,7 +3,6 @@
namespace Froxlor\Api;
use Exception;
use voku\helper\AntiXSS;
/**
* This file is part of the Froxlor project.
@ -23,110 +22,111 @@ use voku\helper\AntiXSS;
*/
class FroxlorRPC
{
/**
* validate a given request
*
* @param $request
* @return array
* @throws Exception
*/
public static function validateRequest($request): array
{
// make basic authentication
if (!isset($_SERVER['PHP_AUTH_USER']) || !self::validateAuth($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) {
header('WWW-Authenticate: Basic realm="API"');
throw new Exception('Unauthenticated. Please provide api user credentials.', 401);
}
/**
* validate a given request
*
* @param $request
* @return array
* @throws Exception
*/
public static function validateRequest($request): array
{
// make basic authentication
if (!isset($_SERVER['PHP_AUTH_USER']) || !self::validateAuth($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) {
if (@php_sapi_name() !== 'cli') {
header('WWW-Authenticate: Basic realm="API"');
}
throw new Exception('Unauthenticated. Please provide api user credentials.', 401);
}
// check if present
if (empty($request)) {
throw new Exception('Empty request body.', 400);
}
// check if present
if (empty($request)) {
throw new Exception('Empty request body.', 400);
}
// decode json request
$decoded_request = json_decode($request, true);
// decode json request
$decoded_request = json_decode($request, true);
// is it valid?
if (is_null($decoded_request)) {
throw new Exception('Invalid JSON Format.', 400);
}
// is it valid?
if (is_null($decoded_request)) {
throw new Exception('Invalid JSON Format.', 400);
}
return self::validateBody($decoded_request);
}
return self::validateBody($decoded_request);
}
/**
* validates the given api credentials
*
* @param string $key
* @param string $secret
* @return boolean
*/
private static function validateAuth(string $key, string $secret): bool
{
$sel_stmt = \Froxlor\Database\Database::prepare(
"
/**
* validates the given api credentials
*
* @param string $key
* @param string $secret
* @return boolean
*/
private static function validateAuth(string $key, string $secret): bool
{
$sel_stmt = \Froxlor\Database\Database::prepare(
"
SELECT ak.*, a.api_allowed as admin_api_allowed, c.api_allowed as cust_api_allowed, c.deactivated
FROM `api_keys` ak
LEFT JOIN `panel_admins` a ON a.adminid = ak.adminid
LEFT JOIN `panel_customers` c ON c.customerid = ak.customerid
WHERE `apikey` = :ak AND `secret` = :as
"
);
$result = \Froxlor\Database\Database::pexecute_first($sel_stmt, array(
'ak' => $key,
'as' => $secret
), true, true);
if ($result) {
if ($result['apikey'] == $key && $result['secret'] == $secret && ($result['valid_until'] == -1 || $result['valid_until'] >= time(
)) && (($result['customerid'] == 0 && $result['admin_api_allowed'] == 1) || ($result['customerid'] > 0 && $result['cust_api_allowed'] == 1 && $result['deactivated'] == 0))) {
// get user to check whether api call is allowed
if (!empty($result['allowed_from'])) {
// @todo allow specification and validating of whole subnets later
$ip_list = explode(",", $result['allowed_from']);
$access_ip = inet_ntop(inet_pton($_SERVER['REMOTE_ADDR']));
if (in_array($access_ip, $ip_list)) {
return true;
}
} else {
return true;
}
}
}
return false;
}
);
$result = \Froxlor\Database\Database::pexecute_first($sel_stmt, array(
'ak' => $key,
'as' => $secret
), true, true);
if ($result) {
if ($result['apikey'] == $key && $result['secret'] == $secret && ($result['valid_until'] == -1 || $result['valid_until'] >= time()) && (($result['customerid'] == 0 && $result['admin_api_allowed'] == 1) || ($result['customerid'] > 0 && $result['cust_api_allowed'] == 1 && $result['deactivated'] == 0))) {
// get user to check whether api call is allowed
if (!empty($result['allowed_from'])) {
// @todo allow specification and validating of whole subnets later
$ip_list = explode(",", $result['allowed_from']);
$access_ip = inet_ntop(inet_pton($_SERVER['REMOTE_ADDR']));
if (in_array($access_ip, $ip_list)) {
return true;
}
} else {
return true;
}
}
}
throw new Exception('Invalid authorization credentials', 403);
}
/**
* validates the given command
*
* @param array $request
*
* @return array
* @throws Exception
*/
private static function validateBody($request)
{
// check command exists
if (empty($request['command'])) {
throw new Exception("Please provide a command.", 400);
}
/**
* validates the given command
*
* @param array $request
*
* @return array
* @throws Exception
*/
private static function validateBody($request)
{
// check command exists
if (empty($request['command'])) {
throw new Exception("Please provide a command.", 400);
}
$command = explode(".", $request['command']);
$command = explode(".", $request['command']);
if (count($command) != 2) {
throw new Exception("The given command is invalid.", 400);
}
// simply check for file-existance, as we do not want to use our autoloader because this way
// it will recognize non-api classes+methods as valid commands
$apiclass = '\\Froxlor\\Api\\Commands\\' . $command[0];
if (!class_exists($apiclass) || !@method_exists($apiclass, $command[1])) {
throw new Exception("Unknown command", 400);
}
return array(
'command' => array(
'class' => $command[0],
'method' => $command[1]
),
'params' => $request['params'] ?? null
);
}
if (count($command) != 2) {
throw new Exception("The given command is invalid.", 400);
}
// simply check for file-existance, as we do not want to use our autoloader because this way
// it will recognize non-api classes+methods as valid commands
$apiclass = '\\Froxlor\\Api\\Commands\\' . $command[0];
if (!class_exists($apiclass) || !@method_exists($apiclass, $command[1])) {
throw new Exception("Unknown command", 400);
}
return array(
'command' => array(
'class' => $command[0],
'method' => $command[1]
),
'params' => $request['params'] ?? null
);
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace Froxlor\UI\Callbacks;
use Froxlor\UI\Panel\UI;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Listing
*
*/
class Domain
{
public static function domainTarget(string $data, array $attributes): mixed
{
if (empty($attributes['aliasdomain'])) {
// path or redirect
if (preg_match('/^https?\:\/\//', $attributes['documentroot'])) {
return [
'type' => 'link',
'data' => [
'text' => $attributes['documentroot'],
'href' => $attributes['documentroot'],
'target' => '_blank'
]
];
} else {
// show docroot nicely
if (strpos($attributes['documentroot'], UI::getCurrentUser()['documentroot']) === 0) {
$attributes['documentroot'] = \Froxlor\FileDir::makeCorrectDir(str_replace(UI::getCurrentUser()['documentroot'], "/", $attributes['documentroot']));
}
return $attributes['documentroot'];
}
}
return UI::getLng('domains.aliasdomain') . ' ' . $attributes['aliasdomain'];
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Froxlor\UI\Callbacks;
use Froxlor\Settings;
use Froxlor\PhpHelper;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Listing
*
*/
class Email
{
public static function account(string $data, array $attributes): mixed
{
return [
'type' => 'booleanWithInfo',
'data' => [
'checked' => $data != 0,
'info' => $data != 0 ? PhpHelper::sizeReadable($attributes['mboxsize'], 'GiB', 'bi', '%01.' . (int) Settings::Get('panel.decimal_places') . 'f %s') : ''
]
];
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace Froxlor\UI\Callbacks;
use Froxlor\UI\Panel\UI;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Listing
*
*/
class Ftp
{
public static function pathRelative(string $data, array $attributes): string
{
if (strpos($data, UI::getCurrentUser()['documentroot']) === 0) {
$data = str_replace(UI::getCurrentUser()['documentroot'], "/", $data);
}
$data = \Froxlor\FileDir::makeCorrectDir($data);
return $data;
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace Froxlor\UI\Callbacks;
use Froxlor\UI\Panel\UI;
@ -21,38 +22,41 @@ use Froxlor\UI\Panel\UI;
class Impersonate
{
public static function admin(string $data, array $attributes): array
{
$linker = UI::getLinker();
return [
'type' => 'link',
'data' => [
'text' => $data,
'href' => $linker->getLink([
'section' => 'admins',
'page' => 'admins',
'action' => 'su',
'id' => $attributes['adminid'],
]),
]
];
}
public static function admin(string $data, array $attributes): mixed
{
if (UI::getCurrentUser()['adminid'] != $attributes['adminid']) {
$linker = UI::getLinker();
return [
'type' => 'link',
'data' => [
'text' => $data,
'href' => $linker->getLink([
'section' => 'admins',
'page' => 'admins',
'action' => 'su',
'id' => $attributes['adminid'],
]),
]
];
}
return $data;
}
public static function customer(string $data, array $attributes): array
{
$linker = UI::getLinker();
return [
'type' => 'link',
'data' => [
'text' => $data,
'href' => $linker->getLink([
'section' => 'customers',
'page' => 'customers',
'action' => 'su',
'sort' => $attributes['loginname'],
'id' => $attributes['customerid'],
]),
]
];
}
public static function customer(string $data, array $attributes): array
{
$linker = UI::getLinker();
return [
'type' => 'link',
'data' => [
'text' => $data,
'href' => $linker->getLink([
'section' => 'customers',
'page' => 'customers',
'action' => 'su',
'sort' => $attributes['loginname'],
'id' => $attributes['customerid'],
]),
]
];
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace Froxlor\UI\Callbacks;
use Froxlor\Database\Database;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Listing
*
*/
class Mysql
{
public static function dbserver(string $data, array $attributes): string
{
// get sql-root access data
Database::needRoot(true, (int) $data);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
return $sql_root['caption'] . '<br><small>' . $sql_root['host'] . '</small>';
}
}

View File

@ -1,6 +1,9 @@
<?php
namespace Froxlor\UI\Callbacks;
use Froxlor\PhpHelper;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
@ -18,22 +21,32 @@ namespace Froxlor\UI\Callbacks;
*/
class Text
{
public static function boolean(?string $data): array
{
return [
'type' => 'boolean',
'data' => (bool) $data
];
}
public static function boolean(?string $data): array
{
return [
'type' => 'boolean',
'data' => (bool) $data
];
}
public static function domainWithSan(string $data, array $attributes): array
{
return [
'type' => 'domainWithSan',
'data' => [
'domain' => $data,
'san' => implode(', ', $attributes['san'] ?? []),
]
];
}
public static function domainWithSan(string $data, array $attributes): array
{
return [
'type' => 'domainWithSan',
'data' => [
'domain' => $data,
'san' => implode(', ', $attributes['san'] ?? []),
]
];
}
public static function customerfullname(string $data, array $attributes): string
{
return \Froxlor\User::getCorrectFullUserDetails($attributes);
}
public static function size(string $data, array $attributes): string
{
return PhpHelper::sizeReadable($data, null, 'bi');
}
}

View File

@ -87,16 +87,23 @@ class Collection
public function has(string $column, string $class, string $parentKey = 'id', string $childKey = 'id', array $params = []): Collection
{
$this->has[] = [
'column' => $column,
'class' => $class,
'parentKey' => $parentKey,
'childKey' => $childKey,
'params' => $params
'column' => $column,
'class' => $class,
'parentKey' => $parentKey,
'childKey' => $childKey,
'params' => $params
];
return $this;
}
public function addParam(array $keyval): Collection
{
$this->params = array_merge($this->params, $keyval);
return $this;
}
public function withPagination(array $columns): Collection
{
// Get only searchable columns

View File

@ -12,10 +12,10 @@ use Froxlor\Settings;
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/

View File

@ -35,6 +35,13 @@ class UI
*/
private static $linker = null;
/**
* current logged in user
*
* @var array
*/
private static $userinfo = [];
/**
* default fallback theme
*
@ -224,6 +231,16 @@ class UI
return self::$linker;
}
public static function setCurrentUser($userinfo = null)
{
self::$userinfo = $userinfo;
}
public static function getCurrentUser(): array
{
return self::$userinfo;
}
public static function setLng($lng = array())
{
self::$lng = $lng;

View File

@ -24,7 +24,7 @@ class User
$returnval = $userinfo['name'] . ', ' . $userinfo['firstname'];
} else {
if ($userinfo['name'] != '' && $userinfo['firstname'] != '') {
$returnval = $userinfo['name'] . ', ' . $userinfo['firstname'] . ' | ' . $userinfo['company'];
$returnval = $userinfo['name'] . ', ' . $userinfo['firstname'] . '<br><small>' . $userinfo['company'] . '</small>';
} else {
$returnval = $userinfo['company'];
}

View File

@ -14,6 +14,9 @@
* @package Formfields
*
*/
use Froxlor\Settings;
return array(
'domain_add' => array(
'title' => $lng['domains']['subdomain_add'],
@ -41,19 +44,19 @@ return array(
),
'path' => array(
'label' => $lng['panel']['path'],
'desc' => (\Froxlor\Settings::Get('panel.pathedit') != 'Dropdown' ? $lng['panel']['pathDescriptionSubdomain'] : null),
'desc' => (Settings::Get('panel.pathedit') != 'Dropdown' ? $lng['panel']['pathDescriptionSubdomain'] : null),
'type' => $pathSelect['type'],
'select_var' => $pathSelect['select_var'] ?? '',
'value' => $pathSelect['value'],
'note' => $pathSelect['note'] ?? '',
),
'url' => array(
'visible' => (\Froxlor\Settings::Get('panel.pathedit') == 'Dropdown' ? true : false),
'visible' => (Settings::Get('panel.pathedit') == 'Dropdown' ? true : false),
'label' => $lng['panel']['urloverridespath'],
'type' => 'text'
),
'redirectcode' => array(
'visible' => (\Froxlor\Settings::Get('customredirect.enabled') == '1' ? true : false),
'visible' => (Settings::Get('customredirect.enabled') == '1' ? true : false),
'label' => $lng['domains']['redirectifpathisurl'],
'desc' => $lng['domains']['redirectifpathisurlinfo'],
'type' => 'select',
@ -71,18 +74,18 @@ return array(
'select_var' => $openbasedir
),
'phpsettingid' => array(
'visible' => (((int) \Froxlor\Settings::Get('system.mod_fcgid') == 1 || (int) \Froxlor\Settings::Get('phpfpm.enabled') == 1) && count($phpconfigs) > 0 ? true : false),
'visible' => (((int) Settings::Get('system.mod_fcgid') == 1 || (int) Settings::Get('phpfpm.enabled') == 1) && count($phpconfigs) > 0 ? true : false),
'label' => $lng['admin']['phpsettings']['title'],
'type' => 'select',
'select_var' => $phpconfigs,
'selected' => (int) Settings::Get('phpfpm.enabled') == 1) ? Settings::Get('phpfpm.defaultini') : Settings::Get('system.mod_fcgid_defaultini')
'selected' => (int) Settings::Get('phpfpm.enabled') == 1 ? Settings::Get('phpfpm.defaultini') : Settings::Get('system.mod_fcgid_defaultini')
)
)
),
'section_bssl' => array(
'title' => $lng['admin']['webserversettings_ssl'],
'image' => 'icons/domain_add.png',
'visible' => \Froxlor\Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports ? true : false) : false,
'visible' => Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports ? true : false) : false,
'fields' => array(
'sslenabled' => array(
'label' => $lng['admin']['domain_sslenabled'],
@ -98,7 +101,7 @@ return array(
'checked' => false
),
'letsencrypt' => array(
'visible' => (\Froxlor\Settings::Get('system.leenabled') == '1' ? true : false),
'visible' => (Settings::Get('system.leenabled') == '1' ? true : false),
'label' => $lng['customer']['letsencrypt']['title'],
'desc' => $lng['customer']['letsencrypt']['description'],
'type' => 'checkbox',
@ -106,7 +109,7 @@ return array(
'checked' => false
),
'http2' => array(
'visible' => ($ssl_ipsandports ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' && \Froxlor\Settings::Get('system.http2_support') == '1',
'visible' => ($ssl_ipsandports ? true : false) && Settings::Get('system.webserver') != 'lighttpd' && Settings::Get('system.http2_support') == '1',
'label' => $lng['admin']['domain_http2']['title'],
'desc' => $lng['admin']['domain_http2']['description'],
'type' => 'checkbox',

View File

@ -23,7 +23,7 @@ return array(
'title' => $lng['emails']['account_add'],
'image' => 'icons/email_add.png',
'fields' => array(
'email_full' => array(
'emailaddr' => array(
'label' => $lng['emails']['emailaddress'],
'type' => 'label',
'value' => $result['email_full']

View File

@ -23,7 +23,7 @@ return array(
'title' => $lng['emails']['forwarder_add'],
'image' => 'icons/autoresponder_add.png',
'fields' => array(
'email_full' => array(
'emailaddr' => array(
'label' => $lng['emails']['from'],
'type' => 'label',
'value' => $result['email_full']

View File

@ -17,7 +17,7 @@
return array(
'backup' => array(
'title' => $lng['extras']['backup'],
'image' => 'icons/backup_big.png',
'image' => 'fa-solid fa-server',
'sections' => array(
'section_a' => array(
'title' => $lng['extras']['backup'],
@ -33,8 +33,9 @@ return array(
),
'path_protection_info' => array(
'label' => $lng['extras']['path_protection_label'],
'type' => 'label',
'value' => $lng['extras']['path_protection_info']
'type' => 'infotext',
'value' => $lng['extras']['path_protection_info'],
'classes' => 'fw-bold text-danger'
),
'backup_web' => array(
'label' => $lng['extras']['backup_web'],

View File

@ -17,7 +17,7 @@
return array(
'htaccess_add' => array(
'title' => $lng['extras']['pathoptions_add'],
'image' => 'icons/htpasswd_add.png',
'image' => 'fa-solid fa-folder',
'sections' => array(
'section_a' => array(
'title' => $lng['extras']['pathoptions_add'],

View File

@ -17,7 +17,7 @@
return array(
'htaccess_edit' => array(
'title' => $lng['extras']['pathoptions_edit'],
'image' => 'icons/htpasswd_edit.png',
'image' => 'fa-solid fa-folder',
'sections' => array(
'section_a' => array(
'title' => $lng['extras']['pathoptions_edit'],

View File

@ -17,7 +17,7 @@
return array(
'htpasswd_add' => array(
'title' => $lng['extras']['directoryprotection_add'],
'image' => 'icons/htpasswd_add.png',
'image' => 'fa-solid fa-lock',
'sections' => array(
'section_a' => array(
'title' => $lng['extras']['directoryprotection_add'],

View File

@ -17,7 +17,7 @@
return array(
'htpasswd_edit' => array(
'title' => $lng['extras']['directoryprotection_edit'],
'image' => 'icons/htpasswd_edit.png',
'image' => 'fa-solid fa-lock',
'sections' => array(
'section_a' => array(
'title' => $lng['extras']['directoryprotection_edit'],

View File

@ -362,6 +362,7 @@ if ($nosession == 1 && AREA != 'login') {
}
UI::twig()->addGlobal('userinfo', ($userinfo ?? []));
UI::setCurrentUser($userinfo);
/**
* Logic moved out of lng-file

View File

@ -83,7 +83,7 @@ return array(
'url' => 'customer_ftp.php',
'label' => $lng['menue']['ftp']['ftp'],
'show_element' => (! \Froxlor\Settings::IsInList('panel.customer_hide_options', 'ftp')),
'icon' => 'fa fa-transfer',
'icon' => 'fa fa-users',
'elements' => array(
array(
'url' => 'customer_ftp.php?page=accounts',

View File

@ -16,81 +16,74 @@
*
*/
use Froxlor\UI\Callbacks\Text;
use Froxlor\UI\Callbacks\Impersonate;
use Froxlor\UI\Callbacks\ProgressBar;
use Froxlor\UI\Listing;
return [
'customer_list' => [
'title' => $lng['admin']['customers'],
'icon' => 'fa-solid fa-user',
'columns' => [
'c.loginname' => [
'label' => $lng['login']['username'],
'column' => 'loginname',
'format_callback' => [Impersonate::class, 'customer'],
],
'a.loginname' => [
'label' => $lng['admin']['admin'],
'column' => 'admin.loginname',
'format_callback' => [Impersonate::class, 'admin'],
],
'c.name' => [
'label' => $lng['customer']['name'],
'column' => 'name',
],
'c.email' => [
'label' => $lng['customer']['email'],
'column' => 'email',
],
'c.firstname' => [
'label' => $lng['customer']['firstname'],
'column' => 'firstname',
],
'c.company' => [
'label' => $lng['customer']['company'],
'column' => 'company',
],
'c.diskspace' => [
'label' => $lng['customer']['diskspace'],
'column' => 'diskspace',
'format_callback' => [ProgressBar::class, 'diskspace'],
],
'c.traffic' => [
'label' => $lng['customer']['traffic'],
'column' => 'traffic',
'format_callback' => [ProgressBar::class, 'traffic'],
],
],
'visible_columns' => Listing::getVisibleColumnsForListing('customer_list', [
'c.loginname',
'a.loginname',
'c.email',
'c.firstname',
'c.company',
'c.diskspace',
'c.traffic',
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'customers',
'page' => 'customers',
'action' => 'edit',
'id' => ':customerid'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'customers',
'page' => 'customers',
'action' => 'delete',
'id' => ':customerid'
],
],
],
]
'customer_list' => [
'title' => $lng['admin']['customers'],
'icon' => 'fa-solid fa-user',
'columns' => [
'c.name' => [
'label' => $lng['customer']['name'],
'column' => 'name',
'format_callback' => [Text::class, 'customerfullname'],
],
'c.loginname' => [
'label' => $lng['login']['username'],
'column' => 'loginname',
'format_callback' => [Impersonate::class, 'customer'],
],
'a.loginname' => [
'label' => $lng['admin']['admin'],
'column' => 'admin.loginname',
'format_callback' => [Impersonate::class, 'admin'],
],
'c.email' => [
'label' => $lng['customer']['email'],
'column' => 'email',
],
'c.diskspace' => [
'label' => $lng['customer']['diskspace'],
'column' => 'diskspace',
'format_callback' => [ProgressBar::class, 'diskspace'],
],
'c.traffic' => [
'label' => $lng['customer']['traffic'],
'column' => 'traffic',
'format_callback' => [ProgressBar::class, 'traffic'],
],
],
'visible_columns' => Listing::getVisibleColumnsForListing('customer_list', [
'c.name',
'c.loginname',
'a.loginname',
'c.email',
'c.diskspace',
'c.traffic',
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'customers',
'page' => 'customers',
'action' => 'edit',
'id' => ':customerid'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'customers',
'page' => 'customers',
'action' => 'delete',
'id' => ':customerid'
],
],
],
]
];

View File

@ -16,86 +16,76 @@
*
*/
use Froxlor\UI\Callbacks\Text;
use Froxlor\UI\Callbacks\Impersonate;
use Froxlor\UI\Listing;
return [
'domain_list' => [
'title' => $lng['admin']['domains'],
'icon' => 'fa-solid fa-user',
'columns' => [
'd.domain_ace' => [
'label' => $lng['domains']['domainname'],
'column' => 'domain_ace',
'sortable' => true,
],
'c.name' => [
'label' => $lng['customer']['name'],
'column' => 'customer.name',
],
'c.firstname' => [
'label' => $lng['customer']['firstname'],
'column' => 'customer.firstname',
],
'c.company' => [
'label' => $lng['customer']['company'],
'column' => 'customer.company',
],
'c.loginname' => [
'label' => $lng['login']['username'],
'column' => 'customer.loginname',
'format_callback' => [Impersonate::class, 'customer'],
'sortable' => true,
],
'd.aliasdomain' => [
'label' => $lng['domains']['aliasdomain'],
'column' => 'aliasdomain',
],
],
'visible_columns' => Listing::getVisibleColumnsForListing('domain_list', [
'd.domain_ace',
'c.name',
'c.firstname',
'c.company',
'c.loginname',
'd.aliasdomain',
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'domains',
'page' => 'domains',
'action' => 'edit',
'id' => ':id'
],
],
'logfiles' => [
'icon' => 'fa fa-file',
'href' => [
'section' => 'domains',
'page' => 'logfiles',
'domain_id' => ':id'
],
],
'domaindnseditor' => [
'icon' => 'fa fa-globe',
'href' => [
'section' => 'domains',
'page' => 'domaindnseditor',
'domain_id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'domains',
'page' => 'domains',
'action' => 'delete',
'id' => ':id'
],
],
]
]
'domain_list' => [
'title' => $lng['admin']['domains'],
'icon' => 'fa-solid fa-user',
'columns' => [
'd.domain_ace' => [
'label' => $lng['domains']['domainname'],
'column' => 'domain_ace',
],
'c.name' => [
'label' => $lng['customer']['name'],
'column' => 'customer.name',
'format_callback' => [Text::class, 'customerfullname'],
],
'c.loginname' => [
'label' => $lng['login']['username'],
'column' => 'customer.loginname',
'format_callback' => [Impersonate::class, 'customer'],
],
'd.aliasdomain' => [
'label' => $lng['domains']['aliasdomain'],
'column' => 'aliasdomain',
],
],
'visible_columns' => Listing::getVisibleColumnsForListing('domain_list', [
'd.domain_ace',
'c.name',
'c.loginname',
'd.aliasdomain',
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'domains',
'page' => 'domains',
'action' => 'edit',
'id' => ':id'
],
],
'logfiles' => [
'icon' => 'fa fa-file',
'href' => [
'section' => 'domains',
'page' => 'logfiles',
'domain_id' => ':id'
],
],
'domaindnseditor' => [
'icon' => 'fa fa-globe',
'href' => [
'section' => 'domains',
'page' => 'domaindnseditor',
'domain_id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'domains',
'page' => 'domains',
'action' => 'delete',
'id' => ':id'
],
]
]
]
];

View File

@ -21,7 +21,7 @@ use Froxlor\UI\Listing;
return [
'plan_list' => [
'title' => $lng['domains']['ssl_certificates'],
'title' => $lng['admin']['plans']['plans'],
'icon' => 'fa-solid fa-user',
'columns' => [
'p.name' => [

View File

@ -0,0 +1,79 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @author Maurice Preuß <hello@envoyr.com>
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Tabellisting
*
*/
use Froxlor\UI\Callbacks\Domain;
use Froxlor\UI\Listing;
return [
'domain_list' => [
'title' => $lng['admin']['domains'],
'icon' => 'fa-solid fa-user',
'columns' => [
'd.domain_ace' => [
'label' => $lng['domains']['domainname'],
'column' => 'domain_ace',
],
'd.documentroot' => [
'label' => $lng['panel']['path'],
'column' => 'documentroot',
'format_callback' => [Domain::class, 'domainTarget'],
]
],
'visible_columns' => Listing::getVisibleColumnsForListing('domain_list', [
'd.domain_ace',
'd.documentroot'
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'domains',
'page' => 'domains',
'action' => 'edit',
'id' => ':id'
],
],
'logfiles' => [
'icon' => 'fa fa-file',
'href' => [
'section' => 'domains',
'page' => 'logfiles',
'domain_id' => ':id'
],
],
'domaindnseditor' => [
'icon' => 'fa fa-globe',
'href' => [
'section' => 'domains',
'page' => 'domaindnseditor',
'domain_id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'domains',
'page' => 'domains',
'action' => 'delete',
'id' => ':id'
],
]
]
]
];

View File

@ -0,0 +1,83 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @author Maurice Preuß <hello@envoyr.com>
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Tabellisting
*
*/
use Froxlor\UI\Callbacks\Email;
use Froxlor\UI\Callbacks\Text;
use Froxlor\UI\Listing;
return [
'email_list' => [
'title' => $lng['menue']['email']['emails'],
'icon' => 'fa-solid fa-envelope',
'columns' => [
'm.email_full' => [
'label' => $lng['emails']['emailaddress'],
'column' => 'email_full',
],
'm.destination' => [
'label' => $lng['emails']['forwarders'],
'column' => 'destination',
// @todo formatting
],
'm.popaccountid' => [
'label' => $lng['emails']['account'],
'column' => 'popaccountid',
'format_callback' => [Email::class, 'account'],
],
'm.iscatchall' => [
'label' => $lng['emails']['catchall'],
'column' => 'iscatchall',
'format_callback' => [Text::class, 'boolean'],
'visible' => \Froxlor\Settings::Get('catchall.catchall_enabled') == '1'
],
'm.quota' => [
'label' => $lng['emails']['quota'],
'column' => 'quota',
'visible' => \Froxlor\Settings::Get('system.mail_quota_enabled') == '1'
]
],
'visible_columns' => Listing::getVisibleColumnsForListing('email_list', [
'm.email_full',
'm.destination',
'm.popaccountid',
'm.iscatchall',
'm.quota'
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'email',
'page' => 'emails',
'action' => 'edit',
'id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'email',
'page' => 'emails',
'action' => 'delete',
'id' => ':id'
],
]
]
]
];

View File

@ -0,0 +1,74 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @author Maurice Preuß <hello@envoyr.com>
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Tabellisting
*
*/
use Froxlor\UI\Callbacks\Ftp;
use Froxlor\UI\Listing;
return [
'ftp_list' => [
'title' => $lng['menue']['ftp']['accounts'],
'icon' => 'fa-solid fa-users',
'columns' => [
'username' => [
'label' => $lng['login']['username'],
'column' => 'username',
],
'description' => [
'label' => $lng['panel']['ftpdesc'],
'column' => 'description'
],
'homedir' => [
'label' => $lng['panel']['path'],
'column' => 'homedir',
'format_callback' => [Ftp::class, 'pathRelative']
],
'shell' => [
'label' => $lng['panel']['shell'],
'column' => 'shell',
'visible' => \Froxlor\Settings::Get('system.allow_customer_shell') == '1'
]
],
'visible_columns' => Listing::getVisibleColumnsForListing('ftp_list', [
'username',
'description',
'homedir',
'shell'
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'ftp',
'page' => 'ftps',
'action' => 'edit',
'id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'ftp',
'page' => 'ftps',
'action' => 'delete',
'id' => ':id'
],
]
]
]
];

View File

@ -0,0 +1,87 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @author Maurice Preuß <hello@envoyr.com>
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Tabellisting
*
*/
use Froxlor\UI\Callbacks\Ftp;
use Froxlor\UI\Callbacks\Text;
use Froxlor\UI\Listing;
return [
'htaccess_list' => [
'title' => $lng['menue']['extras']['pathoptions'],
'icon' => 'fa-solid fa-folder',
'columns' => [
'path' => [
'label' => $lng['panel']['path'],
'column' => 'path',
'format_callback' => [Ftp::class, 'pathRelative']
],
'option_indexes' => [
'label' => $lng['extras']['view_directory'],
'column' => 'option_indexes',
'format_callback' => [Text::class, 'boolean']
],
'error404path' => [
'label' => $lng['extras']['error404path'],
'column' => 'error404path'
],
'error403path' => [
'label' => $lng['extras']['error403path'],
'column' => 'error403path'
],
'error500path' => [
'label' => $lng['extras']['error500path'],
'column' => 'error500path'
],
'options_cgi' => [
'label' => $lng['extras']['execute_perl'],
'column' => 'options_cgi',
'format_callback' => [Text::class, 'boolean'],
'visible' => $cperlenabled
]
],
'visible_columns' => Listing::getVisibleColumnsForListing('htaccess_list', [
'path',
'option_indexes',
'error404path',
'error403path',
'error500path',
'options_cgi'
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'extras',
'page' => 'htaccess',
'action' => 'edit',
'id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'extras',
'page' => 'htaccess',
'action' => 'delete',
'id' => ':id'
],
]
]
]
];

View File

@ -0,0 +1,63 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @author Maurice Preuß <hello@envoyr.com>
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Tabellisting
*
*/
use Froxlor\UI\Callbacks\Ftp;
use Froxlor\UI\Listing;
return [
'htpasswd_list' => [
'title' => $lng['menue']['extras']['directoryprotection'],
'icon' => 'fa-solid fa-lock',
'columns' => [
'username' => [
'label' => $lng['login']['username'],
'column' => 'username'
],
'path' => [
'label' => $lng['panel']['path'],
'column' => 'path',
'format_callback' => [Ftp::class, 'pathRelative']
]
],
'visible_columns' => Listing::getVisibleColumnsForListing('htpasswd_list', [
'username',
'path'
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'extras',
'page' => 'htpasswds',
'action' => 'edit',
'id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'extras',
'page' => 'htpasswds',
'action' => 'delete',
'id' => ':id'
],
]
]
]
];

View File

@ -0,0 +1,76 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @author Maurice Preuß <hello@envoyr.com>
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Tabellisting
*
*/
use Froxlor\UI\Callbacks\Mysql;
use Froxlor\UI\Callbacks\Text;
use Froxlor\UI\Listing;
return [
'mysql_list' => [
'title' => $lng['menue']['mysql']['databases'],
'icon' => 'fa-solid fa-database',
'columns' => [
'databasename' => [
'label' => $lng['mysql']['databasename'],
'column' => 'databasename',
],
'description' => [
'label' => $lng['mysql']['databasedescription'],
'column' => 'description'
],
'size' => [
'label' => $lng['mysql']['size'],
'column' => 'size',
'format_callback' => [Text::class, 'size']
],
'dbserver' => [
'label' => $lng['mysql']['mysql_server'],
'column' => 'dbserver',
'format_callback' => [Mysql::class, 'dbserver'],
'visible' => $count_mysqlservers > 1
]
],
'visible_columns' => Listing::getVisibleColumnsForListing('mysql_list', [
'databasename',
'description',
'size',
'dbserver'
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'mysql',
'page' => 'mysqls',
'action' => 'edit',
'id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'mysql',
'page' => 'mysqls',
'action' => 'delete',
'id' => ':id'
],
]
]
]
];

View File

@ -1893,8 +1893,8 @@ $lng['crondesc']['cron_backup'] = 'Process backup jobs';
$lng['error']['backupfunctionnotenabled'] = 'The backup function is not enabled';
$lng['serversettings']['backupenabled']['title'] = "Enable backup for customers";
$lng['serversettings']['backupenabled']['description'] = "If activated, the customer will be able to schedule backup jobs (cron-backup) which generates an archive within his docroot (subdirectory chosable by customer)";
$lng['extras']['path_protection_label'] = '<strong class="red">Important</strong>';
$lng['extras']['path_protection_info'] = '<strong class="red">We strongly recommend protecting the given path, see "Extras" -> "Directory protection"</strong>';
$lng['extras']['path_protection_label'] = '<strong class="text-danger">Important</strong>';
$lng['extras']['path_protection_info'] = 'We strongly recommend protecting the given path, see "Extras" -> "Directory protection"';
$lng['tasks']['CREATE_CUSTOMER_BACKUP'] = 'Backup job for customer %loginname%';
$lng['error']['dns_domain_nodns'] = 'DNS is not enabled for this domain';

View File

@ -1543,8 +1543,8 @@ $lng['crondesc']['cron_backup'] = 'Ausstehende Sicherungen erstellen';
$lng['error']['backupfunctionnotenabled'] = 'Die Sicherungs-Funktion is nicht aktiviert';
$lng['serversettings']['backupenabled']['title'] = "Backup für Kunden aktivieren";
$lng['serversettings']['backupenabled']['description'] = "Wenn dies aktiviert ist, kann der Kunde Sicherungen planen (cron-backup) welche ein Archiv in sein Heimatverzeichnis ablegt (Unterordner vom Kunden wählbar)";
$lng['extras']['path_protection_label'] = '<strong class="red">Wichtig</strong>';
$lng['extras']['path_protection_info'] = '<strong class="red">Wir raten dringend dazu den angegebenen Pfad zu schützen, siehe "Extras" -> "Verzeichnisschutz"</strong>';
$lng['extras']['path_protection_label'] = '<strong class="text-danger">Wichtig</strong>';
$lng['extras']['path_protection_info'] = 'Wir raten dringend dazu den angegebenen Pfad zu schützen, siehe "Extras" -> "Verzeichnisschutz"';
$lng['tasks']['CREATE_CUSTOMER_BACKUP'] = 'Datensicherung für Kunde %loginname%';
$lng['error']['dns_domain_nodns'] = 'DNS ist für diese Domain nicht aktiviert';

View File

@ -19,15 +19,13 @@ if (! defined('AREA')) {
*
*/
use Froxlor\Api\Commands\SubDomains as SubDomains;
use Froxlor\Api\Commands\SubDomains;
use Froxlor\Settings;
use Froxlor\UI\Request;
// This file is being included in admin_domains and customer_domains
// and therefore does not need to require lib/init.php
// TODO get domain related settings for logfile (speciallogfile)
$domain_id = (int) Request::get('domain_id');
$last_n = (int) Request::get('number_of_lines', 100);

View File

@ -6,7 +6,7 @@
{% if field.desc is defined and field.desc is not empty %}<br><small>{{ field.desc|raw }}</small>
{% endif %}
</label>
<div class="col-sm-8">
<div class="col-sm-8{% if field.type == 'infotext' %} d-flex align-items-center{% endif %}">
{% endif %}
{% if field.type == 'text' or field.type == 'password' or field.type == 'number' or field.type == 'file' or field.type == 'email' or field.type == 'hidden' %}
{{ _self.input(id, field) }}
@ -24,6 +24,8 @@
{{ _self.link(id, field) }}
{% elseif field.type == 'itemlist' %}
{{ _self.itemlist(id, field) }}
{% elseif field.type == 'infotext' %}
{{ _self.infotext(id, field) }}
{% endif %}
{% if norow == false and field.type != 'hidden' %}
</div>
@ -49,11 +51,27 @@
{% endif %}
{% endmacro %}
{% macro infotext(id, field) %}
{% if field.next_to is defined %}
<div class="input-group">
{% endif %}
<span {% if field.classes is defined %} class="{{ field.classes }}" {% endif %}>{{ field.value }}</span>
{% if field.next_to is defined %}
{% for nid, nfield in field.next_to %}
{% if nfield.next_to_prefix is defined %}
<span class="input-group-text">{{ nfield.next_to_prefix }}</span>
{% endif %}
{{ _self.fieldrow(nid, nfield, true) }}
{% endfor %}
</div>
{% endif %}
{% endmacro %}
{% macro plain(id, field) %}
{% if field.next_to is defined %}
<div class="input-group">
{% endif %}
<input type="text" readonly class="form-control-plaintext" id="{{ id }}" value="{{ field.value }}">
<input type="text" readonly class="form-control-plaintext" id="{{ id }}" name="{{ id }}" value="{{ field.value }}">
{% if field.next_to is defined %}
{% for nid, nfield in field.next_to %}
{% if nfield.next_to_prefix is defined %}
@ -74,7 +92,7 @@
<input type="text" readonly class="form-control-plaintext" value="{{ field.display }}">
{% endif %}
{% if field.note is defined and field.note is not empty %}
<div class="invalid-feedback">{{ field.note|raw }}</div>
<div class="invalid-feedback">{{ field.note|raw }}</div>
{% endif %}
{% if field.next_to is defined %}
{% for nid, nfield in field.next_to %}

View File

@ -18,6 +18,17 @@
{% endif %}
{% endmacro %}
{% macro booleanWithInfo(data) %}
{% if (data.checked) %}
<i class="fa fa-check-circle text-success"></i>
{% else %}
<i class="fa fa-times-circle text-danger"></i>
{% endif %}
{% if data.info is not empty %}
{{ data.info }}
{% endif %}
{% endmacro %}
{% macro link(data) %}
{% apply spaceless %}
<a href="{{ data.href }}" {% if data.class is defined %}class="{{ data.class }}"{% endif %} {% if data.target is defined %}target="{{ data.target }}"{% endif %}>

View File

@ -32,6 +32,8 @@
{{ callbacks.progressbar(td.data.data) }}
{% elseif td.data.type == 'boolean' %}
{{ callbacks.boolean(td.data.data) }}
{% elseif td.data.type == 'booleanWithInfo' %}
{{ callbacks.booleanWithInfo(td.data.data) }}
{% elseif td.data.type == 'link' %}
{{ callbacks.link(td.data.data) }}
{% elseif td.data.type == 'domainWithSan' %}

View File

@ -1,9 +1,26 @@
{% extends "Froxlor/userarea.html.twig" %}
{% block content %}
{% import "Froxlor/table/table.html.twig" as table %}
{{ table.table(listing) }}
<div class="row">
<div class="col-12 {% if actions_links is iterable or (entity_info is defined and entity_info is not empty) %}col-md-10 order-2 order-md-1{% endif %}">
{% import "Froxlor/table/table.html.twig" as table %}
{{ table.table(listing) }}
</div>
{% if actions_links is iterable or (entity_info is defined and entity_info is not empty) %}
<div class="col-12 col-md-2 order-1 order-md-2">
{% if actions_links is iterable %}
{% for link in actions_links %}
<a class="btn {{ link.class|default('btn-success') }} d-block mb-2" href="{{ link.href|raw }}">
<i class="{{ link.icon|default('fa-solid fa-plus-circle') }} me-1"></i>
{{ link.label }}</a>
{% endfor %}
{% endif %}
{% if entity_info is defined and entity_info is not empty %}
<div class="alert alert-info" role="alert">
{{ entity_info|raw }}
</div>
{% endif %}
</div>
{% endif %}
</div>
{% endblock %}

View File

@ -43,7 +43,7 @@
</li>
<li class="nav-item dropdown me-2">
<a class="btn btn-secondary btn-sm d-block dropdown-toggle" href="#" id="navbarOpts" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="fa fa-wrench"></i> {{ lng('panel.options') }}
<i class="fa fa-gears"></i> {{ lng('panel.options') }}
</a>
<ul class="dropdown-menu" aria-labelledby="navbarOpts">
<li>

View File

@ -929,7 +929,7 @@ class DomainZonesTest extends TestCase
$json_result = DomainZones::getLocal($customer_userdata, $data)->delete();
$result = json_decode($json_result, true);
$this->assertTrue($result['data']);
$this->assertEquals(200, $result['status']);
$this->assertEquals(200, http_response_code());
}
public function testCustomerDomainZonesDeleteUnmodified()
@ -949,6 +949,6 @@ class DomainZonesTest extends TestCase
$json_result = DomainZones::getLocal($customer_userdata, $data)->delete();
$result = json_decode($json_result, true);
$this->assertTrue($result['data']);
$this->assertEquals(304, $result['status']);
$this->assertEquals(304, http_response_code());
}
}

View File

@ -11,32 +11,20 @@ use Froxlor\Api\FroxlorRPC;
class FroxlorRpcTest extends TestCase
{
public function testInvalidRequestHeader()
{
$this->expectExceptionCode(400);
$this->expectExceptionMessage("Invalid request header");
FroxlorRPC::validateRequest(array());
}
public function testNoCredentialsGiven()
{
$this->expectExceptionCode(400);
$this->expectExceptionMessage("No authorization credentials given");
FroxlorRPC::validateRequest(array(
'header' => 'asd'
));
$this->expectExceptionCode(401);
$this->expectExceptionMessage("Unauthenticated. Please provide api user credentials.");
FroxlorRPC::validateRequest("");
}
public function testValidateAuthInvalid()
{
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Invalid authorization credentials");
FroxlorRPC::validateRequest(array(
'header' => [
'apikey' => 'asd',
'secret' => 'asd'
]
));
$_SERVER['PHP_AUTH_USER'] = 'asd';
$_SERVER['PHP_AUTH_PW'] = 'asd';
FroxlorRPC::validateRequest("");
}
public function testValidateAuthAllowFromInvalid()
@ -45,81 +33,62 @@ class FroxlorRpcTest extends TestCase
Database::query("UPDATE `api_keys` SET `allowed_from` = '123.123.123.123';");
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Invalid authorization credentials");
FroxlorRPC::validateRequest(array(
'header' => [
'apikey' => 'test',
'secret' => 'test'
]
));
$_SERVER['PHP_AUTH_USER'] = 'test';
$_SERVER['PHP_AUTH_PW'] = 'test';
FroxlorRPC::validateRequest("");
}
public function testInvalidRequestBody()
public function testEmptyRequestBody()
{
Database::query("UPDATE `api_keys` SET `allowed_from` = '';");
$this->expectExceptionCode(400);
$this->expectExceptionMessage("Invalid request body");
FroxlorRPC::validateRequest(array(
'header' => [
'apikey' => 'test',
'secret' => 'test'
]
));
$this->expectExceptionMessage("Empty request body.");
$_SERVER['PHP_AUTH_USER'] = 'test';
$_SERVER['PHP_AUTH_PW'] = 'test';
FroxlorRPC::validateRequest("");
}
public function testInvalidJSON()
{
$this->expectExceptionCode(400);
$this->expectExceptionMessage("Invalid JSON Format.");
$_SERVER['PHP_AUTH_USER'] = 'test';
$_SERVER['PHP_AUTH_PW'] = 'test';
FroxlorRPC::validateRequest('asd');
}
public function testNoCommandGiven()
{
$this->expectExceptionCode(400);
$this->expectExceptionMessage("No command given");
FroxlorRPC::validateRequest(array(
'header' => [
'apikey' => 'test',
'secret' => 'test'
],
'body' => 'asd'
));
$this->expectExceptionMessage("Please provide a command.");
$_SERVER['PHP_AUTH_USER'] = 'test';
$_SERVER['PHP_AUTH_PW'] = 'test';
FroxlorRPC::validateRequest(json_encode(['cmd' => 'test']));
}
public function testInvalidCommandGiven()
{
$this->expectExceptionCode(400);
$this->expectExceptionMessage("Invalid command");
FroxlorRPC::validateRequest(array(
'header' => [
'apikey' => 'test',
'secret' => 'test'
],
'body' => [
'command' => 'Froxlor'
]
));
$this->expectExceptionMessage("The given command is invalid.");
$_SERVER['PHP_AUTH_USER'] = 'test';
$_SERVER['PHP_AUTH_PW'] = 'test';
FroxlorRPC::validateRequest(json_encode(['command' => 'Froxlor']));
}
public function testUnknownCommandGiven()
{
$this->expectExceptionCode(400);
$this->expectExceptionMessage("Unknown command");
FroxlorRPC::validateRequest(array(
'header' => [
'apikey' => 'test',
'secret' => 'test'
],
'body' => [
'command' => 'SomeModule.cmd'
]
));
$_SERVER['PHP_AUTH_USER'] = 'test';
$_SERVER['PHP_AUTH_PW'] = 'test';
FroxlorRPC::validateRequest(json_encode(['command' => 'SomeModule.cmd']));
}
public function testCommandOk()
{
$result = FroxlorRPC::validateRequest(array(
'header' => [
'apikey' => 'test',
'secret' => 'test'
],
'body' => [
'command' => 'Froxlor.listFunctions'
]
));
$_SERVER['PHP_AUTH_USER'] = 'test';
$_SERVER['PHP_AUTH_PW'] = 'test';
$result = FroxlorRPC::validateRequest(json_encode(['command' => 'Froxlor.listFunctions']));
$this->assertEquals('Froxlor', $result['command']['class']);
$this->assertEquals('listFunctions', $result['command']['method']);
$this->assertNull($result['params']);
@ -129,16 +98,14 @@ class FroxlorRpcTest extends TestCase
{
$key = $this->generateKey();
$request = array(
'body' => [
'command' => 'Froxlor.listFunctions',
'params' => $key
]
'command' => 'Froxlor.listFunctions',
'params' => $key
);
$json_request = json_encode($request);
$decoded_request = json_decode($json_request, true);
$decoded_request = $this->stripcslashes_deep($decoded_request);
$this->assertEquals($key['key'], $decoded_request['body']['params']['key']);
$this->assertEquals($key['cert'], $decoded_request['body']['params']['cert']);
$this->assertEquals($key['key'], $decoded_request['params']['key']);
$this->assertEquals($key['cert'], $decoded_request['params']['cert']);
}
private function stripcslashes_deep($value)