Compare commits
196 Commits
2.0.4
...
5bb228ce78
| Author | SHA1 | Date | |
|---|---|---|---|
| 5bb228ce78 | |||
| 804128280c | |||
| 5b8e918f75 | |||
| 0e3e83d184 | |||
| 8ced61c6aa | |||
| 29a2ab7567 | |||
|
|
166ec0575b | ||
|
|
215e749ba8 | ||
|
|
506cccd7c8 | ||
|
|
6d9014c29b | ||
|
|
10555bff76 | ||
|
|
37aa7af4da | ||
|
|
4b75369597 | ||
|
|
9d0e463906 | ||
|
|
a7198f58ce | ||
|
|
47be4b2847 | ||
|
|
b0fae4bd14 | ||
|
|
4711a41436 | ||
|
|
faa71ceaef | ||
|
|
2d30394150 | ||
|
|
99c1182af8 | ||
|
|
d9abe58dd2 | ||
|
|
23034b8ad2 | ||
|
|
1cae5638d3 | ||
|
|
ce9a5f97a3 | ||
|
|
c38b90deef | ||
|
|
13daa7d6fa | ||
|
|
b0e43d332d | ||
|
|
75c8754fb4 | ||
|
|
e0fa64f897 | ||
|
|
ed72fd1766 | ||
|
|
826ae36647 | ||
|
|
9ddf24539e | ||
|
|
3940c1429d | ||
|
|
c236d9eaab | ||
|
|
688994e40c | ||
|
|
9facaee809 | ||
|
|
a7dd5f4685 | ||
|
|
da810ea953 | ||
|
|
51b6e067e8 | ||
|
|
34cf6698bc | ||
|
|
4642160724 | ||
|
|
78a259ef3b | ||
|
|
68cf4ab69a | ||
|
|
d5661d492d | ||
|
|
6900898ae1 | ||
|
|
d90fb7fa68 | ||
|
|
4ea8629fcc | ||
|
|
9d4ff8698d | ||
|
|
b164038846 | ||
|
|
5c46960734 | ||
|
|
a7f4f0c737 | ||
|
|
b64dd501dd | ||
|
|
1679675aa1 | ||
|
|
640466f301 | ||
|
|
9c9771a371 | ||
|
|
1922b3ce65 | ||
|
|
83e819908a | ||
|
|
0924aa644b | ||
|
|
7711ce1d66 | ||
|
|
7dae63e586 | ||
|
|
1bcaa45492 | ||
|
|
66cb114f0d | ||
|
|
1c5d60dcfd | ||
|
|
b6da6356fc | ||
|
|
c09670cc45 | ||
|
|
464f5b7bed | ||
|
|
c799235c24 | ||
|
|
a2860e70a5 | ||
|
|
95a96d46a6 | ||
|
|
81f3dbda31 | ||
|
|
4eb4191843 | ||
|
|
ca433d8a61 | ||
|
|
8f4dfe1514 | ||
|
|
ee42f5168e | ||
|
|
fc8ca57f8c | ||
|
|
7e4bba2d55 | ||
|
|
7e635f9be4 | ||
|
|
e9406a20f2 | ||
|
|
de7729cec8 | ||
|
|
d60e48849b | ||
|
|
908df5a7bb | ||
|
|
c1952afb94 | ||
|
|
7a22e8f4dd | ||
|
|
3ac0da2cdd | ||
|
|
eb816c4cc6 | ||
|
|
64d8bf4fba | ||
|
|
ae6ee95973 | ||
|
|
e9051dc30a | ||
|
|
b6c7c53c3a | ||
|
|
f36bc61fc7 | ||
|
|
c56e0b9dac | ||
|
|
1deb08bf75 | ||
|
|
b30d7a8252 | ||
|
|
b03e11c18d | ||
|
|
bf7d22a794 | ||
|
|
fb57a8a3b5 | ||
|
|
0d625797b0 | ||
|
|
6777fbf229 | ||
|
|
23f1f79eff | ||
|
|
a5af104d53 | ||
|
|
38d94698ce | ||
|
|
5ba28ef599 | ||
|
|
a3486cc5b3 | ||
|
|
5ab322ab1d | ||
|
|
4f26bdd535 | ||
|
|
88f76e4355 | ||
|
|
a464d8cb19 | ||
|
|
0f596dce8b | ||
|
|
60270b20b3 | ||
|
|
4003a8d2b6 | ||
|
|
89843d6f37 | ||
|
|
256a52a5da | ||
|
|
c9b2bfe53c | ||
|
|
98cb36327e | ||
|
|
7d23e4882d | ||
|
|
1cc3a1d066 | ||
|
|
de0f7d2f01 | ||
|
|
aa48ffca2b | ||
|
|
802168cb5b | ||
|
|
6ace2e9f3d | ||
|
|
0bff360d22 | ||
|
|
e300acf109 | ||
|
|
14d8e12cdc | ||
|
|
d29411dba6 | ||
|
|
464663877c | ||
|
|
c3f769d48b | ||
|
|
f97536ed02 | ||
|
|
7686effc8c | ||
|
|
ee8385467b | ||
|
|
0a51d97684 | ||
|
|
67fc762eef | ||
|
|
8378795f5d | ||
|
|
98e6f1df4a | ||
|
|
674e35e5c5 | ||
|
|
b24ca44e6f | ||
|
|
e0f7fcd2ef | ||
|
|
c5bece64ce | ||
|
|
0034681412 | ||
|
|
bd5b99dc1c | ||
|
|
2feb802094 | ||
|
|
7b08a71c59 | ||
|
|
2a84e9c120 | ||
|
|
d854e8e991 | ||
|
|
0a363910d6 | ||
|
|
b23d5cd909 | ||
|
|
3b753aa69d | ||
|
|
492cd288bc | ||
|
|
47938c5082 | ||
|
|
97c4c9a366 | ||
|
|
d090e48544 | ||
|
|
314e4407a0 | ||
|
|
ed50e03957 | ||
|
|
dff7530cc5 | ||
|
|
19423c9644 | ||
|
|
42b3f1e59d | ||
|
|
1b77632fa8 | ||
|
|
867b7b1390 | ||
|
|
4c6ebde58c | ||
|
|
1e013d9e9a | ||
|
|
c56bc651b9 | ||
|
|
6cbdf45a7c | ||
|
|
715667e227 | ||
|
|
41de161555 | ||
|
|
1f1ea370c0 | ||
|
|
090cfc26f2 | ||
|
|
529890b5d2 | ||
|
|
d4a6ab146d | ||
|
|
e3f02879cf | ||
|
|
b52d6df777 | ||
|
|
9e671100ae | ||
|
|
7e801ea502 | ||
|
|
b68522f7d5 | ||
|
|
86852942e0 | ||
|
|
ea88d53e39 | ||
|
|
61f6a474e4 | ||
|
|
ec05c84f4d | ||
|
|
9e13c077e9 | ||
|
|
da8d315e77 | ||
|
|
82af9af1e1 | ||
|
|
cb67e3ae63 | ||
|
|
82d15c4dc2 | ||
|
|
6d048e2cee | ||
|
|
87bd80eea1 | ||
|
|
80e442e396 | ||
|
|
489ad375bd | ||
|
|
c420196e73 | ||
|
|
cc6d8d5f8b | ||
|
|
24f47bc58b | ||
|
|
c769c074e0 | ||
|
|
2ecb8eb034 | ||
|
|
6827c100c3 | ||
|
|
c402acd1bd | ||
|
|
c4ec2509fa | ||
|
|
0f382586ce | ||
|
|
9c2f12ecb1 |
50
.drone.yml
Normal file
50
.drone.yml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
kind: pipeline
|
||||||
|
name: deploy-froxlor
|
||||||
|
type: docker
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: linux
|
||||||
|
arch: arm64
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
- upgrade-2.0
|
||||||
|
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
|
||||||
|
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
|
||||||
|
- name: npm
|
||||||
|
image: appleboy/drone-ssh
|
||||||
|
settings:
|
||||||
|
host:
|
||||||
|
- rechner02.maketank.net
|
||||||
|
username: www-data
|
||||||
|
key:
|
||||||
|
from_secret: ssh-www-data-maketank-rsa
|
||||||
|
script:
|
||||||
|
- cd ~/froxlor-test && npm install && npm run build
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
name: build-docs
|
name: build-documentation
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
@@ -11,4 +11,4 @@ jobs:
|
|||||||
- env:
|
- env:
|
||||||
GITHUB_TOKEN: ${{ secrets.ORG_GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.ORG_GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
gh workflow run --repo Froxlor/Documentation build-docs -f ref=${{github.ref_name}}
|
gh workflow run --repo Froxlor/Documentation build-and-deploy.yml -f type=tags ref=${{github.ref_name}}
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,6 +2,7 @@ install/update.log
|
|||||||
install/*.json
|
install/*.json
|
||||||
lib/userdata.inc.php
|
lib/userdata.inc.php
|
||||||
lib/userdata.inc.php.bak
|
lib/userdata.inc.php.bak
|
||||||
|
lib/config.inc.php
|
||||||
logs/*
|
logs/*
|
||||||
!logs/index.html
|
!logs/index.html
|
||||||
.buildpath
|
.buildpath
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ May be found in [COPYING](COPYING)
|
|||||||
### Tarball
|
### Tarball
|
||||||
https://files.froxlor.org/releases/froxlor-latest.tar.gz [MD5](https://files.froxlor.org/releases/froxlor-latest.tar.gz.md5) [SHA1](https://files.froxlor.org/releases/froxlor-latest.tar.gz.sha1)
|
https://files.froxlor.org/releases/froxlor-latest.tar.gz [MD5](https://files.froxlor.org/releases/froxlor-latest.tar.gz.md5) [SHA1](https://files.froxlor.org/releases/froxlor-latest.tar.gz.sha1)
|
||||||
|
|
||||||
### Debian / Ubutnu repository
|
### Debian / Ubuntu repository
|
||||||
|
|
||||||
[HowTo](https://docs.froxlor.org/latest/general/installation/apt-package.html)
|
[HowTo](https://docs.froxlor.org/latest/general/installation/apt-package.html)
|
||||||
|
|
||||||
|
|||||||
@@ -269,7 +269,8 @@ return [
|
|||||||
'traffic' => lng('menue.traffic.traffic'),
|
'traffic' => lng('menue.traffic.traffic'),
|
||||||
'traffic.http' => lng('menue.traffic.traffic') . " / HTTP",
|
'traffic.http' => lng('menue.traffic.traffic') . " / HTTP",
|
||||||
'traffic.ftp' => lng('menue.traffic.traffic') . " / FTP",
|
'traffic.ftp' => lng('menue.traffic.traffic') . " / FTP",
|
||||||
'traffic.mail' => lng('menue.traffic.traffic') . " / Mail"
|
'traffic.mail' => lng('menue.traffic.traffic') . " / Mail",
|
||||||
|
'misc.documentation' => lng('admin.documentation'),
|
||||||
],
|
],
|
||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
|
|||||||
@@ -138,6 +138,26 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
|
'system_req_limit_per_interval' => [
|
||||||
|
'label' => lng('serversettings.req_limit_per_interval'),
|
||||||
|
'settinggroup' => 'system',
|
||||||
|
'varname' => 'req_limit_per_interval',
|
||||||
|
'type' => 'number',
|
||||||
|
'min' => 30,
|
||||||
|
'default' => 60,
|
||||||
|
'save_method' => 'storeSettingField',
|
||||||
|
'advanced_mode' => true
|
||||||
|
],
|
||||||
|
'system_req_limit_interval' => [
|
||||||
|
'label' => lng('serversettings.req_limit_interval'),
|
||||||
|
'settinggroup' => 'system',
|
||||||
|
'varname' => 'req_limit_interval',
|
||||||
|
'type' => 'number',
|
||||||
|
'min' => 5,
|
||||||
|
'default' => 60,
|
||||||
|
'save_method' => 'storeSettingField',
|
||||||
|
'advanced_mode' => true
|
||||||
|
],
|
||||||
'customer_accountprefix' => [
|
'customer_accountprefix' => [
|
||||||
'label' => lng('serversettings.accountprefix'),
|
'label' => lng('serversettings.accountprefix'),
|
||||||
'settinggroup' => 'customer',
|
'settinggroup' => 'customer',
|
||||||
|
|||||||
@@ -109,7 +109,19 @@ return [
|
|||||||
'default' => false,
|
'default' => false,
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
],
|
],
|
||||||
'update_channel' => [
|
'api_customer_default' => [
|
||||||
|
'label' => lng('serversettings.api_customer_default'),
|
||||||
|
'settinggroup' => 'api',
|
||||||
|
'varname' => 'customer_default',
|
||||||
|
'type' => 'select',
|
||||||
|
'default' => 1,
|
||||||
|
'select_var' => [
|
||||||
|
1 => lng('panel.yes'),
|
||||||
|
0 => lng('panel.no')
|
||||||
|
],
|
||||||
|
'save_method' => 'storeSettingField'
|
||||||
|
],
|
||||||
|
'system_update_channel' => [
|
||||||
'label' => lng('serversettings.update_channel'),
|
'label' => lng('serversettings.update_channel'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'update_channel',
|
'varname' => 'update_channel',
|
||||||
@@ -122,7 +134,7 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'system_validatedomain' => [
|
'system_validate_domain' => [
|
||||||
'label' => lng('serversettings.validate_domain'),
|
'label' => lng('serversettings.validate_domain'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'validate_domain',
|
'varname' => 'validate_domain',
|
||||||
@@ -307,7 +319,7 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'hide_incompatible_settings' => [
|
'system_hide_incompatible_settings' => [
|
||||||
'label' => lng('serversettings.hide_incompatible_settings'),
|
'label' => lng('serversettings.hide_incompatible_settings'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'hide_incompatible_settings',
|
'varname' => 'hide_incompatible_settings',
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ return [
|
|||||||
'string_regexp' => '/^(([a-z0-9\-\._]+, ?)*[a-z0-9\-\._]+)?$/i',
|
'string_regexp' => '/^(([a-z0-9\-\._]+, ?)*[a-z0-9\-\._]+)?$/i',
|
||||||
'string_emptyallowed' => true,
|
'string_emptyallowed' => true,
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingClearCertificates',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
/**
|
/**
|
||||||
@@ -154,7 +154,7 @@ return [
|
|||||||
/**
|
/**
|
||||||
* FCGID
|
* FCGID
|
||||||
*/
|
*/
|
||||||
'system_mod_fcgid_enabled_ownvhost' => [
|
'system_mod_fcgid_ownvhost' => [
|
||||||
'label' => lng('serversettings.mod_fcgid_ownvhost'),
|
'label' => lng('serversettings.mod_fcgid_ownvhost'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'mod_fcgid_ownvhost',
|
'varname' => 'mod_fcgid_ownvhost',
|
||||||
@@ -224,7 +224,7 @@ return [
|
|||||||
/**
|
/**
|
||||||
* php-fpm
|
* php-fpm
|
||||||
*/
|
*/
|
||||||
'system_phpfpm_enabled_ownvhost' => [
|
'phpfpm_enabled_ownvhost' => [
|
||||||
'label' => lng('phpfpm.ownvhost'),
|
'label' => lng('phpfpm.ownvhost'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'enabled_ownvhost',
|
'varname' => 'enabled_ownvhost',
|
||||||
@@ -237,7 +237,7 @@ return [
|
|||||||
]),
|
]),
|
||||||
'requires_reconf' => ['system:php-fpm']
|
'requires_reconf' => ['system:php-fpm']
|
||||||
],
|
],
|
||||||
'system_phpfpm_httpuser' => [
|
'phpfpm_vhost_httpuser' => [
|
||||||
'label' => lng('phpfpm.vhost_httpuser'),
|
'label' => lng('phpfpm.vhost_httpuser'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'vhost_httpuser',
|
'varname' => 'vhost_httpuser',
|
||||||
@@ -250,7 +250,7 @@ return [
|
|||||||
]),
|
]),
|
||||||
'requires_reconf' => ['system:php-fpm']
|
'requires_reconf' => ['system:php-fpm']
|
||||||
],
|
],
|
||||||
'system_phpfpm_httpgroup' => [
|
'phpfpm_vhost_httpgroup' => [
|
||||||
'label' => lng('phpfpm.vhost_httpgroup'),
|
'label' => lng('phpfpm.vhost_httpgroup'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'vhost_httpgroup',
|
'varname' => 'vhost_httpgroup',
|
||||||
@@ -263,7 +263,7 @@ return [
|
|||||||
]),
|
]),
|
||||||
'requires_reconf' => ['system:php-fpm']
|
'requires_reconf' => ['system:php-fpm']
|
||||||
],
|
],
|
||||||
'system_phpfpm_defaultini_ownvhost' => [
|
'phpfpm_vhost_defaultini' => [
|
||||||
'label' => lng('serversettings.mod_fcgid.defaultini_ownvhost'),
|
'label' => lng('serversettings.mod_fcgid.defaultini_ownvhost'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'vhost_defaultini',
|
'varname' => 'vhost_defaultini',
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ return [
|
|||||||
'apache2'
|
'apache2'
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'system_apache_itksupport' => [
|
'system_apacheitksupport' => [
|
||||||
'label' => lng('serversettings.apache_itksupport'),
|
'label' => lng('serversettings.apache_itksupport'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'apacheitksupport',
|
'varname' => 'apacheitksupport',
|
||||||
@@ -229,7 +229,7 @@ return [
|
|||||||
'nginx'
|
'nginx'
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'system_customersslpath' => [
|
'system_customer_ssl_path' => [
|
||||||
'label' => lng('serversettings.customerssl_directory'),
|
'label' => lng('serversettings.customerssl_directory'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'customer_ssl_path',
|
'varname' => 'customer_ssl_path',
|
||||||
@@ -287,7 +287,7 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'system_apache_globaldiropt' => [
|
'system_apacheglobaldiropt' => [
|
||||||
'label' => lng('serversettings.apache_globaldiropt'),
|
'label' => lng('serversettings.apache_globaldiropt'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'apacheglobaldiropt',
|
'varname' => 'apacheglobaldiropt',
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ return [
|
|||||||
'title' => lng('admin.sslsettings'),
|
'title' => lng('admin.sslsettings'),
|
||||||
'icon' => 'fa-solid fa-shield',
|
'icon' => 'fa-solid fa-shield',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'system_ssl_enabled' => [
|
'system_use_ssl' => [
|
||||||
'label' => lng('serversettings.ssl.use_ssl'),
|
'label' => lng('serversettings.ssl.use_ssl'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'use_ssl',
|
'varname' => 'use_ssl',
|
||||||
@@ -180,7 +180,9 @@ return [
|
|||||||
'letsencrypt' => 'Let\'s Encrypt (Live)',
|
'letsencrypt' => 'Let\'s Encrypt (Live)',
|
||||||
'buypass_test' => 'Buypass (Test / Staging)',
|
'buypass_test' => 'Buypass (Test / Staging)',
|
||||||
'buypass' => 'Buypass (Live)',
|
'buypass' => 'Buypass (Live)',
|
||||||
'zerossl' => 'ZeroSSL (Live)'
|
'zerossl' => 'ZeroSSL (Live)',
|
||||||
|
'google' => 'Google (Live)',
|
||||||
|
'google_test' => 'Google (Test / Staging)',
|
||||||
],
|
],
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
],
|
],
|
||||||
@@ -239,6 +241,16 @@ return [
|
|||||||
'type' => 'checkbox',
|
'type' => 'checkbox',
|
||||||
'default' => true,
|
'default' => true,
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
|
],
|
||||||
|
'system_le_domain_dnscheck_resolver' => [
|
||||||
|
'label' => lng('serversettings.le_domain_dnscheck_resolver'),
|
||||||
|
'settinggroup' => 'system',
|
||||||
|
'varname' => 'le_domain_dnscheck_resolver',
|
||||||
|
'type' => 'text',
|
||||||
|
'string_regexp' => '/^(([0-9]+ [a-z0-9\-\._]+, ?)*[0-9]+ [a-z0-9\-\._]+)?$/i',
|
||||||
|
'string_emptyallowed' => true,
|
||||||
|
'default' => '',
|
||||||
|
'save_method' => 'storeSettingField'
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ return [
|
|||||||
'lighttpd'
|
'lighttpd'
|
||||||
],
|
],
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'system_mod_fcgid_enabled' => [
|
'system_mod_fcgid' => [
|
||||||
'label' => lng('serversettings.mod_fcgid'),
|
'label' => lng('serversettings.mod_fcgid'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'mod_fcgid',
|
'varname' => 'mod_fcgid',
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ return [
|
|||||||
'title' => lng('admin.phpfpm_settings'),
|
'title' => lng('admin.phpfpm_settings'),
|
||||||
'icon' => 'fa-brands fa-php',
|
'icon' => 'fa-brands fa-php',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'system_phpfpm_enabled' => [
|
'phpfpm_enabled' => [
|
||||||
'label' => lng('serversettings.phpfpm'),
|
'label' => lng('serversettings.phpfpm'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'enabled',
|
'varname' => 'enabled',
|
||||||
@@ -45,7 +45,7 @@ return [
|
|||||||
'overview_option' => true,
|
'overview_option' => true,
|
||||||
'requires_reconf' => ['http', 'system:php-fpm']
|
'requires_reconf' => ['http', 'system:php-fpm']
|
||||||
],
|
],
|
||||||
'system_phpfpm_defaultini' => [
|
'phpfpm_defaultini' => [
|
||||||
'label' => lng('serversettings.mod_fcgid.defaultini'),
|
'label' => lng('serversettings.mod_fcgid.defaultini'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'defaultini',
|
'varname' => 'defaultini',
|
||||||
@@ -57,7 +57,7 @@ return [
|
|||||||
],
|
],
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
],
|
],
|
||||||
'system_phpfpm_aliasconfigdir' => [
|
'phpfpm_aliasconfigdir' => [
|
||||||
'label' => lng('serversettings.phpfpm_settings.aliasconfigdir'),
|
'label' => lng('serversettings.phpfpm_settings.aliasconfigdir'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'aliasconfigdir',
|
'varname' => 'aliasconfigdir',
|
||||||
@@ -67,7 +67,7 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'system_phpfpm_tmpdir' => [
|
'phpfpm_tmpdir' => [
|
||||||
'label' => lng('serversettings.mod_fcgid.tmpdir'),
|
'label' => lng('serversettings.mod_fcgid.tmpdir'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'tmpdir',
|
'varname' => 'tmpdir',
|
||||||
@@ -76,7 +76,7 @@ return [
|
|||||||
'default' => '/var/customers/tmp/',
|
'default' => '/var/customers/tmp/',
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
],
|
],
|
||||||
'system_phpfpm_peardir' => [
|
'phpfpm_peardir' => [
|
||||||
'label' => lng('serversettings.mod_fcgid.peardir'),
|
'label' => lng('serversettings.mod_fcgid.peardir'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'peardir',
|
'varname' => 'peardir',
|
||||||
@@ -88,7 +88,7 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'system_phpfpm_envpath' => [
|
'phpfpm_envpath' => [
|
||||||
'label' => lng('serversettings.phpfpm_settings.envpath'),
|
'label' => lng('serversettings.phpfpm_settings.envpath'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'envpath',
|
'varname' => 'envpath',
|
||||||
@@ -100,7 +100,7 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'system_phpfpm_fastcgi_ipcdir' => [
|
'phpfpm_fastcgi_ipcdir' => [
|
||||||
'label' => lng('serversettings.phpfpm_settings.ipcdir'),
|
'label' => lng('serversettings.phpfpm_settings.ipcdir'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'fastcgi_ipcdir',
|
'varname' => 'fastcgi_ipcdir',
|
||||||
@@ -110,7 +110,7 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'system_phpfpm_use_mod_proxy' => [
|
'phpfpm_use_mod_proxy' => [
|
||||||
'label' => lng('phpfpm.use_mod_proxy'),
|
'label' => lng('phpfpm.use_mod_proxy'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'use_mod_proxy',
|
'varname' => 'use_mod_proxy',
|
||||||
@@ -119,7 +119,7 @@ return [
|
|||||||
'visible' => Settings::Get('system.apache24'),
|
'visible' => Settings::Get('system.apache24'),
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
],
|
],
|
||||||
'system_phpfpm_ini_flags' => [
|
'phpfpm_ini_flags' => [
|
||||||
'label' => lng('phpfpm.ini_flags'),
|
'label' => lng('phpfpm.ini_flags'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'ini_flags',
|
'varname' => 'ini_flags',
|
||||||
@@ -128,7 +128,7 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'system_phpfpm_ini_values' => [
|
'phpfpm_ini_values' => [
|
||||||
'label' => lng('phpfpm.ini_values'),
|
'label' => lng('phpfpm.ini_values'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'ini_values',
|
'varname' => 'ini_values',
|
||||||
@@ -137,7 +137,7 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'system_phpfpm_ini_admin_flags' => [
|
'phpfpm_ini_admin_flags' => [
|
||||||
'label' => lng('phpfpm.ini_admin_flags'),
|
'label' => lng('phpfpm.ini_admin_flags'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'ini_admin_flags',
|
'varname' => 'ini_admin_flags',
|
||||||
@@ -146,7 +146,7 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'system_phpfpm_ini_admin_values' => [
|
'phpfpm_ini_admin_values' => [
|
||||||
'label' => lng('phpfpm.ini_admin_values'),
|
'label' => lng('phpfpm.ini_admin_values'),
|
||||||
'settinggroup' => 'phpfpm',
|
'settinggroup' => 'phpfpm',
|
||||||
'varname' => 'ini_admin_values',
|
'varname' => 'ini_admin_values',
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ return [
|
|||||||
'title' => lng('admin.perl_settings'),
|
'title' => lng('admin.perl_settings'),
|
||||||
'icon' => 'fa-solid fa-code',
|
'icon' => 'fa-solid fa-code',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'perl_path' => [
|
'system_perl_path' => [
|
||||||
'label' => lng('serversettings.perl_path'),
|
'label' => lng('serversettings.perl_path'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'perl_path',
|
'varname' => 'perl_path',
|
||||||
@@ -40,7 +40,7 @@ return [
|
|||||||
'lighttpd'
|
'lighttpd'
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'system_perl_suexecworkaround' => [
|
'perl_suexecworkaround' => [
|
||||||
'label' => lng('serversettings.perl.suexecworkaround'),
|
'label' => lng('serversettings.perl.suexecworkaround'),
|
||||||
'settinggroup' => 'perl',
|
'settinggroup' => 'perl',
|
||||||
'varname' => 'suexecworkaround',
|
'varname' => 'suexecworkaround',
|
||||||
@@ -51,7 +51,7 @@ return [
|
|||||||
'apache2'
|
'apache2'
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'system_perl_suexeccgipath' => [
|
'perl_suexecpath' => [
|
||||||
'label' => lng('serversettings.perl.suexeccgipath'),
|
'label' => lng('serversettings.perl.suexeccgipath'),
|
||||||
'settinggroup' => 'perl',
|
'settinggroup' => 'perl',
|
||||||
'varname' => 'suexecpath',
|
'varname' => 'suexecpath',
|
||||||
@@ -63,7 +63,7 @@ return [
|
|||||||
'apache2'
|
'apache2'
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'perl_server' => [
|
'serversettings_perl_server' => [
|
||||||
'label' => lng('serversettings.perl_server'),
|
'label' => lng('serversettings.perl_server'),
|
||||||
'settinggroup' => 'serversettings',
|
'settinggroup' => 'serversettings',
|
||||||
'varname' => 'perl_server',
|
'varname' => 'perl_server',
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ return [
|
|||||||
'default' => 100,
|
'default' => 100,
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
],
|
],
|
||||||
'system_catchall_enabled' => [
|
'catchall_catchall_enabled' => [
|
||||||
'label' => lng('serversettings.catchall_enabled'),
|
'label' => lng('serversettings.catchall_enabled'),
|
||||||
'settinggroup' => 'catchall',
|
'settinggroup' => 'catchall',
|
||||||
'varname' => 'catchall_enabled',
|
'varname' => 'catchall_enabled',
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ return [
|
|||||||
'title' => lng('admin.ftpserversettings'),
|
'title' => lng('admin.ftpserversettings'),
|
||||||
'icon' => 'fa-solid fa-arrow-right-arrow-left',
|
'icon' => 'fa-solid fa-arrow-right-arrow-left',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'ftpserver' => [
|
'system_ftpserver' => [
|
||||||
'label' => lng('admin.ftpserver'),
|
'label' => lng('admin.ftpserver'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'ftpserver',
|
'varname' => 'ftpserver',
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ return [
|
|||||||
'title' => lng('admin.nameserversettings'),
|
'title' => lng('admin.nameserversettings'),
|
||||||
'icon' => 'fa-solid fa-globe',
|
'icon' => 'fa-solid fa-globe',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'nameserver_enable' => [
|
'system_bind_enable' => [
|
||||||
'label' => lng('serversettings.bindenable'),
|
'label' => lng('serversettings.bindenable'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'bind_enable',
|
'varname' => 'bind_enable',
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ return [
|
|||||||
'title' => lng('admin.dkimsettings'),
|
'title' => lng('admin.dkimsettings'),
|
||||||
'icon' => 'fa-solid fa-fingerprint',
|
'icon' => 'fa-solid fa-fingerprint',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'dkim_enabled' => [
|
'dkim_use_dkim' => [
|
||||||
'label' => lng('dkim.use_dkim'),
|
'label' => lng('dkim.use_dkim'),
|
||||||
'settinggroup' => 'dkim',
|
'settinggroup' => 'dkim',
|
||||||
'varname' => 'use_dkim',
|
'varname' => 'use_dkim',
|
||||||
@@ -40,7 +40,7 @@ return [
|
|||||||
'save_method' => 'storeSettingFieldInsertBindTask',
|
'save_method' => 'storeSettingFieldInsertBindTask',
|
||||||
'overview_option' => true
|
'overview_option' => true
|
||||||
],
|
],
|
||||||
'dkim_prefix' => [
|
'dkim_dkim_prefix' => [
|
||||||
'label' => lng('dkim.dkim_prefix'),
|
'label' => lng('dkim.dkim_prefix'),
|
||||||
'settinggroup' => 'dkim',
|
'settinggroup' => 'dkim',
|
||||||
'varname' => 'dkim_prefix',
|
'varname' => 'dkim_prefix',
|
||||||
@@ -59,7 +59,7 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'dkim_domains' => [
|
'dkim_dkim_domains' => [
|
||||||
'label' => lng('dkim.dkim_domains'),
|
'label' => lng('dkim.dkim_domains'),
|
||||||
'settinggroup' => 'dkim',
|
'settinggroup' => 'dkim',
|
||||||
'varname' => 'dkim_domains',
|
'varname' => 'dkim_domains',
|
||||||
@@ -68,7 +68,7 @@ return [
|
|||||||
'default' => 'domains',
|
'default' => 'domains',
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
],
|
],
|
||||||
'dkim_dkimkeys' => [
|
'dkim_dkim_dkimkeys' => [
|
||||||
'label' => lng('dkim.dkim_dkimkeys'),
|
'label' => lng('dkim.dkim_dkimkeys'),
|
||||||
'settinggroup' => 'dkim',
|
'settinggroup' => 'dkim',
|
||||||
'varname' => 'dkim_dkimkeys',
|
'varname' => 'dkim_dkimkeys',
|
||||||
@@ -77,7 +77,7 @@ return [
|
|||||||
'default' => 'dkim-keys.conf',
|
'default' => 'dkim-keys.conf',
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
],
|
],
|
||||||
'dkim_algorithm' => [
|
'dkim_dkim_algorithm' => [
|
||||||
'label' => lng('dkim.dkim_algorithm'),
|
'label' => lng('dkim.dkim_algorithm'),
|
||||||
'settinggroup' => 'dkim',
|
'settinggroup' => 'dkim',
|
||||||
'varname' => 'dkim_algorithm',
|
'varname' => 'dkim_algorithm',
|
||||||
@@ -92,7 +92,7 @@ return [
|
|||||||
'save_method' => 'storeSettingFieldInsertBindTask',
|
'save_method' => 'storeSettingFieldInsertBindTask',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'dkim_servicetype' => [
|
'dkim_dkim_servicetype' => [
|
||||||
'label' => lng('dkim.dkim_servicetype'),
|
'label' => lng('dkim.dkim_servicetype'),
|
||||||
'settinggroup' => 'dkim',
|
'settinggroup' => 'dkim',
|
||||||
'varname' => 'dkim_servicetype',
|
'varname' => 'dkim_servicetype',
|
||||||
@@ -105,7 +105,7 @@ return [
|
|||||||
'save_method' => 'storeSettingFieldInsertBindTask',
|
'save_method' => 'storeSettingFieldInsertBindTask',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'dkim_keylength' => [
|
'dkim_dkim_keylength' => [
|
||||||
'label' => [
|
'label' => [
|
||||||
'title' => lng('dkim.dkim_keylength.title'),
|
'title' => lng('dkim.dkim_keylength.title'),
|
||||||
'description' => lng('dkim.dkim_keylength.description', [Settings::Get('dkim.dkim_prefix')])
|
'description' => lng('dkim.dkim_keylength.description', [Settings::Get('dkim.dkim_prefix')])
|
||||||
@@ -120,7 +120,7 @@ return [
|
|||||||
],
|
],
|
||||||
'save_method' => 'storeSettingFieldInsertBindTask'
|
'save_method' => 'storeSettingFieldInsertBindTask'
|
||||||
],
|
],
|
||||||
'dkim_notes' => [
|
'dkim_dkim_notes' => [
|
||||||
'label' => lng('dkim.dkim_notes'),
|
'label' => lng('dkim.dkim_notes'),
|
||||||
'settinggroup' => 'dkim',
|
'settinggroup' => 'dkim',
|
||||||
'varname' => 'dkim_notes',
|
'varname' => 'dkim_notes',
|
||||||
@@ -130,7 +130,7 @@ return [
|
|||||||
'save_method' => 'storeSettingFieldInsertBindTask',
|
'save_method' => 'storeSettingFieldInsertBindTask',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
],
|
],
|
||||||
'dkimrestart_command' => [
|
'dkim_dkimrestart_command' => [
|
||||||
'label' => lng('dkim.dkimrestart_command'),
|
'label' => lng('dkim.dkimrestart_command'),
|
||||||
'settinggroup' => 'dkim',
|
'settinggroup' => 'dkim',
|
||||||
'varname' => 'dkimrestart_command',
|
'varname' => 'dkimrestart_command',
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ return [
|
|||||||
'title' => lng('admin.spfsettings'),
|
'title' => lng('admin.spfsettings'),
|
||||||
'icon' => 'fa-solid fa-clipboard-check',
|
'icon' => 'fa-solid fa-clipboard-check',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'use_spf' => [
|
'spf_use_spf' => [
|
||||||
'label' => lng('spf.use_spf'),
|
'label' => lng('spf.use_spf'),
|
||||||
'settinggroup' => 'spf',
|
'settinggroup' => 'spf',
|
||||||
'varname' => 'use_spf',
|
'varname' => 'use_spf',
|
||||||
@@ -38,7 +38,7 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'overview_option' => true
|
'overview_option' => true
|
||||||
],
|
],
|
||||||
'spf_entry' => [
|
'spf_spf_entry' => [
|
||||||
'label' => lng('spf.spf_entry'),
|
'label' => lng('spf.spf_entry'),
|
||||||
'settinggroup' => 'spf',
|
'settinggroup' => 'spf',
|
||||||
'varname' => 'spf_entry',
|
'varname' => 'spf_entry',
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ return [
|
|||||||
'icon' => 'fa-solid fa-sliders',
|
'icon' => 'fa-solid fa-sliders',
|
||||||
'advanced_mode' => true,
|
'advanced_mode' => true,
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'diskquota_enabled' => [
|
'system_diskquota_enabled' => [
|
||||||
'label' => lng('serversettings.diskquota_enabled'),
|
'label' => lng('serversettings.diskquota_enabled'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'diskquota_enabled',
|
'varname' => 'diskquota_enabled',
|
||||||
@@ -39,7 +39,7 @@ return [
|
|||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'overview_option' => true
|
'overview_option' => true
|
||||||
],
|
],
|
||||||
'diskquota_repquota_path' => [
|
'system_diskquota_repquota_path' => [
|
||||||
'label' => lng('serversettings.diskquota_repquota_path.description'),
|
'label' => lng('serversettings.diskquota_repquota_path.description'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'diskquota_repquota_path',
|
'varname' => 'diskquota_repquota_path',
|
||||||
@@ -47,7 +47,7 @@ return [
|
|||||||
'default' => '/usr/sbin/repquota',
|
'default' => '/usr/sbin/repquota',
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
],
|
],
|
||||||
'diskquota_quotatool_path' => [
|
'system_diskquota_quotatool_path' => [
|
||||||
'label' => lng('serversettings.diskquota_quotatool_path.description'),
|
'label' => lng('serversettings.diskquota_quotatool_path.description'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'diskquota_quotatool_path',
|
'varname' => 'diskquota_quotatool_path',
|
||||||
@@ -55,7 +55,7 @@ return [
|
|||||||
'default' => '/usr/bin/quotatool',
|
'default' => '/usr/bin/quotatool',
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
],
|
],
|
||||||
'diskquota_customer_partition' => [
|
'system_diskquota_customer_partition' => [
|
||||||
'label' => lng('serversettings.diskquota_customer_partition.description'),
|
'label' => lng('serversettings.diskquota_customer_partition.description'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'diskquota_customer_partition',
|
'varname' => 'diskquota_customer_partition',
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ if (($page == 'admins' || $page == 'overview') && $userinfo['change_serversettin
|
|||||||
$result['switched_user'] = CurrentUser::getData();
|
$result['switched_user'] = CurrentUser::getData();
|
||||||
$result['adminsession'] = 1;
|
$result['adminsession'] = 1;
|
||||||
$result['userid'] = $result['adminid'];
|
$result['userid'] = $result['adminid'];
|
||||||
|
session_regenerate_id(true);
|
||||||
CurrentUser::setData($result);
|
CurrentUser::setData($result);
|
||||||
|
|
||||||
$log->logAction(
|
$log->logAction(
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ require __DIR__ . '/lib/init.php';
|
|||||||
|
|
||||||
use Froxlor\Froxlor;
|
use Froxlor\Froxlor;
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\Http\HttpClient;
|
use Froxlor\FileDir;
|
||||||
use Froxlor\Install\AutoUpdate;
|
use Froxlor\Install\AutoUpdate;
|
||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
use Froxlor\UI\Panel\UI;
|
use Froxlor\UI\Panel\UI;
|
||||||
@@ -132,7 +132,7 @@ elseif ($page == 'getdownload') {
|
|||||||
elseif ($page == 'extract') {
|
elseif ($page == 'extract') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
||||||
$toExtract = isset($_POST['archive']) ? $_POST['archive'] : null;
|
$toExtract = isset($_POST['archive']) ? $_POST['archive'] : null;
|
||||||
$localArchive = Froxlor::getInstallDir() . '/updates/' . $toExtract;
|
$localArchive = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/updates/' . $toExtract);
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Extracting " . $localArchive . " to " . Froxlor::getInstallDir());
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Extracting " . $localArchive . " to " . Froxlor::getInstallDir());
|
||||||
$result = AutoUpdate::extractZip($localArchive);
|
$result = AutoUpdate::extractZip($localArchive);
|
||||||
if ($result > 0) {
|
if ($result > 0) {
|
||||||
@@ -146,7 +146,7 @@ elseif ($page == 'extract') {
|
|||||||
Response::redirectTo('admin_updates.php');
|
Response::redirectTo('admin_updates.php');
|
||||||
} else {
|
} else {
|
||||||
$toExtract = isset($_GET['archive']) ? $_GET['archive'] : null;
|
$toExtract = isset($_GET['archive']) ? $_GET['archive'] : null;
|
||||||
$localArchive = Froxlor::getInstallDir() . '/updates/' . $toExtract;
|
$localArchive = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/updates/' . $toExtract);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file_exists($localArchive)) {
|
if (!file_exists($localArchive)) {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ use Froxlor\Settings;
|
|||||||
use Froxlor\UI\Panel\UI;
|
use Froxlor\UI\Panel\UI;
|
||||||
use Froxlor\UI\Request;
|
use Froxlor\UI\Request;
|
||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
|
use Froxlor\Validate\Validate;
|
||||||
|
|
||||||
if ($userinfo['change_serversettings'] == '1') {
|
if ($userinfo['change_serversettings'] == '1') {
|
||||||
if ($action == 'setconfigured') {
|
if ($action == 'setconfigured') {
|
||||||
@@ -91,13 +92,29 @@ if ($userinfo['change_serversettings'] == '1') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($distribution != "" && isset($_POST['finish'])) {
|
if ($distribution != "" && isset($_POST['finish'])) {
|
||||||
|
$valid_keys = ['http', 'dns', 'smtp', 'mail', 'ftp', 'system', 'distro'];
|
||||||
unset($_POST['finish']);
|
unset($_POST['finish']);
|
||||||
|
unset($_POST['csrf_token']);
|
||||||
$params = $_POST;
|
$params = $_POST;
|
||||||
$params['distro'] = $distribution;
|
$params['distro'] = $distribution;
|
||||||
$params['system'] = [];
|
$params['system'] = [];
|
||||||
foreach ($_POST['system'] as $sysdaemon) {
|
foreach ($_POST['system'] as $sysdaemon) {
|
||||||
$params['system'][] = $sysdaemon;
|
$params['system'][] = $sysdaemon;
|
||||||
}
|
}
|
||||||
|
// validate params
|
||||||
|
foreach ($params as $key => $value) {
|
||||||
|
if (!in_array($key, $valid_keys)) {
|
||||||
|
unset($params[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!is_array($value)) {
|
||||||
|
$params[$key] = Validate::validate($value, $key);
|
||||||
|
} else {
|
||||||
|
foreach ($value as $subkey => $subvalue) {
|
||||||
|
$params[$key][$subkey] = Validate::validate($subvalue, $key.'.'.$subkey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
$params_content = json_encode($params);
|
$params_content = json_encode($params);
|
||||||
$params_filename = FileDir::makeCorrectFile(Froxlor::getInstallDir() . 'install/' . Froxlor::genSessionId() . '.json');
|
$params_filename = FileDir::makeCorrectFile(Froxlor::getInstallDir() . 'install/' . Froxlor::genSessionId() . '.json');
|
||||||
file_put_contents($params_filename, $params_content);
|
file_put_contents($params_filename, $params_content);
|
||||||
@@ -121,8 +138,6 @@ if ($userinfo['change_serversettings'] == '1') {
|
|||||||
'distribution' => $distribution
|
'distribution' => $distribution
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
// @fixme check set distribution from settings
|
|
||||||
|
|
||||||
$cfg_formfield = [
|
$cfg_formfield = [
|
||||||
'config' => [
|
'config' => [
|
||||||
'title' => lng('admin.configfiles.serverconfiguration'),
|
'title' => lng('admin.configfiles.serverconfiguration'),
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
|
|||||||
$result['switched_user'] = CurrentUser::getData();
|
$result['switched_user'] = CurrentUser::getData();
|
||||||
$result['adminsession'] = 0;
|
$result['adminsession'] = 0;
|
||||||
$result['userid'] = $result['customerid'];
|
$result['userid'] = $result['customerid'];
|
||||||
|
session_regenerate_id(true);
|
||||||
CurrentUser::setData($result);
|
CurrentUser::setData($result);
|
||||||
|
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "switched user and is now '" . $destination_user . "'");
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "switched user and is now '" . $destination_user . "'");
|
||||||
|
|||||||
@@ -282,6 +282,12 @@ if ($page == 'domains' || $page == 'overview') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$openbasedir = [
|
||||||
|
0 => lng('domain.docroot'),
|
||||||
|
1 => lng('domain.homedir'),
|
||||||
|
2 => lng('domain.docparent')
|
||||||
|
];
|
||||||
|
|
||||||
// create serveralias options
|
// create serveralias options
|
||||||
$serveraliasoptions = [
|
$serveraliasoptions = [
|
||||||
0 => lng('domains.serveraliasoption_wildcard'),
|
0 => lng('domains.serveraliasoption_wildcard'),
|
||||||
@@ -545,6 +551,12 @@ if ($page == 'domains' || $page == 'overview') {
|
|||||||
$result['temporary_ssl_redirect'] = $result['ssl_redirect'];
|
$result['temporary_ssl_redirect'] = $result['ssl_redirect'];
|
||||||
$result['ssl_redirect'] = ($result['ssl_redirect'] == 0 ? 0 : 1);
|
$result['ssl_redirect'] = ($result['ssl_redirect'] == 0 ? 0 : 1);
|
||||||
|
|
||||||
|
$openbasedir = [
|
||||||
|
0 => lng('domain.docroot'),
|
||||||
|
1 => lng('domain.homedir'),
|
||||||
|
2 => lng('domain.docparent')
|
||||||
|
];
|
||||||
|
|
||||||
$serveraliasoptions = [
|
$serveraliasoptions = [
|
||||||
0 => lng('domains.serveraliasoption_wildcard'),
|
0 => lng('domains.serveraliasoption_wildcard'),
|
||||||
1 => lng('domains.serveraliasoption_www'),
|
1 => lng('domains.serveraliasoption_www'),
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ if ($action == 'logout') {
|
|||||||
if (is_array(CurrentUser::getField('switched_user'))) {
|
if (is_array(CurrentUser::getField('switched_user'))) {
|
||||||
$result = CurrentUser::getData();
|
$result = CurrentUser::getData();
|
||||||
$result = $result['switched_user'];
|
$result = $result['switched_user'];
|
||||||
|
session_regenerate_id(true);
|
||||||
CurrentUser::setData($result);
|
CurrentUser::setData($result);
|
||||||
$target = (isset($_GET['target']) ? $_GET['target'] : 'index');
|
$target = (isset($_GET['target']) ? $_GET['target'] : 'index');
|
||||||
$redirect = "admin_" . $target . ".php";
|
$redirect = "admin_" . $target . ".php";
|
||||||
|
|||||||
@@ -43,12 +43,6 @@ use PHPMailer\PHPMailer\PHPMailer;
|
|||||||
const AREA = 'admin';
|
const AREA = 'admin';
|
||||||
require __DIR__ . '/lib/init.php';
|
require __DIR__ . '/lib/init.php';
|
||||||
|
|
||||||
// get sql-root access data
|
|
||||||
Database::needRoot(true);
|
|
||||||
Database::needSqlData();
|
|
||||||
$sql_root = Database::getSqlData();
|
|
||||||
Database::needRoot(false);
|
|
||||||
|
|
||||||
if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
||||||
$settings_data = PhpHelper::loadConfigArrayDir('./actions/admin/settings/');
|
$settings_data = PhpHelper::loadConfigArrayDir('./actions/admin/settings/');
|
||||||
Settings::loadSettingsInto($settings_data);
|
Settings::loadSettingsInto($settings_data);
|
||||||
|
|||||||
@@ -253,6 +253,9 @@ if ($action == '') {
|
|||||||
if (isset($_POST['prepare']) && $_POST['prepare'] == 'prepare') {
|
if (isset($_POST['prepare']) && $_POST['prepare'] == 'prepare') {
|
||||||
// email templates
|
// email templates
|
||||||
$language = htmlentities(Validate::validate($_POST['language'], 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect'));
|
$language = htmlentities(Validate::validate($_POST['language'], 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect'));
|
||||||
|
if (!array_key_exists($language, $languages)) {
|
||||||
|
Response::standardError('templatelanguageinvalid');
|
||||||
|
}
|
||||||
$template = Validate::validate($_POST['template'], 'template');
|
$template = Validate::validate($_POST['template'], 'template');
|
||||||
|
|
||||||
$result_stmt = Database::prepare("
|
$result_stmt = Database::prepare("
|
||||||
@@ -288,6 +291,9 @@ if ($action == '') {
|
|||||||
} elseif (isset($_POST['send']) && $_POST['send'] == 'send' && !isset($_POST['filesend'])) {
|
} elseif (isset($_POST['send']) && $_POST['send'] == 'send' && !isset($_POST['filesend'])) {
|
||||||
// email templates
|
// email templates
|
||||||
$language = htmlentities(Validate::validate($_POST['language'], 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect'));
|
$language = htmlentities(Validate::validate($_POST['language'], 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect'));
|
||||||
|
if (!array_key_exists($language, $languages)) {
|
||||||
|
Response::standardError('templatelanguageinvalid');
|
||||||
|
}
|
||||||
$template = Validate::validate($_POST['template'], 'template');
|
$template = Validate::validate($_POST['template'], 'template');
|
||||||
$subject = Validate::validate($_POST['subject'], 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate');
|
$subject = Validate::validate($_POST['subject'], 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate');
|
||||||
$mailbody = Validate::validate($_POST['mailbody'], 'mailbody', '/^[^\0]+$/', 'nomailbodycreate');
|
$mailbody = Validate::validate($_POST['mailbody'], 'mailbody', '/^[^\0]+$/', 'nomailbodycreate');
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Froxlor\Cli\ConfigDiff;
|
||||||
use Symfony\Component\Console\Application;
|
use Symfony\Component\Console\Application;
|
||||||
use Froxlor\Cli\RunApiCommand;
|
use Froxlor\Cli\RunApiCommand;
|
||||||
use Froxlor\Cli\ConfigServices;
|
use Froxlor\Cli\ConfigServices;
|
||||||
@@ -35,6 +36,7 @@ use Froxlor\Cli\UpdateCommand;
|
|||||||
use Froxlor\Cli\InstallCommand;
|
use Froxlor\Cli\InstallCommand;
|
||||||
use Froxlor\Cli\MasterCron;
|
use Froxlor\Cli\MasterCron;
|
||||||
use Froxlor\Cli\UserCommand;
|
use Froxlor\Cli\UserCommand;
|
||||||
|
use Froxlor\Cli\ValidateAcmeWebroot;
|
||||||
use Froxlor\Froxlor;
|
use Froxlor\Froxlor;
|
||||||
|
|
||||||
// validate correct php version
|
// validate correct php version
|
||||||
@@ -59,4 +61,6 @@ $application->add(new UpdateCommand());
|
|||||||
$application->add(new InstallCommand());
|
$application->add(new InstallCommand());
|
||||||
$application->add(new MasterCron());
|
$application->add(new MasterCron());
|
||||||
$application->add(new UserCommand());
|
$application->add(new UserCommand());
|
||||||
|
$application->add(new ValidateAcmeWebroot());
|
||||||
|
$application->add(new ConfigDiff());
|
||||||
$application->run();
|
$application->run();
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
"ext-openssl": "*",
|
"ext-openssl": "*",
|
||||||
"ext-fileinfo": "*",
|
"ext-fileinfo": "*",
|
||||||
"ext-gmp": "*",
|
"ext-gmp": "*",
|
||||||
|
"ext-gd": "*",
|
||||||
"phpmailer/phpmailer": "~6.0",
|
"phpmailer/phpmailer": "~6.0",
|
||||||
"monolog/monolog": "^1.24",
|
"monolog/monolog": "^1.24",
|
||||||
"robthree/twofactorauth": "^1.6",
|
"robthree/twofactorauth": "^1.6",
|
||||||
@@ -52,7 +53,8 @@
|
|||||||
"voku/anti-xss": "^4.1",
|
"voku/anti-xss": "^4.1",
|
||||||
"twig/twig": "^3.3",
|
"twig/twig": "^3.3",
|
||||||
"erusev/parsedown": "^1.7",
|
"erusev/parsedown": "^1.7",
|
||||||
"symfony/console": "^5.4"
|
"symfony/console": "^5.4",
|
||||||
|
"pear/net_dns2": "^1.5"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^9",
|
"phpunit/phpunit": "^9",
|
||||||
|
|||||||
836
composer.lock
generated
836
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -59,7 +59,6 @@ if ($page == 'overview' || $page == 'domains') {
|
|||||||
$domain_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.domains.php';
|
$domain_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.domains.php';
|
||||||
$collection = (new Collection(SubDomains::class, $userinfo))
|
$collection = (new Collection(SubDomains::class, $userinfo))
|
||||||
->withPagination($domain_list_data['domain_list']['columns'], $domain_list_data['domain_list']['default_sorting']);
|
->withPagination($domain_list_data['domain_list']['columns'], $domain_list_data['domain_list']['default_sorting']);
|
||||||
$parentDomainCollection = (new Collection(SubDomains::class, $userinfo, ['sql_search' => ['d.parentdomainid' => 0]]));
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,9 +26,10 @@
|
|||||||
const AREA = 'customer';
|
const AREA = 'customer';
|
||||||
require __DIR__ . '/lib/init.php';
|
require __DIR__ . '/lib/init.php';
|
||||||
|
|
||||||
use Froxlor\Api\Commands\EmailAccounts as EmailAccounts;
|
use Froxlor\Api\Commands\EmailAccounts;
|
||||||
use Froxlor\Api\Commands\EmailForwarders as EmailForwarders;
|
use Froxlor\Api\Commands\EmailForwarders;
|
||||||
use Froxlor\Api\Commands\Emails as Emails;
|
use Froxlor\Api\Commands\Emails;
|
||||||
|
use Froxlor\Api\Commands\EmailDomains;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\PhpHelper;
|
use Froxlor\PhpHelper;
|
||||||
@@ -50,13 +51,50 @@ if (Settings::IsInList('panel.customer_hide_options', 'email') || $userinfo['ema
|
|||||||
$id = (int)Request::any('id');
|
$id = (int)Request::any('id');
|
||||||
|
|
||||||
if ($page == 'overview' || $page == 'emails') {
|
if ($page == 'overview' || $page == 'emails') {
|
||||||
|
$result_stmt = Database::prepare("
|
||||||
|
SELECT COUNT(DISTINCT `domainid`) as maildomains FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `customerid`= :cid
|
||||||
|
");
|
||||||
|
$domain_count = Database::pexecute_first($result_stmt, [
|
||||||
|
"cid" => $userinfo['customerid']
|
||||||
|
]);
|
||||||
|
if ($domain_count['maildomains'] && $domain_count['maildomains'] > 1) {
|
||||||
|
try {
|
||||||
|
$emaildomain_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.emails_overview.php';
|
||||||
|
$collection = (new Collection(EmailDomains::class, $userinfo))
|
||||||
|
->withPagination($emaildomain_list_data['emaildomain_list']['columns'],
|
||||||
|
$emaildomain_list_data['emaildomain_list']['default_sorting']);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Response::dynamicError($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
UI::view('user/table.html.twig', [
|
||||||
|
'listing' => Listing::format($collection, $emaildomain_list_data, 'emaildomain_list'),
|
||||||
|
'actions_links' => CurrentUser::canAddResource('emails') ? [
|
||||||
|
[
|
||||||
|
'href' => $linker->getLink(['section' => 'email', 'page' => 'email_domain', 'action' => 'add']),
|
||||||
|
'label' => lng('emails.emails_add')
|
||||||
|
]
|
||||||
|
] : null,
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
// only emails for one domain -> show email address listing directly
|
||||||
|
$page = 'email_domain';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($page == 'email_domain') {
|
||||||
|
$email_domainid = Request::any('domainid', 0);
|
||||||
if ($action == '') {
|
if ($action == '') {
|
||||||
$log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_email::emails");
|
$log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_email::emails");
|
||||||
|
|
||||||
|
$sql_search = [];
|
||||||
|
if ($email_domainid > 0) {
|
||||||
|
$sql_search = ['sql_search' => ['m.domainid' => ['op' => '=', 'value' => $email_domainid]]];
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
$email_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.emails.php';
|
$email_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.emails.php';
|
||||||
$collection = (new Collection(Emails::class, $userinfo))
|
$collection = (new Collection(Emails::class, $userinfo, $sql_search))
|
||||||
->withPagination($email_list_data['email_list']['columns'], $email_list_data['email_list']['default_sorting']);
|
->withPagination($email_list_data['email_list']['columns'],
|
||||||
|
$email_list_data['email_list']['default_sorting']);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -71,13 +109,22 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
]);
|
]);
|
||||||
$emaildomains_count = $result2['emaildomains'];
|
$emaildomains_count = $result2['emaildomains'];
|
||||||
|
|
||||||
$actions_links = false;
|
$actions_links = [];
|
||||||
|
if ($email_domainid > 0) {
|
||||||
|
$actions_links[] = [
|
||||||
|
'class' => 'btn-outline-primary',
|
||||||
|
'href' => $linker->getLink([
|
||||||
|
'section' => 'email',
|
||||||
|
'page' => 'emails',
|
||||||
|
]),
|
||||||
|
'label' => lng('emails.back_to_overview'),
|
||||||
|
'icon' => 'fa-solid fa-reply'
|
||||||
|
];
|
||||||
|
}
|
||||||
if (CurrentUser::canAddResource('emails')) {
|
if (CurrentUser::canAddResource('emails')) {
|
||||||
$actions_links = [
|
$actions_links[] = [
|
||||||
[
|
'href' => $linker->getLink(['section' => 'email', 'page' => 'email_domain', 'action' => 'add', 'domainid' => $email_domainid]),
|
||||||
'href' => $linker->getLink(['section' => 'email', 'page' => $page, 'action' => 'add']),
|
|
||||||
'label' => lng('emails.emails_add')
|
'label' => lng('emails.emails_add')
|
||||||
]
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +192,11 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
"cid" => $userinfo['customerid']
|
"cid" => $userinfo['customerid']
|
||||||
]);
|
]);
|
||||||
$domains = [];
|
$domains = [];
|
||||||
|
$selected_domain = "";
|
||||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
if ($email_domainid == $row['id']) {
|
||||||
|
$selected_domain = $row['domain'];
|
||||||
|
}
|
||||||
$domains[$row['domain']] = $idna_convert->decode($row['domain']);
|
$domains[$row['domain']] = $idna_convert->decode($row['domain']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,11 +295,13 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
}
|
}
|
||||||
Response::redirectTo($filename, [
|
Response::redirectTo($filename, [
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
|
'domainid' => $email_domainid,
|
||||||
'action' => 'edit',
|
'action' => 'edit',
|
||||||
'id' => $id
|
'id' => $id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} elseif ($page == 'accounts') {
|
} elseif ($page == 'accounts') {
|
||||||
|
$email_domainid = Request::any('domainid', 0);
|
||||||
if ($action == 'add' && $id != 0) {
|
if ($action == 'add' && $id != 0) {
|
||||||
if ($userinfo['email_accounts'] == '-1' || ($userinfo['email_accounts_used'] < $userinfo['email_accounts'])) {
|
if ($userinfo['email_accounts'] == '-1' || ($userinfo['email_accounts_used'] < $userinfo['email_accounts'])) {
|
||||||
try {
|
try {
|
||||||
@@ -267,7 +320,8 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
Response::redirectTo($filename, [
|
Response::redirectTo($filename, [
|
||||||
'page' => 'emails',
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid,
|
||||||
'action' => 'edit',
|
'action' => 'edit',
|
||||||
'id' => $id
|
'id' => $id
|
||||||
]);
|
]);
|
||||||
@@ -292,7 +346,8 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
'class' => 'btn-secondary',
|
'class' => 'btn-secondary',
|
||||||
'href' => $linker->getLink([
|
'href' => $linker->getLink([
|
||||||
'section' => 'email',
|
'section' => 'email',
|
||||||
'page' => 'emails',
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid,
|
||||||
'action' => 'edit',
|
'action' => 'edit',
|
||||||
'id' => $id
|
'id' => $id
|
||||||
]),
|
]),
|
||||||
@@ -301,7 +356,11 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'class' => 'btn-secondary',
|
'class' => 'btn-secondary',
|
||||||
'href' => $linker->getLink(['section' => 'email', 'page' => 'emails']),
|
'href' => $linker->getLink([
|
||||||
|
'section' => 'email',
|
||||||
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid
|
||||||
|
]),
|
||||||
'label' => lng('menue.email.emails'),
|
'label' => lng('menue.email.emails'),
|
||||||
'icon' => 'fa-solid fa-envelope'
|
'icon' => 'fa-solid fa-envelope'
|
||||||
]
|
]
|
||||||
@@ -332,7 +391,8 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
Response::redirectTo($filename, [
|
Response::redirectTo($filename, [
|
||||||
'page' => 'emails',
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid,
|
||||||
'action' => 'edit',
|
'action' => 'edit',
|
||||||
'id' => $id
|
'id' => $id
|
||||||
]);
|
]);
|
||||||
@@ -350,7 +410,8 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
'class' => 'btn-secondary',
|
'class' => 'btn-secondary',
|
||||||
'href' => $linker->getLink([
|
'href' => $linker->getLink([
|
||||||
'section' => 'email',
|
'section' => 'email',
|
||||||
'page' => 'emails',
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid,
|
||||||
'action' => 'edit',
|
'action' => 'edit',
|
||||||
'id' => $id
|
'id' => $id
|
||||||
]),
|
]),
|
||||||
@@ -359,7 +420,11 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'class' => 'btn-secondary',
|
'class' => 'btn-secondary',
|
||||||
'href' => $linker->getLink(['section' => 'email', 'page' => 'emails']),
|
'href' => $linker->getLink([
|
||||||
|
'section' => 'email',
|
||||||
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid
|
||||||
|
]),
|
||||||
'label' => lng('menue.email.emails'),
|
'label' => lng('menue.email.emails'),
|
||||||
'icon' => 'fa-solid fa-envelope'
|
'icon' => 'fa-solid fa-envelope'
|
||||||
]
|
]
|
||||||
@@ -385,7 +450,8 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
Response::redirectTo($filename, [
|
Response::redirectTo($filename, [
|
||||||
'page' => 'emails',
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid,
|
||||||
'action' => 'edit',
|
'action' => 'edit',
|
||||||
'id' => $id
|
'id' => $id
|
||||||
]);
|
]);
|
||||||
@@ -403,7 +469,8 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
'class' => 'btn-secondary',
|
'class' => 'btn-secondary',
|
||||||
'href' => $linker->getLink([
|
'href' => $linker->getLink([
|
||||||
'section' => 'email',
|
'section' => 'email',
|
||||||
'page' => 'emails',
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid,
|
||||||
'action' => 'edit',
|
'action' => 'edit',
|
||||||
'id' => $id
|
'id' => $id
|
||||||
]),
|
]),
|
||||||
@@ -412,7 +479,11 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'class' => 'btn-secondary',
|
'class' => 'btn-secondary',
|
||||||
'href' => $linker->getLink(['section' => 'email', 'page' => 'emails']),
|
'href' => $linker->getLink([
|
||||||
|
'section' => 'email',
|
||||||
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid
|
||||||
|
]),
|
||||||
'label' => lng('menue.email.emails'),
|
'label' => lng('menue.email.emails'),
|
||||||
'icon' => 'fa-solid fa-envelope'
|
'icon' => 'fa-solid fa-envelope'
|
||||||
]
|
]
|
||||||
@@ -438,7 +509,8 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
Response::redirectTo($filename, [
|
Response::redirectTo($filename, [
|
||||||
'page' => 'emails',
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid,
|
||||||
'action' => 'edit',
|
'action' => 'edit',
|
||||||
'id' => $id
|
'id' => $id
|
||||||
]);
|
]);
|
||||||
@@ -446,12 +518,14 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
HTML::askYesNoWithCheckbox('email_reallydelete_account', 'admin_customer_alsoremovemail', $filename, [
|
HTML::askYesNoWithCheckbox('email_reallydelete_account', 'admin_customer_alsoremovemail', $filename, [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
|
'domainid' => $email_domainid,
|
||||||
'action' => $action
|
'action' => $action
|
||||||
], $idna_convert->decode($result['email_full']));
|
], $idna_convert->decode($result['email_full']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($page == 'forwarders') {
|
} elseif ($page == 'forwarders') {
|
||||||
|
$email_domainid = Request::any('domainid', 0);
|
||||||
if ($action == 'add' && $id != 0) {
|
if ($action == 'add' && $id != 0) {
|
||||||
if ($userinfo['email_forwarders_used'] < $userinfo['email_forwarders'] || $userinfo['email_forwarders'] == '-1') {
|
if ($userinfo['email_forwarders_used'] < $userinfo['email_forwarders'] || $userinfo['email_forwarders'] == '-1') {
|
||||||
try {
|
try {
|
||||||
@@ -471,7 +545,8 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
Response::redirectTo($filename, [
|
Response::redirectTo($filename, [
|
||||||
'page' => 'emails',
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid,
|
||||||
'action' => 'edit',
|
'action' => 'edit',
|
||||||
'id' => $id
|
'id' => $id
|
||||||
]);
|
]);
|
||||||
@@ -489,7 +564,8 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
'class' => 'btn-secondary',
|
'class' => 'btn-secondary',
|
||||||
'href' => $linker->getLink([
|
'href' => $linker->getLink([
|
||||||
'section' => 'email',
|
'section' => 'email',
|
||||||
'page' => 'emails',
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid,
|
||||||
'action' => 'edit',
|
'action' => 'edit',
|
||||||
'id' => $id
|
'id' => $id
|
||||||
]),
|
]),
|
||||||
@@ -498,7 +574,11 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'class' => 'btn-secondary',
|
'class' => 'btn-secondary',
|
||||||
'href' => $linker->getLink(['section' => 'email', 'page' => 'emails']),
|
'href' => $linker->getLink([
|
||||||
|
'section' => 'email',
|
||||||
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid
|
||||||
|
]),
|
||||||
'label' => lng('menue.email.emails'),
|
'label' => lng('menue.email.emails'),
|
||||||
'icon' => 'fa-solid fa-envelope'
|
'icon' => 'fa-solid fa-envelope'
|
||||||
]
|
]
|
||||||
@@ -540,7 +620,8 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
Response::redirectTo($filename, [
|
Response::redirectTo($filename, [
|
||||||
'page' => 'emails',
|
'page' => 'email_domain',
|
||||||
|
'domainid' => $email_domainid,
|
||||||
'action' => 'edit',
|
'action' => 'edit',
|
||||||
'id' => $id
|
'id' => $id
|
||||||
]);
|
]);
|
||||||
@@ -549,6 +630,7 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
'id' => $id,
|
'id' => $id,
|
||||||
'forwarderid' => $forwarderid,
|
'forwarderid' => $forwarderid,
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
|
'domainid' => $email_domainid,
|
||||||
'action' => $action
|
'action' => $action
|
||||||
], $idna_convert->decode($result['email_full']) . ' -> ' . $idna_convert->decode($forwarder));
|
], $idna_convert->decode($result['email_full']) . ' -> ' . $idna_convert->decode($forwarder));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ use Froxlor\UI\Response;
|
|||||||
use Froxlor\CurrentUser;
|
use Froxlor\CurrentUser;
|
||||||
|
|
||||||
// redirect if this customer page is hidden via settings
|
// redirect if this customer page is hidden via settings
|
||||||
if (Settings::IsInList('panel.customer_hide_options', 'ftp') || $userinfo['ftps'] == 0) {
|
if (Settings::IsInList('panel.customer_hide_options', 'ftp')) {
|
||||||
Response::redirectTo('customer_index.php');
|
Response::redirectTo('customer_index.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ if ($page == 'overview' || $page == 'accounts') {
|
|||||||
if (Settings::Get('customer.ftpatdomain') == '1') {
|
if (Settings::Get('customer.ftpatdomain') == '1') {
|
||||||
$domainlist = [];
|
$domainlist = [];
|
||||||
$result_domains_stmt = Database::prepare("SELECT `domain` FROM `" . TABLE_PANEL_DOMAINS . "`
|
$result_domains_stmt = Database::prepare("SELECT `domain` FROM `" . TABLE_PANEL_DOMAINS . "`
|
||||||
WHERE `customerid`= :customerid");
|
WHERE `customerid`= :customerid ORDER BY `domain` ASC");
|
||||||
Database::pexecute($result_domains_stmt, [
|
Database::pexecute($result_domains_stmt, [
|
||||||
"customerid" => $userinfo['customerid']
|
"customerid" => $userinfo['customerid']
|
||||||
]);
|
]);
|
||||||
@@ -127,7 +127,6 @@ if ($page == 'overview' || $page == 'accounts') {
|
|||||||
while ($row_domain = $result_domains_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row_domain = $result_domains_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
$domainlist[$row_domain['domain']] = $idna_convert->decode($row_domain['domain']);
|
$domainlist[$row_domain['domain']] = $idna_convert->decode($row_domain['domain']);
|
||||||
}
|
}
|
||||||
sort($domainlist);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::Get('system.allow_customer_shell') == '1') {
|
if (Settings::Get('system.allow_customer_shell') == '1') {
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ if ($action == 'logout') {
|
|||||||
if (is_array(CurrentUser::getField('switched_user'))) {
|
if (is_array(CurrentUser::getField('switched_user'))) {
|
||||||
$result = CurrentUser::getData();
|
$result = CurrentUser::getData();
|
||||||
$result = $result['switched_user'];
|
$result = $result['switched_user'];
|
||||||
|
session_regenerate_id(true);
|
||||||
CurrentUser::setData($result);
|
CurrentUser::setData($result);
|
||||||
$target = (isset($_GET['target']) ? $_GET['target'] : 'index');
|
$target = (isset($_GET['target']) ? $_GET['target'] : 'index');
|
||||||
$redirect = "admin_" . $target . ".php";
|
$redirect = "admin_" . $target . ".php";
|
||||||
@@ -115,10 +116,14 @@ if ($page == 'overview') {
|
|||||||
|
|
||||||
if ($usages) {
|
if ($usages) {
|
||||||
$userinfo['diskspace_bytes_used'] = $usages['webspace'] * 1024;
|
$userinfo['diskspace_bytes_used'] = $usages['webspace'] * 1024;
|
||||||
|
$userinfo['mailspace_used'] = $usages['mail'] * 1024;
|
||||||
|
$userinfo['dbspace_used'] = $usages['mysql'] * 1024;
|
||||||
$userinfo['total_bytes_used'] = ($usages['webspace'] + $usages['mail'] + $usages['mysql']) * 1024;
|
$userinfo['total_bytes_used'] = ($usages['webspace'] + $usages['mail'] + $usages['mysql']) * 1024;
|
||||||
} else {
|
} else {
|
||||||
$userinfo['diskspace_bytes_used'] = 0;
|
$userinfo['diskspace_bytes_used'] = 0;
|
||||||
$userinfo['total_bytes_used'] = 0;
|
$userinfo['total_bytes_used'] = 0;
|
||||||
|
$userinfo['mailspace_used'] = 0;
|
||||||
|
$userinfo['dbspace_used'] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
UI::twig()->addGlobal('userinfo', $userinfo);
|
UI::twig()->addGlobal('userinfo', $userinfo);
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ if ($page == 'overview' || $page == 'mysqls') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['databasename']) && $result['databasename'] != '') {
|
if (isset($result['databasename']) && $result['databasename'] != '') {
|
||||||
Database::needRoot(true, $result['dbserver']);
|
Database::needRoot(true, $result['dbserver'], false);
|
||||||
Database::needSqlData();
|
Database::needSqlData();
|
||||||
$sql_root = Database::getSqlData();
|
$sql_root = Database::getSqlData();
|
||||||
Database::needRoot(false);
|
Database::needRoot(false);
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ if ($action == 'add_record' && !empty($_POST)) {
|
|||||||
try {
|
try {
|
||||||
$dns_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/tablelisting.dns.php';
|
$dns_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/tablelisting.dns.php';
|
||||||
$collection = (new Collection(DomainZones::class, $userinfo, ['id' => $domain_id]))
|
$collection = (new Collection(DomainZones::class, $userinfo, ['id' => $domain_id]))
|
||||||
->withPagination($dns_list_data['dns_list']['columns'], $dns_list_data['dns_list']['default_sorting']);
|
->withPagination($dns_list_data['dns_list']['columns'], $dns_list_data['dns_list']['default_sorting'], ['domain_id='.$domain_id]);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ use Froxlor\Froxlor;
|
|||||||
use Froxlor\UI\Panel\UI;
|
use Froxlor\UI\Panel\UI;
|
||||||
use Froxlor\UI\Request;
|
use Froxlor\UI\Request;
|
||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
|
use Froxlor\Database\Database;
|
||||||
|
|
||||||
// This file is being included in admin_domains and customer_domains
|
// This file is being included in admin_domains and customer_domains
|
||||||
// and therefore does not need to require lib/init.php
|
// and therefore does not need to require lib/init.php
|
||||||
|
|||||||
97
index.php
97
index.php
@@ -40,7 +40,6 @@ use Froxlor\UI\Panel\UI;
|
|||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
use Froxlor\User;
|
use Froxlor\User;
|
||||||
use Froxlor\Validate\Validate;
|
use Froxlor\Validate\Validate;
|
||||||
use Froxlor\Language;
|
|
||||||
|
|
||||||
if ($action == '') {
|
if ($action == '') {
|
||||||
$action = 'login';
|
$action = 'login';
|
||||||
@@ -53,9 +52,15 @@ if ($action == '2fa_entercode') {
|
|||||||
Response::redirectTo('index.php');
|
Response::redirectTo('index.php');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
$smessage = isset($_GET['showmessage']) ? (int)$_GET['showmessage'] : 0;
|
||||||
|
$message = "";
|
||||||
|
if ($smessage > 0) {
|
||||||
|
$message = lng('error.2fa_wrongcode');
|
||||||
|
}
|
||||||
// show template to enter code
|
// show template to enter code
|
||||||
UI::view('login/enter2fa.html.twig', [
|
UI::view('login/enter2fa.html.twig', [
|
||||||
'pagetitle' => lng('login.2fa')
|
'pagetitle' => lng('login.2fa'),
|
||||||
|
'message' => $message
|
||||||
]);
|
]);
|
||||||
} elseif ($action == '2fa_verify') {
|
} elseif ($action == '2fa_verify') {
|
||||||
// verify code from 2fa code-enter form
|
// verify code from 2fa code-enter form
|
||||||
@@ -68,25 +73,25 @@ if ($action == '2fa_entercode') {
|
|||||||
// verify entered code
|
// verify entered code
|
||||||
$tfa = new FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname'));
|
$tfa = new FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname'));
|
||||||
$result = ($_SESSION['secret_2fa'] == 'email' ? true : $tfa->verifyCode($_SESSION['secret_2fa'], $code, 3));
|
$result = ($_SESSION['secret_2fa'] == 'email' ? true : $tfa->verifyCode($_SESSION['secret_2fa'], $code, 3));
|
||||||
// either the code is valid when using authenticator-app, or we will select userdata by id and entered code
|
|
||||||
// which is temporarily stored for the customer when using email-2fa
|
|
||||||
if ($result) {
|
|
||||||
// get user-data
|
// get user-data
|
||||||
$table = $_SESSION['uidtable_2fa'];
|
$table = $_SESSION['uidtable_2fa'];
|
||||||
$field = $_SESSION['uidfield_2fa'];
|
$field = $_SESSION['uidfield_2fa'];
|
||||||
$uid = $_SESSION['uid_2fa'];
|
$uid = $_SESSION['uid_2fa'];
|
||||||
$isadmin = $_SESSION['unfo_2fa'];
|
$isadmin = $_SESSION['unfo_2fa'];
|
||||||
|
// either the code is valid when using authenticator-app, or we will select userdata by id and entered code
|
||||||
|
// which is temporarily stored for the customer when using email-2fa
|
||||||
|
if ($result) {
|
||||||
$sel_param = [
|
$sel_param = [
|
||||||
'uid' => $uid
|
'uid' => $uid
|
||||||
];
|
];
|
||||||
if ($_SESSION['secret_2fa'] == 'email') {
|
if ($_SESSION['secret_2fa'] == 'email') {
|
||||||
// verify code by selecting user by id and the temp. stored code,
|
// verify code by selecting user by id and the temp. stored code,
|
||||||
// so only if it's the correct code, we get the user-data
|
// so only if it's the correct code, we get the user-data
|
||||||
$sel_stmt = Database::prepare("SELECT * FROM $table WHERE `" . $field . "` = :uid AND `data_2fa` = :code");
|
$sel_stmt = Database::prepare("SELECT * FROM " . $table . " WHERE `" . $field . "` = :uid AND `data_2fa` = :code");
|
||||||
$sel_param['code'] = $code;
|
$sel_param['code'] = $code;
|
||||||
} else {
|
} else {
|
||||||
// Authenticator-verification has already happened at this point, so just get the user-data
|
// Authenticator-verification has already happened at this point, so just get the user-data
|
||||||
$sel_stmt = Database::prepare("SELECT * FROM $table WHERE `" . $field . "` = :uid");
|
$sel_stmt = Database::prepare("SELECT * FROM " . $table . " WHERE `" . $field . "` = :uid");
|
||||||
}
|
}
|
||||||
$userinfo = Database::pexecute_first($sel_stmt, $sel_param);
|
$userinfo = Database::pexecute_first($sel_stmt, $sel_param);
|
||||||
// whoops, no (valid) user? Start again
|
// whoops, no (valid) user? Start again
|
||||||
@@ -108,19 +113,54 @@ if ($action == '2fa_entercode') {
|
|||||||
|
|
||||||
// when using email-2fa, remove the one-time-code
|
// when using email-2fa, remove the one-time-code
|
||||||
if ($userinfo['type_2fa'] == '1') {
|
if ($userinfo['type_2fa'] == '1') {
|
||||||
$del_stmt = Database::prepare("UPDATE $table SET `data_2fa` = '' WHERE `" . $field . "` = :uid");
|
$del_stmt = Database::prepare("UPDATE " . $table . " SET `data_2fa` = '' WHERE `" . $field . "` = :uid");
|
||||||
$userinfo = Database::pexecute_first($del_stmt, [
|
$userinfo = Database::pexecute_first($del_stmt, [
|
||||||
'uid' => $uid
|
'uid' => $uid
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
// wrong 2fa code - treat like "wrong password"
|
||||||
|
$stmt = Database::prepare("
|
||||||
|
UPDATE " . $table . "
|
||||||
|
SET `lastlogin_fail`= :lastlogin_fail, `loginfail_count`=`loginfail_count`+1
|
||||||
|
WHERE `" . $field . "`= :uid
|
||||||
|
");
|
||||||
|
Database::pexecute($stmt, [
|
||||||
|
"lastlogin_fail" => time(),
|
||||||
|
"uid" => $uid
|
||||||
|
]);
|
||||||
|
|
||||||
|
// get data for processing further
|
||||||
|
$stmt = Database::prepare("
|
||||||
|
SELECT `loginname`, `loginfail_count`, `lastlogin_fail` FROM " . $table . "
|
||||||
|
WHERE `" . $field . "`= :uid
|
||||||
|
");
|
||||||
|
$fail_user = Database::pexecute_first($stmt, [
|
||||||
|
"uid" => $uid
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($fail_user['loginfail_count'] >= Settings::Get('login.maxloginattempts') && $fail_user['lastlogin_fail'] > (time() - Settings::Get('login.deactivatetime'))) {
|
||||||
|
// Log failed login
|
||||||
|
$rstlog = FroxlorLogger::getInstanceOf([
|
||||||
|
'loginname' => $_SERVER['REMOTE_ADDR']
|
||||||
|
]);
|
||||||
|
$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "User '" . $fail_user['loginname'] . "' entered wrong 2fa code too often.");
|
||||||
|
unset($fail_user);
|
||||||
Response::redirectTo('index.php', [
|
Response::redirectTo('index.php', [
|
||||||
'showmessage' => '2'
|
'showmessage' => '3'
|
||||||
|
]);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
unset($fail_user);
|
||||||
|
// back to form
|
||||||
|
Response::redirectTo('index.php', [
|
||||||
|
'action' => '2fa_entercode',
|
||||||
|
'showmessage' => '1'
|
||||||
]);
|
]);
|
||||||
exit();
|
exit();
|
||||||
} elseif ($action == 'login') {
|
} elseif ($action == 'login') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (!empty($_POST)) {
|
||||||
$loginname = Validate::validate($_POST['loginname'], 'loginname');
|
$loginname = Validate::validate($_POST['loginname'], 'loginname');
|
||||||
$password = Validate::validate($_POST['password'], 'password');
|
$password = Validate::validate($_POST['password'], 'password');
|
||||||
|
|
||||||
@@ -390,13 +430,18 @@ if ($action == '2fa_entercode') {
|
|||||||
}
|
}
|
||||||
$lastqrystr = "";
|
$lastqrystr = "";
|
||||||
if (isset($_REQUEST['qrystr']) && $_REQUEST['qrystr'] != "") {
|
if (isset($_REQUEST['qrystr']) && $_REQUEST['qrystr'] != "") {
|
||||||
$lastqrystr = htmlspecialchars($_REQUEST['qrystr'], ENT_QUOTES);
|
$lastqrystr = urlencode($_REQUEST['qrystr']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($lastscript)) {
|
||||||
|
$_SESSION['lastscript'] = $lastscript;
|
||||||
|
}
|
||||||
|
if (!empty($lastqrystr)) {
|
||||||
|
$_SESSION['lastqrystr'] = $lastqrystr;
|
||||||
}
|
}
|
||||||
|
|
||||||
UI::view('login/login.html.twig', [
|
UI::view('login/login.html.twig', [
|
||||||
'pagetitle' => 'Login',
|
'pagetitle' => 'Login',
|
||||||
'lastscript' => $lastscript,
|
|
||||||
'lastqrystr' => $lastqrystr,
|
|
||||||
'upd_in_progress' => $update_in_progress,
|
'upd_in_progress' => $update_in_progress,
|
||||||
'message' => $message,
|
'message' => $message,
|
||||||
'successmsg' => $successmessage
|
'successmsg' => $successmessage
|
||||||
@@ -408,7 +453,7 @@ if ($action == 'forgotpwd') {
|
|||||||
$adminchecked = false;
|
$adminchecked = false;
|
||||||
$message = '';
|
$message = '';
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (!empty($_POST)) {
|
||||||
$loginname = Validate::validate($_POST['loginname'], 'loginname');
|
$loginname = Validate::validate($_POST['loginname'], 'loginname');
|
||||||
$email = Validate::validateEmail($_POST['loginemail']);
|
$email = Validate::validateEmail($_POST['loginemail']);
|
||||||
$result_stmt = Database::prepare("SELECT `adminid`, `customerid`, `customernumber`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_CUSTOMERS . "`
|
$result_stmt = Database::prepare("SELECT `adminid`, `customerid`, `customernumber`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_CUSTOMERS . "`
|
||||||
@@ -592,7 +637,7 @@ if ($action == 'forgotpwd') {
|
|||||||
|
|
||||||
UI::view('login/fpwd.html.twig', [
|
UI::view('login/fpwd.html.twig', [
|
||||||
'pagetitle' => lng('login.presend'),
|
'pagetitle' => lng('login.presend'),
|
||||||
'action' => $action,
|
'formaction' => 'index.php?action=' . $action,
|
||||||
'message' => $message,
|
'message' => $message,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -615,7 +660,7 @@ if ($action == 'resetpwd') {
|
|||||||
$check = substr($activationcode, 40, 10);
|
$check = substr($activationcode, 40, 10);
|
||||||
|
|
||||||
if (substr(md5($third . $timestamp), 0, 10) == $check && $timestamp >= time() - 86400) {
|
if (substr(md5($third . $timestamp), 0, 10) == $check && $timestamp >= time() - 86400) {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (!empty($_POST)) {
|
||||||
$stmt = Database::prepare("SELECT `userid`, `admin` FROM `" . TABLE_PANEL_ACTIVATION . "`
|
$stmt = Database::prepare("SELECT `userid`, `admin` FROM `" . TABLE_PANEL_ACTIVATION . "`
|
||||||
WHERE `activationcode` = :activationcode");
|
WHERE `activationcode` = :activationcode");
|
||||||
$result = Database::pexecute_first($stmt, [
|
$result = Database::pexecute_first($stmt, [
|
||||||
@@ -692,6 +737,7 @@ if ($action == 'resetpwd') {
|
|||||||
function finishLogin($userinfo)
|
function finishLogin($userinfo)
|
||||||
{
|
{
|
||||||
if (isset($userinfo['userid']) && $userinfo['userid'] != '') {
|
if (isset($userinfo['userid']) && $userinfo['userid'] != '') {
|
||||||
|
session_regenerate_id(true);
|
||||||
CurrentUser::setData($userinfo);
|
CurrentUser::setData($userinfo);
|
||||||
|
|
||||||
$language = $userinfo['def_language'] ?? Settings::Get('panel.standardlanguage');
|
$language = $userinfo['def_language'] ?? Settings::Get('panel.standardlanguage');
|
||||||
@@ -705,29 +751,34 @@ function finishLogin($userinfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
$qryparams = [];
|
$qryparams = [];
|
||||||
if (isset($_POST['qrystr']) && $_POST['qrystr'] != "") {
|
if (!empty($_SESSION['lastqrystr'])) {
|
||||||
parse_str(urldecode($_POST['qrystr']), $qryparams);
|
parse_str(urldecode($_SESSION['lastqrystr']), $qryparams);
|
||||||
|
unset($_SESSION['lastqrystr']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($userinfo['adminsession'] == '1') {
|
if ($userinfo['adminsession'] == '1') {
|
||||||
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
|
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
|
||||||
Response::redirectTo('admin_updates.php?page=overview');
|
Response::redirectTo('admin_updates.php?page=overview');
|
||||||
} else {
|
} else {
|
||||||
if (isset($_POST['script']) && $_POST['script'] != "") {
|
if (!empty($_SESSION['lastscript'])) {
|
||||||
if (preg_match("/customer\_/", $_POST['script']) === 1) {
|
$lastscript = $_SESSION['lastscript'];
|
||||||
|
unset($_SESSION['lastscript']);
|
||||||
|
if (preg_match("/customer\_/", $lastscript) === 1) {
|
||||||
Response::redirectTo('admin_customers.php', [
|
Response::redirectTo('admin_customers.php', [
|
||||||
"page" => "customers"
|
"page" => "customers"
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
Response::redirectTo($_POST['script'], $qryparams);
|
Response::redirectTo($lastscript, $qryparams);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Response::redirectTo('admin_index.php', $qryparams);
|
Response::redirectTo('admin_index.php', $qryparams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isset($_POST['script']) && $_POST['script'] != "") {
|
if (!empty($_SESSION['lastscript'])) {
|
||||||
Response::redirectTo($_POST['script'], $qryparams);
|
$lastscript = $_SESSION['lastscript'];
|
||||||
|
unset($_SESSION['lastscript']);
|
||||||
|
Response::redirectTo($lastscript, $qryparams);
|
||||||
} else {
|
} else {
|
||||||
Response::redirectTo('customer_index.php', $qryparams);
|
Response::redirectTo('customer_index.php', $qryparams);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ CREATE TABLE `panel_customers` (
|
|||||||
`allowed_mysqlserver` text NOT NULL,
|
`allowed_mysqlserver` text NOT NULL,
|
||||||
PRIMARY KEY (`customerid`),
|
PRIMARY KEY (`customerid`),
|
||||||
UNIQUE KEY `loginname` (`loginname`)
|
UNIQUE KEY `loginname` (`loginname`)
|
||||||
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
|
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=DYNAMIC;
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `panel_databases`;
|
DROP TABLE IF EXISTS `panel_databases`;
|
||||||
@@ -642,7 +642,7 @@ opcache.validate_timestamps'),
|
|||||||
('system', 'leprivatekey', 'unset'),
|
('system', 'leprivatekey', 'unset'),
|
||||||
('system', 'lepublickey', 'unset'),
|
('system', 'lepublickey', 'unset'),
|
||||||
('system', 'letsencryptca', 'letsencrypt'),
|
('system', 'letsencryptca', 'letsencrypt'),
|
||||||
('system', 'letsencryptchallengepath', '/var/www/froxlor'),
|
('system', 'letsencryptchallengepath', '/var/www/html/froxlor'),
|
||||||
('system', 'letsencryptkeysize', '4096'),
|
('system', 'letsencryptkeysize', '4096'),
|
||||||
('system', 'letsencryptreuseold', 0),
|
('system', 'letsencryptreuseold', 0),
|
||||||
('system', 'leenabled', '0'),
|
('system', 'leenabled', '0'),
|
||||||
@@ -670,6 +670,7 @@ opcache.validate_timestamps'),
|
|||||||
('system', 'leaccount', ''),
|
('system', 'leaccount', ''),
|
||||||
('system', 'nssextrausers', '1'),
|
('system', 'nssextrausers', '1'),
|
||||||
('system', 'le_domain_dnscheck', '1'),
|
('system', 'le_domain_dnscheck', '1'),
|
||||||
|
('system', 'le_domain_dnscheck_resolver', '1.1.1.1'),
|
||||||
('system', 'ssl_protocols', 'TLSv1.2'),
|
('system', 'ssl_protocols', 'TLSv1.2'),
|
||||||
('system', 'tlsv13_cipher_list', ''),
|
('system', 'tlsv13_cipher_list', ''),
|
||||||
('system', 'honorcipherorder', '0'),
|
('system', 'honorcipherorder', '0'),
|
||||||
@@ -696,9 +697,12 @@ opcache.validate_timestamps'),
|
|||||||
('system', 'distribution', ''),
|
('system', 'distribution', ''),
|
||||||
('system', 'update_channel', 'stable'),
|
('system', 'update_channel', 'stable'),
|
||||||
('system', 'updatecheck_data', ''),
|
('system', 'updatecheck_data', ''),
|
||||||
('system', 'update_notify_last', '2.0.4'),
|
('system', 'update_notify_last', '2.0.24'),
|
||||||
('system', 'traffictool', 'goaccess'),
|
('system', 'traffictool', 'goaccess'),
|
||||||
|
('system', 'req_limit_per_interval', 60),
|
||||||
|
('system', 'req_limit_interval', 60),
|
||||||
('api', 'enabled', '0'),
|
('api', 'enabled', '0'),
|
||||||
|
('api', 'customer_default', '1'),
|
||||||
('2fa', 'enabled', '1'),
|
('2fa', 'enabled', '1'),
|
||||||
('panel', 'decimal_places', '4'),
|
('panel', 'decimal_places', '4'),
|
||||||
('panel', 'adminmail', 'admin@SERVERNAME'),
|
('panel', 'adminmail', 'admin@SERVERNAME'),
|
||||||
@@ -740,8 +744,8 @@ opcache.validate_timestamps'),
|
|||||||
('panel', 'logo_overridetheme', '0'),
|
('panel', 'logo_overridetheme', '0'),
|
||||||
('panel', 'logo_overridecustom', '0'),
|
('panel', 'logo_overridecustom', '0'),
|
||||||
('panel', 'settings_mode', '0'),
|
('panel', 'settings_mode', '0'),
|
||||||
('panel', 'version', '2.0.4'),
|
('panel', 'version', '2.0.24'),
|
||||||
('panel', 'db_version', '202212060');
|
('panel', 'db_version', '202304260');
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `panel_tasks`;
|
DROP TABLE IF EXISTS `panel_tasks`;
|
||||||
@@ -981,7 +985,9 @@ CREATE TABLE IF NOT EXISTS `domain_ssl_settings` (
|
|||||||
`ssl_cert_chainfile` mediumtext,
|
`ssl_cert_chainfile` mediumtext,
|
||||||
`ssl_csr_file` mediumtext,
|
`ssl_csr_file` mediumtext,
|
||||||
`ssl_fullchain_file` mediumtext,
|
`ssl_fullchain_file` mediumtext,
|
||||||
`expirationdate` datetime DEFAULT NULL,
|
`validfromdate` datetime DEFAULT NULL,
|
||||||
|
`validtodate` datetime DEFAULT NULL,
|
||||||
|
`issuer` varchar(255) NOT NULL default '',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY (`domainid`)
|
UNIQUE KEY (`domainid`)
|
||||||
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
|
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Froxlor\Http\RateLimiter;
|
||||||
use Froxlor\UI\Panel\UI;
|
use Froxlor\UI\Panel\UI;
|
||||||
use Froxlor\Install\Install;
|
use Froxlor\Install\Install;
|
||||||
|
|
||||||
@@ -62,6 +63,7 @@ require dirname(__DIR__) . '/lib/tables.inc.php';
|
|||||||
// init twig
|
// init twig
|
||||||
UI::initTwig(true);
|
UI::initTwig(true);
|
||||||
UI::sendHeaders();
|
UI::sendHeaders();
|
||||||
|
RateLimiter::run(true);
|
||||||
|
|
||||||
$installer = new Install();
|
$installer = new Install();
|
||||||
$installer->handle();
|
$installer->handle();
|
||||||
|
|||||||
@@ -23,11 +23,11 @@
|
|||||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Froxlor\Froxlor;
|
|
||||||
use Froxlor\FileDir;
|
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\Settings;
|
use Froxlor\FileDir;
|
||||||
|
use Froxlor\Froxlor;
|
||||||
use Froxlor\Install\Update;
|
use Froxlor\Install\Update;
|
||||||
|
use Froxlor\Settings;
|
||||||
|
|
||||||
if (!defined('_CRON_UPDATE')) {
|
if (!defined('_CRON_UPDATE')) {
|
||||||
if (!defined('AREA') || (defined('AREA') && AREA != 'admin') || !isset($userinfo['loginname']) || (isset($userinfo['loginname']) && $userinfo['loginname'] == '')) {
|
if (!defined('AREA') || (defined('AREA') && AREA != 'admin') || !isset($userinfo['loginname']) || (isset($userinfo['loginname']) && $userinfo['loginname'] == '')) {
|
||||||
@@ -38,7 +38,6 @@ if (!defined('_CRON_UPDATE')) {
|
|||||||
|
|
||||||
// last 0.10.x release
|
// last 0.10.x release
|
||||||
if (Froxlor::isFroxlorVersion('0.10.38.3')) {
|
if (Froxlor::isFroxlorVersion('0.10.38.3')) {
|
||||||
|
|
||||||
$update_to = '2.0.0-beta1';
|
$update_to = '2.0.0-beta1';
|
||||||
|
|
||||||
Update::showUpdateStep("Updating from 0.10.38.3 to " . $update_to, false);
|
Update::showUpdateStep("Updating from 0.10.38.3 to " . $update_to, false);
|
||||||
@@ -66,8 +65,8 @@ if (Froxlor::isFroxlorVersion('0.10.38.3')) {
|
|||||||
KEY customerid (customerid)
|
KEY customerid (customerid)
|
||||||
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;";
|
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;";
|
||||||
Database::query($sql);
|
Database::query($sql);
|
||||||
Database::query("SET SESSION innodb_strict_mode=OFF;");
|
|
||||||
// new customer allowed_mysqlserver field
|
// new customer allowed_mysqlserver field
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ROW_FORMAT=DYNAMIC;");
|
||||||
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE COLUMN `customernumber` `customernumber` varchar(100) NOT NULL default '';");
|
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE COLUMN `customernumber` `customernumber` varchar(100) NOT NULL default '';");
|
||||||
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE COLUMN `allowed_phpconfigs` `allowed_phpconfigs` text NOT NULL;");
|
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE COLUMN `allowed_phpconfigs` `allowed_phpconfigs` text NOT NULL;");
|
||||||
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `allowed_mysqlserver` text NOT NULL;");
|
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `allowed_mysqlserver` text NOT NULL;");
|
||||||
@@ -83,7 +82,7 @@ if (Froxlor::isFroxlorVersion('0.10.38.3')) {
|
|||||||
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` DROP COLUMN `domains_see_all`;");
|
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` DROP COLUMN `domains_see_all`;");
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
Update::showUpdateStep("Checking for multiple mysql-servers to allow acccess to customers for existing databases");
|
Update::showUpdateStep("Checking for multiple mysql-servers to allow access to customers for existing databases");
|
||||||
$dbservers_stmt = Database::query("
|
$dbservers_stmt = Database::query("
|
||||||
SELECT `customerid`,
|
SELECT `customerid`,
|
||||||
GROUP_CONCAT(DISTINCT `dbserver` SEPARATOR ',') as allowed_mysqlserver
|
GROUP_CONCAT(DISTINCT `dbserver` SEPARATOR ',') as allowed_mysqlserver
|
||||||
@@ -94,7 +93,8 @@ if (Froxlor::isFroxlorVersion('0.10.38.3')) {
|
|||||||
while ($dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
if (isset($dbserver['allowed_mysqlserver']) && !empty($dbserver['allowed_mysqlserver'])) {
|
if (isset($dbserver['allowed_mysqlserver']) && !empty($dbserver['allowed_mysqlserver'])) {
|
||||||
$allowed_mysqlserver = json_encode(explode(",", $dbserver['allowed_mysqlserver']));
|
$allowed_mysqlserver = json_encode(explode(",", $dbserver['allowed_mysqlserver']));
|
||||||
Database::pexecute($upd_stmt, ['allowed_mysql_server' => $allowed_mysqlserver, 'customerid' => $dbserver['customerid']]);
|
Database::pexecute($upd_stmt,
|
||||||
|
['allowed_mysql_server' => $allowed_mysqlserver, 'customerid' => $dbserver['customerid']]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
@@ -141,14 +141,15 @@ if (Froxlor::isFroxlorVersion('0.10.38.3')) {
|
|||||||
// none of the files existed
|
// none of the files existed
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
} else {
|
} else {
|
||||||
Update::lastStepStatus(1, 'manual commands needed', 'Please run the following commands manually:<br><pre>' . $del_list . '</pre>');
|
Update::lastStepStatus(1, 'manual commands needed',
|
||||||
|
'Please run the following commands manually:<br><pre>' . $del_list . '</pre>');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Update::showUpdateStep("Adding new settings");
|
Update::showUpdateStep("Adding new settings");
|
||||||
$panel_settings_mode = isset($_POST['panel_settings_mode']) ? (int)$_POST['panel_settings_mode'] : 0;
|
$panel_settings_mode = isset($_POST['panel_settings_mode']) ? (int)$_POST['panel_settings_mode'] : 0;
|
||||||
Settings::AddNew("panel.settings_mode", $panel_settings_mode);
|
Settings::AddNew("panel.settings_mode", $panel_settings_mode);
|
||||||
$system_distribution = isset($_POST['system_distribution']) ? $_POST['system_distribution'] : '';
|
$system_distribution = isset($_POST['system_distribution']) ? $_POST['system_distribution'] : 'bullseye';
|
||||||
Settings::AddNew("system.distribution", $system_distribution);
|
Settings::AddNew("system.distribution", $system_distribution);
|
||||||
Settings::AddNew("system.update_channel", 'stable');
|
Settings::AddNew("system.update_channel", 'stable');
|
||||||
Settings::AddNew("system.updatecheck_data", '');
|
Settings::AddNew("system.updatecheck_data", '');
|
||||||
@@ -183,17 +184,16 @@ if (Froxlor::isFroxlorVersion('0.10.38.3')) {
|
|||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
Update::showUpdateStep("Updating email account password-hashes");
|
Update::showUpdateStep("Updating email account password-hashes");
|
||||||
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password` = REPLACE(`password`, '$1$', '{MD5-CRYPT}$1$') WHERE SUBSTRING(`password`, 1, 3) = '$1$'");
|
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$1$', '{MD5-CRYPT}$1$') WHERE SUBSTRING(`password_enc`, 1, 3) = '$1$'");
|
||||||
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password` = REPLACE(`password`, '$5$', '{SHA256-CRYPT}$5$') WHERE SUBSTRING(`password`, 1, 3) = '$5$'");
|
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$5$', '{SHA256-CRYPT}$5$') WHERE SUBSTRING(`password_enc`, 1, 3) = '$5$'");
|
||||||
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password` = REPLACE(`password`, '$6$', '{SHA512-CRYPT}$6$') WHERE SUBSTRING(`password`, 1, 3) = '$6$'");
|
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$6$', '{SHA512-CRYPT}$6$') WHERE SUBSTRING(`password_enc`, 1, 3) = '$6$'");
|
||||||
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password` = REPLACE(`password`, '$2y$', '{BLF-CRYPT}$2y$') WHERE SUBSTRING(`password`, 1, 4) = '$2y$'");
|
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$2y$', '{BLF-CRYPT}$2y$') WHERE SUBSTRING(`password_enc`, 1, 4) = '$2y$'");
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
Froxlor::updateToVersion($update_to);
|
Froxlor::updateToVersion($update_to);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Froxlor::isDatabaseVersion('202112310')) {
|
if (Froxlor::isDatabaseVersion('202112310')) {
|
||||||
|
|
||||||
Update::showUpdateStep("Adjusting traffic tool settings");
|
Update::showUpdateStep("Adjusting traffic tool settings");
|
||||||
$traffic_tool = Settings::Get('system.awstats_enabled') == 1 ? 'awstats' : 'webalizer';
|
$traffic_tool = Settings::Get('system.awstats_enabled') == 1 ? 'awstats' : 'webalizer';
|
||||||
Settings::AddNew("system.traffictool", $traffic_tool);
|
Settings::AddNew("system.traffictool", $traffic_tool);
|
||||||
@@ -204,8 +204,13 @@ if (Froxlor::isDatabaseVersion('202112310')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Froxlor::isDatabaseVersion('202211030')) {
|
if (Froxlor::isDatabaseVersion('202211030')) {
|
||||||
|
|
||||||
Update::showUpdateStep("Creating backward compatibility for cronjob");
|
Update::showUpdateStep("Creating backward compatibility for cronjob");
|
||||||
|
$disabled = explode(',', ini_get('disable_functions'));
|
||||||
|
$exec_allowed = !in_array('exec', $disabled);
|
||||||
|
// check whether old files could be deleted in previous updates and if not,
|
||||||
|
// user should run cron to regenerate cron.d-file manually as he will run
|
||||||
|
// the other commands manually only after the update so this file would be deleted too
|
||||||
|
if ($exec_allowed) {
|
||||||
$complete_filedir = Froxlor::getInstallDir() . '/scripts';
|
$complete_filedir = Froxlor::getInstallDir() . '/scripts';
|
||||||
mkdir($complete_filedir, 0750, true);
|
mkdir($complete_filedir, 0750, true);
|
||||||
$newCronBin = Froxlor::getInstallDir() . '/bin/froxlor-cli';
|
$newCronBin = Froxlor::getInstallDir() . '/bin/froxlor-cli';
|
||||||
@@ -218,6 +223,12 @@ exit;
|
|||||||
EOF;
|
EOF;
|
||||||
file_put_contents($complete_filedir . '/froxlor_master_cronjob.php', $compCron);
|
file_put_contents($complete_filedir . '/froxlor_master_cronjob.php', $compCron);
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
|
} else {
|
||||||
|
$cron_run_cmd = 'chmod +x ' . FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/bin/froxlor-cli') . PHP_EOL;
|
||||||
|
$cron_run_cmd .= FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/bin/froxlor-cli') . ' froxlor:cron -r 99';
|
||||||
|
Update::lastStepStatus(1, 'manual commands needed',
|
||||||
|
'Please run the following commands manually:<br><pre>' . $cron_run_cmd . '</pre>');
|
||||||
|
}
|
||||||
|
|
||||||
Froxlor::updateToDbVersion('202212060');
|
Froxlor::updateToDbVersion('202212060');
|
||||||
}
|
}
|
||||||
@@ -259,6 +270,9 @@ if (Froxlor::isFroxlorVersion('2.0.3')) {
|
|||||||
// check if compat. cronjob still exists (most likely didn't run successfully b/c of error from former 2.0 release)
|
// check if compat. cronjob still exists (most likely didn't run successfully b/c of error from former 2.0 release)
|
||||||
if (@file_exists($complete_filedir . '/froxlor_master_cronjob.php')) {
|
if (@file_exists($complete_filedir . '/froxlor_master_cronjob.php')) {
|
||||||
Update::showUpdateStep("Adjusting backward compatibility for cronjob");
|
Update::showUpdateStep("Adjusting backward compatibility for cronjob");
|
||||||
|
$disabled = explode(',', ini_get('disable_functions'));
|
||||||
|
$exec_allowed = !in_array('exec', $disabled);
|
||||||
|
if ($exec_allowed) {
|
||||||
$newCronBin = Froxlor::getInstallDir() . '/bin/froxlor-cli';
|
$newCronBin = Froxlor::getInstallDir() . '/bin/froxlor-cli';
|
||||||
$compCron = <<<EOF
|
$compCron = <<<EOF
|
||||||
<?php
|
<?php
|
||||||
@@ -269,7 +283,237 @@ exit;
|
|||||||
EOF;
|
EOF;
|
||||||
file_put_contents($complete_filedir . '/froxlor_master_cronjob.php', $compCron);
|
file_put_contents($complete_filedir . '/froxlor_master_cronjob.php', $compCron);
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
|
} else {
|
||||||
|
$cron_run_cmd = 'chmod +x ' . FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/bin/froxlor-cli') . PHP_EOL;
|
||||||
|
$cron_run_cmd .= FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/bin/froxlor-cli') . ' froxlor:cron -r 99';
|
||||||
|
Update::lastStepStatus(1, 'manual commands needed',
|
||||||
|
'Please run the following commands manually:<br><pre>' . $cron_run_cmd . '</pre>');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Froxlor::updateToVersion('2.0.4');
|
Froxlor::updateToVersion('2.0.4');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.4')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.4 to 2.0.5", false);
|
||||||
|
Froxlor::updateToVersion('2.0.5');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.5')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.5 to 2.0.6", false);
|
||||||
|
|
||||||
|
Update::showUpdateStep("Updating possible missing email account password-hashes");
|
||||||
|
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$1$', '{MD5-CRYPT}$1$') WHERE SUBSTRING(`password_enc`, 1, 3) = '$1$'");
|
||||||
|
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$5$', '{SHA256-CRYPT}$5$') WHERE SUBSTRING(`password_enc`, 1, 3) = '$5$'");
|
||||||
|
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$6$', '{SHA512-CRYPT}$6$') WHERE SUBSTRING(`password_enc`, 1, 3) = '$6$'");
|
||||||
|
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password_enc` = REPLACE(`password_enc`, '$2y$', '{BLF-CRYPT}$2y$') WHERE SUBSTRING(`password_enc`, 1, 4) = '$2y$'");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Froxlor::updateToVersion('2.0.6');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.6')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.6 to 2.0.7", false);
|
||||||
|
|
||||||
|
Update::showUpdateStep("Correcting allowed_mysqlserver for customers");
|
||||||
|
Database::query("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `allowed_mysqlserver` = '[0]' WHERE `allowed_mysqlserver` = ''");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Froxlor::updateToVersion('2.0.7');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isDatabaseVersion('202212060')) {
|
||||||
|
Update::showUpdateStep("Validating acme.sh challenge path");
|
||||||
|
$acmesh_challenge_dir = Settings::Get('system.letsencryptchallengepath');
|
||||||
|
$system_letsencryptchallengepath_upd = isset($_POST['system_letsencryptchallengepath_upd']) ? $_POST['system_letsencryptchallengepath_upd'] : $acmesh_challenge_dir;
|
||||||
|
if ($acmesh_challenge_dir != $system_letsencryptchallengepath_upd) {
|
||||||
|
Settings::Set('system.letsencryptchallengepath', $system_letsencryptchallengepath_upd);
|
||||||
|
if ((int)Settings::Get('system.leenabled') == 1) {
|
||||||
|
// create JSON string for --apply
|
||||||
|
$dist = Settings::Get('system.distribution');
|
||||||
|
$webserver = Settings::Get('system.webserver');
|
||||||
|
if ($webserver == 'apache2') {
|
||||||
|
$webserver = 'apache22';
|
||||||
|
if (Settings::Get('system.apache24')) {
|
||||||
|
$webserver = 'apache24';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$apply_json = '{"http":"' . $webserver . '","dns":"x","smtp":"x","mail":"x","ftp":"x","distro":"' . $dist . '","system":[]}';
|
||||||
|
Update::lastStepStatus(1, 'manual commands needed',
|
||||||
|
"Please reconfigure webserver service using <pre>bin/froxlor-cli froxlor:config-services --apply='" . $apply_json . "'</pre>" .
|
||||||
|
'<br>or adjust the path manually in <pre>' . Settings::Get('system.letsencryptacmeconf') . '</pre>' .
|
||||||
|
'<br><br>In case you already have certificates issued, run the following command to validate and correct the webroot used for renewal:<br>' .
|
||||||
|
'<pre>bin/froxlor-cli froxlor:validate-acme-webroot</pre><br>'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Froxlor::updateToDbVersion('202301120');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.7')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.7 to 2.0.8", false);
|
||||||
|
|
||||||
|
// adjust file-logging to be set to froxlor/logs/
|
||||||
|
$logtypes = explode(',', Settings::Get('logger.logtypes'));
|
||||||
|
if (in_array('file', $logtypes)) {
|
||||||
|
Update::showUpdateStep("Adjusting froxlor logfile for system-logging to be stored in logs/froxlor.log");
|
||||||
|
Settings::Set('logger.logfile', 'froxlor.log');
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Froxlor::updateToVersion('2.0.8');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isDatabaseVersion('202301120')) {
|
||||||
|
Update::showUpdateStep("Adding new setting for DNS resolver when using Let's Encrypt");
|
||||||
|
$system_le_domain_dnscheck_resolver = isset($_POST['system_le_domain_dnscheck_resolver']) ? $_POST['system_le_domain_dnscheck_resolver'] : '1.1.1.1';
|
||||||
|
Settings::AddNew("system.le_domain_dnscheck_resolver", $system_le_domain_dnscheck_resolver);
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Froxlor::updateToDbVersion('202301180');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.8')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.8 to 2.0.9", false);
|
||||||
|
Froxlor::updateToVersion('2.0.9');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.9')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.9 to 2.0.10", false);
|
||||||
|
Froxlor::updateToVersion('2.0.10');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isDatabaseVersion('202301180')) {
|
||||||
|
Update::showUpdateStep("Adding new setting for 'Allow API access' default value for new customers");
|
||||||
|
Settings::AddNew("api.customer_default", "1");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Froxlor::updateToDbVersion('202302030');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.10')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.10 to 2.0.11", false);
|
||||||
|
Froxlor::updateToVersion('2.0.11');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.11')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.11 to 2.0.12", false);
|
||||||
|
Froxlor::updateToVersion('2.0.12');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.12')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.12 to 2.0.13", false);
|
||||||
|
Froxlor::updateToVersion('2.0.13');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isDatabaseVersion('202302030')) {
|
||||||
|
Update::showUpdateStep("Correcting language mapping of templates created pre 2.0.x");
|
||||||
|
// languages from 0.10.x
|
||||||
|
$language_mapping_comp = [
|
||||||
|
'de' => 'Deutsch',
|
||||||
|
'en' => 'English',
|
||||||
|
'fr' => 'Français',
|
||||||
|
'pt' => 'Português',
|
||||||
|
'it' => 'Italiano',
|
||||||
|
'nl' => 'Nederlands',
|
||||||
|
'se' => 'Svenska',
|
||||||
|
'cz' => 'Česká republika'
|
||||||
|
];
|
||||||
|
$upd_tpl_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_TEMPLATES . "` SET `language` = :iso WHERE `language` = :lng");
|
||||||
|
foreach ($language_mapping_comp as $iso => $lang) {
|
||||||
|
Database::pexecute($upd_tpl_stmt, ['iso' => $iso, 'lng' => $lang]);
|
||||||
|
}
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Update::showUpdateStep("Enhancing ssl data table");
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` CHANGE `expirationdate` `validtodate` datetime DEFAULT NULL;");
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` ADD `validfromdate` datetime DEFAULT NULL AFTER `ssl_fullchain_file`;");
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` ADD `issuer` varchar(255) NOT NULL default '' AFTER `validtodate`;");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Update::showUpdateStep("Filling new ssl data fields with existing certificate data");
|
||||||
|
$crt_upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` SET `validfromdate` = :validfromdate, `issuer` = :issuer WHERE `id` = :id");
|
||||||
|
$crt_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`");
|
||||||
|
Database::pexecute($crt_stmt);
|
||||||
|
while ($cert = $crt_stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||||
|
$cert_content = openssl_x509_parse($cert['ssl_cert_file']);
|
||||||
|
if (is_array($cert_content)) {
|
||||||
|
$validfromdate = empty($cert_content['validFrom_time_t']) ? null : date("Y-m-d H:i:s", $cert_content['validFrom_time_t']);
|
||||||
|
$issuer = $cert_content['issuer']['O'] ?? "";
|
||||||
|
Database::pexecute($crt_upd_stmt, ['validfromdate' => $validfromdate, 'issuer' => $issuer, 'id' => $cert['id']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clear possible user customized columns
|
||||||
|
Database::query("DELETE FROM `" . TABLE_PANEL_USERCOLUMNS . "` WHERE `section` = 'sslcertificates_list'");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Froxlor::updateToDbVersion('202303150');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.13')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.13 to 2.0.14", false);
|
||||||
|
Froxlor::updateToVersion('2.0.14');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.14')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.14 to 2.0.15", false);
|
||||||
|
Froxlor::updateToVersion('2.0.15');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isDatabaseVersion('202303150')) {
|
||||||
|
Update::showUpdateStep("Adding new request rate limit settings");
|
||||||
|
Settings::AddNew("system.req_limit_per_interval", "60");
|
||||||
|
Settings::AddNew("system.req_limit_interval", "60");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Froxlor::updateToDbVersion('202304260');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.15')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.15 to 2.0.16", false);
|
||||||
|
Froxlor::updateToVersion('2.0.16');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.16')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.16 to 2.0.17", false);
|
||||||
|
Froxlor::updateToVersion('2.0.17');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.17')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.17 to 2.0.18", false);
|
||||||
|
Froxlor::updateToVersion('2.0.18');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.18')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.18 to 2.0.19", false);
|
||||||
|
Froxlor::updateToVersion('2.0.19');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.19')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.19 to 2.0.20", false);
|
||||||
|
Froxlor::updateToVersion('2.0.20');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.20')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.20 to 2.0.21", false);
|
||||||
|
Froxlor::updateToVersion('2.0.21');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.21')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.21 to 2.0.22", false);
|
||||||
|
Froxlor::updateToVersion('2.0.22');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.22')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.22 to 2.0.23", false);
|
||||||
|
Froxlor::updateToVersion('2.0.23');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.23')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.23 to 2.0.24", false);
|
||||||
|
Froxlor::updateToVersion('2.0.24');
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,9 +34,14 @@ $return = [];
|
|||||||
if (Update::versionInUpdate($current_db_version, '202004140')) {
|
if (Update::versionInUpdate($current_db_version, '202004140')) {
|
||||||
$has_preconfig = true;
|
$has_preconfig = true;
|
||||||
$description = 'Froxlor can now optionally validate the dns entries of domains that request Lets Encrypt certificates to reduce dns-related problems (e.g. freshly registered domain or updated a-record).';
|
$description = 'Froxlor can now optionally validate the dns entries of domains that request Lets Encrypt certificates to reduce dns-related problems (e.g. freshly registered domain or updated a-record).';
|
||||||
$return['system_le_domain_dnscheck_note'] = ['type' => 'infotext', 'value' => $description];
|
|
||||||
$question = '<strong>Validate DNS of domains when using Lets Encrypt ';
|
$question = '<strong>Validate DNS of domains when using Lets Encrypt ';
|
||||||
$return['system_le_domain_dnscheck'] = ['type' => 'checkbox', 'value' => 1, 'checked' => 1, 'label' => $question];
|
$return['system_le_domain_dnscheck'] = [
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'value' => 1,
|
||||||
|
'checked' => 1,
|
||||||
|
'label' => $question,
|
||||||
|
'prior_infotext' => $description
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$preconfig['fields'] = $return;
|
$preconfig['fields'] = $return;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ use Froxlor\Froxlor;
|
|||||||
use Froxlor\FileDir;
|
use Froxlor\FileDir;
|
||||||
use Froxlor\Config\ConfigParser;
|
use Froxlor\Config\ConfigParser;
|
||||||
use Froxlor\Install\Update;
|
use Froxlor\Install\Update;
|
||||||
|
use Froxlor\Settings;
|
||||||
|
|
||||||
$preconfig = [
|
$preconfig = [
|
||||||
'title' => '2.x updates',
|
'title' => '2.x updates',
|
||||||
@@ -36,7 +37,6 @@ $return = [];
|
|||||||
|
|
||||||
if (Update::versionInUpdate($current_version, '2.0.0-beta1')) {
|
if (Update::versionInUpdate($current_version, '2.0.0-beta1')) {
|
||||||
$description = 'We have rearranged the settings and split them into basic and advanced categories. This makes it easier for users who do not need all the detailed or very specific settings and options and gives a better overview of the basic/mostly used settings.';
|
$description = 'We have rearranged the settings and split them into basic and advanced categories. This makes it easier for users who do not need all the detailed or very specific settings and options and gives a better overview of the basic/mostly used settings.';
|
||||||
$return['panel_settings_mode_note'] = ['type' => 'infotext', 'value' => $description];
|
|
||||||
$question = '<strong>Chose settings mode (you can change that at any time)</strong>';
|
$question = '<strong>Chose settings mode (you can change that at any time)</strong>';
|
||||||
$return['panel_settings_mode'] = [
|
$return['panel_settings_mode'] = [
|
||||||
'type' => 'select',
|
'type' => 'select',
|
||||||
@@ -45,16 +45,16 @@ if (Update::versionInUpdate($current_version, '2.0.0-beta1')) {
|
|||||||
1 => 'Advanced'
|
1 => 'Advanced'
|
||||||
],
|
],
|
||||||
'selected' => 1,
|
'selected' => 1,
|
||||||
'label' => $question
|
'label' => $question,
|
||||||
|
'prior_infotext' => $description
|
||||||
];
|
];
|
||||||
|
|
||||||
$description = 'The configuration page now can preselect a distribution, please select your current distribution';
|
$description = 'The configuration page now can preselect a distribution, please select your current distribution';
|
||||||
$return['system_distribution_note'] = ['type' => 'infotext', 'value' => $description];
|
|
||||||
$question = '<strong>Select distribution</strong>';
|
$question = '<strong>Select distribution</strong>';
|
||||||
$config_dir = FileDir::makeCorrectDir(Froxlor::getInstallDir() . '/lib/configfiles/');
|
$config_dir = FileDir::makeCorrectDir(Froxlor::getInstallDir() . '/lib/configfiles/');
|
||||||
// show list of available distro's
|
// show list of available distro's
|
||||||
$distros = glob($config_dir . '*.xml');
|
$distros = glob($config_dir . '*.xml');
|
||||||
$distributions_select[''] = '-';
|
// selection is required $distributions_select[''] = '-';
|
||||||
// read in all the distros
|
// read in all the distros
|
||||||
foreach ($distros as $_distribution) {
|
foreach ($distros as $_distribution) {
|
||||||
// get configparser object
|
// get configparser object
|
||||||
@@ -68,9 +68,44 @@ if (Update::versionInUpdate($current_version, '2.0.0-beta1')) {
|
|||||||
'type' => 'select',
|
'type' => 'select',
|
||||||
'select_var' => $distributions_select,
|
'select_var' => $distributions_select,
|
||||||
'selected' => '',
|
'selected' => '',
|
||||||
'label' => $question
|
'label' => $question,
|
||||||
|
'prior_infotext' => $description
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Update::versionInUpdate($current_db_version, '202301120')) {
|
||||||
|
$acmesh_challenge_dir = rtrim(FileDir::makeCorrectDir(Settings::Get('system.letsencryptchallengepath')), "/");
|
||||||
|
$recommended = rtrim(FileDir::makeCorrectDir(Froxlor::getInstallDir()), "/");
|
||||||
|
if ((int) Settings::Get('system.leenabled') == 1 && $acmesh_challenge_dir != $recommended) {
|
||||||
|
$has_preconfig = true;
|
||||||
|
$description = 'ACME challenge docroot from settings differs from the current installation directory.';
|
||||||
|
$question = '<strong>Validate Let\'s Encrypt challenge path (recommended value: ' . $recommended . ')</strong>';
|
||||||
|
$return['system_letsencryptchallengepath_upd'] = [
|
||||||
|
'type' => 'text',
|
||||||
|
'value' => $recommended,
|
||||||
|
'placeholder' => $acmesh_challenge_dir,
|
||||||
|
'label' => $question,
|
||||||
|
'prior_infotext' => $description,
|
||||||
|
'mandatory' => true,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Update::versionInUpdate($current_db_version, '202301180')) {
|
||||||
|
if ((int) Settings::Get('system.leenabled') == 1) {
|
||||||
|
$has_preconfig = true;
|
||||||
|
$description = 'Froxlor now supports to set an external DNS resolver for the Let\'s Encrypt pre-check.';
|
||||||
|
$question = '<strong>Specify a DNS resolver IP (recommended value: 1.1.1.1 or similar)</strong>';
|
||||||
|
$return['system_le_domain_dnscheck_resolver'] = [
|
||||||
|
'type' => 'text',
|
||||||
|
'pattern' => '^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$|^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$|^\s*$',
|
||||||
|
'value' => '1.1.1.1',
|
||||||
|
'placeholder' => '1.1.1.1',
|
||||||
|
'label' => $question,
|
||||||
|
'prior_infotext' => $description,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$preconfig['fields'] = $return;
|
$preconfig['fields'] = $return;
|
||||||
return $preconfig;
|
return $preconfig;
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ class Ajax
|
|||||||
$content = preg_replace("/[\r\n]+/", " ", strip_tags($item->description));
|
$content = preg_replace("/[\r\n]+/", " ", strip_tags($item->description));
|
||||||
$content = substr($content, 0, 150) . "...";
|
$content = substr($content, 0, 150) . "...";
|
||||||
|
|
||||||
$items .= UI::twig()->render($this->theme . '/user/newsfeeditem.html.twig', [
|
$items .= UI::twig()->render(UI::validateThemeTemplate('/user/newsfeeditem.html.twig', $this->theme), [
|
||||||
'link' => $link,
|
'link' => $link,
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'date' => $date,
|
'date' => $date,
|
||||||
@@ -201,7 +201,7 @@ class Ajax
|
|||||||
$result['last_update_check'] = $uc_data['ts'];
|
$result['last_update_check'] = $uc_data['ts'];
|
||||||
$result['channel'] = Settings::Get('system.update_channel');
|
$result['channel'] = Settings::Get('system.update_channel');
|
||||||
|
|
||||||
$result_rendered = UI::twig()->render($this->theme . '/misc/version_top.html.twig', $result);
|
$result_rendered = UI::twig()->render(UI::validateThemeTemplate('/misc/version_top.html.twig', $this->theme), $result);
|
||||||
return $this->jsonResponse($result_rendered);
|
return $this->jsonResponse($result_rendered);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
// don't display anything if just not allowed due to permissions
|
// don't display anything if just not allowed due to permissions
|
||||||
@@ -237,11 +237,11 @@ class Ajax
|
|||||||
private function updateTablelisting()
|
private function updateTablelisting()
|
||||||
{
|
{
|
||||||
$columns = [];
|
$columns = [];
|
||||||
foreach ((Request::any('columns') ?? []) as $value) {
|
foreach ((Request::post('columns') ?? []) as $value) {
|
||||||
$columns[] = $value;
|
$columns[] = $value;
|
||||||
}
|
}
|
||||||
if (!empty($columns)) {
|
if (!empty($columns)) {
|
||||||
Listing::storeColumnListingForUser([Request::any('listing') => $columns]);
|
$columns = Listing::storeColumnListingForUser([Request::get('listing') => $columns]);
|
||||||
return $this->jsonResponse($columns);
|
return $this->jsonResponse($columns);
|
||||||
}
|
}
|
||||||
return $this->errorResponse('At least one column must be selected', 406);
|
return $this->errorResponse('At least one column must be selected', 406);
|
||||||
@@ -249,7 +249,7 @@ class Ajax
|
|||||||
|
|
||||||
private function resetTablelisting()
|
private function resetTablelisting()
|
||||||
{
|
{
|
||||||
Listing::deleteColumnListingForUser([Request::any('listing') => []]);
|
Listing::deleteColumnListingForUser([Request::get('listing') => []]);
|
||||||
return $this->jsonResponse([]);
|
return $this->jsonResponse([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ namespace Froxlor\Ajax;
|
|||||||
use Froxlor\Api\Commands\Admins;
|
use Froxlor\Api\Commands\Admins;
|
||||||
use Froxlor\Api\Commands\Customers;
|
use Froxlor\Api\Commands\Customers;
|
||||||
use Froxlor\Api\Commands\Domains;
|
use Froxlor\Api\Commands\Domains;
|
||||||
|
use Froxlor\Api\Commands\EmailDomains;
|
||||||
use Froxlor\Api\Commands\Emails;
|
use Froxlor\Api\Commands\Emails;
|
||||||
use Froxlor\Api\Commands\FpmDaemons;
|
use Froxlor\Api\Commands\FpmDaemons;
|
||||||
use Froxlor\Api\Commands\Ftps;
|
use Froxlor\Api\Commands\Ftps;
|
||||||
@@ -267,7 +268,20 @@ class GlobalSearch
|
|||||||
'result_format' => [
|
'result_format' => [
|
||||||
'title' => ['self', 'getFieldFromResult'],
|
'title' => ['self', 'getFieldFromResult'],
|
||||||
'title_args' => 'email',
|
'title_args' => 'email',
|
||||||
'href' => 'customer_email.php?page=emails&searchfield=m.email&searchtext='
|
'href' => 'customer_email.php?page=email_domain&domainid={domainid}&searchfield=m.email&searchtext='
|
||||||
|
]
|
||||||
|
],
|
||||||
|
// email-domains
|
||||||
|
'email_domains' => [
|
||||||
|
'class' => EmailDomains::class,
|
||||||
|
'searchfields' => [
|
||||||
|
'd.domain',
|
||||||
|
],
|
||||||
|
'result_key' => 'domain',
|
||||||
|
'result_format' => [
|
||||||
|
'title' => ['self', 'getFieldFromResult'],
|
||||||
|
'title_args' => 'domain',
|
||||||
|
'href' => 'customer_email.php?page=emails&searchfield=d.domain&searchtext='
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
// databases
|
// databases
|
||||||
@@ -326,6 +340,14 @@ class GlobalSearch
|
|||||||
if (!isset($result[$entity])) {
|
if (!isset($result[$entity])) {
|
||||||
$result[$entity] = [];
|
$result[$entity] = [];
|
||||||
}
|
}
|
||||||
|
// replacer from result in href
|
||||||
|
$href_replacer = [];
|
||||||
|
if (preg_match_all('/\{([a-z]+)\}/', $edata['result_format']['href'], $href_replacer) !== false) {
|
||||||
|
foreach ($href_replacer[1] as $href_field) {
|
||||||
|
$href_field_value = self::getFieldFromResult($cresult, $href_field);
|
||||||
|
$edata['result_format']['href'] = str_replace('{'.$href_field.'}', $href_field_value, $edata['result_format']['href']);
|
||||||
|
}
|
||||||
|
}
|
||||||
$result[$entity][] = [
|
$result[$entity][] = [
|
||||||
'title' => call_user_func($edata['result_format']['title'], $cresult, ($edata['result_format']['title_args'] ?? null)),
|
'title' => call_user_func($edata['result_format']['title'], $cresult, ($edata['result_format']['title_args'] ?? null)),
|
||||||
'href' => $edata['result_format']['href'] . $cresult[$edata['result_key']]
|
'href' => $edata['result_format']['href'] . $cresult[$edata['result_key']]
|
||||||
@@ -335,7 +357,7 @@ class GlobalSearch
|
|||||||
}
|
}
|
||||||
} // foreach entity
|
} // foreach entity
|
||||||
|
|
||||||
} // foreach splitted search-term
|
} // foreach split search-term
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
namespace Froxlor\Api;
|
namespace Froxlor\Api;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Froxlor\Http\RateLimiter;
|
||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
use voku\helper\AntiXSS;
|
use voku\helper\AntiXSS;
|
||||||
|
|
||||||
@@ -52,6 +53,8 @@ class Api
|
|||||||
if (Settings::Get('api.enabled') != 1) {
|
if (Settings::Get('api.enabled') != 1) {
|
||||||
throw new Exception('API is not enabled. Please contact the administrator if you think this is wrong.', 400);
|
throw new Exception('API is not enabled. Please contact the administrator if you think this is wrong.', 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RateLimiter::run();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,6 +120,6 @@ class Api
|
|||||||
|
|
||||||
private function stripcslashesDeep($value)
|
private function stripcslashesDeep($value)
|
||||||
{
|
{
|
||||||
return is_array($value) ? array_map([$this, 'stripcslashesDeep'], $value) : stripcslashes($value);
|
return is_array($value) ? array_map([$this, 'stripcslashesDeep'], $value) : (!empty($value) ? stripcslashes($value) : $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,12 +39,12 @@ abstract class ApiParameter
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param array $params
|
* @param array|null $params
|
||||||
* optional, array of parameters (var=>value) for the command
|
* optional, array of parameters (var=>value) for the command
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function __construct($params = null)
|
public function __construct(array $params = null)
|
||||||
{
|
{
|
||||||
if (!is_null($params)) {
|
if (!is_null($params)) {
|
||||||
$params = $this->trimArray($params);
|
$params = $this->trimArray($params);
|
||||||
@@ -57,7 +57,7 @@ abstract class ApiParameter
|
|||||||
*
|
*
|
||||||
* @param array $input
|
* @param array $input
|
||||||
*
|
*
|
||||||
* @return array
|
* @return string|array
|
||||||
*/
|
*/
|
||||||
private function trimArray($input)
|
private function trimArray($input)
|
||||||
{
|
{
|
||||||
@@ -79,9 +79,9 @@ abstract class ApiParameter
|
|||||||
/**
|
/**
|
||||||
* get specific parameter which also has and unlimited-field
|
* get specific parameter which also has and unlimited-field
|
||||||
*
|
*
|
||||||
* @param string $param
|
* @param string|null $param
|
||||||
* parameter to get out of the request-parameter list
|
* parameter to get out of the request-parameter list
|
||||||
* @param string $ul_field
|
* @param string|null $ul_field
|
||||||
* parameter to get out of the request-parameter list
|
* parameter to get out of the request-parameter list
|
||||||
* @param bool $optional
|
* @param bool $optional
|
||||||
* default: false
|
* default: false
|
||||||
@@ -91,7 +91,7 @@ abstract class ApiParameter
|
|||||||
* @return mixed
|
* @return mixed
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function getUlParam($param = null, $ul_field = null, $optional = false, $default = 0)
|
protected function getUlParam(string $param = null, string $ul_field = null, bool $optional = false, $default = 0)
|
||||||
{
|
{
|
||||||
$param_value = (int)$this->getParam($param, $optional, $default);
|
$param_value = (int)$this->getParam($param, $optional, $default);
|
||||||
$ul_field_value = $this->getBoolParam($ul_field, true, 0);
|
$ul_field_value = $this->getBoolParam($ul_field, true, 0);
|
||||||
@@ -106,7 +106,7 @@ abstract class ApiParameter
|
|||||||
* check for existence and != empty if needed.
|
* check for existence and != empty if needed.
|
||||||
* Maybe more in the future
|
* Maybe more in the future
|
||||||
*
|
*
|
||||||
* @param string $param
|
* @param string|null $param
|
||||||
* parameter to get out of the request-parameter list
|
* parameter to get out of the request-parameter list
|
||||||
* @param bool $optional
|
* @param bool $optional
|
||||||
* default: false
|
* default: false
|
||||||
@@ -116,7 +116,7 @@ abstract class ApiParameter
|
|||||||
* @return mixed
|
* @return mixed
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function getParam($param = null, $optional = false, $default = '')
|
protected function getParam(string $param = null, bool $optional = false, $default = '')
|
||||||
{
|
{
|
||||||
// does it exist?
|
// does it exist?
|
||||||
if (!isset($this->cmd_params[$param])) {
|
if (!isset($this->cmd_params[$param])) {
|
||||||
@@ -128,7 +128,7 @@ abstract class ApiParameter
|
|||||||
return $default;
|
return $default;
|
||||||
}
|
}
|
||||||
// is it empty? - test really on string, as value 0 is being seen as empty by php
|
// is it empty? - test really on string, as value 0 is being seen as empty by php
|
||||||
if ($this->cmd_params[$param] === "") {
|
if (!is_array($this->cmd_params[$param]) && trim($this->cmd_params[$param]) === "") {
|
||||||
if ($optional === false) {
|
if ($optional === false) {
|
||||||
// get module + function for better error-messages
|
// get module + function for better error-messages
|
||||||
$inmod = $this->getModFunctionString();
|
$inmod = $this->getModFunctionString();
|
||||||
@@ -142,7 +142,7 @@ abstract class ApiParameter
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* returns "module::function()" for better error-messages (missing parameter etc.)
|
* returns "module::function()" for better error-messages (missing parameter etc.)
|
||||||
* makes debugging a whole lot more comfortable
|
* makes debugging a lot more comfortable
|
||||||
*
|
*
|
||||||
* @param int $level
|
* @param int $level
|
||||||
* depth of backtrace, default 2
|
* depth of backtrace, default 2
|
||||||
@@ -152,7 +152,7 @@ abstract class ApiParameter
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function getModFunctionString($level = 1, $max_level = 5, $trace = null)
|
private function getModFunctionString(int $level = 1, int $max_level = 5, $trace = null)
|
||||||
{
|
{
|
||||||
// which class called us
|
// which class called us
|
||||||
$_class = get_called_class();
|
$_class = get_called_class();
|
||||||
@@ -174,7 +174,7 @@ abstract class ApiParameter
|
|||||||
/**
|
/**
|
||||||
* getParam wrapper for boolean parameter
|
* getParam wrapper for boolean parameter
|
||||||
*
|
*
|
||||||
* @param string $param
|
* @param string|null $param
|
||||||
* parameter to get out of the request-parameter list
|
* parameter to get out of the request-parameter list
|
||||||
* @param bool $optional
|
* @param bool $optional
|
||||||
* default: false
|
* default: false
|
||||||
@@ -183,7 +183,7 @@ abstract class ApiParameter
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function getBoolParam($param = null, $optional = false, $default = false)
|
protected function getBoolParam(string $param = null, bool $optional = false, $default = false)
|
||||||
{
|
{
|
||||||
$_default = '0';
|
$_default = '0';
|
||||||
if ($default) {
|
if ($default) {
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ class Admins extends ApiCommand implements ResourceEntity
|
|||||||
public function listing()
|
public function listing()
|
||||||
{
|
{
|
||||||
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
|
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list admins");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] list admins");
|
||||||
$query_fields = [];
|
$query_fields = [];
|
||||||
$result_stmt = Database::prepare("
|
$result_stmt = Database::prepare("
|
||||||
SELECT *
|
SELECT *
|
||||||
@@ -407,7 +407,7 @@ class Admins extends ApiCommand implements ResourceEntity
|
|||||||
];
|
];
|
||||||
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get admin '" . $result['loginname'] . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] get admin '" . $result['loginname'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
$key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'");
|
$key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'");
|
||||||
@@ -584,6 +584,18 @@ class Admins extends ApiCommand implements ResourceEntity
|
|||||||
$theme = Settings::Get('panel.default_theme');
|
$theme = Settings::Get('panel.default_theme');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (empty(trim($name))) {
|
||||||
|
Response::standardError([
|
||||||
|
'stringisempty',
|
||||||
|
'admin.name'
|
||||||
|
], '', true);
|
||||||
|
}
|
||||||
|
if (empty(trim($email))) {
|
||||||
|
Response::standardError([
|
||||||
|
'stringisempty',
|
||||||
|
'admin.email'
|
||||||
|
], '', true);
|
||||||
|
}
|
||||||
if (!Validate::validateEmail($email)) {
|
if (!Validate::validateEmail($email)) {
|
||||||
Response::standardError('emailiswrong', $email, true);
|
Response::standardError('emailiswrong', $email, true);
|
||||||
} else {
|
} else {
|
||||||
@@ -705,7 +717,7 @@ class Admins extends ApiCommand implements ResourceEntity
|
|||||||
WHERE `adminid` = :adminid
|
WHERE `adminid` = :adminid
|
||||||
");
|
");
|
||||||
Database::pexecute($upd_stmt, $upd_data, true, true);
|
Database::pexecute($upd_stmt, $upd_data, true, true);
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] edited admin '" . $result['loginname'] . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] edited admin '" . $result['loginname'] . "'");
|
||||||
|
|
||||||
// get all admin-data for return-array
|
// get all admin-data for return-array
|
||||||
$result = $this->apiCall('Admins.get', [
|
$result = $this->apiCall('Admins.get', [
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ class Certificates extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
if (!$has_cert) {
|
if (!$has_cert) {
|
||||||
$this->addOrUpdateCertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, true);
|
$this->addOrUpdateCertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, true);
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added ssl-certificate for '" . $domain['domain'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added ssl-certificate for '" . $domain['domain'] . "'");
|
||||||
$result = $this->apiCall('Certificates.get', [
|
$result = $this->apiCall('Certificates.get', [
|
||||||
'id' => $domain['id']
|
'id' => $domain['id']
|
||||||
]);
|
]);
|
||||||
@@ -127,7 +127,9 @@ class Certificates extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
$do_verify = true;
|
$do_verify = true;
|
||||||
$expirationdate = null;
|
$validtodate = null;
|
||||||
|
$validtodate = null;
|
||||||
|
$issuer = "";
|
||||||
// no cert-file given -> forget everything
|
// no cert-file given -> forget everything
|
||||||
if ($ssl_cert_file == '') {
|
if ($ssl_cert_file == '') {
|
||||||
$ssl_key_file = '';
|
$ssl_key_file = '';
|
||||||
@@ -168,7 +170,10 @@ class Certificates extends ApiCommand implements ResourceEntity
|
|||||||
} else {
|
} else {
|
||||||
Response::standardError('sslcertificateinvalidcert', '', true);
|
Response::standardError('sslcertificateinvalidcert', '', true);
|
||||||
}
|
}
|
||||||
$expirationdate = empty($cert_content['validTo_time_t']) ? null : date("Y-m-d H:i:s", $cert_content['validTo_time_t']);
|
// get data from certificate to store in the table
|
||||||
|
$validfromdate = empty($cert_content['validFrom_time_t']) ? null : date("Y-m-d H:i:s", $cert_content['validFrom_time_t']);
|
||||||
|
$validtodate = empty($cert_content['validTo_time_t']) ? null : date("Y-m-d H:i:s", $cert_content['validTo_time_t']);
|
||||||
|
$issuer = $cert_content['issuer']['O'] ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add/Update database entry
|
// Add/Update database entry
|
||||||
@@ -183,7 +188,9 @@ class Certificates extends ApiCommand implements ResourceEntity
|
|||||||
`ssl_key_file` = :ssl_key_file,
|
`ssl_key_file` = :ssl_key_file,
|
||||||
`ssl_ca_file` = :ssl_ca_file,
|
`ssl_ca_file` = :ssl_ca_file,
|
||||||
`ssl_cert_chainfile` = :ssl_cert_chainfile,
|
`ssl_cert_chainfile` = :ssl_cert_chainfile,
|
||||||
`expirationdate` = :expirationdate
|
`validfromdate` = :validfromdate,
|
||||||
|
`validtodate` = :validtodate,
|
||||||
|
`issuer` = :issuer
|
||||||
" . $qrywhere . " `domainid`= :domainid
|
" . $qrywhere . " `domainid`= :domainid
|
||||||
");
|
");
|
||||||
$params = [
|
$params = [
|
||||||
@@ -191,7 +198,9 @@ class Certificates extends ApiCommand implements ResourceEntity
|
|||||||
"ssl_key_file" => $ssl_key_file,
|
"ssl_key_file" => $ssl_key_file,
|
||||||
"ssl_ca_file" => $ssl_ca_file,
|
"ssl_ca_file" => $ssl_ca_file,
|
||||||
"ssl_cert_chainfile" => $ssl_cert_chainfile,
|
"ssl_cert_chainfile" => $ssl_cert_chainfile,
|
||||||
"expirationdate" => $expirationdate,
|
"validfromdate" => $validfromdate,
|
||||||
|
"validtodate" => $validtodate,
|
||||||
|
"issuer" => $issuer,
|
||||||
"domainid" => $domainid
|
"domainid" => $domainid
|
||||||
];
|
];
|
||||||
Database::pexecute($stmt, $params, true, true);
|
Database::pexecute($stmt, $params, true, true);
|
||||||
@@ -239,7 +248,7 @@ class Certificates extends ApiCommand implements ResourceEntity
|
|||||||
$ssl_ca_file = $this->getParam('ssl_ca_file', true, '');
|
$ssl_ca_file = $this->getParam('ssl_ca_file', true, '');
|
||||||
$ssl_cert_chainfile = $this->getParam('ssl_cert_chainfile', true, '');
|
$ssl_cert_chainfile = $this->getParam('ssl_cert_chainfile', true, '');
|
||||||
$this->addOrUpdateCertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, false);
|
$this->addOrUpdateCertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, false);
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated ssl-certificate for '" . $domain['domain'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] updated ssl-certificate for '" . $domain['domain'] . "'");
|
||||||
$result = $this->apiCall('Certificates.get', [
|
$result = $this->apiCall('Certificates.get', [
|
||||||
'id' => $domain['id']
|
'id' => $domain['id']
|
||||||
]);
|
]);
|
||||||
@@ -299,16 +308,12 @@ class Certificates extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set data from certificate
|
// Set data from certificate
|
||||||
|
$cert['isvalid'] = false;
|
||||||
|
$cert['san'] = null;
|
||||||
$cert_data = openssl_x509_parse($cert['ssl_cert_file']);
|
$cert_data = openssl_x509_parse($cert['ssl_cert_file']);
|
||||||
if ($cert_data) {
|
if ($cert_data) {
|
||||||
$cert['validfromdate'] = date('Y-m-d H:i:s', $cert_data['validFrom_time_t']);
|
|
||||||
$cert['validtodate'] = date('Y-m-d H:i:s', $cert_data['validTo_time_t']);
|
|
||||||
$cert['isvalid'] = (bool)$cert_data['validTo_time_t'] > time();
|
$cert['isvalid'] = (bool)$cert_data['validTo_time_t'] > time();
|
||||||
$cert['issuer'] = $cert_data['issuer']['O'] ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set subject alt names from certificate
|
// Set subject alt names from certificate
|
||||||
$cert['san'] = null;
|
|
||||||
if (isset($cert_data['extensions']['subjectAltName']) && !empty($cert_data['extensions']['subjectAltName'])) {
|
if (isset($cert_data['extensions']['subjectAltName']) && !empty($cert_data['extensions']['subjectAltName'])) {
|
||||||
$SANs = explode(",", $cert_data['extensions']['subjectAltName']);
|
$SANs = explode(",", $cert_data['extensions']['subjectAltName']);
|
||||||
$SANs = array_map('trim', $SANs);
|
$SANs = array_map('trim', $SANs);
|
||||||
@@ -319,7 +324,7 @@ class Certificates extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
$result[] = $cert;
|
$result[] = $cert;
|
||||||
}
|
}
|
||||||
return $this->response([
|
return $this->response([
|
||||||
@@ -465,7 +470,7 @@ class Certificates extends ApiCommand implements ResourceEntity
|
|||||||
if ($chk['letsencrypt'] == '1') {
|
if ($chk['letsencrypt'] == '1') {
|
||||||
Cronjob::inserttask(TaskId::DELETE_DOMAIN_SSL, $chk['domain']);
|
Cronjob::inserttask(TaskId::DELETE_DOMAIN_SSL, $chk['domain']);
|
||||||
}
|
}
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] removed ssl-certificate for '" . $chk['domain'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] removed ssl-certificate for '" . $chk['domain'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
throw new Exception("Unable to determine SSL certificate. Maybe no access?", 406);
|
throw new Exception("Unable to determine SSL certificate. Maybe no access?", 406);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ use Froxlor\Cron\TaskId;
|
|||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\System\Cronjob;
|
use Froxlor\System\Cronjob;
|
||||||
|
use Froxlor\UI\Response;
|
||||||
use Froxlor\Validate\Validate;
|
use Froxlor\Validate\Validate;
|
||||||
use PDO;
|
use PDO;
|
||||||
|
|
||||||
@@ -41,6 +42,14 @@ use PDO;
|
|||||||
class Cronjobs extends ApiCommand implements ResourceEntity
|
class Cronjobs extends ApiCommand implements ResourceEntity
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private array $allowed_intervals = [
|
||||||
|
'MINUTE',
|
||||||
|
'HOUR',
|
||||||
|
'DAY',
|
||||||
|
'WEEK',
|
||||||
|
'MONTH'
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* You cannot add new cronjobs yet.
|
* You cannot add new cronjobs yet.
|
||||||
*/
|
*/
|
||||||
@@ -118,6 +127,10 @@ class Cronjobs extends ApiCommand implements ResourceEntity
|
|||||||
$interval_value = Validate::validate($interval_value, 'interval_value', '/^([0-9]+)$/Di', 'stringisempty', [], true);
|
$interval_value = Validate::validate($interval_value, 'interval_value', '/^([0-9]+)$/Di', 'stringisempty', [], true);
|
||||||
$interval_interval = Validate::validate($interval_interval, 'interval_interval', '', '', [], true);
|
$interval_interval = Validate::validate($interval_interval, 'interval_interval', '', '', [], true);
|
||||||
|
|
||||||
|
if (!in_array(strtoupper($interval_interval), $this->allowed_intervals)) {
|
||||||
|
Response::standardError('invalidcronjobintervalvalue', implode(", ", $this->allowed_intervals), true);
|
||||||
|
}
|
||||||
|
|
||||||
// put together interval value
|
// put together interval value
|
||||||
$interval = $interval_value . ' ' . strtoupper($interval_interval);
|
$interval = $interval_value . ' ' . strtoupper($interval_interval);
|
||||||
|
|
||||||
@@ -134,7 +147,7 @@ class Cronjobs extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// insert task to re-generate the cron.d-file
|
// insert task to re-generate the cron.d-file
|
||||||
Cronjob::inserttask(TaskId::REBUILD_CRON);
|
Cronjob::inserttask(TaskId::REBUILD_CRON);
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] cronjob with description '" . $result['module'] . '/' . $result['cronfile'] . "' has been updated by '" . $this->getUserDetail('loginname') . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] cronjob with description '" . $result['module'] . '/' . $result['cronfile'] . "' has been updated by '" . $this->getUserDetail('loginname') . "'");
|
||||||
$result = $this->apiCall('Cronjobs.get', [
|
$result = $this->apiCall('Cronjobs.get', [
|
||||||
'id' => $id
|
'id' => $id
|
||||||
]);
|
]);
|
||||||
@@ -164,7 +177,7 @@ class Cronjobs extends ApiCommand implements ResourceEntity
|
|||||||
public function listing()
|
public function listing()
|
||||||
{
|
{
|
||||||
if ($this->isAdmin()) {
|
if ($this->isAdmin()) {
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list cronjobs");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] list cronjobs");
|
||||||
$query_fields = [];
|
$query_fields = [];
|
||||||
$result_stmt = Database::prepare("
|
$result_stmt = Database::prepare("
|
||||||
SELECT `c`.* FROM `" . TABLE_PANEL_CRONRUNS . "` `c` " . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
|
SELECT `c`.* FROM `" . TABLE_PANEL_CRONRUNS . "` `c` " . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ class CustomerBackups extends ApiCommand implements ResourceEntity
|
|||||||
$result[] = $entry;
|
$result[] = $entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list customer-backups");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] list customer-backups");
|
||||||
return $this->response([
|
return $this->response([
|
||||||
'count' => count($result),
|
'count' => count($result),
|
||||||
'list' => $result
|
'list' => $result
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$fax = $this->getParam('fax', true, '');
|
$fax = $this->getParam('fax', true, '');
|
||||||
$customernumber = $this->getParam('customernumber', true, '');
|
$customernumber = $this->getParam('customernumber', true, '');
|
||||||
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
|
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
|
||||||
$api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled'));
|
$api_allowed = $this->getBoolParam('api_allowed', true, (Settings::Get('api.enabled') && Settings::Get('api.customer_default')));
|
||||||
$gender = (int)$this->getParam('gender', true, 0);
|
$gender = (int)$this->getParam('gender', true, 0);
|
||||||
$custom_notes = $this->getParam('custom_notes', true, '');
|
$custom_notes = $this->getParam('custom_notes', true, '');
|
||||||
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
|
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
|
||||||
@@ -895,7 +895,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$result['dbspace_used'] = 0;
|
$result['dbspace_used'] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get customer '" . $result['loginname'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get customer '" . $result['loginname'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
$key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'");
|
$key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'");
|
||||||
@@ -1327,7 +1327,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
'vu' => $valid_until
|
'vu' => $valid_until
|
||||||
], true, true);
|
], true, true);
|
||||||
|
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] " . ($deactivated ? 'deactivated' : 'reactivated') . " user '" . $result['loginname'] . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] " . ($deactivated ? 'deactivated' : 'reactivated') . " user '" . $result['loginname'] . "'");
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1538,7 +1538,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
Database::query($admin_update_query);
|
Database::query($admin_update_query);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] edited user '" . $result['loginname'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] edited user '" . $result['loginname'] . "'");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* move customer to another admin/reseller; #1166
|
* move customer to another admin/reseller; #1166
|
||||||
@@ -1911,7 +1911,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
// now, recalculate the resource-usage for the old and the new admin
|
// now, recalculate the resource-usage for the old and the new admin
|
||||||
User::updateCounters(false);
|
User::updateCounters(false);
|
||||||
|
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] moved user '" . $c_result['loginname'] . "' from admin/reseller '" . $c_result['adminname'] . " to admin/reseller '" . $a_result['loginname'] . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] moved user '" . $c_result['loginname'] . "' from admin/reseller '" . $c_result['adminname'] . " to admin/reseller '" . $a_result['loginname'] . "'");
|
||||||
|
|
||||||
$result = $this->apiCall('Customers.get', [
|
$result = $this->apiCall('Customers.get', [
|
||||||
'id' => $c_result['customerid']
|
'id' => $c_result['customerid']
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
|||||||
];
|
];
|
||||||
Database::pexecute($stmt, $params, true, true);
|
Database::pexecute($stmt, $params, true, true);
|
||||||
$id = Database::lastInsertId();
|
$id = Database::lastInsertId();
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added directory-option for '" . $userpath . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added directory-option for '" . $userpath . "'");
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
|
|
||||||
$result = $this->apiCall('DirOptions.get', [
|
$result = $this->apiCall('DirOptions.get', [
|
||||||
@@ -157,16 +157,15 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
|||||||
* this functions validates a given value as ErrorDocument
|
* this functions validates a given value as ErrorDocument
|
||||||
* refs #267
|
* refs #267
|
||||||
*
|
*
|
||||||
* @param
|
* @param string $errdoc
|
||||||
* string error-document-string
|
|
||||||
* @param bool $throw_exception
|
* @param bool $throw_exception
|
||||||
*
|
*
|
||||||
* @return string error-document-string
|
* @return string error-document-string
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private function correctErrorDocument($errdoc = null, $throw_exception = false)
|
private function correctErrorDocument(string $errdoc, $throw_exception = false)
|
||||||
{
|
{
|
||||||
if ($errdoc !== null && $errdoc != '') {
|
if (trim($errdoc) != '') {
|
||||||
// not a URL
|
// not a URL
|
||||||
if ((strtoupper(substr($errdoc, 0, 5)) != 'HTTP:' && strtoupper(substr($errdoc, 0, 6)) != 'HTTPS:') || !Validate::validateUrl($errdoc)) {
|
if ((strtoupper(substr($errdoc, 0, 5)) != 'HTTP:' && strtoupper(substr($errdoc, 0, 6)) != 'HTTPS:') || !Validate::validateUrl($errdoc)) {
|
||||||
// a file
|
// a file
|
||||||
@@ -176,14 +175,14 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
|||||||
if (!substr($errdoc, 0, 1) == '/') {
|
if (!substr($errdoc, 0, 1) == '/') {
|
||||||
$errdoc = '/' . $errdoc;
|
$errdoc = '/' . $errdoc;
|
||||||
}
|
}
|
||||||
} else {
|
} elseif (preg_match('/^"([^\r\n\t\f\0"]+)"$/', $errdoc)) {
|
||||||
// a string (check for ending ")
|
// a string (check for ending ")
|
||||||
// string won't work for lighty
|
// string won't work for lighty
|
||||||
if (Settings::Get('system.webserver') == 'lighttpd') {
|
if (Settings::Get('system.webserver') == 'lighttpd') {
|
||||||
Response::standardError('stringerrordocumentnotvalidforlighty', '', $throw_exception);
|
Response::standardError('stringerrordocumentnotvalidforlighty', '', $throw_exception);
|
||||||
} elseif (substr($errdoc, -1) != '"') {
|
|
||||||
$errdoc .= '"';
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Response::standardError('invaliderrordocumentvalue', '', $throw_exception);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Settings::Get('system.webserver') == 'lighttpd') {
|
if (Settings::Get('system.webserver') == 'lighttpd') {
|
||||||
@@ -191,7 +190,7 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $errdoc;
|
return trim($errdoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -248,7 +247,7 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
|||||||
$params['id'] = $id;
|
$params['id'] = $id;
|
||||||
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get directory options for '" . $result['path'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get directory options for '" . $result['path'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
$key = "id #" . $id;
|
$key = "id #" . $id;
|
||||||
@@ -332,7 +331,7 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
|||||||
"id" => $id
|
"id" => $id
|
||||||
];
|
];
|
||||||
Database::pexecute($stmt, $params, true, true);
|
Database::pexecute($stmt, $params, true, true);
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] edited directory options for '" . str_replace($customer['documentroot'], '/', $result['path']) . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] edited directory options for '" . str_replace($customer['documentroot'], '/', $result['path']) . "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->apiCall('DirOptions.get', [
|
$result = $this->apiCall('DirOptions.get', [
|
||||||
@@ -380,7 +379,7 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
|||||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
$result[] = $row;
|
$result[] = $row;
|
||||||
}
|
}
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list directory-options");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] list directory-options");
|
||||||
return $this->response([
|
return $this->response([
|
||||||
'count' => count($result),
|
'count' => count($result),
|
||||||
'list' => $result
|
'list' => $result
|
||||||
@@ -479,7 +478,7 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
|||||||
"customerid" => $customer_data['customerid'],
|
"customerid" => $customer_data['customerid'],
|
||||||
"id" => $id
|
"id" => $id
|
||||||
], true, true);
|
], true, true);
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted directory-option for '" . str_replace($customer_data['documentroot'], '/', $result['path']) . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] deleted directory-option for '" . str_replace($customer_data['documentroot'], '/', $result['path']) . "'");
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ class DirProtections extends ApiCommand implements ResourceEntity
|
|||||||
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path);
|
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path);
|
||||||
$username = Validate::validate($username, 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', [], true);
|
$username = Validate::validate($username, 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', [], true);
|
||||||
$authname = Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', [], true);
|
$authname = Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', [], true);
|
||||||
Validate::validate($password, 'password', '', '', [], true);
|
$password = Validate::validate($password, 'password', '', '', [], true);
|
||||||
|
$password = Crypt::validatePassword($password, true);
|
||||||
|
|
||||||
// check for duplicate usernames for the path
|
// check for duplicate usernames for the path
|
||||||
$username_path_check_stmt = Database::prepare("
|
$username_path_check_stmt = Database::prepare("
|
||||||
@@ -128,7 +129,7 @@ class DirProtections extends ApiCommand implements ResourceEntity
|
|||||||
];
|
];
|
||||||
Database::pexecute($stmt, $params, true, true);
|
Database::pexecute($stmt, $params, true, true);
|
||||||
$id = Database::lastInsertId();
|
$id = Database::lastInsertId();
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added directory-protection for '" . $username . " (" . $path . ")'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added directory-protection for '" . $username . " (" . $path . ")'");
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
|
|
||||||
$result = $this->apiCall('DirProtections.get', [
|
$result = $this->apiCall('DirProtections.get', [
|
||||||
@@ -195,7 +196,7 @@ class DirProtections extends ApiCommand implements ResourceEntity
|
|||||||
$params['idun'] = ($id <= 0 ? $username : $id);
|
$params['idun'] = ($id <= 0 ? $username : $id);
|
||||||
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get directory protection for '" . $result['path'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get directory protection for '" . $result['path'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
$key = ($id > 0 ? "id #" . $id : "username '" . $username . "'");
|
$key = ($id > 0 ? "id #" . $id : "username '" . $username . "'");
|
||||||
@@ -244,7 +245,8 @@ class DirProtections extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// validation
|
// validation
|
||||||
$authname = Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', [], true);
|
$authname = Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', [], true);
|
||||||
Validate::validate($password, 'password', '', '', [], true);
|
$password = Validate::validate($password, 'password', '', '', [], true);
|
||||||
|
$password = Crypt::validatePassword($password, true);
|
||||||
|
|
||||||
$upd_query = "";
|
$upd_query = "";
|
||||||
$upd_params = [
|
$upd_params = [
|
||||||
@@ -277,7 +279,7 @@ class DirProtections extends ApiCommand implements ResourceEntity
|
|||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated directory-protection '" . $result['username'] . " (" . $result['path'] . ")'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] updated directory-protection '" . $result['username'] . " (" . $result['path'] . ")'");
|
||||||
$result = $this->apiCall('DirProtections.get', [
|
$result = $this->apiCall('DirProtections.get', [
|
||||||
'id' => $result['id']
|
'id' => $result['id']
|
||||||
]);
|
]);
|
||||||
@@ -323,7 +325,7 @@ class DirProtections extends ApiCommand implements ResourceEntity
|
|||||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
$result[] = $row;
|
$result[] = $row;
|
||||||
}
|
}
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list directory-protections");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] list directory-protections");
|
||||||
return $this->response([
|
return $this->response([
|
||||||
'count' => count($result),
|
'count' => count($result),
|
||||||
'list' => $result
|
'list' => $result
|
||||||
@@ -411,7 +413,7 @@ class DirProtections extends ApiCommand implements ResourceEntity
|
|||||||
"id" => $id
|
"id" => $id
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted htpasswd for '" . $result['username'] . " (" . $result['path'] . ")'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted htpasswd for '" . $result['username'] . " (" . $result['path'] . ")'");
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -413,7 +413,7 @@ class DomainZones extends ApiCommand implements ResourceEntity
|
|||||||
$zone = Dns::createDomainZone($id);
|
$zone = Dns::createDomainZone($id);
|
||||||
$zonefile = (string)$zone;
|
$zonefile = (string)$zone;
|
||||||
|
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get dns-zone for '" . $result['domain'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get dns-zone for '" . $result['domain'] . "'");
|
||||||
return $this->response(explode("\n", $zonefile));
|
return $this->response(explode("\n", $zonefile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -225,6 +225,8 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
* optional, whether php is enabled for this domain, default 0 (false)
|
* optional, whether php is enabled for this domain, default 0 (false)
|
||||||
* @param bool $openbasedir
|
* @param bool $openbasedir
|
||||||
* optional, whether to activate openbasedir restriction for this domain, default 0 (false)
|
* optional, whether to activate openbasedir restriction for this domain, default 0 (false)
|
||||||
|
* @param int $openbasedir_path
|
||||||
|
* optional, either 0 for domains-docroot, 1 for customers-homedir or 2 for parent-directory of domains-docroot
|
||||||
* @param int $phpsettingid
|
* @param int $phpsettingid
|
||||||
* optional, specify php-configuration that is being used by id, default 1 (system-default)
|
* optional, specify php-configuration that is being used by id, default 1 (system-default)
|
||||||
* @param int $mod_fcgid_starter
|
* @param int $mod_fcgid_starter
|
||||||
@@ -312,6 +314,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$documentroot = $this->getParam('documentroot', true, '');
|
$documentroot = $this->getParam('documentroot', true, '');
|
||||||
$phpenabled = $this->getBoolParam('phpenabled', true, 0);
|
$phpenabled = $this->getBoolParam('phpenabled', true, 0);
|
||||||
$openbasedir = $this->getBoolParam('openbasedir', true, 0);
|
$openbasedir = $this->getBoolParam('openbasedir', true, 0);
|
||||||
|
$openbasedir_path = $this->getParam('openbasedir_path', true, 0);
|
||||||
$phpsettingid = $this->getParam('phpsettingid', true, 1);
|
$phpsettingid = $this->getParam('phpsettingid', true, 1);
|
||||||
$mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, -1);
|
$mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, -1);
|
||||||
$mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, -1);
|
$mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, -1);
|
||||||
@@ -404,20 +407,25 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$documentroot = $_documentroot;
|
$documentroot = $_documentroot;
|
||||||
}
|
}
|
||||||
|
|
||||||
$registration_date = Validate::validate($registration_date, 'registration_date', Validate::REGEX_YYYY_MM_DD, '', [
|
if (!is_null($registration_date)) {
|
||||||
|
$registration_date = Validate::validate($registration_date, 'registration_date',
|
||||||
|
Validate::REGEX_YYYY_MM_DD, '', [
|
||||||
'0000-00-00',
|
'0000-00-00',
|
||||||
'0',
|
'0',
|
||||||
''
|
''
|
||||||
], true);
|
], true);
|
||||||
|
}
|
||||||
if ($registration_date == '0000-00-00' || empty($registration_date)) {
|
if ($registration_date == '0000-00-00' || empty($registration_date)) {
|
||||||
$registration_date = null;
|
$registration_date = null;
|
||||||
}
|
}
|
||||||
|
if (!is_null($termination_date)) {
|
||||||
$termination_date = Validate::validate($termination_date, 'termination_date', Validate::REGEX_YYYY_MM_DD, '', [
|
$termination_date = Validate::validate($termination_date, 'termination_date',
|
||||||
|
Validate::REGEX_YYYY_MM_DD, '', [
|
||||||
'0000-00-00',
|
'0000-00-00',
|
||||||
'0',
|
'0',
|
||||||
''
|
''
|
||||||
], true);
|
], true);
|
||||||
|
}
|
||||||
if ($termination_date == '0000-00-00' || empty($termination_date)) {
|
if ($termination_date == '0000-00-00' || empty($termination_date)) {
|
||||||
$termination_date = null;
|
$termination_date = null;
|
||||||
}
|
}
|
||||||
@@ -525,6 +533,10 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$mod_fcgid_maxrequests = '-1';
|
$mod_fcgid_maxrequests = '-1';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($openbasedir_path > 2 && $openbasedir_path < 0) {
|
||||||
|
$openbasedir_path = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// check non-ssl IP
|
// check non-ssl IP
|
||||||
$ipandports = $this->validateIpAddresses($p_ipandports);
|
$ipandports = $this->validateIpAddresses($p_ipandports);
|
||||||
// check ssl IP
|
// check ssl IP
|
||||||
@@ -559,7 +571,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// validate dns if lets encrypt is enabled to check whether we can use it at all
|
// validate dns if lets encrypt is enabled to check whether we can use it at all
|
||||||
if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
|
if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
|
||||||
$domain_ips = PhpHelper::gethostbynamel6($domain);
|
$domain_ips = PhpHelper::gethostbynamel6($domain, true, Settings::Get('system.le_domain_dnscheck_resolver'));
|
||||||
$selected_ips = $this->getIpsFromIdArray($ssl_ipandports);
|
$selected_ips = $this->getIpsFromIdArray($ssl_ipandports);
|
||||||
if ($domain_ips == false || count(array_intersect($selected_ips, $domain_ips)) <= 0) {
|
if ($domain_ips == false || count(array_intersect($selected_ips, $domain_ips)) <= 0) {
|
||||||
Response::standardError('invaliddnsforletsencrypt', '', true);
|
Response::standardError('invaliddnsforletsencrypt', '', true);
|
||||||
@@ -696,6 +708,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
'caneditdomain' => $caneditdomain,
|
'caneditdomain' => $caneditdomain,
|
||||||
'phpenabled' => $phpenabled,
|
'phpenabled' => $phpenabled,
|
||||||
'openbasedir' => $openbasedir,
|
'openbasedir' => $openbasedir,
|
||||||
|
'openbasedir_path' => $openbasedir_path,
|
||||||
'speciallogfile' => $speciallogfile,
|
'speciallogfile' => $speciallogfile,
|
||||||
'specialsettings' => $specialsettings,
|
'specialsettings' => $specialsettings,
|
||||||
'ssl_specialsettings' => $ssl_specialsettings,
|
'ssl_specialsettings' => $ssl_specialsettings,
|
||||||
@@ -749,6 +762,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
`caneditdomain` = :caneditdomain,
|
`caneditdomain` = :caneditdomain,
|
||||||
`phpenabled` = :phpenabled,
|
`phpenabled` = :phpenabled,
|
||||||
`openbasedir` = :openbasedir,
|
`openbasedir` = :openbasedir,
|
||||||
|
`openbasedir_path` = :openbasedir_path,
|
||||||
`speciallogfile` = :speciallogfile,
|
`speciallogfile` = :speciallogfile,
|
||||||
`specialsettings` = :specialsettings,
|
`specialsettings` = :specialsettings,
|
||||||
`ssl_specialsettings` = :ssl_specialsettings,
|
`ssl_specialsettings` = :ssl_specialsettings,
|
||||||
@@ -884,7 +898,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$result['ipsandports'] = $this->getIpsForDomain($result['id']);
|
$result['ipsandports'] = $this->getIpsForDomain($result['id']);
|
||||||
}
|
}
|
||||||
$result['domain_hascert'] = $this->getHasCertValueForDomain((int)$result['id'], (int)$result['parentdomainid']);
|
$result['domain_hascert'] = $this->getHasCertValueForDomain((int)$result['id'], (int)$result['parentdomainid']);
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get domain '" . $result['domain'] . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] get domain '" . $result['domain'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
$key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'");
|
$key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'");
|
||||||
@@ -1096,6 +1110,8 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
* from setting system.apply_phpconfigs_default
|
* from setting system.apply_phpconfigs_default
|
||||||
* @param bool $openbasedir
|
* @param bool $openbasedir
|
||||||
* optional, whether to activate openbasedir restriction for this domain, default 0 (false)
|
* optional, whether to activate openbasedir restriction for this domain, default 0 (false)
|
||||||
|
* @param int $openbasedir_path
|
||||||
|
* optional, either 0 for domains-docroot, 1 for customers-homedir or 2 for parent-directory of domains-docroot
|
||||||
* @param int $phpsettingid
|
* @param int $phpsettingid
|
||||||
* optional, specify php-configuration that is being used by id, default 1 (system-default)
|
* optional, specify php-configuration that is being used by id, default 1 (system-default)
|
||||||
* @param int $mod_fcgid_starter
|
* @param int $mod_fcgid_starter
|
||||||
@@ -1193,6 +1209,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$phpenabled = $this->getBoolParam('phpenabled', true, $result['phpenabled']);
|
$phpenabled = $this->getBoolParam('phpenabled', true, $result['phpenabled']);
|
||||||
$phpfs = $this->getBoolParam('phpsettingsforsubdomains', true, Settings::Get('system.apply_phpconfigs_default'));
|
$phpfs = $this->getBoolParam('phpsettingsforsubdomains', true, Settings::Get('system.apply_phpconfigs_default'));
|
||||||
$openbasedir = $this->getBoolParam('openbasedir', true, $result['openbasedir']);
|
$openbasedir = $this->getBoolParam('openbasedir', true, $result['openbasedir']);
|
||||||
|
$openbasedir_path = $this->getParam('openbasedir_path', true, $result['openbasedir_path']);
|
||||||
$phpsettingid = $this->getParam('phpsettingid', true, $result['phpsettingid']);
|
$phpsettingid = $this->getParam('phpsettingid', true, $result['phpsettingid']);
|
||||||
$mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, $result['mod_fcgid_starter']);
|
$mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, $result['mod_fcgid_starter']);
|
||||||
$mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, $result['mod_fcgid_maxrequests']);
|
$mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, $result['mod_fcgid_maxrequests']);
|
||||||
@@ -1322,19 +1339,25 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$adminid = $result['adminid'];
|
$adminid = $result['adminid'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$registration_date = Validate::validate($registration_date, 'registration_date', Validate::REGEX_YYYY_MM_DD, '', [
|
if (!is_null($registration_date)) {
|
||||||
|
$registration_date = Validate::validate($registration_date, 'registration_date',
|
||||||
|
Validate::REGEX_YYYY_MM_DD, '', [
|
||||||
'0000-00-00',
|
'0000-00-00',
|
||||||
'0',
|
'0',
|
||||||
''
|
''
|
||||||
], true);
|
], true);
|
||||||
|
}
|
||||||
if ($registration_date == '0000-00-00' || empty($registration_date)) {
|
if ($registration_date == '0000-00-00' || empty($registration_date)) {
|
||||||
$registration_date = null;
|
$registration_date = null;
|
||||||
}
|
}
|
||||||
$termination_date = Validate::validate($termination_date, 'termination_date', Validate::REGEX_YYYY_MM_DD, '', [
|
if (!is_null($termination_date)) {
|
||||||
|
$termination_date = Validate::validate($termination_date, 'termination_date',
|
||||||
|
Validate::REGEX_YYYY_MM_DD, '', [
|
||||||
'0000-00-00',
|
'0000-00-00',
|
||||||
'0',
|
'0',
|
||||||
''
|
''
|
||||||
], true);
|
], true);
|
||||||
|
}
|
||||||
if ($termination_date == '0000-00-00' || empty($termination_date)) {
|
if ($termination_date == '0000-00-00' || empty($termination_date)) {
|
||||||
$termination_date = null;
|
$termination_date = null;
|
||||||
}
|
}
|
||||||
@@ -1478,6 +1501,11 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$mod_fcgid_maxrequests = $result['mod_fcgid_maxrequests'];
|
$mod_fcgid_maxrequests = $result['mod_fcgid_maxrequests'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check changes of openbasedir-path variable
|
||||||
|
if ($openbasedir_path > 2 && $openbasedir_path < 0) {
|
||||||
|
$openbasedir_path = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// check non-ssl IP
|
// check non-ssl IP
|
||||||
$ipandports = $this->validateIpAddresses($p_ipandports, false, $result['id']);
|
$ipandports = $this->validateIpAddresses($p_ipandports, false, $result['id']);
|
||||||
// check ssl IP
|
// check ssl IP
|
||||||
@@ -1523,7 +1551,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// validate dns if lets encrypt is enabled to check whether we can use it at all
|
// validate dns if lets encrypt is enabled to check whether we can use it at all
|
||||||
if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
|
if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
|
||||||
$domain_ips = PhpHelper::gethostbynamel6($result['domain']);
|
$domain_ips = PhpHelper::gethostbynamel6($result['domain'], true, Settings::Get('system.le_domain_dnscheck_resolver'));
|
||||||
$selected_ips = $this->getIpsFromIdArray($ssl_ipandports);
|
$selected_ips = $this->getIpsFromIdArray($ssl_ipandports);
|
||||||
if ($domain_ips == false || count(array_intersect($selected_ips, $domain_ips)) <= 0) {
|
if ($domain_ips == false || count(array_intersect($selected_ips, $domain_ips)) <= 0) {
|
||||||
Response::standardError('invaliddnsforletsencrypt', '', true);
|
Response::standardError('invaliddnsforletsencrypt', '', true);
|
||||||
@@ -1623,7 +1651,31 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$wwwserveralias = ($serveraliasoption == '1') ? '1' : '0';
|
$wwwserveralias = ($serveraliasoption == '1') ? '1' : '0';
|
||||||
$iswildcarddomain = ($serveraliasoption == '0') ? '1' : '0';
|
$iswildcarddomain = ($serveraliasoption == '0') ? '1' : '0';
|
||||||
|
|
||||||
if ($documentroot != $result['documentroot'] || $ssl_redirect != $result['ssl_redirect'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $phpenabled != $result['phpenabled'] || $openbasedir != $result['openbasedir'] || $phpsettingid != $result['phpsettingid'] || $mod_fcgid_starter != $result['mod_fcgid_starter'] || $mod_fcgid_maxrequests != $result['mod_fcgid_maxrequests'] || $specialsettings != $result['specialsettings'] || $ssl_specialsettings != $result['ssl_specialsettings'] || $notryfiles != $result['notryfiles'] || $writeaccesslog != $result['writeaccesslog'] || $writeerrorlog != $result['writeerrorlog'] || $aliasdomain != $result['aliasdomain'] || $issubof != $result['ismainbutsubto'] || $email_only != $result['email_only'] || ($speciallogfile != $result['speciallogfile'] && $speciallogverified == '1') || $letsencrypt != $result['letsencrypt'] || $http2 != $result['http2'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload'] || $ocsp_stapling != $result['ocsp_stapling']) {
|
if ($documentroot != $result['documentroot']
|
||||||
|
|| $ssl_redirect != $result['ssl_redirect']
|
||||||
|
|| $wwwserveralias != $result['wwwserveralias']
|
||||||
|
|| $iswildcarddomain != $result['iswildcarddomain']
|
||||||
|
|| $phpenabled != $result['phpenabled']
|
||||||
|
|| $openbasedir != $result['openbasedir']
|
||||||
|
|| $phpsettingid != $result['phpsettingid']
|
||||||
|
|| $mod_fcgid_starter != $result['mod_fcgid_starter']
|
||||||
|
|| $mod_fcgid_maxrequests != $result['mod_fcgid_maxrequests']
|
||||||
|
|| $specialsettings != $result['specialsettings']
|
||||||
|
|| $ssl_specialsettings != $result['ssl_specialsettings']
|
||||||
|
|| $notryfiles != $result['notryfiles']
|
||||||
|
|| $writeaccesslog != $result['writeaccesslog']
|
||||||
|
|| $writeerrorlog != $result['writeerrorlog']
|
||||||
|
|| $aliasdomain != $result['aliasdomain']
|
||||||
|
|| $issubof != $result['ismainbutsubto']
|
||||||
|
|| $email_only != $result['email_only']
|
||||||
|
|| ($speciallogfile != $result['speciallogfile'] && $speciallogverified == '1')
|
||||||
|
|| $letsencrypt != $result['letsencrypt']
|
||||||
|
|| $http2 != $result['http2']
|
||||||
|
|| $hsts_maxage != $result['hsts']
|
||||||
|
|| $hsts_sub != $result['hsts_sub']
|
||||||
|
|| $hsts_preload != $result['hsts_preload']
|
||||||
|
|| $ocsp_stapling != $result['ocsp_stapling']
|
||||||
|
) {
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1749,7 +1801,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
Database::pexecute($upd_stmt, [
|
Database::pexecute($upd_stmt, [
|
||||||
'id' => $id
|
'id' => $id
|
||||||
], true, true);
|
], true, true);
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] removed specialsettings on all subdomains of domain #" . $id);
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] removed specialsettings on all subdomains of domain #" . $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
$wwwserveralias = ($serveraliasoption == '1') ? '1' : '0';
|
$wwwserveralias = ($serveraliasoption == '1') ? '1' : '0';
|
||||||
@@ -1771,7 +1823,8 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$update_data['wwwserveralias'] = $wwwserveralias;
|
$update_data['wwwserveralias'] = $wwwserveralias;
|
||||||
$update_data['iswildcarddomain'] = $iswildcarddomain;
|
$update_data['iswildcarddomain'] = $iswildcarddomain;
|
||||||
$update_data['phpenabled'] = $phpenabled;
|
$update_data['phpenabled'] = $phpenabled;
|
||||||
$update_data['openbasedir'] = $openbasedir;
|
$update_data['openbasedir'] = $openbasedir;;
|
||||||
|
$update_data['openbasedir_path'] = $openbasedir_path;
|
||||||
$update_data['speciallogfile'] = $speciallogfile;
|
$update_data['speciallogfile'] = $speciallogfile;
|
||||||
$update_data['phpsettingid'] = $phpsettingid;
|
$update_data['phpsettingid'] = $phpsettingid;
|
||||||
$update_data['mod_fcgid_starter'] = $mod_fcgid_starter;
|
$update_data['mod_fcgid_starter'] = $mod_fcgid_starter;
|
||||||
@@ -1819,6 +1872,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
`iswildcarddomain` = :iswildcarddomain,
|
`iswildcarddomain` = :iswildcarddomain,
|
||||||
`phpenabled` = :phpenabled,
|
`phpenabled` = :phpenabled,
|
||||||
`openbasedir` = :openbasedir,
|
`openbasedir` = :openbasedir,
|
||||||
|
`openbasedir_path` = :openbasedir_path,
|
||||||
`speciallogfile` = :speciallogfile,
|
`speciallogfile` = :speciallogfile,
|
||||||
`phpsettingid` = :phpsettingid,
|
`phpsettingid` = :phpsettingid,
|
||||||
`mod_fcgid_starter` = :mod_fcgid_starter,
|
`mod_fcgid_starter` = :mod_fcgid_starter,
|
||||||
@@ -1854,6 +1908,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$_update_data['adminid'] = $adminid;
|
$_update_data['adminid'] = $adminid;
|
||||||
$_update_data['phpenabled'] = $phpenabled;
|
$_update_data['phpenabled'] = $phpenabled;
|
||||||
$_update_data['openbasedir'] = $openbasedir;
|
$_update_data['openbasedir'] = $openbasedir;
|
||||||
|
$_update_data['openbasedir_path'] = $openbasedir_path;
|
||||||
$_update_data['mod_fcgid_starter'] = $mod_fcgid_starter;
|
$_update_data['mod_fcgid_starter'] = $mod_fcgid_starter;
|
||||||
$_update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests;
|
$_update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests;
|
||||||
$_update_data['notryfiles'] = $notryfiles;
|
$_update_data['notryfiles'] = $notryfiles;
|
||||||
@@ -1887,6 +1942,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
`adminid` = :adminid,
|
`adminid` = :adminid,
|
||||||
`phpenabled` = :phpenabled,
|
`phpenabled` = :phpenabled,
|
||||||
`openbasedir` = :openbasedir,
|
`openbasedir` = :openbasedir,
|
||||||
|
`openbasedir_path` = :openbasedir_path,
|
||||||
`mod_fcgid_starter` = :mod_fcgid_starter,
|
`mod_fcgid_starter` = :mod_fcgid_starter,
|
||||||
`mod_fcgid_maxrequests` = :mod_fcgid_maxrequests,
|
`mod_fcgid_maxrequests` = :mod_fcgid_maxrequests,
|
||||||
`notryfiles` = :notryfiles,
|
`notryfiles` = :notryfiles,
|
||||||
@@ -1903,6 +1959,18 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
");
|
");
|
||||||
Database::pexecute($_update_stmt, $_update_data, true, true);
|
Database::pexecute($_update_stmt, $_update_data, true, true);
|
||||||
|
|
||||||
|
// get current ip<>domain entries
|
||||||
|
$ip_sel_stmt = Database::prepare("
|
||||||
|
SELECT id_ipandports FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id
|
||||||
|
");
|
||||||
|
Database::pexecute($ip_sel_stmt, [
|
||||||
|
'id' => $id
|
||||||
|
], true, true);
|
||||||
|
$current_ips = [];
|
||||||
|
while ($cIP = $ip_sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||||
|
$current_ips[] = $cIP['id_ipandports'];
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup domain <-> ip mapping
|
// Cleanup domain <-> ip mapping
|
||||||
$del_stmt = Database::prepare("
|
$del_stmt = Database::prepare("
|
||||||
DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id
|
DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id
|
||||||
@@ -1930,6 +1998,12 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check ip changes
|
||||||
|
$all_new_ips = array_merge($ipandports, $ssl_ipandports);
|
||||||
|
if (count(array_diff($current_ips, $all_new_ips)) != 0 || count(array_diff($all_new_ips, $current_ips)) != 0) {
|
||||||
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup domain <-> ip mapping for subdomains
|
// Cleanup domain <-> ip mapping for subdomains
|
||||||
$domainidsresult_stmt = Database::prepare("
|
$domainidsresult_stmt = Database::prepare("
|
||||||
SELECT `id` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `parentdomainid` = :id
|
SELECT `id` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `parentdomainid` = :id
|
||||||
@@ -1974,12 +2048,11 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
if ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) {
|
if ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) {
|
||||||
// or when wwwserveralias or letsencrypt was changed
|
// or when wwwserveralias or letsencrypt was changed
|
||||||
Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
|
|
||||||
if ((int)$aliasdomain === 0) {
|
if ((int)$aliasdomain === 0) {
|
||||||
// in case the wwwserveralias is set on a main domain, $aliasdomain is 0
|
// in case the wwwserveralias is set on a main domain, $aliasdomain is 0
|
||||||
// --> the call just above to triggerLetsEncryptCSRForAliasDestinationDomain
|
|
||||||
// is a noop...let's repeat it with the domain id of the main domain
|
|
||||||
Domain::triggerLetsEncryptCSRForAliasDestinationDomain($id, $this->logger());
|
Domain::triggerLetsEncryptCSRForAliasDestinationDomain($id, $this->logger());
|
||||||
|
} else {
|
||||||
|
Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2138,7 +2211,9 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
'domainid' => $id
|
'domainid' => $id
|
||||||
], true, true);
|
], true, true);
|
||||||
|
|
||||||
|
if ((int)$result['aliasdomain'] !== 0) {
|
||||||
Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger());
|
Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger());
|
||||||
|
}
|
||||||
|
|
||||||
// remove domains DNS from powerDNS if used, #581
|
// remove domains DNS from powerDNS if used, #581
|
||||||
Cronjob::inserttask(TaskId::DELETE_DOMAIN_PDNS, $result['domain']);
|
Cronjob::inserttask(TaskId::DELETE_DOMAIN_PDNS, $result['domain']);
|
||||||
@@ -2146,7 +2221,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
// remove domain from acme.sh / lets encrypt if used
|
// remove domain from acme.sh / lets encrypt if used
|
||||||
Cronjob::inserttask(TaskId::DELETE_DOMAIN_SSL, $result['domain']);
|
Cronjob::inserttask(TaskId::DELETE_DOMAIN_SSL, $result['domain']);
|
||||||
|
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] deleted domain/subdomains (#" . $result['id'] . ")");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted domain/subdomains (#" . $result['id'] . ")");
|
||||||
User::updateCounters();
|
User::updateCounters();
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
// Using nameserver, insert a task which rebuilds the server config
|
// Using nameserver, insert a task which rebuilds the server config
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
|||||||
* @param string $alternative_email
|
* @param string $alternative_email
|
||||||
* optional email address to send account information to, default is the account that is being created
|
* optional email address to send account information to, default is the account that is being created
|
||||||
* @param int $email_quota
|
* @param int $email_quota
|
||||||
* optional quota if enabled in MB, default 0
|
* optional quota if enabled in MB, default setting: system.mail_quota
|
||||||
* @param bool $sendinfomail
|
* @param bool $sendinfomail
|
||||||
* optional, sends the welcome message to the new account (needed for creation, without the user won't
|
* optional, sends the welcome message to the new account (needed for creation, without the user won't
|
||||||
* be able to login before any mail is received), default 1 (true)
|
* be able to login before any mail is received), default 1 (true)
|
||||||
@@ -85,7 +85,7 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
|||||||
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
|
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
|
||||||
$email_password = $this->getParam('email_password');
|
$email_password = $this->getParam('email_password');
|
||||||
$alternative_email = $this->getParam('alternative_email', true, '');
|
$alternative_email = $this->getParam('alternative_email', true, '');
|
||||||
$quota = $this->getParam('email_quota', true, 0);
|
$quota = $this->getParam('email_quota', true, Settings::Get('system.mail_quota') ?? 0);
|
||||||
$sendinfomail = $this->getBoolParam('sendinfomail', true, 1);
|
$sendinfomail = $this->getBoolParam('sendinfomail', true, 1);
|
||||||
|
|
||||||
// validation
|
// validation
|
||||||
@@ -99,6 +99,11 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
|||||||
Response::standardError('notallowedtouseaccounts', '', true);
|
Response::standardError('notallowedtouseaccounts', '', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($emailaddr)) {
|
||||||
|
$idna_convert = new IdnaWrapper();
|
||||||
|
$emailaddr = $idna_convert->encode($emailaddr);
|
||||||
|
}
|
||||||
|
|
||||||
// get email address
|
// get email address
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
@@ -306,7 +311,7 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added email account for '" . $result['email_full'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added email account for '" . $result['email_full'] . "'");
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
'emailaddr' => $result['email_full']
|
'emailaddr' => $result['email_full']
|
||||||
]);
|
]);
|
||||||
@@ -357,6 +362,11 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
|||||||
$ea_optional = $id > 0;
|
$ea_optional = $id > 0;
|
||||||
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
|
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
|
||||||
|
|
||||||
|
if (!empty($emailaddr)) {
|
||||||
|
$idna_convert = new IdnaWrapper();
|
||||||
|
$emailaddr = $idna_convert->encode($emailaddr);
|
||||||
|
}
|
||||||
|
|
||||||
// validation
|
// validation
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
@@ -450,7 +460,7 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
|||||||
Admins::increaseUsage($customer['adminid'], 'email_quota_used', '', ($quota - $result['quota']));
|
Admins::increaseUsage($customer['adminid'], 'email_quota_used', '', ($quota - $result['quota']));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated email account '" . $result['email_full'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] updated email account '" . $result['email_full'] . "'");
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
'emailaddr' => $result['email_full']
|
'emailaddr' => $result['email_full']
|
||||||
]);
|
]);
|
||||||
@@ -556,7 +566,7 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
|||||||
Customers::decreaseUsage($customer['customerid'], 'email_accounts_used');
|
Customers::decreaseUsage($customer['customerid'], 'email_accounts_used');
|
||||||
Customers::decreaseUsage($customer['customerid'], 'email_quota_used', '', $quota);
|
Customers::decreaseUsage($customer['customerid'], 'email_quota_used', '', $quota);
|
||||||
|
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email account for '" . $result['email_full'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted email account for '" . $result['email_full'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
188
lib/Froxlor/Api/Commands/EmailDomains.php
Normal file
188
lib/Froxlor/Api/Commands/EmailDomains.php
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file is part of the Froxlor project.
|
||||||
|
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you can also view it online at
|
||||||
|
* https://files.froxlor.org/misc/COPYING.txt
|
||||||
|
*
|
||||||
|
* @copyright the authors
|
||||||
|
* @author Froxlor team <team@froxlor.org>
|
||||||
|
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Froxlor\Api\Commands;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Froxlor\Api\ApiCommand;
|
||||||
|
use Froxlor\Api\ResourceEntity;
|
||||||
|
use Froxlor\Database\Database;
|
||||||
|
use Froxlor\FroxlorLogger;
|
||||||
|
use Froxlor\Settings;
|
||||||
|
use PDO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.0
|
||||||
|
*/
|
||||||
|
class EmailDomains extends ApiCommand implements ResourceEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* list all domains with email addresses connected to it.
|
||||||
|
* If called from an admin, list all domains with email addresses
|
||||||
|
* connected to it from all customers you are allowed to view, or
|
||||||
|
* specify id or loginname for one specific customer
|
||||||
|
*
|
||||||
|
* @param int $customerid
|
||||||
|
* optional, admin-only, select email addresses of a specific customer by id
|
||||||
|
* @param string $loginname
|
||||||
|
* optional, admin-only, select email addresses of a specific customer by loginname
|
||||||
|
* @param array $sql_search
|
||||||
|
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =),
|
||||||
|
* LIKE is used if left empty and 'value' => searchvalue
|
||||||
|
* @param int $sql_limit
|
||||||
|
* optional specify number of results to be returned
|
||||||
|
* @param int $sql_offset
|
||||||
|
* optional specify offset for resultset
|
||||||
|
* @param array $sql_orderby
|
||||||
|
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more
|
||||||
|
* fields
|
||||||
|
*
|
||||||
|
* @access admin, customer
|
||||||
|
* @return string json-encoded array count|list
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function listing()
|
||||||
|
{
|
||||||
|
$customer_ids = $this->getAllowedCustomerIds('email');
|
||||||
|
$result = [];
|
||||||
|
$query_fields = [];
|
||||||
|
$result_stmt = Database::prepare("
|
||||||
|
SELECT DISTINCT d.domain, e.domainid,
|
||||||
|
COUNT(e.email) as addresses,
|
||||||
|
IFNULL(SUM(CASE WHEN e.popaccountid > 0 THEN 1 ELSE 0 END), 0) as accounts,
|
||||||
|
IFNULL(SUM(
|
||||||
|
CASE
|
||||||
|
WHEN LENGTH(REPLACE(e.destination, CONCAT(e.email_full, ' '), '')) - LENGTH(REPLACE(REPLACE(e.destination, CONCAT(e.email_full, ' '), ''), ' ', '')) > 0
|
||||||
|
THEN LENGTH(REPLACE(e.destination, CONCAT(e.email_full, ' '), '')) - LENGTH(REPLACE(REPLACE(e.destination, CONCAT(e.email_full, ' '), ''), ' ', ''))
|
||||||
|
WHEN e.destination <> e.email_full THEN 1
|
||||||
|
ELSE 0
|
||||||
|
END
|
||||||
|
), 0) as forwarder
|
||||||
|
FROM `" . TABLE_MAIL_VIRTUAL . "` e
|
||||||
|
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON d.id = e.domainid
|
||||||
|
WHERE e.customerid IN (" . implode(", ", $customer_ids) . ") AND d.domain IS NOT NULL " .
|
||||||
|
$this->getSearchWhere($query_fields,
|
||||||
|
true) . " GROUP BY e.domainid " . $this->getOrderBy() . $this->getLimit());
|
||||||
|
Database::pexecute($result_stmt, $query_fields, true, true);
|
||||||
|
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
$result[] = $row;
|
||||||
|
}
|
||||||
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO,
|
||||||
|
"[API] list email-domains");
|
||||||
|
return $this->response([
|
||||||
|
'count' => count($result),
|
||||||
|
'list' => $result
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the total number of accessible domains with email addresses connected to
|
||||||
|
*
|
||||||
|
* @param int $customerid
|
||||||
|
* optional, admin-only, select email addresses of a specific customer by id
|
||||||
|
* @param string $loginname
|
||||||
|
* optional, admin-only, select email addresses of a specific customer by loginname
|
||||||
|
*
|
||||||
|
* @access admin, customer
|
||||||
|
* @return string json-encoded response message
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function listingCount()
|
||||||
|
{
|
||||||
|
$customer_ids = $this->getAllowedCustomerIds('email');
|
||||||
|
$result_stmt = Database::prepare("
|
||||||
|
SELECT COUNT(DISTINCT d.domain) as num_emaildomains
|
||||||
|
FROM `" . TABLE_MAIL_VIRTUAL . "` e
|
||||||
|
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON d.id = e.domainid
|
||||||
|
WHERE e.customerid IN (" . implode(", ", $customer_ids) . ") AND d.domain IS NOT NULL
|
||||||
|
");
|
||||||
|
$result = Database::pexecute_first($result_stmt, null, true, true);
|
||||||
|
if ($result) {
|
||||||
|
return $this->response($result['num_emaildomains']);
|
||||||
|
}
|
||||||
|
return $this->response(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You cannot directly access email-domains
|
||||||
|
*
|
||||||
|
* @access admin, customer
|
||||||
|
* @return string json-encoded array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function get()
|
||||||
|
{
|
||||||
|
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
|
||||||
|
throw new Exception("You cannot access this resource", 405);
|
||||||
|
}
|
||||||
|
throw new Exception('You cannot directly access this resource.', 303);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You cannot directly add email-domains
|
||||||
|
*
|
||||||
|
* @access admin, customer
|
||||||
|
* @return string json-encoded array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
|
||||||
|
throw new Exception("You cannot access this resource", 405);
|
||||||
|
}
|
||||||
|
throw new Exception('You cannot directly add this resource.', 303);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* toggle catchall flag of given email address either by id or email-address
|
||||||
|
*
|
||||||
|
* @access admin, customer
|
||||||
|
* @return string json-encoded array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function update()
|
||||||
|
{
|
||||||
|
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
|
||||||
|
throw new Exception("You cannot access this resource", 405);
|
||||||
|
}
|
||||||
|
throw new Exception('You cannot directly update this resource.', 303);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You cannot directly delete email-domains
|
||||||
|
*
|
||||||
|
* @access admin, customer
|
||||||
|
* @return string json-encoded array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function delete()
|
||||||
|
{
|
||||||
|
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
|
||||||
|
throw new Exception("You cannot access this resource", 405);
|
||||||
|
}
|
||||||
|
throw new Exception('You cannot directly delete this resource.', 303);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -77,6 +77,11 @@ class EmailForwarders extends ApiCommand implements ResourceEntity
|
|||||||
$idna_convert = new IdnaWrapper();
|
$idna_convert = new IdnaWrapper();
|
||||||
$destination = $idna_convert->encode($destination);
|
$destination = $idna_convert->encode($destination);
|
||||||
|
|
||||||
|
if (!empty($emailaddr)) {
|
||||||
|
$idna_convert = new IdnaWrapper();
|
||||||
|
$emailaddr = $idna_convert->encode($emailaddr);
|
||||||
|
}
|
||||||
|
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'emailaddr' => $emailaddr
|
'emailaddr' => $emailaddr
|
||||||
@@ -116,7 +121,7 @@ class EmailForwarders extends ApiCommand implements ResourceEntity
|
|||||||
// update customer usage
|
// update customer usage
|
||||||
Customers::increaseUsage($customer['customerid'], 'email_forwarders_used');
|
Customers::increaseUsage($customer['customerid'], 'email_forwarders_used');
|
||||||
|
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added email forwarder for '" . $result['email_full'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added email forwarder for '" . $result['email_full'] . "'");
|
||||||
|
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
'emailaddr' => $result['email_full']
|
'emailaddr' => $result['email_full']
|
||||||
@@ -293,7 +298,7 @@ class EmailForwarders extends ApiCommand implements ResourceEntity
|
|||||||
// update customer usage
|
// update customer usage
|
||||||
Customers::decreaseUsage($customer['customerid'], 'email_forwarders_used');
|
Customers::decreaseUsage($customer['customerid'], 'email_forwarders_used');
|
||||||
|
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email forwarder for '" . $result['email_full'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] deleted email forwarder for '" . $result['email_full'] . "'");
|
||||||
|
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
'emailaddr' => $result['email_full']
|
'emailaddr' => $result['email_full']
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
// update customer usage
|
// update customer usage
|
||||||
Customers::increaseUsage($customer['customerid'], 'emails_used');
|
Customers::increaseUsage($customer['customerid'], 'emails_used');
|
||||||
|
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added email address '" . $email_full . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added email address '" . $email_full . "'");
|
||||||
|
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
'emailaddr' => $email_full
|
'emailaddr' => $email_full
|
||||||
@@ -195,11 +195,11 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
FROM `" . TABLE_MAIL_VIRTUAL . "` v
|
FROM `" . TABLE_MAIL_VIRTUAL . "` v
|
||||||
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON v.`popaccountid` = u.`id`
|
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON v.`popaccountid` = u.`id`
|
||||||
WHERE v.`customerid` IN (" . implode(", ", $customer_ids) . ")
|
WHERE v.`customerid` IN (" . implode(", ", $customer_ids) . ")
|
||||||
AND (v.`id`= :idea OR (v.`email` = :idea OR v.`email_full` = :idea))
|
AND " . (is_numeric($params['idea']) ? "v.`id`= :idea" : "(v.`email` = :idea OR v.`email_full` = :idea)")
|
||||||
");
|
);
|
||||||
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get email address '" . $result['email_full'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get email address '" . $result['email_full'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
$key = ($id > 0 ? "id #" . $id : "emailaddr '" . $emailaddr . "'");
|
$key = ($id > 0 ? "id #" . $id : "emailaddr '" . $emailaddr . "'");
|
||||||
@@ -294,7 +294,7 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
"id" => $id
|
"id" => $id
|
||||||
];
|
];
|
||||||
Database::pexecute($stmt, $params, true, true);
|
Database::pexecute($stmt, $params, true, true);
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] toggled catchall-flag for email address '" . $result['email_full'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] toggled catchall-flag for email address '" . $result['email_full'] . "'");
|
||||||
|
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
'emailaddr' => $result['email_full']
|
'emailaddr' => $result['email_full']
|
||||||
@@ -340,7 +340,7 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
$result[] = $row;
|
$result[] = $row;
|
||||||
}
|
}
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list email-addresses");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] list email-addresses");
|
||||||
return $this->response([
|
return $this->response([
|
||||||
'count' => count($result),
|
'count' => count($result),
|
||||||
'list' => $result
|
'list' => $result
|
||||||
@@ -445,7 +445,7 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
], true, true);
|
], true, true);
|
||||||
Customers::decreaseUsage($customer['customerid'], 'emails_used');
|
Customers::decreaseUsage($customer['customerid'], 'emails_used');
|
||||||
|
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email address '" . $result['email_full'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted email address '" . $result['email_full'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class FpmDaemons extends ApiCommand implements ResourceEntity
|
|||||||
public function listing()
|
public function listing()
|
||||||
{
|
{
|
||||||
if ($this->isAdmin()) {
|
if ($this->isAdmin()) {
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list fpm-daemons");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] list fpm-daemons");
|
||||||
$query_fields = [];
|
$query_fields = [];
|
||||||
$result_stmt = Database::prepare("
|
$result_stmt = Database::prepare("
|
||||||
SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "`" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
|
SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "`" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
|
||||||
@@ -258,7 +258,7 @@ class FpmDaemons extends ApiCommand implements ResourceEntity
|
|||||||
$id = Database::lastInsertId();
|
$id = Database::lastInsertId();
|
||||||
|
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon with description '" . $description . "' has been created by '" . $this->getUserDetail('loginname') . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] fpm-daemon with description '" . $description . "' has been created by '" . $this->getUserDetail('loginname') . "'");
|
||||||
$result = $this->apiCall('FpmDaemons.get', [
|
$result = $this->apiCall('FpmDaemons.get', [
|
||||||
'id' => $id
|
'id' => $id
|
||||||
]);
|
]);
|
||||||
@@ -384,7 +384,7 @@ class FpmDaemons extends ApiCommand implements ResourceEntity
|
|||||||
Database::pexecute($upd_stmt, $upd_data, true, true);
|
Database::pexecute($upd_stmt, $upd_data, true, true);
|
||||||
|
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon with description '" . $description . "' has been updated by '" . $this->getUserDetail('loginname') . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] fpm-daemon with description '" . $description . "' has been updated by '" . $this->getUserDetail('loginname') . "'");
|
||||||
$result = $this->apiCall('FpmDaemons.get', [
|
$result = $this->apiCall('FpmDaemons.get', [
|
||||||
'id' => $id
|
'id' => $id
|
||||||
]);
|
]);
|
||||||
@@ -433,7 +433,7 @@ class FpmDaemons extends ApiCommand implements ResourceEntity
|
|||||||
], true, true);
|
], true, true);
|
||||||
|
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] fpm-daemon setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
throw new Exception("Not allowed to execute given command.", 403);
|
throw new Exception("Not allowed to execute given command.", 403);
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class Froxlor extends ApiCommand
|
|||||||
|
|
||||||
if (empty($uc_data) || empty($response) || $uc_data['ts'] + self::UPDATE_CHECK_INTERVAL < time() || $uc_data['channel'] != Settings::Get('system.update_channel') || $force_ucheck) {
|
if (empty($uc_data) || empty($response) || $uc_data['ts'] + self::UPDATE_CHECK_INTERVAL < time() || $uc_data['channel'] != Settings::Get('system.update_channel') || $force_ucheck) {
|
||||||
// log our actions
|
// log our actions
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] checking for updates");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] checking for updates");
|
||||||
|
|
||||||
// check for new version
|
// check for new version
|
||||||
$aucheck = AutoUpdate::checkVersion();
|
$aucheck = AutoUpdate::checkVersion();
|
||||||
@@ -142,7 +142,7 @@ class Froxlor extends ApiCommand
|
|||||||
{
|
{
|
||||||
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
|
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
|
||||||
$json_str = $this->getParam('json_str');
|
$json_str = $this->getParam('json_str');
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "User " . $this->getUserDetail('loginname') . " imported settings");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "User " . $this->getUserDetail('loginname') . " imported settings");
|
||||||
try {
|
try {
|
||||||
SImExporter::import($json_str);
|
SImExporter::import($json_str);
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ class Ftps extends ApiCommand implements ResourceEntity
|
|||||||
Customers::increaseUsage($customer['customerid'], 'ftp_lastaccountnumber');
|
Customers::increaseUsage($customer['customerid'], 'ftp_lastaccountnumber');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added ftp-account '" . $username . " (" . $path . ")'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added ftp-account '" . $username . " (" . $path . ")'");
|
||||||
Cronjob::inserttask(TaskId::CREATE_FTP);
|
Cronjob::inserttask(TaskId::CREATE_FTP);
|
||||||
|
|
||||||
if ($sendinfomail == 1) {
|
if ($sendinfomail == 1) {
|
||||||
@@ -302,7 +302,7 @@ class Ftps extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
$this->mailer()->clearAddresses();
|
$this->mailer()->clearAddresses();
|
||||||
}
|
}
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added ftp-user '" . $username . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added ftp-user '" . $username . "'");
|
||||||
|
|
||||||
$result = $this->apiCall('Ftps.get', [
|
$result = $this->apiCall('Ftps.get', [
|
||||||
'username' => $username
|
'username' => $username
|
||||||
@@ -367,7 +367,7 @@ class Ftps extends ApiCommand implements ResourceEntity
|
|||||||
$params['idun'] = ($id <= 0 ? $username : $id);
|
$params['idun'] = ($id <= 0 ? $username : $id);
|
||||||
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get ftp-user '" . $result['username'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get ftp-user '" . $result['username'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
$key = ($id > 0 ? "id #" . $id : "username '" . $username . "'");
|
$key = ($id > 0 ? "id #" . $id : "username '" . $username . "'");
|
||||||
@@ -453,7 +453,7 @@ class Ftps extends ApiCommand implements ResourceEntity
|
|||||||
"id" => $id,
|
"id" => $id,
|
||||||
"password" => $cryptPassword
|
"password" => $cryptPassword
|
||||||
], true, true);
|
], true, true);
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated ftp-account password for '" . $result['username'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] updated ftp-account password for '" . $result['username'] . "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
// path update?
|
// path update?
|
||||||
@@ -471,7 +471,7 @@ class Ftps extends ApiCommand implements ResourceEntity
|
|||||||
"customerid" => $customer['customerid'],
|
"customerid" => $customer['customerid'],
|
||||||
"id" => $id
|
"id" => $id
|
||||||
], true, true);
|
], true, true);
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated ftp-account homdir for '" . $result['username'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] updated ftp-account homdir for '" . $result['username'] . "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// it's the task for "new ftp" but that will
|
// it's the task for "new ftp" but that will
|
||||||
@@ -533,7 +533,7 @@ class Ftps extends ApiCommand implements ResourceEntity
|
|||||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
$result[] = $row;
|
$result[] = $row;
|
||||||
}
|
}
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list ftp-users");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] list ftp-users");
|
||||||
return $this->response([
|
return $this->response([
|
||||||
'count' => count($result),
|
'count' => count($result),
|
||||||
'list' => $result
|
'list' => $result
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class HostingPlans extends ApiCommand implements ResourceEntity
|
|||||||
public function listing()
|
public function listing()
|
||||||
{
|
{
|
||||||
if ($this->isAdmin()) {
|
if ($this->isAdmin()) {
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list hosting-plans");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] list hosting-plans");
|
||||||
$query_fields = [];
|
$query_fields = [];
|
||||||
$result_stmt = Database::prepare("
|
$result_stmt = Database::prepare("
|
||||||
SELECT p.*, a.loginname as adminname
|
SELECT p.*, a.loginname as adminname
|
||||||
@@ -200,8 +200,8 @@ class HostingPlans extends ApiCommand implements ResourceEntity
|
|||||||
$value_arr['logviewenabled'] = $this->getBoolParam('logviewenabled', true, 0);
|
$value_arr['logviewenabled'] = $this->getBoolParam('logviewenabled', true, 0);
|
||||||
|
|
||||||
// validation
|
// validation
|
||||||
$name = Validate::validate(trim($name), 'name', '', '', [], true);
|
$name = Validate::validate(trim($name), 'name', Validate::REGEX_DESC_TEXT, '', [], true);
|
||||||
$description = Validate::validate(str_replace("\r\n", "\n", $description), 'description', Validate::REGEX_DESC_TEXT);
|
$description = Validate::validate(str_replace("\r\n", "\n", $description), 'description', Validate::REGEX_CONF_TEXT);
|
||||||
|
|
||||||
if (Settings::Get('system.mail_quota_enabled') != '1') {
|
if (Settings::Get('system.mail_quota_enabled') != '1') {
|
||||||
$value_arr['email_quota'] = -1;
|
$value_arr['email_quota'] = -1;
|
||||||
@@ -227,7 +227,7 @@ class HostingPlans extends ApiCommand implements ResourceEntity
|
|||||||
'valuearr' => json_encode($value_arr)
|
'valuearr' => json_encode($value_arr)
|
||||||
];
|
];
|
||||||
Database::pexecute($ins_stmt, $ins_data, true, true);
|
Database::pexecute($ins_stmt, $ins_data, true, true);
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added hosting-plan '" . $name . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] added hosting-plan '" . $name . "'");
|
||||||
$result = $this->apiCall('HostingPlans.get', [
|
$result = $this->apiCall('HostingPlans.get', [
|
||||||
'planname' => $name
|
'planname' => $name
|
||||||
]);
|
]);
|
||||||
@@ -264,7 +264,7 @@ class HostingPlans extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get hosting-plan '" . $result['name'] . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] get hosting-plan '" . $result['name'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
$key = ($id > 0 ? "id #" . $id : "planname '" . $planname . "'");
|
$key = ($id > 0 ? "id #" . $id : "planname '" . $planname . "'");
|
||||||
@@ -382,8 +382,8 @@ class HostingPlans extends ApiCommand implements ResourceEntity
|
|||||||
$value_arr['logviewenabled'] = $this->getBoolParam('logviewenabled', true, $result['logviewenabled']);
|
$value_arr['logviewenabled'] = $this->getBoolParam('logviewenabled', true, $result['logviewenabled']);
|
||||||
|
|
||||||
// validation
|
// validation
|
||||||
$name = Validate::validate(trim($name), 'name', '', '', [], true);
|
$name = Validate::validate(trim($name), 'name', Validate::REGEX_DESC_TEXT, '', [], true);
|
||||||
$description = Validate::validate(str_replace("\r\n", "\n", $description), 'description', Validate::REGEX_DESC_TEXT);
|
$description = Validate::validate(str_replace("\r\n", "\n", $description), 'description', Validate::REGEX_CONF_TEXT);
|
||||||
|
|
||||||
if (Settings::Get('system.mail_quota_enabled') != '1') {
|
if (Settings::Get('system.mail_quota_enabled') != '1') {
|
||||||
$value_arr['email_quota'] = -1;
|
$value_arr['email_quota'] = -1;
|
||||||
@@ -414,7 +414,7 @@ class HostingPlans extends ApiCommand implements ResourceEntity
|
|||||||
'id' => $id
|
'id' => $id
|
||||||
];
|
];
|
||||||
Database::pexecute($upd_stmt, $update_data, true, true);
|
Database::pexecute($upd_stmt, $update_data, true, true);
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated hosting-plan '" . $result['name'] . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] updated hosting-plan '" . $result['name'] . "'");
|
||||||
return $this->response($update_data);
|
return $this->response($update_data);
|
||||||
}
|
}
|
||||||
throw new Exception("Not allowed to execute given command.", 403);
|
throw new Exception("Not allowed to execute given command.", 403);
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class IpsAndPorts extends ApiCommand implements ResourceEntity
|
|||||||
public function listing()
|
public function listing()
|
||||||
{
|
{
|
||||||
if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || !empty($this->getUserDetail('ip')))) {
|
if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || !empty($this->getUserDetail('ip')))) {
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list ips and ports");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] list ips and ports");
|
||||||
$ip_where = "";
|
$ip_where = "";
|
||||||
$append_where = false;
|
$append_where = false;
|
||||||
if (!empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != -1) {
|
if (!empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != -1) {
|
||||||
@@ -175,9 +175,9 @@ class IpsAndPorts extends ApiCommand implements ResourceEntity
|
|||||||
$docroot = Validate::validate($this->getParam('docroot', true, ''), 'docroot', Validate::REGEX_DIR, '', [], true);
|
$docroot = Validate::validate($this->getParam('docroot', true, ''), 'docroot', Validate::REGEX_DIR, '', [], true);
|
||||||
|
|
||||||
if ((int)Settings::Get('system.use_ssl') == 1) {
|
if ((int)Settings::Get('system.use_ssl') == 1) {
|
||||||
$ssl = !empty($this->getBoolParam('ssl', true, 0)) ? intval($this->getBoolParam('ssl', true, 0)) : 0;
|
$ssl = (bool)$this->getBoolParam('ssl', true, 0);
|
||||||
$ssl_cert_file = Validate::validate($this->getParam('ssl_cert_file', $ssl, ''), 'ssl_cert_file', '', '', [], true);
|
$ssl_cert_file = Validate::validate($this->getParam('ssl_cert_file', !$ssl, ''), 'ssl_cert_file', '', '', [], true);
|
||||||
$ssl_key_file = Validate::validate($this->getParam('ssl_key_file', $ssl, ''), 'ssl_key_file', '', '', [], true);
|
$ssl_key_file = Validate::validate($this->getParam('ssl_key_file', !$ssl, ''), 'ssl_key_file', '', '', [], true);
|
||||||
$ssl_ca_file = Validate::validate($this->getParam('ssl_ca_file', true, ''), 'ssl_ca_file', '', '', [], true);
|
$ssl_ca_file = Validate::validate($this->getParam('ssl_ca_file', true, ''), 'ssl_ca_file', '', '', [], true);
|
||||||
$ssl_cert_chainfile = Validate::validate($this->getParam('ssl_cert_chainfile', true, ''), 'ssl_cert_chainfile', '', '', [], true);
|
$ssl_cert_chainfile = Validate::validate($this->getParam('ssl_cert_chainfile', true, ''), 'ssl_cert_chainfile', '', '', [], true);
|
||||||
$sslss = $this->getParam('ssl_specialsettings', true, '');
|
$sslss = $this->getParam('ssl_specialsettings', true, '');
|
||||||
@@ -335,7 +335,7 @@ class IpsAndPorts extends ApiCommand implements ResourceEntity
|
|||||||
'id' => $id
|
'id' => $id
|
||||||
], true, true);
|
], true, true);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get ip " . $result['ip'] . " " . $result['port']);
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] get ip " . $result['ip'] . " " . $result['port']);
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
throw new Exception("IP/port with id #" . $id . " could not be found", 404);
|
throw new Exception("IP/port with id #" . $id . " could not be found", 404);
|
||||||
@@ -414,9 +414,9 @@ class IpsAndPorts extends ApiCommand implements ResourceEntity
|
|||||||
$docroot = Validate::validate($this->getParam('docroot', true, $result['docroot']), 'docroot', Validate::REGEX_DIR, '', [], true);
|
$docroot = Validate::validate($this->getParam('docroot', true, $result['docroot']), 'docroot', Validate::REGEX_DIR, '', [], true);
|
||||||
|
|
||||||
if ((int)Settings::Get('system.use_ssl') == 1) {
|
if ((int)Settings::Get('system.use_ssl') == 1) {
|
||||||
$ssl = $this->getBoolParam('ssl', true, $result['ssl']);
|
$ssl = (bool)$this->getBoolParam('ssl', true, $result['ssl']);
|
||||||
$ssl_cert_file = Validate::validate($this->getParam('ssl_cert_file', $ssl, $result['ssl_cert_file']), 'ssl_cert_file', '', '', [], true);
|
$ssl_cert_file = Validate::validate($this->getParam('ssl_cert_file', !$ssl, $result['ssl_cert_file']), 'ssl_cert_file', '', '', [], true);
|
||||||
$ssl_key_file = Validate::validate($this->getParam('ssl_key_file', $ssl, $result['ssl_key_file']), 'ssl_key_file', '', '', [], true);
|
$ssl_key_file = Validate::validate($this->getParam('ssl_key_file', !$ssl, $result['ssl_key_file']), 'ssl_key_file', '', '', [], true);
|
||||||
$ssl_ca_file = Validate::validate($this->getParam('ssl_ca_file', true, $result['ssl_ca_file']), 'ssl_ca_file', '', '', [], true);
|
$ssl_ca_file = Validate::validate($this->getParam('ssl_ca_file', true, $result['ssl_ca_file']), 'ssl_ca_file', '', '', [], true);
|
||||||
$ssl_cert_chainfile = Validate::validate($this->getParam('ssl_cert_chainfile', true, $result['ssl_cert_chainfile']), 'ssl_cert_chainfile', '', '', [], true);
|
$ssl_cert_chainfile = Validate::validate($this->getParam('ssl_cert_chainfile', true, $result['ssl_cert_chainfile']), 'ssl_cert_chainfile', '', '', [], true);
|
||||||
$sslss = $this->getParam('ssl_specialsettings', true, $result['ssl_specialsettings']);
|
$sslss = $this->getParam('ssl_specialsettings', true, $result['ssl_specialsettings']);
|
||||||
|
|||||||
@@ -26,14 +26,15 @@
|
|||||||
namespace Froxlor\Api\Commands;
|
namespace Froxlor\Api\Commands;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use PDO;
|
|
||||||
use PDOException;
|
|
||||||
use Froxlor\Froxlor;
|
|
||||||
use Froxlor\PhpHelper;
|
|
||||||
use Froxlor\Api\ApiCommand;
|
use Froxlor\Api\ApiCommand;
|
||||||
use Froxlor\Api\ResourceEntity;
|
use Froxlor\Api\ResourceEntity;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
|
use Froxlor\Froxlor;
|
||||||
|
use Froxlor\FroxlorLogger;
|
||||||
|
use Froxlor\PhpHelper;
|
||||||
use Froxlor\Validate\Validate;
|
use Froxlor\Validate\Validate;
|
||||||
|
use PDO;
|
||||||
|
use PDOException;
|
||||||
|
|
||||||
class MysqlServer extends ApiCommand implements ResourceEntity
|
class MysqlServer extends ApiCommand implements ResourceEntity
|
||||||
{
|
{
|
||||||
@@ -73,8 +74,8 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
|||||||
* optional, test connection with given credentials, default is true (yes)
|
* optional, test connection with given credentials, default is true (yes)
|
||||||
*
|
*
|
||||||
* @access admin
|
* @access admin
|
||||||
* @throws Exception
|
|
||||||
* @return string json-encoded array
|
* @return string json-encoded array
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function add()
|
public function add()
|
||||||
{
|
{
|
||||||
@@ -167,6 +168,8 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
|||||||
$this->addDatabaseFromCustomerAllowedList($newdbserver);
|
$this->addDatabaseFromCustomerAllowedList($newdbserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added new database server '" . $description . "' (" . $mysql_host . ")");
|
||||||
|
|
||||||
return $this->response(['dbserver' => $newdbserver]);
|
return $this->response(['dbserver' => $newdbserver]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,8 +182,8 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
|||||||
* optional the number of the mysql server (either id or dbserver must be set)
|
* optional the number of the mysql server (either id or dbserver must be set)
|
||||||
*
|
*
|
||||||
* @access admin
|
* @access admin
|
||||||
* @throws Exception
|
|
||||||
* @return string json-encoded array
|
* @return string json-encoded array
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function delete()
|
public function delete()
|
||||||
{
|
{
|
||||||
@@ -212,8 +215,12 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
|||||||
// when removing, remove from list of allowed_mysqlservers from any customers
|
// when removing, remove from list of allowed_mysqlservers from any customers
|
||||||
$this->removeDatabaseFromCustomerAllowedList($dbserver);
|
$this->removeDatabaseFromCustomerAllowedList($dbserver);
|
||||||
|
|
||||||
|
$description = $sql_root[$dbserver]['caption'] ?? "unknown";
|
||||||
|
$mysql_host = $sql_root[$dbserver]['host'] ?? "unknown";
|
||||||
unset($sql_root[$dbserver]);
|
unset($sql_root[$dbserver]);
|
||||||
|
|
||||||
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] removed database server '" . $description . "' (" . $mysql_host . ")");
|
||||||
|
|
||||||
$this->generateNewUserData($sql, $sql_root);
|
$this->generateNewUserData($sql, $sql_root);
|
||||||
return $this->response(['true']);
|
return $this->response(['true']);
|
||||||
}
|
}
|
||||||
@@ -287,8 +294,8 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
|||||||
* optional the number of the mysql server (either id or dbserver must be set)
|
* optional the number of the mysql server (either id or dbserver must be set)
|
||||||
*
|
*
|
||||||
* @access admin, customer
|
* @access admin, customer
|
||||||
* @throws Exception
|
|
||||||
* @return string json-encoded array
|
* @return string json-encoded array
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function get()
|
public function get()
|
||||||
{
|
{
|
||||||
@@ -317,6 +324,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
unset($sql_root[$dbserver]['password']);
|
unset($sql_root[$dbserver]['password']);
|
||||||
$sql_root[$dbserver]['id'] = $dbserver;
|
$sql_root[$dbserver]['id'] = $dbserver;
|
||||||
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] get database-server '" . $sql_root[$dbserver]['caption'] . "'");
|
||||||
return $this->response($sql_root[$dbserver]);
|
return $this->response($sql_root[$dbserver]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,8 +355,8 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
|||||||
* optional, test connection with given credentials, default is true (yes)
|
* optional, test connection with given credentials, default is true (yes)
|
||||||
*
|
*
|
||||||
* @access admin
|
* @access admin
|
||||||
* @throws Exception
|
|
||||||
* @return string json-encoded array
|
* @return string json-encoded array
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function update()
|
public function update()
|
||||||
{
|
{
|
||||||
@@ -448,6 +456,8 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
|||||||
$this->addDatabaseFromCustomerAllowedList($dbserver);
|
$this->addDatabaseFromCustomerAllowedList($dbserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] edited database server '" . $description . "' (" . $mysql_host . ")");
|
||||||
|
|
||||||
return $this->response(['true']);
|
return $this->response(['true']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,7 +526,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
|||||||
`allowed_mysqlserver` = :am WHERE `customerid` = :cid
|
`allowed_mysqlserver` = :am WHERE `customerid` = :cid
|
||||||
");
|
");
|
||||||
while ($customer = $sel_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($customer = $sel_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
$allowed_mysqls = json_decode(($customer['allowed_mysqlserver'] ?? '[]'), true);
|
$allowed_mysqls = json_decode(($customer['allowed_mysqlserver'] ?: '[]'), true);
|
||||||
if (!in_array($dbserver, $allowed_mysqls)) {
|
if (!in_array($dbserver, $allowed_mysqls)) {
|
||||||
$allowed_mysqls[] = $dbserver;
|
$allowed_mysqls[] = $dbserver;
|
||||||
$allowed_mysqls = json_encode($allowed_mysqls);
|
$allowed_mysqls = json_encode($allowed_mysqls);
|
||||||
|
|||||||
@@ -73,12 +73,12 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
|||||||
$password = $this->getParam('mysql_password');
|
$password = $this->getParam('mysql_password');
|
||||||
|
|
||||||
// parameters
|
// parameters
|
||||||
$dbserver = $this->getParam('mysql_server', true, 0);
|
|
||||||
$databasedescription = $this->getParam('description', true, '');
|
$databasedescription = $this->getParam('description', true, '');
|
||||||
$databasename = $this->getParam('custom_suffix', true, '');
|
$databasename = $this->getParam('custom_suffix', true, '');
|
||||||
$sendinfomail = $this->getBoolParam('sendinfomail', true, 0);
|
$sendinfomail = $this->getBoolParam('sendinfomail', true, 0);
|
||||||
// get needed customer info to reduce the mysql-usage-counter by one
|
// get needed customer info to reduce the mysql-usage-counter by one
|
||||||
$customer = $this->getCustomerData('mysqls');
|
$customer = $this->getCustomerData('mysqls');
|
||||||
|
$dbserver = $this->getParam('mysql_server', true, $this->getDefaultMySqlServer($customer));
|
||||||
|
|
||||||
// validation
|
// validation
|
||||||
$password = Validate::validate($password, 'password', '', '', [], true);
|
$password = Validate::validate($password, 'password', '', '', [], true);
|
||||||
@@ -90,7 +90,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// validate whether the dbserver exists
|
// validate whether the dbserver exists
|
||||||
$dbserver = Validate::validate($dbserver, html_entity_decode(lng('mysql.mysql_server')), '/^[0-9]+$/', '', 0, true);
|
$dbserver = Validate::validate($dbserver, html_entity_decode(lng('mysql.mysql_server')), '/^[0-9]+$/', '', 0, true);
|
||||||
Database::needRoot(true, $dbserver);
|
Database::needRoot(true, $dbserver, false);
|
||||||
Database::needSqlData();
|
Database::needSqlData();
|
||||||
$sql_root = Database::getSqlData();
|
$sql_root = Database::getSqlData();
|
||||||
Database::needRoot(false);
|
Database::needRoot(false);
|
||||||
@@ -150,7 +150,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
|||||||
$pma = Settings::Get('panel.phpmyadmin_url');
|
$pma = Settings::Get('panel.phpmyadmin_url');
|
||||||
}
|
}
|
||||||
|
|
||||||
Database::needRoot(true, $dbserver);
|
Database::needRoot(true, $dbserver, false);
|
||||||
Database::needSqlData();
|
Database::needSqlData();
|
||||||
$sql_root = Database::getSqlData();
|
$sql_root = Database::getSqlData();
|
||||||
Database::needRoot(false);
|
Database::needRoot(false);
|
||||||
@@ -199,7 +199,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
$this->mailer()->clearAddresses();
|
$this->mailer()->clearAddresses();
|
||||||
}
|
}
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added mysql-database '" . $username . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added mysql-database '" . $username . "'");
|
||||||
|
|
||||||
$result = $this->apiCall('Mysqls.get', [
|
$result = $this->apiCall('Mysqls.get', [
|
||||||
'dbname' => $username,
|
'dbname' => $username,
|
||||||
@@ -287,7 +287,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
Database::needRoot(true, $result['dbserver']);
|
Database::needRoot(true, $result['dbserver'], false);
|
||||||
$mbdata_stmt = Database::prepare("
|
$mbdata_stmt = Database::prepare("
|
||||||
SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES
|
SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES
|
||||||
WHERE table_schema = :table_schema
|
WHERE table_schema = :table_schema
|
||||||
@@ -299,7 +299,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
|||||||
$mbdata = $mbdata_stmt->fetch(PDO::FETCH_ASSOC);
|
$mbdata = $mbdata_stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
Database::needRoot(false);
|
Database::needRoot(false);
|
||||||
$result['size'] = $mbdata['MB'] ?? 0;
|
$result['size'] = $mbdata['MB'] ?? 0;
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get database '" . $result['databasename'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get database '" . $result['databasename'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
$key = ($id > 0 ? "id #" . $id : "dbname '" . $dbname . "'");
|
$key = ($id > 0 ? "id #" . $id : "dbname '" . $dbname . "'");
|
||||||
@@ -364,7 +364,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Begin root-session
|
// Begin root-session
|
||||||
Database::needRoot(true, $result['dbserver']);
|
Database::needRoot(true, $result['dbserver'], false);
|
||||||
$dbmgr = new DbManager($this->logger());
|
$dbmgr = new DbManager($this->logger());
|
||||||
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
|
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
|
||||||
$dbmgr->getManager()->grantPrivilegesTo($result['databasename'], $password, $mysql_access_host, false, true);
|
$dbmgr->getManager()->grantPrivilegesTo($result['databasename'], $password, $mysql_access_host, false, true);
|
||||||
@@ -388,7 +388,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
|||||||
];
|
];
|
||||||
Database::pexecute($stmt, $params, true, true);
|
Database::pexecute($stmt, $params, true, true);
|
||||||
|
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] updated mysql-database '" . $result['databasename'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] updated mysql-database '" . $result['databasename'] . "'");
|
||||||
$result = $this->apiCall('Mysqls.get', [
|
$result = $this->apiCall('Mysqls.get', [
|
||||||
'dbname' => $result['databasename']
|
'dbname' => $result['databasename']
|
||||||
]);
|
]);
|
||||||
@@ -449,7 +449,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
|||||||
'dbserver' => $_dbserver['dbserver']
|
'dbserver' => $_dbserver['dbserver']
|
||||||
], $query_fields), true, true);
|
], $query_fields), true, true);
|
||||||
// Begin root-session
|
// Begin root-session
|
||||||
Database::needRoot(true, $_dbserver['dbserver']);
|
Database::needRoot(true, $_dbserver['dbserver'], false);
|
||||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
$mbdata_stmt = Database::prepare("
|
$mbdata_stmt = Database::prepare("
|
||||||
SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES
|
SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES
|
||||||
@@ -536,7 +536,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
|||||||
$id = $result['id'];
|
$id = $result['id'];
|
||||||
|
|
||||||
// Begin root-session
|
// Begin root-session
|
||||||
Database::needRoot(true, $result['dbserver']);
|
Database::needRoot(true, $result['dbserver'], false);
|
||||||
$dbm = new DbManager($this->logger());
|
$dbm = new DbManager($this->logger());
|
||||||
$dbm->getManager()->deleteDatabase($result['databasename']);
|
$dbm->getManager()->deleteDatabase($result['databasename']);
|
||||||
Database::needRoot(false);
|
Database::needRoot(false);
|
||||||
@@ -558,4 +558,13 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
|||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted database '" . $result['databasename'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted database '" . $result['databasename'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getDefaultMySqlServer(array $customer) {
|
||||||
|
$allowed_mysqlservers = json_decode($customer['allowed_mysqlserver'] ?? '[]', true);
|
||||||
|
asort($allowed_mysqlservers, SORT_NUMERIC);
|
||||||
|
if (count($allowed_mysqlservers) == 1 && $allowed_mysqlservers[0] != 0) {
|
||||||
|
return (int) $allowed_mysqlservers[0];
|
||||||
|
}
|
||||||
|
return (int) array_shift($allowed_mysqlservers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
|||||||
public function listing()
|
public function listing()
|
||||||
{
|
{
|
||||||
if ($this->isAdmin()) {
|
if ($this->isAdmin()) {
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list php-configs");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] list php-configs");
|
||||||
|
|
||||||
$with_subdomains = $this->getBoolParam('with_subdomains', true, false);
|
$with_subdomains = $this->getBoolParam('with_subdomains', true, false);
|
||||||
$query_fields = [];
|
$query_fields = [];
|
||||||
@@ -392,7 +392,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
|||||||
$ins_data['id'] = Database::lastInsertId();
|
$ins_data['id'] = Database::lastInsertId();
|
||||||
|
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting with description '" . $description . "' has been created by '" . $this->getUserDetail('loginname') . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] php setting with description '" . $description . "' has been created by '" . $this->getUserDetail('loginname') . "'");
|
||||||
|
|
||||||
$result = $this->apiCall('PhpSettings.get', [
|
$result = $this->apiCall('PhpSettings.get', [
|
||||||
'id' => $ins_data['id']
|
'id' => $ins_data['id']
|
||||||
@@ -629,7 +629,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
|||||||
Database::pexecute($upd_stmt, $upd_data, true, true);
|
Database::pexecute($upd_stmt, $upd_data, true, true);
|
||||||
|
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting with description '" . $description . "' has been updated by '" . $this->getUserDetail('loginname') . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] php setting with description '" . $description . "' has been updated by '" . $this->getUserDetail('loginname') . "'");
|
||||||
|
|
||||||
$result = $this->apiCall('PhpSettings.get', [
|
$result = $this->apiCall('PhpSettings.get', [
|
||||||
'id' => $id
|
'id' => $id
|
||||||
@@ -686,7 +686,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
|||||||
], true, true);
|
], true, true);
|
||||||
|
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] php setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
throw new Exception("Not allowed to execute given command.", 403);
|
throw new Exception("Not allowed to execute given command.", 403);
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
* optional, overwrites path value with an URL to generate a redirect, alternatively use the path
|
* optional, overwrites path value with an URL to generate a redirect, alternatively use the path
|
||||||
* parameter also for URLs
|
* parameter also for URLs
|
||||||
* @param int $openbasedir_path
|
* @param int $openbasedir_path
|
||||||
* optional, either 0 for domains-docroot, 1 for customers-homedir or 2 for parent-directory of domains-docroot
|
* optional, either 0 for domains-docroot [default], 1 for customers-homedir or 2 for parent-directory of domains-docroot
|
||||||
* @param int $phpsettingid
|
* @param int $phpsettingid
|
||||||
* optional, php-settings-id, if empty the $domain value is used
|
* optional, php-settings-id, if empty the $domain value is used
|
||||||
* @param int $redirectcode
|
* @param int $redirectcode
|
||||||
@@ -104,7 +104,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
$aliasdomain = $this->getParam('alias', true, 0);
|
$aliasdomain = $this->getParam('alias', true, 0);
|
||||||
$path = $this->getParam('path', true, '');
|
$path = $this->getParam('path', true, '');
|
||||||
$url = $this->getParam('url', true, '');
|
$url = $this->getParam('url', true, '');
|
||||||
$openbasedir_path = $this->getParam('openbasedir_path', true, 1);
|
$openbasedir_path = $this->getParam('openbasedir_path', true, 0);
|
||||||
$phpsettingid = $this->getParam('phpsettingid', true, 0);
|
$phpsettingid = $this->getParam('phpsettingid', true, 0);
|
||||||
$redirectcode = $this->getParam('redirectcode', true, Settings::Get('customredirect.default'));
|
$redirectcode = $this->getParam('redirectcode', true, Settings::Get('customredirect.default'));
|
||||||
$isemaildomain = $this->getParam('isemaildomain', true, 0);
|
$isemaildomain = $this->getParam('isemaildomain', true, 0);
|
||||||
@@ -262,7 +262,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
// validate dns if lets encrypt is enabled to check whether we can use it at all
|
// validate dns if lets encrypt is enabled to check whether we can use it at all
|
||||||
if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
|
if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
|
||||||
$our_ips = Domain::getIpsOfDomain($domain_check['id']);
|
$our_ips = Domain::getIpsOfDomain($domain_check['id']);
|
||||||
$domain_ips = PhpHelper::gethostbynamel6($completedomain);
|
$domain_ips = PhpHelper::gethostbynamel6($completedomain, true, Settings::Get('system.le_domain_dnscheck_resolver'));
|
||||||
if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) {
|
if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) {
|
||||||
Response::standardError('invaliddnsforletsencrypt', '', true);
|
Response::standardError('invaliddnsforletsencrypt', '', true);
|
||||||
}
|
}
|
||||||
@@ -486,7 +486,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
$result['ipsandports'] = $this->getIpsForDomain($result['id']);
|
$result['ipsandports'] = $this->getIpsForDomain($result['id']);
|
||||||
}
|
}
|
||||||
$result['domain_hascert'] = $this->getHasCertValueForDomain((int)$result['id'], (int)$result['parentdomainid']);
|
$result['domain_hascert'] = $this->getHasCertValueForDomain((int)$result['id'], (int)$result['parentdomainid']);
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get subdomain '" . $result['domain'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get subdomain '" . $result['domain'] . "'");
|
||||||
return $this->response($result);
|
return $this->response($result);
|
||||||
}
|
}
|
||||||
$key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'");
|
$key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'");
|
||||||
@@ -701,11 +701,13 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
$wwwserveralias = ($selectserveralias == '1') ? '1' : '0';
|
$wwwserveralias = ($selectserveralias == '1') ? '1' : '0';
|
||||||
|
|
||||||
// if allowed, check for 'is email domain'-flag
|
// if allowed, check for 'is email domain'-flag
|
||||||
if ($result['parentdomainid'] != '0' && ($result['subcanemaildomain'] == '1' || $result['subcanemaildomain'] == '2') && $isemaildomain != $result['isemaildomain']) {
|
if ($isemaildomain != $result['isemaildomain']) {
|
||||||
|
if ($result['parentdomainid'] != '0' && ($result['subcanemaildomain'] == '1' || $result['subcanemaildomain'] == '2')) {
|
||||||
$isemaildomain = intval($isemaildomain);
|
$isemaildomain = intval($isemaildomain);
|
||||||
} elseif ($result['parentdomainid'] != '0') {
|
} elseif ($result['parentdomainid'] != '0') {
|
||||||
$isemaildomain = $result['subcanemaildomain'] == '3' ? 1 : 0;
|
$isemaildomain = $result['subcanemaildomain'] == '3' ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check changes of openbasedir-path variable
|
// check changes of openbasedir-path variable
|
||||||
if ($openbasedir_path > 2 && $openbasedir_path < 0) {
|
if ($openbasedir_path > 2 && $openbasedir_path < 0) {
|
||||||
@@ -736,7 +738,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
// validate dns if lets encrypt is enabled to check whether we can use it at all
|
// validate dns if lets encrypt is enabled to check whether we can use it at all
|
||||||
if ($result['letsencrypt'] != $letsencrypt && $letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
|
if ($result['letsencrypt'] != $letsencrypt && $letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
|
||||||
$our_ips = Domain::getIpsOfDomain($result['parentdomainid']);
|
$our_ips = Domain::getIpsOfDomain($result['parentdomainid']);
|
||||||
$domain_ips = PhpHelper::gethostbynamel6($result['domain']);
|
$domain_ips = PhpHelper::gethostbynamel6($result['domain'], true, Settings::Get('system.le_domain_dnscheck_resolver'));
|
||||||
if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) {
|
if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) {
|
||||||
Response::standardError('invaliddnsforletsencrypt', '', true);
|
Response::standardError('invaliddnsforletsencrypt', '', true);
|
||||||
}
|
}
|
||||||
@@ -854,7 +856,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
Cronjob::inserttask(TaskId::REBUILD_DNS);
|
Cronjob::inserttask(TaskId::REBUILD_DNS);
|
||||||
$idna_convert = new IdnaWrapper();
|
$idna_convert = new IdnaWrapper();
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] edited domain '" . $idna_convert->decode($result['domain']) . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] edited domain '" . $idna_convert->decode($result['domain']) . "'");
|
||||||
}
|
}
|
||||||
$result = $this->apiCall('SubDomains.get', [
|
$result = $this->apiCall('SubDomains.get', [
|
||||||
'id' => $id
|
'id' => $id
|
||||||
@@ -1131,7 +1133,9 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((int)$result['aliasdomain'] !== 0) {
|
||||||
Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger());
|
Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger());
|
||||||
|
}
|
||||||
|
|
||||||
// delete domain from table
|
// delete domain from table
|
||||||
$stmt = Database::prepare("
|
$stmt = Database::prepare("
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class SysLog extends ApiCommand implements ResourceEntity
|
|||||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
$result[] = $row;
|
$result[] = $row;
|
||||||
}
|
}
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list log-entries");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] list log-entries");
|
||||||
return $this->response([
|
return $this->response([
|
||||||
'count' => count($result),
|
'count' => count($result),
|
||||||
'list' => $result
|
'list' => $result
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ class Traffic extends ApiCommand implements ResourceEntity
|
|||||||
$row['mail'] *= 1024;
|
$row['mail'] *= 1024;
|
||||||
$result[] = $row;
|
$result[] = $row;
|
||||||
}
|
}
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list traffic");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] list traffic");
|
||||||
return $this->response([
|
return $this->response([
|
||||||
'count' => count($result),
|
'count' => count($result),
|
||||||
'list' => $result
|
'list' => $result
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
|||||||
class CliCommand extends Command
|
class CliCommand extends Command
|
||||||
{
|
{
|
||||||
|
|
||||||
protected function validateRequirements(InputInterface $input, OutputInterface $output): int
|
protected function validateRequirements(InputInterface $input, OutputInterface $output, bool $ignore_has_updates = false): int
|
||||||
{
|
{
|
||||||
if (!file_exists(Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
|
if (!file_exists(Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
|
||||||
$output->writeln("<error>Could not find froxlor's userdata.inc.php file. You should use this script only with an installed froxlor system.</>");
|
$output->writeln("<error>Could not find froxlor's userdata.inc.php file. You should use this script only with an installed froxlor system.</>");
|
||||||
@@ -51,7 +51,7 @@ class CliCommand extends Command
|
|||||||
$output->writeln("<error>" . $e->getMessage() . "</>");
|
$output->writeln("<error>" . $e->getMessage() . "</>");
|
||||||
return self::INVALID;
|
return self::INVALID;
|
||||||
}
|
}
|
||||||
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
|
if (!$ignore_has_updates && (Froxlor::hasUpdates() || Froxlor::hasDbUpdates())) {
|
||||||
if ((int)Settings::Get('system.cron_allowautoupdate') == 1) {
|
if ((int)Settings::Get('system.cron_allowautoupdate') == 1) {
|
||||||
return $this->runUpdate($output);
|
return $this->runUpdate($output);
|
||||||
} else {
|
} else {
|
||||||
@@ -122,7 +122,7 @@ class CliCommand extends Command
|
|||||||
include_once Froxlor::getInstallDir() . '/lib/tables.inc.php';
|
include_once Froxlor::getInstallDir() . '/lib/tables.inc.php';
|
||||||
define('_CRON_UPDATE', 1);
|
define('_CRON_UPDATE', 1);
|
||||||
ob_start([
|
ob_start([
|
||||||
'this',
|
$this,
|
||||||
'cleanUpdateOutput'
|
'cleanUpdateOutput'
|
||||||
]);
|
]);
|
||||||
include_once Froxlor::getInstallDir() . '/install/updatesql.php';
|
include_once Froxlor::getInstallDir() . '/install/updatesql.php';
|
||||||
|
|||||||
178
lib/Froxlor/Cli/ConfigDiff.php
Normal file
178
lib/Froxlor/Cli/ConfigDiff.php
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file is part of the Froxlor project.
|
||||||
|
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you can also view it online at
|
||||||
|
* https://files.froxlor.org/misc/COPYING.txt
|
||||||
|
*
|
||||||
|
* @copyright the authors
|
||||||
|
* @author Froxlor team <team@froxlor.org>
|
||||||
|
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Froxlor\Cli;
|
||||||
|
|
||||||
|
use Froxlor\Config\ConfigParser;
|
||||||
|
use Froxlor\FileDir;
|
||||||
|
use Froxlor\Froxlor;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
final class ConfigDiff extends CliCommand
|
||||||
|
{
|
||||||
|
protected function configure(): void
|
||||||
|
{
|
||||||
|
$this->setName('froxlor:config-diff')
|
||||||
|
->setDescription('Shows differences in config templates between OS versions')
|
||||||
|
->addArgument('from', InputArgument::OPTIONAL, 'OS version to compare against')
|
||||||
|
->addArgument('to', InputArgument::OPTIONAL, 'OS version to compare from')
|
||||||
|
->addOption('list', 'l', InputOption::VALUE_NONE, 'List all possible OS versions')
|
||||||
|
->addOption('diff-params', '', InputOption::VALUE_REQUIRED, 'Additional parameters for `diff`, e.g. --diff-params="--color=always"');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
require Froxlor::getInstallDir() . '/lib/functions.php';
|
||||||
|
|
||||||
|
$parsers = $versions = [];
|
||||||
|
foreach (glob(Froxlor::getInstallDir() . '/lib/configfiles/*.xml') as $config) {
|
||||||
|
$name = str_replace(".xml", "", strtolower(basename($config)));
|
||||||
|
$parser = new ConfigParser($config);
|
||||||
|
$versions[$name] = $parser->getCompleteDistroName();
|
||||||
|
$parsers[$name] = $parser;
|
||||||
|
}
|
||||||
|
asort($versions);
|
||||||
|
|
||||||
|
if ($input->getOption('list') === true) {
|
||||||
|
$output->writeln('The following OS version templates are available:');
|
||||||
|
foreach ($versions as $k => $v) {
|
||||||
|
$output->writeln(str_pad($k, 20) . $v);
|
||||||
|
}
|
||||||
|
return self::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$input->hasArgument('from') || !array_key_exists($input->getArgument('from'), $versions)) {
|
||||||
|
$output->writeln('<error>Missing or invalid "from" argument.</error>');
|
||||||
|
$output->writeln('Available versions: ' . implode(', ', array_keys($versions)));
|
||||||
|
return self::INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$input->hasArgument('to') || !array_key_exists($input->getArgument('to'), $versions)) {
|
||||||
|
$output->writeln('<error>Missing or invalid "to" argument.</error>');
|
||||||
|
$output->writeln('Available versions: ' . implode(', ', array_keys($versions)));
|
||||||
|
return self::INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure diff is installed
|
||||||
|
$check_diff_installed = FileDir::safe_exec('which diff');
|
||||||
|
if (count($check_diff_installed) === 0) {
|
||||||
|
$output->writeln('<error>Unable to find "diff" installation on your system.</error>');
|
||||||
|
return self::INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parser_from = $parsers[$input->getArgument('from')];
|
||||||
|
$parser_to = $parsers[$input->getArgument('to')];
|
||||||
|
$tmp_from = tempnam(sys_get_temp_dir(), 'froxlor_config_diff_from');
|
||||||
|
$tmp_to = tempnam(sys_get_temp_dir(), 'froxlor_config_diff_to');
|
||||||
|
$files = [];
|
||||||
|
$titles_by_key = [];
|
||||||
|
|
||||||
|
// Aggregate content for each config file
|
||||||
|
foreach ([[$parser_from, 'from'], [$parser_to, 'to']] as $todo) {
|
||||||
|
foreach ($todo[0]->getServices() as $service_type => $service) {
|
||||||
|
foreach ($service->getDaemons() as $daemon_name => $daemon) {
|
||||||
|
foreach ($daemon->getConfig() as $instruction) {
|
||||||
|
if ($instruction['type'] !== 'file') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($instruction['subcommands'])) {
|
||||||
|
foreach ($instruction['subcommands'] as $subinstruction) {
|
||||||
|
if ($subinstruction['type'] !== 'file') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$content = $subinstruction['content'];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$content = $instruction['content'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($content)) {
|
||||||
|
throw new \Exception("Cannot find content for {$instruction['name']}");
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = "{$service_type}_{$daemon_name}_{$instruction['name']}";
|
||||||
|
$titles_by_key[$key] = "{$service->title} : {$daemon->title} : {$instruction['name']}";
|
||||||
|
if (!isset($files[$key])) {
|
||||||
|
$files[$key] = ['from' => '', 'to' => ''];
|
||||||
|
}
|
||||||
|
$files[$key][$todo[1]] = $this->filterContent($content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ksort($files);
|
||||||
|
|
||||||
|
$diff_params = '';
|
||||||
|
if ($input->hasOption('diff-params') && trim($input->getOption('diff-params')) !== '') {
|
||||||
|
$diff_params = trim($input->getOption('diff-params'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run diff on each file and output, if anything changed
|
||||||
|
foreach ($files as $file_key => $content) {
|
||||||
|
file_put_contents($tmp_from, $content['from']);
|
||||||
|
file_put_contents($tmp_to, $content['to']);
|
||||||
|
$diff_output = FileDir::safe_exec("{$check_diff_installed[0]} {$diff_params} {$tmp_from} {$tmp_to}");
|
||||||
|
|
||||||
|
if (count($diff_output) === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$output->writeln('<info># ' . $titles_by_key[$file_key] . '</info>');
|
||||||
|
$output->writeln(implode("\n", $diff_output) . "\n");
|
||||||
|
unset($diff_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove tmp files again
|
||||||
|
unlink($tmp_from);
|
||||||
|
unlink($tmp_to);
|
||||||
|
|
||||||
|
return self::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function filterContent(string $content): string
|
||||||
|
{
|
||||||
|
$new_content = '';
|
||||||
|
|
||||||
|
foreach (explode("\n", $content) as $n) {
|
||||||
|
$n = trim($n);
|
||||||
|
if (!$n) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str_starts_with($n, '#')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$new_content .= $n . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $new_content;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -80,7 +80,7 @@ final class InstallCommand extends Command
|
|||||||
$_SERVER['SERVER_NAME'] = $host[0] ?? '';
|
$_SERVER['SERVER_NAME'] = $host[0] ?? '';
|
||||||
$ips = [];
|
$ips = [];
|
||||||
exec('hostname -I', $ips);
|
exec('hostname -I', $ips);
|
||||||
$ips = explode(" ", $ips[0]);
|
$ips = explode(" ", $ips[0] ?? "");
|
||||||
// ipv4 address?
|
// ipv4 address?
|
||||||
$_SERVER['SERVER_ADDR'] = filter_var($ips[0] ?? "", FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? ($ips[0] ?? '') : '';
|
$_SERVER['SERVER_ADDR'] = filter_var($ips[0] ?? "", FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? ($ips[0] ?? '') : '';
|
||||||
if (empty($_SERVER['SERVER_ADDR'])) {
|
if (empty($_SERVER['SERVER_ADDR'])) {
|
||||||
@@ -246,8 +246,11 @@ final class InstallCommand extends Command
|
|||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->io->error($e->getMessage());
|
$this->io->error($e->getMessage());
|
||||||
|
if ($this->io->confirm('Retry?', empty($decoded_input))) {
|
||||||
return $this->showStep($step, $extended, $decoded_input);
|
return $this->showStep($step, $extended, $decoded_input);
|
||||||
}
|
}
|
||||||
|
return self::FAILURE;
|
||||||
|
}
|
||||||
if ($step == 3) {
|
if ($step == 3) {
|
||||||
// do actual install with data from $this->formfielddata
|
// do actual install with data from $this->formfielddata
|
||||||
$core = new Core($this->formfielddata);
|
$core = new Core($this->formfielddata);
|
||||||
@@ -297,7 +300,7 @@ final class InstallCommand extends Command
|
|||||||
$json_output = [];
|
$json_output = [];
|
||||||
foreach ($fields['install']['sections'] as $section => $section_fields) {
|
foreach ($fields['install']['sections'] as $section => $section_fields) {
|
||||||
foreach ($section_fields['fields'] as $name => $field) {
|
foreach ($section_fields['fields'] as $name => $field) {
|
||||||
if ($name == 'system' || $name == 'manual_config') {
|
if ($name == 'system' || $name == 'manual_config' || $name == 'target_servername') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($field['type'] == 'text' || $field['type'] == 'email') {
|
if ($field['type'] == 'text' || $field['type'] == 'email') {
|
||||||
|
|||||||
@@ -62,6 +62,11 @@ final class MasterCron extends CliCommand
|
|||||||
$result = self::SUCCESS;
|
$result = self::SUCCESS;
|
||||||
$result = $this->validateRequirements($input, $output);
|
$result = $this->validateRequirements($input, $output);
|
||||||
|
|
||||||
|
if ($result != self::SUCCESS) {
|
||||||
|
// requirements failed, exit
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
$jobs = $input->getArgument('job');
|
$jobs = $input->getArgument('job');
|
||||||
|
|
||||||
// handle force option
|
// handle force option
|
||||||
@@ -111,8 +116,8 @@ final class MasterCron extends CliCommand
|
|||||||
]);
|
]);
|
||||||
$this->cronLog->setCronDebugFlag(defined('CRON_DEBUG_FLAG'));
|
$this->cronLog->setCronDebugFlag(defined('CRON_DEBUG_FLAG'));
|
||||||
|
|
||||||
// check whether there are actual tasks to perform by 'tasks'-cron so
|
// check whether there are actual tasks to perform by 'tasks'-cron, so
|
||||||
// we dont regenerate files unnecessarily
|
// we don't regenerate files unnecessarily
|
||||||
$tasks_cnt_stmt = Database::query("SELECT COUNT(*) as jobcnt FROM `panel_tasks`");
|
$tasks_cnt_stmt = Database::query("SELECT COUNT(*) as jobcnt FROM `panel_tasks`");
|
||||||
$tasks_cnt = $tasks_cnt_stmt->fetch(PDO::FETCH_ASSOC);
|
$tasks_cnt = $tasks_cnt_stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
|||||||
165
lib/Froxlor/Cli/ValidateAcmeWebroot.php
Normal file
165
lib/Froxlor/Cli/ValidateAcmeWebroot.php
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file is part of the Froxlor project.
|
||||||
|
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you can also view it online at
|
||||||
|
* https://files.froxlor.org/misc/COPYING.txt
|
||||||
|
*
|
||||||
|
* @copyright the authors
|
||||||
|
* @author Froxlor team <team@froxlor.org>
|
||||||
|
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Froxlor\Cli;
|
||||||
|
|
||||||
|
use Froxlor\Cron\TaskId;
|
||||||
|
use Froxlor\Database\Database;
|
||||||
|
use Froxlor\FileDir;
|
||||||
|
use Froxlor\Froxlor;
|
||||||
|
use Froxlor\Settings;
|
||||||
|
use Froxlor\System\Cronjob;
|
||||||
|
use PDO;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
final class ValidateAcmeWebroot extends CliCommand
|
||||||
|
{
|
||||||
|
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName('froxlor:validate-acme-webroot');
|
||||||
|
$this->setDescription('Validates the Le_Webroot value is correct for froxlor managed domains with Let\'s Encrypt certificate.');
|
||||||
|
$this->addOption('yes-to-all', 'A', InputOption::VALUE_NONE, 'Do not ask for confirmation, update files if necessary');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$result = self::SUCCESS;
|
||||||
|
|
||||||
|
$result = $this->validateRequirements($input, $output, true);
|
||||||
|
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
if ((int) Settings::Get('system.leenabled') == 0) {
|
||||||
|
$io->info("Let's Encrypt not activated in froxlor settings.");
|
||||||
|
$result = self::INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result == self::SUCCESS) {
|
||||||
|
$yestoall = $input->getOption('yes-to-all') !== false;
|
||||||
|
$helper = $this->getHelper('question');
|
||||||
|
$count_changes = 0;
|
||||||
|
// get all Let's Encrypt enabled domains
|
||||||
|
$sel_stmt = Database::prepare("SELECT id, domain FROM panel_domains WHERE `letsencrypt` = '1' AND aliasdomain IS NULL ORDER BY id ASC");
|
||||||
|
Database::pexecute($sel_stmt);
|
||||||
|
$domains = $sel_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
// check for froxlor-vhost
|
||||||
|
if (Settings::Get('system.le_froxlor_enabled') == '1') {
|
||||||
|
$domains[] = [
|
||||||
|
'id' => 0,
|
||||||
|
'domain' => Settings::Get('system.hostname')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$upd_stmt = Database::prepare("UPDATE domain_ssl_settings SET `validtodate`=NULL WHERE `domainid` = :did");
|
||||||
|
$acmesh_dir = dirname(Settings::Get('system.acmeshpath'));
|
||||||
|
$acmesh_challenge_dir = rtrim(FileDir::makeCorrectDir(Settings::Get('system.letsencryptchallengepath')), "/");
|
||||||
|
$recommended = rtrim(FileDir::makeCorrectDir(Froxlor::getInstallDir()), "/");
|
||||||
|
|
||||||
|
if ($acmesh_challenge_dir != $recommended) {
|
||||||
|
$io->warning([
|
||||||
|
"ACME challenge docroot from settings differs from the current installation directory.",
|
||||||
|
"Settings: '" . $acmesh_challenge_dir . "'",
|
||||||
|
"Default/recommended value: '" . $recommended . "'",
|
||||||
|
]);
|
||||||
|
$question = new ConfirmationQuestion('Fix ACME challenge docroot setting? [yes] ', true, '/^(y|j)/i');
|
||||||
|
if ($yestoall || $helper->ask($input, $output, $question)) {
|
||||||
|
Settings::Set('system.letsencryptchallengepath', $recommended);
|
||||||
|
$former_value = $acmesh_challenge_dir;
|
||||||
|
$acmesh_challenge_dir = $recommended;
|
||||||
|
// need to update the corresponding acme-alias config-file
|
||||||
|
$acme_alias_file = Settings::Get('system.letsencryptacmeconf');
|
||||||
|
$sed_params = "s@".$former_value."@" . $acmesh_challenge_dir . "@";
|
||||||
|
FileDir::safe_exec('sed -i -e "' . $sed_params . '" ' . escapeshellarg($acme_alias_file));
|
||||||
|
$count_changes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($domains as $domain_arr) {
|
||||||
|
$domain = $domain_arr['domain'];
|
||||||
|
$acme_domain_conf = FileDir::makeCorrectFile($acmesh_dir . '/' . $domain . '/' . $domain . '.conf');
|
||||||
|
if (file_exists($acme_domain_conf)) {
|
||||||
|
$io->text("Getting info from " . $acme_domain_conf);
|
||||||
|
$conf_content = file_get_contents($acme_domain_conf);
|
||||||
|
} else {
|
||||||
|
$acme_domain_conf = FileDir::makeCorrectFile($acmesh_dir . '/' . $domain . '_ecc/' . $domain . '.conf');
|
||||||
|
if (file_exists($acme_domain_conf)) {
|
||||||
|
$io->text("Getting info from " . $acme_domain_conf);
|
||||||
|
$conf_content = file_get_contents($acme_domain_conf);
|
||||||
|
} else {
|
||||||
|
$io->info("No domain configuration file found in '" . $acmesh_dir . "'");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($conf_content)) {
|
||||||
|
$lines = explode("\n", $conf_content);
|
||||||
|
foreach ($lines as $line) {
|
||||||
|
$val_key = explode("=", $line);
|
||||||
|
if ($val_key[0] == 'Le_Webroot') {
|
||||||
|
$domain_webroot = trim(trim($val_key[1], "'"), '"');
|
||||||
|
if ($domain_webroot != $acmesh_challenge_dir) {
|
||||||
|
$io->warning("Domain '" . $domain . "' has old/wrong Le_Webroot setting: '" . $domain_webroot . ' <> ' . $acmesh_challenge_dir . "'");
|
||||||
|
$question = new ConfirmationQuestion('Fix Le_Webroot? [yes] ', true, '/^(y|j)/i');
|
||||||
|
if ($yestoall || $helper->ask($input, $output, $question)) {
|
||||||
|
$sed_params = "s@Le_Webroot=.*@Le_Webroot='" . $acmesh_challenge_dir . "'@";
|
||||||
|
FileDir::safe_exec('sed -i -e "' . $sed_params . '" ' . escapeshellarg($acme_domain_conf));
|
||||||
|
Database::pexecute($upd_stmt, ['did' => $domain_arr['id']]);
|
||||||
|
$io->success("Correction of Le_Webroot successful");
|
||||||
|
$count_changes++;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$io->info("Domain '" . $domain . "' Le_Webroot value is correct");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($count_changes > 0) {
|
||||||
|
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
|
||||||
|
$io->info("Changes detected but froxlor has been updated. Inserting task to rebuild vhosts after update.");
|
||||||
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
|
} else {
|
||||||
|
$question = new ConfirmationQuestion('Changes detected. Force cronjob to refresh certificates? [yes] ', true, '/^(y|j)/i');
|
||||||
|
if ($yestoall || $helper->ask($input, $output, $question)) {
|
||||||
|
passthru(FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/bin/froxlor-cli') . ' froxlor:cron -f -d');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$io->success("No changes necessary.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -148,7 +148,7 @@ class ConfigDisplay
|
|||||||
if ($lasttype != '' && $lasttype != $_action['type']) {
|
if ($lasttype != '' && $lasttype != $_action['type']) {
|
||||||
$commands = trim($commands);
|
$commands = trim($commands);
|
||||||
$numbrows = count(explode("\n", $commands));
|
$numbrows = count(explode("\n", $commands));
|
||||||
$configpage .= UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', [
|
$configpage .= UI::twig()->render(UI::validateThemeTemplate('/settings/conf/command.html.twig', self::$theme), [
|
||||||
'commands' => $commands,
|
'commands' => $commands,
|
||||||
'numbrows' => $numbrows
|
'numbrows' => $numbrows
|
||||||
]);
|
]);
|
||||||
@@ -182,7 +182,7 @@ class ConfigDisplay
|
|||||||
$commands = trim($commands_pre);
|
$commands = trim($commands_pre);
|
||||||
if ($commands != "") {
|
if ($commands != "") {
|
||||||
$numbrows = count(explode("\n", $commands));
|
$numbrows = count(explode("\n", $commands));
|
||||||
$commands_pre = UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', [
|
$commands_pre = UI::twig()->render(UI::validateThemeTemplate('/settings/conf/command.html.twig', self::$theme), [
|
||||||
'commands' => $commands,
|
'commands' => $commands,
|
||||||
'numbrows' => $numbrows
|
'numbrows' => $numbrows
|
||||||
]);
|
]);
|
||||||
@@ -190,12 +190,12 @@ class ConfigDisplay
|
|||||||
$commands = trim($commands_post);
|
$commands = trim($commands_post);
|
||||||
if ($commands != "") {
|
if ($commands != "") {
|
||||||
$numbrows = count(explode("\n", $commands));
|
$numbrows = count(explode("\n", $commands));
|
||||||
$commands_post = UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', [
|
$commands_post = UI::twig()->render(UI::validateThemeTemplate('/settings/conf/command.html.twig', self::$theme), [
|
||||||
'commands' => $commands,
|
'commands' => $commands,
|
||||||
'numbrows' => $numbrows
|
'numbrows' => $numbrows
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
$configpage .= UI::twig()->render(self::$theme . '/settings/conf/fileblock.html.twig', [
|
$configpage .= UI::twig()->render(UI::validateThemeTemplate('/settings/conf/fileblock.html.twig', self::$theme), [
|
||||||
'realname' => $realname,
|
'realname' => $realname,
|
||||||
'commands_pre' => $commands_pre,
|
'commands_pre' => $commands_pre,
|
||||||
'commands_file' => $commands_file,
|
'commands_file' => $commands_file,
|
||||||
@@ -210,7 +210,7 @@ class ConfigDisplay
|
|||||||
$commands = trim($commands);
|
$commands = trim($commands);
|
||||||
if ($commands != '') {
|
if ($commands != '') {
|
||||||
$numbrows = count(explode("\n", $commands));
|
$numbrows = count(explode("\n", $commands));
|
||||||
$configpage .= UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', [
|
$configpage .= UI::twig()->render(UI::validateThemeTemplate('/settings/conf/command.html.twig', self::$theme), [
|
||||||
'commands' => $commands,
|
'commands' => $commands,
|
||||||
'numbrows' => $numbrows
|
'numbrows' => $numbrows
|
||||||
]);
|
]);
|
||||||
@@ -233,7 +233,7 @@ class ConfigDisplay
|
|||||||
$file_content = htmlspecialchars($file_content);
|
$file_content = htmlspecialchars($file_content);
|
||||||
$numbrows = count(explode("\n", $file_content));
|
$numbrows = count(explode("\n", $file_content));
|
||||||
//eval("\$files=\"" . \Froxlor\UI\Template::getTemplate("configfiles/configfiles_file") . "\";");
|
//eval("\$files=\"" . \Froxlor\UI\Template::getTemplate("configfiles/configfiles_file") . "\";");
|
||||||
$files = UI::twig()->render(self::$theme . '/settings/conf/file.html.twig', [
|
$files = UI::twig()->render(UI::validateThemeTemplate('/settings/conf/file.html.twig', self::$theme), [
|
||||||
'distro_editor' => self::$editor,
|
'distro_editor' => self::$editor,
|
||||||
'realname' => $realname,
|
'realname' => $realname,
|
||||||
'numbrows' => $numbrows,
|
'numbrows' => $numbrows,
|
||||||
|
|||||||
@@ -613,7 +613,10 @@ class Apache extends HttpConfigBase
|
|||||||
// Apply header
|
// Apply header
|
||||||
$this->virtualhosts_data[$vhosts_filename] = '# Domain ID: ' . $domain['id'] . ' - CustomerID: ' . $domain['customerid'] . ' - CustomerLogin: ' . $domain['loginname'] . "\n";
|
$this->virtualhosts_data[$vhosts_filename] = '# Domain ID: ' . $domain['id'] . ' - CustomerID: ' . $domain['customerid'] . ' - CustomerLogin: ' . $domain['loginname'] . "\n";
|
||||||
|
|
||||||
if ($domain['deactivated'] != '1' || Settings::Get('system.deactivateddocroot') != '') {
|
$ddr = Settings::Get('system.deactivateddocroot');
|
||||||
|
if (($domain['deactivated'] == '1' || $domain['customer_deactivated'] == '1') && empty($ddr)) {
|
||||||
|
$this->virtualhosts_data[$vhosts_filename] .= '# Customer/domain deactivated and a docroot for deactivated users hasn\'t been set.' . "\n";
|
||||||
|
} else {
|
||||||
// Create vhost without ssl
|
// Create vhost without ssl
|
||||||
$this->virtualhosts_data[$vhosts_filename] .= $this->getVhostContent($domain, false);
|
$this->virtualhosts_data[$vhosts_filename] .= $this->getVhostContent($domain, false);
|
||||||
|
|
||||||
@@ -623,8 +626,6 @@ class Apache extends HttpConfigBase
|
|||||||
$this->virtualhosts_data[$vhosts_filename_ssl] = '# Domain ID: ' . $domain['id'] . ' (SSL) - CustomerID: ' . $domain['customerid'] . ' - CustomerLogin: ' . $domain['loginname'] . "\n";
|
$this->virtualhosts_data[$vhosts_filename_ssl] = '# Domain ID: ' . $domain['id'] . ' (SSL) - CustomerID: ' . $domain['customerid'] . ' - CustomerLogin: ' . $domain['loginname'] . "\n";
|
||||||
$this->virtualhosts_data[$vhosts_filename_ssl] .= $this->getVhostContent($domain, true);
|
$this->virtualhosts_data[$vhosts_filename_ssl] .= $this->getVhostContent($domain, true);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$this->virtualhosts_data[$vhosts_filename] .= '# Customer deactivated and a docroot for deactivated users hasn\'t been set.' . "\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -840,6 +841,8 @@ class Apache extends HttpConfigBase
|
|||||||
$domain['documentroot'] = trim($domain['documentroot']);
|
$domain['documentroot'] = trim($domain['documentroot']);
|
||||||
|
|
||||||
if (preg_match('/^https?\:\/\//', $domain['documentroot'])) {
|
if (preg_match('/^https?\:\/\//', $domain['documentroot'])) {
|
||||||
|
$possible_deactivated_webroot = $this->getWebroot($domain);
|
||||||
|
if ($this->deactivated == false) {
|
||||||
$corrected_docroot = $domain['documentroot'];
|
$corrected_docroot = $domain['documentroot'];
|
||||||
|
|
||||||
// Get domain's redirect code
|
// Get domain's redirect code
|
||||||
@@ -863,6 +866,9 @@ class Apache extends HttpConfigBase
|
|||||||
$vhost_content .= ' <IfModule !mod_rewrite.c>' . "\n";
|
$vhost_content .= ' <IfModule !mod_rewrite.c>' . "\n";
|
||||||
$vhost_content .= ' Redirect ' . $code . ' / ' . $domain['documentroot_norewrite'] . "\n";
|
$vhost_content .= ' Redirect ' . $code . ' / ' . $domain['documentroot_norewrite'] . "\n";
|
||||||
$vhost_content .= ' </IfModule>' . "\n";
|
$vhost_content .= ' </IfModule>' . "\n";
|
||||||
|
} elseif (Settings::Get('system.deactivateddocroot') != '') {
|
||||||
|
$vhost_content .= $possible_deactivated_webroot;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
FileDir::mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true, true);
|
FileDir::mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true, true);
|
||||||
$vhost_content .= $this->getWebroot($domain);
|
$vhost_content .= $this->getWebroot($domain);
|
||||||
@@ -952,8 +958,8 @@ class Apache extends HttpConfigBase
|
|||||||
$domain['customerroot'] = FileDir::makeCorrectDir($domain['customerroot']);
|
$domain['customerroot'] = FileDir::makeCorrectDir($domain['customerroot']);
|
||||||
$domain['documentroot'] = FileDir::makeCorrectDir($domain['documentroot']);
|
$domain['documentroot'] = FileDir::makeCorrectDir($domain['documentroot']);
|
||||||
|
|
||||||
if ($domain['deactivated'] == '1' && Settings::Get('system.deactivateddocroot') != '') {
|
if (($domain['deactivated'] == '1' || $domain['customer_deactivated'] == '1') && Settings::Get('system.deactivateddocroot') != '') {
|
||||||
$webroot_text .= ' # Using docroot for deactivated users...' . "\n";
|
$webroot_text .= ' # Using docroot for deactivated users/domains...' . "\n";
|
||||||
$webroot_text .= ' DocumentRoot "' . rtrim(FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')), "/") . "\"\n";
|
$webroot_text .= ' DocumentRoot "' . rtrim(FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')), "/") . "\"\n";
|
||||||
$webroot_text .= ' <Directory "' . FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')) . '">' . "\n";
|
$webroot_text .= ' <Directory "' . FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')) . '">' . "\n";
|
||||||
// >=apache-2.4 enabled?
|
// >=apache-2.4 enabled?
|
||||||
@@ -1034,6 +1040,10 @@ class Apache extends HttpConfigBase
|
|||||||
|
|
||||||
$statTool = Settings::Get('system.traffictool');
|
$statTool = Settings::Get('system.traffictool');
|
||||||
$statDomain = "";
|
$statDomain = "";
|
||||||
|
if ($statTool == 'awstats') {
|
||||||
|
// awstats generates for each domain regardless of speciallogfile
|
||||||
|
$statDomain = "/" . $domain['domain'];
|
||||||
|
}
|
||||||
if ($domain['speciallogfile'] == '1') {
|
if ($domain['speciallogfile'] == '1') {
|
||||||
$statDomain = "/" . (($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']);
|
$statDomain = "/" . (($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,6 +126,9 @@ class ApacheFcgi extends Apache
|
|||||||
|
|
||||||
// mod_proxy stuff for apache-2.4
|
// mod_proxy stuff for apache-2.4
|
||||||
if (Settings::Get('system.apache24') == '1' && Settings::Get('phpfpm.use_mod_proxy') == '1') {
|
if (Settings::Get('system.apache24') == '1' && Settings::Get('phpfpm.use_mod_proxy') == '1') {
|
||||||
|
|
||||||
|
$php_options_text .= ' <Directory "' . FileDir::makeCorrectDir($domain['documentroot']) . '">' . "\n";
|
||||||
|
|
||||||
$filesmatch = $phpconfig['fpm_settings']['limit_extensions'];
|
$filesmatch = $phpconfig['fpm_settings']['limit_extensions'];
|
||||||
$extensions = explode(" ", $filesmatch);
|
$extensions = explode(" ", $filesmatch);
|
||||||
$filesmatch = "";
|
$filesmatch = "";
|
||||||
@@ -141,23 +144,19 @@ class ApacheFcgi extends Apache
|
|||||||
$php_options_text .= ' </FilesMatch>' . "\n";
|
$php_options_text .= ' </FilesMatch>' . "\n";
|
||||||
|
|
||||||
$mypath_dir = new Directory($domain['documentroot']);
|
$mypath_dir = new Directory($domain['documentroot']);
|
||||||
|
// only create the "require all granted" directive if there is no active directory-protection
|
||||||
// only create the require all granted if there is not active directory-protection
|
|
||||||
// for this path, as this would be the first require and therefore grant all access
|
// for this path, as this would be the first require and therefore grant all access
|
||||||
if ($mypath_dir->isUserProtected() == false) {
|
if ($mypath_dir->isUserProtected() == false) {
|
||||||
$php_options_text .= ' <Directory "' . FileDir::makeCorrectDir($domain['documentroot']) . '">' . "\n";
|
|
||||||
if ($phpconfig['pass_authorizationheader'] == '1') {
|
if ($phpconfig['pass_authorizationheader'] == '1') {
|
||||||
$php_options_text .= ' CGIPassAuth On' . "\n";
|
$php_options_text .= ' CGIPassAuth On' . "\n";
|
||||||
}
|
}
|
||||||
$php_options_text .= ' Require all granted' . "\n";
|
$php_options_text .= ' Require all granted' . "\n";
|
||||||
$php_options_text .= ' AllowOverride All' . "\n";
|
$php_options_text .= ' AllowOverride All' . "\n";
|
||||||
$php_options_text .= ' </Directory>' . "\n";
|
|
||||||
} elseif ($phpconfig['pass_authorizationheader'] == '1') {
|
} elseif ($phpconfig['pass_authorizationheader'] == '1') {
|
||||||
// allow Pass of Authorization header
|
// allow Pass of Authorization header
|
||||||
$php_options_text .= ' <Directory "' . FileDir::makeCorrectDir($domain['documentroot']) . '">' . "\n";
|
|
||||||
$php_options_text .= ' CGIPassAuth On' . "\n";
|
$php_options_text .= ' CGIPassAuth On' . "\n";
|
||||||
$php_options_text .= ' </Directory>' . "\n";
|
|
||||||
}
|
}
|
||||||
|
$php_options_text .= ' </Directory>' . "\n";
|
||||||
} else {
|
} else {
|
||||||
$addheader = "";
|
$addheader = "";
|
||||||
if ($phpconfig['pass_authorizationheader'] == '1') {
|
if ($phpconfig['pass_authorizationheader'] == '1') {
|
||||||
@@ -196,6 +195,9 @@ class ApacheFcgi extends Apache
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$php_options_text .= ' FcgidIdleTimeout ' . Settings::Get('system.mod_fcgid_idle_timeout') . "\n";
|
$php_options_text .= ' FcgidIdleTimeout ' . Settings::Get('system.mod_fcgid_idle_timeout') . "\n";
|
||||||
|
if ($phpconfig['pass_authorizationheader'] == '1') {
|
||||||
|
$php_options_text .= ' FcgidPassHeader Authorization' . "\n";
|
||||||
|
}
|
||||||
if ((int)Settings::Get('system.mod_fcgid_wrapper') == 0) {
|
if ((int)Settings::Get('system.mod_fcgid_wrapper') == 0) {
|
||||||
$php_options_text .= ' SuexecUserGroup "' . $domain['loginname'] . '" "' . $domain['loginname'] . '"' . "\n";
|
$php_options_text .= ' SuexecUserGroup "' . $domain['loginname'] . '" "' . $domain['loginname'] . '"' . "\n";
|
||||||
$php_options_text .= ' ScriptAlias /php/ ' . $php->getInterface()->getConfigDir() . "\n";
|
$php_options_text .= ' ScriptAlias /php/ ' . $php->getInterface()->getConfigDir() . "\n";
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ class HttpConfigBase
|
|||||||
$froxlor_ssl_settings_stmt = Database::prepare("
|
$froxlor_ssl_settings_stmt = Database::prepare("
|
||||||
SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
|
SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
|
||||||
WHERE `domainid` = '0' AND
|
WHERE `domainid` = '0' AND
|
||||||
(`expirationdate` < DATE_ADD(NOW(), INTERVAL 30 DAY) OR `expirationdate` IS NULL)
|
(`validtodate` < DATE_ADD(NOW(), INTERVAL 30 DAY) OR `validtodate` IS NULL)
|
||||||
");
|
");
|
||||||
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
|
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
|
||||||
if ($froxlor_ssl && !empty($froxlor_ssl['ssl_cert_file'])) {
|
if ($froxlor_ssl && !empty($froxlor_ssl['ssl_cert_file'])) {
|
||||||
|
|||||||
@@ -46,7 +46,9 @@ class AcmeSh extends FroxlorCron
|
|||||||
'letsencrypt_test' => "https://acme-staging-v02.api.letsencrypt.org/directory",
|
'letsencrypt_test' => "https://acme-staging-v02.api.letsencrypt.org/directory",
|
||||||
'buypass' => "https://api.buypass.com/acme/directory",
|
'buypass' => "https://api.buypass.com/acme/directory",
|
||||||
'buypass_test' => "https://api.test4.buypass.no/acme/directory",
|
'buypass_test' => "https://api.test4.buypass.no/acme/directory",
|
||||||
'zerossl' => "https://acme.zerossl.com/v2/DV90"
|
'zerossl' => "https://acme.zerossl.com/v2/DV90",
|
||||||
|
'google' => "https://dv.acme-v02.api.pki.goog/directory",
|
||||||
|
'google_test' => "https://dv.acme-v02.test-api.pki.goog/directory",
|
||||||
];
|
];
|
||||||
public static $no_inserttask = false;
|
public static $no_inserttask = false;
|
||||||
private static $apiserver = "";
|
private static $apiserver = "";
|
||||||
@@ -112,7 +114,9 @@ class AcmeSh extends FroxlorCron
|
|||||||
`ssl_cert_chainfile` = :chain,
|
`ssl_cert_chainfile` = :chain,
|
||||||
`ssl_csr_file` = :csr,
|
`ssl_csr_file` = :csr,
|
||||||
`ssl_fullchain_file` = :fullchain,
|
`ssl_fullchain_file` = :fullchain,
|
||||||
`expirationdate` = :expirationdate
|
`validfromdate` = :validfromdate,
|
||||||
|
`validtodate` = :validtodate,
|
||||||
|
`issuer` = :issuer
|
||||||
");
|
");
|
||||||
|
|
||||||
// prepare domain update sql
|
// prepare domain update sql
|
||||||
@@ -134,7 +138,9 @@ class AcmeSh extends FroxlorCron
|
|||||||
'lepublickey' => Settings::Get('system.lepublickey'),
|
'lepublickey' => Settings::Get('system.lepublickey'),
|
||||||
'leregistered' => Settings::Get('system.leregistered'),
|
'leregistered' => Settings::Get('system.leregistered'),
|
||||||
'ssl_redirect' => Settings::Get('system.le_froxlor_redirect'),
|
'ssl_redirect' => Settings::Get('system.le_froxlor_redirect'),
|
||||||
'expirationdate' => null,
|
'validfromdate' => null,
|
||||||
|
'validtodate' => null,
|
||||||
|
'issuer' => "",
|
||||||
'ssl_cert_file' => null,
|
'ssl_cert_file' => null,
|
||||||
'ssl_key_file' => null,
|
'ssl_key_file' => null,
|
||||||
'ssl_ca_file' => null,
|
'ssl_ca_file' => null,
|
||||||
@@ -169,7 +175,9 @@ class AcmeSh extends FroxlorCron
|
|||||||
'lepublickey' => Settings::Get('system.lepublickey'),
|
'lepublickey' => Settings::Get('system.lepublickey'),
|
||||||
'leregistered' => Settings::Get('system.leregistered'),
|
'leregistered' => Settings::Get('system.leregistered'),
|
||||||
'ssl_redirect' => Settings::Get('system.le_froxlor_redirect'),
|
'ssl_redirect' => Settings::Get('system.le_froxlor_redirect'),
|
||||||
'expirationdate' => is_array($renew_froxlor) ? $renew_froxlor['expirationdate'] : date('Y-m-d H:i:s', 0),
|
'validfromdate' => is_array($renew_froxlor) ? $renew_froxlor['validfromdate'] : date('Y-m-d H:i:s', 0),
|
||||||
|
'validtodate' => is_array($renew_froxlor) ? $renew_froxlor['validtodate'] : date('Y-m-d H:i:s', 0),
|
||||||
|
'issuer' => is_array($renew_froxlor) ? $renew_froxlor['issuer'] : "",
|
||||||
'ssl_cert_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_cert_file'] : null,
|
'ssl_cert_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_cert_file'] : null,
|
||||||
'ssl_key_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_key_file'] : null,
|
'ssl_key_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_key_file'] : null,
|
||||||
'ssl_ca_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_ca_file'] : null,
|
'ssl_ca_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_ca_file'] : null,
|
||||||
@@ -185,7 +193,7 @@ class AcmeSh extends FroxlorCron
|
|||||||
'loginname' => $domain['loginname'],
|
'loginname' => $domain['loginname'],
|
||||||
'adminsession' => 0
|
'adminsession' => 0
|
||||||
]);
|
]);
|
||||||
if (defined('CRON_IS_FORCED') || self::checkFsFilesAreNewer($domain['domain'], $domain['expirationdate'])) {
|
if (defined('CRON_IS_FORCED') || self::checkFsFilesAreNewer($domain['domain'], $domain['validtodate'])) {
|
||||||
self::certToDb($domain, $cronlog, []);
|
self::certToDb($domain, $cronlog, []);
|
||||||
$changedetected = 1;
|
$changedetected = 1;
|
||||||
}
|
}
|
||||||
@@ -219,16 +227,21 @@ class AcmeSh extends FroxlorCron
|
|||||||
");
|
");
|
||||||
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
|
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
|
||||||
// also check for possible existing certificate
|
// also check for possible existing certificate
|
||||||
if (!$froxlor_ssl && !self::checkFsFilesAreNewer(Settings::Get('system.hostname'), date('Y-m-d H:i:s'))) {
|
if (($froxlor_ssl && empty($froxlor_ssl['validtodate']))
|
||||||
|
|| (!$froxlor_ssl && !self::checkFsFilesAreNewer(Settings::Get('system.hostname'), date('Y-m-d H:i:s')))
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function checkFsFilesAreNewer($domain, $cert_date = 0)
|
private static function checkFsFilesAreNewer($domain, $cert_date = 0): bool
|
||||||
{
|
{
|
||||||
$certificate_folder = self::getWorkingDirFromEnv(strtolower($domain));
|
$certificate_folder = self::getCertificateFolder(strtolower($domain));
|
||||||
|
if (empty($certificate_folder)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$ssl_file = FileDir::makeCorrectFile($certificate_folder . '/' . strtolower($domain) . '.cer');
|
$ssl_file = FileDir::makeCorrectFile($certificate_folder . '/' . strtolower($domain) . '.cer');
|
||||||
|
|
||||||
if (is_dir($certificate_folder) && file_exists($ssl_file) && is_readable($ssl_file)) {
|
if (is_dir($certificate_folder) && file_exists($ssl_file) && is_readable($ssl_file)) {
|
||||||
@@ -240,9 +253,13 @@ class AcmeSh extends FroxlorCron
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getWorkingDirFromEnv($domain = "", $forced_noecc = false)
|
public static function getWorkingDirFromEnv($domain = "", $forced_ecc = false): string
|
||||||
{
|
{
|
||||||
if (Settings::Get('system.leecc') > 0 && !$forced_noecc) {
|
// first try without _ecc either if it's enabled currently or not as
|
||||||
|
// it might have been at some point so there is a chance we have certificates
|
||||||
|
// with and without _ecc - the method getCertificateFolder() will check both
|
||||||
|
// possibilities
|
||||||
|
if ($forced_ecc) {
|
||||||
$domain .= "_ecc";
|
$domain .= "_ecc";
|
||||||
}
|
}
|
||||||
$env_file = FileDir::makeCorrectFile(dirname(self::getAcmeSh()) . '/acme.sh.env');
|
$env_file = FileDir::makeCorrectFile(dirname(self::getAcmeSh()) . '/acme.sh.env');
|
||||||
@@ -252,7 +269,7 @@ class AcmeSh extends FroxlorCron
|
|||||||
cut -d'"' -f2
|
cut -d'"' -f2
|
||||||
EOC;
|
EOC;
|
||||||
exec('grep "LE_WORKING_DIR" ' . escapeshellarg($env_file) . ' | ' . $cut, $output);
|
exec('grep "LE_WORKING_DIR" ' . escapeshellarg($env_file) . ' | ' . $cut, $output);
|
||||||
if (is_array($output) && !empty($output) && isset($output[0]) && !empty($output[0])) {
|
if (is_array($output) && !empty($output) && !empty($output[0])) {
|
||||||
return FileDir::makeCorrectDir($output[0] . "/" . $domain);
|
return FileDir::makeCorrectDir($output[0] . "/" . $domain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -277,7 +294,9 @@ EOC;
|
|||||||
SELECT
|
SELECT
|
||||||
domssl.`id`,
|
domssl.`id`,
|
||||||
domssl.`domainid`,
|
domssl.`domainid`,
|
||||||
domssl.`expirationdate`,
|
domssl.`validfromdate`,
|
||||||
|
domssl.`validtodate`,
|
||||||
|
domssl.`issuer`,
|
||||||
domssl.`ssl_cert_file`,
|
domssl.`ssl_cert_file`,
|
||||||
domssl.`ssl_key_file`,
|
domssl.`ssl_key_file`,
|
||||||
domssl.`ssl_ca_file`,
|
domssl.`ssl_ca_file`,
|
||||||
@@ -304,7 +323,7 @@ EOC;
|
|||||||
AND dom.`letsencrypt` = 1
|
AND dom.`letsencrypt` = 1
|
||||||
AND dom.`aliasdomain` IS NULL
|
AND dom.`aliasdomain` IS NULL
|
||||||
AND dom.`iswildcarddomain` = 0
|
AND dom.`iswildcarddomain` = 0
|
||||||
AND domssl.`expirationdate` IS NULL
|
AND domssl.`validtodate` IS NULL
|
||||||
");
|
");
|
||||||
$customer_ssl = $certificates_stmt->fetchAll(PDO::FETCH_ASSOC);
|
$customer_ssl = $certificates_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
if ($customer_ssl) {
|
if ($customer_ssl) {
|
||||||
@@ -328,7 +347,7 @@ EOC;
|
|||||||
");
|
");
|
||||||
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
|
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
|
||||||
// also check for possible existing certificate
|
// also check for possible existing certificate
|
||||||
if ($froxlor_ssl && self::checkFsFilesAreNewer(Settings::Get('system.hostname'), $froxlor_ssl['expirationdate'])) {
|
if ($froxlor_ssl && self::checkFsFilesAreNewer(Settings::Get('system.hostname'), $froxlor_ssl['validtodate'])) {
|
||||||
return $froxlor_ssl;
|
return $froxlor_ssl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,7 +363,9 @@ EOC;
|
|||||||
SELECT
|
SELECT
|
||||||
domssl.`id`,
|
domssl.`id`,
|
||||||
domssl.`domainid`,
|
domssl.`domainid`,
|
||||||
domssl.`expirationdate`,
|
domssl.`validfromdate`,
|
||||||
|
domssl.`validtodate`,
|
||||||
|
domssl.`issuer`,
|
||||||
domssl.`ssl_cert_file`,
|
domssl.`ssl_cert_file`,
|
||||||
domssl.`ssl_key_file`,
|
domssl.`ssl_key_file`,
|
||||||
dom.`domain`,
|
dom.`domain`,
|
||||||
@@ -368,7 +389,7 @@ EOC;
|
|||||||
if ($renew_certs) {
|
if ($renew_certs) {
|
||||||
if ($check) {
|
if ($check) {
|
||||||
foreach ($renew_certs as $cert) {
|
foreach ($renew_certs as $cert) {
|
||||||
if (self::checkFsFilesAreNewer($cert['domain'], $cert['expirationdate'])) {
|
if (self::checkFsFilesAreNewer($cert['domain'], $cert['validtodate'])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -451,7 +472,7 @@ EOC;
|
|||||||
// Only issue let's encrypt certificate if no broken ssl_redirect is enabled
|
// Only issue let's encrypt certificate if no broken ssl_redirect is enabled
|
||||||
if ($certrow['ssl_redirect'] != 2) {
|
if ($certrow['ssl_redirect'] != 2) {
|
||||||
$do_force = false;
|
$do_force = false;
|
||||||
if (!empty($certrow['ssl_cert_file']) && empty($certrow['expirationdate'])) {
|
if (!empty($certrow['ssl_cert_file']) && empty($certrow['validtodate'])) {
|
||||||
// domain changed (SAN or similar)
|
// domain changed (SAN or similar)
|
||||||
$do_force = true;
|
$do_force = true;
|
||||||
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Re-creating certificate for " . $certrow['domain']);
|
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Re-creating certificate for " . $certrow['domain']);
|
||||||
@@ -519,7 +540,7 @@ EOC;
|
|||||||
foreach ($loop_domains as $idx => $domain) {
|
foreach ($loop_domains as $idx => $domain) {
|
||||||
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Validating DNS of " . $domain);
|
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Validating DNS of " . $domain);
|
||||||
// ips according to NS
|
// ips according to NS
|
||||||
$domain_ips = PhpHelper::gethostbynamel6($domain);
|
$domain_ips = PhpHelper::gethostbynamel6($domain, true, Settings::Get('system.le_domain_dnscheck_resolver'));
|
||||||
if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) {
|
if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) {
|
||||||
// no common ips...
|
// no common ips...
|
||||||
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $domain . " due to no system known IP address via DNS check");
|
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $domain . " due to no system known IP address via DNS check");
|
||||||
@@ -555,7 +576,7 @@ EOC;
|
|||||||
if (Settings::Get('system.letsencryptreuseold') != '1') {
|
if (Settings::Get('system.letsencryptreuseold') != '1') {
|
||||||
$acmesh_cmd .= " --always-force-new-domain-key";
|
$acmesh_cmd .= " --always-force-new-domain-key";
|
||||||
}
|
}
|
||||||
if (Settings::Get('system.letsencryptca') == 'letsencrypt_test') {
|
if (substr(Settings::Get('system.letsencryptca'), -5) == '_test') {
|
||||||
$acmesh_cmd .= " --staging";
|
$acmesh_cmd .= " --staging";
|
||||||
}
|
}
|
||||||
if ($force) {
|
if ($force) {
|
||||||
@@ -592,7 +613,9 @@ EOC;
|
|||||||
'chain' => $return['chain'],
|
'chain' => $return['chain'],
|
||||||
'csr' => $return['csr'],
|
'csr' => $return['csr'],
|
||||||
'fullchain' => $return['fullchain'],
|
'fullchain' => $return['fullchain'],
|
||||||
'expirationdate' => date('Y-m-d H:i:s', $newcert['validTo_time_t'])
|
'validfromdate' => date('Y-m-d H:i:s', $newcert['validFrom_time_t']),
|
||||||
|
'validtodate' => date('Y-m-d H:i:s', $newcert['validTo_time_t']),
|
||||||
|
'issuer' => $newcert['issuer']['O'] ?? ""
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($certrow['ssl_redirect'] == 3) {
|
if ($certrow['ssl_redirect'] == 3) {
|
||||||
@@ -619,35 +642,21 @@ EOC;
|
|||||||
*/
|
*/
|
||||||
private static function readCertificateToVar($domain, &$return, &$cronlog)
|
private static function readCertificateToVar($domain, &$return, &$cronlog)
|
||||||
{
|
{
|
||||||
$certificate_folder = self::getWorkingDirFromEnv($domain);
|
$certificate_folder = self::getCertificateFolder($domain);
|
||||||
$certificate_folder_noecc = null;
|
|
||||||
if (Settings::Get('system.leecc') > 0) {
|
|
||||||
$certificate_folder_noecc = self::getWorkingDirFromEnv($domain, true);
|
|
||||||
}
|
|
||||||
$certificate_folder = FileDir::makeCorrectDir($certificate_folder);
|
|
||||||
|
|
||||||
if (is_dir($certificate_folder) || is_dir($certificate_folder_noecc)) {
|
if (!empty($certificate_folder)) {
|
||||||
foreach (
|
$certificate_files = [
|
||||||
[
|
|
||||||
'crt' => $domain . '.cer',
|
'crt' => $domain . '.cer',
|
||||||
'key' => $domain . '.key',
|
'key' => $domain . '.key',
|
||||||
'chain' => 'ca.cer',
|
'chain' => 'ca.cer',
|
||||||
'fullchain' => 'fullchain.cer',
|
'fullchain' => 'fullchain.cer',
|
||||||
'csr' => $domain . '.csr'
|
'csr' => $domain . '.csr'
|
||||||
] as $index => $sslfile
|
];
|
||||||
) {
|
foreach ($certificate_files as $index => $sslfile) {
|
||||||
$ssl_file = FileDir::makeCorrectFile($certificate_folder . '/' . $sslfile);
|
$ssl_file = FileDir::makeCorrectFile($certificate_folder . '/' . $sslfile);
|
||||||
if (file_exists($ssl_file)) {
|
if (file_exists($ssl_file)) {
|
||||||
$return[$index] = file_get_contents($ssl_file);
|
$return[$index] = file_get_contents($ssl_file);
|
||||||
} else {
|
} else {
|
||||||
if (!empty($certificate_folder_noecc)) {
|
|
||||||
$ssl_file_fb = FileDir::makeCorrectFile($certificate_folder_noecc . '/' . $sslfile);
|
|
||||||
if (file_exists($ssl_file_fb)) {
|
|
||||||
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "ECC certificates activated but found only non-ecc file");
|
|
||||||
$return[$index] = file_get_contents($ssl_file_fb);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not find file '" . $sslfile . "' in '" . $certificate_folder . "'");
|
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not find file '" . $sslfile . "' in '" . $certificate_folder . "'");
|
||||||
$return[$index] = null;
|
$return[$index] = null;
|
||||||
}
|
}
|
||||||
@@ -656,4 +665,18 @@ EOC;
|
|||||||
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not find certificate-folder '" . $certificate_folder . "'");
|
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not find certificate-folder '" . $certificate_folder . "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function getCertificateFolder(string $domain): string
|
||||||
|
{
|
||||||
|
$certificate_folder = self::getWorkingDirFromEnv(strtolower($domain));
|
||||||
|
if (file_exists($certificate_folder)) {
|
||||||
|
return $certificate_folder;
|
||||||
|
}
|
||||||
|
$certificate_folder_ecc = self::getWorkingDirFromEnv($domain, true);
|
||||||
|
if (file_exists($certificate_folder_ecc)) {
|
||||||
|
return $certificate_folder_ecc;
|
||||||
|
}
|
||||||
|
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not find certificate-folder for domain '" . $domain . "'");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -414,6 +414,8 @@ class Lighttpd extends HttpConfigBase
|
|||||||
$domain['documentroot'] = trim($domain['documentroot']);
|
$domain['documentroot'] = trim($domain['documentroot']);
|
||||||
|
|
||||||
if (preg_match('/^https?\:\/\//', $domain['documentroot'])) {
|
if (preg_match('/^https?\:\/\//', $domain['documentroot'])) {
|
||||||
|
$possible_deactivated_webroot = $this->getWebroot($domain);
|
||||||
|
if ($this->deactivated == false) {
|
||||||
$uri = $domain['documentroot'];
|
$uri = $domain['documentroot'];
|
||||||
|
|
||||||
// Get domain's redirect code
|
// Get domain's redirect code
|
||||||
@@ -423,6 +425,9 @@ class Lighttpd extends HttpConfigBase
|
|||||||
$vhost_content .= ' url.redirect = (' . "\n";
|
$vhost_content .= ' url.redirect = (' . "\n";
|
||||||
$vhost_content .= ' "^/(.*)$" => "' . $uri . '$1"' . "\n";
|
$vhost_content .= ' "^/(.*)$" => "' . $uri . '$1"' . "\n";
|
||||||
$vhost_content .= ' )' . "\n";
|
$vhost_content .= ' )' . "\n";
|
||||||
|
} elseif (Settings::Get('system.deactivateddocroot') != '') {
|
||||||
|
$vhost_content .= $possible_deactivated_webroot;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
FileDir::mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true, true);
|
FileDir::mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true, true);
|
||||||
|
|
||||||
@@ -562,12 +567,12 @@ class Lighttpd extends HttpConfigBase
|
|||||||
return $servernames_text;
|
return $servernames_text;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getWebroot($domain, $ssl)
|
protected function getWebroot($domain, bool $ssl = false)
|
||||||
{
|
{
|
||||||
$webroot_text = '';
|
$webroot_text = '';
|
||||||
|
|
||||||
if ($domain['deactivated'] == '1' && Settings::Get('system.deactivateddocroot') != '') {
|
if (($domain['deactivated'] == '1' || $domain['customer_deactivated'] == '1') && Settings::Get('system.deactivateddocroot') != '') {
|
||||||
$webroot_text .= ' # Using docroot for deactivated users...' . "\n";
|
$webroot_text .= ' # Using docroot for deactivated users/domains...' . "\n";
|
||||||
$webroot_text .= ' server.document-root = "' . FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')) . "\"\n";
|
$webroot_text .= ' server.document-root = "' . FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')) . "\"\n";
|
||||||
$this->deactivated = true;
|
$this->deactivated = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -719,6 +724,10 @@ class Lighttpd extends HttpConfigBase
|
|||||||
|
|
||||||
$statTool = Settings::Get('system.traffictool');
|
$statTool = Settings::Get('system.traffictool');
|
||||||
$statDomain = "";
|
$statDomain = "";
|
||||||
|
if ($statTool == 'awstats') {
|
||||||
|
// awstats generates for each domain regardless of speciallogfile
|
||||||
|
$statDomain = "/" . $domain['domain'];
|
||||||
|
}
|
||||||
if ($domain['speciallogfile'] == '1') {
|
if ($domain['speciallogfile'] == '1') {
|
||||||
$statDomain = "/" . (($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']);
|
$statDomain = "/" . (($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ class Nginx extends HttpConfigBase
|
|||||||
$this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n";
|
$this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n";
|
||||||
|
|
||||||
// protect bin/
|
// protect bin/
|
||||||
$this->nginx_data[$vhost_filename] .= "\t" . 'location ~ ' . rtrim($relpath, "/") . '/(bin|cache|logs|tests|vendor) {' . "\n";
|
$this->nginx_data[$vhost_filename] .= "\t" . 'location ~ ^' . rtrim($relpath, "/") . '/(bin|cache|logs|tests|vendor) {' . "\n";
|
||||||
$this->nginx_data[$vhost_filename] .= "\t" . ' deny all;' . "\n";
|
$this->nginx_data[$vhost_filename] .= "\t" . ' deny all;' . "\n";
|
||||||
$this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n";
|
$this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n";
|
||||||
}
|
}
|
||||||
@@ -493,10 +493,10 @@ class Nginx extends HttpConfigBase
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// check whether the customer is deactivated and NO docroot for deactivated users has been set#
|
// check whether the customer/domain is deactivated and NO docroot for deactivated users has been set#
|
||||||
$ddr = Settings::Get('system.deactivateddocroot');
|
$ddr = Settings::Get('system.deactivateddocroot');
|
||||||
if ($domain['deactivated'] == '1' && empty($ddr)) {
|
if (($domain['deactivated'] == '1' || $domain['customer_deactivated'] == '1') && empty($ddr)) {
|
||||||
return '# Customer deactivated and a docroot for deactivated users hasn\'t been set.' . "\n";
|
return '# Customer deactivated and a docroot for deactivated users/domains hasn\'t been set.' . "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
$vhost_content = '';
|
$vhost_content = '';
|
||||||
@@ -596,6 +596,8 @@ class Nginx extends HttpConfigBase
|
|||||||
|
|
||||||
// if the documentroot is an URL we just redirect
|
// if the documentroot is an URL we just redirect
|
||||||
if (preg_match('/^https?\:\/\//', $domain['documentroot'])) {
|
if (preg_match('/^https?\:\/\//', $domain['documentroot'])) {
|
||||||
|
$possible_deactivated_webroot = $this->getWebroot($domain);
|
||||||
|
if ($this->deactivated == false) {
|
||||||
$uri = $domain['documentroot'];
|
$uri = $domain['documentroot'];
|
||||||
if (substr($uri, -1) == '/') {
|
if (substr($uri, -1) == '/') {
|
||||||
$uri = substr($uri, 0, -1);
|
$uri = substr($uri, 0, -1);
|
||||||
@@ -607,11 +609,14 @@ class Nginx extends HttpConfigBase
|
|||||||
$vhost_content .= "\t" . 'location / {' . "\n";
|
$vhost_content .= "\t" . 'location / {' . "\n";
|
||||||
$vhost_content .= "\t\t" . 'return ' . $code . ' ' . $uri . '$request_uri;' . "\n";
|
$vhost_content .= "\t\t" . 'return ' . $code . ' ' . $uri . '$request_uri;' . "\n";
|
||||||
$vhost_content .= "\t" . '}' . "\n";
|
$vhost_content .= "\t" . '}' . "\n";
|
||||||
|
} elseif (Settings::Get('system.deactivateddocroot') != '') {
|
||||||
|
$vhost_content .= $possible_deactivated_webroot;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
FileDir::mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true);
|
FileDir::mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true);
|
||||||
|
|
||||||
$vhost_content .= $this->getLogFiles($domain);
|
$vhost_content .= $this->getLogFiles($domain);
|
||||||
$vhost_content .= $this->getWebroot($domain, $ssl_vhost);
|
$vhost_content .= $this->getWebroot($domain);
|
||||||
|
|
||||||
if ($this->deactivated == false) {
|
if ($this->deactivated == false) {
|
||||||
$vhost_content = $this->mergeVhostCustom($vhost_content, $this->createPathOptions($domain)) . "\n";
|
$vhost_content = $this->mergeVhostCustom($vhost_content, $this->createPathOptions($domain)) . "\n";
|
||||||
@@ -770,12 +775,12 @@ class Nginx extends HttpConfigBase
|
|||||||
return $logfiles_text;
|
return $logfiles_text;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getWebroot($domain, $ssl)
|
protected function getWebroot($domain)
|
||||||
{
|
{
|
||||||
$webroot_text = '';
|
$webroot_text = '';
|
||||||
|
|
||||||
if ($domain['deactivated'] == '1' && Settings::Get('system.deactivateddocroot') != '') {
|
if (($domain['deactivated'] == '1' || $domain['customer_deactivated'] == '1' ) && Settings::Get('system.deactivateddocroot') != '') {
|
||||||
$webroot_text .= "\t" . '# Using docroot for deactivated users...' . "\n";
|
$webroot_text .= "\t" . '# Using docroot for deactivated users/domains...' . "\n";
|
||||||
$webroot_text .= "\t" . 'root ' . FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')) . ';' . "\n";
|
$webroot_text .= "\t" . 'root ' . FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')) . ';' . "\n";
|
||||||
$this->deactivated = true;
|
$this->deactivated = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -878,13 +883,7 @@ class Nginx extends HttpConfigBase
|
|||||||
// remove comments
|
// remove comments
|
||||||
$vhost = implode("\n", preg_replace('/^(\s+)?#(.*)$/', '', explode("\n", $vhost)));
|
$vhost = implode("\n", preg_replace('/^(\s+)?#(.*)$/', '', explode("\n", $vhost)));
|
||||||
// Break blocks into lines
|
// Break blocks into lines
|
||||||
$vhost = str_replace([
|
$vhost = preg_replace("/^(\s+)?location(.+)\{(.+)\}$/misU", "location $2 {\n $3 \n}", $vhost);
|
||||||
"{",
|
|
||||||
"}"
|
|
||||||
], [
|
|
||||||
" {\n",
|
|
||||||
"\n}"
|
|
||||||
], $vhost);
|
|
||||||
// Break into array items
|
// Break into array items
|
||||||
$vhost = explode("\n", preg_replace('/[ \t]+/', ' ', trim(preg_replace('/\t+/', '', $vhost))));
|
$vhost = explode("\n", preg_replace('/[ \t]+/', ' ', trim(preg_replace('/\t+/', '', $vhost))));
|
||||||
// Remove empty lines
|
// Remove empty lines
|
||||||
@@ -1035,6 +1034,11 @@ class Nginx extends HttpConfigBase
|
|||||||
$path_options .= "\t\t" . 'auth_basic_user_file ' . FileDir::makeCorrectFile($single['usrf']) . ';' . "\n";
|
$path_options .= "\t\t" . 'auth_basic_user_file ' . FileDir::makeCorrectFile($single['usrf']) . ';' . "\n";
|
||||||
if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') {
|
if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') {
|
||||||
$path_options .= "\t\t" . 'index index.php index.html index.htm;' . "\n";
|
$path_options .= "\t\t" . 'index index.php index.html index.htm;' . "\n";
|
||||||
|
if ($domain['notryfiles'] != 1) {
|
||||||
|
$path_options .= "\t\t" . 'location ~ ^(.+?\.php)(/.*)?$ {' . "\n";
|
||||||
|
$path_options .= "\t\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n";
|
||||||
|
$path_options .= "\t\t" . '}' . "\n\n";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$path_options .= "\t\t" . 'index index.html index.htm;' . "\n";
|
$path_options .= "\t\t" . 'index index.html index.htm;' . "\n";
|
||||||
}
|
}
|
||||||
@@ -1120,6 +1124,10 @@ class Nginx extends HttpConfigBase
|
|||||||
|
|
||||||
$statTool = Settings::Get('system.traffictool');
|
$statTool = Settings::Get('system.traffictool');
|
||||||
$statDomain = "";
|
$statDomain = "";
|
||||||
|
if ($statTool == 'awstats') {
|
||||||
|
// awstats generates for each domain regardless of speciallogfile
|
||||||
|
$statDomain = "/" . $domain['domain'];
|
||||||
|
}
|
||||||
if ($domain['speciallogfile'] == '1') {
|
if ($domain['speciallogfile'] == '1') {
|
||||||
$statDomain = "/" . (($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']);
|
$statDomain = "/" . (($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']);
|
||||||
}
|
}
|
||||||
@@ -1157,7 +1165,6 @@ class Nginx extends HttpConfigBase
|
|||||||
$phpopts .= "\t\tinclude " . Settings::Get('nginx.fastcgiparams') . ";\n";
|
$phpopts .= "\t\tinclude " . Settings::Get('nginx.fastcgiparams') . ";\n";
|
||||||
$phpopts .= "\t\tfastcgi_param SCRIPT_FILENAME \$request_filename;\n";
|
$phpopts .= "\t\tfastcgi_param SCRIPT_FILENAME \$request_filename;\n";
|
||||||
$phpopts .= "\t\tfastcgi_param PATH_INFO \$fastcgi_path_info;\n";
|
$phpopts .= "\t\tfastcgi_param PATH_INFO \$fastcgi_path_info;\n";
|
||||||
$phpopts .= "\t\ttry_files \$fastcgi_script_name =404;\n";
|
|
||||||
$phpopts .= "\t\tfastcgi_pass " . Settings::Get('system.nginx_php_backend') . ";\n";
|
$phpopts .= "\t\tfastcgi_pass " . Settings::Get('system.nginx_php_backend') . ";\n";
|
||||||