Compare commits

..

75 Commits

Author SHA1 Message Date
Michael Kaufmann
cdf02ceab6 set version to 0.10.7 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-22 16:14:13 +01:00
Michael Kaufmann
d24056c925 fix vhost-merging of specialsettings in nginx; fixes #757
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-22 16:12:11 +01:00
Michael Kaufmann
d2852fbd5d add new setting to set default value of domain-edit-setting 'Apply specialsettings to all subdomains' and 'Apply php-config to all subdomains'
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-22 16:10:27 +01:00
Michael Kaufmann
d76ebc7c06 fix sort-ordering parameter for pagination
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-20 13:08:36 +01:00
Michael Kaufmann
4fbaacb159 fix domain listing for admin-domains
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-20 12:20:20 +01:00
Michael Kaufmann
2d43a8714d let's try to fix the mysql-user-create/update issue, fingers crossed; refs #758
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-20 11:06:21 +01:00
Michael Kaufmann
620a22bf3e fix listing of subdomains for customers, fixes #759
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-20 09:33:28 +01:00
Michael Kaufmann
5e01018f30 fix typo in SysLog.delete(), thx to Wolfgang
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-18 14:47:56 +01:00
Michael Kaufmann
c84732a0cd fix issue when adding new database users with already-hashed passwords, refs #758
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-18 10:48:31 +01:00
Michael Kaufmann
dfce1fea3c re-add \Froxlor\UI\Paging as it's still required for api_keys.php because they are not (yet) listable via API
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-17 15:20:46 +01:00
Michael Kaufmann
e6dad6c6d0 Use authentication_string for mysql-5.7 and mysql-8 (not password-field) - let's see what happens
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-17 14:29:37 +01:00
Michael Kaufmann
605d2340d1 first unittest for mysql-users and their password, refs #758
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-17 13:42:35 +01:00
Michael Kaufmann
d5df4dd7a4 set version to 0.10.6 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-15 16:43:36 +01:00
Michael Kaufmann
57497bd03f if no ssl IP/port is selected when editing a domain within the webinterface, set the remove_ssl_ipandport parameter to true to not fallback to defaults
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-15 16:36:14 +01:00
Michael Kaufmann
1a3cc52188 fix parameters defaults for Domains.update() and add new parameter 'remove_ssl_ipandport' to clear ssl ip/port instead of defaulting to the current set value; fixes #756
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-15 15:11:24 +01:00
Michael Kaufmann
21f6874a61 check whether there actually is quota read for a user if newly created, thx again to J-BBB
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-15 12:58:28 +01:00
Michael Kaufmann
b34e66dfd6 fix install-dir replacement in configfiles, thx to J-BBB
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-15 08:02:46 +01:00
Michael Kaufmann
a77f890462 Merge branch 'master' of github.com:Froxlor/Froxlor 2019-11-15 07:20:38 +01:00
Michael Kaufmann
3cc5352c01 implement EmailForwarders.listing(); fixes #754
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-15 07:20:16 +01:00
Michael Kaufmann
d01d470119 Merge pull request #755 from danielrona/patch-1
enabled autofocus for 2fa_code
2019-11-14 12:58:18 +01:00
Daniel
a97ce74cc8 enabled autofocus for 2fa_code 2019-11-14 12:31:29 +01:00
Michael Kaufmann
fe7bfcc7c2 fix update of hosting plans via interface; fixes #753
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-13 15:28:08 +01:00
Michael Kaufmann
cff0ac72d0 optimize varchar fields in admin/customer table; fixes #752
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-13 08:57:53 +01:00
Michael Kaufmann
e8dcb29b69 keep searching code in ssl_certificates if something was searched and no results were returned, thx to Ithariel
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-12 12:53:38 +01:00
Michael Kaufmann
2b3b68efa3 remove testing code
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-12 08:17:54 +01:00
Michael Kaufmann
d937029bf7 implement [ApiModule].listing() in frontend-module as sorting/limiting/searching is now possible via API call (partly untested)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-10 18:35:32 +01:00
Michael Kaufmann
1955b5dd32 add task to remove certificate from acme.sh when removed in froxlor; fix issue when mode of certificate generation was not reset to 'issue' and kept trying to 'renew' instead
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-10 18:34:02 +01:00
Michael Kaufmann
c2a9880616 add new Api-Module 'SysLog' to query froxlor logs; set default value for api_allowed to the value of api.enabled setting when adding new customer via frontend to behave like Customers.add() API method
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-09 11:37:45 +01:00
Michael Kaufmann
dfedc478f7 check for given customer loginname/id before anything happens in Mysqls.add/update/delete when called as admin; fixes #749
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-07 15:53:30 +01:00
Michael Kaufmann
6efe500cee validate that the admin/reseller has customers in SubDomains.listing(); return all domain fields for admins/resellers in SubDomains.listing()
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-05 11:21:49 +01:00
Michael Kaufmann
9c3549c604 lowercase domain-names in AcmeSh implementation to avoid https://github.com/Neilpang/acme.sh/issues/2556
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-04 11:39:06 +01:00
Michael Kaufmann
50755f4399 set phpunit to fixed 8.4.1 in favor of https://github.com/sebastianbergmann/phpunit/issues/3793 to not break jenkins testing for now
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-02 13:26:38 +01:00
Michael Kaufmann
ef11ad8da7 fix broke count sql-queries
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-02 11:12:49 +01:00
Michael Kaufmann
1b2c186c07 introduce search, limit, offset and orderby possibilities for (almost) all API listing() functions; added listingCount() function in preparation to replace the old UI\Paging class later on
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-02 10:58:52 +01:00
Michael Kaufmann
b162324ff0 fix renew-check of let's encrypt implementation, set version to 0.10.5 for bugfix release; fixes #747
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-01 14:19:06 +01:00
Michael Kaufmann
6cd061d74c set version to 0.10.4 for upcoming maintenance release; minor code formatting + adjustments
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-01 11:16:13 +01:00
Michael Kaufmann
53b7420dc9 fix stripping of escape-sequences in api-endpoint; fixes #746
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-01 07:39:28 +01:00
Michael Kaufmann
aa85c648a3 check for renewal of certificates not only if there's a task to regenerate vhosts but everytime the letsencrypt cronjob runs (which is basically obsolete due to the integration into the tasks cron but perfect for checking renewal dates
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-31 21:37:54 +01:00
Michael Kaufmann
35e228ff09 Merge pull request #745 from pquerner/unittests/564
Add UnitTests for #679
2019-10-30 13:01:02 +01:00
Pascal
62236da496 changed method name 2019-10-30 12:50:16 +01:00
Pascal
e1cc896b6c add unit tests for Validate::is_ipv6 2019-10-30 12:39:56 +01:00
Pascal
36595baa65 Merge remote-tracking branch 'Froxlor/master' 2019-10-30 12:14:39 +01:00
Michael Kaufmann
ec3fd1d105 Create SECURITY.md 2019-10-30 11:00:08 +01:00
Michael Kaufmann
e39dcfbfe2 Update FUNDING.yml 2019-10-30 10:50:20 +01:00
Michael Kaufmann
ef6254b307 Merge pull request #679 from pquerner/#564
Allow CIDR and Netmask in mysql_host_access; fixes #564
2019-10-30 10:40:26 +01:00
Michael Kaufmann
44bf211ab5 Merge pull request #743 from kionez/fix_split_path_info
Correct fastcgi_split_path_info; fixes #744
2019-10-29 16:09:44 +01:00
kionez
b0e920104f Fix fastcgi_split_path_info as https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/ 2019-10-29 16:00:14 +01:00
kionez
299e201142 Fix fastcgi_split_path_info 2019-10-29 15:47:28 +01:00
Michael Kaufmann
46982ad2dc validate that a customer gets the default ftp account created even if the admin/reseller has no more resource for ftp accounts; fixes #741
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-29 07:52:00 +01:00
Michael Kaufmann
c0e07fd659 fix undefined variable in hosting-plans frontend, fixes #742
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-28 20:06:14 +01:00
Pascal
5c11eecbd7 remove code for checking ipv6 mapped ipv4 notation 2019-10-28 17:27:39 +01:00
Pascal
9689afc759 change method signature of \Froxlor\Validate\Validate::validate_ip2 2019-10-28 16:58:34 +01:00
Pascal
d76f4108e5 dont need $result if we're expecting an exception 2019-10-28 16:40:22 +01:00
Pascal
9c4d619840 remove inner if statement
check ipv6 when cidr>netmask flag is set
2019-10-28 16:32:52 +01:00
Pascal
7774e7606d dont check notated ips again 2019-10-28 16:29:53 +01:00
Pascal
2ed0cad27b #564:
cidr notation can only be 1 through 32
2019-10-28 16:27:54 +01:00
Pascal
686c2ae534 fix comparison 2019-10-28 16:00:43 +01:00
Pascal
faf3abe800 introduce new parameter to allow automatic convert cidr notation to netmask notation 2019-10-28 15:33:26 +01:00
Pascal
220b493a1b better readability 2019-10-28 14:16:27 +01:00
Pascal
e8d67f9711 check if ipv6 first 2019-10-28 14:07:31 +01:00
Pascal
83e932b068 switch join with implode 2019-10-28 13:26:32 +01:00
Pascal
84d1be538e block ipv6 addresses in cidr notation (mysql can't handle it) 2019-10-28 13:25:34 +01:00
Pascal
c97cdb1c0e make it more readable 2019-10-28 13:15:48 +01:00
Pascal
ffefe85fb4 Merge branch 'master' into #564 2019-10-28 12:18:55 +01:00
Pascal
27341ca490 Merge remote-tracking branch 'Froxlor/master' 2019-10-28 12:17:51 +01:00
Michael Kaufmann
822bb2bd4d fixed deletion of default-ftp-user possible via API (not through the interface though); refs #741
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-27 16:02:32 +01:00
Michael Kaufmann
88ee76e4c9 setting version to 0.10.3 for upcoming release
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-25 14:48:13 +02:00
Michael Kaufmann
90d921ebb5 preserve downward compatibility for 0.10.1 updaters regarding specialsettings for ssl-enabled domains; fixes #739
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-24 18:14:51 +02:00
Michael Kaufmann
7b162c4bd0 added tls-settings per domain for admins with change_serversettings-flag set; fixes #519
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-22 16:45:03 +02:00
Michael Kaufmann
32e2d48aed fallback to /tmp/froxlor.log if file-log is activated but no file given or not writeable; fixes #737
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-22 15:06:41 +02:00
Michael Kaufmann
1fdc524171 correct permissions
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-19 11:08:55 +02:00
Pascal
836b6f2fdb Merge remote-tracking branch 'upstream/master' 2019-05-10 02:54:33 +02:00
Pascal
f297058461 #564
fix wording
add validation for cidr syntax
add automatic transform of cidr to netmask for mysql
2019-05-04 00:39:12 +02:00
Pascal
0f4d8d76ae #564
fix wording
2019-05-03 23:31:31 +02:00
Pascal
12884c91a6 #564
fix #564 by allowing CIDR in mysql host validation. 
fix english and german field description accordingly
2019-05-03 22:32:57 +02:00
99 changed files with 3603 additions and 1147 deletions

1
.github/FUNDING.yml vendored
View File

@@ -1,3 +1,4 @@
# These are supported funding model platforms
github: d00p
custom: ['https://paypal.me/Froxlor']

14
SECURITY.md Normal file
View File

@@ -0,0 +1,14 @@
# Security Policy
## Supported Versions
Our main and active version is currently 0.10.x. It will receive maintenance and security updates periodically. The older version 0.9.x will not receive any kind of updates. Please update to [0.10.x](https://github.com/Froxlor/Froxlor/wiki/Updating-Froxlor)
| Version | Supported |
| ------- | ------------------ |
| 0.10.x | :white_check_mark: |
| 0.9.x | :x: |
## Reporting a Vulnerability
If you think you have found a vulnerability in froxlor, please send an email to [team@froxlor.org](mailto:team@froxlor.org) with as many information as possible. Also, please give us appropriate time to fix the issue and build update-packages before publishing anything into the wild.

View File

@@ -253,7 +253,23 @@ return array(
'type' => 'hiddenString',
'default' => '',
'save_method' => 'storeSettingField'
)
),
'system_apply_specialsettings_default' => array(
'label' => $lng['serversettings']['apply_specialsettings_default'],
'settinggroup' => 'system',
'varname' => 'apply_specialsettings_default',
'type' => 'bool',
'default' => true,
'save_method' => 'storeSettingField'
),
'system_apply_phpconfigs_default' => array(
'label' => $lng['serversettings']['apply_phpconfigs_default'],
'settinggroup' => 'system',
'varname' => 'apply_phpconfigs_default',
'type' => 'bool',
'default' => true,
'save_method' => 'storeSettingField'
),
)
)
)

View File

