Compare commits

...

122 Commits

Author SHA1 Message Date
4dd13200d0 updated dmarc entry 2025-09-03 12:16:59 +02:00
77d399a645 WET RUN
Some checks reported errors
continuous-integration/drone/push Build was killed
2023-12-06 18:59:18 +01:00
c3186e9803 WET RUN
Some checks reported errors
continuous-integration/drone/push Build was killed
2023-12-06 18:51:36 +01:00
92824194fb vars test - fuck it!
Some checks reported errors
continuous-integration/drone/push Build was killed
2023-12-06 18:48:20 +01:00
3b42d5832b vars test
Some checks reported errors
continuous-integration/drone/push Build was killed
2023-12-06 18:45:34 +01:00
9be43e98fa running compose
Some checks reported errors
continuous-integration/drone/push Build was killed
2023-12-06 18:40:40 +01:00
59ce699440 exclude vendor
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-06 18:33:41 +01:00
9dbb5322f2 drone yaml typo
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-06 18:30:23 +01:00
b3290085c0 drone yaml 01
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-06 18:27:45 +01:00
0e75f74eb8 drone yaml
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-06 18:03:16 +01:00
91d2f2da8a drone deployment 2023-12-06 17:48:53 +01:00
638b153969 Merge remote-tracking branch 'origin/0.10.x' into private-0.10.35.1-dmarc 2023-01-18 16:18:03 +01:00
Michael Kaufmann
fbac2f2bbc fix deletion of dns entry
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-12-07 13:50:54 +01:00
Michael Kaufmann
e10f77e219 fix missing id parameter after security question when deleting a ssl-certificate
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-12-02 16:17:59 +01:00
Michael Kaufmann
83ff0f5b00 fix api-key creation
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-12-02 13:42:26 +01:00
Michael Kaufmann
0562d248b5 use same error message for invalid user and disabled password reset to not give away if a user exists
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-12-02 13:24:27 +01:00
Michael Kaufmann
3fda5be5a3 set version to 0.10.38.3 for upcoming security release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-12-02 09:32:29 +01:00
Michael Kaufmann
4d454a3903 secure api-key generation, dns-record as well as ssl-certificate deletion, logo uploading, frame-inclusion and user/email enumeration via 'forgot password'
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-12-02 09:22:08 +01:00
Michael Kaufmann
0e703a4199 adjust validate-test for 'sql username too long' for mariadb
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-11-24 10:30:01 +01:00
Michael Kaufmann
47c71f6035 adjust mysql-usernamelength values for mariadb according to docs
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-11-24 10:03:23 +01:00
Michael Kaufmann
5923cbb1d5 set version to 0.10.38.2 for security release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-11-05 12:41:50 +01:00
Michael Kaufmann
3f10a4aded fix still possible html injection
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-11-05 12:37:53 +01:00
Michael Kaufmann
eaea93296d set version to 0.10.38.1 for security release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-11-04 08:23:44 +01:00
Michael Kaufmann
1182453c18 fix possible code-injection when adding/editing admins/customers; dont output invalid email address in index on error message
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-10-27 14:06:00 +02:00
Michael Kaufmann
2c8bdfbbbc set version to 0.10.38 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-09-02 13:23:51 +02:00
Michael Kaufmann
bbe82286aa add security question for deleting api-keys to avoid accidental deletion
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-08-27 15:02:48 +02:00
Michael Kaufmann
13571f1f16 correct Dropdown directory selection; fixes #1044
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-08-16 08:32:43 +02:00
d82e9b1e81 more template update 2022-08-10 13:57:53 +02:00
992ebebf89 more template update 2022-08-10 13:55:25 +02:00
Michael Kaufmann
d6b34cc8f8 set version to 0.10.37 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-08-05 14:36:02 +02:00
Michael Kaufmann
cfda35a36b update sql-users with their corresponding password-hash-algorithm; remove a few notices for empty values in str_replace and others
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-07-17 12:03:37 +02:00
Michael Kaufmann
57ae625d38 use correct version_compare as PHP8+ does not compare correctly
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-07-11 12:35:07 +02:00
Michael Kaufmann
65ab064289 re-enable quota and sieve plugins for dovecot in buster and bullseye config-templates, fixes #1042
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-07-07 15:13:32 +02:00
Michael Kaufmann
e6a6f6f9de rework FileDir::makePathfield() is mode is 'dropdown' to show all directories correctly (depth limited); fixes #1044
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-07-07 14:45:50 +02:00
Michael Kaufmann
a7b91eb1ed fix missing namespace in BackupCron
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-07-05 17:03:45 +02:00
Michael Kaufmann
a2342ad1d2 set version to 0.10.36 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-07-01 10:16:47 +02:00
Michael Kaufmann
add1818723 fix missing mapping for recently added loginname placeholder in ReportsCron; fixes #1039
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-06-29 08:23:40 +02:00
Michael Kaufmann
51c1d648b2 fix passing complex passwords with special characters to mysqldump in backup-cron; fixes #1038
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-06-28 20:06:52 +02:00
2cb06be3d6 Merge tag '0.10.35.1' into private-0.10.33-dmarc
tagging release 0.10.35.1
2022-06-20 20:06:59 +02:00
93c72e6754 nextcloud quotas for froxlor logins 2022-06-20 20:06:50 +02:00
Daniel
0fca98c652 Add login header image max-width (#1036) 2022-06-16 07:36:12 +02:00
Michael Kaufmann
3682116ba2 set version to 0.10.35.1 for bugfix release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-06-03 08:58:31 +02:00
Michael Kaufmann
3b99070496 argh, typo in the version to update to
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-06-03 08:57:01 +02:00
Michael Kaufmann
25f20e4a7d set version to 0.10.35 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-06-03 08:28:15 +02:00
Michael Kaufmann
d46b2d1d80 add USERNAME replacer to all email templates; fixes #1032
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-05-31 10:43:39 +02:00
Michael Kaufmann
4750dad9e2 fix wrong number of bound variables when customers_see_all == 0
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-05-25 18:54:15 +02:00
Michael Kaufmann
c6830d8e7a set default-ca for acme.sh after updating acme.sh
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-05-09 08:34:38 +02:00
Michael Kaufmann
10b4de4cf9 remove unused IgnorantRecursiveDirectoryIterator and fix uninitialized variables
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-04-20 15:11:48 +02:00
FliegenKLATSCH
ae39a1759a Silence some php 8.1 warnings (#1029) 2022-04-20 15:09:19 +02:00
Michael Kaufmann
989b4fee0e set version to 0.10.34.1 for upcoming bugfix release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-04-13 12:46:16 +02:00
Michael Kaufmann
7f6810c5bd remove accidentally added character
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-04-03 14:43:37 +02:00
Michael Kaufmann
3fbc9815ea respect domain.writeerrorlog and domain.writeaccesslog when using log-to-pipe
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-04-03 14:34:20 +02:00
Michael Kaufmann
11533c2d75 fix exit statement in cli scripts
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-04-02 18:07:36 +02:00
Michael Kaufmann
652a998188 don't rely on executable flag for php-sessionclean script
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-04-01 12:01:06 +02:00
b118883013 merged with v0.10.33 2022-03-01 12:29:50 +01:00
2e81445a4e greylisting dis/enable 2020-11-11 13:40:33 +01:00
5821f4a0e5 dmarc entries for all emaildomains 2020-03-03 16:09:19 +01:00
a9c258105a Merge branch 'origin-0.10.13' into private-0.10.12 2020-03-03 14:49:44 +01:00
34fd64e5b9 theme 2020-01-30 15:04:18 +01:00
0adc511d07 theme 2020-01-30 14:56:49 +01:00
6f32d810c1 theme update 2020-01-30 14:48:22 +01:00
70faf0cf2a merged with 0.10.12 - greylisting still needs work 2020-01-21 12:54:21 +01:00
11b589c399 new dkim keys 2020-01-15 12:41:41 +01:00
c8e5668852 new DKIM keys 2020-01-15 12:37:07 +01:00
1eb0f698c0 restructuring dmarc entry 2020-01-15 11:47:54 +01:00
d4d98122bf DMARC 2019-06-13 12:00:59 +02:00
44d430950c dmarc w/o external auth 2018-07-11 21:04:28 +02:00
4ac5e2439c DKIM format fix 2018-07-11 21:02:51 +02:00
99f7fc14de merge 2018-03-25 11:48:01 +02:00
3dcd109ee2 merge 2018-03-25 11:30:04 +02:00
2ab6b9f6f3 other stuff 2018-03-23 12:31:46 +01:00
2c7502485b bind stuff 2018-03-23 12:30:02 +01:00
581e4deca1 checking for emaildomain and continue 2017-06-27 14:29:04 +02:00
92f8986477 fonts and colors 2016-12-16 17:59:04 +01:00
1f800f5298 merged for live 2016-12-16 17:22:28 +01:00
cb582a2947 Merge remote-tracking branch 'private/maketank-theme' into 0.9.38.4 2016-12-16 17:20:55 +01:00
caf2c21ae9 merged with dkim 2016-12-16 17:20:39 +01:00
18998d40c0 debug 2016-12-16 15:53:13 +01:00
e2380284e8 fonts and colors 2016-12-16 14:28:17 +01:00
dce20e55b8 fonts and colors 2016-12-16 14:27:12 +01:00
8bd32821dd fonts and colors 2016-12-16 14:26:58 +01:00
fe5072d0a2 fonts and colors 2016-12-16 14:25:55 +01:00
6ca2292820 fonts and colors 2016-12-16 14:25:23 +01:00
a51ff99ec2 fonts and colors 2016-12-16 14:23:03 +01:00
57464ba8c4 fonts and colors 2016-12-16 14:22:11 +01:00
924f93435f fonts and colors 2016-12-16 14:17:03 +01:00
c141868fd4 fonts and colors 2016-12-16 14:15:32 +01:00
3154914532 fonts and colors 2016-12-16 14:13:39 +01:00
f6e3779728 fonts and colors 2016-12-16 14:10:18 +01:00
c7e0fe57d1 fonts and colors 2016-12-16 14:09:33 +01:00
57aacd96e4 fonts and colors 2016-12-16 14:07:09 +01:00
27be204c96 fonts and colors 2016-12-16 14:06:26 +01:00
b7ab10665a fonts and colors 2016-12-16 14:02:04 +01:00
8bc1a5be69 fonts and colors 2016-12-16 14:00:44 +01:00
832799942e fonts and colors 2016-12-16 13:59:48 +01:00
081858d7bb fonts and colors 2016-12-16 13:58:30 +01:00
88791d3d4a fonts and colors 2016-12-16 13:57:24 +01:00
1f0b90ceef fonts and colors 2016-12-16 13:55:51 +01:00
8f295f1b5d fonts and colors 2016-12-16 13:54:21 +01:00
9abe4415af fonts and colors 2016-12-16 13:53:20 +01:00
d25dd58f7b fonts and colors 2016-12-16 13:49:51 +01:00
9d363c5eb0 fonts and colors 2016-12-16 13:48:25 +01:00
acd357f561 fonts and colors 2016-12-16 13:47:58 +01:00
660272b64b fonts and colors 2016-12-16 13:46:03 +01:00
e2209f53d1 logo 2016-12-16 13:44:41 +01:00
7a7f131861 logo 2016-12-16 13:38:22 +01:00
67803ff106 logo 2016-12-16 13:37:42 +01:00
03bafc9540 logo 2016-12-16 13:34:03 +01:00
8fbc3acba6 logo 2016-12-16 13:32:03 +01:00
0e9dad1b71 logo 2016-12-16 13:28:59 +01:00
3542e85195 Maketank theme 2016-12-16 13:23:16 +01:00
b4829b521b .gitignore not maketank 2016-12-16 13:22:44 +01:00
46bf7005e6 disabled AXFR settings 2016-12-15 15:51:21 +01:00
924731d54d disabled AXFR settings 2016-12-15 15:49:06 +01:00
bc550e086f DKIM and dmarc hardcoded 2016-12-15 15:31:40 +01:00
3167df9947 DKIM and dmarc hardcoded 2016-12-15 13:31:26 +01:00
8686b54fb8 DKIM and dmarc hardcoded 2016-12-15 13:29:15 +01:00
480afb0ccd what a bullshit 2016-12-15 13:20:33 +01:00
b52364a873 DKIM and dmarc hardcoded 2016-12-15 13:10:39 +01:00
ccc95b638b Greylisting TODO: Describe system config 2016-11-09 19:00:00 +01:00
2365d3eae3 initial Greylist: TODO: System-settings 2016-11-09 17:53:59 +01:00
2e0ee3d683 initial Greylist: TODO: System-settings 2016-11-09 17:52:38 +01:00
359 changed files with 9692 additions and 441 deletions

40
.drone.yml Normal file
View File

@@ -0,0 +1,40 @@
kind: pipeline
name: deploy-froxlor
type: docker
platform:
os: linux
arch: arm64
trigger:
branch:
- live
event:
include:
- push
steps:
- name: deploy
image: cr.wks/drone/drone-rsync:latest
settings:
hosts: ["rechner02.maketank.net"]
source: ./
target: ~/froxlor-test
user: www-data
exclude: ['vendor', '.git*', '*drone.yml', '.settings', '.buildpath', '.editorconfig', '.project', '.travis.yml']
args: '-v --delete'
log_level: quiet
key:
from_secret: ssh-www-data-maketank-rsa
command_timeout: 10m
- name: compose-install
image: appleboy/drone-ssh
settings:
host:
- rechner02.maketank.net
username: www-data
key:
from_secret: ssh-www-data-maketank-rsa
script:
- cd ~/froxlor-test && composer install --no-dev

1
.gitignore vendored
View File

@@ -14,6 +14,7 @@ logs/*
*.iml
img/
!templates/Maketank/
!templates/Froxlor/
!templates/Sparkle/
!templates/misc/

View File

@@ -229,7 +229,7 @@ return array(
'default' => true,
'save_method' => 'storeSettingField'
),
'system_disable_le_selfcheck' => array(
'system_le_domain_dnscheck' => array(
'label' => $lng['serversettings']['le_domain_dnscheck'],
'settinggroup' => 'system',
'varname' => 'le_domain_dnscheck',

View File

@@ -90,7 +90,23 @@ return array(
'varname' => 'catchall_enabled',
'type' => 'bool',
'default' => true,
'save_method' => 'storeSettingResetCatchall'
'save_method' => 'storeSettingResetCatchall',
),
'mail_greylist_enabled' => array(
'label' => $lng['serversettings']['greylist_enabled'],
'settinggroup' => 'mail',
'varname' => 'greylist_enabled',
'type' => 'bool',
'default' => true,
'save_method' => 'storeSettingField',
),
'mail_greylist_disabled_default' => array(
'label' => $lng['serversettings']['greylist_disabled_default'],
'settinggroup' => 'mail',
'varname' => 'greylist_disabled_default',
'type' => 'bool',
'default' => false,
'save_method' => 'storeSettingField',
),
'system_mailtraffic_enabled' => array(
'label' => $lng['serversettings']['mailtraffic_enabled'],

View File

@@ -260,7 +260,7 @@ if ($page == 'admins' && $userinfo['change_serversettings'] == '1') {
$dec_places = Settings::Get('panel.decimal_places');
$result['traffic'] = round($result['traffic'] / (1024 * 1024), $dec_places);
$result['diskspace'] = round($result['diskspace'] / 1024, $dec_places);
$result['email'] = $idna_convert->decode($result['email']);
$result['email'] = $idna_convert->decode($result['email'] ?? '');
$customers_ul = \Froxlor\UI\HTML::makecheckbox('customers_ul', $lng['customer']['unlimited'], '-1', false, $result['customers'], true, true);
if ($result['customers'] == '-1') {

View File

@@ -298,6 +298,7 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
$email_quota_ul = \Froxlor\UI\HTML::makecheckbox('email_quota_ul', $lng['customer']['unlimited'], '-1', false, '0', true, true);
$ftps_ul = \Froxlor\UI\HTML::makecheckbox('ftps_ul', $lng['customer']['unlimited'], '-1', false, '0', true, true);
$mysqls_ul = \Froxlor\UI\HTML::makecheckbox('mysqls_ul', $lng['customer']['unlimited'], '-1', false, '0', true, true);
$nextcloud_quota_ul = \Froxlor\UI\HTML::makecheckbox('nextcloud_quota_ul', $lng['customer']['unlimited'], '-1', false, '0', true, true);
$gender_options = \Froxlor\UI\HTML::makeoption($lng['gender']['undef'], 0, true, true, true);
$gender_options .= \Froxlor\UI\HTML::makeoption($lng['gender']['male'], 1, null, true, true);
@@ -395,13 +396,18 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
$dec_places = Settings::Get('panel.decimal_places');
$result['traffic'] = round($result['traffic'] / (1024 * 1024), $dec_places);
$result['diskspace'] = round($result['diskspace'] / 1024, $dec_places);
$result['email'] = $idna_convert->decode($result['email']);
$result['email'] = $idna_convert->decode($result['email'] ?? '');
$nextcloud_quota_ul = \Froxlor\UI\HTML::makecheckbox('nextcloud_quota_ul', $lng['customer']['unlimited'], '-1', false, $result['nextcloud_quota'], true, true);
if ($result['nextcloud_quota'] == '-1') {
$result['nextcloud_quota'] = '';
}
$diskspace_ul = \Froxlor\UI\HTML::makecheckbox('diskspace_ul', $lng['customer']['unlimited'], '-1', false, $result['diskspace'], true, true);
if ($result['diskspace'] == '-1') {
$result['diskspace'] = '';
}
$traffic_ul = \Froxlor\UI\HTML::makecheckbox('traffic_ul', $lng['customer']['unlimited'], '-1', false, $result['traffic'], true, true);
if ($result['traffic'] == '-1') {
$result['traffic'] = '';

View File

@@ -148,7 +148,7 @@ if ($page == 'domains' || $page == 'overview') {
$customers = \Froxlor\UI\HTML::makeoption($lng['panel']['please_choose'], 0, 0, true);
$result_customers_stmt = Database::prepare("
SELECT `customerid`, `loginname`, `name`, `firstname`, `company`
FROM `" . TABLE_PANEL_CUSTOMERS . "` " . ($userinfo['customers_see_all'] ? '' : " WHERE `adminid` = '" . (int) $userinfo['adminid'] . "' ") . " ORDER BY COALESCE(NULLIF(`name`,''), `company`) ASC");
FROM `" . TABLE_PANEL_CUSTOMERS . "` " . ($userinfo['customers_see_all'] ? '' : " WHERE `adminid` = :adminid ") . " ORDER BY COALESCE(NULLIF(`name`,''), `company`) ASC");
$params = array();
if ($userinfo['customers_see_all'] == '0') {
$params['adminid'] = $userinfo['adminid'];
@@ -674,7 +674,7 @@ if ($page == 'domains' || $page == 'overview') {
function formatDomainEntry(&$row, &$idna_convert)
{
$row['domain'] = $idna_convert->decode($row['domain']);
$row['aliasdomain'] = $idna_convert->decode($row['aliasdomain']);
$row['aliasdomain'] = $idna_convert->decode($row['aliasdomain'] ?? '');
$row['ipandport'] = '';
foreach ($row['ipsandports'] as $rowip) {
@@ -685,7 +685,7 @@ function formatDomainEntry(&$row, &$idna_convert)
}
}
$row['ipandport'] = substr($row['ipandport'], 0, - 1);
$row['termination_date'] = str_replace("0000-00-00", "", $row['termination_date']);
$row['termination_date'] = str_replace("0000-00-00", "", $row['termination_date'] ?? '');
$row['termination_css'] = "";
if ($row['termination_date'] != "") {

View File

@@ -1,5 +1,5 @@
<?php
if (! defined('AREA')) {
if (!defined('AREA')) {
header("Location: index.php");
exit();
}
@@ -27,68 +27,88 @@ use Froxlor\Database\Database;
$del_stmt = Database::prepare("DELETE FROM `" . TABLE_API_KEYS . "` WHERE id = :id");
$success_message = "";
$id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
$id = isset($_POST['id']) ? (int) $_POST['id'] : (isset($_GET['id']) ? (int) $_GET['id'] : 0);
$area = AREA;
// do the delete and then just show a success-message and the apikeys list again
if ($action == 'delete') {
if ($id > 0) {
$chk = (AREA == 'admin' && $userinfo['customers_see_all'] == '1') ? true : false;
if (AREA == 'customer') {
$chk_stmt = Database::prepare("
SELECT c.customerid FROM `" . TABLE_PANEL_CUSTOMERS . "` c
LEFT JOIN `" . TABLE_API_KEYS . "` ak ON ak.customerid = c.customerid
WHERE ak.`id` = :id AND c.`customerid` = :cid
");
$chk = Database::pexecute_first($chk_stmt, array(
'id' => $id,
'cid' => $userinfo['customerid']
));
} elseif (AREA == 'admin' && $userinfo['customers_see_all'] == '0') {
$chk_stmt = Database::prepare("
SELECT a.adminid FROM `" . TABLE_PANEL_ADMINS . "` a
LEFT JOIN `" . TABLE_API_KEYS . "` ak ON ak.adminid = a.adminid
WHERE ak.`id` = :id AND a.`adminid` = :aid
");
$chk = Database::pexecute_first($chk_stmt, array(
'id' => $id,
'aid' => $userinfo['adminid']
));
}
if ($chk !== false) {
Database::pexecute($del_stmt, array(
if (isset($_POST['send']) && $_POST['send'] == 'send') {
$chk = (AREA == 'admin' && $userinfo['customers_see_all'] == '1') ? true : false;
if (AREA == 'customer') {
$chk_stmt = Database::prepare("
SELECT c.customerid FROM `" . TABLE_PANEL_CUSTOMERS . "` c
LEFT JOIN `" . TABLE_API_KEYS . "` ak ON ak.customerid = c.customerid
WHERE ak.`id` = :id AND c.`customerid` = :cid
");
$chk = Database::pexecute_first($chk_stmt, array(
'id' => $id,
'cid' => $userinfo['customerid']
));
} elseif (AREA == 'admin' && $userinfo['customers_see_all'] == '0') {
$chk_stmt = Database::prepare("
SELECT a.adminid FROM `" . TABLE_PANEL_ADMINS . "` a
LEFT JOIN `" . TABLE_API_KEYS . "` ak ON ak.adminid = a.adminid
WHERE ak.`id` = :id AND a.`adminid` = :aid
");
$chk = Database::pexecute_first($chk_stmt, array(
'id' => $id,
'aid' => $userinfo['adminid']
));
}
if ($chk !== false) {
Database::pexecute($del_stmt, array(
'id' => $id
));
$success_message = sprintf($lng['apikeys']['apikey_removed'], $id);
}
} else {
\Froxlor\UI\HTML::askYesNo('api_reallydelete', $filename, array(
'page' => $page,
'action' => $action,
'id' => $id
));
$success_message = sprintf($lng['apikeys']['apikey_removed'], $id);
), $id);
}
}
} elseif ($action == 'add') {
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_API_KEYS . "` SET
`apikey` = :key, `secret` = :secret, `adminid` = :aid, `customerid` = :cid, `valid_until` = '-1', `allowed_from` = ''
");
// customer generates for himself, admins will see a customer-select-box later
if (AREA == 'admin') {
$cid = 0;
} elseif (AREA == 'customer') {
$cid = $userinfo['customerid'];
if (isset($_POST['send']) && $_POST['send'] == 'send') {
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_API_KEYS . "` SET
`apikey` = :key, `secret` = :secret, `adminid` = :aid, `customerid` = :cid, `valid_until` = '-1', `allowed_from` = ''
");
// customer generates for himself, admins will see a customer-select-box later
if (AREA == 'admin') {
$cid = 0;
} elseif (AREA == 'customer') {
$cid = $userinfo['customerid'];
}
$key = hash('sha256', openssl_random_pseudo_bytes(64 * 64));
$secret = hash('sha512', openssl_random_pseudo_bytes(64 * 64 * 4));
Database::pexecute($ins_stmt, array(
'key' => $key,
'secret' => $secret,
'aid' => $userinfo['adminid'],
'cid' => $cid
));
$success_message = $lng['apikeys']['apikey_added'];
} else {
\Froxlor\UI\HTML::askYesNo('api_reallyadd', $filename, array(
'page' => $page,
'action' => $action
), $id);
}
$key = hash('sha256', openssl_random_pseudo_bytes(64 * 64));
$secret = hash('sha512', openssl_random_pseudo_bytes(64 * 64 * 4));
Database::pexecute($ins_stmt, array(
'key' => $key,
'secret' => $secret,
'aid' => $userinfo['adminid'],
'cid' => $cid
));
$success_message = $lng['apikeys']['apikey_added'];
} elseif ($action == 'jqEditApiKey') {
$keyid = isset($_POST['id']) ? (int) $_POST['id'] : 0;
if (empty($keyid)) {
echo json_encode(false);
exit;
}
$allowed_from = isset($_POST['allowed_from']) ? $_POST['allowed_from'] : "";
$valid_until = isset($_POST['valid_until']) ? (int) $_POST['valid_until'] : - 1;
$valid_until = isset($_POST['valid_until']) ? (int) $_POST['valid_until'] : -1;
// validate allowed_from
if (! empty($allowed_from)) {
if (!empty($allowed_from)) {
$ip_list = array_map('trim', explode(",", $allowed_from));
$_check_list = $ip_list;
foreach ($_check_list as $idx => $ip) {
@@ -100,8 +120,8 @@ if ($action == 'delete') {
$allowed_from = implode(",", array_unique($ip_list));
}
if ($valid_until <= 0 || ! is_numeric($valid_until)) {
$valid_until = - 1;
if ($valid_until <= 0 || !is_numeric($valid_until)) {
$valid_until = -1;
}
$upd_stmt = Database::prepare("

View File

@@ -83,7 +83,7 @@ if ($page == 'overview') {
$statsapp = 'webalizer';
}
$row = [
'domain' => $idna_convert->decode($parentdomain)
'domain' => $idna_convert->decode($parentdomain ?? '')
];
eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_delimiter") . "\";");
@@ -472,8 +472,8 @@ if ($page == 'overview') {
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']);
$row['aliasdomain'] = $idna_convert->decode($row['aliasdomain'] ?? '');
$row['domainalias'] = $idna_convert->decode($row['domainalias'] ?? '');
/**
* check for set ssl-certs to show different state-icons
@@ -503,7 +503,7 @@ function formatDomainEntry(&$row, &$idna_convert)
}
}
$row['termination_date'] = str_replace("0000-00-00", "", $row['termination_date']);
$row['termination_date'] = str_replace("0000-00-00", "", $row['termination_date'] ?? '');
$row['termination_css'] = "";
if ($row['termination_date'] != "") {

View File

@@ -212,7 +212,9 @@ if ($page == 'overview') {
if (Settings::Get('catchall.catchall_enabled') != '1') {
unset($email_add_data['emails_add']['sections']['section_a']['fields']['iscatchall']);
}
if (Settings::Get('mail.greylist_enabled') != '1') {
unset($email_edit_data['emails_edit']['sections']['section_a']['fields']['mail_greylist']);
}
$email_add_form = \Froxlor\UI\HtmlForm::genHTMLForm($email_add_data);
$title = $email_add_data['emails_add']['title'];
@@ -232,7 +234,7 @@ if ($page == 'overview') {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
if (isset($result['email']) && $result['email'] != '') {
$result['email'] = $idna_convert->decode($result['email']);
$result['email_full'] = $idna_convert->decode($result['email_full']);
@@ -260,7 +262,9 @@ if ($page == 'overview') {
if (Settings::Get('catchall.catchall_enabled') != '1') {
unset($email_edit_data['emails_edit']['sections']['section_a']['fields']['mail_catchall']);
}
if (Settings::Get('mail.greylist_enabled') != '1') {
unset($email_edit_data['emails_edit']['sections']['section_a']['fields']['mail_greylist']);
}
$email_edit_form = \Froxlor\UI\HtmlForm::genHTMLForm($email_edit_data);
$title = $email_edit_data['emails_edit']['title'];
@@ -281,7 +285,7 @@ if ($page == 'overview') {
try {
Emails::getLocal($userinfo, array(
'id' => $id,
'iscatchall' => ($result['iscatchall'] == '1' ? 0 : 1)
'iscatchall' => ($result['iscatchall'] == '1' ? 0 : 1),
))->update();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
@@ -292,6 +296,30 @@ if ($page == 'overview') {
'id' => $id,
's' => $s
));
} elseif ($action == 'togglegreylist' && $id != 0) {
try {
$json_result = Emails::getLocal($userinfo, array(
'id' => $id
))->get();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
try {
Emails::getLocal($userinfo, array(
'id' => $id,
'disablegreylist' => ($result['disablegreylist'] == '1' ? 0 : 1)
))->update_greylist();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
\Froxlor\UI\Response::redirectTo($filename, array(
'page' => $page,
'action' => 'edit',
'id' => $id,
's' => $s
));
}
} elseif ($page == 'accounts') {
if ($action == 'add' && $id != 0) {

View File

@@ -24,7 +24,7 @@ use Froxlor\Api\Commands\DomainZones as DomainZones;
// This file is being included in admin_domains and customer_domains
// and therefore does not need to require lib/init.php
$domain_id = isset($_GET['domain_id']) ? (int) $_GET['domain_id'] : null;
$domain_id = isset($_GET['domain_id']) ? (int) $_GET['domain_id'] : (isset($_POST['domain_id']) ? (int)$_POST['domain_id'] : null);
$record = isset($_POST['record']['record']) ? trim($_POST['record']['record']) : null;
$type = isset($_POST['record']['type']) ? $_POST['record']['type'] : 'A';
@@ -56,17 +56,25 @@ if ($action == 'add_record' && ! empty($_POST)) {
}
} elseif ($action == 'delete') {
// remove entry
$entry_id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
if ($entry_id > 0) {
try {
DomainZones::getLocal($userinfo, array(
'entry_id' => $entry_id,
'id' => $domain_id
))->delete();
// success message (inline)
$success_message = $lng['success']['dns_record_deleted'];
} catch (Exception $e) {
$errors = str_replace("\n", "<br>", $e->getMessage());
if ($id > 0) {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
try {
DomainZones::getLocal($userinfo, array(
'entry_id' => $id,
'id' => $domain_id
))->delete();
// success message (inline)
$success_message = $lng['success']['dns_record_deleted'];
} catch (Exception $e) {
$errors = str_replace("\n", "<br>", $e->getMessage());
}
} else {
\Froxlor\UI\HTML::askYesNo('dnsentry_reallydelete', $filename, array(
'page' => $page,
'action' => $action,
'id' => $id,
'domain_id' => $domain_id
), $id);
}
}
}

277
index.php
View File

@@ -22,6 +22,7 @@ require './lib/init.php';
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\FroxlorLogger;
use Froxlor\Validate\Validate;
if ($action == '') {
$action = 'login';
@@ -352,8 +353,7 @@ if ($action == '2fa_entercode') {
$message = sprintf($lng['error']['login_blocked'], Settings::Get('login.deactivatetime'));
break;
case 4:
$cmail = isset($_GET['customermail']) ? $_GET['customermail'] : 'unknown';
$message = str_replace('%s', $cmail, $lng['error']['errorsendingmail']);
$message = $lng['error']['errorsendingmailpub'];
break;
case 5:
$message = $lng['error']['user_banned'];
@@ -425,159 +425,162 @@ if ($action == 'forgotpwd') {
}
}
if ($result_stmt !== null) {
$user = $result_stmt->fetch(PDO::FETCH_ASSOC);
/* Check whether user is banned */
if ($user['deactivated']) {
\Froxlor\UI\Response::redirectTo('index.php', array(
'showmessage' => '8'
));
exit();
$no_action = false;
if ($adminchecked) {
if (Settings::Get('panel.allow_preset_admin') != '1') {
$message = $lng['pwdreminder']['notallowed'];
unset($adminchecked);
}
} else {
if (Settings::Get('panel.allow_preset') != '1') {
$message = $lng['pwdreminder']['notallowed'];
}
}
if (($adminchecked && Settings::Get('panel.allow_preset_admin') == '1') || $adminchecked == false) {
if ($user !== false) {
// build a activation code
$timestamp = time();
$first = substr(md5($user['loginname'] . $timestamp . \Froxlor\PhpHelper::randomStr(16)), 0, 15);
$third = substr(md5($user['email'] . $timestamp . \Froxlor\PhpHelper::randomStr(16)), - 15);
$activationcode = $first . $timestamp . $third . substr(md5($third . $timestamp), 0, 10);
if (empty($message)) {
if ($result_stmt !== null) {
$user = $result_stmt->fetch(PDO::FETCH_ASSOC);
// Drop all existing activation codes for this user
$stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_ACTIVATION . "`
WHERE `userid` = :userid
AND `admin` = :admin");
$params = array(
"userid" => $adminchecked ? $user['adminid'] : $user['customerid'],
"admin" => $adminchecked ? 1 : 0
);
Database::pexecute($stmt, $params);
// Add new activation code to database
$stmt = Database::prepare("INSERT INTO `" . TABLE_PANEL_ACTIVATION . "`
(userid, admin, creation, activationcode)
VALUES (:userid, :admin, :creation, :activationcode)");
$params = array(
"userid" => $adminchecked ? $user['adminid'] : $user['customerid'],
"admin" => $adminchecked ? 1 : 0,
"creation" => $timestamp,
"activationcode" => $activationcode
);
Database::pexecute($stmt, $params);
$rstlog = FroxlorLogger::getInstanceOf(array(
'loginname' => 'password_reset'
/* Check whether user is banned */
if ($user['deactivated']) {
\Froxlor\UI\Response::redirectTo('index.php', array(
'showmessage' => '8'
));
$rstlog->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $user['loginname'] . "' requested a link for setting a new password.");
exit();
}
// Set together our activation link
$protocol = empty($_SERVER['HTTPS']) ? 'http' : 'https';
// this can be a fixed value to avoid potential exploiting by modifying headers
$host = Settings::Get('system.hostname'); // $_SERVER['HTTP_HOST'];
$port = $_SERVER['SERVER_PORT'] != 80 ? ':' . $_SERVER['SERVER_PORT'] : '';
// don't add :443 when https is used, as it is default (and just looks weird!)
if ($protocol == 'https' && $_SERVER['SERVER_PORT'] == '443') {
$port = '';
}
// there can be only one script to handle this so we can use a fixed value here
$script = "/index.php"; // $_SERVER['SCRIPT_NAME'];
if (Settings::Get('system.froxlordirectlyviahostname') == 0) {
$script = \Froxlor\FileDir::makeCorrectFile("/" . basename(__DIR__) . "/" . $script);
}
$activationlink = $protocol . '://' . $host . $port . $script . '?action=resetpwd&resetcode=' . $activationcode;
if (($adminchecked && Settings::Get('panel.allow_preset_admin') == '1') || $adminchecked == false) {
if ($user !== false) {
// build a activation code
$timestamp = time();
$first = substr(md5($user['loginname'] . $timestamp . \Froxlor\PhpHelper::randomStr(16)), 0, 15);
$third = substr(md5($user['email'] . $timestamp . \Froxlor\PhpHelper::randomStr(16)), - 15);
$activationcode = $first . $timestamp . $third . substr(md5($third . $timestamp), 0, 10);
$replace_arr = array(
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($user),
'NAME' => $user['name'],
'FIRSTNAME' => $user['firstname'] ?? "",
'COMPANY' => $user['company'] ?? "",
'CUSTOMER_NO' => $user['customernumber'] ?? 0,
'USERNAME' => $loginname,
'LINK' => $activationlink
);
// Drop all existing activation codes for this user
$stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_ACTIVATION . "`
WHERE `userid` = :userid
AND `admin` = :admin");
$params = array(
"userid" => $adminchecked ? $user['adminid'] : $user['customerid'],
"admin" => $adminchecked ? 1 : 0
);
Database::pexecute($stmt, $params);
$def_language = ($user['def_language'] != '') ? $user['def_language'] : Settings::Get('panel.standardlanguage');
$result_stmt = Database::prepare('SELECT `value` FROM `' . TABLE_PANEL_TEMPLATES . '`
WHERE `adminid`= :adminid
AND `language`= :lang
AND `templategroup`=\'mails\'
AND `varname`=\'password_reset_subject\'');
Database::pexecute($result_stmt, array(
"adminid" => $user['adminid'],
"lang" => $def_language
));
$result = $result_stmt->fetch(PDO::FETCH_ASSOC);
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result['value'] != '') ? $result['value'] : $lng['mails']['password_reset']['subject']), $replace_arr));
// Add new activation code to database
$stmt = Database::prepare("INSERT INTO `" . TABLE_PANEL_ACTIVATION . "`
(userid, admin, creation, activationcode)
VALUES (:userid, :admin, :creation, :activationcode)");
$params = array(
"userid" => $adminchecked ? $user['adminid'] : $user['customerid'],
"admin" => $adminchecked ? 1 : 0,
"creation" => $timestamp,
"activationcode" => $activationcode
);
Database::pexecute($stmt, $params);
$result_stmt = Database::prepare('SELECT `value` FROM `' . TABLE_PANEL_TEMPLATES . '`
WHERE `adminid`= :adminid
AND `language`= :lang
AND `templategroup`=\'mails\'
AND `varname`=\'password_reset_mailbody\'');
Database::pexecute($result_stmt, array(
"adminid" => $user['adminid'],
"lang" => $def_language
));
$result = $result_stmt->fetch(PDO::FETCH_ASSOC);
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result['value'] != '') ? $result['value'] : $lng['mails']['password_reset']['mailbody']), $replace_arr));
$_mailerror = false;
$mailerr_msg = "";
try {
$mail->Subject = $mail_subject;
$mail->AltBody = $mail_body;
$mail->MsgHTML(str_replace("\n", "<br />", $mail_body));
$mail->AddAddress($user['email'], \Froxlor\User::getCorrectUserSalutation($user));
$mail->Send();
} catch (\PHPMailer\PHPMailer\Exception $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$rstlog = FroxlorLogger::getInstanceOf(array(
'loginname' => 'password_reset'
));
$rstlog->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
$rstlog->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $user['loginname'] . "' requested a link for setting a new password.");
// Set together our activation link
$protocol = empty($_SERVER['HTTPS']) ? 'http' : 'https';
// this can be a fixed value to avoid potential exploiting by modifying headers
$host = Settings::Get('system.hostname'); // $_SERVER['HTTP_HOST'];
$port = $_SERVER['SERVER_PORT'] != 80 ? ':' . $_SERVER['SERVER_PORT'] : '';
// don't add :443 when https is used, as it is default (and just looks weird!)
if ($protocol == 'https' && $_SERVER['SERVER_PORT'] == '443') {
$port = '';
}
// there can be only one script to handle this so we can use a fixed value here
$script = "/index.php"; // $_SERVER['SCRIPT_NAME'];
if (Settings::Get('system.froxlordirectlyviahostname') == 0) {
$script = \Froxlor\FileDir::makeCorrectFile("/" . basename(__DIR__) . "/" . $script);
}
$activationlink = $protocol . '://' . $host . $port . $script . '?action=resetpwd&resetcode=' . $activationcode;
$replace_arr = array(
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($user),
'NAME' => $user['name'],
'FIRSTNAME' => $user['firstname'] ?? "",
'COMPANY' => $user['company'] ?? "",
'CUSTOMER_NO' => $user['customernumber'] ?? 0,
'USERNAME' => $loginname,
'LINK' => $activationlink
);
$def_language = ($user['def_language'] != '') ? $user['def_language'] : Settings::Get('panel.standardlanguage');
$result_stmt = Database::prepare('SELECT `value` FROM `' . TABLE_PANEL_TEMPLATES . '`
WHERE `adminid`= :adminid
AND `language`= :lang
AND `templategroup`=\'mails\'
AND `varname`=\'password_reset_subject\'');
Database::pexecute($result_stmt, array(
"adminid" => $user['adminid'],
"lang" => $def_language
));
$result = $result_stmt->fetch(PDO::FETCH_ASSOC);
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result['value'] != '') ? $result['value'] : $lng['mails']['password_reset']['subject']), $replace_arr));
$result_stmt = Database::prepare('SELECT `value` FROM `' . TABLE_PANEL_TEMPLATES . '`
WHERE `adminid`= :adminid
AND `language`= :lang
AND `templategroup`=\'mails\'
AND `varname`=\'password_reset_mailbody\'');
Database::pexecute($result_stmt, array(
"adminid" => $user['adminid'],
"lang" => $def_language
));
$result = $result_stmt->fetch(PDO::FETCH_ASSOC);
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result['value'] != '') ? $result['value'] : $lng['mails']['password_reset']['mailbody']), $replace_arr));
$_mailerror = false;
$mailerr_msg = "";
try {
$mail->Subject = $mail_subject;
$mail->AltBody = $mail_body;
$mail->MsgHTML(str_replace("\n", "<br />", $mail_body));
$mail->AddAddress($user['email'], \Froxlor\User::getCorrectUserSalutation($user));
$mail->Send();
} catch (\PHPMailer\PHPMailer\Exception $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$rstlog = FroxlorLogger::getInstanceOf(array(
'loginname' => 'password_reset'
));
$rstlog->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
\Froxlor\UI\Response::redirectTo('index.php', array(
'showmessage' => '4',
'customermail' => $user['email']
));
exit();
}
$mail->ClearAddresses();
\Froxlor\UI\Response::redirectTo('index.php', array(
'showmessage' => '4',
'customermail' => $user['email']
'showmessage' => '1'
));
exit();
} else {
$rstlog = FroxlorLogger::getInstanceOf(array(
'loginname' => 'password_reset'
));
$rstlog->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $loginname . "' requested to set a new password, but was not found in database!");
$message = $lng['login']['combination_not_found'];
}
$mail->ClearAddresses();
\Froxlor\UI\Response::redirectTo('index.php', array(
'showmessage' => '1'
));
exit();
} else {
$rstlog = FroxlorLogger::getInstanceOf(array(
'loginname' => 'password_reset'
));
$rstlog->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $loginname . "' requested to set a new password, but was not found in database!");
$message = $lng['login']['combination_not_found'];
unset($user);
}
unset($user);
} else {
$message = $lng['pwdreminder']['notallowed'];
}
} else {
$message = $lng['login']['usernotfound'];
}
}
if ($adminchecked) {
if (Settings::Get('panel.allow_preset_admin') != '1') {
$message = $lng['pwdreminder']['notallowed'];
unset($adminchecked);
}
} else {
if (Settings::Get('panel.allow_preset') != '1') {
$message = $lng['pwdreminder']['notallowed'];
}
}

View File

@@ -723,7 +723,7 @@ opcache.validate_timestamps'),
('panel', 'logo_image_login', ''),
('panel', 'logo_overridetheme', '0'),
('panel', 'logo_overridecustom', '0'),
('panel', 'version', '0.10.34'),
('panel', 'version', '0.10.38.3'),
('panel', 'db_version', '202112310');

View File

@@ -28,5 +28,5 @@ try {
\Froxlor\Cli\ConfigServicesCmd::processParameters($argc, $argv);
} catch (Exception $e) {
\Froxlor\Cli\ConfigServicesCmd::printerr($e->getMessage());
exit 1;
exit(1);
}

View File

@@ -28,5 +28,5 @@ try {
\Froxlor\Cli\SwitchServerIpCmd::processParameters($argc, $argv);
} catch (Exception $e) {
\Froxlor\Cli\SwitchServerIpCmd::printerr($e->getMessage());
exit 1;
exit(1);
}

View File

@@ -975,3 +975,49 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.33')) {
showUpdateStep("Updating from 0.10.33 to 0.10.34", false);
\Froxlor\Froxlor::updateToVersion('0.10.34');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.34')) {
showUpdateStep("Updating from 0.10.34 to 0.10.34.1", false);
\Froxlor\Froxlor::updateToVersion('0.10.34.1');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.34.1')) {
showUpdateStep("Updating from 0.10.34.1 to 0.10.35", false);
\Froxlor\Froxlor::updateToVersion('0.10.35');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.35')) {
showUpdateStep("Updating from 0.10.35 to 0.10.35.1", false);
\Froxlor\Froxlor::updateToVersion('0.10.35.1');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.35.1')) {
showUpdateStep("Updating from 0.10.35.1 to 0.10.36", false);
\Froxlor\Froxlor::updateToVersion('0.10.36');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.36')) {
showUpdateStep("Updating from 0.10.36 to 0.10.37", false);
\Froxlor\Froxlor::updateToVersion('0.10.37');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.37')) {
showUpdateStep("Updating from 0.10.37 to 0.10.38", false);
\Froxlor\Froxlor::updateToVersion('0.10.38');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.38')) {
showUpdateStep("Updating from 0.10.38 to 0.10.38.1", false);
\Froxlor\Froxlor::updateToVersion('0.10.38.1');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.38.1')) {
showUpdateStep("Updating from 0.10.38.1 to 0.10.38.2", false);
\Froxlor\Froxlor::updateToVersion('0.10.38.2');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.38.2')) {
showUpdateStep("Updating from 0.10.38.2 to 0.10.38.3", false);
\Froxlor\Froxlor::updateToVersion('0.10.38.3');
}