@@ -43,67 +43,71 @@ if ($page == 'admins' && $userinfo['change_serversettings'] == '1') {
'traffic_used' => $lng['customer']['traffic'] . ' (' . $lng['panel']['used'] . ')',
'deactivated' => $lng['admin']['deactivated']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_ADMINS, $fields);
try {
// get total count
$json_result = Admins::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 = Admins::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$admins = '';
$result_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_ADMINS . "` " . $paging->getSqlWhere(false) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
$numrows_admins = Database::num_rows();
$paging->setEntries($numrows_admins);
$sortcode = $paging->getHtmlSortCode($lng, true);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0;
$dec_places = Settings::Get('panel.decimal_places');
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
foreach ($result['list'] as $row) {
if ($paging->checkDisplay($i)) {
$row['traffic_used'] = round($row['traffic_used'] / (1024 * 1024), $dec_places);
$row['traffic'] = round($row['traffic'] / (1024 * 1024), $dec_places);
$row['diskspace_used'] = round($row['diskspace_used'] / 1024, $dec_places);
$row['diskspace'] = round($row['diskspace'] / 1024, $dec_places);
$row['traffic_used'] = round($row['traffic_used'] / (1024 * 1024), $dec_places);
$row['traffic'] = round($row['traffic'] / (1024 * 1024), $dec_places);
$row['diskspace_used'] = round($row['diskspace_used'] / 1024, $dec_places);
$row['diskspace'] = round($row['diskspace'] / 1024, $dec_places);
// percent-values for progressbar
// For Disk usage
if ($row['diskspace'] > 0) {
$disk_percent = round(($row['diskspace_used'] * 100) / $row['diskspace'], 0);
$disk_doublepercent = round($disk_percent * 2, 2);
} else {
$disk_percent = 0;
$disk_doublepercent = 0;
}
// For Traffic usage
if ($row['traffic'] > 0) {
$traffic_percent = round(($row['traffic_used'] * 100) / $row['traffic'], 0);
$traffic_doublepercent = round($traffic_percent * 2, 2);
} else {
$traffic_percent = 0;
$traffic_doublepercent = 0;
}
// fix progress-bars if value is >100%
if ($disk_percent > 100) {
$disk_percent = 100;
}
if ($traffic_percent > 100) {
$traffic_percent = 100;
}
$row = \Froxlor\PhpHelper::strReplaceArray('-1', 'UL', $row, 'customers domains diskspace traffic mysqls emails email_accounts email_forwarders email_quota ftps subdomains');
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
$row['custom_notes'] = ($row['custom_notes'] != '') ? nl2br($row['custom_notes']) : '';
eval("\$admins.=\"" . \Froxlor\UI\Template::getTemplate("admins/admins_admin") . "\";");
$count ++;
// percent-values for progressbar
// For Disk usage
if ($row['diskspace'] > 0) {
$disk_percent = round(($row['diskspace_used'] * 100) / $row['diskspace'], 0);
$disk_doublepercent = round($disk_percent * 2, 2);
} else {
$disk_percent = 0;
$disk_doublepercent = 0;
}
$i ++;
// For Traffic usage
if ($row['traffic'] > 0) {
$traffic_percent = round(($row['traffic_used'] * 100) / $row['traffic'], 0);
$traffic_doublepercent = round($traffic_percent * 2, 2);
} else {
$traffic_percent = 0;
$traffic_doublepercent = 0;
}
// fix progress-bars if value is >100%
if ($disk_percent > 100) {
$disk_percent = 100;
}
if ($traffic_percent > 100) {
$traffic_percent = 100;
}
$row = \Froxlor\PhpHelper::strReplaceArray('-1', 'UL', $row, 'customers domains diskspace traffic mysqls emails email_accounts email_forwarders email_quota ftps subdomains');
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
$row['custom_notes'] = ($row['custom_notes'] != '') ? nl2br($row['custom_notes']) : '';
eval("\$admins.=\"" . \Froxlor\UI\Template::getTemplate("admins/admins_admin") . "\";");
$count ++;
}
$admincount = $numrows_admins;
$admincount = $paging->getEntries();
eval("echo \"" . \Froxlor\UI\Template::getTemplate("admins/admins") . "\";");
} elseif ($action == 'su') {

View File

@@ -17,8 +17,7 @@
define('AREA', 'admin');
require './lib/init.php';
use Froxlor\Database\Database;
use Froxlor\Api\Commands\Cronjobs as Cronjobs;
use Froxlor\Api\Commands\Cronjobs;
if (isset($_POST['id'])) {
$id = intval($_POST['id']);
@@ -31,45 +30,47 @@ if ($page == 'cronjobs' || $page == 'overview') {
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'viewed admin_cronjobs');
$fields = array(
'c.module' => 'Module',
'c.lastrun' => $lng['cron']['lastrun'],
'c.interval' => $lng['cron']['interval'],
'c.isactive' => $lng['cron']['isactive']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_CRONRUNS, $fields);
try {
// get total count
$json_result = Cronjobs::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 = Cronjobs::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$crons = '';
$result_stmt = Database::prepare("SELECT `c`.* FROM `" . TABLE_PANEL_CRONRUNS . "` `c` ORDER BY `module` ASC, `cronfile` ASC");
Database::pexecute($result_stmt);
$paging->setEntries(Database::num_rows());
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0;
$cmod = '';
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
foreach ($result['list'] as $row) {
if ($cmod != $row['module']) {
$_mod = explode("/", $row['module']);
$module = ucfirst($_mod[1]);
eval("\$crons.=\"" . \Froxlor\UI\Template::getTemplate('cronjobs/cronjobs_cronjobmodule') . "\";");
$cmod = $row['module'];
}
if ($paging->checkDisplay($i)) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
$row['lastrun'] = date('d.m.Y H:i', $row['lastrun']);
$row['isactive'] = ((int) $row['isactive'] == 1) ? $lng['panel']['yes'] : $lng['panel']['no'];
$description = $lng['crondesc'][$row['desc_lng_key']];
$row['lastrun'] = date('d.m.Y H:i', $row['lastrun']);
$row['isactive'] = ((int) $row['isactive'] == 1) ? $lng['panel']['yes'] : $lng['panel']['no'];
$description = $lng['crondesc'][$row['desc_lng_key']];
eval("\$crons.=\"" . \Froxlor\UI\Template::getTemplate('cronjobs/cronjobs_cronjob') . "\";");
$count ++;
}
$i ++;
eval("\$crons.=\"" . \Froxlor\UI\Template::getTemplate('cronjobs/cronjobs_cronjob') . "\";");
$count ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate('cronjobs/cronjobs') . "\";");

View File

@@ -35,6 +35,7 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
unset($_SESSION['requestData']);
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_customers");
$fields = array(
'c.loginname' => $lng['login']['username'],
'a.loginname' => $lng['admin']['admin'],
@@ -47,112 +48,109 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
'c.traffic' => $lng['customer']['traffic'],
'c.traffic_used' => $lng['customer']['traffic'] . ' (' . $lng['panel']['used'] . ')'
);
try {
// get total count
$json_result = Customers::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 = Customers::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_CUSTOMERS, $fields);
$customers = '';
$result_stmt = Database::prepare("
SELECT `c`.*, `a`.`loginname` AS `adminname`
FROM `" . TABLE_PANEL_CUSTOMERS . "` `c`, `" . TABLE_PANEL_ADMINS . "` `a`
WHERE " . ($userinfo['customers_see_all'] ? '' : " `c`.`adminid` = :adminid AND ") . "
`c`.`adminid` = `a`.`adminid` " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
Database::pexecute($result_stmt, array(
'adminid' => $userinfo['adminid']
));
$num_rows = Database::num_rows();
$paging->setEntries($num_rows);
$sortcode = $paging->getHtmlSortCode($lng, true);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0;
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
foreach ($result['list'] as $row) {
if ($paging->checkDisplay($i)) {
$domains_stmt = Database::prepare("
SELECT COUNT(`id`) AS `domains`
FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `customerid` = :cid
AND `parentdomainid` = '0'
AND `id`<> :stdd
");
Database::pexecute($domains_stmt, array(
'cid' => $row['customerid'],
'stdd' => $row['standardsubdomain']
));
$domains = $domains_stmt->fetch(PDO::FETCH_ASSOC);
$row['domains'] = intval($domains['domains']);
$dec_places = Settings::Get('panel.decimal_places');
$domains_stmt = Database::prepare("
SELECT COUNT(`id`) AS `domains`
FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `customerid` = :cid
AND `parentdomainid` = '0'
AND `id`<> :stdd");
Database::pexecute($domains_stmt, array(
'cid' => $row['customerid'],
'stdd' => $row['standardsubdomain']
));
$domains = $domains_stmt->fetch(PDO::FETCH_ASSOC);
$row['domains'] = intval($domains['domains']);
$dec_places = Settings::Get('panel.decimal_places');
// get disk-space usages for web, mysql and mail
$usages_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DISKSPACE . "`
WHERE `customerid` = :cid
ORDER BY `stamp` DESC LIMIT 1
");
$usages = Database::pexecute_first($usages_stmt, array(
'cid' => $row['customerid']
));
// get disk-space usages for web, mysql and mail
$usages_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DISKSPACE . "` WHERE `customerid` = :cid ORDER BY `stamp` DESC LIMIT 1");
$usages = Database::pexecute_first($usages_stmt, array(
'cid' => $row['customerid']
));
if ($usages) {
$row['webspace_used'] = round($usages['webspace'] / 1024, $dec_places);
$row['mailspace_used'] = round($usages['mail'] / 1024, $dec_places);
$row['dbspace_used'] = round($usages['mysql'] / 1024, $dec_places);
} else {
$row['webspace_used'] = 0;
$row['mailspace_used'] = 0;
$row['dbspace_used'] = 0;
}
$row['traffic_used'] = round($row['traffic_used'] / (1024 * 1024), $dec_places);
$row['traffic'] = round($row['traffic'] / (1024 * 1024), $dec_places);
$row['diskspace_used'] = round($row['diskspace_used'] / 1024, $dec_places);
$row['diskspace'] = round($row['diskspace'] / 1024, $dec_places);
$last_login = ((int) $row['lastlogin_succ'] == 0) ? $lng['panel']['neverloggedin'] : date('d.m.Y', $row['lastlogin_succ']);
if ($usages)
{
$row['webspace_used'] = round($usages['webspace'] / 1024, $dec_places);
$row['mailspace_used'] = round($usages['mail'] / 1024, $dec_places);
$row['dbspace_used'] = round($usages['mysql'] / 1024, $dec_places);
} else {
$row['webspace_used'] = 0;
$row['mailspace_used'] = 0;
$row['dbspace_used'] = 0;
}
$row['traffic_used'] = round($row['traffic_used'] / (1024 * 1024), $dec_places);
$row['traffic'] = round($row['traffic'] / (1024 * 1024), $dec_places);
$row['diskspace_used'] = round($row['diskspace_used'] / 1024, $dec_places);
$row['diskspace'] = round($row['diskspace'] / 1024, $dec_places);
$last_login = ((int) $row['lastlogin_succ'] == 0) ? $lng['panel']['neverloggedin'] : date('d.m.Y', $row['lastlogin_succ']);
/**
* percent-values for progressbar
*/
// For Disk usage
if ($row['diskspace'] > 0) {
$disk_percent = round(($row['diskspace_used'] * 100) / $row['diskspace'], 0);
$disk_doublepercent = round($disk_percent * 2, 2);
} else {
$disk_percent = 0;
$disk_doublepercent = 0;
}
if ($row['traffic'] > 0) {
$traffic_percent = round(($row['traffic_used'] * 100) / $row['traffic'], 0);
$traffic_doublepercent = round($traffic_percent * 2, 2);
} else {
$traffic_percent = 0;
$traffic_doublepercent = 0;
}
$islocked = 0;
if ($row['loginfail_count'] >= Settings::Get('login.maxloginattempts') && $row['lastlogin_fail'] > (time() - Settings::Get('login.deactivatetime'))) {
$islocked = 1;
}
$row = \Froxlor\PhpHelper::strReplaceArray('-1', 'UL', $row, 'diskspace traffic mysqls emails email_accounts email_forwarders ftps subdomains');
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
// fix progress-bars if value is >100%
if ($disk_percent > 100) {
$disk_percent = 100;
}
if ($traffic_percent > 100) {
$traffic_percent = 100;
}
$row['custom_notes'] = ($row['custom_notes'] != '') ? nl2br($row['custom_notes']) : '';
eval("\$customers.=\"" . \Froxlor\UI\Template::getTemplate("customers/customers_customer") . "\";");
$count ++;
/**
* percent-values for progressbar
*/
if ($row['diskspace'] > 0) {
$disk_percent = round(($row['diskspace_used'] * 100) / $row['diskspace'], 0);
$disk_doublepercent = round($disk_percent * 2, 2);
} else {
$disk_percent = 0;
$disk_doublepercent = 0;
}
if ($row['traffic'] > 0) {
$traffic_percent = round(($row['traffic_used'] * 100) / $row['traffic'], 0);
$traffic_doublepercent = round($traffic_percent * 2, 2);
} else {
$traffic_percent = 0;
$traffic_doublepercent = 0;
}
$i ++;
$islocked = 0;
if ($row['loginfail_count'] >= Settings::Get('login.maxloginattempts') && $row['lastlogin_fail'] > (time() - Settings::Get('login.deactivatetime'))) {
$islocked = 1;
}
$row = \Froxlor\PhpHelper::strReplaceArray('-1', 'UL', $row, 'diskspace traffic mysqls emails email_accounts email_forwarders ftps subdomains');
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
// fix progress-bars if value is >100%
if ($disk_percent > 100) {
$disk_percent = 100;
}
if ($traffic_percent > 100) {
$traffic_percent = 100;
}
$row['custom_notes'] = ($row['custom_notes'] != '') ? nl2br($row['custom_notes']) : '';
eval("\$customers.=\"" . \Froxlor\UI\Template::getTemplate("customers/customers_customer") . "\";");
$count ++;
}
$customercount = $num_rows;
$customercount = $paging->getEntries();
eval("echo \"" . \Froxlor\UI\Template::getTemplate("customers/customers") . "\";");
} elseif ($action == 'su' && $id != 0) {
try {

View File

@@ -21,6 +21,7 @@ require './lib/init.php';
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Api\Commands\Customers as Customers;
use Froxlor\Api\Commands\Domains as Domains;
if (isset($_POST['id'])) {
@@ -31,14 +32,8 @@ if (isset($_POST['id'])) {
if ($page == 'domains' || $page == 'overview') {
// Let's see how many customers we have
$stmt = Database::prepare("
SELECT COUNT(`customerid`) as `countcustomers` FROM `" . TABLE_PANEL_CUSTOMERS . "` " . ($userinfo['customers_see_all'] ? '' : " WHERE `adminid` = :adminid"));
$params = array();
if ($userinfo['customers_see_all'] == '0') {
$params['adminid'] = $userinfo['adminid'];
}
$countcustomers = Database::pexecute_first($stmt, $params);
$countcustomers = (int) $countcustomers['countcustomers'];
$json_result = Customers::getLocal($userinfo)->listingCount();
$countcustomers = json_decode($json_result, true)['data'];
if ($action == '') {
@@ -51,71 +46,41 @@ if ($page == 'domains' || $page == 'overview') {
'c.loginname' => $lng['login']['username'],
'd.aliasdomain' => $lng['domains']['aliasdomain']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_DOMAINS, $fields);
$domains = "";
$result_stmt = Database::prepare("
SELECT `d`.*, `c`.`loginname`, `c`.`deactivated`, `c`.`name`, `c`.`firstname`, `c`.`company`, `c`.`standardsubdomain`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`
FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`)
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id`
WHERE `d`.`parentdomainid`='0' " . ($userinfo['customers_see_all'] ? '' : " AND `d`.`adminid` = :adminid ") . " " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
$params = array();
if ($userinfo['customers_see_all'] == '0') {
$params['adminid'] = $userinfo['adminid'];
try {
// get total count
$json_result = Domains::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 = Domains::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
Database::pexecute($result_stmt, $params);
$numrows_domains = Database::num_rows();
$paging->setEntries($numrows_domains);
$result = json_decode($json_result, true)['data'];
$domains = '';
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$domain_array = array();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
formatDomainEntry($row, $idna_convert);
if (! isset($domain_array[$row['domain']])) {
$domain_array[$row['domain']] = $row;
} else {
$domain_array[$row['domain']] = array_merge($row, $domain_array[$row['domain']]);
}
if (isset($row['aliasdomainid']) && $row['aliasdomainid'] != null && isset($row['aliasdomain']) && $row['aliasdomain'] != '') {
if (! isset($domain_array[$row['aliasdomain']])) {
$domain_array[$row['aliasdomain']] = array();
}
$domain_array[$row['aliasdomain']]['domainaliasid'] = $row['id'];
$domain_array[$row['aliasdomain']]['domainalias'] = $row['domain'];
}
}
/**
* We need ksort/krsort here to make sure idna-domains are also sorted correctly
*/
if ($paging->sortfield == 'd.domain' && $paging->sortorder == 'asc') {
ksort($domain_array);
} elseif ($paging->sortfield == 'd.domain' && $paging->sortorder == 'desc') {
krsort($domain_array);
}
$i = 0;
$count = 0;
foreach ($domain_array as $row) {
if (isset($row['domain']) && $row['domain'] != '' && $paging->checkDisplay($i)) {
$row['customername'] = \Froxlor\User::getCorrectFullUserDetails($row);
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
// display a nice list of IP's
foreach ($result['list'] as $row) {
formatDomainEntry($row, $idna_convert);
$row['customername'] = \Froxlor\User::getCorrectFullUserDetails($row);
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
// display a nice list of IP's if it's not an alias for another domain
if (isset($row['aliasdomainid']) && $row['aliasdomainid'] != null && isset($row['aliasdomain']) && $row['aliasdomain'] != '') {
$row['ipandport'] = sprintf($lng['domains']['isaliasdomainof'], $row['aliasdomain']);
} else {
$row['ipandport'] = str_replace("\n", "<br />", $row['ipandport']);
eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_domain") . "\";");
$count ++;
}
$i ++;
eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_domain") . "\";");
$count++;
}
$domainscount = $numrows_domains;
$domainscount = $paging->getEntries();
// Display the list
eval("echo \"" . \Froxlor\UI\Template::getTemplate("domains/domains") . "\";");
@@ -416,6 +381,10 @@ if ($page == 'domains' || $page == 'overview') {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
try {
// remove ssl ip/ports if set is empty
if (isset($_POST['ssl_ipandport']) && empty($_POST['ssl_ipandport'])) {
$_POST['remove_ssl_ipandport'] = true;
}
Domains::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
@@ -717,18 +686,8 @@ function formatDomainEntry(&$row, &$idna_convert)
$row['domain'] = $idna_convert->decode($row['domain']);
$row['aliasdomain'] = $idna_convert->decode($row['aliasdomain']);
$resultips_stmt = Database::prepare("
SELECT `ips`.* FROM `" . TABLE_DOMAINTOIP . "` AS `dti`, `" . TABLE_PANEL_IPSANDPORTS . "` AS `ips`
WHERE `dti`.`id_ipandports` = `ips`.`id` AND `dti`.`id_domain` = :domainid
");
Database::pexecute($resultips_stmt, array(
'domainid' => $row['id']
));
$row['ipandport'] = '';
while ($rowip = $resultips_stmt->fetch(PDO::FETCH_ASSOC)) {
foreach ($row['ipsandports'] as $rowip) {
if (filter_var($rowip['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$row['ipandport'] .= '[' . $rowip['ip'] . ']:' . $rowip['port'] . "\n";
} else {

View File

@@ -19,9 +19,8 @@
define('AREA', 'admin');
require './lib/init.php';
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Api\Commands\IpsAndPorts as IpsAndPorts;
use Froxlor\Api\Commands\IpsAndPorts;
if (isset($_POST['id'])) {
$id = intval($_POST['id']);
@@ -43,29 +42,33 @@ if ($page == 'ipsandports' || $page == 'overview') {
'ip' => $lng['admin']['ipsandports']['ip'],
'port' => $lng['admin']['ipsandports']['port']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_IPSANDPORTS, $fields);
try {
// get total count
$json_result = IpsAndPorts::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 = IpsAndPorts::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$ipsandports = '';
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $paging->getSqlWhere(false) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
Database::pexecute($result_stmt);
$paging->setEntries(Database::num_rows());
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0;
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if ($paging->checkDisplay($i)) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
if (filter_var($row['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$row['ip'] = '[' . $row['ip'] . ']';
}
eval("\$ipsandports.=\"" . \Froxlor\UI\Template::getTemplate("ipsandports/ipsandports_ipandport") . "\";");
$count ++;
foreach ($result['list'] as $row) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
if (filter_var($row['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$row['ip'] = '[' . $row['ip'] . ']';
}
$i ++;
eval("\$ipsandports.=\"" . \Froxlor\UI\Template::getTemplate("ipsandports/ipsandports_ipandport") . "\";");
$count ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("ipsandports/ipsandports") . "\";");
} elseif ($action == 'delete' && $id != 0) {

View File

@@ -19,7 +19,7 @@
define('AREA', 'admin');
require './lib/init.php';
use Froxlor\Database\Database;
use Froxlor\Api\Commands\SysLog;
if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
if ($action == '') {
@@ -29,20 +29,25 @@ if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
'user' => $lng['logger']['user'],
'text' => $lng['logger']['action']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_LOG, $fields, null, null, 0, 'desc', 30);
$query = 'SELECT * FROM `' . TABLE_PANEL_LOG . '` ' . $paging->getSqlWhere(false) . ' ' . $paging->getSqlOrderBy();
$result_stmt = Database::query($query . ' ' . $paging->getSqlLimit());
$result_cnt_stmt = Database::query($query);
$logs_count = $result_cnt_stmt->rowCount();
$paging->setEntries($logs_count);
try {
// get total count
$json_result = SysLog::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 = SysLog::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);
$clog = array();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
foreach ($result['list'] as $row) {
if (! isset($clog[$row['action']]) || ! is_array($clog[$row['action']])) {
$clog[$row['action']] = array();
}
@@ -55,7 +60,6 @@ if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
ksort($clog);
}
$i = 0;
$count = 0;
$log_count = 0;
$log = '';
@@ -100,23 +104,20 @@ if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
eval("\$log.=\"" . \Froxlor\UI\Template::getTemplate('logger/logger_log') . "\";");
$count ++;
$_action = $action;
// }
$i ++;
}
$i ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate('logger/logger') . "\";");
} elseif ($action == 'truncate') {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
$truncatedate = time() - (60 * 10);
$trunc_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_LOG . "` WHERE `date` < :trunc");
Database::pexecute($trunc_stmt, array(
'trunc' => $truncatedate
));
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, 'truncated the system-log (mysql)');
try {
SysLog::getLocal($userinfo, array(
'min_to_keep' => 10
))->delete();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
\Froxlor\UI\Response::redirectTo($filename, array(
'page' => $page,
's' => $s

View File

@@ -52,7 +52,7 @@ if ($page == 'overview') {
$domains = "";
$subdomains_count = count($row['subdomains']);
foreach ($row['domains'] as $configdomain) {
$domains .= $configdomain . "<br>";
$domains .= $idna_convert->decode($configdomain) . "<br>";
}
$count ++;
if ($subdomains_count == 0 && empty($domains)) {

View File

@@ -38,33 +38,31 @@ if ($page == '' || $page == 'overview') {
'adminname' => $lng['admin']['admin'],
'p.ts' => $lng['admin']['plans']['last_update']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_PLANS, $fields);
try {
// get total count
$json_result = HostingPlans::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 = HostingPlans::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$plans = '';
$result_stmt = Database::prepare("
SELECT p.*, a.loginname as adminname
FROM `" . TABLE_PANEL_PLANS . "` p, `" . TABLE_PANEL_ADMINS . "` a
WHERE " . ($userinfo['customers_see_all'] ? '' : " `p`.`adminid` = :adminid AND ") . "
`p`.`adminid` = `a`.`adminid` " . $paging->getSqlWhere(false) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
Database::pexecute($result_stmt, array(
'adminid' => $userinfo['adminid']
));
$paging->setEntries(Database::num_rows());
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0;
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if ($paging->checkDisplay($i)) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
$row['ts_format'] = date("d.m.Y H:i", $row['ts']);
eval("\$plans.=\"" . \Froxlor\UI\Template::getTemplate("plans/plans_plan") . "\";");
$count ++;
}
$i ++;
foreach ($result['list'] as $row) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
$row['ts_format'] = date("d.m.Y H:i", $row['ts']);
eval("\$plans.=\"" . \Froxlor\UI\Template::getTemplate("plans/plans_plan") . "\";");
$count ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("plans/plans") . "\";");
@@ -191,9 +189,7 @@ if ($page == '' || $page == 'overview') {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
try {
HostingPlans::getLocal($userinfo, array(
'id' => $id
))->update();
HostingPlans::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
@@ -289,6 +285,7 @@ if ($page == '' || $page == 'overview') {
$result['customernumber'] = null;
$result['custom_notes'] = null;
$result['custom_notes_show'] = null;
$result['api_allowed'] = null;
$hosting_plans = null;
$admin_select_cnt = null;
$admin_select = null;

View File

@@ -23,7 +23,7 @@ if (empty($request)) {
}
// decode json request
$decoded_request = json_decode(stripslashes($request), true);
$decoded_request = json_decode($request, true);
// is it valid?
if (is_null($decoded_request)) {
@@ -32,6 +32,7 @@ if (is_null($decoded_request)) {
// validate content
try {
$decoded_request = stripcslashes_deep($decoded_request);
$request = \Froxlor\Api\FroxlorRPC::validateRequest($decoded_request);
// now actually do it
$cls = "\\Froxlor\\Api\\Commands\\" . $request['command']['class'];
@@ -72,3 +73,8 @@ function json_response($status, $status_message = '', $data = null)
echo $json_response;
exit();
}
function stripcslashes_deep($value)
{
return is_array($value) ? array_map('stripcslashes_deep', $value) : stripcslashes($value);
}

View File

@@ -49,7 +49,7 @@
"algo26-matthias/idna-convert": "^2.1"
},
"require-dev": {
"phpunit/phpunit": "^8",
"phpunit/phpunit": "8.4.1",
"php": ">=7.3",
"ext-pcntl": "*",
"phpcompatibility/php-compatibility": "*",

87
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "77819131afd1abe70f1ea6caad9fc3e5",
"content-hash": "5699c65bbdcd2a61a9ced0ac7be84d64",
"packages": [
{
"name": "algo26-matthias/idna-convert",
@@ -200,16 +200,16 @@
},
{
"name": "psr/log",
"version": "1.1.0",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
"url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801",
"shasum": ""
},
"require": {
@@ -218,7 +218,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
"dev-master": "1.1.x-dev"
}
},
"autoload": {
@@ -243,7 +243,7 @@
"psr",
"psr-3"
],
"time": "2018-11-20T15:27:04+00:00"
"time": "2019-11-01T11:05:21+00:00"
},
{
"name": "robthree/twofactorauth",
@@ -404,16 +404,16 @@
},
{
"name": "nikic/php-parser",
"version": "v4.2.4",
"version": "v4.2.5",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4"
"reference": "b76bbc3c51f22c570648de48e8c2d941ed5e2cf2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/97e59c7a16464196a8b9c77c47df68e4a39a45c4",
"reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/b76bbc3c51f22c570648de48e8c2d941ed5e2cf2",
"reference": "b76bbc3c51f22c570648de48e8c2d941ed5e2cf2",
"shasum": ""
},
"require": {
@@ -421,6 +421,7 @@
"php": ">=7.0"
},
"require-dev": {
"ircmaxell/php-yacc": "0.0.4",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0"
},
"bin": [
@@ -451,7 +452,7 @@
"parser",
"php"
],
"time": "2019-09-01T07:51:21+00:00"
"time": "2019-10-25T18:33:07+00:00"
},
{
"name": "pdepend/pdepend",
@@ -597,16 +598,16 @@
},
{
"name": "phpcompatibility/php-compatibility",
"version": "9.3.1",
"version": "9.3.2",
"source": {
"type": "git",
"url": "https://github.com/PHPCompatibility/PHPCompatibility.git",
"reference": "9999344e47e7af6b00e1a898eacc4e4368fb7196"
"reference": "bfca2be3992f40e92206e5a7ebe5eaee37280b58"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9999344e47e7af6b00e1a898eacc4e4368fb7196",
"reference": "9999344e47e7af6b00e1a898eacc4e4368fb7196",
"url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/bfca2be3992f40e92206e5a7ebe5eaee37280b58",
"reference": "bfca2be3992f40e92206e5a7ebe5eaee37280b58",
"shasum": ""
},
"require": {
@@ -651,7 +652,7 @@
"phpcs",
"standards"
],
"time": "2019-09-05T18:36:49+00:00"
"time": "2019-10-16T21:24:24+00:00"
},
{
"name": "phpdocumentor/reflection-common",
@@ -2074,16 +2075,16 @@
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.5.0",
"version": "3.5.2",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "0afebf16a2e7f1e434920fa976253576151effe9"
"reference": "65b12cdeaaa6cd276d4c3033a95b9b88b12701e7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/0afebf16a2e7f1e434920fa976253576151effe9",
"reference": "0afebf16a2e7f1e434920fa976253576151effe9",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/65b12cdeaaa6cd276d4c3033a95b9b88b12701e7",
"reference": "65b12cdeaaa6cd276d4c3033a95b9b88b12701e7",
"shasum": ""
},
"require": {
@@ -2121,20 +2122,20 @@
"phpcs",
"standards"
],
"time": "2019-09-26T23:12:26+00:00"
"time": "2019-10-28T04:36:32+00:00"
},
{
"name": "symfony/config",
"version": "v4.3.5",
"version": "v4.3.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "0acb26407a9e1a64a275142f0ae5e36436342720"
"reference": "f4ee0ebb91b16ca1ac105aa39f9284f3cac19a15"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/0acb26407a9e1a64a275142f0ae5e36436342720",
"reference": "0acb26407a9e1a64a275142f0ae5e36436342720",
"url": "https://api.github.com/repos/symfony/config/zipball/f4ee0ebb91b16ca1ac105aa39f9284f3cac19a15",
"reference": "f4ee0ebb91b16ca1ac105aa39f9284f3cac19a15",
"shasum": ""
},
"require": {
@@ -2185,20 +2186,20 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
"time": "2019-09-19T15:51:53+00:00"
"time": "2019-10-30T13:18:51+00:00"
},
{
"name": "symfony/console",
"version": "v4.3.5",
"version": "v4.3.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "929ddf360d401b958f611d44e726094ab46a7369"
"reference": "136c4bd62ea871d00843d1bc0316de4c4a84bb78"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/929ddf360d401b958f611d44e726094ab46a7369",
"reference": "929ddf360d401b958f611d44e726094ab46a7369",
"url": "https://api.github.com/repos/symfony/console/zipball/136c4bd62ea871d00843d1bc0316de4c4a84bb78",
"reference": "136c4bd62ea871d00843d1bc0316de4c4a84bb78",
"shasum": ""
},
"require": {
@@ -2260,20 +2261,20 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2019-10-07T12:36:49+00:00"
"time": "2019-10-30T12:58:49+00:00"
},
{
"name": "symfony/dependency-injection",
"version": "v4.3.5",
"version": "v4.3.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
"reference": "e1e0762a814b957a1092bff75a550db49724d05b"
"reference": "fc036941dfafa037a7485714b62593c7eaf68edd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e1e0762a814b957a1092bff75a550db49724d05b",
"reference": "e1e0762a814b957a1092bff75a550db49724d05b",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/fc036941dfafa037a7485714b62593c7eaf68edd",
"reference": "fc036941dfafa037a7485714b62593c7eaf68edd",
"shasum": ""
},
"require": {
@@ -2333,11 +2334,11 @@
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
"time": "2019-10-02T12:58:58+00:00"
"time": "2019-10-28T17:07:32+00:00"
},
{
"name": "symfony/filesystem",
"version": "v4.3.5",
"version": "v4.3.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
@@ -2387,16 +2388,16 @@
},
{
"name": "symfony/finder",
"version": "v4.3.5",
"version": "v4.3.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "5e575faa95548d0586f6bedaeabec259714e44d1"
"reference": "72a068f77e317ae77c0a0495236ad292cfb5ce6f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/5e575faa95548d0586f6bedaeabec259714e44d1",
"reference": "5e575faa95548d0586f6bedaeabec259714e44d1",
"url": "https://api.github.com/repos/symfony/finder/zipball/72a068f77e317ae77c0a0495236ad292cfb5ce6f",
"reference": "72a068f77e317ae77c0a0495236ad292cfb5ce6f",
"shasum": ""
},
"require": {
@@ -2432,7 +2433,7 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2019-09-16T11:29:48+00:00"
"time": "2019-10-30T12:53:54+00:00"
},
{
"name": "symfony/polyfill-ctype",

View File

@@ -44,144 +44,62 @@ if ($page == 'overview') {
$fields = array(
'd.domain' => $lng['domains']['domainname']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_DOMAINS, $fields);
$domains_stmt = Database::prepare("SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isbinddomain`, `d`.`isemaildomain`, `d`.`caneditdomain`, `d`.`iswildcarddomain`, `d`.`parentdomainid`, `d`.`letsencrypt`, `d`.`registration_date`, `d`.`termination_date`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias` FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id`
WHERE `d`.`customerid`= :customerid
AND `d`.`email_only`='0'
AND `d`.`id` <> :standardsubdomain " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
Database::pexecute($domains_stmt, array(
"customerid" => $userinfo['customerid'],
"standardsubdomain" => $userinfo['standardsubdomain']
));
$paging->setEntries(Database::num_rows());
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();
} 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);
$domains = '';
$parentdomains_count = 0;
$domains_count = 0;
$domains_count = $paging->getEntries();
$domain_array = array();
while ($row = $domains_stmt->fetch(PDO::FETCH_ASSOC)) {
$row['domain'] = $idna_convert->decode($row['domain']);
$row['aliasdomain'] = $idna_convert->decode($row['aliasdomain']);
$row['domainalias'] = $idna_convert->decode($row['domainalias']);
foreach ($result['list'] as $row) {
formatDomainEntry($row, $idna_convert);
if ($row['parentdomainid'] == '0' && $row['caneditdomain'] == '1') {
$parentdomains_count ++;
}
$domain_array[$row['parentdomainname']][] = $row;
}
/**
* check for set ssl-certs to show different state-icons
*/
// nothing (ssl_global)
$row['domain_hascert'] = 0;
$ssl_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :domainid");
Database::pexecute($ssl_stmt, array(
"domainid" => $row['id']
));
$ssl_result = $ssl_stmt->fetch(PDO::FETCH_ASSOC);
if (is_array($ssl_result) && isset($ssl_result['ssl_cert_file']) && $ssl_result['ssl_cert_file'] != '') {
// own certificate (ssl_customer_green)
$row['domain_hascert'] = 1;
foreach ($domain_array as $parentdomain => $sdomains) {
// PARENTDOMAIN
if (Settings::Get('system.awstats_enabled') == '1') {
$statsapp = 'awstats';
} else {
// check if it's parent has one set (shared)
if ($row['parentdomainid'] != 0) {
$ssl_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :domainid");
Database::pexecute($ssl_stmt, array(
"domainid" => $row['parentdomainid']
));
$ssl_result = $ssl_stmt->fetch(PDO::FETCH_ASSOC);
if (is_array($ssl_result) && isset($ssl_result['ssl_cert_file']) && $ssl_result['ssl_cert_file'] != '') {
// parent has a certificate (ssl_shared)
$row['domain_hascert'] = 2;
}
}
$statsapp = 'webalizer';
}
$row = [
'domain' => $idna_convert->decode($parentdomain)
];
eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_delimiter") . "\";");
$row['termination_date'] = str_replace("0000-00-00", "", $row['termination_date']);
if ($row['termination_date'] != "") {
$cdate = strtotime($row['termination_date'] . " 23:59:59");
$today = time();
foreach ($sdomains as $domain) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($domain);
if ($cdate < $today) {
$row['termination_css'] = 'domain-expired';
} else {
$row['termination_css'] = 'domain-canceled';
// 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") . "\";");
}
$domains_count ++;
$domain_array[$row['domain']] = $row;
}
ksort($domain_array);
$domain_id_array = array();
foreach ($domain_array as $sortkey => $row) {
$domain_id_array[$row['id']] = $sortkey;
}
$domain_sort_array = array();
foreach ($domain_array as $sortkey => $row) {
if ($row['parentdomainid'] == 0) {
$domain_sort_array[$sortkey][$sortkey] = $row;
} else {
// when searching and the results are subdomains only, we need to get
// the parent domain to this subdomain
if (! isset($domain_id_array[$row['parentdomainid']])) {
$domain_id_array[$row['parentdomainid']] = "[parent-domain]";
}
$domain_sort_array[$domain_id_array[$row['parentdomainid']]][$sortkey] = $row;
}
}
$domain_array = array();
if ($paging->sortfield == 'd.domain' && $paging->sortorder == 'asc') {
ksort($domain_sort_array);
} elseif ($paging->sortfield == 'd.domain' && $paging->sortorder == 'desc') {
krsort($domain_sort_array);
}
$i = 0;
foreach ($domain_sort_array as $sortkey => $domain_array) {
if ($paging->checkDisplay($i)) {
if (isset($domain_array[$sortkey])) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($domain_array[$sortkey]);
if (Settings::Get('system.awstats_enabled') == '1') {
$statsapp = 'awstats';
} else {
$statsapp = 'webalizer';
}
eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_delimiter") . "\";");
}
if ($paging->sortfield == 'd.domain' && $paging->sortorder == 'asc') {
ksort($domain_array);
} elseif ($paging->sortfield == 'd.domain' && $paging->sortorder == 'desc') {
krsort($domain_array);
}
foreach ($domain_array as $row) {
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;
}
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_domain") . "\";");
}
}
$i += count($domain_array);
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("domains/domainlist") . "\";");
@@ -459,7 +377,9 @@ if ($page == 'overview') {
}
$alias_stmt = Database::prepare("SELECT COUNT(`id`) AS count FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain`= :aliasdomain");
$alias_check = Database::pexecute_first($alias_stmt, array("aliasdomain" => $result['id']));
$alias_check = Database::pexecute_first($alias_stmt, array(
"aliasdomain" => $result['id']
));
$alias_check = $alias_check['count'];
$domainip = $result_ipandport['ip'];
@@ -547,3 +467,53 @@ if ($page == 'overview') {
require_once __DIR__ . '/logfiles_viewer.php';
}
function formatDomainEntry(&$row, &$idna_convert)
{
$row['domain'] = $idna_convert->decode($row['domain']);
$row['aliasdomain'] = $idna_convert->decode($row['aliasdomain']);
$row['domainalias'] = $idna_convert->decode($row['domainalias']);
/**
* check for set ssl-certs to show different state-icons
*/
// nothing (ssl_global)
$row['domain_hascert'] = 0;
$ssl_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :domainid");
Database::pexecute($ssl_stmt, array(
"domainid" => $row['id']
));
$ssl_result = $ssl_stmt->fetch(PDO::FETCH_ASSOC);
if (is_array($ssl_result) && isset($ssl_result['ssl_cert_file']) && $ssl_result['ssl_cert_file'] != '') {
// own certificate (ssl_customer_green)
$row['domain_hascert'] = 1;
} else {
// check if it's parent has one set (shared)
if ($row['parentdomainid'] != 0) {
$ssl_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :domainid");
Database::pexecute($ssl_stmt, array(
"domainid" => $row['parentdomainid']
));
$ssl_result = $ssl_stmt->fetch(PDO::FETCH_ASSOC);
if (is_array($ssl_result) && isset($ssl_result['ssl_cert_file']) && $ssl_result['ssl_cert_file'] != '') {
// parent has a certificate (ssl_shared)
$row['domain_hascert'] = 2;
}
}
}
$row['termination_date'] = str_replace("0000-00-00", "", $row['termination_date']);
$row['termination_css'] = "";
if ($row['termination_date'] != "") {
$cdate = strtotime($row['termination_date'] . " 23:59:59");
$today = time();
if ($cdate < $today) {
$row['termination_css'] = 'domain-expired';
} else {
$row['termination_css'] = 'domain-canceled';
}
}
}

View File

@@ -19,6 +19,7 @@
define('AREA', 'customer');
require './lib/init.php';
use Froxlor\Api\Commands\SubDomains;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Api\Commands\Emails as Emails;
@@ -47,23 +48,27 @@ if ($page == 'overview') {
'm.email_full' => $lng['emails']['emailaddress'],
'm.destination' => $lng['emails']['forwarders']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_MAIL_VIRTUAL, $fields);
$result_stmt = Database::prepare('SELECT `m`.`id`, `m`.`domainid`, `m`.`email`, `m`.`email_full`, `m`.`iscatchall`, `u`.`quota`, `m`.`destination`, `m`.`popaccountid`, `d`.`domain`, `u`.`mboxsize` FROM `' . TABLE_MAIL_VIRTUAL . '` `m`
LEFT JOIN `' . TABLE_PANEL_DOMAINS . '` `d` ON (`m`.`domainid` = `d`.`id`)
LEFT JOIN `' . TABLE_MAIL_USERS . '` `u` ON (`m`.`popaccountid` = `u`.`id`)
WHERE `m`.`customerid`= :customerid ' . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
Database::pexecute($result_stmt, array(
"customerid" => $userinfo['customerid']
));
$emailscount = Database::num_rows();
$paging->setEntries($emailscount);
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();
} 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();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
foreach ($result['list'] as $row) {
if (! isset($emails[$row['domain']]) || ! is_array($emails[$row['domain']])) {
$emails[$row['domain']] = array();
}
@@ -77,7 +82,6 @@ if ($page == 'overview') {
ksort($emails);
}
$i = 0;
$count = 0;
$accounts = '';
$emails_count = 0;
@@ -90,53 +94,51 @@ if ($page == 'overview') {
}
foreach ($emailaddresses as $row) {
if ($paging->checkDisplay($i)) {
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 ++;
if ($domainname != $idna_convert->decode($row['domain'])) {
$domainname = $idna_convert->decode($row['domain']);
eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate("email/emails_domain") . "\";");
}
$i ++;
$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 ++;
}
}
$emaildomains_count_stmt = Database::prepare("SELECT COUNT(`id`) AS `count` FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `customerid`= :customerid
AND `isemaildomain`='1' ORDER BY `domain` ASC");
Database::pexecute($emaildomains_count_stmt, array(
"customerid" => $userinfo['customerid']
));
$emaildomains_count = $emaildomains_count_stmt->fetch(PDO::FETCH_ASSOC);
$emaildomains_count = $emaildomains_count['count'];
$json_result = SubDomains::getLocal($userinfo, [
'sql_search' => [
'd.isemaildomain' => [
'value' => 1,
'op' => '='
]
]
])->listing();
$result = json_decode($json_result, true)['data'];
$emaildomains_count = $result['count'];
eval("echo \"" . \Froxlor\UI\Template::getTemplate("email/emails") . "\";");
} elseif ($action == 'delete' && $id != 0) {

View File

@@ -19,7 +19,6 @@
define('AREA', 'customer');
require './lib/init.php';
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Api\Commands\DirOptions as DirOptions;
use Froxlor\Api\Commands\DirProtections as DirProtections;
@@ -52,33 +51,34 @@ if ($page == 'overview') {
'username' => $lng['login']['username'],
'path' => $lng['panel']['path']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_HTPASSWDS, $fields);
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `customerid`= :customerid " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
Database::pexecute($result_stmt, array(
"customerid" => $userinfo['customerid']
));
$paging->setEntries(Database::num_rows());
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();
} 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);
$i = 0;
$count = 0;
$htpasswds = '';
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if ($paging->checkDisplay($i)) {
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 ++;
foreach ($result['list'] as $row) {
if (strpos($row['path'], $userinfo['documentroot']) === 0) {
$row['path'] = str_replace($userinfo['documentroot'], "/", $row['path']);
}
$i ++;
$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") . "\";");
@@ -192,39 +192,40 @@ if ($page == 'overview') {
'error500path' => $lng['extras']['error500path'],
'options_cgi' => $lng['extras']['execute_perl']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_HTACCESS, $fields);
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `customerid`= :customerid " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
Database::pexecute($result_stmt, array(
"customerid" => $userinfo['customerid']
));
$paging->setEntries(Database::num_rows());
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);
$i = 0;
$count = 0;
$htaccess = '';
$cperlenabled = \Froxlor\Customer\Customer::customerHasPerlEnabled($userinfo['customerid']);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if ($paging->checkDisplay($i)) {
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 ++;
foreach ($result['list'] as $row) {
if (strpos($row['path'], $userinfo['documentroot']) === 0) {
$row['path'] = str_replace($userinfo['documentroot'], "/", $row['path']);
}
$i ++;
$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 ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("extras/htaccess") . "\";");

View File

@@ -46,39 +46,36 @@ if ($page == 'overview') {
'homedir' => $lng['panel']['path'],
'description' => $lng['panel']['ftpdesc']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_FTP_USERS, $fields);
$result_stmt = Database::prepare("SELECT `id`, `username`, `description`, `homedir`, `shell` FROM `" . TABLE_FTP_USERS . "`
WHERE `customerid`= :customerid " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
Database::pexecute($result_stmt, array(
"customerid" => $userinfo['customerid']
));
$ftps_count = Database::num_rows();
$paging->setEntries($ftps_count);
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();
} 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);
$i = 0;
$count = 0;
$accounts = '';
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if ($paging->checkDisplay($i)) {
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 ++;
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'];
}
$i ++;
$row['documentroot'] = \Froxlor\FileDir::makeCorrectDir($row['documentroot']);
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate('ftp/accounts_account') . "\";");
$count ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate('ftp/accounts') . "\";");

View File

@@ -19,6 +19,7 @@
define('AREA', 'customer');
require './lib/init.php';
use Froxlor\Api\Commands\SysLog;
use Froxlor\Database\Database;
use Froxlor\Settings;
@@ -35,26 +36,25 @@ if ($page == 'log') {
'user' => $lng['logger']['user'],
'text' => $lng['logger']['action']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_LOG, $fields, null, null, 0, 'desc', 30);
$query = 'SELECT * FROM `' . TABLE_PANEL_LOG . '` WHERE `user` = :loginname ' . $paging->getSqlWhere(true) . ' ' . $paging->getSqlOrderBy();
$result_stmt = Database::prepare($query . ' ' . $paging->getSqlLimit());
Database::pexecute($result_stmt, array(
"loginname" => $userinfo['loginname']
));
$result_cnt_stmt = Database::prepare($query);
Database::pexecute($result_cnt_stmt, array(
"loginname" => $userinfo['loginname']
));
$res_cnt = $result_cnt_stmt->fetch(PDO::FETCH_ASSOC);
$logs_count = $result_cnt_stmt->rowCount();
$paging->setEntries($logs_count);
try {
// get total count
$json_result = SysLog::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 = SysLog::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);
$clog = array();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
foreach ($result['list'] as $row) {
if (! isset($clog[$row['action']]) || ! is_array($clog[$row['action']])) {
$clog[$row['action']] = array();
@@ -68,7 +68,6 @@ if ($page == 'log') {
ksort($clog);
}
$i = 0;
$count = 0;
$log_count = 0;
$log = '';
@@ -113,10 +112,7 @@ if ($page == 'log') {
eval("\$log.=\"" . \Froxlor\UI\Template::getTemplate('logger/logger_log') . "\";");
$count ++;
$_action = $action;
// }
$i ++;
}
$i ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate('logger/logger') . "\";");

View File

@@ -53,20 +53,24 @@ if ($page == 'overview') {
'databasename' => $lng['mysql']['databasename'],
'description' => $lng['mysql']['databasedescription']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_DATABASES, $fields);
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DATABASES . "`
WHERE `customerid`= :customerid " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
Database::pexecute($result_stmt, array(
"customerid" => $userinfo['customerid']
));
$mysqls_count = Database::num_rows();
$paging->setEntries($mysqls_count);
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);
$i = 0;
$count = 0;
$mysqls = '';
@@ -76,21 +80,18 @@ if ($page == 'overview') {
// Begin root-session
Database::needRoot(true);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if ($paging->checkDisplay($i)) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
$mbdata_stmt = Database::prepare("SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES
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");
Database::pexecute($mbdata_stmt, array(
"table_schema" => $row['databasename']
));
$mbdata = $mbdata_stmt->fetch(PDO::FETCH_ASSOC);
$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 ++;
}
$i ++;
Database::pexecute($mbdata_stmt, array(
"table_schema" => $row['databasename']
));
$mbdata = $mbdata_stmt->fetch(PDO::FETCH_ASSOC);
$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 ++;
}
Database::needRoot(false);
// End root-session

View File

@@ -37,11 +37,16 @@ $ttl = isset($_POST['record']['ttl']) ? (int) $_POST['record']['ttl'] : 18000;
$domain = \Froxlor\Dns\Dns::getAllowedDomainEntry($domain_id, AREA, $userinfo);
// select all entries
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE domain_id = :did");
Database::pexecute($sel_stmt, array(
'did' => $domain_id
));
$dom_entries = $sel_stmt->fetchAll(PDO::FETCH_ASSOC);
try {
// get list
$json_result = DomainZones::getLocal($userinfo, [
'id' => $domain_id
])->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$dom_entries = $result['list'];
$errors = "";
$success_message = "";
@@ -117,7 +122,7 @@ $type_select_values = array(
'RP',
'SRV',
'SSHFP',
'TXT',
'TXT'
);
asort($type_select_values);
foreach ($type_select_values as $_type) {

View File

@@ -94,7 +94,7 @@ CREATE TABLE `panel_admins` (
`password` varchar(255) NOT NULL default '',
`name` varchar(255) NOT NULL default '',
`email` varchar(255) NOT NULL default '',
`def_language` varchar(255) NOT NULL default '',
`def_language` varchar(100) NOT NULL default '',
`ip` varchar(500) NOT NULL default '-1',
`customers` int(15) NOT NULL default '0',
`customers_used` int(15) NOT NULL default '0',
@@ -127,11 +127,11 @@ CREATE TABLE `panel_admins` (
`lastlogin_fail` int(11) unsigned NOT NULL default '0',
`loginfail_count` int(11) unsigned NOT NULL default '0',
`reportsent` tinyint(4) unsigned NOT NULL default '0',
`theme` varchar(255) NOT NULL default 'Sparkle',
`theme` varchar(50) NOT NULL default 'Sparkle',
`custom_notes` text,
`custom_notes_show` tinyint(1) NOT NULL default '0',
`type_2fa` tinyint(1) NOT NULL default '0',
`data_2fa` varchar(500) NOT NULL default '',
`data_2fa` varchar(25) NOT NULL default '',
`api_allowed` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`adminid`),
UNIQUE KEY `loginname` (`loginname`)
@@ -150,13 +150,13 @@ CREATE TABLE `panel_customers` (
`gender` int(1) NOT NULL DEFAULT '0',
`company` varchar(255) NOT NULL default '',
`street` varchar(255) NOT NULL default '',
`zipcode` varchar(255) NOT NULL default '',
`zipcode` varchar(25) NOT NULL default '',
`city` varchar(255) NOT NULL default '',
`phone` varchar(255) NOT NULL default '',
`fax` varchar(255) NOT NULL default '',
`phone` varchar(50) NOT NULL default '',
`fax` varchar(50) NOT NULL default '',
`email` varchar(255) NOT NULL default '',
`customernumber` varchar(255) NOT NULL default '',
`def_language` varchar(255) NOT NULL default '',
`def_language` varchar(100) NOT NULL default '',
`diskspace` bigint(30) NOT NULL default '0',
`diskspace_used` bigint(30) NOT NULL default '0',
`mysqls` int(15) NOT NULL default '0',
@@ -190,16 +190,15 @@ CREATE TABLE `panel_customers` (
`imap` tinyint(1) NOT NULL default '1',
`perlenabled` tinyint(1) NOT NULL default '0',
`dnsenabled` tinyint(1) NOT NULL default '0',
`theme` varchar(255) NOT NULL default 'Sparkle',
`theme` varchar(50) NOT NULL default 'Sparkle',
`custom_notes` text,
`custom_notes_show` tinyint(1) NOT NULL default '0',
`lepublickey` mediumtext default NULL,
`leprivatekey` mediumtext default NULL,
`leregistered` tinyint(1) NOT NULL default '0',
`leaccount` varchar(255) default '',
`allowed_phpconfigs` varchar(500) NOT NULL default '',
`type_2fa` tinyint(1) NOT NULL default '0',
`data_2fa` varchar(500) NOT NULL default '',
`data_2fa` varchar(25) NOT NULL default '',
`api_allowed` tinyint(1) NOT NULL default '1',
`logviewenabled` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`customerid`),
@@ -268,6 +267,10 @@ CREATE TABLE `panel_domains` (
`notryfiles` tinyint(1) DEFAULT '0',
`writeaccesslog` tinyint(1) DEFAULT '1',
`writeerrorlog` tinyint(1) DEFAULT '1',
`override_tls` tinyint(1) DEFAULT '0',
`ssl_protocols` text,
`ssl_cipher_list` text,
`tlsv13_cipher_list` text,
PRIMARY KEY (`id`),
KEY `customerid` (`customerid`),
KEY `parentdomain` (`parentdomainid`),
@@ -657,6 +660,8 @@ opcache.interned_strings_buffer'),
('system', 'errorlog_level', 'warn'),
('system', 'leecc', '0'),
('system', 'froxloraliases', ''),
('system', 'apply_specialsettings_default', '1'),
('system', 'apply_phpconfigs_default', '1'),
('api', 'enabled', '0'),
('2fa', 'enabled', '1'),
('panel', 'decimal_places', '4'),
@@ -691,8 +696,8 @@ opcache.interned_strings_buffer'),
('panel', 'password_special_char', '!?<>§$%+#=@'),
('panel', 'customer_hide_options', ''),
('panel', 'is_configured', '0'),
('panel', 'version', '0.10.2'),
('panel', 'db_version', '201910120');
('panel', 'version', '0.10.7'),
('panel', 'db_version', '201911220');
DROP TABLE IF EXISTS `panel_tasks`;

View File

@@ -403,6 +403,26 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201910110')) {
lastStepStatus(0);
}
// select all domains with an ssl IP connected and specialsettings content to include these in the ssl-vhost
// to maintain former behavior
$sel_stmt = Database::prepare("
SELECT d.id FROM `" . TABLE_PANEL_DOMAINS . "` d
LEFT JOIN `" . TABLE_DOMAINTOIP . "` d2i ON d2i.id_domain = d.id
LEFT JOIN `" . TABLE_PANEL_IPSANDPORTS . "` i ON i.id = d2i.id_ipandports
WHERE d.specialsettings <> '' AND i.ssl = '1'
");
Database::pexecute($sel_stmt);
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `include_specialsettings` = '1' WHERE `id` = :id");
if ($sel_stmt->columnCount() > 0) {
showUpdateStep("Adjusting domain settings for downward compatibility");
while ($row = $sel_stmt->fetch(PDO::FETCH_ASSOC)) {
Database::pexecute($upd_stmt, [
'id' => $row['id']
]);
}
lastStepStatus(0);
}
\Froxlor\Froxlor::updateToDbVersion('201910120');
}
@@ -410,3 +430,68 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.1')) {
showUpdateStep("Updating from 0.10.1 to 0.10.2", false);
\Froxlor\Froxlor::updateToVersion('0.10.2');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201910120')) {
showUpdateStep("Adding new TLS options to domains-table");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `override_tls` tinyint(1) DEFAULT '0' AFTER `writeerrorlog`;");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `ssl_protocols` text AFTER `override_tls`;");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `ssl_cipher_list` text AFTER `ssl_protocols`;");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `tlsv13_cipher_list` text AFTER `ssl_cipher_list`;");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201910200');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.2')) {
showUpdateStep("Updating from 0.10.2 to 0.10.3", false);
\Froxlor\Froxlor::updateToVersion('0.10.3');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.3')) {
showUpdateStep("Updating from 0.10.3 to 0.10.4", false);
\Froxlor\Froxlor::updateToVersion('0.10.4');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.4')) {
showUpdateStep("Updating from 0.10.4 to 0.10.5", false);
\Froxlor\Froxlor::updateToVersion('0.10.5');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201910200')) {
showUpdateStep("Optimizing customer and admin table for size");
// ALTER TABLE `panel_customers` CHANGE `name` `name` VARCHAR(250) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '';
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `zipcode` `zipcode` varchar(25) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `phone` `phone` varchar(50) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `fax` `fax` varchar(50) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `def_language` `def_language` varchar(100) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `theme` `theme` varchar(50) NOT NULL default 'Sparkle';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `data_2fa` `data_2fa` varchar(25) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `def_language` `def_language` varchar(100) NOT 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) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` CHANGE `theme` `theme` varchar(50) NOT NULL default 'Sparkle';");
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` CHANGE `data_2fa` `data_2fa` varchar(25) NOT NULL default '';");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201911130');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.5')) {
showUpdateStep("Updating from 0.10.5 to 0.10.6", false);
\Froxlor\Froxlor::updateToVersion('0.10.6');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201911130')) {
showUpdateStep("Adding new settings for domain edit form default values");
Settings::AddNew("system.apply_specialsettings_default", '1');
Settings::AddNew("system.apply_phpconfigs_default", '1');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201911220');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.6')) {
showUpdateStep("Updating from 0.10.6 to 0.10.7", false);
\Froxlor\Froxlor::updateToVersion('0.10.7');
}

View File

@@ -232,6 +232,157 @@ abstract class ApiCommand extends ApiParameter
return $this->user_data;
}
/**
* return SQL when parameter $sql_search is given via API
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param array $query_fields
* optional array of placeholders mapped to the actual value which is used in the API commands when executing the statement [internal]
* @param boolean $append
* optional append to WHERE clause rather then create new one, default false [internal]
*
* @return string
*/
protected function getSearchWhere(&$query_fields = array(), $append = false)
{
$search = $this->getParam('sql_search', true, array());
$condition = '';
if (! empty($search)) {
if ($append == true) {
$condition = ' AND ';
} else {
$condition = ' WHERE ';
}
$ops = array(
'<',
'>',
'='
);
$first = true;
foreach ($search as $field => $valoper) {
$cleanfield = str_replace(".", "", $field);
$sortfield = explode('.', $field);
foreach ($sortfield as $id => $sfield) {
if (substr($sfield, - 1, 1) != '`') {
$sfield .= '`';
}
if ($sfield[0] != '`') {
$sfield = '`' . $sfield;
}
$sortfield[$id] = $sfield;
}
$field = implode('.', $sortfield);
if (! $first) {
$condition .= ' AND ';
}
if (! is_array($valoper) || ! isset($valoper['op']) || empty($valoper['op'])) {
$condition .= $field . ' LIKE :' . $cleanfield;
if (! 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'] ?? '';
} else {
continue;
}
if ($first) {
$first = false;
}
}
}
return $condition;
}
/**
* return LIMIT clause when at least $sql_limit parameter is given via API
*
* @param int $sql_limit
* optional, limit resultset, default 0
* @param int $sql_offset
* optional, offset for limitation, default 0
*
* @return string
*/
protected function getLimit()
{
$limit = $this->getParam('sql_limit', true, 0);
$offset = $this->getParam('sql_offset', true, 0);
if (! is_numeric($limit)) {
$limit = 0;
}
if (! is_numeric($offset)) {
$offset = 0;
}
if ($limit > 0) {
return ' LIMIT ' . $offset . ',' . $limit;
}
return '';
}
/**
* return ORDER BY clause if parameter $sql_orderby parameter is given via API
*
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC
* @param boolean $append
* optional append to ORDER BY clause rather then create new one, default false [internal]
*
* @return string
*/
protected function getOrderBy($append = false)
{
$orderby = $this->getParam('sql_orderby', true, array());
$order = "";
if (! empty($orderby)) {
if ($append) {
$order .= ", ";
} else {
$order .= " ORDER BY ";
}
foreach ($orderby as $field => $by) {
$sortfield = explode('.', $field);
foreach ($sortfield as $id => $sfield) {
if (substr($sfield, - 1, 1) != '`') {
$sfield .= '`';
}
if ($sfield[0] != '`') {
$sfield = '`' . $sfield;
}
$sortfield[$id] = $sfield;
}
$field = implode('.', $sortfield);
$by = strtoupper($by);
if (! in_array($by, [
'ASC',
'DESC'
])) {
$by = 'ASC';
}
if (\Froxlor\Settings::Get('panel.natsorting') == 1) {
// Acts similar to php's natsort(), found in one comment at http://my.opera.com/cpr/blog/show.dml/160556
$order .= "CONCAT( IF( ASCII( LEFT( " . $field . ", 5 ) ) > 57,
LEFT( " . $field . ", 1 ), 0 ),
IF( ASCII( RIGHT( " . $field . ", 1 ) ) > 57,
LPAD( " . $field . ", 255, '0' ),
LPAD( CONCAT( " . $field . ", '-' ), 255, '0' )
)) " . $by . ", ";
} else {
$order .= $field . " " . $by . ", ";
}
}
$order = substr($order, 0, - 2);
}
return $order;
}
/**
* return logger instance
*

View File

@@ -25,6 +25,15 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
/**
* lists all admin entries
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin
* @throws \Exception
* @return string json-encoded array count|list
@@ -33,12 +42,11 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list admins");
$query_fields = array();
$result_stmt = Database::prepare("
SELECT *
FROM `" . TABLE_PANEL_ADMINS . "`
ORDER BY `loginname` ASC
");
Database::pexecute($result_stmt, null, true, true);
FROM `" . TABLE_PANEL_ADMINS . "`" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
Database::pexecute($result_stmt, $query_fields, true, true);
$result = array();
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
@@ -51,6 +59,28 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* returns the total number of admins for the given admin
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_admins
FROM `" . TABLE_PANEL_ADMINS . "`
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_admins']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* return an admin entry by either id or loginname
*

View File

@@ -75,7 +75,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
throw $e;
}
}
if (!$has_cert) {
if (! $has_cert) {
$this->addOrUpdateCertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, true);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added ssl-certificate for '" . $domain['domain'] . "'");
$result = $this->apiCall('Certificates.get', array(
@@ -174,6 +174,15 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
/**
* lists all certificate entries
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
@@ -188,7 +197,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
WHERE ";
$qry_params = array();
$query_fields = array();
if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '0') {
// admin with only customer-specific permissions
$certs_stmt_query .= "d.adminid = :adminid ";
@@ -200,7 +209,8 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
} else {
$certs_stmt_query .= "1 ";
}
$certs_stmt = Database::prepare($certs_stmt_query);
$certs_stmt = Database::prepare($certs_stmt_query . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
$qry_params = array_merge($qry_params, $query_fields);
Database::pexecute($certs_stmt, $qry_params, true, true);
$result = array();
while ($cert = $certs_stmt->fetch(\PDO::FETCH_ASSOC)) {
@@ -218,6 +228,40 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
));
}
/**
* returns the total number of certificates for the given user
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
// select all my (accessable) certificates
$certs_stmt_query = "SELECT COUNT(*) as num_certs
FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON `d`.`id` = `s`.`domainid`
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` c ON `c`.`customerid` = `d`.`customerid`
WHERE ";
$qry_params = array();
if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '0') {
// admin with only customer-specific permissions
$certs_stmt_query .= "d.adminid = :adminid ";
$qry_params['adminid'] = $this->getUserDetail('adminid');
} elseif ($this->isAdmin() == false) {
// customer-area
$certs_stmt_query .= "d.customerid = :cid ";
$qry_params['cid'] = $this->getUserDetail('customerid');
} else {
$certs_stmt_query .= "1 ";
}
$certs_stmt = Database::prepare($certs_stmt_query);
$result = Database::pexecute_first($certs_stmt, $qry_params, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_certs']);
}
}
/**
* delete certificates entry by id
*
@@ -232,7 +276,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
if ($this->isAdmin() == false) {
$chk_stmt = Database::prepare("
SELECT d.domain FROM `" . TABLE_PANEL_DOMAINS . "` d
SELECT d.domain, d.letsencrypt FROM `" . TABLE_PANEL_DOMAINS . "` d
LEFT JOIN `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s ON s.domainid = d.id
WHERE s.`id` = :id AND d.`customerid` = :cid
");
@@ -242,7 +286,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
));
} elseif ($this->isAdmin()) {
$chk_stmt = Database::prepare("
SELECT d.domain FROM `" . TABLE_PANEL_DOMAINS . "` d
SELECT d.domain, d.letsencrypt FROM `" . TABLE_PANEL_DOMAINS . "` d
LEFT JOIN `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s ON s.domainid = d.id
WHERE s.`id` = :id" . ($this->getUserDetail('customers_see_all') == '0' ? " AND d.`adminid` = :aid" : ""));
$params = array(
@@ -255,7 +299,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
if ($chk == false && $this->getUserDetail('change_serversettings')) {
// check whether it might be the froxlor-vhost certificate
$chk_stmt = Database::prepare("
SELECT \"" . Settings::Get('system.hostname') . "\" as domain FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
SELECT \"" . Settings::Get('system.hostname') . "\" as domain, \"" . Settings::Get('system.le_froxlor_enabled') . "\" as letsencrypt FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
WHERE `id` = :id AND `domainid` = '0'");
$params = array(
'id' => $id
@@ -277,13 +321,16 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
Database::pexecute($del_stmt, array(
'id' => $id
));
// trigger removing of certificate from acme.sh if let's encrypt
if ($chk['letsencrypt'] == '1') {
\Froxlor\System\Cronjob::inserttask('12', $chk['domain']);
}
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] removed ssl-certificate for '" . $chk['domain'] . "'");
return $this->response(200, "successfull", $result);
}
throw new \Exception("Unable to determine SSL certificate. Maybe no access?", 406);
}
/**
* insert or update certificates entry
*

View File

@@ -127,6 +127,15 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE
/**
* lists all cronjob entries
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin
* @throws \Exception
* @return string json-encoded array count|list
@@ -135,10 +144,10 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE
{
if ($this->isAdmin()) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list cronjobs");
$query_fields = array();
$result_stmt = Database::prepare("
SELECT `c`.* FROM `" . TABLE_PANEL_CRONRUNS . "` `c` ORDER BY `module` ASC, `cronfile` ASC
");
Database::pexecute($result_stmt);
SELECT `c`.* FROM `" . TABLE_PANEL_CRONRUNS . "` `c` " . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
Database::pexecute($result_stmt, $query_fields, true, true);
$result = array();
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
@@ -151,6 +160,27 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* returns the total number of cronjobs
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin()) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_crons FROM `" . TABLE_PANEL_CRONRUNS . "` `c`
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_crons']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* You cannot delete system cronjobs.
*/

View File

@@ -137,7 +137,15 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
* optional, admin-only, select backup-jobs of a specific customer by id
* @param string $loginname
* optional, admin-only, select backup-jobs of a specific customer by loginname
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
@@ -149,8 +157,9 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
$customer_ids = $this->getAllowedCustomerIds('extras.backup');
// check whether there is a backup-job for this customer
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'");
Database::pexecute($sel_stmt);
$query_fields = array();
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
Database::pexecute($sel_stmt, $query_fields, true, true);
$result = array();
while ($entry = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
$entry['data'] = json_decode($entry['data'], true);
@@ -165,6 +174,37 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
));
}
/**
* returns the total number of planned backups
*
* @param int $customerid
* optional, admin-only, select backup-jobs of a specific customer by id
* @param string $loginname
* optional, admin-only, select backup-jobs of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
$this->validateAccess();
$customer_ids = $this->getAllowedCustomerIds('extras.backup');
// check whether there is a backup-job for this customer
$result_count = 0;
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'");
Database::pexecute($sel_stmt, null, true, true);
while ($entry = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
$entry['data'] = json_decode($entry['data'], true);
if (in_array($entry['data']['customerid'], $customer_ids)) {
$result_count ++;
}
}
return $this->response(200, "successfull", $result_count);
}
/**
* delete a planned backup-jobs by id, if called from an admin you need to specify the customerid/loginname
*
@@ -195,7 +235,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
if ($backupjob['id'] == $entry && in_array($backupjob['data']['customerid'], $customer_ids)) {
Database::pexecute($del_stmt, array(
'tid' => $entry
));
), true, true);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] deleted planned customer-backup #" . $entry);
return $this->response(200, "successfull", true);
}

View File

@@ -25,6 +25,15 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
/**
* lists all customer entries
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin
* @throws \Exception
* @return string json-encoded array count|list
@@ -33,19 +42,19 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
{
if ($this->isAdmin()) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list customers");
$query_fields = array();
$result_stmt = Database::prepare("
SELECT `c`.*, `a`.`loginname` AS `adminname`
FROM `" . TABLE_PANEL_CUSTOMERS . "` `c`, `" . TABLE_PANEL_ADMINS . "` `a`
WHERE " . ($this->getUserDetail('customers_see_all') ? '' : " `c`.`adminid` = :adminid AND ") . "
`c`.`adminid` = `a`.`adminid`
ORDER BY `c`.`loginname` ASC
");
`c`.`adminid` = `a`.`adminid`" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
$params = array();
if ($this->getUserDetail('customers_see_all') == '0') {
$params = array(
'adminid' => $this->getUserDetail('adminid')
);
}
$params = array_merge($params, $query_fields);
Database::pexecute($result_stmt, $params, true, true);
$result = array();
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
@@ -59,6 +68,34 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* returns the total number of customers for the given admin
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin()) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_customers
FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE " . ($this->getUserDetail('customers_see_all') ? "1" : " `adminid` = :adminid "));
$params = array();
if ($this->getUserDetail('customers_see_all') == '0') {
$params = array(
'adminid' => $this->getUserDetail('adminid')
);
}
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_customers']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* return a customer entry by either id or loginname
*

View File

@@ -285,7 +285,15 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* optional, admin-only, select directory-protections of a specific customer by id
* @param string $loginname
* optional, admin-only, select directory-protections of a specific customer by loginname
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
@@ -298,11 +306,12 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$customer_ids = $this->getAllowedCustomerIds('extras.pathoptions');
$result = array();
$query_fields = array();
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")
");
Database::pexecute($result_stmt, null, true, true);
WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()
);
Database::pexecute($result_stmt, $query_fields, true, true);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
@@ -313,6 +322,36 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
));
}
/**
* returns the total number of accessable directory options
*
* @param int $customerid
* optional, admin-only, select directory-protections of a specific customer by id
* @param string $loginname
* optional, admin-only, select directory-protections of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
*/
public function listingCount()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) {
throw new \Exception("You cannot access this resource", 405);
}
$customer_ids = $this->getAllowedCustomerIds('extras.pathoptions');
$result = array();
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_htaccess FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_htaccess']);
}
}
/**
* delete a directory-options by id
*
@@ -373,7 +412,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
Database::pexecute($stmt, array(
"customerid" => $customer_data['customerid'],
"id" => $id
));
), true, true);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted directory-option for '" . str_replace($customer_data['documentroot'], '/', $result['path']) . "'");
\Froxlor\System\Cronjob::inserttask('1');
return $this->response(200, "successfull", $result);

View File

@@ -268,7 +268,15 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
* optional, admin-only, select directory-protections of a specific customer by id
* @param string $loginname
* optional, admin-only, select directory-protections of a specific customer by loginname
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
@@ -281,11 +289,11 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
$customer_ids = $this->getAllowedCustomerIds('extras.directoryprotection');
$result = array();
$query_fields = array();
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")
");
Database::pexecute($result_stmt, null, true, true);
WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
Database::pexecute($result_stmt, $query_fields, true, true);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
@@ -296,6 +304,36 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
));
}
/**
* returns the total number of accessable directory protections
*
* @param int $customerid
* optional, admin-only, select directory-protections of a specific customer by id
* @param string $loginname
* optional, admin-only, select directory-protections of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
*/
public function listingCount()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) {
throw new \Exception("You cannot access this resource", 405);
}
$customer_ids = $this->getAllowedCustomerIds('extras.directoryprotection');
$result = array();
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_htpasswd FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_htpasswd']);
}
}
/**
* delete a directory-protection by either id or username
*

View File

@@ -379,6 +379,14 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
* optional, the domain id
* @param string $domainname
* optional, the domain name
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer
* @throws \Exception
@@ -404,11 +412,10 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
'domainname' => $domainname
));
$id = $result['id'];
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :did");
Database::pexecute($sel_stmt, array(
'did' => $id
), true, true);
$query_fields = array();
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :did" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
$query_fields['did'] = $id;
Database::pexecute($sel_stmt, $query_fields, true, true);
$result = [];
while ($row = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
@@ -419,6 +426,48 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
));
}
/**
* returns the total number of domainzone-entries for given domain
*
* @param int $id
* optional, the domain id
* @param string $domainname
* optional, the domain name
*
* @access admin, customer
* @throws \Exception
* @return bool
*/
public function listingCount()
{
if (Settings::Get('system.dnsenabled') != '1') {
throw new \Exception("DNS service not enabled on this system", 405);
}
if ($this->isAdmin() == false && $this->getUserDetail('dnsenabled') != '1') {
throw new \Exception("You cannot access this resource", 405);
}
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$domainname = $this->getParam('domainname', $dn_optional, '');
// get requested domain
$result = $this->apiCall('SubDomains.get', array(
'id' => $id,
'domainname' => $domainname
));
$id = $result['id'];
$sel_stmt = Database::prepare("SELECT COUNT(*) as num_dns FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :did");
$result = Database::pexecute_first($sel_stmt, array(
'did' => $id
), true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_dns']);
}
}
/**
* deletes a domain-dns entry by id
*

View File

@@ -25,6 +25,17 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
/**
* lists all domain entries
*
* @param bool $with_ips
* optional, default true
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin
* @throws \Exception
* @return string json-encoded array count|list
@@ -32,7 +43,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
public function listing()
{
if ($this->isAdmin()) {
$with_ips = $this->getParam('with_ips', true, true);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list domains");
$query_fields = array();
$result_stmt = Database::prepare("
SELECT
`d`.*, `c`.`loginname`, `c`.`deactivated`, `c`.`name`, `c`.`firstname`, `c`.`company`, `c`.`standardsubdomain`,
@@ -40,14 +53,19 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`)
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id`
WHERE `d`.`parentdomainid`='0' " . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid "));
WHERE `d`.`parentdomainid`='0' " . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid ") . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
$params = array();
if ($this->getUserDetail('customers_see_all') == '0') {
$params['adminid'] = $this->getUserDetail('adminid');
}
Database::pexecute($result_stmt, $params);
$params = array_merge($params, $query_fields);
Database::pexecute($result_stmt, $params, true, true);
$result = array();
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$row['ipsandports'] = array();
if ($with_ips) {
$row['ipsandports'] = $this->getIpsForDomain($row['id']);
}
$result[] = $row;
}
return $this->response(200, "successfull", array(
@@ -58,6 +76,36 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* returns the total number of accessable domains
*
* @access admin
* @throws \Exception
* @return string json-encoded array count|list
*/
public function listingCount()
{
if ($this->isAdmin()) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list domains");
$result_stmt = Database::prepare("
SELECT
COUNT(*) as num_domains
FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`)
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id`
WHERE `d`.`parentdomainid`='0' " . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid "));
$params = array();
if ($this->getUserDetail('customers_see_all') == '0') {
$params['adminid'] = $this->getUserDetail('adminid');
}
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_domains']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* return a domain entry by either id or domainname
*
@@ -65,6 +113,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, the domain-id
* @param string $domainname
* optional, the domainname
* @param bool $with_ips
* optional, default true
* @param bool $no_std_subdomain
* optional, default false
*
@@ -78,6 +128,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$domainname = $this->getParam('domainname', $dn_optional, '');
$with_ips = $this->getParam('with_ips', true, true);
$no_std_subdomain = $this->getParam('no_std_subdomain', true, false);
// convert possible idn domain to punycode
@@ -100,6 +151,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
}
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
$result['ipsandports'] = array();
if ($with_ips) {
$result['ipsandports'] = $this->getIpsForDomain($result['id']);
}
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get domain '" . $result['domain'] . "'");
return $this->response(200, "successfull", $result);
}
@@ -109,6 +164,34 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* get ips connected to given domain as array
*
* @param number $domain_id
* @return array
*/
private function getIpsForDomain($domain_id = 0)
{
$resultips_stmt = Database::prepare("
SELECT `ips`.* FROM `" . TABLE_DOMAINTOIP . "` AS `dti`, `" . TABLE_PANEL_IPSANDPORTS . "` AS `ips`
WHERE `dti`.`id_ipandports` = `ips`.`id` AND `dti`.`id_domain` = :domainid
");
Database::pexecute($resultips_stmt, array(
'domainid' => $domain_id
));
$ipandports = array();
while ($rowip = $resultips_stmt->fetch(\PDO::FETCH_ASSOC)) {
if (filter_var($rowip['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$rowip['is_ipv6'] = true;
}
$ipandports[] = $rowip;
}
return $ipandports;
}
/**
* add new domain entry
*
@@ -187,6 +270,14 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional whether or not to preload HSTS header value
* @param bool $ocsp_stapling
* optional whether to enable ocsp-stapling for this domain. default 0 (false), requires SSL
* @param bool $override_tls
* optional whether or not to override system-tls settings like protocol, ssl-ciphers and if applicable tls-1.3 ciphers, requires change_serversettings flag for the admin, default false
* @param array $ssl_protocols
* optional list of allowed/used ssl/tls protocols, see system.ssl_protocols setting, only used/required if $override_tls is true, default empty or system.ssl_protocols setting if $override_tls is true
* @param string $ssl_cipher_list
* optional list of allowed/used ssl/tls ciphers, see system.ssl_cipher_list setting, only used/required if $override_tls is true, default empty or system.ssl_cipher_list setting if $override_tls is true
* @param string $tlsv13_cipher_list
* optional list of allowed/used tls-1.3 specific ciphers, see system.tlsv13_cipher_list setting, only used/required if $override_tls is true, default empty or system.tlsv13_cipher_list setting if $override_tls is true
*
* @access admin
* @throws \Exception
@@ -239,6 +330,19 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$hsts_preload = $this->getBoolParam('hsts_preload', true, 0);
$ocsp_stapling = $this->getBoolParam('ocsp_stapling', true, 0);
$override_tls = $this->getBoolParam('override_tls', true, 0);
$p_ssl_protocols = array();
$ssl_cipher_list = "";
$tlsv13_cipher_list = "";
if ($this->getUserDetail('change_serversettings') == '1') {
if ($override_tls) {
$p_ssl_protocols = $this->getParam('ssl_protocols', true, explode(',', Settings::Get('system.ssl_protocols')));
$ssl_cipher_list = $this->getParam('ssl_cipher_list', true, Settings::Get('system.ssl_cipher_list'));
$tlsv13_cipher_list = $this->getParam('tlsv13_cipher_list', true, Settings::Get('system.tlsv13_cipher_list'));
}
}
// validation
if ($p_domain == Settings::Get('system.hostname')) {
\Froxlor\UI\Response::standard_error('admin_domain_emailsystemhostname', '', true);
@@ -325,6 +429,34 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
} else {
$documentroot = $_documentroot;
}
$ssl_protocols = array();
if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) {
$p_ssl_protocols = array(
$p_ssl_protocols
);
}
if (! empty($p_ssl_protocols) && ! is_array($p_ssl_protocols)) {
$p_ssl_protocols = json_decode($p_ssl_protocols, true);
}
if (! empty($p_ssl_protocols) && is_array($p_ssl_protocols)) {
$protocols_available = array(
'TLSv1',
'TLSv1.1',
'TLSv1.2',
'TLSv1.3'
);
foreach ($p_ssl_protocols as $ssl_protocol) {
if (! in_array(trim($ssl_protocol), $protocols_available)) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_DEBUG, "[API] unknown SSL protocol '" . trim($ssl_protocol) . "'");
continue;
}
$ssl_protocols[] = $ssl_protocol;
}
}
if (empty($ssl_protocols)) {
$override_tls = '0';
}
} else {
$isbinddomain = '0';
if (Settings::Get('system.bind_enable') == '1') {
@@ -340,6 +472,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$writeaccesslog = '1';
$writeerrorlog = '1';
$documentroot = $_documentroot;
$override_tls = '0';
$ssl_protocols = array();
}
if ($this->getUserDetail('caneditphpsettings') == '1' || $this->getUserDetail('change_serversettings') == '1') {
@@ -574,7 +708,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'hsts' => $hsts_maxage,
'hsts_sub' => $hsts_sub,
'hsts_preload' => $hsts_preload,
'ocsp_stapling' => $ocsp_stapling
'ocsp_stapling' => $ocsp_stapling,
'override_tls' => $override_tls,
'ssl_protocols' => implode(",", $ssl_protocols),
'ssl_cipher_list' => $ssl_cipher_list,
'tlsv13_cipher_list' => $tlsv13_cipher_list
);
$ins_stmt = Database::prepare("
@@ -618,7 +756,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload,
`ocsp_stapling` = :ocsp_stapling
`ocsp_stapling` = :ocsp_stapling,
`override_tls` = :override_tls,
`ssl_protocols` = :ssl_protocols,
`ssl_cipher_list` = :ssl_cipher_list,
`tlsv13_cipher_list` = :tlsv13_cipher_list
");
Database::pexecute($ins_stmt, $ins_data, true, true);
$domainid = Database::lastInsertId();
@@ -723,7 +865,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* @param bool $include_specialsettings
* optional, whether or not to include non-ssl specialsettings in the generated ssl-vhost, default false
* @param bool $specialsettingsforsubdomains
* optional, whether to apply specialsettings to all subdomains of this domain, default 0 (false)
* optional, whether to apply specialsettings to all subdomains of this domain, default is read from setting system.apply_specialsettings_default
* @param bool $notryfiles
* optional, [nginx only] do not generate the default try-files directive, default 0 (false)
* @param bool $writeaccesslog
@@ -735,7 +877,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* @param bool $phpenabled
* optional, whether php is enabled for this domain, default 0 (false)
* @param bool $phpsettingsforsubdomains
* optional, whether to apply php-setting to apply to all subdomains of this domain, default 0 (false)
* optional, whether to apply php-setting to apply to all subdomains of this domain, default is read from setting system.apply_phpconfigs_default
* @param bool $openbasedir
* optional, whether to activate openbasedir restriction for this domain, default 0 (false)
* @param int $phpsettingid
@@ -749,7 +891,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* @param bool $letsencrypt
* optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled
* @param array $ssl_ipandport
* optional, list of ssl-enabled ip/port id's to assign to this domain
* optional, list of ssl-enabled ip/port id's to assign to this domain, if left empty, the current set value is being used, to remove all ssl ips use $remove_ssl_ipandport
* @param bool $remove_ssl_ipandport
* optional, if set to true and no $ssl_ipandport value is given, the ip's get removed, otherwise, the currently set value is used, default false
* @param bool $http2
* optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default 0 (false)
* @param int $hsts_maxage
@@ -803,26 +947,47 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$specialsettings = $this->getParam('specialsettings', true, $result['specialsettings']);
$ssl_specialsettings = $this->getParam('ssl_specialsettings', true, $result['ssl_specialsettings']);
$include_specialsettings = $this->getBoolParam('include_specialsettings', true, $result['include_specialsettings']);
$ssfs = $this->getBoolParam('specialsettingsforsubdomains', true, 0);
$ssfs = $this->getBoolParam('specialsettingsforsubdomains', true, \Froxlor\Settings::Get('system.apply_specialsettings_default'));
$notryfiles = $this->getBoolParam('notryfiles', true, $result['notryfiles']);
$writeaccesslog = $this->getBoolParam('writeaccesslog', true, $result['writeaccesslog']);
$writeerrorlog = $this->getBoolParam('writeerrorlog', true, $result['writeerrorlog']);
$documentroot = $this->getParam('documentroot', true, $result['documentroot']);
$phpenabled = $this->getBoolParam('phpenabled', true, $result['phpenabled']);
$phpfs = $this->getBoolParam('phpsettingsforsubdomains', true, 0);
$phpfs = $this->getBoolParam('phpsettingsforsubdomains', true, \Froxlor\Settings::Get('system.apply_phpconfigs_default'));
$openbasedir = $this->getBoolParam('openbasedir', true, $result['openbasedir']);
$phpsettingid = $this->getParam('phpsettingid', true, $result['phpsettingid']);
$mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, $result['mod_fcgid_starter']);
$mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, $result['mod_fcgid_maxrequests']);
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, $result['ssl_redirect']);
$letsencrypt = $this->getBoolParam('letsencrypt', true, $result['letsencrypt']);
$p_ssl_ipandports = $this->getParam('ssl_ipandport', true, array());
$remove_ssl_ipandport = $this->getBoolParam('remove_ssl_ipandport', true, 0);
$p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $remove_ssl_ipandport ? array(
- 1
) : null);
$http2 = $this->getBoolParam('http2', true, $result['http2']);
$hsts_maxage = $this->getParam('hsts_maxage', true, $result['hsts']);
$hsts_sub = $this->getBoolParam('hsts_sub', true, $result['hsts_sub']);
$hsts_preload = $this->getBoolParam('hsts_preload', true, $result['hsts_preload']);
$ocsp_stapling = $this->getBoolParam('ocsp_stapling', true, $result['ocsp_stapling']);
$override_tls = $this->getBoolParam('override_tls', true, $result['override_tls']);
if ($this->getUserDetail('change_serversettings') == '1') {
if ($override_tls) {
$p_ssl_protocols = $this->getParam('ssl_protocols', true, explode(',', $result['ssl_protocols']));
$ssl_cipher_list = $this->getParam('ssl_cipher_list', true, $result['ssl_cipher_list']);
$tlsv13_cipher_list = $this->getParam('tlsv13_cipher_list', true, $result['tlsv13_cipher_list']);
} else {
$p_ssl_protocols = array();
$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'];
}
// count subdomain usage of source-domain
$subdomains_stmt = Database::prepare("
SELECT COUNT(`id`) AS count FROM `" . TABLE_PANEL_DOMAINS . "` WHERE
@@ -992,6 +1157,34 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
if (! preg_match('/^https?\:\/\//', $documentroot) && strstr($documentroot, ":") !== false) {
\Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true);
}
$ssl_protocols = array();
if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) {
$p_ssl_protocols = array(
$p_ssl_protocols
);
}
if (! empty($p_ssl_protocols) && ! is_array($p_ssl_protocols)) {
$p_ssl_protocols = json_decode($p_ssl_protocols, true);
}
if (! empty($p_ssl_protocols) && is_array($p_ssl_protocols)) {
$protocols_available = array(
'TLSv1',
'TLSv1.1',
'TLSv1.2',
'TLSv1.3'
);
foreach ($p_ssl_protocols as $ssl_protocol) {
if (! in_array(trim($ssl_protocol), $protocols_available)) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_DEBUG, "[API] unknown SSL protocol '" . trim($ssl_protocol) . "'");
continue;
}
$ssl_protocols[] = $ssl_protocol;
}
}
if (empty($ssl_protocols)) {
$override_tls = '0';
}
} else {
$isbinddomain = $result['isbinddomain'];
$zonefile = $result['zonefile'];
@@ -1004,6 +1197,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$writeaccesslog = $result['writeaccesslog'];
$writeerrorlog = $result['writeerrorlog'];
$documentroot = $result['documentroot'];
$override_tls = $result['override_tls'];
}
if ($this->getUserDetail('caneditphpsettings') == '1' || $this->getUserDetail('change_serversettings') == '1') {
@@ -1051,14 +1246,24 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
// check non-ssl IP
$ipandports = $this->validateIpAddresses($p_ipandports, false, $result['id']);
// check ssl IP
if (empty($p_ssl_ipandports) || (! is_array($p_ssl_ipandports) && is_null($p_ssl_ipandports))) {
foreach ($result['ipsandports'] as $ip) {
if ($ip['ssl'] == 1) {
$p_ssl_ipandports[] = $ip['id'];
}
}
}
$ssl_ipandports = array();
if (Settings::Get('system.use_ssl') == "1" && ! empty($p_ssl_ipandports)) {
if (Settings::Get('system.use_ssl') == "1" && ! empty($p_ssl_ipandports) && $p_ssl_ipandports[0] != - 1) {
$ssl_ipandports = $this->validateIpAddresses($p_ssl_ipandports, true, $result['id']);
if ($this->getUserDetail('change_serversettings') == '1') {
$ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $ssl_specialsettings), 'ssl_specialsettings', '/^[^\0]*$/', '', array(), true);
}
}
if ($remove_ssl_ipandport || (! empty($p_ssl_ipandports) && $p_ssl_ipandports[0] == - 1)) {
$ssl_ipandports = array();
}
if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports)) {
$ssl_redirect = 0;
$letsencrypt = 0;
@@ -1337,6 +1542,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$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['id'] = $id;
$update_stmt = Database::prepare("
@@ -1375,7 +1584,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload,
`ocsp_stapling` = :ocsp_stapling
`ocsp_stapling` = :ocsp_stapling,
`override_tls` = :override_tls,
`ssl_protocols` = :ssl_protocols,
`ssl_cipher_list` = :ssl_cipher_list,
`tlsv13_cipher_list` = :tlsv13_cipher_list
WHERE `id` = :id
");
Database::pexecute($update_stmt, $update_data, true, true);
@@ -1386,6 +1599,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$_update_data['openbasedir'] = $openbasedir;
$_update_data['mod_fcgid_starter'] = $mod_fcgid_starter;
$_update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests;
$_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['parentdomainid'] = $id;
// if php config is to be set for all subdomains, check here
@@ -1394,7 +1611,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$_update_data['phpsettingid'] = $phpsettingid;
$update_phpconfig = ", `phpsettingid` = :phpsettingid";
}
// if we have no more ssl-ip's for this domain,
// all its subdomains must have "ssl-redirect = 0"
// and disable let's encrypt
@@ -1410,7 +1626,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`phpenabled` = :phpenabled,
`openbasedir` = :openbasedir,
`mod_fcgid_starter` = :mod_fcgid_starter,
`mod_fcgid_maxrequests` = :mod_fcgid_maxrequests
`mod_fcgid_maxrequests` = :mod_fcgid_maxrequests,
`override_tls` = :override_tls,
`ssl_protocols` = :ssl_protocols,
`ssl_cipher_list` = :ssl_cipher_list,
`tlsv13_cipher_list` = :tlsv13_cipher_list
" . $update_phpconfig . $upd_specialsettings . $updatechildren . $update_sslredirect . "
WHERE `parentdomainid` = :parentdomainid
");
@@ -1735,8 +1955,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
} elseif ($edit_id > 0) {
// set currently used ip's
$ipsresult_stmt = Database::prepare("
SELECT `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id
");
SELECT d2i.`id_ipandports`
FROM `" . TABLE_DOMAINTOIP . "` d2i
LEFT JOIN `" . TABLE_PANEL_IPSANDPORTS . "` i ON i.id = d2i.id_ipandports
WHERE d2i.`id_domain` = :id AND i.`ssl` = " . ($ssl ? "'1'" : "'0'"));
Database::pexecute($ipsresult_stmt, array(
'id' => $edit_id
), true, true);

View File

@@ -388,12 +388,21 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
}
/**
* You cannot directly list email forwarders.
* You cannot directly list email accounts.
* You need to call Emails.listing()
*/
public function listing()
{
throw new \Exception('You cannot directly list email forwarders. You need to call Emails.listing()', 303);
throw new \Exception('You cannot directly list email accounts. You need to call Emails.listing()', 303);
}
/**
* You cannot directly count email accounts.
* You need to call Emails.listingCount()
*/
public function listingCount()
{
throw new \Exception('You cannot directly count email accounts. You need to call Emails.listingCount()', 303);
}
/**

View File

@@ -109,11 +109,11 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
/**
* You cannot directly get an email forwarder.
* You need to call Emails.get()
* Try EmailForwarders.listing()
*/
public function get()
{
throw new \Exception('You cannot directly get an email forwarder. You need to call Emails.get()', 303);
throw new \Exception('You cannot directly get an email forwarder. Try EmailForwarders.listing()', 303);
}
/**
@@ -126,12 +126,91 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
}
/**
* You cannot directly list email forwarders.
* You need to call Emails.listing()
* List email forwarders for a given email address
*
* @param int $id
* optional, the email-address-id
* @param string $emailaddr
* optional, the email-address to delete the forwarder from
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
*
* @access admin,customer
* @throws \Exception
* @return string json-encoded array count|list
*/
public function listing()
{
throw new \Exception('You cannot directly list email forwarders. You need to call Emails.listing()', 303);
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new \Exception("You cannot access this resource", 405);
}
// parameter
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
// validation
$result = $this->apiCall('Emails.get', array(
'id' => $id,
'emailaddr' => $emailaddr
));
$id = $result['id'];
$result['destination'] = explode(' ', $result['destination']);
$destination = array();
foreach ($result['destination'] as $index => $address) {
$destination[] = [
'id' => $index,
'address' => $address
];
}
return $this->response(200, "successfull", [
'count' => count($destination),
'list' => $destination
]);
}
/**
* count email forwarders for a given email address
*
* @param int $id
* optional, the email-address-id
* @param string $emailaddr
* optional, the email-address to delete the forwarder from
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
*
* @access admin,customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new \Exception("You cannot access this resource", 405);
}
// parameter
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
// validation
$result = $this->apiCall('Emails.get', array(
'id' => $id,
'emailaddr' => $emailaddr
));
$id = $result['id'];
$result['destination'] = explode(' ', $result['destination']);
return $this->response(200, "successfull", count($result['destination']));
}
/**

View File

@@ -265,7 +265,15 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, admin-only, select email addresses of a specific customer by id
* @param string $loginname
* optional, admin-only, select email addresses of a specific customer by loginname
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
@@ -274,14 +282,14 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
{
$customer_ids = $this->getAllowedCustomerIds('email');
$result = array();
$query_fields = array();
$result_stmt = Database::prepare("
SELECT m.`id`, m.`domainid`, m.`email`, m.`email_full`, m.`iscatchall`, u.`quota`, m.`destination`, m.`popaccountid`, d.`domain`, u.`mboxsize`
FROM `" . TABLE_MAIL_VIRTUAL . "` m
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`)
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`)
WHERE m.`customerid` IN (" . implode(", ", $customer_ids) . ")
");
Database::pexecute($result_stmt, null, true, true);
WHERE m.`customerid` IN (" . implode(", ", $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
Database::pexecute($result_stmt, $query_fields, true, true);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
@@ -292,6 +300,34 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
));
}
/**
* returns the total number of accessable email addresses
*
* @param int $customerid
* optional, admin-only, select email addresses of a specific customer by id
* @param string $loginname
* optional, admin-only, select email addresses of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
$customer_ids = $this->getAllowedCustomerIds('email');
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_emails
FROM `" . TABLE_MAIL_VIRTUAL . "` m
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`)
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`)
WHERE m.`customerid` IN (" . implode(", ", $customer_ids) . ")
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_emails']);
}
}
/**
* delete an email address by either id or username
*

View File

@@ -24,6 +24,15 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
/**
* lists all fpm-daemon entries
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin
* @throws \Exception
* @return string json-encoded array count|list
@@ -32,21 +41,18 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
{
if ($this->isAdmin()) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list fpm-daemons");
$result = Database::query("
SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` ORDER BY `description` ASC
");
$query_fields = array();
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "`" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
Database::pexecute($result_stmt, $query_fields, true, true);
$fpmdaemons = array();
while ($row = $result->fetch(\PDO::FETCH_ASSOC)) {
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$query_params = array(
'id' => $row['id']
);
$query = "SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `fpmsettingid` = :id";
$configresult_stmt = Database::prepare($query);
$configresult_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `fpmsettingid` = :id");
Database::pexecute($configresult_stmt, $query_params, true, true);
$configs = array();
@@ -72,6 +78,27 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* returns the total number of accessable fpm daemons
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin()) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_fpms FROM `" . TABLE_PANEL_FPMDAEMONS . "`
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_fpms']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* return a fpm-daemon entry by id
*

View File

@@ -56,7 +56,9 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
throw new \Exception("You cannot access this resource", 405);
}
if ($this->getUserDetail('ftps_used') < $this->getUserDetail('ftps') || $this->getUserDetail('ftps') == '-1') {
$is_defaultuser = $this->getBoolParam('is_defaultuser', true, 0);
if (($this->getUserDetail('ftps_used') < $this->getUserDetail('ftps') || $this->getUserDetail('ftps') == '-1') || $this->isAdmin() && $is_defaultuser == 1) {
// required paramters
$path = $this->getParam('path');
@@ -71,7 +73,6 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
$ftpdomain = $this->getParam('ftp_domain', true, '');
$additional_members = $this->getParam('additional_members', true, array());
$is_defaultuser = $this->getBoolParam('is_defaultuser', true, 0);
// validation
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
@@ -105,7 +106,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
$sendinfomail = 0;
}
if (Settings::Get('customer.ftpatdomain') == '1' && !$is_defaultuser) {
if (Settings::Get('customer.ftpatdomain') == '1' && ! $is_defaultuser) {
if ($ftpusername == '') {
\Froxlor\UI\Response::standard_error(array(
'stringisempty',
@@ -459,7 +460,15 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
* optional, admin-only, select ftp-users of a specific customer by id
* @param string $loginname
* optional, admin-only, select ftp-users of a specific customer by loginname
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
@@ -468,11 +477,11 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
{
$customer_ids = $this->getAllowedCustomerIds('ftp');
$result = array();
$query_fields = array();
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_FTP_USERS . "`
WHERE `customerid` IN (" . implode(", ", $customer_ids) . ")
");
Database::pexecute($result_stmt, null, true, true);
WHERE `customerid` IN (" . implode(", ", $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
Database::pexecute($result_stmt, $query_fields, true, true);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
@@ -483,6 +492,32 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
));
}
/**
* returns the total number of accessable ftp accounts
*
* @param int $customerid
* optional, admin-only, select ftp-users of a specific customer by id
* @param string $loginname
* optional, admin-only, select ftp-users of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
$customer_ids = $this->getAllowedCustomerIds('ftp');
$result = array();
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_ftps FROM `" . TABLE_FTP_USERS . "`
WHERE `customerid` IN (" . implode(", ", $customer_ids) . ")
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_ftps']);
}
}
/**
* delete a ftp-user by either id or username
*
@@ -541,6 +576,9 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
"username" => $customer_data['loginname']
);
Database::pexecute($stmt, $params, true, true);
} else {
// do not allow removing default ftp-account
\Froxlor\UI\Response::standard_error('ftp_cantdeletemainaccount', '', true);
}
// remove all quotatallies

View File

@@ -25,6 +25,15 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
/**
* list all available hosting plans
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin
* @throws \Exception
* @return string json-encoded array count|list
@@ -33,15 +42,17 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
{
if ($this->isAdmin()) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list hosting-plans");
$query_fields = array();
$result_stmt = Database::prepare("
SELECT p.*, a.loginname as adminname
FROM `" . TABLE_PANEL_PLANS . "` p, `" . TABLE_PANEL_ADMINS . "` a
WHERE `p`.`adminid` = `a`.`adminid`" . ($this->getUserDetail('customers_see_all') ? '' : " AND `p`.`adminid` = :adminid "));
WHERE `p`.`adminid` = `a`.`adminid`" . ($this->getUserDetail('customers_see_all') ? '' : " AND `p`.`adminid` = :adminid ") . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
$params = array();
if ($this->getUserDetail('customers_see_all') == '0') {
$params['adminid'] = $this->getUserDetail('adminid');
}
Database::pexecute($result_stmt, $params);
$params = array_merge($params, $query_fields);
Database::pexecute($result_stmt, $params, true, true);
$result = array();
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
@@ -54,6 +65,32 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* returns the total number of accessable hosting plans
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin()) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_plans
FROM `" . TABLE_PANEL_PLANS . "` p, `" . TABLE_PANEL_ADMINS . "` a
WHERE `p`.`adminid` = `a`.`adminid`" . ($this->getUserDetail('customers_see_all') ? '' : " AND `p`.`adminid` = :adminid "));
$params = array();
if ($this->getUserDetail('customers_see_all') == '0') {
$params['adminid'] = $this->getUserDetail('adminid');
}
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_plans']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* return a hosting-plan entry by either id or plan-name
*

View File

@@ -25,6 +25,15 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
/**
* lists all ip/port entries
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin
* @throws \Exception
* @return string json-encoded array count|list
@@ -34,12 +43,14 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list ips and ports");
$ip_where = "";
$append_where = false;
if (! empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != - 1) {
$ip_where = "WHERE `id` IN (" . implode(", ", json_decode($this->getUserDetail('ip'), true)) . ")";
$append_where = true;
}
$query_fields = array();
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $ip_where . " ORDER BY `ip` ASC, `port` ASC
");
SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $ip_where . $this->getSearchWhere($query_fields, $append_where) . $this->getOrderBy() . $this->getLimit());
Database::pexecute($result_stmt, null, true, true);
$result = array();
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
@@ -53,6 +64,30 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* returns the total number of accessable ip/port entries
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) {
$ip_where = "";
if (! empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != - 1) {
$ip_where = "WHERE `id` IN (" . implode(", ", json_decode($this->getUserDetail('ip'), true)) . ")";
}
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_ips FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $ip_where);
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_ips']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* return an ip/port entry by id
*
@@ -135,7 +170,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
$ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip'), false, 'invalidip', false, false, false, true);
$ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip'), false, 'invalidip', false, false, false, false, true);
$port = \Froxlor\Validate\Validate::validate($this->getParam('port', true, 80), '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', array(
'stringisempty',
'myport'
@@ -332,7 +367,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
'id' => $id
));
$ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip', true, $result['ip']), false, 'invalidip', false, false, false, true);
$ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip', true, $result['ip']), false, 'invalidip', false, false, false, false, true);
$port = \Froxlor\Validate\Validate::validate($this->getParam('port', true, $result['port']), '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', array(
'stringisempty',
'myport'
@@ -505,7 +540,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
));
$result_checkdomain_stmt = Database::prepare("
SELECT `id_domain` as `id` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_ipandports` = :id
SELECT `id_domain` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_ipandports` = :id
");
$result_checkdomain = Database::pexecute_first($result_checkdomain_stmt, array(
'id' => $id

View File

@@ -34,7 +34,9 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param bool $sendinfomail
* optional, send created resource-information to customer, default: false
* @param int $customerid
* required when called as admin, not needed when called as customer
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
*
* @access admin, customer
* @throws \Exception
@@ -42,53 +44,50 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*/
public function add()
{
if ($this->getUserDetail('mysqls_used') < $this->getUserDetail('mysqls') || $this->getUserDetail('mysqls') == '-1') {
// required paramters
$password = $this->getParam('mysql_password');
// required paramters
$password = $this->getParam('mysql_password');
// parameters
$dbserver = $this->getParam('mysql_server', true, 0);
$databasedescription = $this->getParam('description', true, '');
$sendinfomail = $this->getBoolParam('sendinfomail', true, 0);
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData('mysqls');
// parameters
$dbserver = $this->getParam('mysql_server', true, 0);
$databasedescription = $this->getParam('description', true, '');
$sendinfomail = $this->getBoolParam('sendinfomail', true, 0);
// validation
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
$password = \Froxlor\System\Crypt::validatePassword($password, true);
$databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true);
// validation
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
$password = \Froxlor\System\Crypt::validatePassword($password, true);
$databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true);
// validate whether the dbserver exists
$dbserver = \Froxlor\Validate\Validate::validate($dbserver, html_entity_decode($this->lng['mysql']['mysql_server']), '', '', 0, true);
Database::needRoot(true, $dbserver);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
if (! isset($sql_root) || ! is_array($sql_root)) {
throw new \Exception("Database server with index #" . $dbserver . " is unknown", 404);
}
// validate whether the dbserver exists
$dbserver = \Froxlor\Validate\Validate::validate($dbserver, html_entity_decode($this->lng['mysql']['mysql_server']), '', '', 0, true);
Database::needRoot(true, $dbserver);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
if (! isset($sql_root) || ! is_array($sql_root)) {
throw new \Exception("Database server with index #" . $dbserver . " is unknown", 404);
}
if ($sendinfomail != 1) {
$sendinfomail = 0;
}
if ($sendinfomail != 1) {
$sendinfomail = 0;
}
$newdb_params = array(
'loginname' => ($this->isAdmin() ? $customer['loginname'] : $this->getUserDetail('loginname')),
'mysql_lastaccountnumber' => ($this->isAdmin() ? $customer['mysql_lastaccountnumber'] : $this->getUserDetail('mysql_lastaccountnumber'))
);
// create database, user, set permissions, etc.pp.
$dbm = new \Froxlor\Database\DbManager($this->logger());
$username = $dbm->createDatabase($newdb_params['loginname'], $password, $newdb_params['mysql_lastaccountnumber']);
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData('mysqls');
// we've checked against the password in dbm->createDatabase
if ($username == false) {
\Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true);
}
$newdb_params = array(
'loginname' => ($this->isAdmin() ? $customer['loginname'] : $this->getUserDetail('loginname')),
'mysql_lastaccountnumber' => ($this->isAdmin() ? $customer['mysql_lastaccountnumber'] : $this->getUserDetail('mysql_lastaccountnumber'))
);
// create database, user, set permissions, etc.pp.
$dbm = new \Froxlor\Database\DbManager($this->logger());
$username = $dbm->createDatabase($newdb_params['loginname'], $password, $newdb_params['mysql_lastaccountnumber']);
// we've checked against the password in dbm->createDatabase
if ($username == false) {
\Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true);
}
// add database info to froxlor
$stmt = Database::prepare("
// add database info to froxlor
$stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_DATABASES . "`
SET
`customerid` = :customerid,
@@ -96,79 +95,77 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`description` = :description,
`dbserver` = :dbserver
");
$params = array(
"customerid" => $customer['customerid'],
"databasename" => $username,
"description" => $databasedescription,
"dbserver" => $dbserver
);
Database::pexecute($stmt, $params, true, true);
$databaseid = Database::lastInsertId();
$params['id'] = $databaseid;
$params = array(
"customerid" => $customer['customerid'],
"databasename" => $username,
"description" => $databasedescription,
"dbserver" => $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');
// update customer usage
Customers::increaseUsage($customer['customerid'], 'mysqls_used');
Customers::increaseUsage($customer['customerid'], 'mysql_lastaccountnumber');
// send info-mail?
if ($sendinfomail == 1) {
$pma = $this->lng['admin']['notgiven'];
if (Settings::Get('panel.phpmyadmin_url') != '') {
$pma = Settings::Get('panel.phpmyadmin_url');
}
Database::needRoot(true, $dbserver);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
$userinfo = $customer;
$replace_arr = array(
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($userinfo),
'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($userinfo), // < keep this for compatibility
'DB_NAME' => $username,
'DB_PASS' => $password,
'DB_DESC' => $databasedescription,
'DB_SRV' => $sql_root['host'],
'PMA_URI' => $pma
);
// get template for mail subject
$mail_subject = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_subject', $replace_arr, $this->lng['mails']['new_database_by_customer']['subject']);
// get template for mail body
$mail_body = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_mailbody', $replace_arr, $this->lng['mails']['new_database_by_customer']['mailbody']);
$_mailerror = false;
$mailerr_msg = "";
try {
$this->mailer()->Subject = $mail_subject;
$this->mailer()->AltBody = $mail_body;
$this->mailer()->msgHTML(str_replace("\n", "<br />", $mail_body));
$this->mailer()->addAddress($userinfo['email'], \Froxlor\User::getCorrectUserSalutation($userinfo));
$this->mailer()->send();
} catch (\PHPMailer\PHPMailer\Exception $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (\Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg);
\Froxlor\UI\Response::standard_error('errorsendingmail', $userinfo['email'], true);
}
$this->mailer()->clearAddresses();
// send info-mail?
if ($sendinfomail == 1) {
$pma = $this->lng['admin']['notgiven'];
if (Settings::Get('panel.phpmyadmin_url') != '') {
$pma = Settings::Get('panel.phpmyadmin_url');
}
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added mysql-database '" . $username . "'");
$result = $this->apiCall('Mysqls.get', array(
'dbname' => $username
));
return $this->response(200, "successfull", $result);
Database::needRoot(true, $dbserver);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
$userinfo = $customer;
$replace_arr = array(
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($userinfo),
'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($userinfo), // < keep this for compatibility
'DB_NAME' => $username,
'DB_PASS' => $password,
'DB_DESC' => $databasedescription,
'DB_SRV' => $sql_root['host'],
'PMA_URI' => $pma
);
// get template for mail subject
$mail_subject = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_subject', $replace_arr, $this->lng['mails']['new_database_by_customer']['subject']);
// get template for mail body
$mail_body = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_mailbody', $replace_arr, $this->lng['mails']['new_database_by_customer']['mailbody']);
$_mailerror = false;
$mailerr_msg = "";
try {
$this->mailer()->Subject = $mail_subject;
$this->mailer()->AltBody = $mail_body;
$this->mailer()->msgHTML(str_replace("\n", "<br />", $mail_body));
$this->mailer()->addAddress($userinfo['email'], \Froxlor\User::getCorrectUserSalutation($userinfo));
$this->mailer()->send();
} catch (\PHPMailer\PHPMailer\Exception $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (\Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg);
\Froxlor\UI\Response::standard_error('errorsendingmail', $userinfo['email'], true);
}
$this->mailer()->clearAddresses();
}
throw new \Exception("No more resources available", 406);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added mysql-database '" . $username . "'");
$result = $this->apiCall('Mysqls.get', array(
'dbname' => $username
));
return $this->response(200, "successfull", $result);
}
/**
@@ -276,6 +273,10 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, update password for the database
* @param string $description
* optional, description for database
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
*
* @access admin, customer
* @throws \Exception
@@ -287,6 +288,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$dn_optional = ($id <= 0 ? false : true);
$dbname = $this->getParam('dbname', $dn_optional, '');
$dbserver = $this->getParam('mysql_server', true, - 1);
$customer = $this->getCustomerData();
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) {
throw new \Exception("You cannot access this resource", 405);
@@ -307,9 +309,6 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
$databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true);
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData();
if ($password != '') {
// validate password
$password = \Froxlor\System\Crypt::validatePassword($password, true);
@@ -359,6 +358,14 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, admin-only, select dbs of a specific customer by id
* @param string $loginname
* optional, admin-only, select dbs of a specific customer by loginname
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer
* @throws \Exception
@@ -369,10 +376,10 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$result = array();
$dbserver = $this->getParam('mysql_server', true, - 1);
$customer_ids = $this->getAllowedCustomerIds('mysql');
$query_fields = array();
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DATABASES . "`
WHERE `customerid`= :customerid AND `dbserver` = :dbserver
");
WHERE `customerid`= :customerid AND `dbserver` = :dbserver" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
if ($dbserver < 0) {
// use all dbservers
$dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`");
@@ -388,10 +395,10 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
foreach ($customer_ids as $customer_id) {
foreach ($dbservers as $_dbserver) {
Database::pexecute($result_stmt, array(
Database::pexecute($result_stmt, array_merge(array(
'customerid' => $customer_id,
'dbserver' => $_dbserver['dbserver']
), true, true);
), $query_fields), true, true);
// Begin root-session
Database::needRoot(true, $_dbserver['dbserver']);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
@@ -416,6 +423,31 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
));
}
/**
* returns the total number of accessable databases
*
* @param int $customerid
* optional, admin-only, select dbs of a specific customer by id
* @param string $loginname
* optional, admin-only, select dbs of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
$customer_ids = $this->getAllowedCustomerIds('mysql');
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_dbs FROM `" . TABLE_PANEL_DATABASES . "`
WHERE `customerid` IN (" . implode(", ", $customer_ids) . ")
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_dbs']);
}
}
/**
* delete a mysql database by either id or dbname
*
@@ -425,6 +457,10 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, the databasename
* @param int $mysql_server
* optional, specify database-server, default is none
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
*
* @access admin, customer
* @throws \Exception
@@ -436,6 +472,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$dn_optional = ($id <= 0 ? false : true);
$dbname = $this->getParam('dbname', $dn_optional, '');
$dbserver = $this->getParam('mysql_server', true, - 1);
$customer = $this->getCustomerData();
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) {
throw new \Exception("You cannot access this resource", 405);
@@ -462,7 +499,6 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
), true, true);
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData();
$mysql_used = $customer['mysqls_used'];
// reduce mysql-usage-counter

View File

@@ -27,7 +27,15 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
*
* @param bool $with_subdomains
* optional, also include subdomains to the list domains that use the config, default 0 (false)
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin
* @throws \Exception
* @return string json-encoded array count|list
@@ -38,16 +46,15 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list php-configs");
$with_subdomains = $this->getBoolParam('with_subdomains', true, false);
$result = Database::query("
$query_fields = array();
$result_stmt = Database::prepare("
SELECT c.*, fd.description as fpmdesc
FROM `" . TABLE_PANEL_PHPCONFIGS . "` c
LEFT JOIN `" . TABLE_PANEL_FPMDAEMONS . "` fd ON fd.id = c.fpmsettingid
ORDER BY c.description ASC
");
LEFT JOIN `" . TABLE_PANEL_FPMDAEMONS . "` fd ON fd.id = c.fpmsettingid" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit()
);
Database::pexecute($result_stmt, $query_fields, true, true);
$phpconfigs = array();
while ($row = $result->fetch(\PDO::FETCH_ASSOC)) {
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$query_params = array(
'id' => $row['id']
);
@@ -115,6 +122,28 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* returns the total number of accessable php-setting entries
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin()) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_phps
FROM `" . TABLE_PANEL_PHPCONFIGS . "` c
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_phps']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* return a php-setting entry by id
*

View File

@@ -270,7 +270,12 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
`http2` = :http2,
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload
`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
");
$params = array(
"customerid" => $customer['customerid'],
@@ -295,7 +300,12 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
"http2" => $http2,
"hsts" => $hsts_maxage,
"hsts_sub" => $hsts_sub,
"hsts_preload" => $hsts_preload
"hsts_preload" => $hsts_preload,
"ocsp_stapling" => $domain_check['ocsp_stapling'],
"override_tls" => $domain_check['override_tls'],
"ssl_protocols" => $domain_check['ssl_protocols'],
"ssl_cipher_list" => $domain_check['ssl_cipher_list'],
"tlsv13_cipher_list" => $domain_check['tlsv13_cipher_list']
);
Database::pexecute($stmt, $params, true, true);
$subdomain_id = Database::lastInsertId();
@@ -674,6 +684,19 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
/**
* lists all subdomain entries
*
* @param int $customerid
* optional, admin-only, select (sub)domains of a specific customer by id
* @param string $loginname
* optional, admin-only, select (sub)domains of a specific customer by loginname
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
@@ -686,6 +709,104 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$customerid = $this->getParam('customerid', true, 0);
$loginname = $this->getParam('loginname', true, '');
if (! empty($customerid) || ! empty($loginname)) {
$result = $this->apiCall('Customers.get', array(
'id' => $customerid,
'loginname' => $loginname
));
$custom_list_result = array(
$result
);
} else {
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
}
$customer_ids = array();
$customer_stdsubs = array();
foreach ($custom_list_result as $customer) {
$customer_ids[] = $customer['customerid'];
$customer_stdsubs[$customer['customerid']] = $customer['standardsubdomain'];
}
if (empty($customer_ids)) {
throw new \Exception("Required resource unsatisfied.", 405);
}
if (empty($customer_stdsubs)) {
throw new \Exception("Required resource unsatisfied.", 405);
}
$select_fields = [
'`d`.*'
];
} else {
if (Settings::IsInList('panel.customer_hide_options', 'domains')) {
throw new \Exception("You cannot access this resource", 405);
}
$customer_ids = array(
$this->getUserDetail('customerid')
);
$customer_stdsubs = array(
$this->getUserDetail('customerid') => $this->getUserDetail('standardsubdomain')
);
$select_fields = [
'`d`.`id`',
'`d`.`customerid`',
'`d`.`domain`',
'`d`.`documentroot`',
'`d`.`isbinddomain`',
'`d`.`isemaildomain`',
'`d`.`caneditdomain`',
'`d`.`iswildcarddomain`',
'`d`.`parentdomainid`',
'`d`.`letsencrypt`',
'`d`.`registration_date`',
'`d`.`termination_date`'
];
}
$query_fields = array();
// prepare select statement
$domains_stmt = Database::prepare("
SELECT " . implode(",", $select_fields) . ", IF(`d`.`parentdomainid` > 0, `pd`.`domain`, `d`.`domain`) AS `parentdomainname`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias`
FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `pd` ON `pd`.`id`=`d`.`parentdomainid`
WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ")
AND `d`.`email_only` = '0'
AND `d`.`id` NOT IN (" . implode(', ', $customer_stdsubs) . ")" . $this->getSearchWhere($query_fields, true) . " ORDER BY `parentdomainname` " . $this->getOrderBy(true) . $this->getLimit());
$result = array();
Database::pexecute($domains_stmt, $query_fields, true, true);
while ($row = $domains_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/**
* returns the total number of accessable subdomain entries
*
* @param int $customerid
* optional, admin-only, select (sub)domains of a specific customer by id
* @param string $loginname
* optional, admin-only, select (sub)domains of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin()) {
// if we're an admin, list all databases of all the admins customers
// or optionally for one specific customer identified by id or loginname
$customerid = $this->getParam('customerid', true, 0);
$loginname = $this->getParam('loginname', true, '');
if (! empty($customerid) || ! empty($loginname)) {
$result = $this->apiCall('Customers.get', array(
'id' => $customerid,
@@ -715,32 +836,20 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$this->getUserDetail('customerid') => $this->getUserDetail('standardsubdomain')
);
}
// prepare select statement
$domains_stmt = Database::prepare("
SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isbinddomain`, `d`.`isemaildomain`, `d`.`caneditdomain`, `d`.`iswildcarddomain`, `d`.`parentdomainid`, `d`.`letsencrypt`, `d`.`termination_date`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias`
SELECT COUNT(*) as num_subdom
FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id`
WHERE `d`.`customerid`= :customerid
AND `d`.`email_only`='0'
AND `d`.`id` <> :standardsubdomain
WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ")
AND `d`.`email_only` = '0'
AND `d`.`id` NOT IN (" . implode(', ', $customer_stdsubs) . ")
");
$result = array();
foreach ($customer_ids as $customer_id) {
Database::pexecute($domains_stmt, array(
"customerid" => $customer_id,
"standardsubdomain" => $customer_stdsubs[$customer_id]
), true, true);
while ($row = $domains_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
$result = Database::pexecute_first($domains_stmt, null, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_subdom']);
}
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/**

View File

@@ -0,0 +1,212 @@
<?php
namespace Froxlor\Api\Commands;
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 API
* @since 0.10.6
*
*/
class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity
{
/**
* list all log-entries
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
*/
public function listing()
{
$result = array();
$query_fields = array();
if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '1') {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_LOG . "` " . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
} elseif ($this->isAdmin()) {
// get all admin customers
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
$customer_names = array();
foreach ($custom_list_result as $customer) {
$customer_names[] = $customer['loginname'];
}
if (count($customer_names) > 0) {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_LOG . "`
WHERE `user` = :loginname OR `user` IN (" . implode(', ', $customer_names) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
} else {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_LOG . "`
WHERE `user` = :loginname" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
}
$query_fields['loginname'] = $this->getUserDetail('loginname');
} else {
// every one else just sees their logs
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_LOG . "`
WHERE `user` = :loginname AND `action` <> 99 " . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
$query_fields['loginname'] = $this->getUserDetail('loginname');
}
Database::pexecute($result_stmt, $query_fields, true, true);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list log-entries");
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/**
* returns the total number of log-entries
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
$params = null;
if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '1') {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_logs FROM `" . TABLE_PANEL_LOG . "`
");
} elseif ($this->isAdmin()) {
// get all admin customers
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
$customer_names = array();
foreach ($custom_list_result as $customer) {
$customer_names[] = $customer['loginname'];
}
if (count($customer_names) > 0) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_logs FROM `" . TABLE_PANEL_LOG . "`
WHERE `user` = :loginname OR `user` IN (" . implode(', ', $customer_names) . ")
");
} else {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_logs FROM `" . TABLE_PANEL_LOG . "`
WHERE `user` = :loginname
");
}
$params = [
'loginname' => $this->getUserDetail('loginname')
];
} else {
// every one else just sees their logs
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_logs FROM `" . TABLE_PANEL_LOG . "`
WHERE `user` = :loginname AND `action` <> 99
");
$params = [
'loginname' => $this->getUserDetail('loginname')
];
}
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
return $this->response(200, "successfull", $result['num_logs']);
}
}
/**
* You cannot get log entries
*/
public function get()
{
throw new \Exception('You cannot get log entries', 303);
}
/**
* You cannot add log entries
*/
public function add()
{
throw new \Exception('You cannot add log entries', 303);
}
/**
* You 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 to keep, default is 10
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function delete()
{
if ($this->isAdmin()) {
$min_to_keep = self::getParam('min_to_keep', true, 10);
if ($min_to_keep < 0) {
$min_to_keep = 0;
}
$truncatedate = time() - (60 * $min_to_keep);
$params = array();
if ($this->getUserDetail('customers_see_all') == '1') {
$result_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_LOG . "` WHERE `date` < :trunc
");
} else {
// get all admin customers
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
$customer_names = array();
foreach ($custom_list_result as $customer) {
$customer_names[] = $customer['loginname'];
}
if (count($customer_names) > 0) {
$result_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_LOG . "` WHERE `date` < :trunc AND `user` = :loginname OR `user` IN (" . implode(', ', $customer_names) . ")
");
} else {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_logs FROM `" . TABLE_PANEL_LOG . "`
DELETE FROM `" . TABLE_PANEL_LOG . "` WHERE `date` < :trunc AND `user` = :loginname
");
}
$params = [
'loginname' => $this->getUserDetail('loginname')
];
}
$params['trunc'] = $truncatedate;
Database::pexecute($result_stmt, $params, true, true);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] truncated the froxlor syslog");
return $this->response(200, "successfull", true);
}
throw new \Exception("Not allowed to execute given command.", 403);
}
}

View File

@@ -116,6 +116,16 @@ class Traffic extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
));
}
/**
* You cannot count the traffic data list
*
* @throws \Exception
*/
public function listingCount()
{
throw new \Exception('You cannot count the traffic data list', 303);
}
/**
* You cannot delete traffic data
*

View File

@@ -21,6 +21,8 @@ interface ResourceEntity
public function listing();
public function listingCount();
public function get();
public function add();

0
lib/Froxlor/Cli/ConfigServicesCmd.php Executable file → Normal file
View File

0
lib/Froxlor/Cli/SwitchServerIpCmd.php Executable file → Normal file
View File

View File

@@ -435,11 +435,7 @@ class ConfigDaemon
}
return '';
} elseif (preg_match('/^const\.(.*)$/', $matches[1], $match)) {
if (defined($match[1])) {
return constant($match[1]);
} else {
return '';
}
return $this->returnDynamic($match[1]);
} elseif (preg_match('/^sql\.(.*)$/', $matches[1], $match)) {
if (is_null($this->sqldata_cache)) {
// read in sql-data (if exists)
@@ -455,6 +451,14 @@ class ConfigDaemon
return $content;
}
private function returnDynamic($key = null)
{
$dynamics = [
'install_dir' => \Froxlor\Froxlor::getInstallDir()
];
return $dynamics[$key] ?? '';
}
/**
* Check if visibility should be changed
*

View File

@@ -178,7 +178,7 @@ class Apache extends HttpConfigBase
$this->virtualhosts_data[$vhosts_filename] .= ' ServerName ' . Settings::Get('system.hostname') . "\n";
$froxlor_aliases = Settings::Get('system.froxloraliases');
if (!empty($froxlor_aliases)) {
if (! empty($froxlor_aliases)) {
$froxlor_aliases = explode(",", $froxlor_aliases);
$aliases = "";
foreach ($froxlor_aliases as $falias) {
@@ -187,7 +187,7 @@ class Apache extends HttpConfigBase
}
}
$aliases = trim($aliases);
if (!empty($aliases)) {
if (! empty($aliases)) {
$this->virtualhosts_data[$vhosts_filename] .= ' ServerAlias ' . $aliases . "\n";
}
}
@@ -483,7 +483,7 @@ class Apache extends HttpConfigBase
$this->virtualhosts_data[$vhosts_filename] .= ' SSLHonorCipherOrder On' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' SSLCipherSuite ' . Settings::Get('system.ssl_cipher_list') . "\n";
$protocols = array_map('trim', explode(",", Settings::Get('system.ssl_protocols')));
if (in_array("TLSv1.3", $protocols) && !empty(Settings::Get('system.tlsv13_cipher_list')) && Settings::Get('system.apache24') == 1) {
if (in_array("TLSv1.3", $protocols) && ! empty(Settings::Get('system.tlsv13_cipher_list')) && Settings::Get('system.apache24') == 1) {
$this->virtualhosts_data[$vhosts_filename] .= ' SSLCipherSuite TLSv1.3 ' . Settings::Get('system.tlsv13_cipher_list') . "\n";
}
$this->virtualhosts_data[$vhosts_filename] .= ' SSLVerifyDepth 10' . "\n";
@@ -967,8 +967,13 @@ class Apache extends HttpConfigBase
}
if ($domain['ssl_cert_file'] != '') {
$ssl_protocols = ($domain['override_tls'] == '1' && ! empty($domain['ssl_protocols'])) ? $domain['ssl_protocols'] : Settings::Get('system.ssl_protocols');
$ssl_cipher_list = ($domain['override_tls'] == '1' && ! empty($domain['ssl_cipher_list'])) ? $domain['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list');
$tlsv13_cipher_list = ($domain['override_tls'] == '1' && ! 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(",", " +", Settings::Get('system.ssl_protocols')) . "\n";
$vhost_content .= ' SSLProtocol -ALL +' . str_replace(",", " +", $ssl_protocols) . "\n";
if (Settings::Get('system.apache24') == '1') {
if (isset($domain['http2']) && $domain['http2'] == '1' && Settings::Get('system.http2_support') == '1') {
$vhost_content .= ' Protocols h2 http/1.1' . "\n";
@@ -984,10 +989,10 @@ class Apache extends HttpConfigBase
}
// this makes it more secure, thx to Marcel (08/2013)
$vhost_content .= ' SSLHonorCipherOrder On' . "\n";
$vhost_content .= ' SSLCipherSuite ' . Settings::Get('system.ssl_cipher_list') . "\n";
$protocols = array_map('trim', explode(",", Settings::Get('system.ssl_protocols')));
if (in_array("TLSv1.3", $protocols) && !empty(Settings::Get('system.tlsv13_cipher_list')) && Settings::Get('system.apache24') == 1) {
$vhost_content .= ' SSLCipherSuite TLSv1.3 ' . Settings::Get('system.tlsv13_cipher_list') . "\n";
$vhost_content .= ' SSLCipherSuite ' . $ssl_cipher_list . "\n";
$protocols = array_map('trim', explode(",", $ssl_protocols));
if (in_array("TLSv1.3", $protocols) && ! empty($tlsv13_cipher_list) && Settings::Get('system.apache24') == 1) {
$vhost_content .= ' SSLCipherSuite TLSv1.3 ' . $tlsv13_cipher_list . "\n";
}
$vhost_content .= ' SSLVerifyDepth 10' . "\n";
$vhost_content .= ' SSLCertificateFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_file']) . "\n";

View File

@@ -45,19 +45,8 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
public static $no_inserttask = false;
public static function run($internal = false)
private static function needRenew()
{
if (! defined('CRON_IS_FORCED') && ! defined('CRON_DEBUG_FLAG') && $internal == false) {
// FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Let's Encrypt cronjob is combined with regeneration of webserver configuration files.\nFor debugging purposes you can use the --debug switch and/or the --force switch to run the cron manually.");
return 0;
}
self::checkInstall();
self::$apiserver = 'https://acme-v0' . \Froxlor\Settings::Get('system.leapiversion') . '.api.letsencrypt.org/directory';
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Requesting/renewing Let's Encrypt certificates");
$certificates_stmt = Database::query("
SELECT
domssl.`id`,
@@ -94,6 +83,52 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
OR domssl.`expirationdate` IS NULL
)
");
$customer_ssl = $certificates_stmt->fetchAll(\PDO::FETCH_ASSOC);
if (!$customer_ssl) {
$customer_ssl = array();
}
$froxlor_ssl = array();
if (Settings::Get('system.le_froxlor_enabled') == '1') {
$froxlor_ssl_settings_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
WHERE `domainid` = '0' AND
(`expirationdate` < DATE_ADD(NOW(), INTERVAL 30 DAY) OR `expirationdate` IS NULL)
");
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
if (!$froxlor_ssl) {
$froxlor_ssl = array();
}
}
if (count($customer_ssl) > 0 || count($froxlor_ssl) > 0) {
return array(
'customer_ssl' => $customer_ssl,
'froxlor_ssl' => $froxlor_ssl
);
}
return false;
}
public static function run($internal = false)
{
if (! defined('CRON_IS_FORCED') && ! defined('CRON_DEBUG_FLAG') && $internal == false) {
// Let's Encrypt cronjob is combined with regeneration of webserver configuration files.
// For debugging purposes you can use the --debug switch and the --force switch to run the cron manually.
// check whether we MIGHT need to run although there is no task to regenerate config-files
$needRenew = self::needRenew();
if ($needRenew) {
// insert task to generate certificates and vhost-configs
\Froxlor\System\Cronjob::inserttask(1);
}
return 0;
}
self::checkInstall();
self::$apiserver = 'https://acme-v0' . \Froxlor\Settings::Get('system.leapiversion') . '.api.letsencrypt.org/directory';
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Requesting/renewing Let's Encrypt certificates");
$aliasdomains_stmt = Database::prepare("
SELECT
@@ -127,6 +162,8 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
// flag for re-generation of vhost files
$changedetected = 0;
$needRenew = self::needRenew();
// first - generate LE for system-vhost if enabled
if (Settings::Get('system.le_froxlor_enabled') == '1') {
@@ -147,15 +184,10 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
'id' => null
);
$froxlor_ssl_settings_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
WHERE `domainid` = '0' AND
(`expirationdate` < DATE_ADD(NOW(), INTERVAL 30 DAY) OR `expirationdate` IS NULL)
");
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
$froxlor_ssl = $needRenew ? $needRenew['froxlor_ssl'] : array();
$cert_mode = 'issue';
if ($froxlor_ssl) {
if (count($froxlor_ssl) > 0) {
$cert_mode = 'renew';
$certrow['id'] = $froxlor_ssl['id'];
$certrow['expirationdate'] = $froxlor_ssl['expirationdate'];
@@ -177,7 +209,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
if ($cert_mode) {
$domains = array(
$certrow['domain']
strtolower($certrow['domain'])
);
$froxlor_aliases = Settings::Get('system.froxloraliases');
@@ -185,7 +217,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
$froxlor_aliases = explode(",", $froxlor_aliases);
foreach ($froxlor_aliases as $falias) {
if (\Froxlor\Validate\Validate::validateDomain(trim($falias))) {
$domains[] = trim($falias);
$domains[] = strtolower(trim($falias));
}
}
}
@@ -210,10 +242,12 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
}
// customer domains
$certrows = $certificates_stmt->fetchAll(\PDO::FETCH_ASSOC);
$cert_mode = 'issue';
$certrows = $needRenew ? $needRenew['customer_ssl'] : array();
foreach ($certrows as $certrow) {
// initialize mode to 'issue'
$cert_mode = 'issue';
// set logger to corresponding loginname for the log to appear in the users system-log
$cronlog = FroxlorLogger::getInstanceOf(array(
'loginname' => $certrow['loginname'],
@@ -237,12 +271,12 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $certrow['domain']);
$domains = array(
$certrow['domain']
strtolower($certrow['domain'])
);
// add www.<domain> to SAN list
if ($certrow['wwwserveralias'] == 1) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $certrow['domain']);
$domains[] = 'www.' . $certrow['domain'];
$domains[] = strtolower('www.' . $certrow['domain']);
}
// add alias domains (and possibly www.<aliasdomain>) to SAN list
@@ -252,10 +286,10 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
$aliasdomains = $aliasdomains_stmt->fetchAll(\PDO::FETCH_ASSOC);
foreach ($aliasdomains as $aliasdomain) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $aliasdomain['domain']);
$domains[] = $aliasdomain['domain'];
$domains[] = strtolower($aliasdomain['domain']);
if ($aliasdomain['wwwserveralias'] == 1) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $aliasdomain['domain']);
$domains[] = 'www.' . $aliasdomain['domain'];
$domains[] = strtolower('www.' . $aliasdomain['domain']);
}
}
@@ -390,6 +424,6 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
$acmesh_result = \Froxlor\FileDir::safe_exec(self::$acmesh . " --upgrade");
// check for activated cron (which is installed automatically) but we don't need it
$acmesh_result2 = \Froxlor\FileDir::safe_exec(self::$acmesh . " --uninstall-cronjob");
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Checking for LetsEncrypt client upgrades before renewing certificates:\n" . implode("\n", $acmesh_result)."\n".implode("\n", $acmesh_result2));
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Checking for LetsEncrypt client upgrades before renewing certificates:\n" . implode("\n", $acmesh_result) . "\n" . implode("\n", $acmesh_result2));
}
}

View File

@@ -570,6 +570,8 @@ class Lighttpd extends HttpConfigBase
if ($domain['ssl_cert_file'] != '') {
$ssl_cipher_list = ($domain['override_tls'] == '1' && ! empty($domain['ssl_cipher_list'])) ? $domain['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list');
// ssl.engine only necessary once in the ip/port vhost (SERVER['socket'] condition)
// $ssl_settings .= 'ssl.engine = "enable"' . "\n";
$ssl_settings .= 'ssl.use-compression = "disable"' . "\n";
@@ -583,7 +585,7 @@ class Lighttpd extends HttpConfigBase
}
$ssl_settings .= 'ssl.use-sslv2 = "disable"' . "\n";
$ssl_settings .= 'ssl.use-sslv3 = "disable"' . "\n";
$ssl_settings .= 'ssl.cipher-list = "' . Settings::Get('system.ssl_cipher_list') . '"' . "\n";
$ssl_settings .= 'ssl.cipher-list = "' . $ssl_cipher_list . '"' . "\n";
$ssl_settings .= 'ssl.honor-cipher-order = "enable"' . "\n";
$ssl_settings .= 'ssl.pemfile = "' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_file']) . '"' . "\n";

View File

@@ -285,7 +285,7 @@ class Nginx extends HttpConfigBase
if (! $is_redirect) {
$this->nginx_data[$vhost_filename] .= "\tlocation ~ \.php {\n";
$this->nginx_data[$vhost_filename] .= "\t\tfastcgi_split_path_info ^(.+\.php)(/.+)\$;\n";
$this->nginx_data[$vhost_filename] .= "\t\tfastcgi_split_path_info ^(.+?\.php)(/.*)$;\n";
$this->nginx_data[$vhost_filename] .= "\t\tinclude " . Settings::Get('nginx.fastcgiparams') . ";\n";
$this->nginx_data[$vhost_filename] .= "\t\tfastcgi_param SCRIPT_FILENAME \$request_filename;\n";
$this->nginx_data[$vhost_filename] .= "\t\tfastcgi_param PATH_INFO \$fastcgi_path_info;\n";
@@ -537,7 +537,7 @@ class Nginx extends HttpConfigBase
}
if ($domain['ssl_specialsettings'] != '' && $ssl_vhost == true) {
$vhost_content .= $this->processSpecialConfigTemplate($domain['ssl_specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
$vhost_content = $this->mergeVhostCustom($vhost_content, $this->processSpecialConfigTemplate($domain['ssl_specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost));
}
if ($_vhost_content != '') {
@@ -549,7 +549,7 @@ class Nginx extends HttpConfigBase
}
if (Settings::Get('system.default_sslvhostconf') != '' && $ssl_vhost == true) {
$vhost_content .= $this->processSpecialConfigTemplate(Settings::Get('system.default_sslvhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
$vhost_content = $this->mergeVhostCustom($vhost_content, $this->processSpecialConfigTemplate(Settings::Get('system.default_sslvhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n");
}
}
}
@@ -562,6 +562,8 @@ class Nginx extends HttpConfigBase
{
// Remove windows linebreaks
$vhost = str_replace("\r", "\n", $vhost);
// remove comments
$vhost = implode("\n", preg_replace('/^(\s+)?#(.*)$/', '', explode("\n", $vhost)));
// Break blocks into lines
$vhost = str_replace(array(
"{",
@@ -678,10 +680,14 @@ class Nginx extends HttpConfigBase
if (! file_exists($domain_or_ip['ssl_cert_file'])) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $domain_or_ip['domain'] . ' :: certificate file "' . $domain_or_ip['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives');
} else {
$ssl_protocols = (isset($domain_or_ip['override_tls']) && $domain_or_ip['override_tls'] == '1' && ! 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']) && $domain_or_ip['override_tls'] == '1' && ! empty($domain_or_ip['ssl_cipher_list'])) ? $domain_or_ip['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list');
// obsolete: ssl on now belongs to the listen block as 'ssl' at the end
// $sslsettings .= "\t" . 'ssl on;' . "\n";
$sslsettings .= "\t" . 'ssl_protocols ' . str_replace(",", " ", Settings::Get('system.ssl_protocols')) . ';' . "\n";
$sslsettings .= "\t" . 'ssl_ciphers ' . Settings::Get('system.ssl_cipher_list') . ';' . "\n";
$sslsettings .= "\t" . 'ssl_protocols ' . str_replace(",", " ", $ssl_protocols) . ';' . "\n";
$sslsettings .= "\t" . 'ssl_ciphers ' . $ssl_cipher_list . ';' . "\n";
if (! empty(Settings::Get('system.dhparams_file'))) {
$dhparams = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.dhparams_file'));
if (! file_exists($dhparams)) {
@@ -951,7 +957,7 @@ class Nginx extends HttpConfigBase
$phpopts .= "\t" . '}' . "\n\n";
$phpopts .= "\tlocation @php {\n";
$phpopts .= "\t\tfastcgi_split_path_info ^(.+\.php)(/.+)\$;\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";

View File

@@ -37,7 +37,7 @@ class NginxFcgi extends Nginx
$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_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";
if ($domain['ssl'] == '1' && $ssl_vhost) {

View File

@@ -36,9 +36,7 @@ class WebserverBase
`d`.`phpsettingid`, `c`.`adminid`, `c`.`guid`, `c`.`email`,
`c`.`documentroot` AS `customerroot`, `c`.`deactivated`,
`c`.`phpenabled` AS `phpenabled_customer`,
`d`.`phpenabled` AS `phpenabled_vhost`,
`d`.`mod_fcgid_starter`,`d`.`mod_fcgid_maxrequests`,
`d`.`ocsp_stapling`
`d`.`phpenabled` AS `phpenabled_vhost`
FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`)

View File

@@ -418,17 +418,18 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
// We do not want to set a quota for root by accident
if ($row['guid'] != 0) {
$used_quota = isset($usedquota[$row['guid']]) ? $usedquota[$row['guid']]['block']['hard'] : 0;
// The user has no quota in Froxlor, but on the filesystem
if (($row['diskspace'] == 0 || $row['diskspace'] == - 1024) && $usedquota[$row['guid']]['block']['hard'] != 0) {
if (($row['diskspace'] == 0 || $row['diskspace'] == - 1024) && $used_quota != 0) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Disabling quota for " . $row['loginname']);
if (\Froxlor\FileDir::isFreeBSD()) {
\Froxlor\FileDir::safe_exec(Settings::Get('system.diskquota_quotatool_path') . " -e " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')) . ":0:0 " . $row['guid']);
} else {
\Froxlor\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'] != $usedquota[$row['guid']]['block']['hard'] && $row['diskspace'] != - 1024) {
} elseif ($row['diskspace'] != $used_quota && $row['diskspace'] != - 1024) {
// The user quota in Froxlor is different than on the filesystem
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Setting quota for " . $row['loginname'] . " from " . $usedquota[$row['guid']]['block']['hard'] . " to " . $row['diskspace']);
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Setting quota for " . $row['loginname'] . " from " . $used_quota . " to " . $row['diskspace']);
if (\Froxlor\FileDir::isFreeBSD()) {
\Froxlor\FileDir::safe_exec(Settings::Get('system.diskquota_quotatool_path') . " -e " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')) . ":" . $row['diskspace'] . ":" . $row['diskspace'] . " " . $row['guid']);
} else {

View File

@@ -78,36 +78,35 @@ class DbManagerMySQL
public function grantPrivilegesTo($username = null, $password = null, $access_host = null, $p_encrypted = false, $update = false)
{
if (! $update) {
// mysql8 compatibility
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '8.0.11', '>=')) {
// create user
// create user
if ($p_encrypted) {
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) {
$stmt = Database::prepare("
CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY PASSWORD :password
");
} else {
$stmt = Database::prepare("
CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED WITH mysql_native_password AS :password
");
}
} else {
$stmt = Database::prepare("
CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY :password
");
Database::pexecute($stmt, array(
"password" => $password
));
// grant privileges
$stmt = Database::prepare("
GRANT ALL ON `" . $username . "`.* TO :username@:host
");
Database::pexecute($stmt, array(
"username" => $username,
"host" => $access_host
));
} else {
// grant privileges
$stmt = Database::prepare("
GRANT ALL PRIVILEGES ON `" . $username . "`.* TO :username@:host IDENTIFIED BY :password
");
Database::pexecute($stmt, array(
"username" => $username,
"host" => $access_host,
"password" => $password
));
}
Database::pexecute($stmt, array(
"password" => $password
));
// grant privileges
$stmt = Database::prepare("
GRANT ALL ON `" . $username . "`.* TO :username@:host
");
Database::pexecute($stmt, array(
"username" => $username,
"host" => $access_host
));
} else {
// set passoword
// set password
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.6', '<')) {
if ($p_encrypted) {
$stmt = Database::prepare("SET PASSWORD FOR :username@:host = :password");
@@ -115,7 +114,11 @@ class DbManagerMySQL
$stmt = Database::prepare("SET PASSWORD FOR :username@:host = PASSWORD(:password)");
}
} else {
$stmt = Database::prepare("ALTER USER :username@:host IDENTIFIED BY :password");
if ($p_encrypted) {
$stmt = Database::prepare("ALTER USER :username@:host IDENTIFIED WITH mysql_native_password AS :password");
} else {
$stmt = Database::prepare("ALTER USER :username@:host IDENTIFIED BY :password");
}
}
Database::pexecute($stmt, array(
"username" => $username,
@@ -158,7 +161,6 @@ class DbManagerMySQL
), false);
}
$drop_stmt = Database::prepare("DROP DATABASE IF EXISTS `" . $dbname . "`");
Database::pexecute($drop_stmt);
}
@@ -247,7 +249,7 @@ class DbManagerMySQL
if ($user_only == false) {
if (! isset($allsqlusers[$row['User']]) || ! is_array($allsqlusers[$row['User']])) {
$allsqlusers[$row['User']] = array(
'password' => $row['Password'],
'password' => $row['Password'] ?? $row['authentication_string'],
'hosts' => array()
);
}

View File

@@ -7,10 +7,10 @@ final class Froxlor
{
// Main version variable
const VERSION = '0.10.2';
const VERSION = '0.10.7';
// Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '201910120';
const DBVERSION = '201911220';
// Distribution branding-tag (used for Debian etc.)
const BRANDING = '';

View File

@@ -87,6 +87,9 @@ class FroxlorLogger
self::$ml->pushHandler(new SyslogHandler('froxlor', LOG_USER, Logger::DEBUG));
break;
case 'file':
if (empty(Settings::Get('logger.logfile')) || ! is_writeable(Settings::Get('logger.logfile'))) {
Settings::Set('logger.logfile', '/tmp/froxlor.log');
}
self::$ml->pushHandler(new StreamHandler(Settings::Get('logger.logfile'), Logger::DEBUG));
break;
case 'mysql':

View File

@@ -4,6 +4,36 @@ namespace Froxlor;
class PhpHelper
{
private static $sort_key = 'id';
private static $sort_type = SORT_STRING;
/**
* sort an array by either natural or string sort and a given index where the value for comparison is found
*
* @param array $list
* @param string $key
*
* @return boolean
*/
public static function sortListBy(&$list, $key = 'id')
{
self::$sort_type = Settings::Get('panel.natsorting') == 1 ? SORT_NATURAL : SORT_STRING;
self::$sort_key = $key;
return usort($list, array(
'self',
'sortListByGivenKey'
));
}
private static function sortListByGivenKey($a, $b)
{
if (self::$sort_type == SORT_NATURAL) {
return strnatcasecmp($a[self::$sort_key], $b[self::$sort_key]);
}
return strcasecmp($a[self::$sort_key], $b[self::$sort_key]);
}
/**
* Wrapper around htmlentities to handle arrays, with the advantage that you
* can select which fields should be handled by htmlentities

View File

@@ -252,6 +252,28 @@ class Store
public static function storeSettingMysqlAccessHost($fieldname, $fielddata, $newfieldvalue)
{
$ips = $newfieldvalue;
// Convert cidr to netmask for mysql, if needed be
if (strpos($ips, ',') !== false) {
$ips = explode(',', $ips);
}
if (is_array($ips) && count($ips) > 0) {
$newfieldvalue = [];
foreach ($ips as $ip) {
$org_ip = $ip;
$ip_cidr = explode("/", $ip);
if (count($ip_cidr) === 2) {
$ip = $ip_cidr[0];
if (strlen($ip_cidr[1]) <= 2) {
$ip_cidr[1] = \Froxlor\Validate\Validate::cidr2NetmaskAddr($org_ip);
}
$newfieldvalue[] = $ip . '/' . $ip_cidr[1];
} else {
$newfieldvalue[] = $org_ip;
}
}
$newfieldvalue = implode(',', $newfieldvalue);
}
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'mysql_access_host') {

View File

@@ -0,0 +1,321 @@
<?php
namespace Froxlor\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 API
* @since 0.10.0
*
*/
/**
* Class to manage pagination, limiting and ordering
*/
class Pagination
{
private $data = array();
private $fields = null;
public $sortorder = 'ASC';
public $sortfield = null;
private $searchtext = null;
private $searchfield = null;
private $is_search = false;
private $pageno = 0;
private $entries = 0;
/**
* Create new pagination object to search/filter, limit and sort Api-listing() calls
*
* @param array $userinfo
* @param array $fields
* @param number $total_entries
*/
public function __construct($userinfo, $fields = array(), $total_entries = 0)
{
$this->fields = $fields;
$this->entries = $total_entries;
$this->pageno = 1;
// add default limitation by settings
$this->addLimit(\Froxlor\Settings::Get('panel.paging'));
// check search request
$this->searchtext = '';
if (count($fields) > 0) {
$orderfields = array_keys($fields);
$this->searchfield = $orderfields[0];
}
if (isset($_REQUEST['searchtext']) && (preg_match('/[-_@\p{L}\p{N}*.]+$/u', $_REQUEST['searchtext']) || $_REQUEST['searchtext'] === '')) {
$this->searchtext = trim($_REQUEST['searchtext']);
}
if (isset($_REQUEST['searchfield']) && isset($fields[$_REQUEST['searchfield']])) {
$this->searchfield = $_REQUEST['searchfield'];
}
if (! empty($this->searchtext) && ! empty($this->searchfield)) {
$this->addSearch($this->searchtext, $this->searchfield);
}
// check other ordering requests
if (isset($_REQUEST['sortorder']) && (strtolower($_REQUEST['sortorder']) == 'desc' || strtolower($_REQUEST['sortorder']) == 'asc')) {
$this->sortorder = strtoupper($_REQUEST['sortorder']);
}
if (isset($_REQUEST['sortfield']) && isset($fields[$_REQUEST['sortfield']])) {
$this->sortfield = $_REQUEST['sortfield'];
$this->addOrderBy($this->sortfield, $this->sortorder);
} else {
// add default ordering by given fields
if (count($fields) > 0) {
$orderfields = array_keys($fields);
$this->sortfield = $orderfields[0];
$this->addOrderBy($orderfields[0], $this->sortorder);
}
}
// check current page / pages
if (isset($_REQUEST['pageno']) && intval($_REQUEST['pageno']) != 0) {
$this->pageno = intval($_REQUEST['pageno']);
}
if (($this->pageno - 1) * \Froxlor\Settings::Get('panel.paging') > $this->entries) {
$this->pageno = 1;
}
$this->addOffset(($this->pageno - 1) * \Froxlor\Settings::Get('panel.paging'));
}
/**
* add a field for ordering
*
* @param string $field
* @param string $order
* optional, default 'ASC'
*
* @return \Froxlor\UI\Pagination
*/
public function addOrderBy($field = null, $order = 'ASC')
{
if (! isset($this->data['sql_orderby'])) {
$this->data['sql_orderby'] = array();
}
$this->data['sql_orderby'][$field] = $order;
return $this;
}
/**
* add a limit
*
* @param number $limit
* optional, default 0
*
* @return \Froxlor\UI\Pagination
*/
public function addLimit($limit = 0)
{
$this->data['sql_limit'] = (int) $limit;
return $this;
}
/**
* add an offset
*
* @param number $offset
* optional, default 0
*
* @return \Froxlor\UI\Pagination
*/
public function addOffset($offset = 0)
{
$this->data['sql_offset'] = (int) $offset;
return $this;
}
/**
* add a search operation
*
* @param string $searchtext
* @param string $field
* @param string $operator
*
* @return \Froxlor\UI\Pagination
*/
public function addSearch($searchtext = null, $field = null, $operator = null)
{
if (! isset($this->data['sql_search'])) {
$this->data['sql_search'] = array();
}
$this->data['sql_search'][$field] = [
'value' => $searchtext,
'op' => $operator
];
// if a search is performed, the result-entries-count is irrelevant
// we do not want pagination
$this->is_search = true;
return $this;
}
/**
* return number of total entries the user can access from the current resource
*
* @return number
*/
public function getEntries()
{
return $this->entries;
}
/**
* Returns html code for sorting field
*
* @param array $lng
* Language array
* @return string the html sortcode
*/
public function getHtmlSortCode($lng, $break = false)
{
$sortcode = '';
$fieldoptions = '';
$orderoptions = '';
foreach ($this->fields as $fieldname => $fieldcaption) {
$fieldoptions .= HTML::makeoption($fieldcaption, $fieldname, $this->sortfield, true, true);
}
$breakorws = ($break ? '<br />' : '&nbsp;');
foreach (array(
'asc' => $lng['panel']['ascending'],
'desc' => $lng['panel']['descending']
) as $sortordertype => $sortorderdescription) {
$orderoptions .= HTML::makeoption($sortorderdescription, $sortordertype, $this->sortorder, true, true);
}
eval("\$sortcode =\"" . Template::getTemplate("misc/htmlsortcode", '1') . "\";");
return $sortcode;
}
/**
* Returns html code for sorting arrows
*
* @param string $baseurl
* URL to use as base for links
* @param string $field
* If set, only this field will be returned
*
* @return mixed An array or a string (if field is set) of html code of arrows
*/
public function getHtmlArrowCode($baseurl, $field = '')
{
global $theme;
if ($field != '' && isset($this->fields[$field])) {
$baseurl = htmlspecialchars($baseurl);
$fieldname = htmlspecialchars($field);
eval("\$arrowcode =\"" . Template::getTemplate("misc/htmlarrowcode", '1') . "\";");
} else {
$baseurl = htmlspecialchars($baseurl);
$arrowcode = array();
foreach ($this->fields as $fieldname => $fieldcaption) {
$fieldname = htmlspecialchars($fieldname);
eval("\$arrowcode[\$fieldname] =\"" . Template::getTemplate("misc/htmlarrowcode", '1') . "\";");
}
}
return $arrowcode;
}
/**
* Returns html code for searching field
*
* @param array $lng
* Language array
*
* @return string the html searchcode
*/
public function getHtmlSearchCode($lng)
{
$searchcode = '';
$fieldoptions = '';
$searchtext = htmlspecialchars($this->searchtext);
foreach ($this->fields as $fieldname => $fieldcaption) {
$fieldoptions .= HTML::makeoption($fieldcaption, $fieldname, $this->searchfield, true, true);
}
eval("\$searchcode =\"" . Template::getTemplate("misc/htmlsearchcode", '1') . "\";");
return $searchcode;
}
/**
* Returns html code for paging
*
* @param string $baseurl
* URL to use as base for links
*
* @return string the html pagingcode
*/
public function getHtmlPagingCode($baseurl)
{
if (\Froxlor\Settings::Get('panel.paging') == 0 || $this->is_search) {
return '';
} else {
$pages = intval($this->getEntries() / \Froxlor\Settings::Get('panel.paging'));
}
if ($this->getEntries() % \Froxlor\Settings::Get('panel.paging') != 0) {
$pages ++;
}
if ($pages > 1) {
$start = $this->pageno - 4;
if ($start < 1) {
$start = 1;
}
$stop = $this->pageno + 4;
if ($stop > $pages) {
$stop = $pages;
}
// check for possible sorting values and keep it
$orderstr = '';
if (!empty($this->sortfield)) {
$fieldname = htmlspecialchars($this->sortfield);
$orderstr .= '&amp;sortfield=' . $fieldname . '&amp;sortorder=' . $this->sortorder;
}
$pagingcode = '<a href="' . htmlspecialchars($baseurl) . '&amp;pageno=1' . $orderstr . '">&laquo;</a> <a href="' . htmlspecialchars($baseurl) . '&amp;pageno=' . ((intval($this->pageno) - 1) == 0 ? '1' : intval($this->pageno) - 1) . $orderstr . '">&lt;</a>&nbsp;';
for ($i = $start; $i <= $stop; $i ++) {
if ($i != $this->pageno) {
$pagingcode .= ' <a href="' . htmlspecialchars($baseurl) . '&amp;pageno=' . $i . $orderstr . '">' . $i . '</a>&nbsp;';
} else {
$pagingcode .= ' <strong>' . $i . '</strong>&nbsp;';
}
}
$pagingcode .= ' <a href="' . htmlspecialchars($baseurl) . '&amp;pageno=' . ((intval($this->pageno) + 1) > $pages ? $pages : intval($this->pageno) + 1) . $orderstr . '">&gt;</a> <a href="' . $baseurl . '&amp;pageno=' . $pages . $orderstr . '">&raquo;</a>';
} else {
$pagingcode = '';
}
return $pagingcode;
}
/**
* return parameter array for API command parameters $sql_search, $sql_limit, $sql_offset and $sql_orderby
*
* @return array
*/
public function getApiCommandParams()
{
return $this->data;
}
}

View File

@@ -77,8 +77,7 @@ class Check
$mysql_access_host_array = array_map('trim', explode(',', $newfieldvalue));
foreach ($mysql_access_host_array as $host_entry) {
if (Validate::validate_ip2($host_entry, true, 'invalidip', true, true) == false && Validate::validateDomain($host_entry) == false && Validate::validateLocalHostname($host_entry) == false && $host_entry != '%') {
if (Validate::validate_ip2($host_entry, true, 'invalidip', true, true, true, true, false) == false && Validate::validateDomain($host_entry) == false && Validate::validateLocalHostname($host_entry) == false && $host_entry != '%') {
return array(
self::FORMFIELDS_PLAUSIBILITY_CHECK_ERROR,
'invalidmysqlhost',

View File

@@ -62,6 +62,38 @@ class Validate
\Froxlor\UI\Response::standard_error($lng, $fieldname, $throw_exception);
}
/**
* Converts CIDR to a netmask address
*
* @thx to https://stackoverflow.com/a/5711080/3020926
* @param string $cidr
*
* @return string
*/
public static function cidr2NetmaskAddr($cidr)
{
$ta = substr($cidr, strpos($cidr, '/') + 1) * 1;
$netmask = str_split(str_pad(str_pad('', $ta, '1'), 32, '0'), 8);
foreach ($netmask as &$element) {
$element = bindec($element);
}
return implode('.', $netmask);
}
/**
* Checks if an $address (IP) is IPv6
*
* @param string $address
*
* @return string|bool ip address on success, false on failure
*/
public static function is_ipv6($address)
{
return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
}
/**
* Checks whether it is a valid ip
*
@@ -77,17 +109,35 @@ class Validate
* whether to allow private network addresses
* @param bool $allow_cidr
* whether to allow CIDR values e.g. 10.10.10.10/16
* @param bool $cidr_as_netmask
* whether to format CIDR nodation to netmask notation
* @param bool $throw_exception
* whether to throw an exception on failure
*
* @return string|bool ip address on success, false on failure
*/
public static function validate_ip2($ip, $return_bool = false, $lng = 'invalidip', $allow_localhost = false, $allow_priv = false, $allow_cidr = false, $throw_exception = false)
public static function validate_ip2($ip, $return_bool = false, $lng = 'invalidip', $allow_localhost = false, $allow_priv = false, $allow_cidr = false, $cidr_as_netmask = false, $throw_exception = false)
{
$cidr = "";
if ($allow_cidr) {
$org_ip = $ip;
$ip_cidr = explode("/", $ip);
if (count($ip_cidr) == 2) {
if (count($ip_cidr) === 2) {
if (strlen($ip_cidr[1]) <= 2 && in_array((int) $ip_cidr[1], array_values(range(1, 32)), true) === false) {
\Froxlor\UI\Response::standard_error($lng, $ip, $throw_exception);
}
if ($cidr_as_netmask && self::is_ipv6($ip_cidr[0])) {
// MySQL does not handle CIDR of IPv6 addresses, return error
if ($return_bool) {
return false;
} else {
\Froxlor\UI\Response::standard_error($lng, $ip, $throw_exception);
}
}
$ip = $ip_cidr[0];
if ($cidr_as_netmask && strlen($ip_cidr[1]) <= 2) {
$ip_cidr[1] = self::cidr2NetmaskAddr($org_ip);
}
$cidr = "/" . $ip_cidr[1];
} else {
$ip = $org_ip;

View File

@@ -4629,7 +4629,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
<!-- PHP-FPM -->
<daemon name="php-fpm"
@@ -4667,7 +4667,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
</service>
</services>

View File

@@ -4831,7 +4831,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
<!-- PHP-FPM -->
<daemon name="php-fpm"
@@ -4869,7 +4869,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
</service>
</services>

View File

@@ -3825,7 +3825,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
<!-- PHP-FPM -->
<daemon name="php-fpm"
@@ -3864,7 +3864,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
</service>
</services>

View File

@@ -4724,7 +4724,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
<!-- PHP-FPM -->
<daemon name="php-fpm"
@@ -4768,7 +4768,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
</service>
</services>

View File

@@ -4618,7 +4618,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
<!-- PHP-FPM -->
<daemon name="php-fpm"
@@ -4656,7 +4656,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
</service>
</services>

View File

@@ -1732,7 +1732,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
<!-- PHP-FPM -->
<daemon name="php-fpm"
@@ -1776,7 +1776,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
</service>
</services>

View File

@@ -4629,7 +4629,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
<!-- PHP-FPM -->
<daemon name="php-fpm"
@@ -4667,7 +4667,7 @@ aliases: files
</commands>
<!-- instead of just restarting apache, we let the cronjob do all the
dirty work -->
<command><![CDATA[php {{const.\Froxlor\Froxlor::getInstallDir()}}/scripts/froxlor_master_cronjob.php --force]]></command>
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command>
</daemon>
</service>
</services>

View File

@@ -93,7 +93,7 @@ return array(
)
),
'value' => array(
'1'
(\Froxlor\Settings::Get('api.enabled') == '1' ? '1' : '0')
),
'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
)

View File

@@ -180,6 +180,12 @@ return array(
'image' => 'icons/domain_add.png',
'visible' => \Froxlor\Settings::Get('system.use_ssl') == '1' ? true : false,
'fields' => array(
'no_ssl_available_info' => array(
'visible' => ($ssl_ipsandports == '' ? true : false),
'label' => 'SSL',
'type' => 'label',
'value' => $lng['panel']['nosslipsavailable']
),
'ssl_ipandport' => array(
'label' => $lng['domains']['ipandport_ssl_multi']['title'],
'desc' => $lng['domains']['ipandport_ssl_multi']['description'],
@@ -188,26 +194,6 @@ return array(
'value' => explode(',', \Froxlor\Settings::Get('system.defaultsslip')),
'is_array' => 1
),
'ssl_specialsettings' => array(
'visible' => ($userinfo['change_serversettings'] == '1' ? true : false),
'style' => 'align-top',
'label' => $lng['admin']['ownsslvhostsettings'],
'desc' => $lng['serversettings']['default_vhostconf']['description'],
'type' => 'textarea',
'cols' => 60,
'rows' => 12
),
'include_specialsettings' => array(
'label' => $lng['admin']['include_ownvhostsettings'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array()
),
'ssl_redirect' => array(
'visible' => ($ssl_ipsandports != '' ? true : false),
'label' => $lng['domains']['ssl_redirect']['title'],
@@ -247,11 +233,81 @@ return array(
),
'value' => array()
),
'no_ssl_available_info' => array(
'visible' => ($ssl_ipsandports == '' ? true : false),
'label' => 'SSL',
'type' => 'label',
'value' => $lng['panel']['nosslipsavailable']
'override_tls' => array(
'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' ? true : false),
'label' => $lng['admin']['domain_override_tls'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array()
),
'ssl_protocols' => array(
'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' ? true : false),
'label' => $lng['serversettings']['ssl']['ssl_protocols']['title'],
'desc' => $lng['serversettings']['ssl']['ssl_protocols']['description'],
'type' => 'checkbox',
'value' => array(
'TLSv1',
'TLSv1.2'
),
'values' => array(
array(
'value' => 'TLSv1',
'label' => 'TLSv1<br />'
),
array(
'value' => 'TLSv1.1',
'label' => 'TLSv1.1<br />'
),
array(
'value' => 'TLSv1.2',
'label' => 'TLSv1.2<br />'
),
array(
'value' => 'TLSv1.3',
'label' => 'TLSv1.3<br />'
)
),
'is_array' => 1
),
'ssl_cipher_list' => array(
'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' ? true : false),
'label' => $lng['serversettings']['ssl']['ssl_cipher_list']['title'],
'desc' => $lng['serversettings']['ssl']['ssl_cipher_list']['description'],
'type' => 'text',
'value' => \Froxlor\Settings::Get('system.ssl_cipher_list')
),
'tlsv13_cipher_list' => array(
'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' && \Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1 ? true : false),
'label' => $lng['serversettings']['ssl']['tlsv13_cipher_list']['title'],
'desc' => $lng['serversettings']['ssl']['tlsv13_cipher_list']['description'],
'type' => 'text',
'value' => \Froxlor\Settings::Get('system.tlsv13_cipher_list')
),
'ssl_specialsettings' => array(
'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' ? true : false),
'style' => 'align-top',
'label' => $lng['admin']['ownsslvhostsettings'],
'desc' => $lng['serversettings']['default_vhostconf']['description'],
'type' => 'textarea',
'cols' => 60,
'rows' => 12
),
'include_specialsettings' => array(
'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' ? true : false),
'label' => $lng['admin']['include_ownvhostsettings'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array()
),
'hsts_maxage' => array(
'visible' => ($ssl_ipsandports != '' ? true : false),

View File

@@ -159,7 +159,7 @@ return array(
)
),
'value' => array(
'1'
\Froxlor\Settings::Get('system.apply_specialsettings_default') == 1 ? '1' : ''
)
),
'notryfiles' => array(
@@ -212,6 +212,12 @@ return array(
'image' => 'icons/domain_edit.png',
'visible' => \Froxlor\Settings::Get('system.use_ssl') == '1' ? true : false,
'fields' => array(
'no_ssl_available_info' => array(
'visible' => ($ssl_ipsandports == '' ? true : false),
'label' => 'SSL',
'type' => 'label',
'value' => $lng['panel']['nosslipsavailable']
),
'ssl_ipandport' => array(
'label' => $lng['domains']['ipandport_ssl_multi']['title'],
'desc' => $lng['domains']['ipandport_ssl_multi']['description'],
@@ -220,29 +226,6 @@ return array(
'value' => $usedips,
'is_array' => 1
),
'ssl_specialsettings' => array(
'visible' => ($userinfo['change_serversettings'] == '1' ? true : false),
'style' => 'align-top',
'label' => $lng['admin']['ownsslvhostsettings'],
'desc' => $lng['serversettings']['default_vhostconf']['description'],
'type' => 'textarea',
'cols' => 60,
'rows' => 12,
'value' => $result['ssl_specialsettings']
),
'include_specialsettings' => array(
'label' => $lng['admin']['include_ownvhostsettings'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
$result['include_specialsettings']
)
),
'ssl_redirect' => array(
'visible' => ($ssl_ipsandports != '' ? true : false),
'label' => $lng['domains']['ssl_redirect']['title'],
@@ -288,11 +271,82 @@ return array(
$result['http2']
)
),
'no_ssl_available_info' => array(
'visible' => ($ssl_ipsandports == '' ? true : false),
'label' => 'SSL',
'type' => 'label',
'value' => $lng['panel']['nosslipsavailable']
'override_tls' => array(
'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' ? true : false),
'label' => $lng['admin']['domain_override_tls'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
$result['override_tls']
)
),
'ssl_protocols' => array(
'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' ? true : false),
'label' => $lng['serversettings']['ssl']['ssl_protocols']['title'],
'desc' => $lng['serversettings']['ssl']['ssl_protocols']['description'],
'type' => 'checkbox',
'value' => !empty($result['ssl_protocols']) ? explode(",", $result['ssl_protocols']) : explode(",", \Froxlor\Settings::Get('system.ssl_protocols')),
'values' => array(
array(
'value' => 'TLSv1',
'label' => 'TLSv1<br />'
),
array(
'value' => 'TLSv1.1',
'label' => 'TLSv1.1<br />'
),
array(
'value' => 'TLSv1.2',
'label' => 'TLSv1.2<br />'
),
array(
'value' => 'TLSv1.3',
'label' => 'TLSv1.3<br />'
)
),
'is_array' => 1
),
'ssl_cipher_list' => array(
'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' ? true : false),
'label' => $lng['serversettings']['ssl']['ssl_cipher_list']['title'],
'desc' => $lng['serversettings']['ssl']['ssl_cipher_list']['description'],
'type' => 'text',
'value' => !empty($result['ssl_cipher_list']) ? $result['ssl_cipher_list'] : \Froxlor\Settings::Get('system.ssl_cipher_list')
),
'tlsv13_cipher_list' => array(
'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' && \Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1 ? true : false),
'label' => $lng['serversettings']['ssl']['tlsv13_cipher_list']['title'],
'desc' => $lng['serversettings']['ssl']['tlsv13_cipher_list']['description'],
'type' => 'text',
'value' => !empty($result['tlsv13_cipher_list']) ? $result['tlsv13_cipher_list'] : \Froxlor\Settings::Get('system.tlsv13_cipher_list')
),
'ssl_specialsettings' => array(
'visible' => ($userinfo['change_serversettings'] == '1' ? true : false),
'style' => 'align-top',
'label' => $lng['admin']['ownsslvhostsettings'],
'desc' => $lng['serversettings']['default_vhostconf']['description'],
'type' => 'textarea',
'cols' => 60,
'rows' => 12,
'value' => $result['ssl_specialsettings']
),
'include_specialsettings' => array(
'label' => $lng['admin']['include_ownvhostsettings'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
$result['include_specialsettings']
)
),
'hsts_maxage' => array(
'visible' => ($ssl_ipsandports != '' ? true : false),
@@ -399,7 +453,7 @@ return array(
)
),
'value' => array(
'1'
\Froxlor\Settings::Get('system.apply_phpconfigs_default') == 1 ? '1' : ''
)
),
'mod_fcgid_starter' => array(

View File

@@ -569,7 +569,7 @@ $lng['serversettings']['apacheconf_htpasswddir']['description'] = 'Where should
$lng['error']['formtokencompromised'] = 'The request seems to be compromised. For security reasons you were logged out.';
$lng['serversettings']['mysql_access_host']['title'] = 'MySQL-Access-Hosts';
$lng['serversettings']['mysql_access_host']['description'] = 'A comma separated list of hosts from which users should be allowed to connect to the MySQL-Server.';
$lng['serversettings']['mysql_access_host']['description'] = 'A comma separated list of hosts from which users should be allowed to connect to the MySQL-Server. To allow a subnet the netmask or cidr syntax is valid.';
// ADDED IN 1.2.18-svn1
@@ -1853,7 +1853,7 @@ $lng['domains']['ssl_redirect_temporarilydisabled'] = "<br>The SSL redirect is t
$lng['serversettings']['caa_entry']['title'] = 'Generate CAA DNS records';
$lng['serversettings']['caa_entry']['description'] = 'Automatically generates CAA records for SSL-enabled domains that are using Let\'s Encrypt';
$lng['serversettings']['caa_entry_custom']['title'] = 'Additional CAA DNS records';
$lng['serversettings']['caa_entry_custom']['description'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities<br>whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record.<br><br>The content of this field will be included into the DNS zone directly (each line results in a CAA record).<br>If Let\'s Encrypt is enabled for this domain, this entry will always be added automatically and does not need to be added manually:<br><code>0 issue "letsencrypt.org"</code> (If domain is a wildcard domain, issuewild will be used instead).<br>To enable Incident Reporting, you can add an <code>iodef</code> record. An example for sending such report to <code>me@example.com</code> would be:<br><code>0 iodef "mailto:me@example.com"</code><br><br><strong>Attention:</strong> The code won\'t be checked for any errors. If it contains errors, your CAA records might not work!';
$lng['serversettings']['caa_entry_custom']['description'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities<br>whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record.<br><br>The content of this field will be included into the DNS zone directly (each line results in a CAA record).<br>If Let\'s Encrypt is enabled for this domain, this entry will always be added automatically and does not need to be added manually:<br><code>0 issue "letsencrypt.org"</code> (If domain is a wildcard domain, issuewild will be used instead).<br>To enable Incident Reporting, you can add an <code>iodef</code> record. An example for sending such report to <code>me@example.com</code> would be:<br><code>0 iodef "mailto:me@example.com"</code><br><br><strong>Attention:</strong> The code won\'t be checked for any errors. If it contains errors, your CAA records might not work!';
// Autoupdate
$lng['admin']['autoupdate'] = 'Auto-Update';
@@ -2078,3 +2078,7 @@ $lng['serversettings']['includedefault_sslvhostconf'] = 'Include non-SSL vHost-s
$lng['admin']['ownsslvhostsettings'] = 'Own SSL vHost-settings';
$lng['admin']['ipsandports']['ssl_default_vhostconf_domain'] = 'Default SSL vHost-settings for every domain container';
$lng['customer']['total_diskspace'] = 'Total diskspace (MiB)';
$lng['admin']['domain_override_tls'] = 'Override system TLS settings';
$lng['domains']['isaliasdomainof'] = 'Is aliasdomain for %s';
$lng['serversettings']['apply_specialsettings_default']['title'] = 'Default value for "' . $lng['admin']['specialsettingsforsubdomains'] . "' setting when editing a domain";
$lng['serversettings']['apply_phpconfigs_default']['title'] = 'Default value for "' . $lng['admin']['phpsettingsforsubdomains'] . "' setting when editing a domain";

View File

@@ -564,7 +564,7 @@ $lng['serversettings']['apacheconf_htpasswddir']['description'] = 'Wo sollen die
$lng['error']['formtokencompromised'] = 'Das Formular scheint manipuliert worden zu sein. Aus Sicherheitsgründen wurden Sie ausgelogged.';
$lng['serversettings']['mysql_access_host']['title'] = 'MySQL-Access-Hosts';
$lng['serversettings']['mysql_access_host']['description'] = 'Eine durch Komma getrennte Liste mit den Hostnamen aller Hostnames/IP-Adressen, von denen sich die Benutzer einloggen dürfen.';
$lng['serversettings']['mysql_access_host']['description'] = 'Eine durch Komma getrennte Liste mit den Hostnamen aller Hostnames/IP-Adressen, von denen sich die Benutzer einloggen dürfen. Um ein Subnetz zu erlauben ist die Netzmaske oder CIDR Syntax erlaubt.';
// ADDED IN 1.2.18-svn1
@@ -1725,3 +1725,7 @@ $lng['serversettings']['includedefault_sslvhostconf'] = 'Nicht-SSL vHost-Einstel
$lng['admin']['ownsslvhostsettings'] = 'Eigene SSL vHost-Einstellungen';
$lng['admin']['ipsandports']['ssl_default_vhostconf_domain'] = 'Standard SSL vHost-Einstellungen für jeden Domain-Container';
$lng['customer']['total_diskspace'] = 'Gesamtspeicherplatz (MiB)';
$lng['admin']['domain_override_tls'] = 'Überschreibe System TLS Einstellungen';
$lng['domains']['isaliasdomainof'] = 'Ist Aliasdomain für %s';
$lng['serversettings']['apply_specialsettings_default']['title'] = 'Standardwert für "' . $lng['admin']['specialsettingsforsubdomains'] . "' Einstellung beim Bearbeiten einer Domain";
$lng['serversettings']['apply_phpconfigs_default']['title'] = 'Standardwert für "' . $lng['admin']['phpsettingsforsubdomains'] . "' Einstellung beim Bearbeiten einer Domain";

View File

@@ -19,7 +19,6 @@ if (! defined('AREA')) {
*
*/
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Api\Commands\Certificates as Certificates;
@@ -47,35 +46,20 @@ $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed domains:
$fields = array(
'd.domain' => $lng['domains']['domainname']
);
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_DOMAIN_SSL_SETTINGS, $fields);
// select all my (accessable) certificates
$certs_stmt_query = "SELECT s.*, d.domain, d.letsencrypt, c.customerid, c.loginname
FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON `d`.`id` = `s`.`domainid`
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` c ON `c`.`customerid` = `d`.`customerid`
WHERE ";
$qry_params = array();
if (AREA == 'admin' && $userinfo['customers_see_all'] == '0') {
// admin with only customer-specific permissions
$certs_stmt_query .= "d.adminid = :adminid ";
$qry_params['adminid'] = $userinfo['adminid'];
} elseif (AREA == 'customer') {
// customer-area
$certs_stmt_query .= "d.customerid = :cid ";
$qry_params['cid'] = $userinfo['customerid'];
} else {
$certs_stmt_query .= "1 ";
try {
// get total count
$json_result = Certificates::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 = Certificates::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
// sorting by domain-name
$certs_stmt_query .= $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit();
$certs_stmt = Database::prepare($certs_stmt_query);
Database::pexecute($certs_stmt, $qry_params);
$all_certs = $certs_stmt->fetchAll(PDO::FETCH_ASSOC);
$all_certs = $result['list'];
$certificates = "";
if (count($all_certs) == 0) {
@@ -84,83 +68,78 @@ if (count($all_certs) == 0) {
$arrowcode = array(
'd.domain' => ''
);
$searchcode = "";
// keep searching code if something was searched and no results were returned
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = "";
eval("\$certificates.=\"" . \Froxlor\UI\Template::getTemplate("ssl_certificates/certs_error", true) . "\";");
} else {
$paging->setEntries(count($all_certs));
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
foreach ($all_certs as $idx => $cert) {
if ($paging->checkDisplay($idx)) {
// respect froxlor-hostname
if ($cert['domainid'] == 0) {
$cert['domain'] = Settings::Get('system.hostname');
$cert['letsencrypt'] = Settings::Get('system.le_froxlor_enabled');
$cert['loginname'] = 'froxlor.panel';
}
// respect froxlor-hostname
if ($cert['domainid'] == 0) {
$cert['domain'] = Settings::Get('system.hostname');
$cert['letsencrypt'] = Settings::Get('system.le_froxlor_enabled');
$cert['loginname'] = 'froxlor.panel';
if (empty($cert['domain']) || empty($cert['ssl_cert_file'])) {
// no domain found to the entry or empty entry - safely delete it from the DB
try {
Certificates::getLocal($userinfo, array(
'id' => $cert['id']
))->delete();
} catch (Exception $e) {
// do nothing
}
continue;
}
$cert_data = openssl_x509_parse($cert['ssl_cert_file']);
$cert['domain'] = $idna_convert->decode($cert['domain']);
$adminCustomerLink = "";
if (AREA == 'admin' && $cert['domainid'] > 0) {
if (! empty($cert['loginname'])) {
$adminCustomerLink = '&nbsp;(<a href="' . $linker->getLink(array(
'section' => 'customers',
'page' => 'customers',
'action' => 'su',
'id' => $cert['customerid']
)) . '" rel="external">' . $cert['loginname'] . '</a>)';
}
}
if ($cert_data) {
$validFrom = date('d.m.Y H:i:s', $cert_data['validFrom_time_t']);
$validTo = date('d.m.Y H:i:s', $cert_data['validTo_time_t']);
$isValid = true;
if ($cert_data['validTo_time_t'] < time()) {
$isValid = false;
}
if (empty($cert['domain']) || empty($cert['ssl_cert_file'])) {
// no domain found to the entry or empty entry - safely delete it from the DB
try {
Certificates::getLocal($userinfo, array(
'id' => $cert['id']
))->delete();
} catch (Exception $e) {
// do nothing
}
continue;
}
$cert_data = openssl_x509_parse($cert['ssl_cert_file']);
$cert['domain'] = $idna_convert->decode($cert['domain']);
$adminCustomerLink = "";
if (AREA == 'admin' && $cert['domainid'] > 0) {
if (! empty($cert['loginname'])) {
$adminCustomerLink = '&nbsp;(<a href="' . $linker->getLink(array(
'section' => 'customers',
'page' => 'customers',
'action' => 'su',
'id' => $cert['customerid']
)) . '" rel="external">' . $cert['loginname'] . '</a>)';
}
}
if ($cert_data) {
$validFrom = date('d.m.Y H:i:s', $cert_data['validFrom_time_t']);
$validTo = date('d.m.Y H:i:s', $cert_data['validTo_time_t']);
$isValid = true;
if ($cert_data['validTo_time_t'] < time()) {
$isValid = false;
}
$san_list = "";
if (isset($cert_data['extensions']['subjectAltName']) && ! empty($cert_data['extensions']['subjectAltName'])) {
$SANs = explode(",", $cert_data['extensions']['subjectAltName']);
$SANs = array_map('trim', $SANs);
foreach ($SANs as $san) {
$san = str_replace("DNS:", "", $san);
if ($san != $cert_data['subject']['CN'] && strpos($san, "othername:") === false) {
$san_list .= $san . "<br>";
}
$san_list = "";
if (isset($cert_data['extensions']['subjectAltName']) && ! empty($cert_data['extensions']['subjectAltName'])) {
$SANs = explode(",", $cert_data['extensions']['subjectAltName']);
$SANs = array_map('trim', $SANs);
foreach ($SANs as $san) {
$san = str_replace("DNS:", "", $san);
if ($san != $cert_data['subject']['CN'] && strpos($san, "othername:") === false) {
$san_list .= $san . "<br>";
}
}
$row = \Froxlor\PhpHelper::htmlentitiesArray($cert);
eval("\$certificates.=\"" . \Froxlor\UI\Template::getTemplate("ssl_certificates/certs_cert", true) . "\";");
} else {
$message = sprintf($lng['domains']['ssl_certificate_error'], $cert['domain']);
eval("\$certificates.=\"" . \Froxlor\UI\Template::getTemplate("ssl_certificates/certs_error", true) . "\";");
}
$row = \Froxlor\PhpHelper::htmlentitiesArray($cert);
eval("\$certificates.=\"" . \Froxlor\UI\Template::getTemplate("ssl_certificates/certs_cert", true) . "\";");
} else {
continue;
$message = sprintf($lng['domains']['ssl_certificate_error'], $cert['domain']);
eval("\$certificates.=\"" . \Froxlor\UI\Template::getTemplate("ssl_certificates/certs_error", true) . "\";");
}
}
}

View File

@@ -9,7 +9,7 @@ $header
<legend>Froxlor&nbsp;-&nbsp;{$lng['login']['2fa']}</legend>
<p>
<label for="2fa_code">{$lng['login']['2facode']}:</label>&nbsp;
<input type="text" name="2fa_code" id="2fa_code" value="" required/>
<input type="text" name="2fa_code" id="2fa_code" value="" autofocus required/>
</p>
<p class="submit">
<input type="hidden" name="action" value="2fa_verify" />

View File

@@ -41,8 +41,5 @@
</a>
</if>
</if>
<if isset($row['domainaliasid']) && $row['domainaliasid'] != 0>
&nbsp;<a href="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'searchfield' => 'd.aliasdomain', 'searchtext' => $row['id']))}">{$lng['domains']['hasaliasdomains']}</a>
</if>
</td>
</tr>

View File

@@ -156,6 +156,51 @@ class AdminsTest extends TestCase
$json_result = Admins::getLocal($admin_userdata)->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result['count']);
$json_result = Admins::getLocal($admin_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result);
}
public function testAdminAdminsListLimitOffsetOrderSearch()
{
global $admin_userdata;
$json_result = Admins::getLocal($admin_userdata, [
'sql_orderby' => [
'loginname' => 'DESC'
]
])->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result['count']);
$this->assertEquals('reseller', $result['list'][0]['loginname']);
$json_result = Admins::getLocal($admin_userdata, [
'sql_limit' => 1
])->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['count']);
$this->assertEquals('admin', $result['list'][0]['loginname']);
$json_result = Admins::getLocal($admin_userdata, [
'sql_limit' => 1,
'sql_offset' => 1
])->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['count']);
$this->assertEquals('reseller', $result['list'][0]['loginname']);
$json_result = Admins::getLocal($admin_userdata, [
'sql_search' => [
'loginname' => [
'value' => 'adm',
'op' => null /* LIKE */
]
]
])->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['count']);
$this->assertEquals('admin', $result['list'][0]['loginname']);
}
public function testResellerAdminsGet()

View File

@@ -154,6 +154,10 @@ class CustomerBackupsTest extends TestCase
$this->assertEquals('1', $result['list'][0]['data']['backup_dbs']);
$this->assertEquals('1', $result['list'][0]['data']['backup_mail']);
$this->assertEquals('1', $result['list'][0]['data']['backup_web']);
$json_result = CustomerBackups::getLocal($admin_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result);
}
/**

View File

@@ -74,6 +74,10 @@ class CertificatesTest extends TestCase
$json_result = Certificates::getLocal($admin_userdata)->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result['count']);
$json_result = Certificates::getLocal($admin_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result);
}
public function testResellerCertificatesList()
@@ -89,6 +93,10 @@ class CertificatesTest extends TestCase
$json_result = Certificates::getLocal($reseller_userdata)->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result['count']);
$json_result = Certificates::getLocal($reseller_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result);
}
public function testCustomerCertificatesList()
@@ -103,6 +111,10 @@ class CertificatesTest extends TestCase
$json_result = Certificates::getLocal($customer_userdata)->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result['count']);
$json_result = Certificates::getLocal($customer_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result);
}
public function testAdminCertificatesUpdate()
@@ -189,7 +201,6 @@ class CertificatesTest extends TestCase
));
// export
openssl_csr_export($csr, $csrout);
openssl_x509_export($sscert, $certout);
openssl_pkey_export($privkey, $pkeyout, null);

View File

@@ -21,6 +21,10 @@ class CronjobsTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertTrue(isset($result['list'][0]['module']));
$this->assertTrue(isset($result['list'][0]['cronfile']));
$json_result = Cronjobs::getLocal($admin_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(6, $result);
}
public function testCustomerCronjobsListNotAllowed()

View File

@@ -6,6 +6,7 @@ use Froxlor\Database\Database;
use Froxlor\Api\Commands\Admins;
use Froxlor\Api\Commands\Customers;
use Froxlor\Api\Commands\SubDomains;
use Froxlor\Api\Commands\Ftps;
/**
*
@@ -61,7 +62,9 @@ class CustomersTest extends TestCase
$this->assertEquals('secret', $result['custom_notes']);
// validate that the std-subdomain has been added
$json_result = SubDomains::getLocal($admin_userdata, array('id' => $result['standardsubdomain']))->get();
$json_result = SubDomains::getLocal($admin_userdata, array(
'id' => $result['standardsubdomain']
))->get();
$result = json_decode($json_result, true)['data'];
$this->assertEquals('test1.dev.froxlor.org', $result['domain']);
}
@@ -107,6 +110,10 @@ class CustomersTest extends TestCase
$json_result = Customers::getLocal($admin_userdata)->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['count']);
$json_result = Customers::getLocal($admin_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result);
}
/**
@@ -125,6 +132,10 @@ class CustomersTest extends TestCase
$json_result = Customers::getLocal($reseller_userdata)->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(0, $result['count']);
$json_result = Customers::getLocal($reseller_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(0, $result);
}
/**
@@ -142,8 +153,11 @@ class CustomersTest extends TestCase
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
$json_result = Customers::getLocal($customer_userdata)->listing();
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
$json_result = Customers::getLocal($customer_userdata)->listingCount();
}
/**
@@ -555,4 +569,49 @@ class CustomersTest extends TestCase
$this->expectExceptionMessage('Loginname contains too many characters. Only ' . (\Froxlor\Database\Database::getSqlUsernameLength() - strlen(Settings::Get('customer.mysqlprefix'))) . ' characters are allowed.');
Customers::getLocal($admin_userdata, $data)->add();
}
/**
*
* @depends testAdminCustomersAddAutoLoginname
*/
public function testResellerCustomersAddNoFtpValidateDefaultUserExists()
{
global $admin_userdata;
// get reseller
$json_result = Admins::getLocal($admin_userdata, array(
'loginname' => 'reseller'
))->get();
$reseller_userdata = json_decode($json_result, true)['data'];
$reseller_userdata['adminsession'] = 1;
// set available ftp resources to 0 to validate that when the customer
// is added the default ftp user for the customer is created too regardless of
// available resource of the reseller/admin
$reseller_userdata['ftps'] = 0;
// add new customer
$data = [
'new_loginname' => 'testftpx',
'email' => 'testftp@froxlor.org',
'firstname' => 'Test',
'name' => 'Ftpman',
'customernumber' => 1339,
'new_customer_password' => 'h0lYmo1y'
];
Customers::getLocal($reseller_userdata, $data)->add();
// get FTP user
$json_result = Ftps::getLocal($reseller_userdata, [
'username' => 'testftpx'
])->get();
$ftp_data = json_decode($json_result, true)['data'];
$this->assertEquals("testftpx", $ftp_data['username']);
// now get rid of the customer again
$json_result = Customers::getLocal($reseller_userdata, array(
'loginname' => 'testftpx'
))->delete();
$result = json_decode($json_result, true)['data'];
$this->assertEquals('testftpx', $result['loginname']);
}
}

View File

@@ -83,6 +83,10 @@ class HostingPlansTest extends TestCase
$json_result = HostingPlans::getLocal($admin_userdata)->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['count']);
$json_result = HostingPlans::getLocal($admin_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result);
}
/**
@@ -101,6 +105,10 @@ class HostingPlansTest extends TestCase
$json_result = HostingPlans::getLocal($reseller_userdata)->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(0, $result['count']);
$json_result = HostingPlans::getLocal($reseller_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(0, $result);
}
/**
@@ -118,8 +126,11 @@ class HostingPlansTest extends TestCase
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
$json_result = HostingPlans::getLocal($customer_userdata)->listing();
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
$json_result = HostingPlans::getLocal($customer_userdata)->listingCount();
}
public function testCustomerPlanAdd()

View File

@@ -116,6 +116,10 @@ class DomainZonesTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['count']);
$this->assertEquals('www2', $result['list'][0]['record']);
$json_result = DomainZones::getLocal($admin_userdata, $data)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result);
}
/**

View File

@@ -5,6 +5,7 @@ use Froxlor\Settings;
use Froxlor\Api\Commands\Admins;
use Froxlor\Api\Commands\Customers;
use Froxlor\Api\Commands\Domains;
use Froxlor\Database\Database;
/**
*
@@ -26,11 +27,17 @@ class DomainsTest extends TestCase
$customer_userdata = json_decode($json_result, true)['data'];
$data = [
'domain' => 'test.local',
'customerid' => $customer_userdata['customerid']
'customerid' => $customer_userdata['customerid'],
'override_tls' => 1,
'ssl_protocols' => array(
'TLSv1.2',
'TLSv1.3'
)
];
$json_result = Domains::getLocal($admin_userdata, $data)->add();
$result = json_decode($json_result, true)['data'];
$this->assertEquals($customer_userdata['documentroot'] . 'test.local/', $result['documentroot']);
$this->assertTrue(in_array('TLSv1.3', explode(",", $result['ssl_protocols'])));
}
/**
@@ -44,6 +51,18 @@ class DomainsTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['count']);
$this->assertEquals('test.local', $result['list'][0]['domain']);
$this->assertEquals(2, count($result['list'][0]['ipsandports']));
$this->assertEquals("82.149.225.56", $result['list'][0]['ipsandports'][1]['ip']);
$json_result = Domains::getLocal($admin_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result);
$json_result = Domains::getLocal($admin_userdata, [
'with_ips' => false
])->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEmpty($result['list'][0]['ipsandports']);
}
/**
@@ -62,6 +81,10 @@ class DomainsTest extends TestCase
$json_result = Domains::getLocal($reseller_userdata)->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(0, $result['count']);
$json_result = Domains::getLocal($reseller_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(0, $result);
}
public function testResellerDomainsAddWithCanEditPhpSettingsDefaultIp()
@@ -153,11 +176,68 @@ class DomainsTest extends TestCase
global $admin_userdata;
$data = [
'domainname' => 'test.local',
'email_only' => 1
'email_only' => 1,
'override_tls' => 0
];
$json_result = Domains::getLocal($admin_userdata, $data)->update();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['email_only']);
$this->assertFalse(in_array('TLSv1.3', explode(",", $result['ssl_protocols'])));
}
/**
*
* @depends testAdminDomainsAdd
*/
public function testAdminDomainsUpdateIssue756()
{
global $admin_userdata;
$data = [
'domainname' => 'test.local',
'ssl_redirect' => 1
];
$json_result = Domains::getLocal($admin_userdata, $data)->update();
$result = json_decode($json_result, true)['data'];
// get ssl ip/port for domain which should still exist
$sel_stmt = Database::prepare("
SELECT COUNT(*) as numips
FROM `" . TABLE_DOMAINTOIP . "` di
LEFT JOIN `" . TABLE_PANEL_IPSANDPORTS . "` i ON i.id = di.id_ipandports
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON d.id = di.id_domain
WHERE d.id = :did AND i.ssl = 1
");
$result_ips = Database::pexecute_first($sel_stmt, [
'did' => $result['id']
], true, true);
$this->assertEquals(1, $result_ips['numips']);
// test clearing
$data = [
'domainname' => 'test.local',
'ssl_ipandport' => array()
];
$json_result = Domains::getLocal($admin_userdata, $data)->update();
$result = json_decode($json_result, true)['data'];
// get ssl ip/port for domain which should still exist
$result_ips = Database::pexecute_first($sel_stmt, [
'did' => $result['id']
], true, true);
$this->assertEquals(1, $result_ips['numips']);
$data = [
'domainname' => 'test.local',
'remove_ssl_ipandport' => 1
];
$json_result = Domains::getLocal($admin_userdata, $data)->update();
$result = json_decode($json_result, true)['data'];
// get ssl ip/port for domain which should still exist
$result_ips = Database::pexecute_first($sel_stmt, [
'did' => $result['id']
], true, true);
$this->assertEquals(0, $result_ips['numips']);
}
/**
@@ -226,4 +306,22 @@ class DomainsTest extends TestCase
'loginname' => 'test3'
))->delete();
}
public function testCustomerDomainsList()
{
global $admin_userdata;
// get customer
$json_result = Customers::getLocal($admin_userdata, array(
'id' => 1
))->get();
$customer_userdata = json_decode($json_result, true)['data'];
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
$json_result = Domains::getLocal($customer_userdata)->listing();
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
$json_result = Domains::getLocal($customer_userdata)->listingCount();
}
}

View File

@@ -191,6 +191,38 @@ class MailsTest extends TestCase
$this->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' => 'test1'
))->get();
$customer_userdata = json_decode($json_result, true)['data'];
$data = [
'emailaddr' => 'info@test2.local'
];
$json_result = EmailForwarders::getLocal($customer_userdata, $data)->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result['count']);
$this->assertEquals(0, $result['list'][0]['id']);
$this->assertEquals('other@domain.tld', $result['list'][0]['address']);
$this->assertEquals(1, $result['list'][1]['id']);
$this->assertEquals('other2@domain.tld', $result['list'][1]['address']);
$json_result = EmailForwarders::getLocal($customer_userdata, $data)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result);
}
/**
*
* @depends testCustomerEmailForwardersDeleteEmailHidden
@@ -292,13 +324,6 @@ class MailsTest extends TestCase
EmailForwarders::getLocal($admin_userdata)->update();
}
public function testAdminEmailForwadersUndefinedListing()
{
global $admin_userdata;
$this->expectExceptionCode(303);
EmailForwarders::getLocal($admin_userdata)->listing();
}
/**
*
* @depends testCustomerEmailForwardersAddAnother
@@ -362,6 +387,10 @@ class MailsTest extends TestCase
$this->assertEquals(2, $result['count']);
$this->assertEquals("info@test2.local", $result['list'][0]['email']);
$this->assertEquals("@test2.local", $result['list'][1]['email']);
$json_result = Emails::getLocal($customer_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result);
}
public function testCustomerEmailAccountsAdd()

View File

@@ -158,6 +158,10 @@ class DirOptionsTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['count']);
$this->assertEquals($customer_userdata['documentroot'] . 'test/', $result['list'][0]['path']);
$json_result = DirOptions::getLocal($admin_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result);
}
/**

View File

@@ -175,6 +175,10 @@ class DirProtectionsTest extends TestCase
$this->assertEquals(2, $result['count']);
$this->assertEquals('test1', $result['list'][0]['username']);
$this->assertEquals('testing', $result['list'][1]['username']);
$json_result = DirProtections::getLocal($customer_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result);
}
/**

View File

@@ -50,7 +50,7 @@ class ValidateTest extends TestCase
public function testValidateIp()
{
$result = Validate::validate_ip2("12.34.56.78", false, 'invalidip', false, false, false, true);
$result = Validate::validate_ip2("12.34.56.78", false, 'invalidip', false, false, false, false, true);
$this->assertEquals("12.34.56.78", $result);
}
@@ -58,12 +58,12 @@ class ValidateTest extends TestCase
{
$this->expectException("Exception");
$this->expectExceptionCode(400);
Validate::validate_ip2("10.0.0.1", false, 'invalidip', false, false, false, true);
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, true);
$result = Validate::validate_ip2("10.0.0.1", true, 'invalidip', false, false, false, false, true);
$this->assertFalse($result);
}
@@ -71,34 +71,65 @@ class ValidateTest extends TestCase
{
$this->expectException("Exception");
$this->expectExceptionCode(400);
Validate::validate_ip2("12.34.56.78/24", false, 'invalidip', false, false, false, true);
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, true);
$result = Validate::validate_ip2("12.34.56.78/24", true, 'invalidip', false, false, false, false, true);
$this->assertFalse($result);
}
public function testValidateIpCidr()
{
$result = Validate::validate_ip2("12.34.56.78/24", false, 'invalidip', false, false, true, true);
$result = Validate::validate_ip2("12.34.56.78/24", false, 'invalidip', false, false, true, false, true);
$this->assertEquals("12.34.56.78/24", $result);
}
public function testValidateIpv6Disallowed()
{
$this->expectException("Exception");
$this->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, true);
$result = Validate::validate_ip2("127.0.0.1/32", false, 'invalidip', true, false, true, false, true);
$this->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->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->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->assertEquals("8.8.8.8/128.0.0.0", $result);
}
public function testValidateIPv6()
{
$result = Validate::is_ipv6('1.1.1.1/4');
$this->assertFalse($result);
$result = Validate::is_ipv6('1.1.1.1');
$this->assertFalse($result);
$result = Validate::is_ipv6('::ffff:10.20.30.40');
$this->assertEquals('::ffff:10.20.30.40', $result);
$result = Validate::is_ipv6('2620:0:2d0:200::7/32');
$this->assertFalse($result);
$result = Validate::is_ipv6('2620:0:2d0:200::7');
$this->assertEquals('2620:0:2d0:200::7', $result);
}
public function testValidateIpLocalhostAllowedWrongIp()
{
$this->expectException("Exception");
$this->expectExceptionCode(400);
Validate::validate_ip2("127.0.0.2", false, 'invalidip', true, false, false, true);
Validate::validate_ip2("127.0.0.2", false, 'invalidip', true, false, false, false, true);
}
public function testValidateUrl()
{
$result = Validate::validateUrl("https://froxlor.org/");

View File

@@ -88,6 +88,10 @@ class FtpsTest extends TestCase
$json_result = Ftps::getLocal($admin_userdata)->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result['count']);
$json_result = Ftps::getLocal($admin_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result);
}
public function testAdminFtpsListSpecificCustomer()
@@ -115,6 +119,10 @@ class FtpsTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['count']);
$this->assertEquals('test1', $result['list'][0]['username']);
$json_result = Ftps::getLocal($reseller_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result);
}
public function testCustomerFtpsList()
@@ -129,6 +137,10 @@ class FtpsTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['count']);
$this->assertEquals('test1', $result['list'][0]['username']);
$json_result = Ftps::getLocal($customer_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result);
}
public function testCustomerFtpsAdd()
@@ -277,4 +289,21 @@ class FtpsTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals('test1ftp2', $result['username']);
}
public function testCustomerFtpsDeleteDefaultUser()
{
global $admin_userdata;
// get customer
$json_result = Customers::getLocal($admin_userdata, array(
'loginname' => 'test1'
))->get();
$customer_userdata = json_decode($json_result, true)['data'];
$data = [
'username' => 'test1'
];
$this->expectExceptionCode(400);
$this->expectExceptionMessage('You cannot delete your main FTP account');
Ftps::getLocal($customer_userdata, $data)->delete();
}
}

View File

@@ -124,4 +124,63 @@ class FroxlorRpcTest extends TestCase
$this->assertEquals('listFunctions', $result['command']['method']);
$this->assertNull($result['params']);
}
public function testApiPhpEscaping()
{
$key = $this->generateKey();
$request = array(
'body' => [
'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']);
}
private function stripcslashes_deep($value)
{
return is_array($value) ? array_map([$this, 'stripcslashes_deep'], $value) : stripcslashes($value);
}
private function generateKey()
{
$dn = array(
"countryName" => "DE",
"stateOrProvinceName" => "Hessen",
"localityName" => "Frankfurt",
"organizationName" => "Froxlor",
"organizationalUnitName" => "Testing",
"commonName" => "test2.local",
"emailAddress" => "team@froxlor.org"
);
// generate key pair
$privkey = openssl_pkey_new(array(
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_RSA
));
// generate csr
$csr = openssl_csr_new($dn, $privkey, array(
'digest_alg' => 'sha256'
));
// generate self-signed certificate
$sscert = openssl_csr_sign($csr, null, $privkey, 365, array(
'digest_alg' => 'sha256'
));
// export
openssl_x509_export($sscert, $certout);
openssl_pkey_export($privkey, $pkeyout, null);
return array(
'cert' => $certout,
'key' => $pkeyout
);
}
}

View File

@@ -21,6 +21,10 @@ class IpsAndPortsTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result['count']);
$this->assertEquals('82.149.225.46', $result['list'][0]['ip']);
$json_result = IpsAndPorts::getLocal($admin_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result);
}
public function testResellerIpsAndPortsListHasNone()
@@ -107,6 +111,10 @@ class IpsAndPortsTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['count']);
$this->assertEquals('82.149.225.47', $result['list'][0]['ip']);
$json_result = IpsAndPorts::getLocal($reseller_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result);
}
/**

View File

@@ -4,6 +4,7 @@ use PHPUnit\Framework\TestCase;
use Froxlor\Api\Commands\Admins;
use Froxlor\Api\Commands\Customers;
use Froxlor\Api\Commands\Mysqls;
use Froxlor\Database\Database;
/**
*
@@ -12,6 +13,8 @@ use Froxlor\Api\Commands\Mysqls;
* @covers \Froxlor\Api\Commands\Mysqls
* @covers \Froxlor\Api\Commands\Customers
* @covers \Froxlor\Api\Commands\Admins
* @covers \Froxlor\Database\DbManager
* @covers \Froxlor\Database\Manager\DbManagerMySQL
*/
class MysqlsTest extends TestCase
{
@@ -36,7 +39,7 @@ class MysqlsTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals('testdb', $result['description']);
$this->assertEquals(0, $result['dbserver']);
// test connection
try {
$test_conn = new \PDO("mysql:host=127.0.0.1", 'test1sql1', $newPwd);
@@ -139,6 +142,10 @@ class MysqlsTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['count']);
$this->assertEquals('test1sql1', $result['list'][0]['databasename']);
$json_result = Mysqls::getLocal($customer_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result);
}
/**
@@ -162,4 +169,39 @@ class MysqlsTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals('test1sql1', $result['databasename']);
}
/**
*
* @depends testCustomerMysqlsAdd
*/
public function testGetAllSqlUsers()
{
\Froxlor\Database\Database::needRoot(true);
$dbm = new \Froxlor\Database\DbManager(\Froxlor\FroxlorLogger::getInstanceOf());
$users = $dbm->getManager()->getAllSqlUsers(false);
foreach ($users as $user => $data) {
$this->assertNotEmpty($data['password'], 'No password for user "' . $user . '"');
}
if (TRAVIS_CI == 0) {
// just to be sure, not required for travis as the vm is fresh every time
Database::needRoot(true);
Database::query("DROP USER IF EXISTS froxlor010@10.0.0.10;");
}
// grant privileges to another host
$testdata = $users['froxlor010'];
$dbm->getManager()->grantPrivilegesTo('froxlor010', $testdata['password'], '10.0.0.10', true);
// select all entries from mysql.user for froxlor010 to compare password-hashes
$sel_stmt = Database::prepare("SELECT * FROM mysql.user WHERE `User` = :usr");
Database::pexecute($sel_stmt, [
'usr' => 'froxlor010'
]);
$results = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC);
foreach ($results as $user) {
$passwd = $user['Password'] ?? $user['authentication_string'];
$this->assertEquals($testdata['password'], $passwd);
}
}
}

View File

@@ -141,6 +141,10 @@ class FpmDaemonsTest extends TestCase
$this->assertEquals(2, $result['count']);
$this->assertEquals('System default', $result['list'][0]['description']);
$this->assertEquals('test2 fpm edit', $result['list'][1]['description']);
$json_result = FpmDaemons::getLocal($admin_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result);
}
public function testAdminFpmDaemonsGetNotFound()
@@ -190,6 +194,10 @@ class FpmDaemonsTest extends TestCase
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
FpmDaemons::getLocal($customer_userdata)->listing();
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
FpmDaemons::getLocal($customer_userdata)->listingCount();
}
public function testCustomerFpmDaemonsUpdate()

View File

@@ -23,6 +23,10 @@ class PhpSettingsText extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals("Default Config", $result['list'][0]['description']);
$this->assertEquals("/usr/bin/php-cgi", $result['list'][0]['binary']);
$json_result = PhpSettings::getLocal($admin_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(2, $result);
}
public function testCustomerPhpSettingsListNotAllowed()
@@ -36,6 +40,10 @@ class PhpSettingsText extends TestCase
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
PhpSettings::getLocal($customer_userdata)->listing();
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
PhpSettings::getLocal($customer_userdata)->listingCount();
}
public function testAdminPhpSettingsAdd()

View File

@@ -201,6 +201,10 @@ class SubDomainsTest extends TestCase
$json_result = SubDomains::getLocal($customer_userdata)->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(3, $result['count']);
$json_result = SubDomains::getLocal($customer_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(3, $result);
}
public function testResellerSubDomainsList()
@@ -215,6 +219,10 @@ class SubDomainsTest extends TestCase
$json_result = SubDomains::getLocal($reseller_userdata)->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(3, $result['count']);
$json_result = SubDomains::getLocal($reseller_userdata)->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(3, $result);
}
public function testAdminSubDomainsListWithCustomer()
@@ -225,6 +233,12 @@ class SubDomainsTest extends TestCase
])->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(3, $result['count']);
$json_result = SubDomains::getLocal($admin_userdata, [
'loginname' => 'test1'
])->listingCount();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(3, $result);
}
/**

View File

@@ -79,6 +79,10 @@ class TrafficTest extends TestCase
$this->assertEquals(1, $result['count']);
$http = 2 * (5 * 1024 * 1024 * 1024); // 2x 5 GB
$this->assertEquals($http, $result['list'][0]['http']);
$this->expectExceptionCode(303);
$this->expectExceptionMessage("You cannot count the traffic data list");
Traffic::getLocal($admin_userdata)->listingCount();
}
public function testAdminTrafficListSpecificDate()
@@ -120,6 +124,10 @@ class TrafficTest extends TestCase
$this->assertEquals(1, $result['count']);
$mail = 250 * 1024 * 1024; // 250 MB
$this->assertEquals($mail, $result['list'][0]['mail']);
$this->expectExceptionCode(303);
$this->expectExceptionMessage("You cannot count the traffic data list");
Traffic::getLocal($admin_userdata)->listingCount();
}
public function testAdminTrafficAdd()