View File

@@ -180,12 +180,18 @@ abstract class ApiParameter
*/
private function trimArray($input)
{
if (! is_array($input)) {
if ($input === '') {
return "";
}
if (is_numeric($input) || is_null($input)) {
return $input;
}
if (!is_array($input)) {
return trim($input);
}
return array_map(array(
return array_map([
$this,
'trimArray'
), $input);
], $input);
}
}

View File

@@ -227,7 +227,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$ipaddress = $this->getParam('ipaddress', true, - 1);
// validation
$name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true);
$name = \Froxlor\Validate\Validate::validate($name, 'name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
$def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true);
@@ -472,10 +472,10 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// parameters
$name = $this->getParam('name', true, $result['name']);
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$email = $this->getParam('email', true, $idna_convert->decode($result['email']));
$email = $this->getParam('email', true, $idna_convert->decode($result['email'] ?? ''));
$password = $this->getParam('admin_password', true, '');
$def_language = $this->getParam('def_language', true, $result['def_language']);
$custom_notes = $this->getParam('custom_notes', true, $result['custom_notes']);
$custom_notes = $this->getParam('custom_notes', true, ($result['custom_notes'] ?? ""));
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, $result['custom_notes_show']);
$theme = $this->getParam('theme', true, $result['theme']);
@@ -527,7 +527,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
}
// validation
$name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true);
$name = \Froxlor\Validate\Validate::validate($name, 'name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
$def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true);

View File

@@ -368,6 +368,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
foreach ($hp_result['value'] as $index => $value) {
$hp_result[$index] = $value;
}
$nextcloud_quota = $hp_result['nextcloud_quota'] ?? 0;
$diskspace = $hp_result['diskspace'] ?? 0;
$traffic = $hp_result['traffic'] ?? 0;
$subdomains = $hp_result['subdomains'] ?? 0;
@@ -385,6 +386,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$dnsenabled = $hp_result['dnsenabled'] ?? 0;
$logviewenabled = $hp_result['logviewenabled'] ?? 0;
} else {
$nextcloud_quota = $this->getUlParam('nextcloud_quota', 'nextcloud_quota_ul', true, 0);
$diskspace = $this->getUlParam('diskspace', 'diskspace_ul', true, 0);
$traffic = $this->getUlParam('traffic', 'traffic_ul', true, 0);
$subdomains = $this->getUlParam('subdomains', 'subdomains_ul', true, 0);
@@ -404,12 +406,12 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
}
// validation
$name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true);
$firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', '', '', array(), true);
$company = \Froxlor\Validate\Validate::validate($company, 'company', '', '', array(), true);
$street = \Froxlor\Validate\Validate::validate($street, 'street', '', '', array(), true);
$name = \Froxlor\Validate\Validate::validate($name, 'name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$company = \Froxlor\Validate\Validate::validate($company, 'company', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$street = \Froxlor\Validate\Validate::validate($street, 'street', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$zipcode = \Froxlor\Validate\Validate::validate($zipcode, 'zipcode', '/^[0-9 \-A-Z]*$/', '', array(), true);
$city = \Froxlor\Validate\Validate::validate($city, 'city', '', '', array(), true);
$city = \Froxlor\Validate\Validate::validate($city, 'city', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$phone = \Froxlor\Validate\Validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$fax = \Froxlor\Validate\Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
@@ -533,6 +535,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'api_allowed' => $api_allowed,
'docroot' => $documentroot,
'guid' => $guid,
'nextcloud_quota' => $nextcloud_quota,
'diskspace' => $diskspace,
'traffic' => $traffic,
'subdomains' => $subdomains,
@@ -574,6 +577,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
`api_allowed` = :api_allowed,
`documentroot` = :docroot,
`guid` = :guid,
`nextcloud_quota` = :nextcloud_quota,
`diskspace` = :diskspace,
`traffic` = :traffic,
`subdomains` = :subdomains,
@@ -950,7 +954,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$move_to_admin = (int) ($this->getParam('move_to_admin', true, 0));
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$email = $this->getParam('email', true, $idna_convert->decode($result['email']));
$email = $this->getParam('email', true, $idna_convert->decode($result['email'] ?? ''));
$name = $this->getParam('name', true, $result['name']);
$firstname = $this->getParam('firstname', true, $result['firstname']);
$company_required = empty($result['company']) && ((! empty($name) && empty($firstname)) || (empty($name) && ! empty($firstname)) || (empty($name) && empty($firstname)));
@@ -968,6 +972,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, $result['custom_notes_show']);
$dec_places = Settings::Get('panel.decimal_places');
$nextcloud_quota = $this->getUlParam('nextcloud_quota', 'nextcloud_quota_ul', true, round($result['nextcloud_quota'], $dec_places));
$diskspace = $this->getUlParam('diskspace', 'diskspace_ul', true, round($result['diskspace'] / 1024, $dec_places));
$traffic = $this->getUlParam('traffic', 'traffic_ul', true, round($result['traffic'] / (1024 * 1024), $dec_places));
$subdomains = $this->getUlParam('subdomains', 'subdomains_ul', true, $result['subdomains']);
@@ -998,12 +1003,12 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
// validation
if ($this->isAdmin()) {
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true);
$firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', '', '', array(), true);
$company = \Froxlor\Validate\Validate::validate($company, 'company', '', '', array(), true);
$street = \Froxlor\Validate\Validate::validate($street, 'street', '', '', array(), true);
$name = \Froxlor\Validate\Validate::validate($name, 'name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$company = \Froxlor\Validate\Validate::validate($company, 'company', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$street = \Froxlor\Validate\Validate::validate($street, 'street', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$zipcode = \Froxlor\Validate\Validate::validate($zipcode, 'zipcode', '/^[0-9 \-A-Z]*$/', '', array(), true);
$city = \Froxlor\Validate\Validate::validate($city, 'city', '', '', array(), true);
$city = \Froxlor\Validate\Validate::validate($city, 'city', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$phone = \Froxlor\Validate\Validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$fax = \Froxlor\Validate\Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
@@ -1234,6 +1239,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'fax' => $fax,
'email' => $email,
'customerno' => $customernumber,
'nextcloud_quota' => $nextcloud_quota,
'diskspace' => $diskspace,
'traffic' => $traffic,
'subdomains' => $subdomains,
@@ -1276,6 +1282,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
`fax` = :fax,
`email` = :email,
`customernumber` = :customerno,
`nextcloud_quota` = :nextcloud_quota,
`diskspace` = :diskspace,
`traffic` = :traffic,
`subdomains` = :subdomains,

View File

@@ -197,6 +197,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
'NAME' => $customer['name'],
'FIRSTNAME' => $customer['firstname'],
'COMPANY' => $customer['company'],
'USERNAME' => $customer['loginname'],
'CUSTOMER_NO' => $customer['customernumber']
);

View File

@@ -65,7 +65,7 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
$id = $result['id'];
// current destination array
$result['destination_array'] = explode(' ', $result['destination']);
$result['destination_array'] = explode(' ', ($result['destination'] ?? ''));
// prepare destination
$destination = trim($destination);

View File

@@ -57,6 +57,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// parameters
$iscatchall = $this->getBoolParam('iscatchall', true, 0);
$description = $this->getParam('description', true, '');
$disablegreylist = $this->getBoolParam('disablegreylist', true, 0);
// validation
if (substr($domain, 0, 4) != 'xn--') {
@@ -76,6 +77,9 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
if (Settings::Get('catchall.catchall_enabled') != '1') {
$iscatchall = 0;
}
if (Settings::Get('mail.greylist_enabled') != '1') {
$disablegreylist = 1;
}
// check for catchall-flag
if ($iscatchall) {
@@ -124,6 +128,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`email` = :email,
`email_full` = :email_full,
`iscatchall` = :iscatchall,
`disablegreylist` = :disablegreylist,
`domainid` = :domainid,
`description` = :description
");
@@ -132,8 +137,9 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
"email" => $email,
"email_full" => $email_full,
"iscatchall" => $iscatchall,
"disablegreylist" => $disablegreylist,
"domainid" => $domain_check['id'],
"description" => $description
"description" => $description
);
Database::pexecute($stmt, $params, true, true);
@@ -172,7 +178,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$customer_ids = $this->getAllowedCustomerIds('email');
$params['idea'] = ($id <= 0 ? $emailaddr : $id);
$result_stmt = Database::prepare("SELECT v.`id`, v.`email`, v.`email_full`, v.`iscatchall`, v.`destination`, v.`customerid`, v.`popaccountid`, v.`domainid`, v.`description`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize`
$result_stmt = Database::prepare("SELECT v.`id`, v.`email`, v.`email_full`, v.`iscatchall`, v.`destination`, v.`customerid`, v.`popaccountid`, v.`domainid`, v.`description`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize`, v.`disablegreylist`
FROM `" . TABLE_MAIL_VIRTUAL . "` v
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON v.`popaccountid` = u.`id`
WHERE v.`customerid` IN (" . implode(", ", $customer_ids) . ")
@@ -235,7 +241,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// parameters
$iscatchall = $this->getBoolParam('iscatchall', true, $result['iscatchall']);
$description = $this->getParam('description', true, $result['description']);
// get needed customer info to reduce the email-address-counter by one
$customer = $this->getCustomerData();
@@ -282,7 +288,97 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
));
return $this->response(200, "successful", $result);
}
/**
* toggle greylist flag of given email address either by id or email-address
*
* @param int $id
* optional, the email-address-id
* @param string $emailaddr
* optional, the email-address
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* @param boolean $disablegreylist
* optional
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function update_greylist()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new \Exception("You cannot access this resource", 405);
}
// if enabling catchall is not allowed by settings, we do not need
// to run update()
if (Settings::Get('mail.greylist_enabled') != '1') {
\Froxlor\UI\Response::standard_error(array(
'operationnotpermitted',
'featureisdisabled'
), 'catchall', true);
}
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
$result = $this->apiCall('Emails.get', array(
'id' => $id,
'emailaddr' => $emailaddr
));
$id = $result['id'];
// parameters
$disablegreylist = $this->getBoolParam('disablegreylist', true, $result['disablegreylist']);
// get needed customer info to reduce the email-address-counter by one
$customer = $this->getCustomerData();
// check for catchall-flag
if ($disablegreylist) {
$disablegreylist = '1';
$email_parts = explode('@', $result['email_full']);
$email = '@' . $email_parts[1];
// catchall check
$stmt = Database::prepare("
SELECT `email_full` FROM `" . TABLE_MAIL_VIRTUAL . "`
WHERE `email` = :email AND `customerid` = :cid AND `disablegreylist` = '1'
");
$params = array(
"email" => $email,
"cid" => $customer['customerid']
);
$email_check = Database::pexecute_first($stmt, $params, true, true);
if ($email_check) {
\Froxlor\UI\Response::standard_error('youhavealreadyacatchallforthisdomain', '', true);
}
} else {
$disablegreylist = '0';
$email = $result['email_full'];
}
$stmt = Database::prepare("
UPDATE `" . TABLE_MAIL_VIRTUAL . "`
SET `email` = :email , `disablegreylist` = :disablegreylist
WHERE `customerid`= :cid AND `id`= :id
");
$params = array(
"email" => $email,
"disablegreylist" => $disablegreylist,
"cid" => $customer['customerid'],
"id" => $id
);
Database::pexecute($stmt, $params, true, true);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] toggled greylist-flag for email address '" . $result['email_full'] . "'");
$result = $this->apiCall('Emails.get', array(
'emailaddr' => $result['email_full']
));
return $this->response(200, "successfull", $result);
}
/**
* list all email addresses, if called from an admin, list all email addresses of all customers you are allowed to view, or specify id or loginname for one specific customer
*

View File

@@ -243,6 +243,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
'NAME' => $customer['name'],
'FIRSTNAME' => $customer['firstname'],
'COMPANY' => $customer['company'],
'USERNAME' => $customer['loginname'],
'CUSTOMER_NO' => $customer['customernumber'],
'USR_NAME' => $username,
'USR_PASS' => htmlentities(htmlentities($password)),

View File

@@ -378,9 +378,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$listen_statement = $this->getBoolParam('listen_statement', true, $result['listen_statement']);
$namevirtualhost_statement = $this->getBoolParam('namevirtualhost_statement', true, $result['namevirtualhost_statement']);
$vhostcontainer = $this->getBoolParam('vhostcontainer', true, $result['vhostcontainer']);
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, $result['specialsettings'])), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, ($result['specialsettings'] ?? ""))), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$vhostcontainer_servername_statement = $this->getParam('vhostcontainer_servername_statement', true, $result['vhostcontainer_servername_statement']);
$default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, $result['default_vhostconf_domain'])), 'default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, ($result['default_vhostconf_domain'] ?? ""))), 'default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$docroot = \Froxlor\Validate\Validate::validate($this->getParam('docroot', true, $result['docroot']), 'docroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
if ((int) Settings::Get('system.use_ssl') == 1) {
@@ -389,9 +389,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$ssl_key_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_key_file', $ssl, $result['ssl_key_file']), 'ssl_key_file', '', '', array(), true);
$ssl_ca_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_ca_file', true, $result['ssl_ca_file']), 'ssl_ca_file', '', '', array(), true);
$ssl_cert_chainfile = \Froxlor\Validate\Validate::validate($this->getParam('ssl_cert_chainfile', true, $result['ssl_cert_chainfile']), 'ssl_cert_chainfile', '', '', array(), true);
$ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, $result['ssl_specialsettings'])), 'ssl_specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, ($result['ssl_specialsettings'] ?? ""))), 'ssl_specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$include_specialsettings = $this->getBoolParam('include_specialsettings', true, $result['include_specialsettings']);
$ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, $result['ssl_default_vhostconf_domain'])), 'ssl_default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, ($result['ssl_default_vhostconf_domain'] ?? ""))), 'ssl_default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$include_default_vhostconf_domain = $this->getBoolParam('include_default_vhostconf_domain', true, $result['include_default_vhostconf_domain']);
} else {
$ssl = 0;

View File

@@ -141,6 +141,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
'NAME' => $userinfo['name'],
'FIRSTNAME' => $userinfo['firstname'],
'COMPANY' => $userinfo['company'],
'USERNAME' => $userinfo['loginname'],
'CUSTOMER_NO' => $userinfo['customernumber'],
'DB_NAME' => $username,
'DB_PASS' => htmlentities(htmlentities($password)),

View File

@@ -99,7 +99,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
}
// check whether we use that config as froxor-vhost config
if (Settings::Get('system.mod_fcgid_defaultini_ownvhost') == $row['id'] || Settings::Get('phpfpm.vhost_defaultini') == $row['id']) {
if ((Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_defaultini_ownvhost') == $row['id']) || (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.vhost_defaultini') == $row['id'])) {
$domains[] = Settings::Get('system.hostname');
}

View File

@@ -1,4 +1,5 @@
<?php
namespace Froxlor\Cron;
/**
@@ -18,6 +19,7 @@ namespace Froxlor\Cron;
* @since 0.10.0
*
*/
use Froxlor\Database\Database;
use Froxlor\Settings;
@@ -56,6 +58,12 @@ class CronConfig
SELECT * FROM `" . TABLE_PANEL_CRONRUNS . "` WHERE `isactive` = '1'
");
$binpath = Settings::Get("system.croncmdline");
// fallback as it is important
if ($binpath === null) {
$binpath = "/usr/bin/nice -n 5 /usr/bin/php -q";
}
$hour_delay = 0;
$day_delay = 5;
$month_delay = 7;
@@ -96,20 +104,14 @@ class CronConfig
}
// create entry-line
$binpath = Settings::Get("system.croncmdline");
// fallback as it is important
if ($binpath === null) {
$binpath = "/usr/bin/nice -n 5 /usr/bin/php -q";
}
$cronfile .= "root " . $binpath . " " . \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . "/scripts/froxlor_master_cronjob.php") . " --" . $row_cronentry['cronfile'] . " 1> /dev/null\n";
}
}
// php sessionclean if enabled
if ((int) Settings::Get('phpfpm.enabled') == 1) {
$cronfile .= "# Look for and purge old sessions every 30 minutes".PHP_EOL;
$cronfile .= "09,39 * * * * root " . \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . "/scripts/php-sessionclean.php") . " --froxlor-dir=" . escapeshellarg(\Froxlor\Froxlor::getInstallDir()) . " 1> /dev/null" . PHP_EOL;
$cronfile .= "# Look for and purge old sessions every 30 minutes" . PHP_EOL;
$cronfile .= "09,39 * * * * root " . $binpath . " " . \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . "/scripts/php-sessionclean.php") . " --froxlor-dir=" . escapeshellarg(\Froxlor\Froxlor::getInstallDir()) . " 1> /dev/null" . PHP_EOL;
}
if (\Froxlor\FileDir::isFreeBSD()) {
@@ -127,7 +129,7 @@ class CronConfig
$newcrontab = "";
foreach ($crontablines as $ctl) {
$ctl = trim($ctl);
if (! empty($ctl) && ! preg_match("/(.*)froxlor_master_cronjob\.php(.*)/", $ctl)) {
if (!empty($ctl) && !preg_match("/(.*)froxlor_master_cronjob\.php(.*)/", $ctl)) {
$newcrontab .= $ctl . "\n";
}
}

View File

@@ -773,20 +773,28 @@ class Apache extends HttpConfigBase
}
if (Settings::Get('system.logfiles_piped') == '1' && Settings::Get('system.logfiles_script') != '') {
// replace for error_log
$command = \Froxlor\PhpHelper::replaceVariables(Settings::Get('system.logfiles_script'), array(
'LOGFILE' => $error_log,
'DOMAIN' => $domain['domain'],
'CUSTOMER' => $domain['loginname']
));
$logfiles_text .= ' ErrorLog "|' . $command . "\"\n";
// replace for access_log
$command = \Froxlor\PhpHelper::replaceVariables(Settings::Get('system.logfiles_script'), array(
'LOGFILE' => $access_log,
'DOMAIN' => $domain['domain'],
'CUSTOMER' => $domain['loginname']
));
$logfiles_text .= ' CustomLog "|' . $command . '" ' . $logtype . "\n";
if ($domain['writeerrorlog']) {
// replace for error_log
$command = \Froxlor\PhpHelper::replaceVariables(Settings::Get('system.logfiles_script'), array(
'LOGFILE' => $error_log,
'DOMAIN' => $domain['domain'],
'CUSTOMER' => $domain['loginname']
));
$logfiles_text .= ' ErrorLog "|' . $command . "\"\n";
} else {
$logfiles_text .= ' ErrorLog "' . $error_log . '"' . "\n";
}
if ($domain['writeaccesslog']) {
// replace for access_log
$command = \Froxlor\PhpHelper::replaceVariables(Settings::Get('system.logfiles_script'), array(
'LOGFILE' => $access_log,
'DOMAIN' => $domain['domain'],
'CUSTOMER' => $domain['loginname']
));
$logfiles_text .= ' CustomLog "|' . $command . '" ' . $logtype . "\n";
} else {
$logfiles_text .= ' CustomLog "' . $access_log . '" ' . $logtype . "\n";
}
} else {
$logfiles_text .= ' ErrorLog "' . $error_log . '"' . "\n";
$logfiles_text .= ' CustomLog "' . $access_log . '" ' . $logtype . "\n";

View File

@@ -635,6 +635,9 @@ EOC;
$acmesh_result = \Froxlor\FileDir::safe_exec(self::getAcmeSh() . " --upgrade --auto-upgrade 0");
// check for activated cron
$acmesh_result2 = \Froxlor\FileDir::safe_exec(self::getAcmeSh() . " --install-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));
// set default CA
$acmesh_result3 = \Froxlor\FileDir::safe_exec(self::getAcmeSh() . " --set-default-ca --server " . self::$apiserver);
// log messages
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) . "\n" . implode("\n", $acmesh_result3));
}
}

View File

@@ -760,6 +760,7 @@ class Lighttpd extends HttpConfigBase
'customerid' => $domain['customerid']
));
$diroption_text = '';
while ($row_htpasswds = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if ($this->auth_backend_loaded[$domain['ipandport']] != 'yes' && $this->auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') {
$filename = $domain['customerid'] . '.htpasswd';
@@ -836,6 +837,7 @@ class Lighttpd extends HttpConfigBase
}
}
$servernames_text = '';
for ($i = 0; $i < sizeof($server_string); $i ++) {
$data = $server_string[$i];

View File

@@ -1035,8 +1035,10 @@ class Nginx extends HttpConfigBase
protected function getStats($domain, $single)
{
$stats_text = '';
$stats_text = '';
return $stats_text;
// define basic path to the stats
if (Settings::Get('system.awstats_enabled') == '1') {
$alias_dir = \Froxlor\FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/');

View File

@@ -4,6 +4,7 @@ namespace Froxlor\Cron\System;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\FroxlorLogger;
use Froxlor\FileDir;
/**
* This file is part of the Froxlor project.
@@ -150,13 +151,17 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron
$sql_root = Database::getSqlData();
Database::needRoot(false);
$mysqlcnf_file = tempnam("/tmp", "frx");
$mysqlcnf = "[mysqldump]\npassword=".$sql_root['passwd']."\n";
file_put_contents($mysqlcnf_file, $mysqlcnf);
$has_dbs = false;
while ($row = $sel_stmt->fetch()) {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> mysqldump -u ' . escapeshellarg($sql_root['user']) . ' -pXXXXX ' . $row['databasename'] . ' > ' . \Froxlor\FileDir::makeCorrectFile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql'));
$bool_false = false;
\Froxlor\FileDir::safe_exec('mysqldump -u ' . escapeshellarg($sql_root['user']) . ' -p' . $sql_root['passwd'] . ' ' . $row['databasename'] . ' > ' . \Froxlor\FileDir::makeCorrectFile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql'), $bool_false, array(
\Froxlor\FileDir::safe_exec('mysqldump --defaults-file=' . escapeshellarg($mysqlcnf_file) .' -u ' . escapeshellarg($sql_root['user']) . ' ' . $row['databasename'] . ' > ' . FileDir::makeCorrectFile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql'), $bool_false, [
'>'
));
]);
$has_dbs = true;
}
@@ -164,6 +169,8 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron
$create_backup_tar_data .= './mysql ';
}
unlink($mysqlcnf_file);
unset($sql_root);
}

View File

@@ -324,8 +324,8 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
if (file_exists($logsdir) && $logsdir != '/' && $logsdir != \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.logfiles_directory')) && substr($logsdir, 0, strlen(Settings::Get('system.logfiles_directory'))) == Settings::Get('system.logfiles_directory')) {
// build up wildcard for webX-{access,error}.log{*}
$logfiles .= '-*';
\Froxlor\FileDir::safe_exec('rm -f ' . escapeshellarg($logfiles));
$logsdir .= '-*';
\Froxlor\FileDir::safe_exec('rm -f ' . escapeshellarg($logsdir));
}
}
}

View File

@@ -36,7 +36,7 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
if ((int) Settings::Get('system.report_trafficmax') > 0) {
// Warn the customers at xx% traffic-usage
$result_stmt = Database::prepare("
SELECT `c`.`customerid`, `c`.`customernumber`, `c`.`adminid`, `c`.`name`, `c`.`firstname`,
SELECT `c`.`customerid`, `c`.`loginname`, `c`.`customernumber`, `c`.`adminid`, `c`.`name`, `c`.`firstname`,
`c`.`company`, `c`.`traffic`, `c`.`email`, `c`.`def_language`,
`a`.`name` AS `adminname`, `a`.`email` AS `adminmail`,
(SELECT SUM(`t`.`http` + `t`.`ftp_up` + `t`.`ftp_down` + `t`.`mail`)
@@ -60,6 +60,7 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
'name' => $row['name'],
'firstname' => $row['firstname'],
'company' => $row['company'],
'loginname' => $row['loginname'],
'customernumber' => $row['customernumber']
);
$replace_arr = array(
@@ -67,6 +68,7 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
'NAME' => $rep_userinfo['name'],
'FIRSTNAME' => $rep_userinfo['firstname'],
'COMPANY' => $rep_userinfo['company'],
'USERNAME' => $rep_userinfo['loginname'],
'CUSTOMER_NO' => $rep_userinfo['customernumber'],
'TRAFFIC' => round(($row['traffic'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'TRAFFICUSED' => round(($row['traffic_used'] / 1024), 2), /* traffic is stored in KB, template uses MB */
@@ -354,7 +356,7 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
* report about diskusage for customers
*/
$result_stmt = Database::query("
SELECT `c`.`customerid`, `c`.`customernumber`, `c`.`adminid`, `c`.`name`, `c`.`firstname`,
SELECT `c`.`customerid`, `c`.`loginname`, `c`.`customernumber`, `c`.`adminid`, `c`.`name`, `c`.`firstname`,
`c`.`company`, `c`.`diskspace`, `c`.`diskspace_used`, `c`.`email`, `c`.`def_language`,
`a`.`name` AS `adminname`, `a`.`email` AS `adminmail`
FROM `" . TABLE_PANEL_CUSTOMERS . "` AS `c`
@@ -373,6 +375,7 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
'name' => $row['name'],
'firstname' => $row['firstname'],
'company' => $row['company'],
'loginname' => $row['loginname'],
'customernumber' => $row['customernumber']
);
$replace_arr = array(
@@ -380,6 +383,7 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
'NAME' => $rep_userinfo['name'],
'FIRSTNAME' => $rep_userinfo['firstname'],
'COMPANY' => $rep_userinfo['company'],
'USERNAME' => $rep_userinfo['loginname'],
'CUSTOMER_NO' => $rep_userinfo['customernumber'],
'DISKAVAILABLE' => round(($row['diskspace'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'DISKUSED' => round($row['diskspace_used'] / 1024, 2), /* traffic is stored in KB, template uses MB */

View File

@@ -190,10 +190,16 @@ class Database
*/
public static function getSqlUsernameLength()
{
// MySQL user names can be up to 32 characters long (16 characters before MySQL 5.7.8).
$mysql_max = 32;
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.8', '<')) {
$mysql_max = 16;
// MariaDB supports up to 80 characters but only 64 for databases and as we use the loginname also for
// database names, we set the limit to 64 here
if (strpos(strtolower(Database::getAttribute(\PDO::ATTR_SERVER_VERSION)), "mariadb") !== false) {
$mysql_max = 64;
} else {
// MySQL user names can be up to 32 characters long (16 characters before MySQL 5.7.8).
$mysql_max = 32;
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.8', '<')) {
$mysql_max = 16;
}
}
return $mysql_max;
}

View File

@@ -173,7 +173,10 @@ class DbManager
if (isset($users[$username]) && is_array($users[$username]) && isset($users[$username]['hosts']) && is_array($users[$username]['hosts'])) {
$password = $users[$username]['password'];
$password = [
'password' => $users[$username]['password'],
'plugin' => $users[$username]['plugin']
];
foreach ($mysql_access_host_array as $mysql_access_host) {

View File

@@ -1,4 +1,5 @@
<?php
namespace Froxlor\Database\Manager;
use Froxlor\Database\Database;
@@ -68,7 +69,7 @@ class DbManagerMySQL
* username and sets the password for that user the given access_host
*
* @param string $username
* @param string $password
* @param string|array $password
* @param string $access_host
* @param bool $p_encrypted
* optional, whether the password is encrypted or not, default false
@@ -77,7 +78,13 @@ class DbManagerMySQL
*/
public function grantPrivilegesTo($username = null, $password = null, $access_host = null, $p_encrypted = false, $update = false)
{
if (! $update) {
$pwd_plugin = 'mysql_native_password';
if (is_array($password) && count($password) == 2) {
$pwd_plugin = $password['plugin'];
$password = $password['password'];
}
if (!$update) {
// create user
if ($p_encrypted) {
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) {
@@ -86,7 +93,7 @@ class DbManagerMySQL
");
} else {
$stmt = Database::prepare("
CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED WITH mysql_native_password AS :password
CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED WITH " . $pwd_plugin . " AS :password
");
}
} else {
@@ -115,7 +122,7 @@ class DbManagerMySQL
}
} else {
if ($p_encrypted) {
$stmt = Database::prepare("ALTER USER :username@:host IDENTIFIED WITH mysql_native_password AS :password");
$stmt = Database::prepare("ALTER USER :username@:host IDENTIFIED WITH " . $pwd_plugin . " AS :password");
} else {
$stmt = Database::prepare("ALTER USER :username@:host IDENTIFIED BY :password");
}
@@ -136,7 +143,7 @@ class DbManagerMySQL
*/
public function deleteDatabase($dbname = null)
{
if (Database::getAttribute(\PDO::ATTR_SERVER_VERSION) < '5.0.2') {
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.0.2', '<')) {
// failsafe if user has been deleted manually (requires MySQL 4.1.2+)
$stmt = Database::prepare("REVOKE ALL PRIVILEGES, GRANT OPTION FROM `" . $dbname . "`");
Database::pexecute($stmt, array(), false);
@@ -247,9 +254,10 @@ class DbManagerMySQL
$allsqlusers = array();
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if ($user_only == false) {
if (! isset($allsqlusers[$row['User']]) || ! is_array($allsqlusers[$row['User']])) {
if (!isset($allsqlusers[$row['User']]) || !is_array($allsqlusers[$row['User']])) {
$allsqlusers[$row['User']] = array(
'password' => $row['Password'] ?? $row['authentication_string'],
'plugin' => $row['plugin'] ?? 'mysql_native_password',
'hosts' => array()
);
}

View File

@@ -408,7 +408,20 @@ class Dns
$soa_record = new DnsEntry('@', 'SOA', $soa_content);
array_unshift($zonerecords, $soa_record);
}
//DMARC
//_dmarc 18000 IN TXT ("v=DMARC1; p=reject; fo=1; adkim=r; aspf=r; pct=100; rf=afrf; r"
// "i=86400; rua=mailto:dmarc@zweiseitendergeschichte.de;")
if ($domain['isemaildomain'] == '1') {
$dmarc_txt = '("v=DMARC1; p=reject; fo=1; adkim=r; aspf=r; pct=100; rf=afrf; ri=86400; ruf=mailto:dmarc@'.$domain['domain'].'; rua=mailto:dmarc@'.$domain['domain'].';")';
$dmarc_record = new DnsEntry('_dmarc', 'TXT',$dmarc_txt );
array_unshift($zonerecords,$dmarc_record);
}
if ($domain['isemaildomain'] == '1') {
$dkim_txt = 'v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAosq0CmLqEzJJxIHkQwG1Xwk6CSyHHWSDXL9BHCKzY9lJXH7a23PogVlLvUBYaAgBtFOpsKuUCBl+/g6rOqgVXKg0OpYdpgTxZyz1i4NcubGFLifQGnF8ZKpIEDqIzmLI6SbH+9DKwYA319sXAR6feZI4g5bWqF07t/kzA5LN+2V5QnDQ3th++GPRl5rmWF6uoidIRD85UZVEX4s3J1hce0k6tRb2aEozCJaSXHUwyarmbbX/5rky467QQ+45Uy0q9CNaMMu1IX5eybhLRxYXK1k0TfIRJv4FH1UFLlq2QoGC7d+KvLrUabhzQ5wbdZkWuVgLFZ7CL2NegfzO6YeEcQIDAQAB';
$dkim_record = new DnsEntry('mx._domainkey', 'TXT', $dkim_txt);
array_unshift($zonerecords, $dkim_record);
}
$zone = new DnsZone((int) Settings::Get('system.defaultttl'), $domain['domain'], $domain['bindserial'], $zonerecords);
return $zone;

View File

@@ -1,4 +1,5 @@
<?php
namespace Froxlor;
use Froxlor\Database\Database;
@@ -96,14 +97,14 @@ class FileDir
$subdir = self::makeCorrectDir($subdir);
$subdirs = array();
if ($within_homedir || ! $allow_notwithinhomedir) {
if ($within_homedir || !$allow_notwithinhomedir) {
$subdirlen = strlen($subdir);
$offset = 0;
while ($offset < $subdirlen) {
$offset = strpos($subdir, '/', $offset);
$subdirelem = substr($subdir, 0, $offset);
$offset ++;
$offset++;
array_push($subdirs, self::makeCorrectDir($homeDir . $subdirelem));
}
} else {
@@ -113,7 +114,7 @@ class FileDir
$subdirs = array_unique($subdirs);
sort($subdirs);
foreach ($subdirs as $sdir) {
if (! is_dir($sdir)) {
if (!is_dir($sdir)) {
$sdir = self::makeCorrectDir($sdir);
self::safe_exec('mkdir -p ' . escapeshellarg($sdir));
// place index
@@ -247,7 +248,7 @@ class FileDir
*/
public static function makeCorrectFile($filename)
{
if (! isset($filename) || trim($filename) == '') {
if (!isset($filename) || trim($filename) == '') {
$error = 'Given filename for function ' . __FUNCTION__ . ' is empty.' . "\n";
$error .= 'This is very dangerous and should not happen.' . "\n";
$error .= 'Please inform the Froxlor team about this issue so they can fix it.';
@@ -278,7 +279,7 @@ class FileDir
{
if (is_string($dir) && strlen($dir) > 0) {
$dir = trim($dir);
if (substr($dir, - 1, 1) != '/') {
if (substr($dir, -1, 1) != '/') {
$dir .= '/';
}
if (substr($dir, 0, 1) != '/') {
@@ -355,7 +356,7 @@ class FileDir
$destination = substr($destination, 1);
}
if (substr($destination, - 1, 1) == ' ') {
if (substr($destination, -1, 1) == ' ') {
$destination = substr($destination, 0, strlen($destination) - 1);
}
@@ -390,7 +391,7 @@ class FileDir
// but dirList holds the paths with starting slash
// so we just add one here to get the correct
// default path selected, #225
if (substr($value, 0, 1) != '/' && ! $dom) {
if (substr($value, 0, 1) != '/' && !$dom) {
$value = '/' . $value;
}
@@ -408,34 +409,22 @@ class FileDir
natcasesort($dirList);
if (sizeof($dirList) > 0) {
if (sizeof($dirList) <= 100) {
$_field = '';
foreach ($dirList as $dir) {
if (strpos($dir, $path) === 0) {
$dir = substr($dir, strlen($path));
// docroot cut off of current directory == empty -> directory is the docroot
if (empty($dir)) {
$dir = '/';
}
$dir = self::makeCorrectDir($dir);
$_field = '';
foreach ($dirList as $dir) {
if (strpos($dir, $path) === 0) {
$dir = substr($dir, strlen($path));
// docroot cut off of current directory == empty -> directory is the docroot
if (empty($dir)) {
$dir = '/';
}
$_field .= \Froxlor\UI\HTML::makeoption($dir, $dir, $value);
$dir = self::makeCorrectDir($dir);
}
$field = array(
'type' => 'select',
'value' => $_field
);
} else {
// remove starting slash we added
// for the Dropdown, #225
$value = substr($value, 1);
// $field = $lng['panel']['toomanydirs'];
$field = array(
'type' => 'text',
'value' => htmlspecialchars($value),
'note' => $lng['panel']['toomanydirs']
);
$_field .= \Froxlor\UI\HTML::makeoption($dir, $dir, $value);
}
$field = array(
'type' => 'select',
'value' => $_field
);
} else {
// $field = $lng['panel']['dirsmissing'];
// $field = '<input type="hidden" name="path" value="/" />';
@@ -489,22 +478,31 @@ class FileDir
$filter = function ($file, $key, $iterator) use ($exclude) {
if (in_array($file->getFilename(), $exclude)) {
return false;
} elseif (substr($file->getFilename(), 0, 1) == '.') {
// also hide hidden folders
return false;
}
return true;
};
// create RecursiveIteratorIterator
$its = new \RecursiveIteratorIterator(new \RecursiveCallbackFilterIterator(new System\IgnorantRecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), $filter));
$its = new \RecursiveIteratorIterator(
new \RecursiveCallbackFilterIterator(
new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS),
$filter
),
\RecursiveIteratorIterator::SELF_FIRST,
\RecursiveIteratorIterator::CATCH_GET_CHILD
);
// we can limit the recursion-depth, but will it be helpful or
// will people start asking "why do I only see 2 subdirectories, i want to use /a/b/c"
// let's keep this in mind and see whether it will be useful
// @TODO
// $its->setMaxDepth(2);
$its->setMaxDepth(2);
// check every file
foreach ($its as $fullFileName => $it) {
if ($it->isDir() && (fileowner($fullFileName) == $uid || filegroup($fullFileName) == $gid)) {
$_fileList[] = self::makeCorrectDir(dirname($fullFileName));
$_fileList[] = self::makeCorrectDir($fullFileName);
}
}
$_fileList[] = $path;
@@ -525,7 +523,7 @@ class FileDir
*/
public static function isFreeBSD($exact = false)
{
if (($exact && PHP_OS == 'FreeBSD') || (! $exact && stristr(PHP_OS, 'BSD'))) {
if (($exact && PHP_OS == 'FreeBSD') || (!$exact && stristr(PHP_OS, 'BSD'))) {
return true;
}
return false;

View File

@@ -7,7 +7,7 @@ final class Froxlor
{
// Main version variable
const VERSION = '0.10.34';
const VERSION = '0.10.38.3';
// Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '202112310';

View File

@@ -63,7 +63,7 @@ class PhpHelper
$subject[$field] = self::htmlentitiesArray($subject[$field], $fields, $quote_style, $charset);
}
}
} else {
} elseif (!empty($subject)) {
$subject = htmlentities($subject, $quote_style, $charset);
}

View File

@@ -1,4 +1,5 @@
<?php
namespace Froxlor\Settings;
use Froxlor\Database\Database;
@@ -63,9 +64,9 @@ class Store
if (count($ids) > 0) {
$defaultips_new = explode(',', $newfieldvalue);
if (! empty($defaultips_old) && ! empty($newfieldvalue)) {
if (!empty($defaultips_old) && !empty($newfieldvalue)) {
$in_value = $defaultips_old . ", " . $newfieldvalue;
} elseif (! empty($defaultips_old) && empty($newfieldvalue)) {
} elseif (!empty($defaultips_old) && empty($newfieldvalue)) {
$in_value = $defaultips_old;
} else {
$in_value = $newfieldvalue;
@@ -280,11 +281,11 @@ class Store
if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'mysql_access_host') {
$mysql_access_host_array = array_map('trim', explode(',', $newfieldvalue));
if (in_array('127.0.0.1', $mysql_access_host_array) && ! in_array('localhost', $mysql_access_host_array)) {
if (in_array('127.0.0.1', $mysql_access_host_array) && !in_array('localhost', $mysql_access_host_array)) {
$mysql_access_host_array[] = 'localhost';
}
if (! in_array('127.0.0.1', $mysql_access_host_array) && in_array('localhost', $mysql_access_host_array)) {
if (!in_array('127.0.0.1', $mysql_access_host_array) && in_array('localhost', $mysql_access_host_array)) {
$mysql_access_host_array[] = '127.0.0.1';
}
@@ -306,8 +307,8 @@ class Store
private static function cleanMySQLAccessHost($value)
{
if (substr($value, 0, 1) == '[' && substr($value, - 1) == ']') {
return substr($value, 1, - 1);
if (substr($value, 0, 1) == '[' && substr($value, -1) == ']') {
return substr($value, 1, -1);
}
return $value;
}
@@ -370,66 +371,85 @@ class Store
}
public static function storeSettingImage($fieldname, $fielddata)
{
if (isset($fielddata['settinggroup'], $fielddata['varname']) && is_array($fielddata) && $fielddata['settinggroup'] !== '' && $fielddata['varname'] !== '') {
$save_to = null;
$path = \Froxlor\Froxlor::getInstallDir().'/img/';
$path = \Froxlor\FileDir::makeCorrectDir($path);
{
if (isset($fielddata['settinggroup'], $fielddata['varname']) && is_array($fielddata) && $fielddata['settinggroup'] !== '' && $fielddata['varname'] !== '') {
$save_to = null;
$path = \Froxlor\Froxlor::getInstallDir() . '/img/';
$path = \Froxlor\FileDir::makeCorrectDir($path);
// New file?
if (isset($_FILES[$fieldname]) && $_FILES[$fieldname]['tmp_name']) {
// Make sure upload directory exists
if (!is_dir($path) && !mkdir($path, 0775)) {
throw new \Exception("img directory does not exist and cannot be created");
}
// New file?
if (isset($_FILES[$fieldname]) && $_FILES[$fieldname]['tmp_name']) {
// Make sure upload directory exists
if (!is_dir($path) && !mkdir($path, 0775)) {
throw new \Exception("img directory does not exist and cannot be created");
}
// Make sure we can write to the upload directory
if (!is_writable($path)) {
if (!chmod($path, 0775)) {
throw new \Exception("Cannot write to img directory");
}
}
// Make sure we can write to the upload directory
if (!is_writable($path)) {
if (!chmod($path, 0775)) {
throw new \Exception("Cannot write to img directory");
}
}
// Make sure mime-type matches an image
if (!in_array(mime_content_type($_FILES[$fieldname]['tmp_name']), ['image/jpeg','image/jpg','image/png','image/gif'])) {
throw new \Exception("Uploaded file not a valid image");
}
// Make sure mime-type matches an image
if (function_exists('finfo_open')) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $_FILES[$fieldname]['tmp_name']);
finfo_close($finfo);
} else {
$mimetype = mime_content_type($_FILES[$fieldname]['tmp_name']);
}
if (empty($mimetype)) {
$mimetype = 'application/octet-stream';
}
if (!in_array($mimetype, ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'])) {
throw new \Exception("Uploaded file is not a valid image");
}
// Determine file extension
$spl = explode('.', $_FILES[$fieldname]['name']);
$file_extension = strtolower(array_pop($spl));
unset($spl);
// Determine file extension
$spl = explode('.', $_FILES[$fieldname]['name']);
$file_extension = strtolower(array_pop($spl));
unset($spl);
// Move file
if (!move_uploaded_file($_FILES[$fieldname]['tmp_name'], $path.$fielddata['image_name'].'.'.$file_extension)) {
throw new \Exception("Unable to save image to img folder");
}
if (!in_array($file_extension, [
'jpeg',
'jpg',
'png',
'gif'
])) {
throw new Exception("Invalid file-extension, use one of: jpeg, jpg, png, gif");
}
$save_to = 'img/'.$fielddata['image_name'].'.'.$file_extension.'?v='.time();
}
// Move file
if (!move_uploaded_file($_FILES[$fieldname]['tmp_name'], $path . $fielddata['image_name'] . '.' . $file_extension)) {
throw new \Exception("Unable to save image to img folder");
}
// Delete file?
if ($fielddata['value'] !== "" && array_key_exists($fieldname.'_delete', $_POST) && $_POST[$fieldname.'_delete']) {
@unlink(\Froxlor\Froxlor::getInstallDir() . '/' . explode('?', $fielddata['value'], 2)[0]);
$save_to = '';
}
$save_to = 'img/' . $fielddata['image_name'] . '.' . $file_extension . '?v=' . time();
}
// Nothing changed
if ($save_to === null) {
return array(
$fielddata['settinggroup'] . '.' . $fielddata['varname'] => $fielddata['value']
);
}
// Delete file?
if ($fielddata['value'] !== "" && array_key_exists($fieldname . '_delete', $_POST) && $_POST[$fieldname . '_delete']) {
@unlink(\Froxlor\Froxlor::getInstallDir() . '/' . explode('?', $fielddata['value'], 2)[0]);
$save_to = '';
}
if (Settings::Set($fielddata['settinggroup'] . '.' . $fielddata['varname'], $save_to) === false) {
return false;
}
// Nothing changed
if ($save_to === null) {
return array(
$fielddata['settinggroup'] . '.' . $fielddata['varname'] => $fielddata['value']
);
}
return array(
$fielddata['settinggroup'] . '.' . $fielddata['varname'] => $save_to
);
}
if (Settings::Set($fielddata['settinggroup'] . '.' . $fielddata['varname'], $save_to) === false) {
return false;
}
return false;
}
return array(
$fielddata['settinggroup'] . '.' . $fielddata['varname'] => $save_to
);
}
return false;
}
}

View File

@@ -1,21 +0,0 @@
<?php
namespace Froxlor\System;
/**
* If you use RecursiveDirectoryIterator with RecursiveIteratorIterator and run
* into UnexpectedValueException you may use this little hack to ignore those
* directories, such as lost+found on linux.
* (User "antennen" @ http://php.net/manual/en/class.recursivedirectoryiterator.php#101654)
*/
class IgnorantRecursiveDirectoryIterator extends \RecursiveDirectoryIterator
{
public function getChildren()
{
try {
return new IgnorantRecursiveDirectoryIterator($this->getPathname());
} catch (\UnexpectedValueException $e) {
return new \RecursiveArrayIterator(array());
}
}
}

14
lib/config.inc.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
/**
* change the options below to either true or false
*/
return [
/**
* enable/disable the possibility to update froxlor from within the web-interface,
* recommended value for debian/ubuntu package users is false to rely on apt and not have version mixup.
* This is also useful for providers that manage the servers but give admin access to froxlor to handle
* updates the way the providers does it (e.g. automation, etc.)
*/
'enable_webupdate' => true,
];

View File

@@ -3561,7 +3561,7 @@ postmaster_address = postmaster@<SERVERNAME>
protocol lda {
# Space separated list of plugins to load (default is global mail_plugins).
#mail_plugins = $mail_plugins
mail_plugins = $mail_plugins quota sieve
}
]]>
</content>

View File

@@ -3557,7 +3557,7 @@ postmaster_address = postmaster@<SERVERNAME>
protocol lda {
# Space separated list of plugins to load (default is global mail_plugins).
#mail_plugins = $mail_plugins
mail_plugins = $mail_plugins quota sieve
}
]]>
</content>

View File

@@ -189,6 +189,14 @@ return array(
'title' => $lng['admin']['servicedata'],
'image' => 'icons/user_add.png',
'fields' => array(
'nextcloud_quota' => array(
'label' => $lng['customer']['nextcloud_quota'] . ' (' . $lng['customer']['gib'] . ')',
'type' => 'textul',
'value' => 0,
'maxlength' => 16,
'mandatory' => true,
'ul_field' => $nextcloud_quota_ul
),
'diskspace' => array(
'label' => $lng['customer']['diskspace'] . ' (' . $lng['customer']['mib'] . ')',
'type' => 'textul',

View File

@@ -195,6 +195,14 @@ return array(
'title' => $lng['admin']['servicedata'],
'image' => 'icons/user_edit.png',
'fields' => array(
'nextcloud_quota' => array(
'label' => $lng['customer']['nextcloud_quota'] . ' (' . $lng['customer']['gib'] . ')',
'type' => 'textul',
'value' => $result['nextcloud_quota'],
'maxlength' => 16,
'mandatory' => true,
'ul_field' => $nextcloud_quota_ul
),
'diskspace' => array(
'label' => $lng['customer']['diskspace'] . ' (' . $lng['customer']['mib'] . ')',
'type' => 'textul',

View File

@@ -126,7 +126,7 @@ return array(
$result['ssl_redirect']
)
),
'letsencrypt' => array(
/** 'letsencrypt' => array(
'visible' => \Froxlor\Settings::Get('system.leenabled') == '1' ? true : false,
'label' => $lng['customer']['letsencrypt']['title'],
'desc' => $lng['customer']['letsencrypt']['description'],
@@ -140,7 +140,7 @@ return array(
'value' => array(
$result['letsencrypt']
)
),
), */
'http2' => array(
'visible' => ($ssl_ipsandports != '' ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' && \Froxlor\Settings::Get('system.http2_support') == '1',
'label' => $lng['admin']['domain_http2']['title'],

View File

@@ -1,5 +1,6 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
@@ -45,6 +46,15 @@ return array(
)
),
'value' => array()
),
'disablegreylist' => array(
'label' => $lng['emails']['greylist'],
'type' => 'checkbox',
'values' => array(
array ('label' => $lng['panel']['yes'], 'value' => '1')
),
'visible' => (\Froxlor\Settings::Get('mail.greylist_enabled') == '1' ? true : false),
'value' => array(\Froxlor\Settings::Get('mail.greylist_disabled_default'))
)
)
)

View File

@@ -52,6 +52,12 @@ return array(
'type' => 'label',
'value' => ($result['iscatchall'] == 0 ? $lng['panel']['no'] : $lng['panel']['yes']) . ' [<a href="' . $filename . '?page=' . $page . '&amp;action=togglecatchall&amp;id=' . $result['id'] . '&amp;s=' . $s . '">' . $lng['panel']['toggle'] . '</a>]'
),
'mail_greylist' => array(
'visible' => (\Froxlor\Settings::Get('mail.greylist_enabled') == '1' ? true : false),
'label' => $lng['emails']['greylist'],
'type' => 'label',
'value' => ($result['disablegreylist'] == 0 ? $lng['panel']['no'] : $lng['panel']['yes']).' [<a href="'.$filename.'?page='.$page.'&amp;action=togglegreylist&amp;id='.$result['id'].'&amp;s='.$s.'">'.$lng['panel']['toggle'].'</a>]'
),
'mail_fwds' => array(
'label' => $lng['emails']['forwarders'] . ' (' . $forwarders_count . ')',
'type' => 'label',

View File

@@ -59,7 +59,7 @@ header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
// Inline-JS is no longer allowed and used
// See: http://people.mozilla.org/~bsterne/content-security-policy/index.html
// New stuff see: https://www.owasp.org/index.php/List_of_useful_HTTP_headers and https://www.owasp.org/index.php/Content_Security_Policy
$csp_content = "default-src 'self'; script-src 'self'; connect-src 'self'; img-src 'self' data:; style-src 'self';";
$csp_content = "default-src 'self'; script-src 'self'; connect-src 'self'; img-src 'self' data:; style-src 'self'; object-src 'self'; frame-src 'self'; frame-ancestors 'self';";
header("Content-Security-Policy: " . $csp_content);
header("X-Content-Security-Policy: " . $csp_content);
header("X-WebKit-CSP: " . $csp_content);

View File

@@ -72,6 +72,7 @@ $lng['customer']['domains'] = 'Domains';
$lng['customer']['unlimited'] = '∞';
$lng['customer']['mib'] = 'MiB';
$lng['customer']['gib'] = 'GiB';
$lng['customer']['nextcloud_quota'] = 'Nextcloud Quota';
/**
* Customermenue
@@ -142,6 +143,7 @@ $lng['emails']['from'] = 'Source';
$lng['emails']['to'] = 'Destination';
$lng['emails']['forwarders'] = 'Forwarders';
$lng['emails']['forwarder_add'] = 'Create forwarder';
$lng['emails']['greylist'] = 'Disable greylisting';
/**
* FTP
@@ -384,7 +386,10 @@ $lng['serversettings']['nameservers']['title'] = 'Nameservers';
$lng['serversettings']['nameservers']['description'] = 'A comma separated list containing the hostnames of all nameservers. The first one will be the primary one.';
$lng['serversettings']['mxservers']['title'] = 'MX servers';
$lng['serversettings']['mxservers']['description'] = 'A comma separated list containing a pair of a number and a hostname separated by whitespace (e.g. \'10 mx.example.com\') containing the mx servers.';
$lng['serversettings']['greylist_enabled']['title'] = 'Activate greylisting';
$lng['serversettings']['greylist_enabled']['description'] = 'Does the Mailserver implement greylisting?';
$lng['serversettings']['greylist_disabled_default']['title'] = 'Disable Greylisting initially';
$lng['serversettings']['greylist_disabled_default']['description'] = 'When new accounts are created, should greylisting be disabled?';
/**
* CHANGED BETWEEN 1.2.12 and 1.2.13
*/
@@ -673,6 +678,7 @@ $lng['admin']['message'] = 'Write a Message';
$lng['admin']['text'] = 'Message';
$lng['menu']['message'] = 'Messages';
$lng['error']['errorsendingmail'] = 'The message to "%s" failed';
$lng['error']['errorsendingmailpub'] = 'The message to the given email-address failed';
$lng['error']['cannotreaddir'] = 'Unable to read directory "%s"';
$lng['message']['success'] = 'Successfully sent message to %s recipients';
$lng['message']['norecipients'] = 'No e-mail has been sent because there are no recipients in the database';
@@ -760,7 +766,7 @@ $lng['pwdreminder']['success'] = 'Password reset successfully requested. Please
// ADDED IN 1.2.19-svn18
$lng['serversettings']['allow_password_reset']['title'] = 'Allow password reset by customers';
$lng['pwdreminder']['notallowed'] = 'Password reset is disabled';
$lng['pwdreminder']['notallowed'] = 'Unknown user or password reset is disabled';
// ADDED IN 1.2.19-svn21
@@ -2138,3 +2144,8 @@ $lng['serversettings']['phpfpm_settings']['allow_all_customers']['description']
$lng['error']['pathmustberelative'] = 'The user does not have the permission to specify directories outside the customers home-directory. Please specify a relative path (no leading /).';
$lng['serversettings']['acmeshpath']['title'] = 'Path to acme.sh';
$lng['serversettings']['acmeshpath']['description'] = 'Set this to where acme.sh is installed to, including the acme.sh script<br>Default is <b>/root/.acme.sh/acme.sh</b>';
$lng['question']['api_reallydelete'] = 'Do you really want to delete the api-key?';
$lng['question']['api_reallyadd'] = 'Do you really want to create a new api-key?';
$lng['question']['dnsentry_reallydelete'] = 'Do you really want to delete the dns entry?';
$lng['question']['certificate_reallydelete'] = 'Do you really want to delete the certificate?';

View File

@@ -139,6 +139,7 @@ $lng['emails']['from'] = 'Von';
$lng['emails']['to'] = 'Nach';
$lng['emails']['forwarders'] = 'Weiterleitungen';
$lng['emails']['forwarder_add'] = 'Weiterleitung hinzufügen';
$lng['emails']['greylist'] = 'Greylisting ausschalten';
/**
* FTP
@@ -379,6 +380,10 @@ $lng['serversettings']['nameservers']['title'] = 'Nameserver';
$lng['serversettings']['nameservers']['description'] = 'Eine durch Komma getrennte Liste mit den Hostnamen aller Nameserver. Der Erste ist der Primäre.';
$lng['serversettings']['mxservers']['title'] = 'MX-Server';
$lng['serversettings']['mxservers']['description'] = 'Eine durch Komma getrenne Liste, die ein Paar mit einer Nummer und den Hostnamen einen MX-Servers, getrennt durch ein Leerzeichen, enthält (z. B. \'10 mx.example.tld\').';
$lng['serversettings']['greylist_enabled']['title'] = 'Greylisting aktivieren';
$lng['serversettings']['greylist_enabled']['description'] = 'Greylisting aktivieren?';
$lng['serversettings']['greylist_disabled_default']['title'] = 'Greylisting standardmaessig aus?';
$lng['serversettings']['greylist_disabled_default']['description'] = 'Default Wert beim Erstellen neuer Accounts';
/**
* CHANGED BETWEEN 1.2.12 and 1.2.13
@@ -666,6 +671,7 @@ $lng['admin']['message'] = 'Rundmail senden';
$lng['admin']['text'] = 'Nachricht';
$lng['menu']['message'] = 'Nachrichten';
$lng['error']['errorsendingmail'] = 'Das Versenden der Nachricht an "%s" schlug fehl.';
$lng['error']['errorsendingmailpub'] = 'Das Versenden der Nachricht an die angegebene E-Mail Adresse schlug fehl.';
$lng['error']['cannotreaddir'] = 'Der Ordner "%s" kann nicht gelesen werden';
$lng['message']['success'] = 'Nachricht erfolgreich an "%s" Empfänger gesendet';
$lng['message']['norecipients'] = 'Es wurde keine E-Mail versendet, da sich keine Empfänger in der Datenbank befinden';
@@ -753,7 +759,7 @@ $lng['pwdreminder']['success'] = 'Das Zurücksetzen des Passworts wurde erfolgre
// ADDED IN 1.2.19-svn18
$lng['serversettings']['allow_password_reset']['title'] = 'Erlaube das Zurücksetzen des Kundenpassworts.';
$lng['pwdreminder']['notallowed'] = 'Das Zurücksetzen des Passworts ist deaktiviert.';
$lng['pwdreminder']['notallowed'] = 'Unbekannter Benutzer oder Zurücksetzen des Passworts ist deaktiviert.';
// ADDED IN 1.2.19-svn21
@@ -1784,3 +1790,8 @@ $lng['serversettings']['phpfpm_settings']['allow_all_customers']['description']
$lng['error']['pathmustberelative'] = 'Der Benutzer hat nicht die benötigten Berechtigungen, um Pfade außerhalb des Kunden-Heimatverzeichnisses anzugeben. Bitte einen relativen Pfad angeben (kein führendes /).';
$lng['serversettings']['acmeshpath']['title'] = 'Pfad zu acme.sh';
$lng['serversettings']['acmeshpath']['description'] = 'Installationspfad zu acme.sh, inklusive acme.sh Script<br>Standard ist <b>/root/.acme.sh/acme.sh</b>';
$lng['question']['api_reallydelete'] = 'Api-Key wirklich löschen?';
$lng['question']['api_reallyadd'] = 'Einen neuen Api-Key erstellen?';
$lng['question']['dnsentry_reallydelete'] = 'Zonen-Eintrag wirklich löschen?';
$lng['question']['certificate_reallydelete'] = 'Zertifikat wirklich löschen?';

View File

@@ -28,4 +28,5 @@ try {
\Froxlor\Cli\PhpSessioncleanCmd::processParameters($argc, $argv);
} catch (Exception $e) {
\Froxlor\Cli\PhpSessioncleanCmd::printerr($e->getMessage());
exit(1);
}

View File

@@ -29,15 +29,23 @@ $success_message = "";
// do the delete and then just show a success-message and the certificates list again
if ($action == 'delete') {
$id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
$id = isset($_POST['id']) ? (int) $_POST['id'] : (isset($_GET['id']) ? (int) $_GET['id'] : 0);
if ($id > 0) {
try {
$json_result = Certificates::getLocal($userinfo, array(
if (isset($_POST['send']) && $_POST['send'] == 'send') {
try {
$json_result = Certificates::getLocal($userinfo, array(
'id' => $id
))->delete();
$success_message = sprintf($lng['domains']['ssl_certificate_removed'], $id);
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
} else {
\Froxlor\UI\HTML::askYesNo('certificate_reallydelete', $filename, array(
'page' => $page,
'action' => $action,
'id' => $id
))->delete();
$success_message = sprintf($lng['domains']['ssl_certificate_removed'], $id);
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
), $id);
}
}
}

View File

@@ -0,0 +1,26 @@
$header
<article class="login bradius">
<header class="dark">
<img src="{$header_logo}" alt="Froxlor Server Management Panel" />
</header>
<section class="loginsec">
<form method="post" action="{$filename}" enctype="application/x-www-form-urlencoded">
<fieldset>
<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="" autofocus required/>
</p>
<p class="submit">
<input type="hidden" name="action" value="2fa_verify" />
<input type="hidden" name="send" value="send" />
<input type="submit" value="{$lng['2fa']['2fa_verify']}" />
</p>
</fieldset>
</form>
<aside>
<a href="index.php">{$lng['login']['backtologin']}</a>
</aside>
</section>
</article>
$footer

View File

@@ -0,0 +1,43 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/lock_big.png" alt="" />&nbsp;
{$lng['login']['2fa']}
</h2>
</header>
<section>
<if $userinfo['type_2fa']=='0'>
<form method="post"
action="{$linker->getLink(array('section' => 'index', 'page' => $page, 'action' => 'add'))}">
<p>{$lng['2fa']['2fa_overview_desc']}</p>
<br> <select id="type_2fa" name="type_2fa" class="small">{$type_select}
</select>&nbsp;<input type="submit" class="submit"
value="{$lng['2fa']['2fa_add']}" name="add" />
</form>
</if>
<if $userinfo['type_2fa']=='1'>
<form method="post"
action="{$linker->getLink(array('section' => 'index', 'page' => $page, 'action' => 'delete'))}">
<p>{$lng['2fa']['2fa_email_desc']}</p>
<br> <input type="submit" class="cancel"
value="{$lng['2fa']['2fa_delete']}" name="delete" />
</form>
</if>
<if $userinfo['type_2fa']=='2'>
<form method="post"
action="{$linker->getLink(array('section' => 'index', 'page' => $page, 'action' => 'delete'))}">
<p>{$lng['2fa']['2fa_ga_desc']}</p>
<br> <img src="{$ga_qrcode}" alt="QRCode" /><br>
<br> <input type="submit" class="cancel"
value="{$lng['2fa']['2fa_delete']}" name="delete" />
</form>
</if>
</section>
</article>
$footer

View File

@@ -0,0 +1,2 @@
created and maintained by Roman Schmerold <BNoiZe@froxlor.org>

View File

@@ -0,0 +1,60 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/group_edit_big.png" alt="" />&nbsp;
{$lng['admin']['admins']}&nbsp;({$admincount})
</h2>
</header>
<section>
<form action="{$linker->getLink(array('section' => 'admins'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<div class="overviewsearch">
{$searchcode}
</div>
<div class="overviewadd">
<img src="templates/{$theme}/assets/img/icons/add.png" alt="" />
<a href="{$linker->getLink(array('section' => 'admins', 'page' => $page, 'action' => 'add'))}">{$lng['admin']['admin_add']}</a>
</div>
<table class="full hl">
<thead>
<tr>
<th>{$lng['customer']['name']}&nbsp;{$arrowcode['name']}</th>
<th>{$lng['login']['username']}&nbsp;{$arrowcode['loginname']}</th>
<th>{$lng['admin']['customers']}</th>
<th>&nbsp;</th>
<th>{$lng['panel']['options']}</th>
</tr>
</thead>
<if $pagingcode != ''>
<tfoot>
<tr>
<td colspan="5">{$pagingcode}</td>
</tr>
</tfoot>
</if>
<tbody>
$admins
</tbody>
</table>
</form>
<if 15 < $count >
<div class="overviewadd">
<img src="templates/{$theme}/assets/img/icons/add.png" alt="" />
<a href="{$linker->getLink(array('section' => 'admins', 'page' => $page, 'action' => 'add'))}">{$lng['admin']['admin_add']}</a>
</div>
</if>
</section>
</article>
$footer

View File

@@ -0,0 +1,35 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/user_add_big.png" alt="{$title}" />&nbsp;
{$title}
</h2>
</header>
<section>
<form action="{$linker->getLink(array('section' => 'admins'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="action" value="$action" />
<input type="hidden" name="send" value="send" />
<table class="full">
{$admin_add_form}
</table>
</form>
</section>
</article>
<br />
<article>
<section>
<p>
<span class="red">*</span>: {$lng['admin']['valuemandatory']}<br />
<span class="red">**</span>: {$lng['admin']['valuemandatorycompany']}
</p>
</section>
</article>
$footer

View File

@@ -0,0 +1,86 @@
<tr>
<td>
{$row['name']}
</td>
<td>
<if $row['adminid'] != $userinfo['userid']>
<a href="{$linker->getLink(array('section' => 'admins', 'page' => $page, 'action' => 'su', 'id' => $row['adminid']))}" rel="external">{$row['loginname']}</a>
</if>
<if $row['adminid'] == $userinfo['userid']>
{$row['loginname']}
</if>
</td>
<td>
{$row['customers_used']}
</td>
<td>
<div>
<span class="overviewcustomerextras">
<span>Webspace:</span>
<if $row['diskspace'] != 'UL'>
<if (($row['diskspace']/100)*(int)\Froxlor\Settings::Get('system.report_webmax')) < $row['diskspace_used']>
<div class="progress progress-danger tipper" title="{$row['diskspace_used']} MiB {$lng['panel']['used']}, {$row['diskspace']} MiB {$lng['panel']['assigned']}">
<div class="bar" aria-valuenow="{$disk_percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<else>
<if (($row['diskspace']/100)*((int)\Froxlor\Settings::Get('system.report_webmax') - 15)) < $row['diskspace_used']>
<div class="progress progress-warn tipper" title="{$row['diskspace_used']} MiB {$lng['panel']['used']}, {$row['diskspace']} MiB {$lng['panel']['assigned']}">
<div class="bar" aria-valuenow="{$disk_percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<else>
<div class="progress tipper" title="{$row['diskspace_used']} MiB {$lng['panel']['used']}, {$row['diskspace']} MiB {$lng['panel']['assigned']}">
<div class="bar" aria-valuenow="{$disk_percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</if>
</if>
<else>
<div class="progress">∞
<div class="bar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</if>
</span>
<span class="overviewcustomerextras">
<span>Traffic:</span>
<if $row['traffic'] != 'UL'>
<if (($row['traffic']/100)*(int)\Froxlor\Settings::Get('system.report_trafficmax')) < $row['traffic_used']>
<div class="progress progress-danger tipper" title="{$row['traffic_used']} GiB {$lng['panel']['used']}, {$row['traffic']} GiB {$lng['panel']['assigned']}">
<div class="bar" aria-valuenow="{$traffic_percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<else>
<if (($row['traffic']/100)*((int)\Froxlor\Settings::Get('system.report_trafficmax') - 15)) < $row['traffic_used']>
<div class="progress progress-warn tipper" title="{$row['traffic_used']} GiB {$lng['panel']['used']}, {$row['traffic']} GiB {$lng['panel']['assigned']}">
<div class="bar" aria-valuenow="{$traffic_percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<else>
<div class="progress tipper" title="{$row['traffic_used']} GiB {$lng['panel']['used']}, {$row['traffic']} GiB {$lng['panel']['assigned']}">
<div class="bar" aria-valuenow="{$traffic_percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</if>
</if>
<else>
<div class="progress">∞
<div class="bar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</if>
</span>
</div>
</td>
<td>
<a href="{$linker->getLink(array('section' => 'admins', 'page' => $page, 'action' => 'edit', 'id' => $row['adminid']))}">
<img src="templates/{$theme}/assets/img/icons/edit.png" alt="{$lng['panel']['edit']}" title="{$lng['panel']['edit']}" />
</a>&nbsp;
<a href="{$linker->getLink(array('section' => 'admins', 'page' => $page, 'action' => 'delete', 'id' => $row['adminid']))}">
<img src="templates/{$theme}/assets/img/icons/delete.png" alt="{$lng['panel']['delete']}" title="{$lng['panel']['delete']}" />
</a>
<if $row['custom_notes'] != ''>
&nbsp;<img src="templates/{$theme}/assets/img/icons/info.png" class="notes" data-id="{$row['loginname']}" alt="{$lng['usersettings']['custom_notes']['title']}" title="{$lng['usersettings']['custom_notes']['title']}" />
</if>
</td>
</tr>
<if $row['custom_notes'] != ''>
<tr class="notes_block" id="notes_{$row['loginname']}">
<td colspan="5">
{$row['custom_notes']}
</td>
</tr>
</if>

View File

@@ -0,0 +1,41 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/user_edit_big.png" alt="{$title}" />&nbsp;{$title}
</h2>
</header>
<if $result['adminid'] == $userinfo['userid']>
<div class="warningcontainer bradius">
<div class="warning">{$lng['error']['youcanteditallfieldsofyourself']}</div>
</div>
</if>
<section>
<form action="{$linker->getLink(array('section' => 'admins'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="action" value="$action" />
<input type="hidden" name="id" value="$id" />
<input type="hidden" name="send" value="send" />
<table class="full">
{$admin_edit_form}
</table>
</form>
</section>
</article>
<br />
<article>
<section>
<p>
<span class="red">*</span>: {$lng['admin']['valuemandatory']}
</p>
</section>
</article>
$footer

View File

@@ -0,0 +1,22 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/settings_big.png" alt="{$lng['admin']['configfiles']['serverconfiguration']}" />&nbsp;
{$lng['admin']['configfiles']['serverconfiguration']} &nbsp;
[<a href="{$linker->getLink(array('section' => 'configfiles', 'page' => 'configfiles'))}">{$lng['admin']['configfiles']['wizard']}</a>]
</h2>
</header>
<section>
<form action="{$linker->getLink(array('section' => 'configfiles'))}" method="get" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<table class="tiny center">
$distributions
</table>
</form>
</section>
</article>
$footer

View File

@@ -0,0 +1 @@
<li><a href="{$linker->getLink(array('section' => 'configfiles', 'page' => $page, 'distribution' => $distribution_name, 'service' => $service_name, 'daemon' => $daemon_name))}">{$daemon_details['label']}</a></li>

View File

@@ -0,0 +1,6 @@
<tr class="section">
<th><strong>{$distribution_details['label']}</strong></th>
</tr>
<tr>
<td>$services</td>
</tr>

View File

@@ -0,0 +1,5 @@
<strong>{$service_details['label']}</strong>
<br />
<ul>
$daemons
</ul>

View File

@@ -0,0 +1,30 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/settings_big.png" alt="" />&nbsp;
{$dist_display}&nbsp;&raquo;&nbsp;
{$services[$service]->title}&nbsp;&raquo;&nbsp;
{$daemons[$daemon]->title}&nbsp;[<a href="{$linker->getLink(array('section' => 'configfiles', 'page' => $page, 'distribution' => $distribution, 'service' => $service))}">{$lng['panel']['back']}</a>]
</h2>
</header>
<section>
<div class="info">
<p>{$lng['admin']['configfiles']['legend']}</p>
<p>{$lng['admin']['configfiles']['commands']}</p>
<p>{$lng['admin']['configfiles']['files']}</p>
<p>
<form id="configfiles_setmysqlpw" action="#">
FROXLOR_MYSQL_PASSWORD: <input type="text" class="text" id="configfiles_mysqlpw" name="configfiles_mysqlpw" value="" />
<input type="submit" value="{$lng['panel']['set']}" />
</form>
</p>
</div>
</section>
<section>
{$configpage}
</section>
</article>
$footer

View File

@@ -0,0 +1,3 @@
<div class="pushbot">
<textarea class="shell" rows="{$numbrows}" readonly>{$commands}</textarea>
</div>

View File

@@ -0,0 +1,4 @@
<div class="pushbot">
<textarea class="shell" rows="1" readonly>{$distro_editor} {$realname}</textarea>
<textarea class="filecontent" rows="<if $numbrows <=20 >{$numbrows}<else>21</if>" readonly>{$file_content}</textarea>
</div>

View File

@@ -0,0 +1,8 @@
<div class="filesub">
<fieldset class="file">
<legend>{$realname}</legend>
{$commands_pre}
{$commands_file}
{$commands_post}
</fieldset>
</div>

View File

@@ -0,0 +1,82 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/settings_big.png" alt="{$lng['admin']['configfiles']['serverconfiguration']}" />&nbsp;
{$lng['admin']['configfiles']['serverconfiguration']} &nbsp;
[<a href="{$linker->getLink(array('section' => 'configfiles', 'page' => 'overview'))}">{$lng['admin']['configfiles']['overview']}</a>]
</h2>
</header>
<div class="messagewrapperfull">
<div class="warningcontainer bradius">
<div class="warningtitle">{$lng['admin']['warning']}</div>
<div class="warning">{$lng['panel']['settings_before_configuration']}</div>
</div>
</div>
<section>
<form action="$filename" method="get" enctype="application/x-www-form-urlencoded">
<fieldset>
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<table class="tiny center">
<tr>
<td><b>{$lng['admin']['configfiles']['distribution']}:</b></td>
<td>
<if $distribution != ''>
<input type="hidden" name="distribution" value="$distribution"/>
<a href="{$linker->getLink(array('section' => 'configfiles', 'page' => $page))}">{$dist_display}</a>
<else>
<select id="config_distribution" name="distribution">
<option value="choose">{$lng['admin']['configfiles']['choosedistribution']}</option>
{$distributions_select}
</select>
</if>
</td>
</tr>
<tr>
<td><b>{$lng['admin']['configfiles']['service']}:</b></td>
<td>
<if $service != ''>
<input type="hidden" name="service" value="$service"/>
<a href="{$linker->getLink(array('section' => 'configfiles', 'page' => $page, 'distribution' => $distribution))}">{$services[$service]->title}</a>
<else>
<select id="config_service" name="service">
<option value="choose">{$lng['admin']['configfiles']['chooseservice']}</option>
{$services_select}
</select>
</if>
</td>
</tr>
<tr>
<td><b>{$lng['admin']['configfiles']['daemon']}:</b></td>
<td><select id="config_daemon" name="daemon"><option value="choose">{$lng['admin']['configfiles']['choosedaemon']}</option>{$daemons_select}</select></td>
</tr>
<tfoot>
<tr>
<td colspan="2" align="center"><input class="bottom" type="submit" value="{$lng['panel']['next']}" /></td>
</tr>
<tr>
<if \Froxlor\Settings::Get('panel.is_configured') == '0'>
<td colspan="2" align="center">{$lng['panel']['done_configuring']}:<br><br><a href="{$linker->getLink(array('section' => 'configfiles', 'page' => 'overview', 'action' => 'setconfigured'))}" class="btnlink">{$lng['panel']['ihave_configured']}</a><br><br></td>
<else>
<td colspan="2" align="center">{$lng['panel']['system_is_configured']}</td>
</if>
</tr>
</tfoot>
</table>
</fieldset>
</form>
</section>
<br><br><br>
<section>
<p><strong>{$lng['panel']['alternative_cmdline_config']}:</strong></p>
<div class="pushbot">
<textarea class="shell" rows="2" readonly>php {$basedir}/install/scripts/config-services.php --froxlor-dir={$basedir} --create</textarea>
</div>
</section>
</article>
$footer

View File

@@ -0,0 +1,27 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/clock_edit_big.png" alt="{$title}" />&nbsp;
{$title}
</h2>
</header>
<section>
<form action="{$linker->getLink(array('section' => 'cronjobs'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="action" value="$action" />
<input type="hidden" name="id" value="$id" />
<input type="hidden" name="send" value="send" />
<table class="full">
{$cronjobs_edit_form}
</table>
</form>
</section>
</article>
$footer

View File

@@ -0,0 +1,33 @@
$header
<article>
<header>
<h2><img src="templates/{$theme}/assets/img/icons/clock_big.png" alt="" />&nbsp;
{$lng['admin']['cron']['cronsettings']}</h2>
</header>
<div class="messagewrapperfull">
<div class="warningcontainer bradius">
<div class="warningtitle">{$lng['admin']['warning']}</div>
<div class="warning">{$lng['cron']['changewarning']}</div>
</div>
</div>
<section>
<table class="full">
<thead>
<tr>
<th>{$lng['cron']['description']}</th>
<th>{$lng['cron']['lastrun']}</th>
<th>{$lng['cron']['interval']}</th>
<th>{$lng['cron']['isactive']}</th>
<th>{$lng['panel']['options']}</th>
</tr>
</thead>
<tbody>
$crons
</tbody>
</table>
</section>
</article>
$footer

View File

@@ -0,0 +1,11 @@
<tr>
<td>{$description}</td>
<td>{$row['lastrun']}</td>
<td>{$row['interval']}</td>
<td>{$row['isactive']}</td>
<td>
<a href="{$linker->getLink(array('section' => 'cronjobs', 'page' => $page, 'action' => 'edit', 'id' => $row['id']))}">
<img src="templates/{$theme}/assets/img/icons/edit.png" alt="{$lng['panel']['edit']}" title="{$lng['panel']['edit']}" />
</a>
</td>
</tr>

View File

@@ -0,0 +1,3 @@
<tr>
<td colspan="5"><b>{$module}</b></td>
</tr>

View File

@@ -0,0 +1,71 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/group_edit_big.png" alt="" />
{$lng['admin']['customers']} ({$customercount})
</h2>
</header>
<section>
<form action="{$linker->getLink(array('section' => 'customers'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<div class="overviewsearch">
{$searchcode}
</div>
<if $userinfo['customers_used'] < $userinfo['customers'] || $userinfo['customers'] == '-1'>
<div class="overviewadd">
<img src="templates/{$theme}/assets/img/icons/add.png" alt="" />&nbsp;
<a href="{$linker->getLink(array('section' => 'customers', 'page' => $page, 'action' => 'add'))}">{$lng['admin']['customer_add']}</a>
</div>
</if>
<table class="full hl">
<thead>
<tr>
<th>
{$lng['customer']['name']},
{$lng['customer']['firstname']}&nbsp;{$arrowcode['c.name']}
</th>
<th>
{$lng['login']['username']}&nbsp;{$arrowcode['c.loginname']}
</th>
<th>
{$lng['admin']['admin']}&nbsp;{$arrowcode['a.loginname']}
</th>
<th>{$lng['admin']['lastlogin_succ']}</th>
<th></th>
<th>{$lng['panel']['options']}</th>
</tr>
</thead>
<tbody>
$customers
</tbody>
<if $pagingcode != ''>
<tfoot>
<tr>
<td colspan="6">{$pagingcode}</td>
</tr>
</tfoot>
</if>
</table>
</form>
<if ($userinfo['customers_used'] < $userinfo['customers'] || $userinfo['customers'] == '-1') && 15 < $userinfo['customers_used'] >
<div class="overviewadd">
<img src="templates/{$theme}/assets/img/icons/add.png" alt="" />&nbsp;
<a href="{$linker->getLink(array('section' => 'customers', 'page' => $page, 'action' => 'add'))}">{$lng['admin']['customer_add']}</a>
</div>
</if>
</section>
</article>
$footer

View File

@@ -0,0 +1,36 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/user_add_big.png" alt="{$title}" />&nbsp;
{$title}
</h2>
</header>
<script type="text/javascript" src="templates/{$theme}/assets/js/customers.js"></script>
<section>
<form action="{$linker->getLink(array('section' => 'customers'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="action" value="$action" />
<input type="hidden" name="send" value="send" />
<table class="full">
{$customer_add_form}
</table>
</form>
</section>
</article>
<br />
<article>
<section>
<p>
<span class="red">*</span>: {$lng['admin']['valuemandatory']}<br />
<span class="red">**</span>: {$lng['admin']['valuemandatorycompany']}
</p>
</section>
</article>
$footer

View File

@@ -0,0 +1,98 @@
<tr <if $row['deactivated'] == 1>class="disabled"</if>>
<td>
<if $row['company'] != '' && $row['name'] != ''>
{$row['company']}<br />
<small>{$row['name']}, {$row['firstname']}</small>
</if>
<if $row['company'] != '' && $row['name'] == ''>
{$row['company']}
</if>
<if $row['company'] == ''>
{$row['name']}, {$row['firstname']}
</if>
</td>
<td>
<a href="{$linker->getLink(array('section' => 'customers', 'page' => $page, 'action' => 'su', 'sort' => $row['loginname'], 'id' => $row['customerid']))}" rel="external">{$row['loginname']}</a>
</td>
<td>
{$row['adminname']}
</td>
<td>
{$last_login}
</td>
<td>
<div>
<span class="overviewcustomerextras">
<span>Webspace:</span>
<if $row['diskspace'] != 'UL'>
<if (($row['diskspace']/100)*(int)\Froxlor\Settings::Get('system.report_webmax')) < $row['diskspace_used']>
<div class="progress progress-danger tipper" title="{$lng['panel']['used']}:<br>web: {$row['webspace_used']} {$lng['customer']['mib']}<br>mail: {$row['mailspace_used']} {$lng['customer']['mib']}<br>mysql: {$row['dbspace_used']} MiB<br><br>{$lng['panel']['assigned']}:<br>{$row['diskspace']} {$lng['customer']['mib']}">
<div class="bar" aria-valuenow="{$disk_percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<else>
<if (($row['diskspace']/100)*((int)\Froxlor\Settings::Get('system.report_webmax') - 15)) < $row['diskspace_used']>
<div class="progress progress-warn tipper" title="{$lng['panel']['used']}:<br>web: {$row['webspace_used']} {$lng['customer']['mib']}<br>mail: {$row['mailspace_used']} {$lng['customer']['mib']}<br>mysql: {$row['dbspace_used']} MiB<br><br>{$lng['panel']['assigned']}:<br>{$row['diskspace']} {$lng['customer']['mib']}">
<div class="bar" aria-valuenow="{$disk_percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<else>
<div class="progress tipper" title="{$lng['panel']['used']}:<br>web: {$row['webspace_used']} {$lng['customer']['mib']}<br>mail: {$row['mailspace_used']} {$lng['customer']['mib']}<br>mysql: {$row['dbspace_used']} MiB<br><br>{$lng['panel']['assigned']}:<br>{$row['diskspace']} {$lng['customer']['mib']}">
<div class="bar" aria-valuenow="{$disk_percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</if>
</if>
<else>
<div class="progress">∞
<div class="bar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</if>
</span>
<span class="overviewcustomerextras">
<span>Traffic:</span>
<if $row['traffic'] != 'UL'>
<if (($row['traffic']/100)*(int)\Froxlor\Settings::Get('system.report_trafficmax')) < $row['traffic_used']>
<div class="progress progress-danger tipper" title="{$row['traffic_used']} GiB {$lng['panel']['used']}, {$row['traffic']} GiB {$lng['panel']['assigned']}">
<div class="bar" aria-valuenow="{$traffic_percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<else>
<if (($row['traffic']/100)*((int)\Froxlor\Settings::Get('system.report_trafficmax') - 15)) < $row['traffic_used']>
<div class="progress progress-warn tipper" title="{$row['traffic_used']} GiB {$lng['panel']['used']}, {$row['traffic']} GiB {$lng['panel']['assigned']}">
<div class="bar" aria-valuenow="{$traffic_percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<else>
<div class="progress tipper" title="{$row['traffic_used']} GiB {$lng['panel']['used']}, {$row['traffic']} GiB {$lng['panel']['assigned']}">
<div class="bar" aria-valuenow="{$traffic_percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</if>
</if>
<else>
<div class="progress">∞
<div class="bar" aria-valuenow="{$traffic_percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</if>
</span>
</div>
</td>
<td>
<a href="{$linker->getLink(array('section' => 'customers', 'page' => $page, 'action' => 'edit', 'id' => $row['customerid']))}">
<img src="templates/{$theme}/assets/img/icons/edit.png" alt="{$lng['panel']['edit']}" title="{$lng['panel']['edit']}" />
</a>&nbsp;
<a href="{$linker->getLink(array('section' => 'customers', 'page' => $page, 'action' => 'delete', 'id' => $row['customerid']))}">
<img src="templates/{$theme}/assets/img/icons/delete.png" alt="{$lng['panel']['delete']}" title="{$lng['panel']['delete']}" />
</a>
<if $islocked == 1>
&nbsp;<a href="{$linker->getLink(array('section' => 'customers', 'page' => $page, 'action' => 'unlock', 'id' => $row['customerid']))}">
<img src="templates/{$theme}/assets/img/icons/unlock.png" alt="{$lng['panel']['unlock']}" title="{$lng['panel']['unlock']}" />
</a>
</if>
<if $row['custom_notes'] != ''>
&nbsp;<img src="templates/{$theme}/assets/img/icons/info.png" class="notes" data-id="{$row['loginname']}" alt="{$lng['usersettings']['custom_notes']['title']}" title="{$lng['usersettings']['custom_notes']['title']}" />
</if>
</td>
</tr>
<if $row['custom_notes'] != ''>
<tr class="notes_block" id="notes_{$row['loginname']}">
<td colspan="6">
{$row['custom_notes']}
</td>
</tr>
</if>

View File

@@ -0,0 +1,37 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/user_edit_big.png" alt="{$title}" />&nbsp;
{$title}
</h2>
</header>
<script type="text/javascript" src="templates/{$theme}/assets/js/customers.js"></script>
<section>
<form action="{$linker->getLink(array('section' => 'customers'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="action" value="$action" />
<input type="hidden" name="id" value="$id" />
<input type="hidden" name="send" value="send" />
<table class="full">
{$customer_edit_form}
</table>
</form>
</section>
</article>
<br />
<article>
<section>
<p>
<span class="red">*</span>: {$lng['admin']['valuemandatory']}<br />
<span class="red">**</span>: {$lng['admin']['valuemandatorycompany']}
</p>
</section>
</article>
$footer

View File

@@ -0,0 +1,73 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/domains_big.png" alt="" />&nbsp;
{$lng['admin']['domains']}&nbsp;({$domainscount})
</h2>
</header>
<section>
<form action="{$linker->getLink(array('section' => 'domains'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<div class="overviewsearch">
{$searchcode}
</div>
<if ($userinfo['domains_used'] < $userinfo['domains'] || $userinfo['domains'] == '-1') && $countcustomers !=0 >
<div class="overviewadd">
<img src="templates/{$theme}/assets/img/icons/add.png" alt="" />&nbsp;
<a href="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'action' => 'add'))}">{$lng['admin']['domain_add']}</a>
&nbsp;
<img src="templates/{$theme}/assets/img/icons/archive.png" alt="" />&nbsp;
<a href="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'action' => 'import'))}">{$lng['domains']['domain_import']}</a>
</div>
</if>
<table class="full hl">
<thead>
<tr>
<th>{$lng['domains']['domainname']}&nbsp;{$arrowcode['d.domain_ace']}</th>
<th>{$lng['admin']['ipsandports']['ip']}</th>
<th>{$lng['admin']['customer']}&nbsp;{$arrowcode['c.loginname']}</th>
<th>{$lng['panel']['options']}</th>
</tr>
</thead>
<tbody>
{$domains}
</tbody>
<if $pagingcode != ''>
<tfoot>
<tr>
<td colspan="4">{$pagingcode}</td>
</tr>
</tfoot>
</if>
</table>
</form>
<if $countcustomers == 0 >
<div class="warningcontainer bradius">
<div class="warningtitle">{$lng['admin']['warning']}</div>
<div class="warning">
<a href="{$linker->getLink(array('section' => 'customers', 'page' => 'customers', 'action' => 'add'))}">{$lng['admin']['domain_nocustomeraddingavailable']}</a>
</div>
</div>
</if>
<if ($userinfo['domains_used'] < $userinfo['domains'] || $userinfo['domains'] == '-1') && 15 < $count && 0 < $countcustomers >
<div class="overviewadd">
<img src="templates/{$theme}/assets/img/icons/add.png" alt="" />&nbsp;
<a href="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'action' => 'add'))}">{$lng['admin']['domain_add']}</a>
</div>
</if>
</section>
</article>
$footer

View File

@@ -0,0 +1,32 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/domain_add_big.png" alt="{$title}" />&nbsp;
{$title}
</h2>
</header>
<script type="text/javascript" src="templates/{$theme}/assets/js/domains.js"></script>
<section>
<form action="{$linker->getLink(array('section' => 'domains'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="action" value="$action" />
<input type="hidden" name="send" value="send" />
<table class="full">
{$domain_add_form}
</table>
</form>
</section>
<br />
<section>
<p>
<span class="red">*</span>: {$lng['admin']['valuemandatory']}
</p>
</section>
</article>
$footer

View File

@@ -0,0 +1,45 @@
<if $row['termination_css'] != ''>
<tr class="{$row['termination_css']}<if $row['deactivated'] == 1> disabled</if>">
</if>
<if $row['termination_css'] == ''>
<tr <if $row['deactivated'] == 1>class="disabled"</if>>
</if>
<td><b>{$row['domain']}</b>
<if (isset($row['standardsubdomain']) && $row['standardsubdomain'] == $row['id'])>
&nbsp;({$lng['admin']['stdsubdomain']})
</if>
<if $row['registration_date'] != ''>
<br><small>{$lng['domains']['registration_date']}: {$row['registration_date']}</small>
</if>
<if $row['termination_date'] != ''>
<br><small><div class="red">({$lng['domains']['termination_date_overview']} {$row['termination_date']})</div></small>
</if>
</td>
<td>{$row['ipandport']}</td>
<td>{$row['customername']}&nbsp;
<if !empty($row['loginname'])>(<a href="{$linker->getLink(array('section' => 'customers', 'page' => 'customers', 'action' => 'su', 'id' => $row['customerid']))}" rel="external">{$row['loginname']}</a>)</if>
</td>
<td>
<a href="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'action' => 'edit', 'id' => $row['id']))}">
<img src="templates/{$theme}/assets/img/icons/edit.png" alt="{$lng['panel']['edit']}" title="{$lng['panel']['edit']}" />
</a>
<a href="{$linker->getLink(array('section' => 'domains', 'page' => 'logfiles', 'domain_id' => $row['id']))}">
<img src="templates/{$theme}/assets/img/icons/view.png" alt="{$lng['panel']['viewlogs']}" title="{$lng['panel']['viewlogs']}" />
</a>
<if $row['isbinddomain'] == '1' && \Froxlor\Settings::Get('system.bind_enable') == '1' && \Froxlor\Settings::Get('system.dnsenabled') == '1'>
&nbsp;<a href="{$linker->getLink(array('section' => 'domains', 'page' => 'domaindnseditor', 'domain_id' => $row['id']))}">
<img src="templates/{$theme}/assets/img/icons/dns_edit.png" alt="{$lng['dnseditor']['edit']}" title="{$lng['dnseditor']['edit']}" />
</a>
</if>
<if $row['letsencrypt'] == '1'>
&nbsp;<img src="templates/{$theme}/assets/img/icons/ssl_letsencrypt.png" alt="{$lng['panel']['letsencrypt']}" title="{$lng['panel']['letsencrypt']}" />
</if>
<if !(isset($row['domainaliasid']) && $row['domainaliasid'] != 0) && $row['id'] != \Froxlor\Settings::Get('system.hostname_id')>
<if !(isset($row['standardsubdomain']) && $row['standardsubdomain'] == $row['id'])>
&nbsp;<a href="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'action' => 'delete', 'id' => $row['id']))}">
<img src="templates/{$theme}/assets/img/icons/delete.png" alt="{$lng['panel']['delete']}" title="{$lng['panel']['delete']}" />
</a>
</if>
</if>
</td>
</tr>

View File

@@ -0,0 +1,46 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/domain_edit_big.png" alt="{$title}" />&nbsp;
{$title}
<if $result['isbinddomain'] == '1' && \Froxlor\Settings::Get('system.bind_enable') == '1' && \Froxlor\Settings::Get('system.dnsenabled') == '1'>
&nbsp;(<small><a href="{$linker->getLink(array('section' => 'domains', 'page' => 'domaindnseditor', 'domain_id' => $id))}">{$lng['dnseditor']['edit']}</a></small>)
</if>
</h2>
</header>
<section>
<form action="{$linker->getLink(array('section' => 'domains'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="delete_statistics_str" id="delete_statistics_str" value="{$lng['admin']['delete_statistics']}">
<input type="hidden" name="speciallogverified" id="speciallogverified" value="0" />
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="action" value="$action" />
<input type="hidden" name="id" value="$id" />
<input type="hidden" name="send" value="send" />
<div id="speciallogwarningpopup" name="speciallogwarningpopup" align="center">
<div class="warningtitle">{$lng['admin']['delete_statistics']}</div>
</p>{$speciallogwarning}</p>
<input type="text" name="delete_stats" id="delete_stats"></p>
<div>
<input type="button" class="yesbutton" name="verifybutton" value="{$lng['panel']['delete']}" id="speciallogyesbutton" />&nbsp;
<input type="button" class="nobutton" value="{$lng['panel']['cancel']}" id="speciallognobutton" />
</div>
</div>
<table class="full">
{$domain_edit_form}
</table>
</form>
</section>
<br />
<section>
<p>
<span class="red">*</span>: {$lng['admin']['valuemandatory']}
</p>
</section>
</article>
$footer

View File

@@ -0,0 +1,38 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/domain_add_big.png" alt="{$title}" />&nbsp;
{$title}
</h2>
</header>
<div class="messagewrapperfull">
<div class="warningcontainer bradius">
<div class="warningtitle">{$lng['admin']['note']}</div>
<div class="warning">{$lng['domains']['import_description']}</div>
</div>
</div>
<section>
<form action="{$linker->getLink(array('section' => 'domains'))}" method="post" enctype="multipart/form-data">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="action" value="$action" />
<input type="hidden" name="send" value="send" />
<table class="full">
{$domain_import_form}
</table>
</form>
</section>
<br />
<section>
<p>
<span class="red">*</span>: {$lng['admin']['valuemandatory']}
</p>
</section>
</article>
$footer

View File

@@ -0,0 +1,33 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/flag.png" alt="" />&nbsp;
{$lng['menue']['main']['changelanguage']}
</h2>
</header>
<section>
<form method="post" action="{$linker->getLink(array('section' => 'index'))}" enctype="application/x-www-form-urlencoded">
<fieldset>
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="send" value="send" />
<table class="tiny center">
<tr>
<td><label for="def_language">{$lng['login']['language']}:</label></td>
<td><select id="def_language" name="def_language">$language_options</select></td>
</tr>
<tfoot>
<tr>
<td colspan="2" align="center">
<input type="submit" value="{$lng['menue']['main']['changelanguage']}" />
</td>
</tr>
</tfoot>
</table>
</fieldset>
</form>
</section>
</article>
$footer

View File

@@ -0,0 +1,41 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/lock_big.png" alt="" />&nbsp;
{$lng['menue']['main']['changepassword']}
</h2>
</header>
<section>
<form method="post" action="{$linker->getLink(array('section' => 'index'))}" enctype="application/x-www-form-urlencoded">
<fieldset>
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="send" value="send" />
<table class="middle center">
<tr>
<td><label for="old_password">{$lng['changepassword']['old_password']}:</label></td>
<td><input type="password" id="old_password" name="old_password" /></td>
</tr>
<tr>
<td><label for="new_password">{$lng['changepassword']['new_password']}:</label></td>
<td><input type="password" id="new_password" name="new_password" /></td>
</tr>
<tr>
<td><label for="new_password_confirm">{$lng['changepassword']['new_password_confirm']}:</label></td>
<td><input type="password" id="new_password_confirm" name="new_password_confirm" /></td>
</tr>
<tfoot>
<tr>
<td colspan="2" align="center">
<input type="submit" value="{$lng['menue']['main']['changepassword']}" />
</td>
</tr>
</tfoot>
</table>
</fieldset>
</form>
</section>
</article>
$footer

View File

@@ -0,0 +1,33 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/display_big.png" alt="" />&nbsp;
{$lng['menue']['main']['changetheme']}
</h2>
</header>
<section>
<form method="post" action="{$linker->getLink(array('section' => 'index'))}" enctype="application/x-www-form-urlencoded">
<fieldset>
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="send" value="send" />
<table class="tiny center">
<tr>
<td><label for="theme">{$lng['panel']['theme']}:</label></td>
<td><select id="theme" name="theme">$theme_options</select></td>
</tr>
<tfoot>
<tr>
<td colspan="2" align="center">
<input class="bottom" type="submit" value="{$lng['menue']['main']['changetheme']}" />
</td>
</tr>
</tfoot>
</table>
</fieldset>
</form>
</section>
</article>
$footer

View File

@@ -0,0 +1,279 @@
$header
<article>
<h2>
<img src="templates/{$theme}/assets/img/icons/domains_big.png" alt="" />
{$lng['panel']['dashboard']}
</h2>
<div class="grid-g">
<div class="grid-u-1-2" id="statsbox">
<div class="canvasbox">
<input type="hidden" id="customers" class="circular" data-used="{$overview['number_customers']}" data-available="{$userinfo['customers']}">
<canvas id="customers-canvas" width="120" height="76"></canvas><br/>
{$lng['admin']['customers']}<br />
<small>
{$overview['number_customers']} {$lng['panel']['used']}<br />
<if $userinfo['customers'] != '∞'>
{$userinfo['customers']} {$lng['panel']['available']}
</if>
</small>
</div>
<div class="canvasbox">
<input type="hidden" id="domains" class="circular" data-used="{$overview['number_domains']}" data-available="{$userinfo['domains']}">
<canvas id="domains-canvas" width="120" height="76"></canvas><br/>
{$lng['customer']['domains']}<br />
<small>
{$overview['number_domains']} {$lng['panel']['used']}<br />
<if $userinfo['domains'] != '∞'>
{$userinfo['domains']} {$lng['panel']['available']}
</if>
</small>
</div>
<div class="canvasbox">
<input type="hidden" id="subdomains" class="circular" data-used="{$overview['subdomains_used']}" data-available="{$userinfo['subdomains']}" data-assigned="{$userinfo['subdomains_used']}">
<canvas id="subdomains-canvas" width="120" height="76"></canvas><br/>
{$lng['customer']['subdomains']}<br />
<small>
{$overview['subdomains_used']} {$lng['panel']['used']}<br />
{$userinfo['subdomains_used']} {$lng['panel']['assigned']}<br />
<if $userinfo['subdomains'] != '∞'>
{$userinfo['subdomains']} {$lng['panel']['available']}
</if>
</small>
</div>
<div class="canvasbox">
<input type="hidden" id="diskspace" class="circular" data-used="{$overview['diskspace_used']}" data-available="{$userinfo['diskspace']}" data-assigned="{$userinfo['diskspace_used']}">
<canvas id="diskspace-canvas" width="120" height="76"></canvas><br/>
{$lng['customer']['diskspace']}<br />
<small>
{$overview['diskspace_used']} {$lng['panel']['used']}<br />
{$userinfo['diskspace_used']} {$lng['panel']['assigned']}<br />
<if $userinfo['diskspace'] != '∞'>
{$userinfo['diskspace']} {$lng['panel']['available']}
</if>
</small>
</div>
<div class="canvasbox">
<input type="hidden" id="traffic" class="circular" data-used="{$overview['traffic_used']}" data-available="{$userinfo['traffic']}" data-assigned="{$userinfo['traffic_used']}">
<canvas id="traffic-canvas" width="120" height="76"></canvas><br/>
{$lng['customer']['traffic']}<br />
<small>
{$overview['traffic_used']} {$lng['panel']['used']}<br />
{$userinfo['traffic_used']} {$lng['panel']['assigned']}<br />
<if $userinfo['traffic'] != '∞'>
{$userinfo['traffic']} {$lng['panel']['available']}
</if>
</small>
</div>
<div class="canvasbox">
<input type="hidden" id="mysqls" class="circular" data-used="{$overview['mysqls_used']}" data-available="{$userinfo['mysqls']}" data-assigned="{$userinfo['mysqls_used']}">
<canvas id="mysqls-canvas" width="120" height="76"></canvas><br/>
{$lng['customer']['mysqls']}<br />
<small>
{$overview['mysqls_used']} {$lng['panel']['used']}<br />
{$userinfo['mysqls_used']} {$lng['panel']['assigned']}<br />
<if $userinfo['mysqls'] != '∞'>
{$userinfo['mysqls']} {$lng['panel']['available']}
</if>
</small>
</div>
<div class="canvasbox">
<input type="hidden" id="emails" class="circular" data-used="{$overview['emails_used']}" data-available="{$userinfo['emails']}" data-assigned="{$userinfo['emails_used']}">
<canvas id="emails-canvas" width="120" height="76"></canvas><br/>
{$lng['customer']['emails']}<br />
<small>
{$overview['emails_used']} {$lng['panel']['used']}<br />
{$userinfo['emails_used']} {$lng['panel']['assigned']}<br />
<if $userinfo['emails'] != '∞'>
{$userinfo['emails']} {$lng['panel']['available']}
</if>
</small>
</div>
<div class="canvasbox">
<input type="hidden" id="email_accounts" class="circular" data-used="{$overview['email_accounts_used']}" data-available="{$userinfo['email_accounts']}" data-assigned="{$userinfo['email_accounts_used']}">
<canvas id="email_accounts-canvas" width="120" height="76"></canvas><br/>
{$lng['customer']['accounts']}<br />
<small>
{$overview['email_accounts_used']} {$lng['panel']['used']}<br />
{$userinfo['email_accounts_used']} {$lng['panel']['assigned']}<br />
<if $userinfo['email_accounts'] != '∞'>
{$userinfo['email_accounts']} {$lng['panel']['available']}
</if>
</small>
</div>
<div class="canvasbox">
<input type="hidden" id="email_forwarders" class="circular" data-used="{$overview['email_forwarders_used']}" data-available="{$userinfo['email_forwarders']}" data-assigned="{$userinfo['email_forwarders_used']}">
<canvas id="email_forwarders-canvas" width="120" height="76"></canvas><br/>
{$lng['customer']['forwarders']}<br />
<small>
{$overview['email_forwarders_used']} {$lng['panel']['used']}<br />
{$userinfo['email_forwarders_used']} {$lng['panel']['assigned']}<br />
<if $userinfo['email_forwarders'] != '∞'>
{$userinfo['email_forwarders']} {$lng['panel']['available']}
</if>
</small>
</div>
<if \Froxlor\Settings::Get('system.mail_quota_enabled') == 1>
<div class="canvasbox">
<input type="hidden" id="email_quota" class="circular" data-used="{$overview['email_quota_used']}" data-available="{$userinfo['email_quota']}" data-assigned="{$userinfo['email_quota_used']}">
<canvas id="email_quota-canvas" width="120" height="76"></canvas><br/>
{$lng['customer']['email_quota']}<br />
<small>
{$overview['email_quota_used']} {$lng['panel']['used']}<br />
{$userinfo['email_quota_used']} {$lng['panel']['assigned']}<br />
<if $userinfo['email_quota'] != '∞'>
{$userinfo['email_quota']} {$lng['panel']['available']}
</if>
</small>
</div>
</if>
<div class="canvasbox">
<input type="hidden" id="ftps" class="circular" data-used="{$overview['ftps_used']}" data-available="{$userinfo['ftps']}" data-assigned="{$userinfo['ftps_used']}">
<canvas id="ftps-canvas" width="120" height="76"></canvas><br/>
{$lng['customer']['ftps']}<br />
<small>
{$overview['ftps_used']} {$lng['panel']['used']}<br />
{$userinfo['ftps_used']} {$lng['panel']['assigned']}<br />
<if $userinfo['ftps'] != '∞'>
{$userinfo['ftps']} {$lng['panel']['available']}
</if>
</small>
</div>
</div>
<div class="grid-u-1-2">
<if \Froxlor\Settings::Get('admin.show_news_feed') == '1'>
<table class="dboarditem full" id="newsfeed">
<thead>
<tr>
<th>News</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<ul class="newsfeed" id="newsfeeditems"></ul>
</td>
</tr>
</tbody>
</table>
<else>
<table class="dboarditem full">
<tbody>
<tr><td>
<img src="templates/{$theme}/assets/img/icons/warning_big.png" alt="" />&nbsp;
{$lng['panel']['newsfeed_disabled']}&nbsp;
<a href="{$linker->getLink(array('section' => 'settings', 'part' => 'panel'))}">
<img src="templates/{$theme}/assets/img/icons/edit_20.png" alt="" />
</a>
</td></tr>
</tbody>
</table>
</if>
<if $userinfo['custom_notes'] != '' && $userinfo['custom_notes_show'] == '1'>
<table class="dboarditem full">
<tbody>
<tr><td>{$userinfo['custom_notes']}</td></tr>
</tbody>
</table>
</if>
<table class="dboarditem">
<thead>
<tr>
<th colspan="2">{$lng['admin']['systemdetails']}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{$lng['admin']['hostname']}:</td>
<td>{$system_hostname}</td>
</tr>
<tr>
<td>{$lng['admin']['serversoftware']}:</td>
<td>{$_SERVER['SERVER_SOFTWARE']}</td>
</tr>
<tr>
<td>{$lng['admin']['phpversion']}:</td>
<td><a href="{$linker->getLink(array('section' => 'settings', 'page' => 'phpinfo'))}">$phpversion</a></td>
</tr>
<tr>
<td class="nowrap">{$lng['admin']['mysqlserverversion']}:</td>
<td>$mysqlserverversion</td>
</tr>
<tr>
<td>{$lng['admin']['webserverinterface']}:</td>
<td>$webserverinterface</td>
</tr>
<tr>
<td>{$lng['admin']['memory']}:</td>
<td><pre>$memory</pre></td>
</tr>
<tr>
<td>{$lng['admin']['sysload']}:</td>
<td>$load</td>
</tr>
<if $showkernel == 1>
<tr>
<td>Kernel:</td>
<td>$kernel</td>
</tr>
</if>
<if $uptime != ''>
<tr>
<td>Uptime:</td>
<td>$uptime</td>
</tr>
</if>
</tbody>
</table>
<table class="dboarditem">
<thead>
<tr>
<th colspan="2">{$lng['admin']['froxlordetails']}</th>
</tr>
</thead>
<tbody>
{$outstanding_tasks}
{$cron_last_runs}
<tr>
<td>{$lng['admin']['installedversion']}:</td>
<td>{$version}{$branding} (DB: {$dbversion})</td>
</tr>
<tr>
<td>{$lng['admin']['latestversion']}:</td>
<if $isnewerversion != 0 >
<td><a href="$lookfornewversion_link"><strong>$lookfornewversion_lable</strong></a></td>
<else>
<td><a href="$lookfornewversion_link">$lookfornewversion_lable</a></td>
</if>
</tr>
<if $lookfornewversion_message != ''>
<tr>
<td colspan="2"><strong>$lookfornewversion_message</strong></td>
</tr>
</if>
<if $lookfornewversion_addinfo != ''>
<tr>
<td colspan="2">$lookfornewversion_addinfo</td>
</tr>
</if>
</tbody>
</table>
</div>
</div>
</article>
$footer

View File

@@ -0,0 +1,4 @@
<tr>
<td>{$text}:</td>
<td>{$value}</td>
</tr>

View File

@@ -0,0 +1,43 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/error_report_big.png" alt="" />&nbsp;
{$lng['error']['send_report_title']}
</h2>
</header>
<section>
<form method="post" action="{$linker->getLink(array('section' => 'index', 'errorid' => $errid))}" enctype="application/x-www-form-urlencoded">
<fieldset>
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="send" value="send" />
<table class="full">
<thead>
<tr>
<th>
<p>{$lng['error']['send_report_desc']}</p>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>{$mail_html}</code>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td align="center">
<input class="bottom" type="submit" value="{$lng['error']['send_report']}" />
</td>
</tr>
</tfoot>
</table>
</fieldset>
</form>
</section>
</article>
$footer

View File

@@ -0,0 +1,63 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/ipsports_big.png" alt="" />&nbsp;
{$lng['admin']['ipsandports']['ipsandports']}
</h2>
</header>
<section>
<form action="{$linker->getLink(array('section' => 'ipsandports'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s"/>
<input type="hidden" name="page" value="$page"/>
<div class="overviewsearch">
{$searchcode}
</div>
<div class="overviewadd">
<img src="templates/{$theme}/assets/img/icons/add.png" alt="" />&nbsp;
<a href="{$linker->getLink(array('section' => 'ipsandports', 'page' => $page, 'action' => 'add'))}">{$lng['admin']['ipsandports']['add']}</a>
</div>
<table class="full hl">
<thead>
<tr>
<th>{$lng['admin']['ipsandports']['ip']}&nbsp;{$arrowcode['ip']}</th>
<th>{$lng['admin']['ipsandports']['port']}&nbsp;{$arrowcode['port']}</th>
<if !$is_nginx><th>Listen</th></if>
<if $is_apache && !$is_apache24><th>NameVirtualHost</th></if>
<th>vHost-Container</th>
<th>Specialsettings</th>
<if $is_apache><th>ServerName</th></if>
<th>SSL</th>
<th>{$lng['panel']['options']}</th>
</tr>
</thead>
<if $pagingcode != ''>
<tfoot>
<tr>
<td colspan="<if $is_apache>8<else>6</if>">{$pagingcode}</td>
</tr>
</tfoot>
</if>
<tbody>
$ipsandports
</tbody>
</table>
</form>
<if 15 < $count>
<div class="overviewadd">
<img src="templates/{$theme}/assets/img/icons/add.png" alt="" />&nbsp;
<a href="{$linker->getLink(array('section' => 'ipsandports', 'page' => $page, 'action' => 'add'))}">{$lng['admin']['ipsandports']['add']}</a>
</div>
</if>
</section>
</article>
$footer

View File

@@ -0,0 +1,26 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/ipsports_add_big.png" alt="{$title}" />&nbsp;
{$title}
</h2>
</header>
<section>
<form action="{$linker->getLink(array('section' => 'ipsandports'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="action" value="$action" />
<input type="hidden" name="send" value="send" />
<table class="full">
{$ipsandports_add_form}
</table>
</form>
</section>
</article>
$footer

View File

@@ -0,0 +1,27 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/ipsports_edit_big.png" alt="{$title}" />&nbsp;
{$title}
</h2>
</header>
<section>
<form action="{$linker->getLink(array('section' => 'ipsandports'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="action" value="$action" />
<input type="hidden" name="id" value="$id" />
<input type="hidden" name="send" value="send" />
<table class="full">
{$ipsandports_edit_form}
</table>
</form>
</section>
</article>
$footer

View File

@@ -0,0 +1,18 @@
<tr>
<td>{$row['ip']}</td>
<td>{$row['port']}</td>
<if !$is_nginx><td><if $row['listen_statement']=='1'>{$lng['panel']['yes']}<else>{$lng['panel']['no']}</if></td></if>
<if $is_apache && !$is_apache24><td><if $row['namevirtualhost_statement']=='1'>{$lng['panel']['yes']}<else>{$lng['panel']['no']}</if></td></if>
<td><if $row['vhostcontainer']=='1'>{$lng['panel']['yes']}<else>{$lng['panel']['no']}</if></td>
<td><if $row['specialsettings']!=''>{$lng['panel']['yes']}<else>{$lng['panel']['no']}</if></td>
<if $is_apache><td><if $row['vhostcontainer_servername_statement']=='1'>{$lng['panel']['yes']}<else>{$lng['panel']['no']}</if></td></if>
<td><if $row['ssl']=='1'>{$lng['panel']['yes']}<else>{$lng['panel']['no']}</if></td>
<td>
<a href="{$linker->getLink(array('section' => 'ipsandports', 'page' => $page, 'action' => 'edit', 'id' => $row['id']))}">
<img src="templates/{$theme}/assets/img/icons/edit.png" alt="{$lng['panel']['edit']}" title="{$lng['panel']['edit']}" />
</a>&nbsp;
<a href="{$linker->getLink(array('section' => 'ipsandports', 'page' => $page, 'action' => 'delete', 'id' => $row['id']))}">
<img src="templates/{$theme}/assets/img/icons/delete.png" alt="{$lng['panel']['delete']}" title="{$lng['panel']['delete']}" />
</a>
</td>
</tr>

View File

@@ -0,0 +1,53 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/syslog_big.png" alt="" />&nbsp;
{$lng['menue']['logger']['logger']}
</h2>
</header>
<section>
<form action="{$linker->getLink(array('section' => 'logger'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s"/>
<input type="hidden" name="page" value="$page"/>
<input type="hidden" name="send" value="send" />
<div class="overviewsearch">
{$searchcode}
</div>
<div class="overviewadd">
{$pagingcode}&nbsp;&nbsp;
<img src="templates/{$theme}/assets/img/icons/delete.png" alt="" />&nbsp;
<a href="{$linker->getLink(array('section' => 'logger', 'page' => 'log', 'action' => 'truncate'))}">{$lng['logger']['truncate']}</a>
</div>
<table class="full hl">
<thead>
<tr>
<th>{$lng['logger']['date']}&nbsp;{$arrowcode['date']}</th>
<th>{$lng['logger']['type']}&nbsp;{$arrowcode['type']}</th>
<th>{$lng['logger']['user']}&nbsp;{$arrowcode['user']}</th>
<th>{$lng['logger']['action']}</th>
</tr>
</thead>
<tbody>
$log
</tbody>
</table>
</form>
<if 15 < $log_count >
<div class="overviewadd">
{$pagingcode}&nbsp;&nbsp;
<img src="templates/{$theme}/assets/img/icons/delete.png" alt="" />&nbsp;
<a href="{$linker->getLink(array('section' => 'logger', 'page' => 'log', 'action' => 'truncate'))}">{$lng['logger']['truncate']}</a>
</div>
</if>
</section>
</article>
$footer

View File

@@ -0,0 +1,3 @@
<tr>
<td colspan="4"><strong>{$row['action']}</strong></td>
</tr>

View File

@@ -0,0 +1,6 @@
<tr>
<td>{$row['date']}</td>
<td>{$row['type']}</td>
<td>{$row['user']}</td>
<td>{$row['text']}</td>
</tr>

View File

@@ -0,0 +1,50 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/messages_big.png" alt="" />&nbsp;
{$lng['admin']['message']}
</h2>
</header>
<if 0 < $success >
<div class="successcontainer bradius">
<div class="successtitle">{$lng['success']['success']}</div>
<div class="success">{$successmessage}</div>
</div>
</if>
<section>
<form action="$filename" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s"/>
<input type="hidden" name="page" value="$page"/>
<input type="hidden" name="action" value="$action"/>
<input type="hidden" name="send" value="send"/>
<table class="full">
<tr>
<td><b><label for="receipient">{$lng['admin']['receipient']}</label></b></td>
<td><select name="receipient" id="receipient">$receipients</select></td>
</tr>
<tr>
<td><b><label for="subject">{$lng['admin']['subject']}</label></b></td>
<td><input type="text" name="subject" id="subject" value="{$lng['admin']['nosubject']}"/></td>
</tr>
<tr>
<td><b><label for="message">{$lng['admin']['text']}</label></b></td>
<td><textarea rows="12" cols="80" name="message" id="message"></textarea></td>
</tr>
<tfoot>
<tr>
<td align="right" colspan="2">
<input type="submit" value="{$lng['panel']['send']}" />
</td>
</tr>
</tfoot>
</table>
</form>
</section>
</article>
$footer

View File

@@ -0,0 +1,98 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/phpsettings_add_big.png" alt="{$title}" />&nbsp;
{$title}
</h2>
</header>
<section>
<form action="{$linker->getLink(array('section' => 'phpsettings'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="action" value="$action" />
<input type="hidden" name="send" value="send" />
<table class="full">
{$fpmconfig_add_form}
</table>
</form>
</section>
</article>
<br />
<article>
<header>
<h3>
{$lng['admin']['templates']['template_replace_vars']}
</h3>
</header>
<section>
<table class="full">
<thead>
<tr>
<th>{$lng['panel']['variable']}</th>
<th>{$lng['panel']['description']}</th>
</tr>
</thead>
<tbody>
<tr>
<td><em>{PEAR_DIR}</em></td>
<td>{$lng['admin']['phpconfig']['pear_dir']}</td>
</tr>
<tr>
<td><em>{OPEN_BASEDIR_C}</em></td>
<td>{$lng['admin']['phpconfig']['open_basedir_c']}</td>
</tr>
<tr>
<td><em>{OPEN_BASEDIR}</em></td>
<td>{$lng['admin']['phpconfig']['open_basedir']}</td>
</tr>
<tr>
<td><em>{OPEN_BASEDIR_GLOBAL}</em></td>
<td>{$lng['admin']['phpconfig']['open_basedir_global']}</td>
</tr>
<tr>
<td><em>{TMP_DIR}</em></td>
<td>{$lng['admin']['phpconfig']['tmp_dir']}</td>
</tr>
<tr>
<td><em>{CUSTOMER_EMAIL}</em></td>
<td>{$lng['admin']['phpconfig']['customer_email']}</td>
</tr>
<tr>
<td><em>{ADMIN_EMAIL}</em></td>
<td>{$lng['admin']['phpconfig']['admin_email']}</td>
</tr>
<tr>
<td><em>{DOMAIN}</em></td>
<td>{$lng['admin']['phpconfig']['domain']}</td>
</tr>
<tr>
<td><em>{CUSTOMER}</em></td>
<td>{$lng['admin']['phpconfig']['customer']}</td>
</tr>
<tr>
<td><em>{ADMIN}</em></td>
<td>{$lng['admin']['phpconfig']['admin']}</td>
</tr>
<tr>
<td><em>{DOCUMENT_ROOT}</em></td>
<td>{$lng['admin']['phpconfig']['docroot']}</td>
</tr>
<tr>
<td><em>{CUSTOMER_HOMEDIR}</em></td>
<td>{$lng['admin']['phpconfig']['homedir']}</td>
</tr>
</tbody>
</table>
</section>
</article>
$footer

Some files were not shown because too many files have changed in this diff Show More